changeset 4517:c494ee5d0101

Added "Timeout" parameter everywhere in "/modalities/.../"
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 22 Feb 2021 15:27:25 +0100
parents 671ee7c1fd46
children cb8fcecf1b02
files NEWS OrthancFramework/Sources/DicomNetworking/DicomAssociation.cpp OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp OrthancServer/Sources/QueryRetrieveHandler.cpp OrthancServer/Sources/QueryRetrieveHandler.h
diffstat 5 files changed, 67 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Feb 16 15:01:13 2021 +0100
+++ b/NEWS	Mon Feb 22 15:27:25 2021 +0100
@@ -4,17 +4,22 @@
 General
 -------
 
-* BREAKING CHANGE: The "dicom-as-json" attachments are not explicitly stored anymore.
-  If the storage area doesn't support range reading, or if "StorageCompression"
-  is enabled, a new attachment "dicom-until-pixel-data" is generated.
+* The "dicom-as-json" attachments are not explicitly stored anymore to improve performance
+* If the storage area doesn't support range reading, or if "StorageCompression"
+  is enabled, a new type of attachment "dicom-until-pixel-data" is generated.
 * New metadata automatically computed at the instance level: "PixelDataOffset"
 
 REST API
 --------
 
-* BREAKING CHANGE: The "/instances/.../tags" route does not report the tags
-  after "Pixel Data" (7fe0,0010) anymore
-
+* BREAKING CHANGES:
+  - External applications should *not* call "/instances/.../attachments/dicom-as-json" anymore
+  - "/instances/.../tags" route does not report the tags after "Pixel Data" (7fe0,0010) anymore
+* New arguments in the REST API:
+  - "Timeout" in "/modalities/.../query"
+  - "Timeout" in "/modalities/.../storage-commitment"
+  - "Timeout" in "/queries/.../answers/.../query-{studies|series|instances}"
+  
 Plugins
 -------
 
--- a/OrthancFramework/Sources/DicomNetworking/DicomAssociation.cpp	Tue Feb 16 15:01:13 2021 +0100
+++ b/OrthancFramework/Sources/DicomNetworking/DicomAssociation.cpp	Mon Feb 22 15:27:25 2021 +0100
@@ -277,7 +277,10 @@
                       << "\" to AET \"" << parameters.GetRemoteModality().GetApplicationEntityTitle()
                       << "\" on host " << parameters.GetRemoteModality().GetHost()
                       << ":" << parameters.GetRemoteModality().GetPortNumber() 
-                      << " (manufacturer: " << EnumerationToString(parameters.GetRemoteModality().GetManufacturer()) << ")";
+                      << " (manufacturer: " << EnumerationToString(parameters.GetRemoteModality().GetManufacturer())
+                      << ", " << (parameters.HasTimeout() ?
+                                  "timeout: " + boost::lexical_cast<std::string>(parameters.GetTimeout()) + "s" :
+                                  "no timeout") << ")";
 
     CheckConnecting(parameters, ASC_initializeNetwork(NET_REQUESTOR, 0, /*opt_acse_timeout*/ acseTimeout, &net_));
     CheckConnecting(parameters, ASC_createAssociationParameters(&params_, parameters.GetMaximumPduLength()));
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp	Tue Feb 16 15:01:13 2021 +0100
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp	Mon Feb 22 15:27:25 2021 +0100
@@ -675,6 +675,8 @@
         .SetRequestField(KEY_LOCAL_AET, RestApiCallDocumentation::Type_String,
                          "Local AET that is used for this commands, defaults to `DicomAet` configuration option. "
                          "Ignored if `DicomModalities` already sets `LocalAet` for this modality.", false)
+        .SetRequestField(KEY_TIMEOUT, RestApiCallDocumentation::Type_Number,
+                         "Timeout for the C-FIND command and subsequent C-MOVE retrievals, in seconds (new in Orthanc 1.9.1)", false)
         .SetAnswerField("ID", RestApiCallDocumentation::Type_JsonObject,
                         "Identifier of the query, to be used with `/queries/{id}`")
         .SetAnswerField("Path", RestApiCallDocumentation::Type_JsonObject,
@@ -743,6 +745,12 @@
         handler->SetLocalAet(request[KEY_LOCAL_AET].asString());
       }
 
+      if (request.isMember(KEY_TIMEOUT))
+      {
+        // New in Orthanc 1.9.1
+        handler->SetTimeout(SerializationToolbox::ReadUnsignedInteger(request, KEY_TIMEOUT));
+      }
+
       AnswerQueryHandler(call, handler);
     }
   }
@@ -940,6 +948,11 @@
         // New in Orthanc 1.7.0
         job->SetTimeout(static_cast<uint32_t>(timeout));
       }
+      else if (query.GetHandler().HasTimeout())
+      {
+        // New in Orthanc 1.9.1
+        job->SetTimeout(query.GetHandler().GetTimeout());
+      }
 
       LOG(WARNING) << "Driving C-Move SCU on remote modality "
                    << query.GetHandler().GetRemoteModality().GetApplicationEntityTitle()
@@ -1179,6 +1192,8 @@
         .SetUriArgument("index", "Index of the answer")
         .SetRequestField(KEY_QUERY, RestApiCallDocumentation::Type_JsonObject,
                          "Associative array containing the filter on the values of the DICOM tags", true)
+        .SetRequestField(KEY_TIMEOUT, RestApiCallDocumentation::Type_Number,
+                         "Timeout for the C-FIND command, in seconds (new in Orthanc 1.9.1)", false)
         .SetAnswerField("ID", RestApiCallDocumentation::Type_JsonObject,
                         "Identifier of the query, to be used with `/queries/{id}`")
         .SetAnswerField("Path", RestApiCallDocumentation::Type_JsonObject,
@@ -1230,6 +1245,16 @@
         handler->SetModality(parent.GetHandler().GetModalitySymbolicName());
         handler->SetLevel(CHILDREN_LEVEL);
 
+        // New in Orthanc 1.9.1
+        if (request.isMember(KEY_TIMEOUT))
+        {
+          handler->SetTimeout(SerializationToolbox::ReadUnsignedInteger(request, KEY_TIMEOUT));
+        }
+        else if (parent.GetHandler().HasTimeout())
+        {
+          handler->SetTimeout(parent.GetHandler().GetTimeout());
+        }
+
         if (request.isMember(KEY_QUERY))
         {
           std::map<DicomTag, std::string> query;
@@ -2115,6 +2140,8 @@
                          "List of DICOM resources that are not necessarily stored within Orthanc, but that must "
                          "be checked by storage commitment. This is a list of JSON objects that must contain the "
                          "`SOPClassUID` and `SOPInstanceUID` fields.", true)
+        .SetRequestField(KEY_TIMEOUT, RestApiCallDocumentation::Type_Number,
+                         "Timeout for the storage commitment command (new in Orthanc 1.9.1)", false)
         .SetAnswerField("ID", RestApiCallDocumentation::Type_JsonObject,
                         "Identifier of the storage commitment report, to be used with `/storage-commitment/{id}`")
         .SetAnswerField("Path", RestApiCallDocumentation::Type_JsonObject,
@@ -2272,6 +2299,7 @@
           transactionUid, new StorageCommitmentReports::Report(remoteAet));
 
         DicomAssociationParameters parameters(localAet, remote);
+        InjectAssociationTimeout(parameters, json);
         
         std::vector<std::string> a(sopClassUids.begin(), sopClassUids.end());
         std::vector<std::string> b(sopInstanceUids.begin(), sopInstanceUids.end());
--- a/OrthancServer/Sources/QueryRetrieveHandler.cpp	Tue Feb 16 15:01:13 2021 +0100
+++ b/OrthancServer/Sources/QueryRetrieveHandler.cpp	Mon Feb 22 15:27:25 2021 +0100
@@ -83,6 +83,12 @@
 
       {
         DicomAssociationParameters params(localAet_, modality_);
+
+        if (timeout_ != 0)
+        {
+          params.SetTimeout(timeout_);
+        }
+        
         DicomControlUserConnection connection(params);
         connection.Find(answers_, level_, fixed, findNormalized_);
       }
@@ -98,7 +104,8 @@
     done_(false),
     level_(ResourceType_Study),
     answers_(false),
-    findNormalized_(true)
+    findNormalized_(true),
+    timeout_(0)
   {
   }
 
--- a/OrthancServer/Sources/QueryRetrieveHandler.h	Tue Feb 16 15:01:13 2021 +0100
+++ b/OrthancServer/Sources/QueryRetrieveHandler.h	Mon Feb 22 15:27:25 2021 +0100
@@ -52,6 +52,7 @@
     DicomFindAnswers           answers_;
     std::string                modalityName_;
     bool                       findNormalized_;
+    uint32_t                   timeout_;  // New in Orthanc 1.9.1
 
     void Invalidate();
 
@@ -108,5 +109,20 @@
     }
 
     void SetFindNormalized(bool normalized);
+
+    void SetTimeout(uint32_t seconds)
+    {
+      timeout_ = seconds;
+    }
+
+    uint32_t GetTimeout() const
+    {
+      return timeout_;
+    }
+
+    bool HasTimeout() const
+    {
+      return timeout_ != 0;
+    }
   };
 }