comparison Framework/Oracle/GenericOracleRunner.cpp @ 1136:42581a6182c8 broker

reactivation of the cache of parsed DICOM files
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 06 Nov 2019 17:54:14 +0100
parents a0a33e5ea5bb
children cc029987b6dc
comparison
equal deleted inserted replaced
1135:a0a33e5ea5bb 1136:42581a6182c8
236 emitter.EmitMessage(receiver, message); 236 emitter.EmitMessage(receiver, message);
237 } 237 }
238 238
239 239
240 #if ORTHANC_ENABLE_DCMTK == 1 240 #if ORTHANC_ENABLE_DCMTK == 1
241 static void RunInternal(boost::weak_ptr<IObserver> receiver, 241 namespace
242 IMessageEmitter& emitter, 242 {
243 const std::string& root, 243 class IDicomHandler : public boost::noncopyable
244 const ParseDicomFileCommand& command) 244 {
245 { 245 public:
246 std::string path = GetPath(root, command.GetPath()); 246 virtual ~IDicomHandler()
247 247 {
248 if (!Orthanc::SystemToolbox::IsRegularFile(path)) 248 }
249 { 249
250 throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentFile); 250 virtual void Handle(Orthanc::ParsedDicomFile* dicom,
251 } 251 const ParseDicomFileCommand& command,
252 252 uint64_t fileSize) = 0;
253 uint64_t fileSize = Orthanc::SystemToolbox::GetFileSize(path); 253
254 254 static void Apply(IDicomHandler& handler,
255 // Check for 32bit systems 255 const std::string& root,
256 if (fileSize != static_cast<uint64_t>(static_cast<size_t>(fileSize))) 256 const ParseDicomFileCommand& command)
257 { 257 {
258 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); 258 std::string path = GetPath(root, command.GetPath());
259 } 259
260 260 if (!Orthanc::SystemToolbox::IsRegularFile(path))
261 DcmFileFormat dicom; 261 {
262 bool ok; 262 throw Orthanc::OrthancException(Orthanc::ErrorCode_InexistentFile);
263 263 }
264 if (command.IsPixelDataIncluded()) 264
265 { 265 uint64_t fileSize = Orthanc::SystemToolbox::GetFileSize(path);
266 ok = dicom.loadFile(path.c_str()).good(); 266
267 } 267 // Check for 32bit systems
268 else 268 if (fileSize != static_cast<uint64_t>(static_cast<size_t>(fileSize)))
269 { 269 {
270 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory);
271 }
272
273 DcmFileFormat dicom;
274 bool ok;
275
276 if (command.IsPixelDataIncluded())
277 {
278 ok = dicom.loadFile(path.c_str()).good();
279 }
280 else
281 {
270 #if DCMTK_VERSION_NUMBER >= 362 282 #if DCMTK_VERSION_NUMBER >= 362
271 // NB : We could stop at (0x3007, 0x0000) instead of 283 // NB : We could stop at (0x3007, 0x0000) instead of
272 // DCM_PixelData, cf. the Orthanc::DICOM_TAG_* constants 284 // DCM_PixelData, cf. the Orthanc::DICOM_TAG_* constants
273 285
274 static const DcmTagKey STOP = DCM_PixelData; 286 static const DcmTagKey STOP = DCM_PixelData;
275 //static const DcmTagKey STOP(0x3007, 0x0000); 287 //static const DcmTagKey STOP(0x3007, 0x0000);
276 288
277 ok = dicom.loadFileUntilTag(path.c_str(), EXS_Unknown, EGL_noChange, 289 ok = dicom.loadFileUntilTag(path.c_str(), EXS_Unknown, EGL_noChange,
278 DCM_MaxReadLength, ERM_autoDetect, STOP).good(); 290 DCM_MaxReadLength, ERM_autoDetect, STOP).good();
279 #else 291 #else
280 // The primitive "loadFileUntilTag" was introduced in DCMTK 3.6.2 292 // The primitive "loadFileUntilTag" was introduced in DCMTK 3.6.2
281 ok = dicom.loadFile(path.c_str()).good(); 293 ok = dicom.loadFile(path.c_str()).good();
282 #endif 294 #endif
283 } 295 }
284 296
285 printf("Reading %s\n", path.c_str()); 297 printf("Reading %s\n", path.c_str());
286 298
287 if (ok) 299 if (ok)
288 { 300 {
289 Orthanc::ParsedDicomFile parsed(dicom); 301 handler.Handle(new Orthanc::ParsedDicomFile(dicom), command, fileSize);
290 ParseDicomFileCommand::SuccessMessage message 302 }
291 (command, parsed, static_cast<size_t>(fileSize), command.IsPixelDataIncluded()); 303 else
292 emitter.EmitMessage(receiver, message); 304 {
293 } 305 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat,
294 else 306 "Cannot parse file: " + path);
295 { 307 }
296 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadFileFormat, 308 }
297 "Cannot parse file: " + path); 309 };
298 } 310
311
312 class DicomHandlerWithoutCache : public IDicomHandler
313 {
314 private:
315 boost::weak_ptr<IObserver> receiver_;
316 IMessageEmitter& emitter_;
317
318 public:
319 DicomHandlerWithoutCache(boost::weak_ptr<IObserver> receiver,
320 IMessageEmitter& emitter) :
321 receiver_(receiver),
322 emitter_(emitter)
323 {
324 }
325
326 virtual void Handle(Orthanc::ParsedDicomFile* dicom,
327 const ParseDicomFileCommand& command,
328 uint64_t fileSize)
329 {
330 std::auto_ptr<Orthanc::ParsedDicomFile> parsed(dicom);
331
332 ParseDicomFileCommand::SuccessMessage message
333 (command, *parsed, static_cast<size_t>(fileSize), command.IsPixelDataIncluded());
334 emitter_.EmitMessage(receiver_, message);
335 }
336 };
337
338
339 class DicomHandlerWithCache : public IDicomHandler
340 {
341 private:
342 boost::weak_ptr<IObserver> receiver_;
343 IMessageEmitter& emitter_;
344 boost::shared_ptr<ParsedDicomFileCache> cache_;
345
346 public:
347 DicomHandlerWithCache(boost::weak_ptr<IObserver> receiver,
348 IMessageEmitter& emitter,
349 boost::shared_ptr<ParsedDicomFileCache> cache) :
350 receiver_(receiver),
351 emitter_(emitter),
352 cache_(cache)
353 {
354 if (!cache)
355 {
356 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
357 }
358 }
359
360 virtual void Handle(Orthanc::ParsedDicomFile* dicom,
361 const ParseDicomFileCommand& command,
362 uint64_t fileSize)
363 {
364 std::auto_ptr<Orthanc::ParsedDicomFile> parsed(dicom);
365
366 {
367 ParseDicomFileCommand::SuccessMessage message
368 (command, *parsed, static_cast<size_t>(fileSize), command.IsPixelDataIncluded());
369 emitter_.EmitMessage(receiver_, message);
370 }
371
372 // Store it into the cache for future use
373 assert(cache_);
374 cache_->Acquire(command.GetPath(), parsed.release(),
375 static_cast<size_t>(fileSize), command.IsPixelDataIncluded());
376 }
377 };
299 } 378 }
300 379
301 380
302 static void RunInternal(boost::weak_ptr<IObserver> receiver, 381 static void RunInternal(boost::weak_ptr<IObserver> receiver,
303 IMessageEmitter& emitter, 382 IMessageEmitter& emitter,
304 boost::shared_ptr<ParsedDicomFileCache> cache, 383 boost::shared_ptr<ParsedDicomFileCache> cache,
305 const std::string& root, 384 const std::string& root,
306 const ParseDicomFileCommand& command) 385 const ParseDicomFileCommand& command)
307 { 386 {
308 #if 0 387 #if 1
309 // The code to use the cache is buggy in multithreaded environments => TODO FIX
310 if (cache.get()) 388 if (cache.get())
311 { 389 {
312 { 390 {
313 ParsedDicomFileCache::Reader reader(*cache, command.GetPath()); 391 ParsedDicomFileCache::Reader reader(*cache, command.GetPath());
314 if (reader.IsValid() && 392 if (reader.IsValid() &&
315 (!command.IsPixelDataIncluded() || 393 (!command.IsPixelDataIncluded() ||
316 reader.HasPixelData())) 394 reader.HasPixelData()))
317 { 395 {
318 // Reuse the DICOM file from the cache 396 // Reuse the DICOM file from the cache
319 return new ParseDicomFileCommand::SuccessMessage( 397 ParseDicomFileCommand::SuccessMessage message(
320 command, reader.GetDicom(), reader.GetFileSize(), reader.HasPixelData()); 398 command, reader.GetDicom(), reader.GetFileSize(), reader.HasPixelData());
321 emitter.EmitMessage(receiver, message); 399 emitter.EmitMessage(receiver, message);
322 return; 400 return;
323 } 401 }
324 } 402 }
325 403
326 // Not in the cache, first read and parse the DICOM file 404 DicomHandlerWithCache handler(receiver, emitter, cache);
327 std::auto_ptr<ParseDicomFileCommand::SuccessMessage> message(RunInternal(root, command)); 405 IDicomHandler::Apply(handler, root, command);
328
329 // Secondly, store it into the cache for future use
330 assert(&message->GetOrigin() == &command);
331 cache->Acquire(message->GetOrigin().GetPath(), message->GetDicom(),
332 message->GetFileSize(), message->HasPixelData());
333
334 return message.release();
335 } 406 }
336 else 407 else
337 { 408 {
338 // No cache available 409 // No cache available
339 return RunInternal(root, command); 410 DicomHandlerWithoutCache handler(receiver, emitter);
411 IDicomHandler::Apply(handler, root, command);
340 } 412 }
341 #else 413 #else
342 return RunInternal(receiver, emitter, root, command); 414 DicomHandlerWithoutCache handler(receiver, emitter);
415 IDicomHandler::Apply(handler, root, command);
343 #endif 416 #endif
344 } 417 }
345 418
346 #endif 419 #endif
347 420