changeset 241:a063bbf10a3e

simplification of class DatabaseManager::Transaction
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 13 Apr 2021 12:07:30 +0200
parents c82c2cf84ae8
children b97a537f4613
files Framework/Common/DatabaseManager.cpp Framework/Common/DatabaseManager.h MySQL/Plugins/MySQLIndex.cpp PostgreSQL/Plugins/PostgreSQLIndex.cpp SQLite/Plugins/SQLiteIndex.cpp
diffstat 5 files changed, 63 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Common/DatabaseManager.cpp	Mon Apr 12 17:07:06 2021 +0200
+++ b/Framework/Common/DatabaseManager.cpp	Tue Apr 13 12:07:30 2021 +0200
@@ -241,7 +241,7 @@
                                             TransactionType type) :
     manager_(manager),
     database_(manager.GetDatabase()),
-    committed_(false)
+    active_(true)
   {
     manager_.StartTransaction(type);
   }
@@ -249,7 +249,7 @@
 
   DatabaseManager::Transaction::~Transaction()
   {
-    if (!committed_)
+    if (active_)
     {
       try
       {
@@ -266,14 +266,28 @@
   
   void DatabaseManager::Transaction::Commit()
   {
-    if (committed_)
+    if (active_)
+    {
+      manager_.CommitTransaction();
+      active_ = true;
+    }
+    else
     {
       throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
     }
+  }
+
+
+  void DatabaseManager::Transaction::Rollback()
+  {
+    if (active_)
+    {
+      manager_.RollbackTransaction();
+      active_ = true;
+    }
     else
     {
-      manager_.CommitTransaction();
-      committed_ = true;
+      throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
     }
   }
 
--- a/Framework/Common/DatabaseManager.h	Mon Apr 12 17:07:06 2021 +0200
+++ b/Framework/Common/DatabaseManager.h	Tue Apr 13 12:07:30 2021 +0200
@@ -88,13 +88,14 @@
     void RollbackTransaction();
 
 
-    // This class is only used in the "StorageBackend"
+    // This class is only used in the "StorageBackend" and in
+    // "IDatabaseBackend::ConfigureDatabase()"
     class Transaction : public boost::noncopyable
     {
     private:
       DatabaseManager&  manager_;
       IDatabase&        database_;
-      bool              committed_;
+      bool              active_;
 
     public:
       explicit Transaction(DatabaseManager& manager,
@@ -104,29 +105,16 @@
 
       void Commit();
 
-      DatabaseManager& GetManager()
-      {
-        return manager_;
-      }
+      void Rollback();
 
-      IDatabase& GetDatabase()
-      {
-        return database_;
-      }
-
-      bool DoesTableExist(const std::string& name)
+      /**
+       * WARNING: Don't call "GetDatabaseTransaction().Commit()" and
+       * "GetDatabaseTransaction().Rollback()", but use the "Commit()"
+       * and "Rollback()" methods above.
+       **/
+      ITransaction& GetDatabaseTransaction()
       {
-        return manager_.GetTransaction().DoesTableExist(name);
-      }
-
-      bool DoesTriggerExist(const std::string& name)
-      {
-        return manager_.GetTransaction().DoesTriggerExist(name);
-      }
-
-      void ExecuteMultiLines(const std::string& sql)
-      {
-        manager_.GetTransaction().ExecuteMultiLines(sql);
+        return manager_.GetTransaction();
       }
     };
 
--- a/MySQL/Plugins/MySQLIndex.cpp	Mon Apr 12 17:07:06 2021 +0200
+++ b/MySQL/Plugins/MySQLIndex.cpp	Tue Apr 13 12:07:30 2021 +0200
@@ -112,18 +112,18 @@
       {
         DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
         
-        t.ExecuteMultiLines("ALTER DATABASE " + parameters_.GetDatabase() + 
-                            " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
+        t.GetDatabaseTransaction().ExecuteMultiLines("ALTER DATABASE " + parameters_.GetDatabase() + 
+                                                     " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
 
         // This is the first table to be created
-        if (!t.DoesTableExist("GlobalProperties"))
+        if (!t.GetDatabaseTransaction().DoesTableExist("GlobalProperties"))
         {
           std::string query;
           
           Orthanc::EmbeddedResources::GetFileResource
             (query, Orthanc::EmbeddedResources::MYSQL_PREPARE_INDEX);
 
-          // Need to escape arobases: Don't use "t.ExecuteMultiLines()" here
+          // Need to escape arobases: Don't use "t.GetDatabaseTransaction().ExecuteMultiLines()" here
           db.ExecuteMultiLines(query, true);
         }
 
@@ -144,14 +144,14 @@
         DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
 
         // This is the last table to be created
-        if (!t.DoesTableExist("PatientRecyclingOrder"))
+        if (!t.GetDatabaseTransaction().DoesTableExist("PatientRecyclingOrder"))
         {
           LOG(ERROR) << "Corrupted MySQL database";
           throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);        
         }
 
         // This is the last item to be created
-        if (!t.DoesTriggerExist("PatientAdded"))
+        if (!t.GetDatabaseTransaction().DoesTriggerExist("PatientAdded"))
         {
           ThrowCannotCreateTrigger();
         }
@@ -194,7 +194,7 @@
         // very long values => switch to the LONGTEXT type that can
         // store up to 4GB:
         // https://stackoverflow.com/a/13932834/881731
-        t.ExecuteMultiLines("ALTER TABLE GlobalProperties MODIFY value LONGTEXT");
+        t.GetDatabaseTransaction().ExecuteMultiLines("ALTER TABLE GlobalProperties MODIFY value LONGTEXT");
         
         revision = 2;
         SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, revision);
@@ -212,10 +212,10 @@
         Orthanc::EmbeddedResources::GetFileResource
           (query, Orthanc::EmbeddedResources::MYSQL_GET_LAST_CHANGE_INDEX);
 
-        // Need to escape arobases: Don't use "t.ExecuteMultiLines()" here
+        // Need to escape arobases: Don't use "t.GetDatabaseTransaction().ExecuteMultiLines()" here
         db.ExecuteMultiLines(query, true);
 
-        if (!t.DoesTriggerExist("ChangeAdded"))
+        if (!t.GetDatabaseTransaction().DoesTriggerExist("ChangeAdded"))
         {
           ThrowCannotCreateTrigger();
         }
@@ -235,7 +235,7 @@
         // for applications such as the Osimis Web viewer that stores
         // large amount of metadata.
         // http://book.orthanc-server.com/faq/features.html#central-registry-of-metadata-and-attachments
-        t.ExecuteMultiLines("ALTER TABLE Metadata MODIFY value LONGTEXT");
+        t.GetDatabaseTransaction().ExecuteMultiLines("ALTER TABLE Metadata MODIFY value LONGTEXT");
         
         revision = 4;
         SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, revision);
@@ -253,7 +253,7 @@
         Orthanc::EmbeddedResources::GetFileResource
           (query, Orthanc::EmbeddedResources::MYSQL_CREATE_INSTANCE);
 
-        // Need to escape arobases: Don't use "t.ExecuteMultiLines()" here
+        // Need to escape arobases: Don't use "t.GetDatabaseTransaction().ExecuteMultiLines()" here
         db.ExecuteMultiLines(query, true);
         
         revision = 5;
@@ -273,10 +273,10 @@
         // New in release 4.0 to deal with multiple writers
         DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
 
-        if (!t.DoesTableExist("ServerProperties"))
+        if (!t.GetDatabaseTransaction().DoesTableExist("ServerProperties"))
         {
-          t.ExecuteMultiLines("CREATE TABLE ServerProperties(server VARCHAR(64) NOT NULL, "
-                              "property INTEGER, value TEXT, PRIMARY KEY(server, property))");
+          t.GetDatabaseTransaction().ExecuteMultiLines("CREATE TABLE ServerProperties(server VARCHAR(64) NOT NULL, "
+                                                       "property INTEGER, value TEXT, PRIMARY KEY(server, property))");
         }
 
         t.Commit();
--- a/PostgreSQL/Plugins/PostgreSQLIndex.cpp	Mon Apr 12 17:07:06 2021 +0200
+++ b/PostgreSQL/Plugins/PostgreSQLIndex.cpp	Tue Apr 13 12:07:30 2021 +0200
@@ -96,20 +96,20 @@
       {
         DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
 
-        if (!t.DoesTableExist("Resources"))
+        if (!t.GetDatabaseTransaction().DoesTableExist("Resources"))
         {
           std::string query;
 
           Orthanc::EmbeddedResources::GetFileResource
             (query, Orthanc::EmbeddedResources::POSTGRESQL_PREPARE_INDEX);
-          t.ExecuteMultiLines(query);
+          t.GetDatabaseTransaction().ExecuteMultiLines(query);
 
           SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseSchemaVersion, expectedVersion);
           SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, 1);
           SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasTrigramIndex, 0);
         }
           
-        if (!t.DoesTableExist("Resources"))
+        if (!t.GetDatabaseTransaction().DoesTableExist("Resources"))
         {
           LOG(ERROR) << "Corrupted PostgreSQL database";
           throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);        
@@ -163,7 +163,7 @@
             LOG(WARNING) << "Trying to enable trigram matching on the PostgreSQL database "
                          << "to speed up wildcard searches. This may take several minutes";
 
-            t.ExecuteMultiLines(
+            t.GetDatabaseTransaction().ExecuteMultiLines(
               "CREATE EXTENSION IF NOT EXISTS pg_trgm; "
               "CREATE INDEX DicomIdentifiersIndexValues2 ON DicomIdentifiers USING gin(value gin_trgm_ops);");
 
@@ -199,14 +199,14 @@
           if (property == 1)
           {
             // Drop older, experimental versions of this extension
-            t.ExecuteMultiLines("DROP FUNCTION CreateInstance("
-                                "IN patient TEXT, IN study TEXT, IN series TEXT, in instance TEXT)");
+            t.GetDatabaseTransaction().ExecuteMultiLines("DROP FUNCTION CreateInstance("
+                                                         "IN patient TEXT, IN study TEXT, IN series TEXT, in instance TEXT)");
           }
         
           std::string query;
           Orthanc::EmbeddedResources::GetFileResource
             (query, Orthanc::EmbeddedResources::POSTGRESQL_CREATE_INSTANCE);
-          t.ExecuteMultiLines(query);
+          t.GetDatabaseTransaction().ExecuteMultiLines(query);
 
           SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasCreateInstance, 2);
         }
@@ -221,7 +221,7 @@
           std::string query;
           Orthanc::EmbeddedResources::GetFileResource
             (query, Orthanc::EmbeddedResources::POSTGRESQL_FAST_TOTAL_SIZE);
-          t.ExecuteMultiLines(query);
+          t.GetDatabaseTransaction().ExecuteMultiLines(query);
 
           SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_GetTotalSizeIsFast, 1);
         }
@@ -239,7 +239,7 @@
           std::string query;
           Orthanc::EmbeddedResources::GetFileResource
             (query, Orthanc::EmbeddedResources::POSTGRESQL_FAST_COUNT_RESOURCES);
-          t.ExecuteMultiLines(query);
+          t.GetDatabaseTransaction().ExecuteMultiLines(query);
 
           SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_HasFastCountResources, 1);
         }
@@ -257,7 +257,7 @@
           std::string query;
           Orthanc::EmbeddedResources::GetFileResource
             (query, Orthanc::EmbeddedResources::POSTGRESQL_GET_LAST_CHANGE_INDEX);
-          t.ExecuteMultiLines(query);
+          t.GetDatabaseTransaction().ExecuteMultiLines(query);
 
           SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_GetLastChangeIndex, 1);
         }
@@ -270,10 +270,10 @@
         // New in release 4.0 to deal with multiple writers
         DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
 
-        if (!t.DoesTableExist("ServerProperties"))
+        if (!t.GetDatabaseTransaction().DoesTableExist("ServerProperties"))
         {
-          t.ExecuteMultiLines("CREATE TABLE ServerProperties(server VARCHAR(64) NOT NULL, "
-                              "property INTEGER, value TEXT, PRIMARY KEY(server, property))");
+          t.GetDatabaseTransaction().ExecuteMultiLines("CREATE TABLE ServerProperties(server VARCHAR(64) NOT NULL, "
+                                                       "property INTEGER, value TEXT, PRIMARY KEY(server, property))");
         }
 
         t.Commit();
--- a/SQLite/Plugins/SQLiteIndex.cpp	Mon Apr 12 17:07:06 2021 +0200
+++ b/SQLite/Plugins/SQLiteIndex.cpp	Tue Apr 13 12:07:30 2021 +0200
@@ -85,14 +85,14 @@
     {
       DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
 
-      if (!t.DoesTableExist("Resources"))
+      if (!t.GetDatabaseTransaction().DoesTableExist("Resources"))
       {
         std::string query;
 
         Orthanc::EmbeddedResources::GetFileResource
           (query, Orthanc::EmbeddedResources::SQLITE_PREPARE_INDEX);
 
-        t.ExecuteMultiLines(query);
+        t.GetDatabaseTransaction().ExecuteMultiLines(query);
 
         SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabaseSchemaVersion, expectedVersion);
         SetGlobalIntegerProperty(manager, MISSING_SERVER_IDENTIFIER, Orthanc::GlobalProperty_DatabasePatchLevel, 1);
@@ -104,7 +104,7 @@
     {
       DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
 
-      if (!t.DoesTableExist("Resources"))
+      if (!t.GetDatabaseTransaction().DoesTableExist("Resources"))
       {
         LOG(ERROR) << "Corrupted SQLite database";
         throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);        
@@ -137,10 +137,10 @@
     {
       DatabaseManager::Transaction t(manager, TransactionType_ReadWrite);
 
-      if (!t.DoesTableExist("ServerProperties"))
+      if (!t.GetDatabaseTransaction().DoesTableExist("ServerProperties"))
       {
-        t.ExecuteMultiLines("CREATE TABLE ServerProperties(server TEXT, "
-                            "property INTEGER, value TEXT, PRIMARY KEY(server, property))");
+        t.GetDatabaseTransaction().ExecuteMultiLines("CREATE TABLE ServerProperties(server TEXT, "
+                                                     "property INTEGER, value TEXT, PRIMARY KEY(server, property))");
       }
 
       t.Commit();