diff OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp @ 4589:bec74e29f86b db-changes

attaching the listener to transactions in IDatabaseWrapper
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 12 Mar 2021 15:33:47 +0100
parents 9224e107d613
children ff8170d17d90
line wrap: on
line diff
--- a/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Wed Mar 10 17:15:01 2021 +0100
+++ b/OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp	Fri Mar 12 15:33:47 2021 +0100
@@ -47,30 +47,30 @@
 
 namespace Orthanc
 {
-  namespace Internals
+  class SQLiteDatabaseWrapper::SignalFileDeleted : public SQLite::IScalarFunction
   {
-    class SignalFileDeleted : public SQLite::IScalarFunction
+  private:
+    SQLiteDatabaseWrapper& sqlite_;
+
+  public:
+    SignalFileDeleted(SQLiteDatabaseWrapper& sqlite) :
+      sqlite_(sqlite)
     {
-    private:
-      IDatabaseListener& listener_;
+    }
 
-    public:
-      SignalFileDeleted(IDatabaseListener& listener) :
-        listener_(listener)
-      {
-      }
+    virtual const char* GetName() const ORTHANC_OVERRIDE
+    {
+      return "SignalFileDeleted";
+    }
 
-      virtual const char* GetName() const ORTHANC_OVERRIDE
-      {
-        return "SignalFileDeleted";
-      }
+    virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE
+    {
+      return 7;
+    }
 
-      virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE
-      {
-        return 7;
-      }
-
-      virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE
+    virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE
+    {
+      if (sqlite_.listener_ != NULL)
       {
         std::string uncompressedMD5, compressedMD5;
 
@@ -91,100 +91,105 @@
                       static_cast<CompressionType>(context.GetIntValue(3)),
                       static_cast<uint64_t>(context.GetInt64Value(4)),
                       compressedMD5);
-        
-        listener_.SignalAttachmentDeleted(info);
-      }
-    };
 
-    class SignalResourceDeleted : public SQLite::IScalarFunction
-    {
-    private:
-      IDatabaseListener& listener_;
+        sqlite_.listener_->SignalAttachmentDeleted(info);
+      }
+    }
+  };
+    
+
+  class SQLiteDatabaseWrapper::SignalResourceDeleted : public SQLite::IScalarFunction
+  {
+  private:
+    SQLiteDatabaseWrapper& sqlite_;
 
-    public:
-      SignalResourceDeleted(IDatabaseListener& listener) :
-        listener_(listener)
-      {
-      }
+  public:
+    SignalResourceDeleted(SQLiteDatabaseWrapper& sqlite) :
+      sqlite_(sqlite)
+    {
+    }
 
-      virtual const char* GetName() const ORTHANC_OVERRIDE
-      {
-        return "SignalResourceDeleted";
-      }
+    virtual const char* GetName() const ORTHANC_OVERRIDE
+    {
+      return "SignalResourceDeleted";
+    }
 
-      virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE
+    virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE
+    {
+      return 2;
+    }
+
+    virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE
+    {
+      if (sqlite_.listener_ != NULL)
       {
-        return 2;
+        sqlite_.listener_->SignalResourceDeleted(static_cast<ResourceType>(context.GetIntValue(1)),
+                                                 context.GetStringValue(0));
       }
-
-      virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE
-      {
-        listener_.SignalResourceDeleted(static_cast<ResourceType>(context.GetIntValue(1)),
-                                        context.GetStringValue(0));
-      }
-    };
+    }
+  };
 
-    class SignalRemainingAncestor : public SQLite::IScalarFunction
-    {
-    private:
-      bool hasRemainingAncestor_;
-      std::string remainingPublicId_;
-      ResourceType remainingType_;
-
-    public:
-      SignalRemainingAncestor() : 
-        hasRemainingAncestor_(false)
-      {
-      }
+  
+  class SQLiteDatabaseWrapper::SignalRemainingAncestor : public SQLite::IScalarFunction
+  {
+  private:
+    bool hasRemainingAncestor_;
+    std::string remainingPublicId_;
+    ResourceType remainingType_;
 
-      void Reset()
-      {
-        hasRemainingAncestor_ = false;
-      }
+  public:
+    SignalRemainingAncestor() : 
+      hasRemainingAncestor_(false)
+    {
+    }
 
-      virtual const char* GetName() const ORTHANC_OVERRIDE
-      {
-        return "SignalRemainingAncestor";
-      }
+    void Reset()
+    {
+      hasRemainingAncestor_ = false;
+    }
 
-      virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE
-      {
-        return 2;
-      }
+    virtual const char* GetName() const ORTHANC_OVERRIDE
+    {
+      return "SignalRemainingAncestor";
+    }
 
-      virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE
-      {
-        CLOG(TRACE, SQLITE) << "There exists a remaining ancestor with public ID \""
-                            << context.GetStringValue(0) << "\" of type "
-                            << context.GetIntValue(1);
+    virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE
+    {
+      return 2;
+    }
+
+    virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE
+    {
+      CLOG(TRACE, SQLITE) << "There exists a remaining ancestor with public ID \""
+                          << context.GetStringValue(0) << "\" of type "
+                          << context.GetIntValue(1);
 
-        if (!hasRemainingAncestor_ ||
-            remainingType_ >= context.GetIntValue(1))
-        {
-          hasRemainingAncestor_ = true;
-          remainingPublicId_ = context.GetStringValue(0);
-          remainingType_ = static_cast<ResourceType>(context.GetIntValue(1));
-        }
+      if (!hasRemainingAncestor_ ||
+          remainingType_ >= context.GetIntValue(1))
+      {
+        hasRemainingAncestor_ = true;
+        remainingPublicId_ = context.GetStringValue(0);
+        remainingType_ = static_cast<ResourceType>(context.GetIntValue(1));
       }
-
-      bool HasRemainingAncestor() const
-      {
-        return hasRemainingAncestor_;
-      }
+    }
 
-      const std::string& GetRemainingAncestorId() const
-      {
-        assert(hasRemainingAncestor_);
-        return remainingPublicId_;
-      }
+    bool HasRemainingAncestor() const
+    {
+      return hasRemainingAncestor_;
+    }
 
-      ResourceType GetRemainingAncestorType() const
-      {
-        assert(hasRemainingAncestor_);
-        return remainingType_;
-      }
-    };
-  }
+    const std::string& GetRemainingAncestorId() const
+    {
+      assert(hasRemainingAncestor_);
+      return remainingPublicId_;
+    }
+
+    ResourceType GetRemainingAncestorType() const
+    {
+      assert(hasRemainingAncestor_);
+      return remainingType_;
+    }
+  };
 
 
   void SQLiteDatabaseWrapper::GetChangesInternal(std::list<ServerIndexChange>& target,
@@ -436,8 +441,9 @@
       t.Commit();
     }
 
-    signalRemainingAncestor_ = new Internals::SignalRemainingAncestor;
-    db_.Register(signalRemainingAncestor_);
+    signalRemainingAncestor_ = dynamic_cast<SignalRemainingAncestor*>(db_.Register(new SignalRemainingAncestor));
+    db_.Register(new SignalFileDeleted(*this));
+    db_.Register(new SignalResourceDeleted(*this));
   }
 
 
@@ -503,14 +509,6 @@
   }
 
 
-  void SQLiteDatabaseWrapper::SetListener(IDatabaseListener& listener)
-  {
-    listener_ = &listener;
-    db_.Register(new Internals::SignalFileDeleted(listener));
-    db_.Register(new Internals::SignalResourceDeleted(listener));
-  }
-
-
   void SQLiteDatabaseWrapper::ClearTable(const std::string& tableName)
   {
     db_.Execute("DELETE FROM " + tableName);    
@@ -603,10 +601,14 @@
     int64_t                               initialDiskSize_;
 
   public:
-    ReadWriteTransaction(SQLiteDatabaseWrapper& that) :
+    ReadWriteTransaction(SQLiteDatabaseWrapper& that,
+                         IDatabaseListener& listener) :
       that_(that),
       transaction_(new SQLite::Transaction(that_.db_))
     {
+      assert(that_.listener_ == NULL);
+      that_.listener_ = &listener;   // TODO - STORE IN TRANSACTION
+
 #if defined(NDEBUG)
       // Release mode
       initialDiskSize_ = 0;
@@ -616,6 +618,12 @@
 #endif
     }
 
+    virtual ~ReadWriteTransaction()
+    {
+      assert(that_.listener_ != NULL);    
+      that_.listener_ = NULL;   // TODO - STORE IN TRANSACTION
+    }
+
     void Begin()
     {
       transaction_->Begin();
@@ -638,7 +646,24 @@
 
   class SQLiteDatabaseWrapper::ReadOnlyTransaction : public IDatabaseWrapper::ITransaction
   {
+  private:
+    SQLiteDatabaseWrapper&  that_;
+    
   public:
+    ReadOnlyTransaction(SQLiteDatabaseWrapper& that,
+                        IDatabaseListener& listener) :
+      that_(that)
+    {
+      assert(that_.listener_ == NULL);
+      that_.listener_ = &listener;
+    }
+
+    virtual ~ReadOnlyTransaction()
+    {
+      assert(that_.listener_ != NULL);    
+      that_.listener_ = NULL;
+    }
+
     virtual void Rollback() ORTHANC_OVERRIDE
     {
     }
@@ -653,17 +678,18 @@
   };
 
 
-  IDatabaseWrapper::ITransaction* SQLiteDatabaseWrapper::StartTransaction(TransactionType type)
+  IDatabaseWrapper::ITransaction* SQLiteDatabaseWrapper::StartTransaction(TransactionType type,
+                                                                          IDatabaseListener& listener)
   {
     switch (type)
     {
       case TransactionType_ReadOnly:
-        return new ReadOnlyTransaction;  // This is a no-op transaction in SQLite (thanks to mutex)
+        return new ReadOnlyTransaction(*this, listener);  // 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.reset(new ReadWriteTransaction(*this, listener));
         transaction->Begin();
         return transaction.release();
       }