comparison Framework/Loaders/LoaderCache.cpp @ 1337:b1396be5aa27 broker

Moved the fixed loaders back from the dead
author Benjamin Golinvaux <bgo@osimis.io>
date Fri, 03 Apr 2020 16:13:06 +0200
parents Framework/Deprecated/Loaders/LoaderCache.cpp@4f8db2d202c8
children 556b4bc19118
comparison
equal deleted inserted replaced
1334:04055b6b9e2c 1337:b1396be5aa27
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-2020 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 #include "../../Loaders/ILoadersContext.h"
29
30
31 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
32 #include "DicomStructureSetLoader2.h"
33 #endif
34 //BGO_ENABLE_DICOMSTRUCTURESETLOADER2
35
36
37 #if ORTHANC_ENABLE_WASM == 1
38 # include <unistd.h>
39 # include "../../Oracle/WebAssemblyOracle.h"
40 #else
41 # include "../../Oracle/ThreadedOracle.h"
42 #endif
43
44 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
45 #include "../../Toolbox/DicomStructureSet2.h"
46 #endif
47 //BGO_ENABLE_DICOMSTRUCTURESETLOADER2
48
49 #include "../../Volumes/DicomVolumeImage.h"
50 #include "../../Volumes/DicomVolumeImageMPRSlicer.h"
51
52 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
53 #include "../../Volumes/DicomStructureSetSlicer2.h"
54 #endif
55 //BGO_ENABLE_DICOMSTRUCTURESETLOADER2
56
57 #include <Core/OrthancException.h>
58 #include <Core/Toolbox.h>
59
60 namespace OrthancStone
61 {
62 LoaderCache::LoaderCache(OrthancStone::ILoadersContext& loadersContext)
63 : loadersContext_(loadersContext)
64 {
65
66 }
67
68 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader>
69 LoaderCache::GetSeriesVolumeProgressiveLoader(std::string seriesUuid)
70 {
71 try
72 {
73
74 // normalize keys a little
75 seriesUuid = Orthanc::Toolbox::StripSpaces(seriesUuid);
76 Orthanc::Toolbox::ToLowerCase(seriesUuid);
77
78 // find in cache
79 if (seriesVolumeProgressiveLoaders_.find(seriesUuid) == seriesVolumeProgressiveLoaders_.end())
80 {
81 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock());
82
83 boost::shared_ptr<OrthancStone::DicomVolumeImage> volumeImage(new OrthancStone::DicomVolumeImage);
84 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> loader;
85
86 // true means "use progressive quality"
87 // false means "load high quality slices only"
88 loader = OrthancSeriesVolumeProgressiveLoader::Create(loadersContext_, volumeImage, false);
89 loader->LoadSeries(seriesUuid);
90 seriesVolumeProgressiveLoaders_[seriesUuid] = loader;
91 }
92 else
93 {
94 // LOG(TRACE) << "LoaderCache::GetSeriesVolumeProgressiveLoader : returning cached loader for seriesUUid = " << seriesUuid;
95 }
96 return seriesVolumeProgressiveLoaders_[seriesUuid];
97 }
98 catch (const Orthanc::OrthancException& e)
99 {
100 if (e.HasDetails())
101 {
102 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails();
103 }
104 else
105 {
106 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What();
107 }
108 throw;
109 }
110 catch (const std::exception& e)
111 {
112 LOG(ERROR) << "std::exception in LoaderCache: " << e.what();
113 throw;
114 }
115 catch (...)
116 {
117 LOG(ERROR) << "Unknown exception in LoaderCache";
118 throw;
119 }
120 }
121
122 boost::shared_ptr<OrthancMultiframeVolumeLoader> LoaderCache::GetMultiframeVolumeLoader(std::string instanceUuid)
123 {
124 // if the loader is not available, let's trigger its creation
125 if(multiframeVolumeLoaders_.find(instanceUuid) == multiframeVolumeLoaders_.end())
126 {
127 GetMultiframeDicomVolumeImageMPRSlicer(instanceUuid);
128 }
129 ORTHANC_ASSERT(multiframeVolumeLoaders_.find(instanceUuid) != multiframeVolumeLoaders_.end());
130
131 return multiframeVolumeLoaders_[instanceUuid];
132 }
133
134 boost::shared_ptr<OrthancStone::DicomVolumeImageMPRSlicer> LoaderCache::GetMultiframeDicomVolumeImageMPRSlicer(std::string instanceUuid)
135 {
136 try
137 {
138 // normalize keys a little
139 instanceUuid = Orthanc::Toolbox::StripSpaces(instanceUuid);
140 Orthanc::Toolbox::ToLowerCase(instanceUuid);
141
142 // find in cache
143 if (dicomVolumeImageMPRSlicers_.find(instanceUuid) == dicomVolumeImageMPRSlicers_.end())
144 {
145 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock());
146 boost::shared_ptr<OrthancStone::DicomVolumeImage> volumeImage(new OrthancStone::DicomVolumeImage);
147 boost::shared_ptr<OrthancMultiframeVolumeLoader> loader;
148 {
149 loader = OrthancMultiframeVolumeLoader::Create(loadersContext_, volumeImage);
150 loader->LoadInstance(instanceUuid);
151 }
152 multiframeVolumeLoaders_[instanceUuid] = loader;
153 boost::shared_ptr<OrthancStone::DicomVolumeImageMPRSlicer> mprSlicer(new OrthancStone::DicomVolumeImageMPRSlicer(volumeImage));
154 dicomVolumeImageMPRSlicers_[instanceUuid] = mprSlicer;
155 }
156 return dicomVolumeImageMPRSlicers_[instanceUuid];
157 }
158 catch (const Orthanc::OrthancException& e)
159 {
160 if (e.HasDetails())
161 {
162 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails();
163 }
164 else
165 {
166 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What();
167 }
168 throw;
169 }
170 catch (const std::exception& e)
171 {
172 LOG(ERROR) << "std::exception in LoaderCache: " << e.what();
173 throw;
174 }
175 catch (...)
176 {
177 LOG(ERROR) << "Unknown exception in LoaderCache";
178 throw;
179 }
180 }
181
182 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
183
184 boost::shared_ptr<DicomStructureSetSlicer2> LoaderCache::GetDicomStructureSetSlicer2(std::string instanceUuid)
185 {
186 // if the loader is not available, let's trigger its creation
187 if (dicomStructureSetSlicers2_.find(instanceUuid) == dicomStructureSetSlicers2_.end())
188 {
189 GetDicomStructureSetLoader2(instanceUuid);
190 }
191 ORTHANC_ASSERT(dicomStructureSetSlicers2_.find(instanceUuid) != dicomStructureSetSlicers2_.end());
192
193 return dicomStructureSetSlicers2_[instanceUuid];
194 }
195 #endif
196 //BGO_ENABLE_DICOMSTRUCTURESETLOADER2
197
198
199 /**
200 This method allows to convert a list of string into a string by
201 sorting the strings then joining them
202 */
203 static std::string SortAndJoin(const std::vector<std::string>& stringList)
204 {
205 if (stringList.size() == 0)
206 {
207 return "";
208 }
209 else
210 {
211 std::vector<std::string> sortedStringList = stringList;
212 std::sort(sortedStringList.begin(), sortedStringList.end());
213 std::stringstream s;
214 s << sortedStringList[0];
215 for (size_t i = 1; i < sortedStringList.size(); ++i)
216 {
217 s << "-" << sortedStringList[i];
218 }
219 return s.str();
220 }
221 }
222
223 boost::shared_ptr<DicomStructureSetLoader>
224 LoaderCache::GetDicomStructureSetLoader(
225 std::string inInstanceUuid,
226 const std::vector<std::string>& initiallyVisibleStructures)
227 {
228 try
229 {
230 // normalize keys a little
231 inInstanceUuid = Orthanc::Toolbox::StripSpaces(inInstanceUuid);
232 Orthanc::Toolbox::ToLowerCase(inInstanceUuid);
233
234 std::string initiallyVisibleStructuresKey =
235 SortAndJoin(initiallyVisibleStructures);
236
237 std::string entryKey = inInstanceUuid + "_" + initiallyVisibleStructuresKey;
238
239 // find in cache
240 if (dicomStructureSetLoaders_.find(entryKey) == dicomStructureSetLoaders_.end())
241 {
242 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock());
243
244 boost::shared_ptr<DicomStructureSetLoader> loader;
245 {
246 loader = DicomStructureSetLoader::Create(loadersContext_);
247 loader->LoadInstance(inInstanceUuid, initiallyVisibleStructures);
248 }
249 dicomStructureSetLoaders_[entryKey] = loader;
250 }
251 return dicomStructureSetLoaders_[entryKey];
252 }
253 catch (const Orthanc::OrthancException& e)
254 {
255 if (e.HasDetails())
256 {
257 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails();
258 }
259 else
260 {
261 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What();
262 }
263 throw;
264 }
265 catch (const std::exception& e)
266 {
267 LOG(ERROR) << "std::exception in LoaderCache: " << e.what();
268 throw;
269 }
270 catch (...)
271 {
272 LOG(ERROR) << "Unknown exception in LoaderCache";
273 throw;
274 }
275 }
276
277 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
278
279 boost::shared_ptr<DicomStructureSetLoader2> LoaderCache::GetDicomStructureSetLoader2(std::string instanceUuid)
280 {
281 try
282 {
283 // normalize keys a little
284 instanceUuid = Orthanc::Toolbox::StripSpaces(instanceUuid);
285 Orthanc::Toolbox::ToLowerCase(instanceUuid);
286
287 // find in cache
288 if (dicomStructureSetLoaders2_.find(instanceUuid) == dicomStructureSetLoaders2_.end())
289 {
290 boost::shared_ptr<DicomStructureSetLoader2> loader;
291 boost::shared_ptr<DicomStructureSet2> structureSet(new DicomStructureSet2());
292 boost::shared_ptr<DicomStructureSetSlicer2> rtSlicer(new DicomStructureSetSlicer2(structureSet));
293 dicomStructureSetSlicers2_[instanceUuid] = rtSlicer;
294 dicomStructureSets2_[instanceUuid] = structureSet; // to prevent it from being deleted
295 {
296 #if ORTHANC_ENABLE_WASM == 1
297 loader.reset(new DicomStructureSetLoader2(*(structureSet.get()), oracle_, oracle_));
298 #else
299 LockingEmitter::WriterLock lock(lockingEmitter_);
300 // TODO: clarify lifetimes... this is DANGEROUS!
301 loader.reset(new DicomStructureSetLoader2(*(structureSet.get()), oracle_, lock.GetOracleObservable()));
302 #endif
303 loader->LoadInstance(instanceUuid);
304 }
305 dicomStructureSetLoaders2_[instanceUuid] = loader;
306 }
307 return dicomStructureSetLoaders2_[instanceUuid];
308 }
309 catch (const Orthanc::OrthancException& e)
310 {
311 if (e.HasDetails())
312 {
313 LOG(ERROR) << "OrthancException in GetDicomStructureSetLoader2: " << e.What() << " Details: " << e.GetDetails();
314 }
315 else
316 {
317 LOG(ERROR) << "OrthancException in GetDicomStructureSetLoader2: " << e.What();
318 }
319 throw;
320 }
321 catch (const std::exception& e)
322 {
323 LOG(ERROR) << "std::exception in GetDicomStructureSetLoader2: " << e.what();
324 throw;
325 }
326 catch (...)
327 {
328 LOG(ERROR) << "Unknown exception in GetDicomStructureSetLoader2";
329 throw;
330 }
331 }
332
333 #endif
334 // BGO_ENABLE_DICOMSTRUCTURESETLOADER2
335
336
337 void LoaderCache::ClearCache()
338 {
339 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock());
340
341 #ifndef NDEBUG
342 // ISO way of checking for debug builds
343 DebugDisplayObjRefCounts();
344 #endif
345 seriesVolumeProgressiveLoaders_.clear();
346 multiframeVolumeLoaders_.clear();
347 dicomVolumeImageMPRSlicers_.clear();
348 dicomStructureSetLoaders_.clear();
349
350 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
351 // order is important!
352 dicomStructureSetLoaders2_.clear();
353 dicomStructureSetSlicers2_.clear();
354 dicomStructureSets2_.clear();
355 #endif
356 // BGO_ENABLE_DICOMSTRUCTURESETLOADER2
357 }
358
359 template<typename T> void DebugDisplayObjRefCountsInMap(
360 const std::string& name, const std::map<std::string, boost::shared_ptr<T> >& myMap)
361 {
362 LOG(TRACE) << "Map \"" << name << "\" ref counts:";
363 size_t i = 0;
364 for (typename std::map<std::string, boost::shared_ptr<T> >::const_iterator
365 it = myMap.begin(); it != myMap.end(); ++it)
366 {
367 LOG(TRACE) << " element #" << i << ": ref count = " << it->second.use_count();
368 i++;
369 }
370 }
371
372 void LoaderCache::DebugDisplayObjRefCounts()
373 {
374 DebugDisplayObjRefCountsInMap("seriesVolumeProgressiveLoaders_", seriesVolumeProgressiveLoaders_);
375 DebugDisplayObjRefCountsInMap("multiframeVolumeLoaders_", multiframeVolumeLoaders_);
376 DebugDisplayObjRefCountsInMap("dicomVolumeImageMPRSlicers_", dicomVolumeImageMPRSlicers_);
377 DebugDisplayObjRefCountsInMap("dicomStructureSetLoaders_", dicomStructureSetLoaders_);
378 #ifdef BGO_ENABLE_DICOMSTRUCTURESETLOADER2
379 DebugDisplayObjRefCountsInMap("dicomStructureSetLoaders2_", dicomStructureSetLoaders2_);
380 DebugDisplayObjRefCountsInMap("dicomStructureSetSlicers2_", dicomStructureSetSlicers2_);
381 #endif
382 //BGO_ENABLE_DICOMSTRUCTURESETLOADER2
383 }
384 }