comparison OrthancStone/Sources/Loaders/LoaderCache.cpp @ 1512:244ad1e4e76a

reorganization of folders
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 07 Jul 2020 16:21:02 +0200
parents Framework/Loaders/LoaderCache.cpp@30deba7bc8e2
children
comparison
equal deleted inserted replaced
1511:9dfeee74c1e6 1512:244ad1e4e76a
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 #if ORTHANC_ENABLE_WASM == 1
31 # include <unistd.h>
32 # include "../Oracle/WebAssemblyOracle.h"
33 #else
34 # include "../Oracle/ThreadedOracle.h"
35 #endif
36
37 #include "../Volumes/DicomVolumeImage.h"
38 #include "../Volumes/DicomVolumeImageMPRSlicer.h"
39
40 #include <OrthancException.h>
41 #include <Toolbox.h>
42
43 namespace OrthancStone
44 {
45 LoaderCache::LoaderCache(OrthancStone::ILoadersContext& loadersContext, bool useCtProgressiveQuality)
46 : loadersContext_(loadersContext)
47 , useCtProgressiveQuality_(useCtProgressiveQuality)
48
49 {
50
51 }
52
53 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader>
54 LoaderCache::GetSeriesVolumeProgressiveLoader(std::string seriesUuid)
55 {
56 try
57 {
58 // normalize keys a little
59 NormalizeUuid(seriesUuid);
60
61 // find in cache
62 if (seriesVolumeProgressiveLoaders_.find(seriesUuid) == seriesVolumeProgressiveLoaders_.end())
63 {
64 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock());
65
66 boost::shared_ptr<OrthancStone::DicomVolumeImage> volumeImage(new OrthancStone::DicomVolumeImage);
67 boost::shared_ptr<OrthancSeriesVolumeProgressiveLoader> loader;
68
69 // true means "use progressive quality"
70 // false means "load high quality slices only"
71 loader = OrthancSeriesVolumeProgressiveLoader::Create(loadersContext_, volumeImage, useCtProgressiveQuality_);
72 loader->LoadSeries(seriesUuid);
73 seriesVolumeProgressiveLoaders_[seriesUuid] = loader;
74 }
75 else
76 {
77 // LOG(TRACE) << "LoaderCache::GetSeriesVolumeProgressiveLoader : returning cached loader for seriesUUid = " << seriesUuid;
78 }
79 return seriesVolumeProgressiveLoaders_[seriesUuid];
80 }
81 catch (const Orthanc::OrthancException& e)
82 {
83 if (e.HasDetails())
84 {
85 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails();
86 }
87 else
88 {
89 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What();
90 }
91 throw;
92 }
93 catch (const std::exception& e)
94 {
95 LOG(ERROR) << "std::exception in LoaderCache: " << e.what();
96 throw;
97 }
98 catch (...)
99 {
100 LOG(ERROR) << "Unknown exception in LoaderCache";
101 throw;
102 }
103 }
104
105 boost::shared_ptr<OrthancMultiframeVolumeLoader> LoaderCache::GetMultiframeVolumeLoader(std::string instanceUuid)
106 {
107 // normalize keys a little
108 NormalizeUuid(instanceUuid);
109
110 // if the loader is not available, let's trigger its creation
111 if(multiframeVolumeLoaders_.find(instanceUuid) == multiframeVolumeLoaders_.end())
112 {
113 GetMultiframeDicomVolumeImageMPRSlicer(instanceUuid);
114 }
115 ORTHANC_ASSERT(multiframeVolumeLoaders_.find(instanceUuid) != multiframeVolumeLoaders_.end());
116
117 return multiframeVolumeLoaders_[instanceUuid];
118 }
119
120 boost::shared_ptr<OrthancStone::DicomVolumeImageMPRSlicer> LoaderCache::GetMultiframeDicomVolumeImageMPRSlicer(std::string instanceUuid)
121 {
122 try
123 {
124 // normalize keys a little
125 NormalizeUuid(instanceUuid);
126
127 // find in cache
128 if (dicomVolumeImageMPRSlicers_.find(instanceUuid) == dicomVolumeImageMPRSlicers_.end())
129 {
130 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock());
131 boost::shared_ptr<OrthancStone::DicomVolumeImage> volumeImage(new OrthancStone::DicomVolumeImage);
132 boost::shared_ptr<OrthancMultiframeVolumeLoader> loader;
133 {
134 loader = OrthancMultiframeVolumeLoader::Create(loadersContext_, volumeImage);
135 loader->LoadInstance(instanceUuid);
136 }
137 multiframeVolumeLoaders_[instanceUuid] = loader;
138 boost::shared_ptr<OrthancStone::DicomVolumeImageMPRSlicer> mprSlicer(new OrthancStone::DicomVolumeImageMPRSlicer(volumeImage));
139 dicomVolumeImageMPRSlicers_[instanceUuid] = mprSlicer;
140 }
141 return dicomVolumeImageMPRSlicers_[instanceUuid];
142 }
143 catch (const Orthanc::OrthancException& e)
144 {
145 if (e.HasDetails())
146 {
147 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails();
148 }
149 else
150 {
151 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What();
152 }
153 throw;
154 }
155 catch (const std::exception& e)
156 {
157 LOG(ERROR) << "std::exception in LoaderCache: " << e.what();
158 throw;
159 }
160 catch (...)
161 {
162 LOG(ERROR) << "Unknown exception in LoaderCache";
163 throw;
164 }
165 }
166
167 std::string LoaderCache::BuildDicomStructureSetLoaderKey(
168 const std::string& instanceUuid,
169 const std::string& uniqueKey)
170 {
171 return instanceUuid + "_" + uniqueKey;
172 }
173
174 boost::shared_ptr<DicomStructureSetLoader> LoaderCache::GetDicomStructureSetLoader(
175 std::string inInstanceUuid,
176 const std::vector<std::string>& initiallyVisibleStructures,
177 const std::string& uniqueKey)
178 {
179 try
180 {
181 // normalize keys a little
182 NormalizeUuid(inInstanceUuid);
183
184 std::string entryKey = BuildDicomStructureSetLoaderKey(inInstanceUuid, uniqueKey);
185
186 // find in cache
187 if (dicomStructureSetLoaders_.find(entryKey) == dicomStructureSetLoaders_.end())
188 {
189 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock());
190
191 boost::shared_ptr<DicomStructureSetLoader> loader;
192 {
193 loader = DicomStructureSetLoader::Create(loadersContext_);
194 loader->LoadInstance(inInstanceUuid, initiallyVisibleStructures);
195 }
196 dicomStructureSetLoaders_[entryKey] = loader;
197 }
198 return dicomStructureSetLoaders_[entryKey];
199 }
200 catch (const Orthanc::OrthancException& e)
201 {
202 if (e.HasDetails())
203 {
204 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails();
205 }
206 else
207 {
208 LOG(ERROR) << "OrthancException in LoaderCache: " << e.What();
209 }
210 throw;
211 }
212 catch (const std::exception& e)
213 {
214 LOG(ERROR) << "std::exception in LoaderCache: " << e.what();
215 throw;
216 }
217 catch (...)
218 {
219 LOG(ERROR) << "Unknown exception in LoaderCache";
220 throw;
221 }
222 }
223
224 void LoaderCache::ClearCache()
225 {
226 std::unique_ptr<OrthancStone::ILoadersContext::ILock> lock(loadersContext_.Lock());
227
228 #ifndef NDEBUG
229 // ISO way of checking for debug builds
230 DebugDisplayObjRefCounts();
231 #endif
232 seriesVolumeProgressiveLoaders_.clear();
233 multiframeVolumeLoaders_.clear();
234 dicomVolumeImageMPRSlicers_.clear();
235 dicomStructureSetLoaders_.clear();
236
237 }
238
239 template<typename T> void DebugDisplayObjRefCountsInMap(
240 const std::string& name, const std::map<std::string, boost::shared_ptr<T> >& myMap)
241 {
242 LOG(TRACE) << "Map \"" << name << "\" ref counts:";
243 size_t i = 0;
244 for (typename std::map<std::string, boost::shared_ptr<T> >::const_iterator
245 it = myMap.begin(); it != myMap.end(); ++it)
246 {
247 LOG(TRACE) << " element #" << i << ": ref count = " << it->second.use_count();
248 i++;
249 }
250 }
251
252 void LoaderCache::DebugDisplayObjRefCounts()
253 {
254 DebugDisplayObjRefCountsInMap("seriesVolumeProgressiveLoaders_", seriesVolumeProgressiveLoaders_);
255 DebugDisplayObjRefCountsInMap("multiframeVolumeLoaders_", multiframeVolumeLoaders_);
256 DebugDisplayObjRefCountsInMap("dicomVolumeImageMPRSlicers_", dicomVolumeImageMPRSlicers_);
257 DebugDisplayObjRefCountsInMap("dicomStructureSetLoaders_", dicomStructureSetLoaders_);
258 }
259
260 /**
261 This method could have been called StripSpacesAndChangeToLower but we might want to
262 add some UUID validation to the argument
263 */
264 void LoaderCache::NormalizeUuid(std::string& uuid)
265 {
266 std::string temp = Orthanc::Toolbox::StripSpaces(uuid);
267 Orthanc::Toolbox::ToLowerCase(temp);
268 uuid.swap(temp);
269 }
270 }