comparison OrthancFramework/Sources/DicomParsing/ParsedDicomCache.cpp @ 4456:3e4f7b7840f0

new class: ParsedDicomCache()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 19 Jan 2021 16:11:23 +0100
parents
children 789676a8c96a
comparison
equal deleted inserted replaced
4455:a8f554ca5ac6 4456:3e4f7b7840f0
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2021 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program. If not, see
19 * <http://www.gnu.org/licenses/>.
20 **/
21
22
23 #include "../PrecompiledHeaders.h"
24 #include "ParsedDicomCache.h"
25
26 #include "../OrthancException.h"
27
28 namespace Orthanc
29 {
30 class ParsedDicomCache::Item : public ICacheable
31 {
32 private:
33 std::unique_ptr<ParsedDicomFile> dicom_;
34 size_t fileSize_;
35
36 public:
37 Item(ParsedDicomFile* dicom,
38 size_t fileSize) :
39 dicom_(dicom),
40 fileSize_(fileSize)
41 {
42 if (dicom == NULL)
43 {
44 throw OrthancException(ErrorCode_NullPointer);
45 }
46 }
47
48 virtual size_t GetMemoryUsage() const ORTHANC_OVERRIDE
49 {
50 return fileSize_;
51 }
52
53 ParsedDicomFile& GetDicom() const
54 {
55 assert(dicom_.get() != NULL);
56 return *dicom_;
57 }
58 };
59
60
61 ParsedDicomCache::ParsedDicomCache(size_t size) :
62 cacheSize_(size),
63 largeSize_(0)
64 {
65 if (size == 0)
66 {
67 throw OrthancException(ErrorCode_ParameterOutOfRange);
68 }
69 }
70
71
72 size_t ParsedDicomCache::GetCurrentSize() // For unit tests only
73 {
74 boost::mutex::scoped_lock lock(mutex_);
75
76 if (cache_.get() == NULL)
77 {
78 return largeSize_;
79 }
80 else
81 {
82 assert(largeSize_ == 0);
83 return cache_->GetCurrentSize();
84 }
85 }
86
87
88 void ParsedDicomCache::Invalidate(const std::string& id)
89 {
90 boost::mutex::scoped_lock lock(mutex_);
91
92 if (cache_.get() != NULL)
93 {
94 cache_->Invalidate(id);
95 }
96
97 if (largeId_ == id)
98 {
99 largeDicom_.reset(NULL);
100 largeSize_ = 0;
101 }
102 }
103
104
105 void ParsedDicomCache::Acquire(const std::string& id,
106 ParsedDicomFile* dicom, // Takes ownership
107 size_t fileSize)
108 {
109 boost::mutex::scoped_lock lock(mutex_);
110
111 if (fileSize >= cacheSize_)
112 {
113 cache_.reset(NULL);
114 largeDicom_.reset(dicom);
115 largeId_ = id;
116 largeSize_ = fileSize;
117 }
118 else
119 {
120 largeDicom_.reset(NULL);
121 largeSize_ = 0;
122
123 if (cache_.get() == NULL)
124 {
125 cache_.reset(new MemoryObjectCache);
126 cache_->SetMaximumSize(cacheSize_);
127 }
128
129 cache_->Acquire(id, new Item(dicom, fileSize));
130 }
131 }
132
133
134 ParsedDicomCache::Accessor::Accessor(ParsedDicomCache& that,
135 const std::string& id) :
136 lock_(that.mutex_),
137 id_(id),
138 file_(NULL),
139 fileSize_(0)
140 {
141 if (that.largeDicom_.get() != NULL &&
142 that.largeId_ == id)
143 {
144 file_ = that.largeDicom_.get();
145 fileSize_ = that.largeSize_;
146 }
147 else if (that.cache_.get() != NULL)
148 {
149 accessor_.reset(new MemoryObjectCache::Accessor(
150 *that.cache_, id, true /* unique */));
151 if (accessor_->IsValid())
152 {
153 const Item& item = dynamic_cast<const Item&>(accessor_->GetValue());
154 file_ = &item.GetDicom();
155 fileSize_ = item.GetMemoryUsage();
156 }
157 }
158 }
159
160
161 ParsedDicomFile& ParsedDicomCache::Accessor::GetDicom() const
162 {
163 if (IsValid())
164 {
165 assert(file_ != NULL);
166 return *file_;
167 }
168 else
169 {
170 throw OrthancException(ErrorCode_BadSequenceOfCalls);
171 }
172 }
173
174
175 size_t ParsedDicomCache::Accessor::GetFileSize() const
176 {
177 if (IsValid())
178 {
179 return fileSize_;
180 }
181 else
182 {
183 throw OrthancException(ErrorCode_BadSequenceOfCalls);
184 }
185 }
186 }