changeset 4628:5fabef29c4ff db-changes

added new primitive "hasRevisionsSupport" in database SDK, added "CheckRevisions" to URI "/system"
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 20 Apr 2021 15:59:31 +0200
parents f7d5372b59b3
children 88e892e25a51
files NEWS OrthancFramework/Resources/CMake/OrthancFrameworkParameters.cmake OrthancServer/Plugins/Engine/OrthancPluginDatabase.h OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.h OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Plugins/Include/orthanc/OrthancCDatabasePlugin.h OrthancServer/Sources/Database/IDatabaseWrapper.h OrthancServer/Sources/Database/SQLiteDatabaseWrapper.h OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp OrthancServer/Sources/main.cpp
diffstat 11 files changed, 92 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Tue Apr 20 15:11:59 2021 +0200
+++ b/NEWS	Tue Apr 20 15:59:31 2021 +0200
@@ -12,6 +12,7 @@
 --------
 
 * API version upgraded to 12
+* "/system" reports the value of the "CheckRevisions" global option
 * "/.../{id}/metadata/{name}" and "/.../{id}/attachments/{name}/..." URIs handle the
   HTTP headers "If-Match", "If-None-Match" and "ETag" to cope with revisions
 
--- a/OrthancFramework/Resources/CMake/OrthancFrameworkParameters.cmake	Tue Apr 20 15:11:59 2021 +0200
+++ b/OrthancFramework/Resources/CMake/OrthancFrameworkParameters.cmake	Tue Apr 20 15:59:31 2021 +0200
@@ -37,7 +37,7 @@
 # Version of the Orthanc API, can be retrieved from "/system" URI in
 # order to check whether new URI endpoints are available even if using
 # the mainline version of Orthanc
-set(ORTHANC_API_VERSION "11")
+set(ORTHANC_API_VERSION "12")
 
 
 #####################################################################
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabase.h	Tue Apr 20 15:11:59 2021 +0200
+++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabase.h	Tue Apr 20 15:59:31 2021 +0200
@@ -119,6 +119,11 @@
     virtual void Upgrade(unsigned int targetVersion,
                          IStorageArea& storageArea) ORTHANC_OVERRIDE;    
 
+    virtual bool HasRevisionsSupport() const ORTHANC_OVERRIDE
+    {
+      return false;  // No support for revisions in old API
+    }
+
     void AnswerReceived(const _OrthancPluginDatabaseAnswer& answer);
   };
 }
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp	Tue Apr 20 15:11:59 2021 +0200
+++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp	Tue Apr 20 15:59:31 2021 +0200
@@ -1047,7 +1047,7 @@
   };
 
   
-  void OrthancPluginDatabaseV3::CheckSuccess(OrthancPluginErrorCode code)
+  void OrthancPluginDatabaseV3::CheckSuccess(OrthancPluginErrorCode code) const
   {
     if (code != OrthancPluginErrorCode_Success)
     {
@@ -1104,6 +1104,7 @@
     CHECK_FUNCTION_EXISTS(backend_, upgradeDatabase);
     CHECK_FUNCTION_EXISTS(backend_, startTransaction);
     CHECK_FUNCTION_EXISTS(backend_, destructTransaction);
+    CHECK_FUNCTION_EXISTS(backend_, hasRevisionsSupport);
 
     CHECK_FUNCTION_EXISTS(backend_, rollback);
     CHECK_FUNCTION_EXISTS(backend_, commit);
@@ -1231,4 +1232,13 @@
       }
     }
   }
+
+  
+  bool OrthancPluginDatabaseV3::HasRevisionsSupport() const
+  {
+    // WARNING: This method requires "Open()" to have been called
+    uint8_t hasRevisions;
+    CheckSuccess(backend_.hasRevisionsSupport(database_, &hasRevisions));
+    return (hasRevisions != 0);
+  }
 }
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.h	Tue Apr 20 15:11:59 2021 +0200
+++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.h	Tue Apr 20 15:59:31 2021 +0200
@@ -53,7 +53,7 @@
     void*                           database_;
     std::string                     serverIdentifier_;
 
-    void CheckSuccess(OrthancPluginErrorCode code);
+    void CheckSuccess(OrthancPluginErrorCode code) const;
 
   public:
     OrthancPluginDatabaseV3(SharedLibrary& library,
@@ -91,6 +91,8 @@
 
     virtual void Upgrade(unsigned int targetVersion,
                          IStorageArea& storageArea) ORTHANC_OVERRIDE;    
+
+    virtual bool HasRevisionsSupport() const ORTHANC_OVERRIDE;
   };
 }
 
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Tue Apr 20 15:11:59 2021 +0200
+++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp	Tue Apr 20 15:59:31 2021 +0200
@@ -5033,6 +5033,7 @@
       case _OrthancPluginService_RegisterDatabaseBackend:
       {
         LOG(WARNING) << "Performance warning: Plugin has registered a custom database back-end with an old API";
+        LOG(WARNING) << "The database backend has *no* support for revisions of metadata and attachments";
 
         const _OrthancPluginRegisterDatabaseBackend& p =
           *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackend*>(parameters);
@@ -5056,6 +5057,7 @@
       case _OrthancPluginService_RegisterDatabaseBackendV2:
       {
         LOG(WARNING) << "Performance warning: Plugin has registered a custom database back-end with an old API";
+        LOG(WARNING) << "The database backend has *no* support for revisions of metadata and attachments";
 
         const _OrthancPluginRegisterDatabaseBackendV2& p =
           *reinterpret_cast<const _OrthancPluginRegisterDatabaseBackendV2*>(parameters);
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCDatabasePlugin.h	Tue Apr 20 15:11:59 2021 +0200
+++ b/OrthancServer/Plugins/Include/orthanc/OrthancCDatabasePlugin.h	Tue Apr 20 15:59:31 2021 +0200
@@ -1089,6 +1089,9 @@
     OrthancPluginErrorCode (*getDatabaseVersion) (void* database,
                                                   uint32_t* target /* out */);
 
+    OrthancPluginErrorCode (*hasRevisionsSupport) (void* database,
+                                                   uint8_t* target /* out */);
+
     OrthancPluginErrorCode (*upgradeDatabase) (void* database,
                                                OrthancPluginStorageArea* storageArea,
                                                uint32_t targetVersion);
--- a/OrthancServer/Sources/Database/IDatabaseWrapper.h	Tue Apr 20 15:11:59 2021 +0200
+++ b/OrthancServer/Sources/Database/IDatabaseWrapper.h	Tue Apr 20 15:59:31 2021 +0200
@@ -268,5 +268,7 @@
 
     virtual void Upgrade(unsigned int targetVersion,
                          IStorageArea& storageArea) = 0;
+
+    virtual bool HasRevisionsSupport() const = 0;
   };
 }
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.h	Tue Apr 20 15:11:59 2021 +0200
+++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.h	Tue Apr 20 15:59:31 2021 +0200
@@ -103,6 +103,10 @@
     virtual void Upgrade(unsigned int targetVersion,
                          IStorageArea& storageArea) ORTHANC_OVERRIDE;
 
+    virtual bool HasRevisionsSupport() const ORTHANC_OVERRIDE
+    {
+      return false;  // TODO - REVISIONS
+    }
 
 
     /**
--- a/OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp	Tue Apr 20 15:11:59 2021 +0200
+++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp	Tue Apr 20 15:59:31 2021 +0200
@@ -61,29 +61,44 @@
  
   static void GetSystemInformation(RestApiGetCall& call)
   {
+    static const char* const API_VERSION = "ApiVersion";
+    static const char* const CHECK_REVISIONS = "CheckRevisions";
+    static const char* const DATABASE_BACKEND_PLUGIN = "DatabaseBackendPlugin";
+    static const char* const DATABASE_VERSION = "DatabaseVersion";
+    static const char* const DICOM_AET = "DicomAet";
+    static const char* const DICOM_PORT = "DicomPort";
+    static const char* const HTTP_PORT = "HttpPort";
+    static const char* const IS_HTTP_SERVER_SECURE = "IsHttpServerSecure";
+    static const char* const NAME = "Name";
+    static const char* const PLUGINS_ENABLED = "PluginsEnabled";
+    static const char* const STORAGE_AREA_PLUGIN = "StorageAreaPlugin";
+    static const char* const VERSION = "Version";
+    
     if (call.IsDocumentation())
     {
       call.GetDocumentation()
         .SetTag("System")
         .SetSummary("Get system information")
         .SetDescription("Get system information about Orthanc")
-        .SetAnswerField("ApiVersion", RestApiCallDocumentation::Type_Number, "Version of the REST API")
-        .SetAnswerField("Version", RestApiCallDocumentation::Type_String, "Version of Orthanc")
-        .SetAnswerField("DatabaseVersion", RestApiCallDocumentation::Type_Number,
+        .SetAnswerField(API_VERSION, RestApiCallDocumentation::Type_Number, "Version of the REST API")
+        .SetAnswerField(VERSION, RestApiCallDocumentation::Type_String, "Version of Orthanc")
+        .SetAnswerField(DATABASE_VERSION, RestApiCallDocumentation::Type_Number,
                         "Version of the database: https://book.orthanc-server.com/developers/db-versioning.html")
-        .SetAnswerField("IsHttpServerSecure", RestApiCallDocumentation::Type_Boolean,
+        .SetAnswerField(IS_HTTP_SERVER_SECURE, RestApiCallDocumentation::Type_Boolean,
                         "Whether the REST API is properly secured (assuming no reverse proxy is in use): https://book.orthanc-server.com/faq/security.html#securing-the-http-server")
-        .SetAnswerField("StorageAreaPlugin", RestApiCallDocumentation::Type_String,
+        .SetAnswerField(STORAGE_AREA_PLUGIN, RestApiCallDocumentation::Type_String,
                         "Information about the installed storage area plugin (`null` if no such plugin is installed)")
-        .SetAnswerField("DatabaseBackendPlugin", RestApiCallDocumentation::Type_String,
+        .SetAnswerField(DATABASE_BACKEND_PLUGIN, RestApiCallDocumentation::Type_String,
                         "Information about the installed database index plugin (`null` if no such plugin is installed)")
-        .SetAnswerField("DicomAet", RestApiCallDocumentation::Type_String, "The DICOM AET of Orthanc")
-        .SetAnswerField("DicomPort", RestApiCallDocumentation::Type_Number, "The port to the DICOM server of Orthanc")
-        .SetAnswerField("HttpPort", RestApiCallDocumentation::Type_Number, "The port to the HTTP server of Orthanc")
-        .SetAnswerField("Name", RestApiCallDocumentation::Type_String,
+        .SetAnswerField(DICOM_AET, RestApiCallDocumentation::Type_String, "The DICOM AET of Orthanc")
+        .SetAnswerField(DICOM_PORT, RestApiCallDocumentation::Type_Number, "The port to the DICOM server of Orthanc")
+        .SetAnswerField(HTTP_PORT, RestApiCallDocumentation::Type_Number, "The port to the HTTP server of Orthanc")
+        .SetAnswerField(NAME, RestApiCallDocumentation::Type_String,
                         "The name of the Orthanc server, cf. the `Name` configuration option")
-        .SetAnswerField("PluginsEnabled", RestApiCallDocumentation::Type_Boolean,
+        .SetAnswerField(PLUGINS_ENABLED, RestApiCallDocumentation::Type_Boolean,
                         "Whether Orthanc was built with support for plugins")
+        .SetAnswerField(CHECK_REVISIONS, RestApiCallDocumentation::Type_Boolean,
+                        "Whether Orthanc handle revisions of metadata and attachments to deal with multiple writers (new in Orthanc 1.9.2)")
         .SetHttpGetSample("https://demo.orthanc-server.com/system", true);
       return;
     }
@@ -92,39 +107,40 @@
 
     Json::Value result = Json::objectValue;
 
-    result["ApiVersion"] = ORTHANC_API_VERSION;
-    result["Version"] = ORTHANC_VERSION;
-    result["DatabaseVersion"] = OrthancRestApi::GetIndex(call).GetDatabaseVersion();
-    result["IsHttpServerSecure"] = context.IsHttpServerSecure();  // New in Orthanc 1.5.8
+    result[API_VERSION] = ORTHANC_API_VERSION;
+    result[VERSION] = ORTHANC_VERSION;
+    result[DATABASE_VERSION] = OrthancRestApi::GetIndex(call).GetDatabaseVersion();
+    result[IS_HTTP_SERVER_SECURE] = context.IsHttpServerSecure();  // New in Orthanc 1.5.8
 
     {
       OrthancConfiguration::ReaderLock lock;
-      result["DicomAet"] = lock.GetConfiguration().GetOrthancAET();
-      result["DicomPort"] = lock.GetConfiguration().GetUnsignedIntegerParameter("DicomPort", 4242);
-      result["HttpPort"] = lock.GetConfiguration().GetUnsignedIntegerParameter("HttpPort", 8042);
-      result["Name"] = lock.GetConfiguration().GetStringParameter("Name", "");
+      result[DICOM_AET] = lock.GetConfiguration().GetOrthancAET();
+      result[DICOM_PORT] = lock.GetConfiguration().GetUnsignedIntegerParameter(DICOM_PORT, 4242);
+      result[HTTP_PORT] = lock.GetConfiguration().GetUnsignedIntegerParameter(HTTP_PORT, 8042);
+      result[NAME] = lock.GetConfiguration().GetStringParameter(NAME, "");
+      result[CHECK_REVISIONS] = lock.GetConfiguration().GetBooleanParameter(CHECK_REVISIONS, false);  // New in Orthanc 1.9.2
     }
 
-    result["StorageAreaPlugin"] = Json::nullValue;
-    result["DatabaseBackendPlugin"] = Json::nullValue;
+    result[STORAGE_AREA_PLUGIN] = Json::nullValue;
+    result[DATABASE_BACKEND_PLUGIN] = Json::nullValue;
 
 #if ORTHANC_ENABLE_PLUGINS == 1
-    result["PluginsEnabled"] = true;
+    result[PLUGINS_ENABLED] = true;
     const OrthancPlugins& plugins = context.GetPlugins();
 
     if (plugins.HasStorageArea())
     {
       std::string p = plugins.GetStorageAreaLibrary().GetPath();
-      result["StorageAreaPlugin"] = boost::filesystem::canonical(p).string();
+      result[STORAGE_AREA_PLUGIN] = boost::filesystem::canonical(p).string();
     }
 
     if (plugins.HasDatabaseBackend())
     {
       std::string p = plugins.GetDatabaseBackendLibrary().GetPath();
-      result["DatabaseBackendPlugin"] = boost::filesystem::canonical(p).string();     
+      result[DATABASE_BACKEND_PLUGIN] = boost::filesystem::canonical(p).string();     
     }
 #else
-    result["PluginsEnabled"] = false;
+    result[PLUGINS_ENABLED] = false;
 #endif
 
     call.GetOutput().AnswerJson(result);
--- a/OrthancServer/Sources/main.cpp	Tue Apr 20 15:11:59 2021 +0200
+++ b/OrthancServer/Sources/main.cpp	Tue Apr 20 15:59:31 2021 +0200
@@ -1489,6 +1489,25 @@
                            ": Please run Orthanc with the \"--upgrade\" argument");
   }
 
+  {
+    static const char* const CHECK_REVISIONS = "CheckRevisions";
+    
+    OrthancConfiguration::ReaderLock lock;
+    if (lock.GetConfiguration().GetBooleanParameter(CHECK_REVISIONS, false))
+    {
+      if (database.HasRevisionsSupport())
+      {
+        LOG(INFO) << "Handling of revisions is enabled, and the custom database back-end *has* "
+                  << "support for revisions of metadata and attachments";
+      }
+      else
+      {
+        LOG(WARNING) << "The custom database back-end has *no* support for revisions of metadata and attachments, "
+                     << "but configuration option \"" << CHECK_REVISIONS << "\" is set to \"true\"";
+      }
+    }
+  }
+
   bool success = ConfigureServerContext
     (database, storageArea, plugins, loadJobsFromDatabase);