# HG changeset patch # User Sebastien Jodogne # Date 1618927171 -7200 # Node ID 5fabef29c4ff7ed2e7135d3b46121d9b6ca0fa2e # Parent f7d5372b59b3ac822744f638e5cbe3ee83df4f1f added new primitive "hasRevisionsSupport" in database SDK, added "CheckRevisions" to URI "/system" diff -r f7d5372b59b3 -r 5fabef29c4ff NEWS --- 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 diff -r f7d5372b59b3 -r 5fabef29c4ff OrthancFramework/Resources/CMake/OrthancFrameworkParameters.cmake --- 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") ##################################################################### diff -r f7d5372b59b3 -r 5fabef29c4ff OrthancServer/Plugins/Engine/OrthancPluginDatabase.h --- 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); }; } diff -r f7d5372b59b3 -r 5fabef29c4ff OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.cpp --- 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); + } } diff -r f7d5372b59b3 -r 5fabef29c4ff OrthancServer/Plugins/Engine/OrthancPluginDatabaseV3.h --- 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; }; } diff -r f7d5372b59b3 -r 5fabef29c4ff OrthancServer/Plugins/Engine/OrthancPlugins.cpp --- 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(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(parameters); diff -r f7d5372b59b3 -r 5fabef29c4ff OrthancServer/Plugins/Include/orthanc/OrthancCDatabasePlugin.h --- 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); diff -r f7d5372b59b3 -r 5fabef29c4ff OrthancServer/Sources/Database/IDatabaseWrapper.h --- 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; }; } diff -r f7d5372b59b3 -r 5fabef29c4ff OrthancServer/Sources/Database/SQLiteDatabaseWrapper.h --- 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 + } /** diff -r f7d5372b59b3 -r 5fabef29c4ff OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp --- 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); diff -r f7d5372b59b3 -r 5fabef29c4ff OrthancServer/Sources/main.cpp --- 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);