Mercurial > hg > orthanc
annotate OrthancServer/ServerJobs/ArchiveJob.cpp @ 3913:6ddad3e0b569 transcoding
transcoding ZIP archive and media
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 08 May 2020 19:15:28 +0200 |
parents | 56f2397f027a |
children | b99acc213937 |
rev | line source |
---|---|
2632 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
3640
94f4a18a79cc
upgrade to year 2020
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3240
diff
changeset
|
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium |
2632 | 6 * |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU General Public License as | |
9 * published by the Free Software Foundation, either version 3 of the | |
10 * License, or (at your option) any later version. | |
11 * | |
12 * In addition, as a special exception, the copyright holders of this | |
13 * program give permission to link the code of its release with the | |
14 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
15 * that use the same license as the "OpenSSL" library), and distribute | |
16 * the linked executables. You must obey the GNU General Public License | |
17 * in all respects for all of the code used other than "OpenSSL". If you | |
18 * modify file(s) with this exception, you may extend this exception to | |
19 * your version of the file(s), but you are not obligated to do so. If | |
20 * you do not wish to do so, delete this exception statement from your | |
21 * version. If you delete this exception statement from all source files | |
22 * in the program, then also delete it here. | |
23 * | |
24 * This program is distributed in the hope that it will be useful, but | |
25 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
27 * General Public License for more details. | |
28 * | |
29 * You should have received a copy of the GNU General Public License | |
30 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
31 **/ | |
32 | |
33 | |
34 #include "../PrecompiledHeadersServer.h" | |
35 #include "ArchiveJob.h" | |
36 | |
3095
beeeb6096f27
removing dependencies upon ServerContext
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
37 #include "../../Core/Cache/SharedArchive.h" |
2632 | 38 #include "../../Core/Compression/HierarchicalZipWriter.h" |
39 #include "../../Core/DicomParsing/DicomDirWriter.h" | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
40 #include "../../Core/DicomParsing/FromDcmtkBridge.h" |
2632 | 41 #include "../../Core/Logging.h" |
42 #include "../../Core/OrthancException.h" | |
3181
6fd38327e777
Fix issue #130 (Orthanc failed to start when /tmp partition was full)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3095
diff
changeset
|
43 #include "../OrthancConfiguration.h" |
3095
beeeb6096f27
removing dependencies upon ServerContext
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3060
diff
changeset
|
44 #include "../ServerContext.h" |
2632 | 45 |
46 #include <stdio.h> | |
47 | |
48 #if defined(_MSC_VER) | |
49 #define snprintf _snprintf | |
50 #endif | |
51 | |
52 static const uint64_t MEGA_BYTES = 1024 * 1024; | |
53 static const uint64_t GIGA_BYTES = 1024 * 1024 * 1024; | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
54 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
55 static const char* const MEDIA_IMAGES_FOLDER = "IMAGES"; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
56 static const char* const KEY_DESCRIPTION = "Description"; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
57 static const char* const KEY_INSTANCES_COUNT = "InstancesCount"; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
58 static const char* const KEY_UNCOMPRESSED_SIZE_MB = "UncompressedSizeMB"; |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
59 static const char* const KEY_TRANSCODE = "Transcode"; |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
60 |
2632 | 61 |
62 namespace Orthanc | |
63 { | |
64 static bool IsZip64Required(uint64_t uncompressedSize, | |
65 unsigned int countInstances) | |
66 { | |
67 static const uint64_t SAFETY_MARGIN = 64 * MEGA_BYTES; // Should be large enough to hold DICOMDIR | |
68 static const unsigned int FILES_MARGIN = 10; | |
69 | |
70 /** | |
71 * Determine whether ZIP64 is required. Original ZIP format can | |
72 * store up to 2GB of data (some implementation supporting up to | |
73 * 4GB of data), and up to 65535 files. | |
74 * https://en.wikipedia.org/wiki/Zip_(file_format)#ZIP64 | |
75 **/ | |
76 | |
77 const bool isZip64 = (uncompressedSize >= 2 * GIGA_BYTES - SAFETY_MARGIN || | |
78 countInstances >= 65535 - FILES_MARGIN); | |
79 | |
80 LOG(INFO) << "Creating a ZIP file with " << countInstances << " files of size " | |
81 << (uncompressedSize / MEGA_BYTES) << "MB using the " | |
82 << (isZip64 ? "ZIP64" : "ZIP32") << " file format"; | |
83 | |
84 return isZip64; | |
85 } | |
86 | |
87 | |
88 class ArchiveJob::ResourceIdentifiers : public boost::noncopyable | |
89 { | |
90 private: | |
91 ResourceType level_; | |
92 std::string patient_; | |
93 std::string study_; | |
94 std::string series_; | |
95 std::string instance_; | |
96 | |
97 static void GoToParent(ServerIndex& index, | |
98 std::string& current) | |
99 { | |
100 std::string tmp; | |
101 | |
102 if (index.LookupParent(tmp, current)) | |
103 { | |
104 current = tmp; | |
105 } | |
106 else | |
107 { | |
108 throw OrthancException(ErrorCode_UnknownResource); | |
109 } | |
110 } | |
111 | |
112 | |
113 public: | |
114 ResourceIdentifiers(ServerIndex& index, | |
115 const std::string& publicId) | |
116 { | |
117 if (!index.LookupResourceType(level_, publicId)) | |
118 { | |
119 throw OrthancException(ErrorCode_UnknownResource); | |
120 } | |
121 | |
122 std::string current = publicId;; | |
123 switch (level_) // Do not add "break" below! | |
124 { | |
125 case ResourceType_Instance: | |
126 instance_ = current; | |
127 GoToParent(index, current); | |
128 | |
129 case ResourceType_Series: | |
130 series_ = current; | |
131 GoToParent(index, current); | |
132 | |
133 case ResourceType_Study: | |
134 study_ = current; | |
135 GoToParent(index, current); | |
136 | |
137 case ResourceType_Patient: | |
138 patient_ = current; | |
139 break; | |
140 | |
141 default: | |
142 throw OrthancException(ErrorCode_InternalError); | |
143 } | |
144 } | |
145 | |
146 ResourceType GetLevel() const | |
147 { | |
148 return level_; | |
149 } | |
150 | |
151 const std::string& GetIdentifier(ResourceType level) const | |
152 { | |
153 // Some sanity check to ensure enumerations are not altered | |
154 assert(ResourceType_Patient < ResourceType_Study); | |
155 assert(ResourceType_Study < ResourceType_Series); | |
156 assert(ResourceType_Series < ResourceType_Instance); | |
157 | |
158 if (level > level_) | |
159 { | |
160 throw OrthancException(ErrorCode_InternalError); | |
161 } | |
162 | |
163 switch (level) | |
164 { | |
165 case ResourceType_Patient: | |
166 return patient_; | |
167 | |
168 case ResourceType_Study: | |
169 return study_; | |
170 | |
171 case ResourceType_Series: | |
172 return series_; | |
173 | |
174 case ResourceType_Instance: | |
175 return instance_; | |
176 | |
177 default: | |
178 throw OrthancException(ErrorCode_InternalError); | |
179 } | |
180 } | |
181 }; | |
182 | |
183 | |
184 class ArchiveJob::IArchiveVisitor : public boost::noncopyable | |
185 { | |
186 public: | |
187 virtual ~IArchiveVisitor() | |
188 { | |
189 } | |
190 | |
191 virtual void Open(ResourceType level, | |
192 const std::string& publicId) = 0; | |
193 | |
194 virtual void Close() = 0; | |
195 | |
196 virtual void AddInstance(const std::string& instanceId, | |
197 const FileInfo& dicom) = 0; | |
198 }; | |
199 | |
200 | |
201 class ArchiveJob::ArchiveIndex : public boost::noncopyable | |
202 { | |
203 private: | |
204 struct Instance | |
205 { | |
206 std::string id_; | |
207 FileInfo dicom_; | |
208 | |
209 Instance(const std::string& id, | |
210 const FileInfo& dicom) : | |
211 id_(id), dicom_(dicom) | |
212 { | |
213 } | |
214 }; | |
215 | |
216 // A "NULL" value for ArchiveIndex indicates a non-expanded node | |
217 typedef std::map<std::string, ArchiveIndex*> Resources; | |
218 | |
219 ResourceType level_; | |
220 Resources resources_; // Only at patient/study/series level | |
221 std::list<Instance> instances_; // Only at instance level | |
222 | |
223 | |
224 void AddResourceToExpand(ServerIndex& index, | |
225 const std::string& id) | |
226 { | |
227 if (level_ == ResourceType_Instance) | |
228 { | |
229 FileInfo tmp; | |
230 if (index.LookupAttachment(tmp, id, FileContentType_Dicom)) | |
231 { | |
232 instances_.push_back(Instance(id, tmp)); | |
233 } | |
234 } | |
235 else | |
236 { | |
237 resources_[id] = NULL; | |
238 } | |
239 } | |
240 | |
241 | |
242 public: | |
243 ArchiveIndex(ResourceType level) : | |
244 level_(level) | |
245 { | |
246 } | |
247 | |
248 ~ArchiveIndex() | |
249 { | |
250 for (Resources::iterator it = resources_.begin(); | |
251 it != resources_.end(); ++it) | |
252 { | |
253 delete it->second; | |
254 } | |
255 } | |
256 | |
257 | |
258 void Add(ServerIndex& index, | |
259 const ResourceIdentifiers& resource) | |
260 { | |
261 const std::string& id = resource.GetIdentifier(level_); | |
262 Resources::iterator previous = resources_.find(id); | |
263 | |
264 if (level_ == ResourceType_Instance) | |
265 { | |
266 AddResourceToExpand(index, id); | |
267 } | |
268 else if (resource.GetLevel() == level_) | |
269 { | |
270 // Mark this resource for further expansion | |
271 if (previous != resources_.end()) | |
272 { | |
273 delete previous->second; | |
274 } | |
275 | |
276 resources_[id] = NULL; | |
277 } | |
278 else if (previous == resources_.end()) | |
279 { | |
280 // This is the first time we meet this resource | |
3712
2a170a8f1faf
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3640
diff
changeset
|
281 std::unique_ptr<ArchiveIndex> child(new ArchiveIndex(GetChildResourceType(level_))); |
2632 | 282 child->Add(index, resource); |
283 resources_[id] = child.release(); | |
284 } | |
285 else if (previous->second != NULL) | |
286 { | |
287 previous->second->Add(index, resource); | |
288 } | |
289 else | |
290 { | |
291 // Nothing to do: This item is marked for further expansion | |
292 } | |
293 } | |
294 | |
295 | |
296 void Expand(ServerIndex& index) | |
297 { | |
298 if (level_ == ResourceType_Instance) | |
299 { | |
300 // Expanding an instance node makes no sense | |
301 return; | |
302 } | |
303 | |
304 for (Resources::iterator it = resources_.begin(); | |
305 it != resources_.end(); ++it) | |
306 { | |
307 if (it->second == NULL) | |
308 { | |
309 // This is resource is marked for expansion | |
310 std::list<std::string> children; | |
311 index.GetChildren(children, it->first); | |
312 | |
3712
2a170a8f1faf
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3640
diff
changeset
|
313 std::unique_ptr<ArchiveIndex> child(new ArchiveIndex(GetChildResourceType(level_))); |
2632 | 314 |
315 for (std::list<std::string>::const_iterator | |
316 it2 = children.begin(); it2 != children.end(); ++it2) | |
317 { | |
318 child->AddResourceToExpand(index, *it2); | |
319 } | |
320 | |
321 it->second = child.release(); | |
322 } | |
323 | |
324 assert(it->second != NULL); | |
325 it->second->Expand(index); | |
326 } | |
327 } | |
328 | |
329 | |
330 void Apply(IArchiveVisitor& visitor) const | |
331 { | |
332 if (level_ == ResourceType_Instance) | |
333 { | |
334 for (std::list<Instance>::const_iterator | |
335 it = instances_.begin(); it != instances_.end(); ++it) | |
336 { | |
337 visitor.AddInstance(it->id_, it->dicom_); | |
338 } | |
339 } | |
340 else | |
341 { | |
342 for (Resources::const_iterator it = resources_.begin(); | |
343 it != resources_.end(); ++it) | |
344 { | |
345 assert(it->second != NULL); // There must have been a call to "Expand()" | |
346 visitor.Open(level_, it->first); | |
347 it->second->Apply(visitor); | |
348 visitor.Close(); | |
349 } | |
350 } | |
351 } | |
352 }; | |
353 | |
354 | |
355 | |
356 class ArchiveJob::ZipCommands : public boost::noncopyable | |
357 { | |
358 private: | |
359 enum Type | |
360 { | |
361 Type_OpenDirectory, | |
362 Type_CloseDirectory, | |
363 Type_WriteInstance | |
364 }; | |
365 | |
366 class Command : public boost::noncopyable | |
367 { | |
368 private: | |
369 Type type_; | |
370 std::string filename_; | |
371 std::string instanceId_; | |
372 FileInfo info_; | |
373 | |
374 public: | |
375 explicit Command(Type type) : | |
376 type_(type) | |
377 { | |
378 assert(type_ == Type_CloseDirectory); | |
379 } | |
380 | |
381 Command(Type type, | |
382 const std::string& filename) : | |
383 type_(type), | |
384 filename_(filename) | |
385 { | |
386 assert(type_ == Type_OpenDirectory); | |
387 } | |
388 | |
389 Command(Type type, | |
390 const std::string& filename, | |
391 const std::string& instanceId, | |
392 const FileInfo& info) : | |
393 type_(type), | |
394 filename_(filename), | |
395 instanceId_(instanceId), | |
396 info_(info) | |
397 { | |
398 assert(type_ == Type_WriteInstance); | |
399 } | |
400 | |
401 void Apply(HierarchicalZipWriter& writer, | |
402 ServerContext& context, | |
403 DicomDirWriter* dicomDir, | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
404 const std::string& dicomDirFolder, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
405 bool transcode, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
406 DicomTransferSyntax transferSyntax) const |
2632 | 407 { |
408 switch (type_) | |
409 { | |
410 case Type_OpenDirectory: | |
411 writer.OpenDirectory(filename_.c_str()); | |
412 break; | |
413 | |
414 case Type_CloseDirectory: | |
415 writer.CloseDirectory(); | |
416 break; | |
417 | |
418 case Type_WriteInstance: | |
419 { | |
420 std::string content; | |
421 | |
422 try | |
423 { | |
424 context.ReadAttachment(content, info_); | |
425 } | |
426 catch (OrthancException& e) | |
427 { | |
428 LOG(WARNING) << "An instance was removed after the job was issued: " << instanceId_; | |
429 return; | |
430 } | |
2636 | 431 |
432 //boost::this_thread::sleep(boost::posix_time::milliseconds(300)); | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
433 |
2632 | 434 writer.OpenFile(filename_.c_str()); |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
435 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
436 bool transcodeSuccess = false; |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
437 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
438 std::unique_ptr<ParsedDicomFile> parsed; |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
439 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
440 if (transcode) |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
441 { |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
442 // New in Orthanc 1.7.0 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
443 std::set<DicomTransferSyntax> syntaxes; |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
444 syntaxes.insert(transferSyntax); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
445 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
446 parsed.reset(new ParsedDicomFile(content)); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
447 const char* data = content.empty() ? NULL : content.c_str(); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
448 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
449 std::unique_ptr<IDicomTranscoder::TranscodedDicom> transcodedDicom( |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
450 context.GetTranscoder().TranscodeToParsed( |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
451 parsed->GetDcmtkObject(), data, content.size(), |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
452 syntaxes, true /* allow new SOP instance UID */)); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
453 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
454 if (transcodedDicom.get() != NULL && |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
455 transcodedDicom->GetDicom().getDataset() != NULL) |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
456 { |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
457 std::string transcoded; |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
458 FromDcmtkBridge::SaveToMemoryBuffer( |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
459 transcoded, *transcodedDicom->GetDicom().getDataset()); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
460 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
461 writer.Write(transcoded); |
2632 | 462 |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
463 if (dicomDir != NULL) |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
464 { |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
465 std::unique_ptr<ParsedDicomFile> tmp( |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
466 ParsedDicomFile::AcquireDcmtkObject(transcodedDicom->ReleaseDicom())); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
467 dicomDir->Add(dicomDirFolder, filename_, *tmp); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
468 } |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
469 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
470 transcodeSuccess = true; |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
471 } |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
472 else |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
473 { |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
474 LOG(INFO) << "Cannot transcode instance " << instanceId_ |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
475 << " to transfer syntax: " << GetTransferSyntaxUid(transferSyntax); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
476 } |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
477 } |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
478 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
479 if (!transcodeSuccess) |
2632 | 480 { |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
481 writer.Write(content); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
482 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
483 if (dicomDir != NULL) |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
484 { |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
485 if (parsed.get() == NULL) |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
486 { |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
487 parsed.reset(new ParsedDicomFile(content)); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
488 } |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
489 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
490 dicomDir->Add(dicomDirFolder, filename_, *parsed); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
491 } |
2632 | 492 } |
493 | |
494 break; | |
495 } | |
496 | |
497 default: | |
498 throw OrthancException(ErrorCode_InternalError); | |
499 } | |
500 } | |
501 }; | |
502 | |
503 std::deque<Command*> commands_; | |
504 uint64_t uncompressedSize_; | |
505 unsigned int instancesCount_; | |
506 | |
507 | |
508 void ApplyInternal(HierarchicalZipWriter& writer, | |
509 ServerContext& context, | |
510 size_t index, | |
511 DicomDirWriter* dicomDir, | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
512 const std::string& dicomDirFolder, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
513 bool transcode, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
514 DicomTransferSyntax transferSyntax) const |
2632 | 515 { |
516 if (index >= commands_.size()) | |
517 { | |
518 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
519 } | |
520 | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
521 commands_[index]->Apply(writer, context, dicomDir, dicomDirFolder, transcode, transferSyntax); |
2632 | 522 } |
523 | |
524 public: | |
525 ZipCommands() : | |
526 uncompressedSize_(0), | |
527 instancesCount_(0) | |
528 { | |
529 } | |
530 | |
531 ~ZipCommands() | |
532 { | |
533 for (std::deque<Command*>::iterator it = commands_.begin(); | |
534 it != commands_.end(); ++it) | |
535 { | |
536 assert(*it != NULL); | |
537 delete *it; | |
538 } | |
539 } | |
540 | |
541 size_t GetSize() const | |
542 { | |
543 return commands_.size(); | |
544 } | |
545 | |
546 unsigned int GetInstancesCount() const | |
547 { | |
548 return instancesCount_; | |
549 } | |
550 | |
551 uint64_t GetUncompressedSize() const | |
552 { | |
553 return uncompressedSize_; | |
554 } | |
555 | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
556 // "media" flavor (with DICOMDIR) |
2632 | 557 void Apply(HierarchicalZipWriter& writer, |
558 ServerContext& context, | |
559 size_t index, | |
560 DicomDirWriter& dicomDir, | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
561 const std::string& dicomDirFolder, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
562 bool transcode, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
563 DicomTransferSyntax transferSyntax) const |
2632 | 564 { |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
565 ApplyInternal(writer, context, index, &dicomDir, dicomDirFolder, transcode, transferSyntax); |
2632 | 566 } |
567 | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
568 // "archive" flavor (without DICOMDIR) |
2632 | 569 void Apply(HierarchicalZipWriter& writer, |
570 ServerContext& context, | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
571 size_t index, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
572 bool transcode, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
573 DicomTransferSyntax transferSyntax) const |
2632 | 574 { |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
575 ApplyInternal(writer, context, index, NULL, "", transcode, transferSyntax); |
2632 | 576 } |
577 | |
578 void AddOpenDirectory(const std::string& filename) | |
579 { | |
580 commands_.push_back(new Command(Type_OpenDirectory, filename)); | |
581 } | |
582 | |
583 void AddCloseDirectory() | |
584 { | |
585 commands_.push_back(new Command(Type_CloseDirectory)); | |
586 } | |
587 | |
588 void AddWriteInstance(const std::string& filename, | |
589 const std::string& instanceId, | |
590 const FileInfo& info) | |
591 { | |
592 commands_.push_back(new Command(Type_WriteInstance, filename, instanceId, info)); | |
593 instancesCount_ ++; | |
594 uncompressedSize_ += info.GetUncompressedSize(); | |
595 } | |
596 | |
597 bool IsZip64() const | |
598 { | |
599 return IsZip64Required(GetUncompressedSize(), GetInstancesCount()); | |
600 } | |
601 }; | |
602 | |
603 | |
604 | |
605 class ArchiveJob::ArchiveIndexVisitor : public IArchiveVisitor | |
606 { | |
607 private: | |
608 ZipCommands& commands_; | |
609 ServerContext& context_; | |
610 char instanceFormat_[24]; | |
611 unsigned int counter_; | |
612 | |
613 static std::string GetTag(const DicomMap& tags, | |
614 const DicomTag& tag) | |
615 { | |
616 const DicomValue* v = tags.TestAndGetValue(tag); | |
617 if (v != NULL && | |
618 !v->IsBinary() && | |
619 !v->IsNull()) | |
620 { | |
621 return v->GetContent(); | |
622 } | |
623 else | |
624 { | |
625 return ""; | |
626 } | |
627 } | |
628 | |
629 public: | |
630 ArchiveIndexVisitor(ZipCommands& commands, | |
631 ServerContext& context) : | |
632 commands_(commands), | |
633 context_(context), | |
634 counter_(0) | |
635 { | |
636 if (commands.GetSize() != 0) | |
637 { | |
638 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
639 } | |
640 | |
641 snprintf(instanceFormat_, sizeof(instanceFormat_) - 1, "%%08d.dcm"); | |
642 } | |
643 | |
644 virtual void Open(ResourceType level, | |
645 const std::string& publicId) | |
646 { | |
647 std::string path; | |
648 | |
649 DicomMap tags; | |
650 if (context_.GetIndex().GetMainDicomTags(tags, publicId, level, level)) | |
651 { | |
652 switch (level) | |
653 { | |
654 case ResourceType_Patient: | |
655 path = GetTag(tags, DICOM_TAG_PATIENT_ID) + " " + GetTag(tags, DICOM_TAG_PATIENT_NAME); | |
656 break; | |
657 | |
658 case ResourceType_Study: | |
659 path = GetTag(tags, DICOM_TAG_ACCESSION_NUMBER) + " " + GetTag(tags, DICOM_TAG_STUDY_DESCRIPTION); | |
660 break; | |
661 | |
662 case ResourceType_Series: | |
663 { | |
664 std::string modality = GetTag(tags, DICOM_TAG_MODALITY); | |
665 path = modality + " " + GetTag(tags, DICOM_TAG_SERIES_DESCRIPTION); | |
666 | |
667 if (modality.size() == 0) | |
668 { | |
669 snprintf(instanceFormat_, sizeof(instanceFormat_) - 1, "%%08d.dcm"); | |
670 } | |
671 else if (modality.size() == 1) | |
672 { | |
673 snprintf(instanceFormat_, sizeof(instanceFormat_) - 1, "%c%%07d.dcm", | |
674 toupper(modality[0])); | |
675 } | |
676 else if (modality.size() >= 2) | |
677 { | |
678 snprintf(instanceFormat_, sizeof(instanceFormat_) - 1, "%c%c%%06d.dcm", | |
679 toupper(modality[0]), toupper(modality[1])); | |
680 } | |
681 | |
682 counter_ = 0; | |
683 | |
684 break; | |
685 } | |
686 | |
687 default: | |
688 throw OrthancException(ErrorCode_InternalError); | |
689 } | |
690 } | |
691 | |
692 path = Toolbox::StripSpaces(Toolbox::ConvertToAscii(path)); | |
693 | |
694 if (path.empty()) | |
695 { | |
696 path = std::string("Unknown ") + EnumerationToString(level); | |
697 } | |
698 | |
699 commands_.AddOpenDirectory(path.c_str()); | |
700 } | |
701 | |
702 virtual void Close() | |
703 { | |
704 commands_.AddCloseDirectory(); | |
705 } | |
706 | |
707 virtual void AddInstance(const std::string& instanceId, | |
708 const FileInfo& dicom) | |
709 { | |
710 char filename[24]; | |
711 snprintf(filename, sizeof(filename) - 1, instanceFormat_, counter_); | |
712 counter_ ++; | |
713 | |
714 commands_.AddWriteInstance(filename, instanceId, dicom); | |
715 } | |
716 }; | |
717 | |
718 | |
719 class ArchiveJob::MediaIndexVisitor : public IArchiveVisitor | |
720 { | |
721 private: | |
722 ZipCommands& commands_; | |
723 ServerContext& context_; | |
724 unsigned int counter_; | |
725 | |
726 public: | |
727 MediaIndexVisitor(ZipCommands& commands, | |
728 ServerContext& context) : | |
729 commands_(commands), | |
730 context_(context), | |
731 counter_(0) | |
732 { | |
733 } | |
734 | |
735 virtual void Open(ResourceType level, | |
736 const std::string& publicId) | |
737 { | |
738 } | |
739 | |
740 virtual void Close() | |
741 { | |
742 } | |
743 | |
744 virtual void AddInstance(const std::string& instanceId, | |
745 const FileInfo& dicom) | |
746 { | |
747 // "DICOM restricts the filenames on DICOM media to 8 | |
748 // characters (some systems wrongly use 8.3, but this does not | |
749 // conform to the standard)." | |
750 std::string filename = "IM" + boost::lexical_cast<std::string>(counter_); | |
751 commands_.AddWriteInstance(filename, instanceId, dicom); | |
752 | |
753 counter_ ++; | |
754 } | |
755 }; | |
756 | |
757 | |
758 class ArchiveJob::ZipWriterIterator : public boost::noncopyable | |
759 { | |
760 private: | |
3712
2a170a8f1faf
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3640
diff
changeset
|
761 TemporaryFile& target_; |
2a170a8f1faf
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3640
diff
changeset
|
762 ServerContext& context_; |
2a170a8f1faf
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3640
diff
changeset
|
763 ZipCommands commands_; |
2a170a8f1faf
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3640
diff
changeset
|
764 std::unique_ptr<HierarchicalZipWriter> zip_; |
2a170a8f1faf
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3640
diff
changeset
|
765 std::unique_ptr<DicomDirWriter> dicomDir_; |
2a170a8f1faf
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3640
diff
changeset
|
766 bool isMedia_; |
2632 | 767 |
768 public: | |
769 ZipWriterIterator(TemporaryFile& target, | |
770 ServerContext& context, | |
771 ArchiveIndex& archive, | |
772 bool isMedia, | |
773 bool enableExtendedSopClass) : | |
774 target_(target), | |
775 context_(context), | |
776 isMedia_(isMedia) | |
777 { | |
778 if (isMedia) | |
779 { | |
780 MediaIndexVisitor visitor(commands_, context); | |
781 archive.Expand(context.GetIndex()); | |
782 | |
783 commands_.AddOpenDirectory(MEDIA_IMAGES_FOLDER); | |
784 archive.Apply(visitor); | |
785 commands_.AddCloseDirectory(); | |
786 | |
787 dicomDir_.reset(new DicomDirWriter); | |
788 dicomDir_->EnableExtendedSopClass(enableExtendedSopClass); | |
789 } | |
790 else | |
791 { | |
792 ArchiveIndexVisitor visitor(commands_, context); | |
793 archive.Expand(context.GetIndex()); | |
794 archive.Apply(visitor); | |
795 } | |
796 | |
797 zip_.reset(new HierarchicalZipWriter(target.GetPath().c_str())); | |
798 zip_->SetZip64(commands_.IsZip64()); | |
799 } | |
800 | |
801 size_t GetStepsCount() const | |
802 { | |
803 return commands_.GetSize() + 1; | |
804 } | |
805 | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
806 void RunStep(size_t index, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
807 bool transcode, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
808 DicomTransferSyntax transferSyntax) |
2632 | 809 { |
810 if (index > commands_.GetSize()) | |
811 { | |
812 throw OrthancException(ErrorCode_ParameterOutOfRange); | |
813 } | |
814 else if (index == commands_.GetSize()) | |
815 { | |
816 // Last step: Add the DICOMDIR | |
817 if (isMedia_) | |
818 { | |
819 assert(dicomDir_.get() != NULL); | |
820 std::string s; | |
821 dicomDir_->Encode(s); | |
822 | |
823 zip_->OpenFile("DICOMDIR"); | |
824 zip_->Write(s); | |
825 } | |
826 } | |
827 else | |
828 { | |
829 if (isMedia_) | |
830 { | |
831 assert(dicomDir_.get() != NULL); | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
832 commands_.Apply(*zip_, context_, index, *dicomDir_, |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
833 MEDIA_IMAGES_FOLDER, transcode, transferSyntax); |
2632 | 834 } |
835 else | |
836 { | |
837 assert(dicomDir_.get() == NULL); | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
838 commands_.Apply(*zip_, context_, index, transcode, transferSyntax); |
2632 | 839 } |
840 } | |
841 } | |
842 | |
843 unsigned int GetInstancesCount() const | |
844 { | |
845 return commands_.GetInstancesCount(); | |
846 } | |
847 | |
848 uint64_t GetUncompressedSize() const | |
849 { | |
850 return commands_.GetUncompressedSize(); | |
851 } | |
852 }; | |
853 | |
854 | |
2966 | 855 ArchiveJob::ArchiveJob(ServerContext& context, |
2632 | 856 bool isMedia, |
857 bool enableExtendedSopClass) : | |
858 context_(context), | |
859 archive_(new ArchiveIndex(ResourceType_Patient)), // root | |
860 isMedia_(isMedia), | |
861 enableExtendedSopClass_(enableExtendedSopClass), | |
862 currentStep_(0), | |
863 instancesCount_(0), | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
864 uncompressedSize_(0), |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
865 transcode_(false), |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
866 transferSyntax_(DicomTransferSyntax_LittleEndianImplicit) |
2632 | 867 { |
2966 | 868 } |
869 | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
870 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
871 ArchiveJob::~ArchiveJob() |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
872 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
873 if (!mediaArchiveId_.empty()) |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
874 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
875 context_.GetMediaArchive().Remove(mediaArchiveId_); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
876 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
877 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
878 |
2966 | 879 |
880 void ArchiveJob::SetSynchronousTarget(boost::shared_ptr<TemporaryFile>& target) | |
881 { | |
882 if (target.get() == NULL) | |
2632 | 883 { |
884 throw OrthancException(ErrorCode_NullPointer); | |
885 } | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
886 else if (writer_.get() != NULL || // Already started |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
887 synchronousTarget_.get() != NULL || |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
888 asynchronousTarget_.get() != NULL) |
2966 | 889 { |
890 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
891 } | |
892 else | |
893 { | |
894 synchronousTarget_ = target; | |
895 } | |
2632 | 896 } |
897 | |
898 | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
899 void ArchiveJob::SetDescription(const std::string& description) |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
900 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
901 if (writer_.get() != NULL) // Already started |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
902 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
903 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
904 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
905 else |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
906 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
907 description_ = description; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
908 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
909 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
910 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
911 |
2632 | 912 void ArchiveJob::AddResource(const std::string& publicId) |
913 { | |
914 if (writer_.get() != NULL) // Already started | |
915 { | |
916 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
917 } | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
918 else |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
919 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
920 ResourceIdentifiers resource(context_.GetIndex(), publicId); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
921 archive_->Add(context_.GetIndex(), resource); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
922 } |
2632 | 923 } |
924 | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
925 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
926 void ArchiveJob::SetTranscode(DicomTransferSyntax transferSyntax) |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
927 { |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
928 if (writer_.get() != NULL) // Already started |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
929 { |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
930 throw OrthancException(ErrorCode_BadSequenceOfCalls); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
931 } |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
932 else |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
933 { |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
934 transcode_ = true; |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
935 transferSyntax_ = transferSyntax; |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
936 } |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
937 } |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
938 |
2632 | 939 |
2812
ea7aea6f6a95
improved naming of methods in IJob
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2730
diff
changeset
|
940 void ArchiveJob::Reset() |
2632 | 941 { |
2955 | 942 throw OrthancException(ErrorCode_BadSequenceOfCalls, |
943 "Cannot resubmit the creation of an archive"); | |
2632 | 944 } |
945 | |
946 | |
947 void ArchiveJob::Start() | |
948 { | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
949 TemporaryFile* target = NULL; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
950 |
2966 | 951 if (synchronousTarget_.get() == NULL) |
952 { | |
3181
6fd38327e777
Fix issue #130 (Orthanc failed to start when /tmp partition was full)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3095
diff
changeset
|
953 { |
6fd38327e777
Fix issue #130 (Orthanc failed to start when /tmp partition was full)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3095
diff
changeset
|
954 OrthancConfiguration::ReaderLock lock; |
6fd38327e777
Fix issue #130 (Orthanc failed to start when /tmp partition was full)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3095
diff
changeset
|
955 asynchronousTarget_.reset(lock.GetConfiguration().CreateTemporaryFile()); |
6fd38327e777
Fix issue #130 (Orthanc failed to start when /tmp partition was full)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3095
diff
changeset
|
956 } |
6fd38327e777
Fix issue #130 (Orthanc failed to start when /tmp partition was full)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3095
diff
changeset
|
957 |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
958 target = asynchronousTarget_.get(); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
959 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
960 else |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
961 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
962 target = synchronousTarget_.get(); |
2966 | 963 } |
3181
6fd38327e777
Fix issue #130 (Orthanc failed to start when /tmp partition was full)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3095
diff
changeset
|
964 |
6fd38327e777
Fix issue #130 (Orthanc failed to start when /tmp partition was full)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3095
diff
changeset
|
965 assert(target != NULL); |
6fd38327e777
Fix issue #130 (Orthanc failed to start when /tmp partition was full)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3095
diff
changeset
|
966 target->Touch(); // Make sure we can write to the temporary file |
2966 | 967 |
2632 | 968 if (writer_.get() != NULL) |
969 { | |
970 throw OrthancException(ErrorCode_BadSequenceOfCalls); | |
971 } | |
972 | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
973 writer_.reset(new ZipWriterIterator(*target, context_, *archive_, |
2632 | 974 isMedia_, enableExtendedSopClass_)); |
975 | |
976 instancesCount_ = writer_->GetInstancesCount(); | |
977 uncompressedSize_ = writer_->GetUncompressedSize(); | |
978 } | |
979 | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
980 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
981 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
982 namespace |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
983 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
984 class DynamicTemporaryFile : public IDynamicObject |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
985 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
986 private: |
3712
2a170a8f1faf
replacing std::auto_ptr by std::unique_ptr
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3640
diff
changeset
|
987 std::unique_ptr<TemporaryFile> file_; |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
988 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
989 public: |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
990 DynamicTemporaryFile(TemporaryFile* f) : file_(f) |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
991 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
992 if (f == NULL) |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
993 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
994 throw OrthancException(ErrorCode_NullPointer); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
995 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
996 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
997 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
998 const TemporaryFile& GetFile() const |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
999 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1000 assert(file_.get() != NULL); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1001 return *file_; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1002 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1003 }; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1004 } |
2632 | 1005 |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1006 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1007 void ArchiveJob::FinalizeTarget() |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1008 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1009 writer_.reset(); // Flush all the results |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1010 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1011 if (asynchronousTarget_.get() != NULL) |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1012 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1013 // Asynchronous behavior: Move the resulting file into the media archive |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1014 mediaArchiveId_ = context_.GetMediaArchive().Add( |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1015 new DynamicTemporaryFile(asynchronousTarget_.release())); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1016 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1017 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1018 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1019 |
3658
2d90dd30858c
providing job ID to the IJob::Step() methods
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3640
diff
changeset
|
1020 JobStepResult ArchiveJob::Step(const std::string& jobId) |
2632 | 1021 { |
1022 assert(writer_.get() != NULL); | |
1023 | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1024 if (synchronousTarget_.get() != NULL && |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1025 synchronousTarget_.unique()) |
2632 | 1026 { |
1027 LOG(WARNING) << "A client has disconnected while creating an archive"; | |
3240
e44e0127e553
Fix issue #134 (/patient/modify gives 500, should really be 400)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3181
diff
changeset
|
1028 return JobStepResult::Failure(ErrorCode_NetworkProtocol, |
e44e0127e553
Fix issue #134 (/patient/modify gives 500, should really be 400)
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3181
diff
changeset
|
1029 "A client has disconnected while creating an archive"); |
2632 | 1030 } |
1031 | |
1032 if (writer_->GetStepsCount() == 0) | |
1033 { | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1034 FinalizeTarget(); |
2632 | 1035 return JobStepResult::Success(); |
1036 } | |
1037 else | |
1038 { | |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
1039 writer_->RunStep(currentStep_, transcode_, transferSyntax_); |
2632 | 1040 |
1041 currentStep_ ++; | |
1042 | |
1043 if (currentStep_ == writer_->GetStepsCount()) | |
1044 { | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1045 FinalizeTarget(); |
2632 | 1046 return JobStepResult::Success(); |
1047 } | |
1048 else | |
1049 { | |
1050 return JobStepResult::Continue(); | |
1051 } | |
1052 } | |
1053 } | |
1054 | |
1055 | |
1056 float ArchiveJob::GetProgress() | |
1057 { | |
1058 if (writer_.get() == NULL || | |
1059 writer_->GetStepsCount() == 0) | |
1060 { | |
1061 return 1; | |
1062 } | |
1063 else | |
1064 { | |
1065 return (static_cast<float>(currentStep_) / | |
1066 static_cast<float>(writer_->GetStepsCount() - 1)); | |
1067 } | |
1068 } | |
1069 | |
1070 | |
1071 void ArchiveJob::GetJobType(std::string& target) | |
1072 { | |
1073 if (isMedia_) | |
1074 { | |
1075 target = "Media"; | |
1076 } | |
1077 else | |
1078 { | |
1079 target = "Archive"; | |
1080 } | |
1081 } | |
1082 | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1083 |
2632 | 1084 void ArchiveJob::GetPublicContent(Json::Value& value) |
1085 { | |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1086 value = Json::objectValue; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1087 value[KEY_DESCRIPTION] = description_; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1088 value[KEY_INSTANCES_COUNT] = instancesCount_; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1089 value[KEY_UNCOMPRESSED_SIZE_MB] = |
2643 | 1090 static_cast<unsigned int>(uncompressedSize_ / MEGA_BYTES); |
3913
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
1091 |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
1092 if (transcode_) |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
1093 { |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
1094 value[KEY_TRANSCODE] = GetTransferSyntaxUid(transferSyntax_); |
6ddad3e0b569
transcoding ZIP archive and media
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
3713
diff
changeset
|
1095 } |
2632 | 1096 } |
2976
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1097 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1098 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1099 bool ArchiveJob::GetOutput(std::string& output, |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1100 MimeType& mime, |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1101 const std::string& key) |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1102 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1103 if (key == "archive" && |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1104 !mediaArchiveId_.empty()) |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1105 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1106 SharedArchive::Accessor accessor(context_.GetMediaArchive(), mediaArchiveId_); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1107 |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1108 if (accessor.IsValid()) |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1109 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1110 const DynamicTemporaryFile& f = dynamic_cast<DynamicTemporaryFile&>(accessor.GetItem()); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1111 f.GetFile().Read(output); |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1112 mime = MimeType_Zip; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1113 return true; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1114 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1115 else |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1116 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1117 return false; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1118 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1119 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1120 else |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1121 { |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1122 return false; |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1123 } |
cb5d75143da0
Asynchronous generation of ZIP archives and DICOM medias
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
2966
diff
changeset
|
1124 } |
2632 | 1125 } |