comparison OrthancServer/OrthancFindRequestHandler.cpp @ 3012:af1530b45290

Optimization: On finds, do not read JSON (disk) if main DICOM tags (DB) are sufficient
author Sebastien Jodogne <s.jodogne@gmail.com>
date Thu, 13 Dec 2018 17:54:06 +0100
parents 8265a6b56100
children abe49ca61cd5
comparison
equal deleted inserted replaced
3010:9f859a18cbc2 3012:af1530b45290
363 return result.release(); 363 return result.release();
364 } 364 }
365 365
366 366
367 static void AddAnswer(DicomFindAnswers& answers, 367 static void AddAnswer(DicomFindAnswers& answers,
368 const Json::Value& resource, 368 const DicomMap& mainDicomTags,
369 const Json::Value* dicomAsJson, // only used for sequences
369 const DicomArray& query, 370 const DicomArray& query,
370 const std::list<DicomTag>& sequencesToReturn, 371 const std::list<DicomTag>& sequencesToReturn,
371 const DicomMap* counters) 372 const DicomMap* counters)
372 { 373 {
373 DicomMap result; 374 DicomMap result;
381 } 382 }
382 else if (query.GetElement(i).GetTag() == DICOM_TAG_SPECIFIC_CHARACTER_SET) 383 else if (query.GetElement(i).GetTag() == DICOM_TAG_SPECIFIC_CHARACTER_SET)
383 { 384 {
384 // Do not include the encoding, this is handled by class ParsedDicomFile 385 // Do not include the encoding, this is handled by class ParsedDicomFile
385 } 386 }
386 else 387 else if (dicomAsJson != NULL)
387 { 388 {
388 std::string tag = query.GetElement(i).GetTag().Format(); 389 std::string tag = query.GetElement(i).GetTag().Format();
389 std::string value; 390 std::string value;
390 if (resource.isMember(tag)) 391 if (dicomAsJson->isMember(tag))
391 { 392 {
392 value = resource.get(tag, Json::arrayValue).get("Value", "").asString(); 393 value = dicomAsJson->get(tag, Json::arrayValue).get("Value", "").asString();
393 result.SetValue(query.GetElement(i).GetTag(), value, false); 394 result.SetValue(query.GetElement(i).GetTag(), value, false);
394 } 395 }
395 else 396 else
396 { 397 {
397 result.SetValue(query.GetElement(i).GetTag(), "", false); 398 result.SetValue(query.GetElement(i).GetTag(), "", false);
398 } 399 }
400 }
401 else
402 {
403 // Best-effort
404 // TODO
405 throw OrthancException(ErrorCode_NotImplemented);
399 } 406 }
400 } 407 }
401 408
402 if (counters != NULL) 409 if (counters != NULL)
403 { 410 {
411 if (result.GetSize() == 0 && 418 if (result.GetSize() == 0 &&
412 sequencesToReturn.empty()) 419 sequencesToReturn.empty())
413 { 420 {
414 LOG(WARNING) << "The C-FIND request does not return any DICOM tag"; 421 LOG(WARNING) << "The C-FIND request does not return any DICOM tag";
415 } 422 }
416 else if (sequencesToReturn.empty()) 423 else if (sequencesToReturn.empty() ||
424 dicomAsJson == NULL)
417 { 425 {
418 answers.Add(result); 426 answers.Add(result);
419 } 427 }
420 else 428 else
421 { 429 {
422 ParsedDicomFile dicom(result); 430 ParsedDicomFile dicom(result);
423 431
424 for (std::list<DicomTag>::const_iterator tag = sequencesToReturn.begin(); 432 for (std::list<DicomTag>::const_iterator tag = sequencesToReturn.begin();
425 tag != sequencesToReturn.end(); ++tag) 433 tag != sequencesToReturn.end(); ++tag)
426 { 434 {
427 const Json::Value& source = resource[tag->Format()]; 435 assert(dicomAsJson != NULL);
436 const Json::Value& source = (*dicomAsJson) [tag->Format()];
428 437
429 if (source.type() == Json::objectValue && 438 if (source.type() == Json::objectValue &&
430 source.isMember("Type") && 439 source.isMember("Type") &&
431 source.isMember("Value") && 440 source.isMember("Value") &&
432 source["Type"].asString() == "Sequence" && 441 source["Type"].asString() == "Sequence" &&
544 sequencesToReturn_(sequencesToReturn), 553 sequencesToReturn_(sequencesToReturn),
545 query_(filteredInput) 554 query_(filteredInput)
546 { 555 {
547 answers_.SetComplete(false); 556 answers_.SetComplete(false);
548 } 557 }
558
559 virtual bool IsDicomAsJsonNeeded() const
560 {
561 #if 1
562 return true;
563
564 #else
565 // TODO
566
567 // Ask the "DICOM-as-JSON" attachment only if sequences are to
568 // be returned OR if "query_" contains non-main DICOM tags!
569
570 // TODO - configuration option
571 bool findFromDatabase;
572
573 {
574 // New configuration option in 1.5.1
575 OrthancConfiguration::ReaderLock lock;
576 findFromDatabase = lock.GetConfiguration().GetUnsignedIntegerParameter("FindFromDatabase", false);
577 }
578
579 return !sequencesToReturn_.empty();
580 #endif
581 }
549 582
550 virtual void MarkAsComplete() 583 virtual void MarkAsComplete()
551 { 584 {
552 answers_.SetComplete(true); 585 answers_.SetComplete(true);
553 } 586 }
554 587
555 virtual void Visit(const std::string& publicId, 588 virtual void Visit(const std::string& publicId,
556 const std::string& instanceId, 589 const std::string& instanceId,
557 const Json::Value& dicom) 590 const DicomMap& mainDicomTags,
591 const Json::Value* dicomAsJson)
558 { 592 {
559 std::auto_ptr<DicomMap> counters(ComputeCounters(context_, instanceId, level_, filteredInput_)); 593 std::auto_ptr<DicomMap> counters(ComputeCounters(context_, instanceId, level_, filteredInput_));
560 AddAnswer(answers_, dicom, query_, sequencesToReturn_, counters.get()); 594 AddAnswer(answers_, mainDicomTags, dicomAsJson, query_, sequencesToReturn_, counters.get());
561 } 595 }
562 }; 596 };
563 597
564 598
565 void OrthancFindRequestHandler::Handle(DicomFindAnswers& answers, 599 void OrthancFindRequestHandler::Handle(DicomFindAnswers& answers,
688 * Run the query. 722 * Run the query.
689 **/ 723 **/
690 724
691 size_t limit = (level == ResourceType_Instance) ? maxInstances_ : maxResults_; 725 size_t limit = (level == ResourceType_Instance) ? maxInstances_ : maxResults_;
692 726
727
693 LookupVisitor visitor(answers, context_, level, *filteredInput, sequencesToReturn); 728 LookupVisitor visitor(answers, context_, level, *filteredInput, sequencesToReturn);
694 context_.Apply(visitor, lookup, 0 /* "since" is not relevant to C-FIND */, limit); 729 context_.Apply(visitor, lookup, 0 /* "since" is not relevant to C-FIND */, limit);
695 } 730 }
696 731
697 732