changeset 5856:d1dea8ad74a6 find-refactoring

implement StorageAccessOnFind for answers
author Alain Mazy <am@orthanc.team>
date Mon, 04 Nov 2024 21:51:24 +0100
parents aeb9f63923b1
children 39996519afce
files NEWS OrthancServer/Resources/Configuration.json OrthancServer/Sources/OrthancConfiguration.cpp OrthancServer/Sources/OrthancFindRequestHandler.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp OrthancServer/Sources/OrthancWebDav.cpp OrthancServer/Sources/ResourceFinder.cpp OrthancServer/Sources/ResourceFinder.h OrthancServer/Sources/ServerEnumerations.h
diffstat 9 files changed, 75 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon Nov 04 20:00:42 2024 +0100
+++ b/NEWS	Mon Nov 04 21:51:24 2024 +0100
@@ -74,6 +74,7 @@
   - W004_NoMainDicomTagsSignature
   - W005_RequestingTagFromLowerResourceLevel
   - W006_RequestingTagFromMetaHeader
+  - W007_MissingRequestedTagsNotReadFromDisk
 * New default MainDicomTags are now stored in DB.  Note that, in order to store these values
   for resources that were ingested in Orthanc before this release, you would have to run
   the Housekeeper plugin or call /reconstruct on every resources
--- a/OrthancServer/Resources/Configuration.json	Mon Nov 04 20:00:42 2024 +0100
+++ b/OrthancServer/Resources/Configuration.json	Mon Nov 04 21:51:24 2024 +0100
@@ -1009,7 +1009,12 @@
     // Display a warning when a user performs a find request and requests a tag
     // from the DICOM Meta Header.
     // (new in Orthanc 1.12.5)
-    "W006_RequestingTagFromMetaHeader": true
+    "W006_RequestingTagFromMetaHeader": true,
+
+    // Display a warning when a user requests a tag that can not be read from disk
+    // because "StorageAccessOnFind" is set to "Never".
+    // (new in Orthanc 1.12.5)
+    "W007_MissingRequestedTagsNotReadFromDisk": true
   },
 
   // Configure Orthanc in read only mode.
--- a/OrthancServer/Sources/OrthancConfiguration.cpp	Mon Nov 04 20:00:42 2024 +0100
+++ b/OrthancServer/Sources/OrthancConfiguration.cpp	Mon Nov 04 21:51:24 2024 +0100
@@ -1173,6 +1173,10 @@
         {
           warning = Warnings_006_RequestingTagFromMetaHeader;
         }
+        else if (name == "W007_MissingRequestedTagsNotReadFromDisk")
+        {
+          warning = Warnings_007_MissingRequestedTagsNotReadFromDisk;
+        }
         else
         {
           throw OrthancException(ErrorCode_BadFileFormat, name + " is not recognized as a valid warning name");
--- a/OrthancServer/Sources/OrthancFindRequestHandler.cpp	Mon Nov 04 20:00:42 2024 +0100
+++ b/OrthancServer/Sources/OrthancFindRequestHandler.cpp	Mon Nov 04 21:51:24 2024 +0100
@@ -444,7 +444,7 @@
      * Run the query.
      **/
 
-    ResourceFinder finder(level, ResponseContentFlags_ID);
+    ResourceFinder finder(level, ResponseContentFlags_ID, context_.GetFindStorageAccessMode());
     finder.SetDatabaseLookup(lookup);
     finder.AddRequestedTags(requestedTags);
 
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp	Mon Nov 04 20:00:42 2024 +0100
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp	Mon Nov 04 21:51:24 2024 +0100
@@ -152,7 +152,7 @@
       responseContent = static_cast<ResponseContentFlags>(static_cast<uint32_t>(responseContent) | ResponseContentFlags_Metadata);
     }
 
-    ResourceFinder finder(level, responseContent);
+    ResourceFinder finder(level, responseContent, context.GetFindStorageAccessMode());
     finder.SetOrthancId(level, identifier);
     finder.SetRetrieveMetadata(retrieveMetadata);
 
@@ -193,7 +193,7 @@
     std::set<DicomTag> requestedTags;
     OrthancRestApi::GetRequestedTags(requestedTags, call);
 
-    ResourceFinder finder(resourceType, (expand ? ResponseContentFlags_ExpandTrue : ResponseContentFlags_ID));
+    ResourceFinder finder(resourceType, (expand ? ResponseContentFlags_ExpandTrue : ResponseContentFlags_ID), OrthancRestApi::GetContext(call).GetFindStorageAccessMode());
     finder.AddRequestedTags(requestedTags);
 
     if (call.HasArgument("limit") ||
@@ -251,7 +251,7 @@
 
     const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human);
 
-    ResourceFinder finder(resourceType, ResponseContentFlags_ExpandTrue);
+    ResourceFinder finder(resourceType, ResponseContentFlags_ExpandTrue, OrthancRestApi::GetContext(call).GetFindStorageAccessMode());
     finder.AddRequestedTags(requestedTags);
     finder.SetOrthancId(resourceType, call.GetUriComponent("id", ""));
 
@@ -3250,7 +3250,7 @@
 
       const ResourceType level = StringToResourceType(request[KEY_LEVEL].asCString());
 
-      ResourceFinder finder(level, responseContent);
+      ResourceFinder finder(level, responseContent, context.GetFindStorageAccessMode());
 
       DatabaseLookup dicomTagLookup;
 
@@ -3542,7 +3542,7 @@
     std::set<DicomTag> requestedTags;
     OrthancRestApi::GetRequestedTags(requestedTags, call);
 
-    ResourceFinder finder(end, (expand ? ResponseContentFlags_ExpandTrue : ResponseContentFlags_ID));
+    ResourceFinder finder(end, (expand ? ResponseContentFlags_ExpandTrue : ResponseContentFlags_ID), OrthancRestApi::GetContext(call).GetFindStorageAccessMode());
     finder.SetOrthancId(start, call.GetUriComponent("id", ""));
     finder.AddRequestedTags(requestedTags);
 
--- a/OrthancServer/Sources/OrthancWebDav.cpp	Mon Nov 04 20:00:42 2024 +0100
+++ b/OrthancServer/Sources/OrthancWebDav.cpp	Mon Nov 04 21:51:24 2024 +0100
@@ -937,7 +937,7 @@
 
       Visitor visitor(resources);
 
-      ResourceFinder finder(ResourceType_Study, ResponseContentFlags_ID);
+      ResourceFinder finder(ResourceType_Study, ResponseContentFlags_ID, GetContext().GetFindStorageAccessMode());
       finder.SetDatabaseLookup(query);
       finder.Execute(visitor, GetContext());
     }
@@ -1015,7 +1015,7 @@
 
       Visitor visitor;
 
-      ResourceFinder finder(ResourceType_Study, ResponseContentFlags_ID);
+      ResourceFinder finder(ResourceType_Study, ResponseContentFlags_ID, context_.GetFindStorageAccessMode());
       finder.SetDatabaseLookup(query);
       finder.Execute(visitor, context_);
 
@@ -1393,7 +1393,7 @@
         return false;
       }
 
-      ResourceFinder finder(level, ResponseContentFlags_ID);
+      ResourceFinder finder(level, ResponseContentFlags_ID, context_.GetFindStorageAccessMode());
       finder.SetDatabaseLookup(query);
       finder.SetRetrieveMetadata(true);
 
@@ -1444,7 +1444,7 @@
                              ResourceType level,
                              const DatabaseLookup& query)
   {
-    ResourceFinder finder(level, ResponseContentFlags_ExpandTrue);
+    ResourceFinder finder(level, ResponseContentFlags_ExpandTrue, context.GetFindStorageAccessMode());
     finder.SetDatabaseLookup(query);
 
     Json::Value expanded;
@@ -1514,7 +1514,7 @@
       
         mime = MimeType_Dicom;
 
-        ResourceFinder finder(ResourceType_Instance, ResponseContentFlags_ID);
+        ResourceFinder finder(ResourceType_Instance, ResponseContentFlags_ID, context_.GetFindStorageAccessMode());
         finder.SetDatabaseLookup(query);
         finder.SetRetrieveMetadata(true);
         finder.SetRetrieveAttachments(true);
@@ -1644,7 +1644,7 @@
 
         DicomDeleteVisitor visitor(context_, level);
 
-        ResourceFinder finder(level, ResponseContentFlags_ID);
+        ResourceFinder finder(level, ResponseContentFlags_ID, context_.GetFindStorageAccessMode());
         finder.SetDatabaseLookup(query);
         finder.Execute(visitor, context_);
         return true;
--- a/OrthancServer/Sources/ResourceFinder.cpp	Mon Nov 04 20:00:42 2024 +0100
+++ b/OrthancServer/Sources/ResourceFinder.cpp	Mon Nov 04 21:51:24 2024 +0100
@@ -544,7 +544,8 @@
 
 
   ResourceFinder::ResourceFinder(ResourceType level,
-                                 ResponseContentFlags responseContent) :
+                                 ResponseContentFlags responseContent,
+                                 FindStorageAccessMode storageAccessMode) :
     request_(level),
     databaseLimits_(0),
     isSimpleLookup_(true),
@@ -554,7 +555,7 @@
     limitsSince_(0),
     limitsCount_(0),
     responseContent_(responseContent),
-    allowStorageAccess_(true),
+    storageAccessMode_(storageAccessMode),
     isWarning002Enabled_(false),
     isWarning004Enabled_(false),
     isWarning005Enabled_(false)
@@ -1023,12 +1024,14 @@
     bool isWarning002Enabled = false;
     bool isWarning004Enabled = false;
     bool isWarning006Enabled = false;
+    bool isWarning007Enabled = false;
 
     {
       OrthancConfiguration::ReaderLock lock;
       isWarning002Enabled = lock.GetConfiguration().IsWarningEnabled(Warnings_002_InconsistentDicomTagsInDb);
       isWarning004Enabled = lock.GetConfiguration().IsWarningEnabled(Warnings_004_NoMainDicomTagsSignature);
       isWarning006Enabled = lock.GetConfiguration().IsWarningEnabled(Warnings_006_RequestingTagFromMetaHeader);
+      isWarning007Enabled = lock.GetConfiguration().IsWarningEnabled(Warnings_007_MissingRequestedTagsNotReadFromDisk);
     }
 
     FindResponse response;
@@ -1111,15 +1114,16 @@
         if (!remainingRequestedTags.empty() && 
             !DicomMap::HasOnlyComputedTags(remainingRequestedTags)) // if the only remaining tags are computed tags, it is worthless to read them from disk
         {
-          if (!allowStorageAccess_)
-          {
-            throw OrthancException(ErrorCode_BadSequenceOfCalls,
-                                   "Cannot add missing requested tags, as access to file storage is disallowed");
-          }
-          else
+          if (IsStorageAccessAllowedOnAnswers())
           {
             ReadMissingTagsFromStorageArea(outRequestedTags, context, request_, resource, remainingRequestedTags);
           }
+          else if (isWarning007Enabled)
+          {
+            std::string joinedTags;
+            FromDcmtkBridge::FormatListOfTags(joinedTags, remainingRequestedTags);
+            LOG(WARNING) << "W007: Unable to include requested tags since 'StorageAccessOnFind' does not allow accessing the storage to build answers: " << joinedTags;
+          }
         }
 
         std::string mainDicomTagsSignature;
@@ -1191,6 +1195,34 @@
     }
   }
 
+  bool ResourceFinder::IsStorageAccessAllowedOnAnswers()
+  {
+    switch (storageAccessMode_)
+    {
+      case FindStorageAccessMode_DiskOnAnswer:
+      case FindStorageAccessMode_DiskOnLookupAndAnswer:
+        return true;
+      case FindStorageAccessMode_DatabaseOnly:
+        return false;
+      default:
+        throw OrthancException(ErrorCode_InternalError);
+    }
+  }
+
+
+  bool ResourceFinder::IsStorageAccessOnLookup()
+  {
+    switch (storageAccessMode_)
+    {
+      case FindStorageAccessMode_DiskOnAnswer:
+        return false;
+      case FindStorageAccessMode_DiskOnLookupAndAnswer:
+      case FindStorageAccessMode_DatabaseOnly:
+        return true;
+      default:
+        throw OrthancException(ErrorCode_InternalError);
+    }
+  }
 
   void ResourceFinder::Execute(Json::Value& target,
                                ServerContext& context,
--- a/OrthancServer/Sources/ResourceFinder.h	Mon Nov 04 20:00:42 2024 +0100
+++ b/OrthancServer/Sources/ResourceFinder.h	Mon Nov 04 21:51:24 2024 +0100
@@ -66,7 +66,7 @@
     uint64_t                         limitsSince_;
     uint64_t                         limitsCount_;
     ResponseContentFlags             responseContent_;
-    bool                             allowStorageAccess_;
+    FindStorageAccessMode            storageAccessMode_;
     std::set<DicomTag>               requestedTags_;
     std::set<DicomTag>               requestedComputedTags_;
 
@@ -101,22 +101,17 @@
       return requestedTags_.size() > 0;
     }
 
+    bool IsStorageAccessAllowedOnAnswers();
+
+    bool IsStorageAccessOnLookup();
+
   public:
     ResourceFinder(ResourceType level,
-                   ResponseContentFlags responseContent);
+                   ResponseContentFlags responseContent,
+                   FindStorageAccessMode storageAccessMode);
 
     void SetDatabaseLimits(uint64_t limits);
 
-    bool IsAllowStorageAccess() const
-    {
-      return allowStorageAccess_;
-    }
-
-    void SetAllowStorageAccess(bool allow)
-    {
-      allowStorageAccess_ = allow;
-    }
-
     void SetOrthancId(ResourceType level,
                       const std::string& id)
     {
--- a/OrthancServer/Sources/ServerEnumerations.h	Mon Nov 04 20:00:42 2024 +0100
+++ b/OrthancServer/Sources/ServerEnumerations.h	Mon Nov 04 21:51:24 2024 +0100
@@ -251,10 +251,11 @@
     Warnings_None,
     Warnings_001_TagsBeingReadFromStorage,
     Warnings_002_InconsistentDicomTagsInDb,
-    Warnings_003_DecoderFailure,              // new in Orthanc 1.12.5
-    Warnings_004_NoMainDicomTagsSignature,    // new in Orthanc 1.12.5
-    Warnings_005_RequestingTagFromLowerResourceLevel,    // new in Orthanc 1.12.5
-    Warnings_006_RequestingTagFromMetaHeader    // new in Orthanc 1.12.5
+    Warnings_003_DecoderFailure,                           // new in Orthanc 1.12.5
+    Warnings_004_NoMainDicomTagsSignature,                 // new in Orthanc 1.12.5
+    Warnings_005_RequestingTagFromLowerResourceLevel,      // new in Orthanc 1.12.5
+    Warnings_006_RequestingTagFromMetaHeader,              // new in Orthanc 1.12.5
+    Warnings_007_MissingRequestedTagsNotReadFromDisk       // new in Orthanc 1.12.5
   };