changeset 3019:8336204d95dc db-changes

refactoring computation of disk size for recycling
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 14 Dec 2018 18:07:40 +0100
parents e3b5c07146a3
children d207f6ac1f86
files OrthancServer/IDatabaseWrapper.h OrthancServer/InstallTrackAttachmentsSize.sql OrthancServer/SQLiteDatabaseWrapper.cpp OrthancServer/SQLiteDatabaseWrapper.h OrthancServer/ServerEnumerations.h OrthancServer/ServerIndex.cpp Plugins/Engine/OrthancPluginDatabase.cpp Plugins/Engine/OrthancPluginDatabase.h UnitTestsSources/ServerIndexTests.cpp
diffstat 9 files changed, 172 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/OrthancServer/IDatabaseWrapper.h	Fri Dec 14 16:04:17 2018 +0100
+++ b/OrthancServer/IDatabaseWrapper.h	Fri Dec 14 18:07:40 2018 +0100
@@ -48,6 +48,21 @@
   class IDatabaseWrapper : public boost::noncopyable
   {
   public:
+    class ITransaction : public boost::noncopyable
+    {
+    public:
+      virtual ~ITransaction()
+      {
+      }
+
+      virtual void Begin() = 0;
+
+      virtual void Rollback() = 0;
+
+      virtual void Commit(int64_t fileSizeDelta) = 0;
+    };
+
+
     virtual ~IDatabaseWrapper()
     {
     }
@@ -198,7 +213,7 @@
     virtual void SetProtectedPatient(int64_t internalId, 
                                      bool isProtected) = 0;
 
-    virtual SQLite::ITransaction* StartTransaction() = 0;
+    virtual ITransaction* StartTransaction() = 0;
 
     virtual void SetListener(IDatabaseListener& listener) = 0;
 
--- a/OrthancServer/InstallTrackAttachmentsSize.sql	Fri Dec 14 16:04:17 2018 +0100
+++ b/OrthancServer/InstallTrackAttachmentsSize.sql	Fri Dec 14 18:07:40 2018 +0100
@@ -2,7 +2,7 @@
        key INTEGER PRIMARY KEY,
        value INTEGER);
 
-INSERT INTO GlobalProperties VALUES (6, 1);  -- GlobalProperty_DatabaseTracksSizeOfAttachments
+INSERT INTO GlobalProperties VALUES (6, 1);  -- GlobalProperty_GetTotalSizeIsFast
 
 INSERT INTO GlobalIntegers SELECT 0, IFNULL(SUM(compressedSize), 0) FROM AttachedFiles;
 INSERT INTO GlobalIntegers SELECT 1, IFNULL(SUM(uncompressedSize), 0) FROM AttachedFiles;
--- a/OrthancServer/SQLiteDatabaseWrapper.cpp	Fri Dec 14 16:04:17 2018 +0100
+++ b/OrthancServer/SQLiteDatabaseWrapper.cpp	Fri Dec 14 18:07:40 2018 +0100
@@ -36,6 +36,7 @@
 
 #include "../Core/DicomFormat/DicomArray.h"
 #include "../Core/Logging.h"
+#include "../Core/SQLite/Transaction.h"
 #include "EmbeddedResources.h"
 #include "ServerToolbox.h"
 
@@ -373,7 +374,7 @@
     // New in Orthanc 1.5.1
     if (version_ == 6)
     {
-      if (!LookupGlobalProperty(tmp, GlobalProperty_DatabaseTracksSizeOfAttachments) ||
+      if (!LookupGlobalProperty(tmp, GlobalProperty_GetTotalSizeIsFast) ||
           tmp != "1")
       {
         LOG(INFO) << "Installing the SQLite triggers to track the size of the attachments";
@@ -542,6 +543,53 @@
   }
 
 
+  class SQLiteDatabaseWrapper::Transaction : public IDatabaseWrapper::ITransaction
+  {
+  private:
+    SQLiteDatabaseWrapper&              that_;
+    std::auto_ptr<SQLite::Transaction>  transaction_;
+    int64_t                             initialDiskSize_;
+
+  public:
+    Transaction(SQLiteDatabaseWrapper& that) :
+      that_(that),
+      transaction_(new SQLite::Transaction(that_.db_))
+    {
+#if defined(NDEBUG)
+      // Release mode
+      initialDiskSize_ = 0;
+#else
+      // Debug mode
+      initialDiskSize_ = static_cast<int64_t>(that_.GetTotalCompressedSize());
+#endif
+    }
+
+    virtual void Begin()
+    {
+      transaction_->Begin();
+    }
+
+    virtual void Rollback() 
+    {
+      transaction_->Rollback();
+    }
+
+    virtual void Commit(int64_t fileSizeDelta /* only used in debug */)
+    {
+      transaction_->Commit();
+
+      assert(initialDiskSize_ + fileSizeDelta >= 0 &&
+             initialDiskSize_ + fileSizeDelta == static_cast<int64_t>(that_.GetTotalCompressedSize()));
+    }
+  };
+
+
+  IDatabaseWrapper::ITransaction* SQLiteDatabaseWrapper::StartTransaction()
+  {
+    return new Transaction(*this);
+  }
+
+
   void SQLiteDatabaseWrapper::GetAllMetadata(std::map<MetadataType, std::string>& target,
                                              int64_t id)
   {
--- a/OrthancServer/SQLiteDatabaseWrapper.h	Fri Dec 14 16:04:17 2018 +0100
+++ b/OrthancServer/SQLiteDatabaseWrapper.h	Fri Dec 14 18:07:40 2018 +0100
@@ -36,7 +36,6 @@
 #include "IDatabaseWrapper.h"
 
 #include "../Core/SQLite/Connection.h"
-#include "../Core/SQLite/Transaction.h"
 
 namespace Orthanc
 {
@@ -53,6 +52,8 @@
   class SQLiteDatabaseWrapper : public IDatabaseWrapper
   {
   private:
+    class Transaction;
+
     IDatabaseListener* listener_;
     SQLite::Connection db_;
     Internals::SignalRemainingAncestor* signalRemainingAncestor_;
@@ -100,10 +101,7 @@
 
     virtual void GetLastChange(std::list<ServerIndexChange>& target /*out*/);
 
-    virtual SQLite::ITransaction* StartTransaction()
-    {
-      return new SQLite::Transaction(db_);
-    }
+    virtual IDatabaseWrapper::ITransaction* StartTransaction();
 
     virtual void FlushToDisk()
     {
--- a/OrthancServer/ServerEnumerations.h	Fri Dec 14 16:04:17 2018 +0100
+++ b/OrthancServer/ServerEnumerations.h	Fri Dec 14 18:07:40 2018 +0100
@@ -93,9 +93,9 @@
     GlobalProperty_FlushSleep = 2,
     GlobalProperty_AnonymizationSequence = 3,
     GlobalProperty_JobsRegistry = 5,
-    GlobalProperty_DatabaseTracksSizeOfAttachments = 6,  // New in Orthanc 1.5.1
-    GlobalProperty_Modalities = 20,                      // New in Orthanc 1.5.0
-    GlobalProperty_Peers = 21,                           // New in Orthanc 1.5.0
+    GlobalProperty_GetTotalSizeIsFast = 6,      // New in Orthanc 1.5.2
+    GlobalProperty_Modalities = 20,             // New in Orthanc 1.5.0
+    GlobalProperty_Peers = 21,                  // New in Orthanc 1.5.0
 
     // Reserved values for internal use by the database plugins
     GlobalProperty_DatabasePatchLevel = 4,
--- a/OrthancServer/ServerIndex.cpp	Fri Dec 14 16:04:17 2018 +0100
+++ b/OrthancServer/ServerIndex.cpp	Fri Dec 14 18:07:40 2018 +0100
@@ -215,7 +215,7 @@
   {
   private:
     ServerIndex& index_;
-    std::auto_ptr<SQLite::ITransaction> transaction_;
+    std::auto_ptr<IDatabaseWrapper::ITransaction> transaction_;
     bool isCommitted_;
 
   public:
@@ -245,7 +245,10 @@
     {
       if (!isCommitted_)
       {
-        transaction_->Commit();
+        int64_t delta = (static_cast<int64_t>(sizeOfAddedFiles) -
+                         static_cast<int64_t>(index_.listener_->GetSizeOfFilesToRemove()));
+
+        transaction_->Commit(delta);
 
         // We can remove the files once the SQLite transaction has
         // been successfully committed. Some files might have to be
--- a/Plugins/Engine/OrthancPluginDatabase.cpp	Fri Dec 14 16:04:17 2018 +0100
+++ b/Plugins/Engine/OrthancPluginDatabase.cpp	Fri Dec 14 18:07:40 2018 +0100
@@ -47,6 +47,62 @@
 
 namespace Orthanc
 {
+  class OrthancPluginDatabase::Transaction : public IDatabaseWrapper::ITransaction
+  {
+  private:
+    OrthancPluginDatabase&  that_;
+
+    void CheckSuccess(OrthancPluginErrorCode code) const
+    {
+      if (code != OrthancPluginErrorCode_Success)
+      {
+        that_.errorDictionary_.LogError(code, true);
+        throw OrthancException(static_cast<ErrorCode>(code));
+      }
+    }
+
+  public:
+    Transaction(OrthancPluginDatabase& that) :
+      that_(that)
+    {
+    }
+
+    virtual void Begin()
+    {
+      CheckSuccess(that_.backend_.startTransaction(that_.payload_));
+    }
+
+    virtual void Rollback()
+    {
+      CheckSuccess(that_.backend_.rollbackTransaction(that_.payload_));
+    }
+
+    virtual void Commit(int64_t diskSizeDelta)
+    {
+      if (that_.fastGetTotalSize_)
+      {
+        CheckSuccess(that_.backend_.commitTransaction(that_.payload_));
+      }
+      else
+      {
+        if (static_cast<int64_t>(that_.currentDiskSize_) + diskSizeDelta < 0)
+        {
+          throw OrthancException(ErrorCode_DatabasePlugin);
+        }
+
+        uint64_t newDiskSize = (that_.currentDiskSize_ + diskSizeDelta);
+
+        assert(newDiskSize == that_.GetTotalCompressedSize());
+
+        CheckSuccess(that_.backend_.commitTransaction(that_.payload_));
+
+        // The transaction has succeeded, we can commit the new disk size
+        that_.currentDiskSize_ = newDiskSize;
+      }
+    }
+  };
+
+
   static FileInfo Convert(const OrthancPluginAttachment& attachment)
   {
     return FileInfo(attachment.uuid,
@@ -189,6 +245,35 @@
   }
 
 
+  void OrthancPluginDatabase::Open()
+  {
+    CheckSuccess(backend_.open(payload_));
+
+    {
+      Transaction transaction(*this);
+      transaction.Begin();
+
+      std::string tmp;
+      fastGetTotalSize_ =
+        (LookupGlobalProperty(tmp, GlobalProperty_GetTotalSizeIsFast) &&
+         tmp == "1");
+      
+      if (fastGetTotalSize_)
+      {
+        currentDiskSize_ = 0;   // Unused
+      }
+      else
+      {
+        // This is the case of database plugins using Orthanc SDK <= 1.5.2
+        LOG(WARNING) << "Consider upgrading your database index plugin for best performance";
+        currentDiskSize_ = GetTotalCompressedSize();
+      }
+
+      transaction.Commit(0);
+    }
+  }
+
+
   void OrthancPluginDatabase::AddAttachment(int64_t id,
                                             const FileInfo& attachment)
   {
@@ -786,52 +871,9 @@
   }
 
 
-  class OrthancPluginDatabase::Transaction : public SQLite::ITransaction
+  IDatabaseWrapper::ITransaction* OrthancPluginDatabase::StartTransaction()
   {
-  private:
-    const OrthancPluginDatabaseBackend& backend_;
-    void* payload_;
-    PluginsErrorDictionary&  errorDictionary_;
-
-    void CheckSuccess(OrthancPluginErrorCode code)
-    {
-      if (code != OrthancPluginErrorCode_Success)
-      {
-        errorDictionary_.LogError(code, true);
-        throw OrthancException(static_cast<ErrorCode>(code));
-      }
-    }
-
-  public:
-    Transaction(const OrthancPluginDatabaseBackend& backend,
-                void* payload,
-                PluginsErrorDictionary&  errorDictionary) :
-      backend_(backend),
-      payload_(payload),
-      errorDictionary_(errorDictionary)
-    {
-    }
-
-    virtual void Begin()
-    {
-      CheckSuccess(backend_.startTransaction(payload_));
-    }
-
-    virtual void Rollback()
-    {
-      CheckSuccess(backend_.rollbackTransaction(payload_));
-    }
-
-    virtual void Commit()
-    {
-      CheckSuccess(backend_.commitTransaction(payload_));
-    }
-  };
-
-
-  SQLite::ITransaction* OrthancPluginDatabase::StartTransaction()
-  {
-    return new Transaction(backend_, payload_, errorDictionary_);
+    return new Transaction(*this);
   }
 
 
@@ -892,7 +934,7 @@
   {
     if (extensions_.upgradeDatabase != NULL)
     {
-      Transaction transaction(backend_, payload_, errorDictionary_);
+      Transaction transaction(*this);
       transaction.Begin();
 
       OrthancPluginErrorCode code = extensions_.upgradeDatabase(
@@ -901,7 +943,7 @@
 
       if (code == OrthancPluginErrorCode_Success)
       {
-        transaction.Commit();
+        transaction.Commit(0);
       }
       else
       {
--- a/Plugins/Engine/OrthancPluginDatabase.h	Fri Dec 14 16:04:17 2018 +0100
+++ b/Plugins/Engine/OrthancPluginDatabase.h	Fri Dec 14 18:07:40 2018 +0100
@@ -57,6 +57,9 @@
     void* payload_;
     IDatabaseListener* listener_;
 
+    bool      fastGetTotalSize_;
+    uint64_t  currentDiskSize_;
+
     std::list<std::string>         answerStrings_;
     std::list<int32_t>             answerInt32_;
     std::list<int64_t>             answerInt64_;
@@ -93,10 +96,7 @@
                           size_t extensionsSize,
                           void *payload);
 
-    virtual void Open()
-    {
-      CheckSuccess(backend_.open(payload_));
-    }
+    virtual void Open();
 
     virtual void Close()
     {
@@ -255,7 +255,7 @@
     virtual void SetProtectedPatient(int64_t internalId, 
                                      bool isProtected);
 
-    virtual SQLite::ITransaction* StartTransaction();
+    virtual IDatabaseWrapper::ITransaction* StartTransaction();
 
     virtual void SetListener(IDatabaseListener& listener)
     {
--- a/UnitTestsSources/ServerIndexTests.cpp	Fri Dec 14 16:04:17 2018 +0100
+++ b/UnitTestsSources/ServerIndexTests.cpp	Fri Dec 14 18:07:40 2018 +0100
@@ -471,7 +471,7 @@
   ASSERT_EQ("6", tmp);
   ASSERT_TRUE(index_->LookupGlobalProperty(tmp, GlobalProperty_FlushSleep));
   ASSERT_EQ("World", tmp);
-  ASSERT_TRUE(index_->LookupGlobalProperty(tmp, GlobalProperty_DatabaseTracksSizeOfAttachments));
+  ASSERT_TRUE(index_->LookupGlobalProperty(tmp, GlobalProperty_GetTotalSizeIsFast));
   ASSERT_EQ("1", tmp);
 
   ASSERT_EQ(3u, listener_->deletedFiles_.size());