changeset 4570:648defffc8cc db-changes

new enum: TransactionType
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 08 Mar 2021 16:04:56 +0100
parents 19ea4ecd6d9a
children 9224e107d613
files OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp OrthancServer/Plugins/Engine/OrthancPluginDatabase.h OrthancServer/Sources/Database/IDatabaseWrapper.h OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp OrthancServer/Sources/Database/SQLiteDatabaseWrapper.h OrthancServer/Sources/ServerEnumerations.h OrthancServer/Sources/ServerIndex.cpp
diffstat 7 files changed, 85 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp	Mon Mar 08 15:13:25 2021 +0100
+++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabase.cpp	Mon Mar 08 16:04:56 2021 +0100
@@ -889,8 +889,10 @@
   }
 
 
-  IDatabaseWrapper::ITransaction* OrthancPluginDatabase::StartTransaction()
+  IDatabaseWrapper::ITransaction* OrthancPluginDatabase::StartTransaction(TransactionType type)
   {
+    // TODO - Take advantage of "type"
+    
     std::unique_ptr<Transaction> transaction(new Transaction(*this));
     transaction->Begin();
     return transaction.release();
--- a/OrthancServer/Plugins/Engine/OrthancPluginDatabase.h	Mon Mar 08 15:13:25 2021 +0100
+++ b/OrthancServer/Plugins/Engine/OrthancPluginDatabase.h	Mon Mar 08 16:04:56 2021 +0100
@@ -297,7 +297,7 @@
                                      bool isProtected) 
       ORTHANC_OVERRIDE;
 
-    virtual IDatabaseWrapper::ITransaction* StartTransaction() 
+    virtual IDatabaseWrapper::ITransaction* StartTransaction(TransactionType type)
       ORTHANC_OVERRIDE;
 
     virtual void SetListener(IDatabaseListener& listener) 
--- a/OrthancServer/Sources/Database/IDatabaseWrapper.h	Mon Mar 08 15:13:25 2021 +0100
+++ b/OrthancServer/Sources/Database/IDatabaseWrapper.h	Mon Mar 08 16:04:56 2021 +0100
@@ -195,7 +195,7 @@
     virtual void SetProtectedPatient(int64_t internalId, 
                                      bool isProtected) = 0;
 
-    virtual ITransaction* StartTransaction() = 0;
+    virtual ITransaction* StartTransaction(TransactionType type) = 0;
 
     virtual void SetListener(IDatabaseListener& listener) = 0;
 
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Mon Mar 08 15:13:25 2021 +0100
+++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Mon Mar 08 16:04:56 2021 +0100
@@ -596,7 +596,7 @@
   }
 
 
-  class SQLiteDatabaseWrapper::Transaction : public IDatabaseWrapper::ITransaction
+  class SQLiteDatabaseWrapper::ReadWriteTransaction : public IDatabaseWrapper::ITransaction
   {
   private:
     SQLiteDatabaseWrapper&                that_;
@@ -604,7 +604,7 @@
     int64_t                               initialDiskSize_;
 
   public:
-    Transaction(SQLiteDatabaseWrapper& that) :
+    ReadWriteTransaction(SQLiteDatabaseWrapper& that) :
       that_(that),
       transaction_(new SQLite::Transaction(that_.db_))
     {
@@ -637,11 +637,41 @@
   };
 
 
-  IDatabaseWrapper::ITransaction* SQLiteDatabaseWrapper::StartTransaction()
+  class SQLiteDatabaseWrapper::ReadOnlyTransaction : public IDatabaseWrapper::ITransaction
   {
-    std::unique_ptr<Transaction> transaction(new Transaction(*this));
-    transaction->Begin();
-    return transaction.release();
+  public:
+    virtual void Rollback() ORTHANC_OVERRIDE
+    {
+    }
+
+    virtual void Commit(int64_t fileSizeDelta /* only used in debug */) ORTHANC_OVERRIDE
+    {
+      if (fileSizeDelta != 0)
+      {
+        throw OrthancException(ErrorCode_InternalError);
+      }
+    }
+  };
+
+
+  IDatabaseWrapper::ITransaction* SQLiteDatabaseWrapper::StartTransaction(TransactionType type)
+  {
+    switch (type)
+    {
+      case TransactionType_ReadOnly:
+        return new ReadOnlyTransaction;  // This is a no-op transaction in SQLite (thanks to mutex)
+
+      case TransactionType_ReadWrite:
+      {
+        std::unique_ptr<ReadWriteTransaction> transaction;
+        transaction.reset(new ReadWriteTransaction(*this));
+        transaction->Begin();
+        return transaction.release();
+      }
+
+      default:
+        throw OrthancException(ErrorCode_InternalError);
+    }
   }
 
 
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.h	Mon Mar 08 15:13:25 2021 +0100
+++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.h	Mon Mar 08 16:04:56 2021 +0100
@@ -61,7 +61,8 @@
     public Compatibility::ISetResourcesContent
   {
   private:
-    class Transaction;
+    class ReadOnlyTransaction;
+    class ReadWriteTransaction;
     class LookupFormatter;
 
     IDatabaseListener* listener_;
@@ -124,7 +125,7 @@
     virtual void GetLastChange(std::list<ServerIndexChange>& target /*out*/)
       ORTHANC_OVERRIDE;
 
-    virtual IDatabaseWrapper::ITransaction* StartTransaction()
+    virtual IDatabaseWrapper::ITransaction* StartTransaction(TransactionType type)
       ORTHANC_OVERRIDE;
 
     virtual void FlushToDisk()
--- a/OrthancServer/Sources/ServerEnumerations.h	Mon Mar 08 15:13:25 2021 +0100
+++ b/OrthancServer/Sources/ServerEnumerations.h	Mon Mar 08 16:04:56 2021 +0100
@@ -109,6 +109,12 @@
     TransferSyntaxGroup_H265    // New in Orthanc 1.9.0
   };
 
+  enum TransactionType
+  {
+    TransactionType_ReadOnly,
+    TransactionType_ReadWrite
+  };
+
 
   /**
    * WARNING: Do not change the explicit values in the enumerations
--- a/OrthancServer/Sources/ServerIndex.cpp	Mon Mar 08 15:13:25 2021 +0100
+++ b/OrthancServer/Sources/ServerIndex.cpp	Mon Mar 08 16:04:56 2021 +0100
@@ -247,11 +247,12 @@
     bool isCommitted_;
     
   public:
-    explicit Transaction(ServerIndex& index) : 
+    explicit Transaction(ServerIndex& index,
+                         TransactionType type) : 
       index_(index),
       isCommitted_(false)
     {
-      transaction_.reset(index_.db_.StartTransaction());
+      transaction_.reset(index_.db_.StartTransaction(type));
       index_.listener_->StartTransaction();
     }
 
@@ -716,7 +717,7 @@
 
     try
     {
-      Transaction t(*this);
+      Transaction t(*this, TransactionType_ReadWrite);
 
       IDatabaseWrapper::CreateInstanceResult status;
       int64_t instanceId;
@@ -1199,7 +1200,7 @@
   void ServerIndex::StandaloneRecycling()
   {
     // WARNING: No mutex here, do not include this as a public method
-    Transaction t(*this);
+    Transaction t(*this, TransactionType_ReadWrite);
     Recycle(0, "");
     t.Commit(0);
   }
@@ -1292,7 +1293,7 @@
   {
     boost::mutex::scoped_lock lock(mutex_);
 
-    Transaction t(*this);
+    Transaction t(*this, TransactionType_ReadWrite);
 
     ResourceType resourceType;
     int64_t resourceId;
@@ -1349,7 +1350,7 @@
 
     try
     {
-      Transaction t(*this);
+      Transaction t(*this, TransactionType_ReadWrite);
 
       int64_t patient = -1, study = -1, series = -1, instance = -1;
 
@@ -1660,21 +1661,32 @@
       {
         boost::mutex::scoped_lock lock(mutex_);  // TODO - REMOVE
 
-        Transaction transaction(*this);  // TODO - Only if "TransactionType_SingleStatement"
-
         if (readOperations != NULL)
         {
-          ReadOnlyTransaction t(db_);
-          readOperations->Apply(t);
+          /**
+           * IMPORTANT: In Orthanc <= 1.9.1, there was no transaction
+           * in this case. This was OK because of the presence of the
+           * global mutex protecting the database.
+           **/
+          
+          Transaction transaction(*this, TransactionType_ReadOnly);  // TODO - Only if not "TransactionType_Implicit"
+          {
+            ReadOnlyTransaction t(db_);
+            readOperations->Apply(t);
+          }
+          transaction.Commit(0);
         }
         else
         {
           assert(writeOperations != NULL);
-          ReadWriteTransaction t(db_, *this);
-          writeOperations->Apply(t, *listener_);          
+          
+          Transaction transaction(*this, TransactionType_ReadWrite);
+          {
+            ReadWriteTransaction t(db_, *this);
+            writeOperations->Apply(t, *listener_);
+          }
+          transaction.Commit(0);
         }
-
-        transaction.Commit(0);
         
         return;  // Success
       }
@@ -2001,7 +2013,7 @@
       virtual void ApplyTuple(ReadOnlyTransaction& transaction,
                               const Tuple& tuple) ORTHANC_OVERRIDE
       {
-        // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
+        // TODO - CANDIDATE FOR "TransactionType_Implicit"
         transaction.GetAllPublicIds(tuple.get<0>(), tuple.get<1>());
       }
     };
@@ -2028,7 +2040,7 @@
         virtual void ApplyTuple(ReadOnlyTransaction& transaction,
                                 const Tuple& tuple) ORTHANC_OVERRIDE
         {
-          // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
+          // TODO - CANDIDATE FOR "TransactionType_Implicit"
           transaction.GetAllPublicIds(tuple.get<0>(), tuple.get<1>(), tuple.get<2>(), tuple.get<3>());
         }
       };
@@ -2142,7 +2154,7 @@
       virtual void ApplyTuple(ReadOnlyTransaction& transaction,
                               const Tuple& tuple) ORTHANC_OVERRIDE
       {
-        // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
+        // TODO - CANDIDATE FOR "TransactionType_Implicit"
 
         std::list<ExportedResource> exported;
         bool done;
@@ -2164,7 +2176,7 @@
       virtual void ApplyTuple(ReadOnlyTransaction& transaction,
                               const Tuple& tuple) ORTHANC_OVERRIDE
       {
-        // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
+        // TODO - CANDIDATE FOR "TransactionType_Implicit"
 
         std::list<ExportedResource> exported;
         transaction.GetLastExportedResource(exported);
@@ -2589,7 +2601,7 @@
 
       virtual void Apply(ReadOnlyTransaction& transaction) ORTHANC_OVERRIDE
       {
-        // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
+        // TODO - CANDIDATE FOR "TransactionType_Implicit"
         std::list<std::string> tmp;
         transaction.ApplyLookupResources(tmp, NULL, query_, level_, 0);
         CopyListToVector(result_, tmp);
@@ -2610,7 +2622,7 @@
       virtual void ApplyTuple(ReadOnlyTransaction& transaction,
                               const Tuple& tuple) ORTHANC_OVERRIDE
       {
-        // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
+        // TODO - CANDIDATE FOR "TransactionType_Implicit"
         tuple.get<0>() = transaction.LookupGlobalProperty(tuple.get<1>(), tuple.get<2>());
       }
     };
@@ -2797,7 +2809,7 @@
       virtual void ApplyTuple(ReadOnlyTransaction& transaction,
                               const Tuple& tuple) ORTHANC_OVERRIDE
       {
-        // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
+        // TODO - CANDIDATE FOR "TransactionType_Implicit"
         int64_t id;
         tuple.get<0>() = transaction.LookupResource(id, tuple.get<1>(), tuple.get<2>());
       }
@@ -2818,7 +2830,7 @@
       virtual void ApplyTuple(ReadOnlyTransaction& transaction,
                               const Tuple& tuple) ORTHANC_OVERRIDE
       {
-        // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
+        // TODO - CANDIDATE FOR "TransactionType_Implicit"
         tuple.get<0>() = transaction.GetDatabaseVersion();
       }
     };
@@ -2900,7 +2912,7 @@
       virtual void ApplyTuple(ReadOnlyTransaction& transaction,
                               const Tuple& tuple) ORTHANC_OVERRIDE
       {
-        // TODO - CANDIDATE FOR "TransactionType_SingleStatement"
+        // TODO - CANDIDATE FOR "TransactionType_Implicit"
         if (tuple.get<0>())
         {
           transaction.ApplyLookupResources(resourcesList_, &instancesList_, tuple.get<1>(), tuple.get<2>(), tuple.get<3>());