comparison OrthancFramework/Sources/FileStorage/StorageAccessor.cpp @ 4044:d25f4c0fa160 framework

splitting code into OrthancFramework and OrthancServer
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 10 Jun 2020 20:30:34 +0200
parents Core/FileStorage/StorageAccessor.cpp@2a170a8f1faf
children bf7b9edf6b81
comparison
equal deleted inserted replaced
4043:6c6239aec462 4044:d25f4c0fa160
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-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 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 "../PrecompiledHeaders.h"
35 #include "StorageAccessor.h"
36
37 #include "../Compatibility.h"
38 #include "../Compression/ZlibCompressor.h"
39 #include "../MetricsRegistry.h"
40 #include "../OrthancException.h"
41 #include "../Toolbox.h"
42
43 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
44 # include "../HttpServer/HttpStreamTranscoder.h"
45 #endif
46
47
48 static const std::string METRICS_CREATE = "orthanc_storage_create_duration_ms";
49 static const std::string METRICS_READ = "orthanc_storage_read_duration_ms";
50 static const std::string METRICS_REMOVE = "orthanc_storage_remove_duration_ms";
51
52
53 namespace Orthanc
54 {
55 class StorageAccessor::MetricsTimer : public boost::noncopyable
56 {
57 private:
58 std::unique_ptr<MetricsRegistry::Timer> timer_;
59
60 public:
61 MetricsTimer(StorageAccessor& that,
62 const std::string& name)
63 {
64 if (that.metrics_ != NULL)
65 {
66 timer_.reset(new MetricsRegistry::Timer(*that.metrics_, name));
67 }
68 }
69 };
70
71
72 FileInfo StorageAccessor::Write(const void* data,
73 size_t size,
74 FileContentType type,
75 CompressionType compression,
76 bool storeMd5)
77 {
78 std::string uuid = Toolbox::GenerateUuid();
79
80 std::string md5;
81
82 if (storeMd5)
83 {
84 Toolbox::ComputeMD5(md5, data, size);
85 }
86
87 switch (compression)
88 {
89 case CompressionType_None:
90 {
91 MetricsTimer timer(*this, METRICS_CREATE);
92
93 area_.Create(uuid, data, size, type);
94 return FileInfo(uuid, type, size, md5);
95 }
96
97 case CompressionType_ZlibWithSize:
98 {
99 ZlibCompressor zlib;
100
101 std::string compressed;
102 zlib.Compress(compressed, data, size);
103
104 std::string compressedMD5;
105
106 if (storeMd5)
107 {
108 Toolbox::ComputeMD5(compressedMD5, compressed);
109 }
110
111 {
112 MetricsTimer timer(*this, METRICS_CREATE);
113
114 if (compressed.size() > 0)
115 {
116 area_.Create(uuid, &compressed[0], compressed.size(), type);
117 }
118 else
119 {
120 area_.Create(uuid, NULL, 0, type);
121 }
122 }
123
124 return FileInfo(uuid, type, size, md5,
125 CompressionType_ZlibWithSize, compressed.size(), compressedMD5);
126 }
127
128 default:
129 throw OrthancException(ErrorCode_NotImplemented);
130 }
131 }
132
133
134 void StorageAccessor::Read(std::string& content,
135 const FileInfo& info)
136 {
137 switch (info.GetCompressionType())
138 {
139 case CompressionType_None:
140 {
141 MetricsTimer timer(*this, METRICS_READ);
142 area_.Read(content, info.GetUuid(), info.GetContentType());
143 break;
144 }
145
146 case CompressionType_ZlibWithSize:
147 {
148 ZlibCompressor zlib;
149
150 std::string compressed;
151
152 {
153 MetricsTimer timer(*this, METRICS_READ);
154 area_.Read(compressed, info.GetUuid(), info.GetContentType());
155 }
156
157 IBufferCompressor::Uncompress(content, zlib, compressed);
158 break;
159 }
160
161 default:
162 {
163 throw OrthancException(ErrorCode_NotImplemented);
164 }
165 }
166
167 // TODO Check the validity of the uncompressed MD5?
168 }
169
170
171 void StorageAccessor::ReadRaw(std::string& content,
172 const FileInfo& info)
173 {
174 MetricsTimer timer(*this, METRICS_READ);
175 area_.Read(content, info.GetUuid(), info.GetContentType());
176 }
177
178
179 void StorageAccessor::Remove(const std::string& fileUuid,
180 FileContentType type)
181 {
182 MetricsTimer timer(*this, METRICS_REMOVE);
183 area_.Remove(fileUuid, type);
184 }
185
186
187 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
188 void StorageAccessor::SetupSender(BufferHttpSender& sender,
189 const FileInfo& info,
190 const std::string& mime)
191 {
192 {
193 MetricsTimer timer(*this, METRICS_READ);
194 area_.Read(sender.GetBuffer(), info.GetUuid(), info.GetContentType());
195 }
196
197 sender.SetContentType(mime);
198
199 const char* extension;
200 switch (info.GetContentType())
201 {
202 case FileContentType_Dicom:
203 extension = ".dcm";
204 break;
205
206 case FileContentType_DicomAsJson:
207 extension = ".json";
208 break;
209
210 default:
211 // Non-standard content type
212 extension = "";
213 }
214
215 sender.SetContentFilename(info.GetUuid() + std::string(extension));
216 }
217 #endif
218
219
220 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
221 void StorageAccessor::AnswerFile(HttpOutput& output,
222 const FileInfo& info,
223 const std::string& mime)
224 {
225 BufferHttpSender sender;
226 SetupSender(sender, info, mime);
227
228 HttpStreamTranscoder transcoder(sender, info.GetCompressionType());
229 output.Answer(transcoder);
230 }
231 #endif
232
233
234 #if ORTHANC_ENABLE_CIVETWEB == 1 || ORTHANC_ENABLE_MONGOOSE == 1
235 void StorageAccessor::AnswerFile(RestApiOutput& output,
236 const FileInfo& info,
237 const std::string& mime)
238 {
239 BufferHttpSender sender;
240 SetupSender(sender, info, mime);
241
242 HttpStreamTranscoder transcoder(sender, info.GetCompressionType());
243 output.AnswerStream(transcoder);
244 }
245 #endif
246 }