diff OrthancServer/ServerContext.cpp @ 3015:abe49ca61cd5

On C-FIND, avoid accessing the storage area whenever possible
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 14 Dec 2018 12:10:03 +0100
parents af1530b45290
children 2cbafb5d5a62
line wrap: on
line diff
--- a/OrthancServer/ServerContext.cpp	Thu Dec 13 17:58:27 2018 +0100
+++ b/OrthancServer/ServerContext.cpp	Fri Dec 14 12:10:03 2018 +0100
@@ -778,6 +778,35 @@
                             size_t since,
                             size_t limit)
   {
+    LookupMode mode;
+      
+    {
+      // New configuration option in 1.5.1
+      OrthancConfiguration::ReaderLock lock;
+
+      std::string value = lock.GetConfiguration().GetStringParameter("StorageAccessOnFind", "Always");
+
+      if (value == "Always")
+      {
+        mode = LookupMode_DiskOnLookupAndAnswer;
+      }
+      else if (value == "Never")
+      {
+        mode = LookupMode_DatabaseOnly;
+      }
+      else if (value == "Answers")
+      {
+        mode = LookupMode_DiskOnAnswer;
+      }
+      else
+      {
+        throw OrthancException(ErrorCode_ParameterOutOfRange,
+                               "Configuration option \"StorageAccessOnFind\" "
+                               "should be \"Always\", \"Never\" or \"Answers\": " + value);
+      }
+    }      
+
+
     std::vector<std::string> resources, instances;
     GetIndex().FindCandidates(resources, instances, lookup);
 
@@ -788,6 +817,8 @@
     size_t countResults = 0;
     size_t skipped = 0;
     bool complete = true;
+
+    const bool isDicomAsJsonNeeded = visitor.IsDicomAsJsonNeeded();
     
     for (size_t i = 0; i < instances.size(); i++)
     {
@@ -799,11 +830,20 @@
       bool hasOnlyMainDicomTags;
       DicomMap dicom;
       
-      if (lookup.HasOnlyMainDicomTags() &&
-          GetIndex().GetAllMainDicomTags(dicom, instances[i]))
+      if (mode == LookupMode_DatabaseOnly ||
+          mode == LookupMode_DiskOnAnswer ||
+          lookup.HasOnlyMainDicomTags())
       {
         // Case (1): The main DICOM tags, as stored in the database,
         // are sufficient to look for match
+
+        if (!GetIndex().GetAllMainDicomTags(dicom, instances[i]))
+        {
+          // The instance has been removed during the execution of the
+          // lookup, ignore it
+          continue;
+        }
+        
         hasOnlyMainDicomTags = true;
       }
       else
@@ -834,8 +874,10 @@
         }
         else
         {
-          if (dicomAsJson.get() == NULL &&
-              visitor.IsDicomAsJsonNeeded())
+          if ((mode == LookupMode_DiskOnLookupAndAnswer ||
+               mode == LookupMode_DiskOnAnswer) &&
+              dicomAsJson.get() == NULL &&
+              isDicomAsJsonNeeded)
           {
             dicomAsJson.reset(new Json::Value);
             ReadDicomAsJson(*dicomAsJson, instances[i]);
@@ -870,6 +912,77 @@
   }
 
 
+  bool ServerContext::LookupOrReconstructMetadata(std::string& target,
+                                                  const std::string& publicId,
+                                                  MetadataType metadata)
+  {
+    // This is a backwards-compatibility function, that can
+    // reconstruct metadata that were not generated by an older
+    // release of Orthanc
+
+    if (metadata == MetadataType_Instance_SopClassUid ||
+        metadata == MetadataType_Instance_TransferSyntax)
+    {
+      if (index_.LookupMetadata(target, publicId, metadata))
+      {
+        return true;
+      }
+      else
+      {
+        // These metadata are mandatory in DICOM instances, and were
+        // introduced in Orthanc 1.2.0. The fact that
+        // "LookupMetadata()" has failed indicates that this database
+        // comes from an older release of Orthanc.
+        
+        DicomTag tag(0, 0);
+      
+        switch (metadata)
+        {
+          case MetadataType_Instance_SopClassUid:
+            tag = DICOM_TAG_SOP_CLASS_UID;
+            break;
+
+          case MetadataType_Instance_TransferSyntax:
+            tag = DICOM_TAG_TRANSFER_SYNTAX_UID;
+            break;
+
+          default:
+            throw OrthancException(ErrorCode_InternalError);
+        }
+      
+        Json::Value dicomAsJson;
+        ReadDicomAsJson(dicomAsJson, publicId);
+
+        DicomMap tags;
+        tags.FromDicomAsJson(dicomAsJson);
+
+        const DicomValue* value = tags.TestAndGetValue(tag);
+
+        if (value != NULL &&
+            !value->IsNull() &&
+            !value->IsBinary())
+        {
+          target = value->GetContent();
+
+          // Store for reuse
+          index_.SetMetadata(publicId, metadata, target);
+          return true;
+        }
+        else
+        {
+          // Should never happen
+          return false;
+        }
+      }
+    }
+    else
+    {
+      // No backward
+      return index_.LookupMetadata(target, publicId, metadata);
+    }
+  }
+
+
   void ServerContext::AddChildInstances(SetOfInstancesJob& job,
                                         const std::string& publicId)
   {