Mercurial > hg > orthanc
comparison OrthancServer/DicomInstanceToStore.cpp @ 3841:be7df7fe3d80
avoid one memcpy of the DICOM buffer on "POST /instances"
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 16 Apr 2020 16:58:37 +0200 |
parents | 2a170a8f1faf |
children | 281045a1e6db |
comparison
equal
deleted
inserted
replaced
3840:e7003b2203a7 | 3841:be7df7fe3d80 |
---|---|
148 | 148 |
149 class DicomInstanceToStore::PImpl | 149 class DicomInstanceToStore::PImpl |
150 { | 150 { |
151 public: | 151 public: |
152 DicomInstanceOrigin origin_; | 152 DicomInstanceOrigin origin_; |
153 SmartContainer<std::string> buffer_; | 153 bool hasBuffer_; |
154 std::unique_ptr<std::string> ownBuffer_; | |
155 const void* bufferData_; | |
156 size_t bufferSize_; | |
154 SmartContainer<ParsedDicomFile> parsed_; | 157 SmartContainer<ParsedDicomFile> parsed_; |
155 SmartContainer<DicomMap> summary_; | 158 SmartContainer<DicomMap> summary_; |
156 SmartContainer<Json::Value> json_; | 159 SmartContainer<Json::Value> json_; |
157 MetadataMap metadata_; | 160 MetadataMap metadata_; |
158 | 161 |
162 PImpl() : | |
163 hasBuffer_(false), | |
164 bufferData_(NULL), | |
165 bufferSize_(0) | |
166 { | |
167 } | |
168 | |
159 private: | 169 private: |
160 std::unique_ptr<DicomInstanceHasher> hasher_; | 170 std::unique_ptr<DicomInstanceHasher> hasher_; |
161 | 171 |
162 void ComputeMissingInformation() | 172 void ComputeMissingInformation() |
163 { | 173 { |
164 if (buffer_.HasContent() && | 174 if (hasBuffer_ && |
165 summary_.HasContent() && | 175 summary_.HasContent() && |
166 json_.HasContent()) | 176 json_.HasContent()) |
167 { | 177 { |
168 // Fine, everything is available | 178 // Fine, everything is available |
169 return; | 179 return; |
170 } | 180 } |
171 | 181 |
172 if (!buffer_.HasContent()) | 182 if (!hasBuffer_) |
173 { | 183 { |
174 if (!parsed_.HasContent()) | 184 if (!parsed_.HasContent()) |
175 { | 185 { |
176 if (!summary_.HasContent()) | 186 if (!summary_.HasContent()) |
177 { | 187 { |
184 false /* be strict */)); | 194 false /* be strict */)); |
185 } | 195 } |
186 } | 196 } |
187 | 197 |
188 // Serialize the parsed DICOM file | 198 // Serialize the parsed DICOM file |
189 buffer_.Allocate(); | 199 ownBuffer_.reset(new std::string); |
190 if (!FromDcmtkBridge::SaveToMemoryBuffer(buffer_.GetContent(), | 200 if (!FromDcmtkBridge::SaveToMemoryBuffer(*ownBuffer_, |
191 *parsed_.GetContent().GetDcmtkObject().getDataset())) | 201 *parsed_.GetContent().GetDcmtkObject().getDataset())) |
192 { | 202 { |
193 throw OrthancException(ErrorCode_InternalError, | 203 throw OrthancException(ErrorCode_InternalError, |
194 "Unable to serialize a DICOM file to a memory buffer"); | 204 "Unable to serialize a DICOM file to a memory buffer"); |
195 } | 205 } |
206 | |
207 hasBuffer_ = true; | |
196 } | 208 } |
197 | 209 |
198 if (summary_.HasContent() && | 210 if (summary_.HasContent() && |
199 json_.HasContent()) | 211 json_.HasContent()) |
200 { | 212 { |
203 | 215 |
204 // At this point, we know that the DICOM file is available as a | 216 // At this point, we know that the DICOM file is available as a |
205 // memory buffer, but that its summary or its JSON version is | 217 // memory buffer, but that its summary or its JSON version is |
206 // missing | 218 // missing |
207 | 219 |
220 assert(hasBuffer_); | |
208 if (!parsed_.HasContent()) | 221 if (!parsed_.HasContent()) |
209 { | 222 { |
210 parsed_.TakeOwnership(new ParsedDicomFile(buffer_.GetConstContent())); | 223 if (ownBuffer_.get() != NULL) |
224 { | |
225 parsed_.TakeOwnership(new ParsedDicomFile(*ownBuffer_)); | |
226 } | |
227 else | |
228 { | |
229 parsed_.TakeOwnership(new ParsedDicomFile(bufferData_, bufferSize_)); | |
230 } | |
211 } | 231 } |
212 | 232 |
213 // At this point, we have parsed the DICOM file | 233 // At this point, we have parsed the DICOM file |
214 | 234 |
215 if (!summary_.HasContent()) | 235 if (!summary_.HasContent()) |
230 } | 250 } |
231 } | 251 } |
232 | 252 |
233 | 253 |
234 public: | 254 public: |
235 const char* GetBufferData() | 255 void SetBuffer(const void* data, |
256 size_t size) | |
257 { | |
258 ownBuffer_.reset(NULL); | |
259 bufferData_ = data; | |
260 bufferSize_ = size; | |
261 hasBuffer_ = true; | |
262 } | |
263 | |
264 const void* GetBufferData() | |
236 { | 265 { |
237 ComputeMissingInformation(); | 266 ComputeMissingInformation(); |
238 | 267 |
239 if (!buffer_.HasContent()) | 268 if (!hasBuffer_) |
240 { | 269 { |
241 throw OrthancException(ErrorCode_InternalError); | 270 throw OrthancException(ErrorCode_InternalError); |
242 } | 271 } |
243 | 272 |
244 if (buffer_.GetConstContent().size() == 0) | 273 if (ownBuffer_.get() != NULL) |
245 { | 274 { |
246 return NULL; | 275 if (ownBuffer_->empty()) |
276 { | |
277 return NULL; | |
278 } | |
279 else | |
280 { | |
281 return ownBuffer_->c_str(); | |
282 } | |
247 } | 283 } |
248 else | 284 else |
249 { | 285 { |
250 return buffer_.GetConstContent().c_str(); | 286 return bufferData_; |
251 } | 287 } |
252 } | 288 } |
253 | 289 |
254 | 290 |
255 size_t GetBufferSize() | 291 size_t GetBufferSize() |
256 { | 292 { |
257 ComputeMissingInformation(); | 293 ComputeMissingInformation(); |
258 | 294 |
259 if (!buffer_.HasContent()) | 295 if (!hasBuffer_) |
260 { | 296 { |
261 throw OrthancException(ErrorCode_InternalError); | 297 throw OrthancException(ErrorCode_InternalError); |
262 } | 298 } |
263 | 299 |
264 return buffer_.GetConstContent().size(); | 300 if (ownBuffer_.get() != NULL) |
301 { | |
302 return ownBuffer_->size(); | |
303 } | |
304 else | |
305 { | |
306 return bufferSize_; | |
307 } | |
265 } | 308 } |
266 | 309 |
267 | 310 |
268 const DicomMap& GetSummary() | 311 const DicomMap& GetSummary() |
269 { | 312 { |
345 { | 388 { |
346 return pimpl_->origin_; | 389 return pimpl_->origin_; |
347 } | 390 } |
348 | 391 |
349 | 392 |
350 void DicomInstanceToStore::SetBuffer(const std::string& dicom) | 393 void DicomInstanceToStore::SetBuffer(const void* dicom, |
351 { | 394 size_t size) |
352 pimpl_->buffer_.SetConstReference(dicom); | 395 { |
396 pimpl_->SetBuffer(dicom, size); | |
353 } | 397 } |
354 | 398 |
355 | 399 |
356 void DicomInstanceToStore::SetParsedDicomFile(ParsedDicomFile& parsed) | 400 void DicomInstanceToStore::SetParsedDicomFile(ParsedDicomFile& parsed) |
357 { | 401 { |
389 { | 433 { |
390 pimpl_->metadata_[std::make_pair(level, metadata)] = value; | 434 pimpl_->metadata_[std::make_pair(level, metadata)] = value; |
391 } | 435 } |
392 | 436 |
393 | 437 |
394 const char* DicomInstanceToStore::GetBufferData() | 438 const void* DicomInstanceToStore::GetBufferData() |
395 { | 439 { |
396 return pimpl_->GetBufferData(); | 440 return pimpl_->GetBufferData(); |
397 } | 441 } |
398 | 442 |
399 | 443 |