Mercurial > hg > orthanc-stone
comparison Framework/Deprecated/Loaders/LoaderCache.cpp @ 1225:16738485e457 broker
deprecating DicomStructureSetLoader, OrthancMultiframeVolumeLoader and OrthancSeriesVolumeProgressiveLoader
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Sun, 08 Dec 2019 11:45:09 +0100 |
parents | Framework/Loaders/LoaderCache.cpp@477203923f26 |
children | 05d05cba0f4f |
comparison
equal
deleted
inserted
replaced
1224:37bc7f115f81 | 1225:16738485e457 |
---|---|
1 /** | |
2 * Stone of Orthanc | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * Copyright (C) 2017-2019 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 Affero 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 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 #include "LoaderCache.h" | |
22 | |
23 #include "../../StoneException.h" | |
24 #include "OrthancSeriesVolumeProgressiveLoader.h" | |
25 #include "OrthancMultiframeVolumeLoader.h" | |
26 #include "DicomStructureSetLoader.h" | |
27 | |
28 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
29 #include "DicomStructureSetLoader2.h" | |
30 #endif | |
31 //BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
32 | |
33 | |
34 #if ORTHANC_ENABLE_WASM == 1 | |
35 # include <unistd.h> | |
36 # include "../../Oracle/WebAssemblyOracle.h" | |
37 #else | |
38 # include "../../Oracle/ThreadedOracle.h" | |
39 #endif | |
40 | |
41 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
42 #include "../../Toolbox/DicomStructureSet2.h" | |
43 #endif | |
44 //BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
45 | |
46 #include "../../Volumes/DicomVolumeImage.h" | |
47 #include "../../Volumes/DicomVolumeImageMPRSlicer.h" | |
48 | |
49 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
50 #include "../../Volumes/DicomStructureSetSlicer2.h" | |
51 #endif | |
52 //BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
53 | |
54 #include <Core/OrthancException.h> | |
55 #include <Core/Toolbox.h> | |
56 | |
57 namespace Deprecated | |
58 { | |
59 #if ORTHANC_ENABLE_WASM == 1 | |
60 LoaderCache::LoaderCache(OrthancStone::WebAssemblyOracle& oracle) | |
61 : oracle_(oracle) | |
62 { | |
63 | |
64 } | |
65 #else | |
66 LoaderCache::LoaderCache(OrthancStone::ThreadedOracle& oracle, | |
67 OrthancStone::Deprecated::LockingEmitter& lockingEmitter) | |
68 : oracle_(oracle) | |
69 , lockingEmitter_(lockingEmitter) | |
70 { | |
71 } | |
72 #endif | |
73 | |
74 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> | |
75 LoaderCache::GetSeriesVolumeProgressiveLoader(std::string seriesUuid) | |
76 { | |
77 try | |
78 { | |
79 | |
80 // normalize keys a little | |
81 seriesUuid = Orthanc::Toolbox::StripSpaces(seriesUuid); | |
82 Orthanc::Toolbox::ToLowerCase(seriesUuid); | |
83 | |
84 // find in cache | |
85 if (seriesVolumeProgressiveLoaders_.find(seriesUuid) == seriesVolumeProgressiveLoaders_.end()) | |
86 { | |
87 // LOG(TRACE) << "LoaderCache::GetSeriesVolumeProgressiveLoader : CACHEMISS --> need to load seriesUUid = " << seriesUuid; | |
88 #if ORTHANC_ENABLE_WASM == 1 | |
89 // LOG(TRACE) << "Performing request for series " << seriesUuid << " sbrk(0) = " << sbrk(0); | |
90 #else | |
91 // LOG(TRACE) << "Performing request for series " << seriesUuid; | |
92 #endif | |
93 boost::shared_ptr<OrthancStone::DicomVolumeImage> volumeImage(new OrthancStone::DicomVolumeImage); | |
94 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> loader; | |
95 // LOG(TRACE) << "volumeImage = " << volumeImage.get(); | |
96 { | |
97 #if ORTHANC_ENABLE_WASM == 1 | |
98 loader.reset(new OrthancSeriesVolumeProgressiveLoader(volumeImage, oracle_, oracle_)); | |
99 #else | |
100 OrthancStone::Deprecated::LockingEmitter::WriterLock lock(lockingEmitter_); | |
101 loader.reset(new OrthancSeriesVolumeProgressiveLoader(volumeImage, oracle_, lock.GetOracleObservable())); | |
102 #endif | |
103 // LOG(TRACE) << "LoaderCache::GetSeriesVolumeProgressiveLoader : loader = " << loader.get(); | |
104 loader->LoadSeries(seriesUuid); | |
105 // LOG(TRACE) << "LoaderCache::GetSeriesVolumeProgressiveLoader : loader->LoadSeries successful"; | |
106 } | |
107 seriesVolumeProgressiveLoaders_[seriesUuid] = loader; | |
108 } | |
109 else | |
110 { | |
111 // LOG(TRACE) << "LoaderCache::GetSeriesVolumeProgressiveLoader : returning cached loader for seriesUUid = " << seriesUuid; | |
112 } | |
113 return seriesVolumeProgressiveLoaders_[seriesUuid]; | |
114 } | |
115 catch (const Orthanc::OrthancException& e) | |
116 { | |
117 if (e.HasDetails()) | |
118 { | |
119 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails(); | |
120 } | |
121 else | |
122 { | |
123 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What(); | |
124 } | |
125 throw; | |
126 } | |
127 catch (const std::exception& e) | |
128 { | |
129 LOG(ERROR) << "std::exception in LoaderCache: " << e.what(); | |
130 throw; | |
131 } | |
132 catch (...) | |
133 { | |
134 LOG(ERROR) << "Unknown exception in LoaderCache"; | |
135 throw; | |
136 } | |
137 } | |
138 | |
139 boost::shared_ptr<OrthancMultiframeVolumeLoader> LoaderCache::GetMultiframeVolumeLoader(std::string instanceUuid) | |
140 { | |
141 // if the loader is not available, let's trigger its creation | |
142 if(multiframeVolumeLoaders_.find(instanceUuid) == multiframeVolumeLoaders_.end()) | |
143 { | |
144 GetMultiframeDicomVolumeImageMPRSlicer(instanceUuid); | |
145 } | |
146 ORTHANC_ASSERT(multiframeVolumeLoaders_.find(instanceUuid) != multiframeVolumeLoaders_.end()); | |
147 | |
148 return multiframeVolumeLoaders_[instanceUuid]; | |
149 } | |
150 | |
151 boost::shared_ptr<OrthancStone::DicomVolumeImageMPRSlicer> LoaderCache::GetMultiframeDicomVolumeImageMPRSlicer(std::string instanceUuid) | |
152 { | |
153 try | |
154 { | |
155 // normalize keys a little | |
156 instanceUuid = Orthanc::Toolbox::StripSpaces(instanceUuid); | |
157 Orthanc::Toolbox::ToLowerCase(instanceUuid); | |
158 | |
159 // find in cache | |
160 if (dicomVolumeImageMPRSlicers_.find(instanceUuid) == dicomVolumeImageMPRSlicers_.end()) | |
161 { | |
162 boost::shared_ptr<OrthancStone::DicomVolumeImage> volumeImage(new OrthancStone::DicomVolumeImage); | |
163 boost::shared_ptr<OrthancMultiframeVolumeLoader> loader; | |
164 | |
165 { | |
166 #if ORTHANC_ENABLE_WASM == 1 | |
167 loader.reset(new OrthancMultiframeVolumeLoader(volumeImage, oracle_, oracle_)); | |
168 #else | |
169 OrthancStone::Deprecated::LockingEmitter::WriterLock lock(lockingEmitter_); | |
170 loader.reset(new OrthancMultiframeVolumeLoader(volumeImage, oracle_, lock.GetOracleObservable())); | |
171 #endif | |
172 loader->LoadInstance(instanceUuid); | |
173 } | |
174 multiframeVolumeLoaders_[instanceUuid] = loader; | |
175 boost::shared_ptr<OrthancStone::DicomVolumeImageMPRSlicer> mprSlicer(new OrthancStone::DicomVolumeImageMPRSlicer(volumeImage)); | |
176 dicomVolumeImageMPRSlicers_[instanceUuid] = mprSlicer; | |
177 } | |
178 return dicomVolumeImageMPRSlicers_[instanceUuid]; | |
179 } | |
180 catch (const Orthanc::OrthancException& e) | |
181 { | |
182 if (e.HasDetails()) | |
183 { | |
184 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails(); | |
185 } | |
186 else | |
187 { | |
188 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What(); | |
189 } | |
190 throw; | |
191 } | |
192 catch (const std::exception& e) | |
193 { | |
194 LOG(ERROR) << "std::exception in LoaderCache: " << e.what(); | |
195 throw; | |
196 } | |
197 catch (...) | |
198 { | |
199 LOG(ERROR) << "Unknown exception in LoaderCache"; | |
200 throw; | |
201 } | |
202 } | |
203 | |
204 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
205 | |
206 boost::shared_ptr<DicomStructureSetSlicer2> LoaderCache::GetDicomStructureSetSlicer2(std::string instanceUuid) | |
207 { | |
208 // if the loader is not available, let's trigger its creation | |
209 if (dicomStructureSetSlicers2_.find(instanceUuid) == dicomStructureSetSlicers2_.end()) | |
210 { | |
211 GetDicomStructureSetLoader2(instanceUuid); | |
212 } | |
213 ORTHANC_ASSERT(dicomStructureSetSlicers2_.find(instanceUuid) != dicomStructureSetSlicers2_.end()); | |
214 | |
215 return dicomStructureSetSlicers2_[instanceUuid]; | |
216 } | |
217 #endif | |
218 //BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
219 | |
220 | |
221 /** | |
222 This method allows to convert a list of string into a string by | |
223 sorting the strings then joining them | |
224 */ | |
225 static std::string SortAndJoin(const std::vector<std::string>& stringList) | |
226 { | |
227 if (stringList.size() == 0) | |
228 { | |
229 return ""; | |
230 } | |
231 else | |
232 { | |
233 std::vector<std::string> sortedStringList = stringList; | |
234 std::sort(sortedStringList.begin(), sortedStringList.end()); | |
235 std::stringstream s; | |
236 s << sortedStringList[0]; | |
237 for (size_t i = 1; i < sortedStringList.size(); ++i) | |
238 { | |
239 s << "-" << sortedStringList[i]; | |
240 } | |
241 return s.str(); | |
242 } | |
243 } | |
244 | |
245 boost::shared_ptr<DicomStructureSetLoader> | |
246 LoaderCache::GetDicomStructureSetLoader( | |
247 std::string inInstanceUuid, | |
248 const std::vector<std::string>& initiallyVisibleStructures) | |
249 { | |
250 try | |
251 { | |
252 // normalize keys a little | |
253 inInstanceUuid = Orthanc::Toolbox::StripSpaces(inInstanceUuid); | |
254 Orthanc::Toolbox::ToLowerCase(inInstanceUuid); | |
255 | |
256 std::string initiallyVisibleStructuresKey = | |
257 SortAndJoin(initiallyVisibleStructures); | |
258 | |
259 std::string entryKey = inInstanceUuid + "_" + initiallyVisibleStructuresKey; | |
260 | |
261 // find in cache | |
262 if (dicomStructureSetLoaders_.find(entryKey) == dicomStructureSetLoaders_.end()) | |
263 { | |
264 boost::shared_ptr<DicomStructureSetLoader> loader; | |
265 | |
266 { | |
267 #if ORTHANC_ENABLE_WASM == 1 | |
268 loader.reset(new DicomStructureSetLoader(oracle_, oracle_)); | |
269 #else | |
270 OrthancStone::Deprecated::LockingEmitter::WriterLock lock(lockingEmitter_); | |
271 loader.reset(new DicomStructureSetLoader(oracle_, lock.GetOracleObservable())); | |
272 #endif | |
273 loader->LoadInstance(inInstanceUuid, initiallyVisibleStructures); | |
274 } | |
275 dicomStructureSetLoaders_[entryKey] = loader; | |
276 } | |
277 return dicomStructureSetLoaders_[entryKey]; | |
278 } | |
279 catch (const Orthanc::OrthancException& e) | |
280 { | |
281 if (e.HasDetails()) | |
282 { | |
283 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails(); | |
284 } | |
285 else | |
286 { | |
287 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What(); | |
288 } | |
289 throw; | |
290 } | |
291 catch (const std::exception& e) | |
292 { | |
293 LOG(ERROR) << "std::exception in LoaderCache: " << e.what(); | |
294 throw; | |
295 } | |
296 catch (...) | |
297 { | |
298 LOG(ERROR) << "Unknown exception in LoaderCache"; | |
299 throw; | |
300 } | |
301 } | |
302 | |
303 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
304 | |
305 boost::shared_ptr<DicomStructureSetLoader2> LoaderCache::GetDicomStructureSetLoader2(std::string instanceUuid) | |
306 { | |
307 try | |
308 { | |
309 // normalize keys a little | |
310 instanceUuid = Orthanc::Toolbox::StripSpaces(instanceUuid); | |
311 Orthanc::Toolbox::ToLowerCase(instanceUuid); | |
312 | |
313 // find in cache | |
314 if (dicomStructureSetLoaders2_.find(instanceUuid) == dicomStructureSetLoaders2_.end()) | |
315 { | |
316 boost::shared_ptr<DicomStructureSetLoader2> loader; | |
317 boost::shared_ptr<DicomStructureSet2> structureSet(new DicomStructureSet2()); | |
318 boost::shared_ptr<DicomStructureSetSlicer2> rtSlicer(new DicomStructureSetSlicer2(structureSet)); | |
319 dicomStructureSetSlicers2_[instanceUuid] = rtSlicer; | |
320 dicomStructureSets2_[instanceUuid] = structureSet; // to prevent it from being deleted | |
321 { | |
322 #if ORTHANC_ENABLE_WASM == 1 | |
323 loader.reset(new DicomStructureSetLoader2(*(structureSet.get()), oracle_, oracle_)); | |
324 #else | |
325 LockingEmitter::WriterLock lock(lockingEmitter_); | |
326 // TODO: clarify lifetimes... this is DANGEROUS! | |
327 loader.reset(new DicomStructureSetLoader2(*(structureSet.get()), oracle_, lock.GetOracleObservable())); | |
328 #endif | |
329 loader->LoadInstance(instanceUuid); | |
330 } | |
331 dicomStructureSetLoaders2_[instanceUuid] = loader; | |
332 } | |
333 return dicomStructureSetLoaders2_[instanceUuid]; | |
334 } | |
335 catch (const Orthanc::OrthancException& e) | |
336 { | |
337 if (e.HasDetails()) | |
338 { | |
339 LOG(ERROR) << "OrthancException in GetDicomStructureSetLoader2: " << e.What() << " Details: " << e.GetDetails(); | |
340 } | |
341 else | |
342 { | |
343 LOG(ERROR) << "OrthancException in GetDicomStructureSetLoader2: " << e.What(); | |
344 } | |
345 throw; | |
346 } | |
347 catch (const std::exception& e) | |
348 { | |
349 LOG(ERROR) << "std::exception in GetDicomStructureSetLoader2: " << e.what(); | |
350 throw; | |
351 } | |
352 catch (...) | |
353 { | |
354 LOG(ERROR) << "Unknown exception in GetDicomStructureSetLoader2"; | |
355 throw; | |
356 } | |
357 } | |
358 | |
359 #endif | |
360 // BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
361 | |
362 | |
363 void LoaderCache::ClearCache() | |
364 { | |
365 #if ORTHANC_ENABLE_WASM != 1 | |
366 OrthancStone::Deprecated::LockingEmitter::WriterLock lock(lockingEmitter_); | |
367 #endif | |
368 | |
369 //#ifndef NDEBUG | |
370 // ISO way of checking for debug builds | |
371 DebugDisplayObjRefCounts(); | |
372 //#endif | |
373 seriesVolumeProgressiveLoaders_.clear(); | |
374 multiframeVolumeLoaders_.clear(); | |
375 dicomVolumeImageMPRSlicers_.clear(); | |
376 dicomStructureSetLoaders_.clear(); | |
377 | |
378 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
379 // order is important! | |
380 dicomStructureSetLoaders2_.clear(); | |
381 dicomStructureSetSlicers2_.clear(); | |
382 dicomStructureSets2_.clear(); | |
383 #endif | |
384 // BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
385 } | |
386 | |
387 template<typename T> void DebugDisplayObjRefCountsInMap( | |
388 const std::string& name, const std::map<std::string, boost::shared_ptr<T> >& myMap) | |
389 { | |
390 LOG(TRACE) << "Map \"" << name << "\" ref counts:"; | |
391 size_t i = 0; | |
392 for (typename std::map<std::string, boost::shared_ptr<T> >::const_iterator | |
393 it = myMap.begin(); it != myMap.end(); ++it) | |
394 { | |
395 LOG(TRACE) << " element #" << i << ": ref count = " << it->second.use_count(); | |
396 i++; | |
397 } | |
398 } | |
399 | |
400 void LoaderCache::DebugDisplayObjRefCounts() | |
401 { | |
402 DebugDisplayObjRefCountsInMap("seriesVolumeProgressiveLoaders_", seriesVolumeProgressiveLoaders_); | |
403 DebugDisplayObjRefCountsInMap("multiframeVolumeLoaders_", multiframeVolumeLoaders_); | |
404 DebugDisplayObjRefCountsInMap("dicomVolumeImageMPRSlicers_", dicomVolumeImageMPRSlicers_); | |
405 DebugDisplayObjRefCountsInMap("dicomStructureSetLoaders_", dicomStructureSetLoaders_); | |
406 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
407 DebugDisplayObjRefCountsInMap("dicomStructureSetLoaders2_", dicomStructureSetLoaders2_); | |
408 DebugDisplayObjRefCountsInMap("dicomStructureSetSlicers2_", dicomStructureSetSlicers2_); | |
409 #endif | |
410 //BGO_ENABLE_DICOMSTRUCTURESETLOADER2 | |
411 } | |
412 } |