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