changeset 1177:5b2d8c280ac2 db-changes

Plugins can monitor changes through callbacks
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 24 Sep 2014 17:37:44 +0200
parents f24e04838054
children c71d25e6a63c
files NEWS OrthancServer/DatabaseWrapper.cpp OrthancServer/DatabaseWrapper.h OrthancServer/IServerIndexListener.h OrthancServer/ServerEnumerations.cpp OrthancServer/ServerEnumerations.h OrthancServer/ServerIndex.cpp OrthancServer/ServerIndex.h Plugins/Engine/OrthancPlugins.cpp Plugins/Engine/OrthancPlugins.h Plugins/OrthancCPlugin/OrthancCPlugin.h UnitTestsSources/ServerIndexTests.cpp
diffstat 12 files changed, 328 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon Sep 22 14:11:37 2014 +0200
+++ b/NEWS	Wed Sep 24 17:37:44 2014 +0200
@@ -1,6 +1,9 @@
 Pending changes in the mainline
 ===============================
 
+* Speed-up thanks to a new database schema
+* Plugins can monitor changes through callbacks
+
 
 Version 0.8.4 (2014/09/19)
 ==========================
--- a/OrthancServer/DatabaseWrapper.cpp	Mon Sep 22 14:11:37 2014 +0200
+++ b/OrthancServer/DatabaseWrapper.cpp	Wed Sep 24 17:37:44 2014 +0200
@@ -116,7 +116,7 @@
       virtual void Compute(SQLite::FunctionContext& context)
       {
         ResourceType type = static_cast<ResourceType>(context.GetIntValue(1));
-        listener_.SignalResourceDeleted(type, context.GetStringValue(0));
+        listener_.SignalChange(ChangeType_Deleted, type, context.GetStringValue(0));
       }
     };
 
@@ -258,7 +258,7 @@
       throw OrthancException(ErrorCode_InternalError);
     }
 
-    LogChange(changeType, id, type);
+    LogChange(changeType, id, type, publicId);
     return id;
   }
 
@@ -650,14 +650,23 @@
   void DatabaseWrapper::LogChange(ChangeType changeType,
                                   int64_t internalId,
                                   ResourceType resourceType,
-                                  const boost::posix_time::ptime& date)
+                                  const std::string& publicId)
   {
+    if (changeType == ChangeType_Deleted)
+    {
+      throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+
+    const boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
+
     SQLite::Statement s(db_, SQLITE_FROM_HERE, "INSERT INTO Changes VALUES(NULL, ?, ?, ?, ?)");
     s.BindInt(0, changeType);
     s.BindInt64(1, internalId);
     s.BindInt(2, resourceType);
-    s.BindString(3, boost::posix_time::to_iso_string(date));
-    s.Run();      
+    s.BindString(3, boost::posix_time::to_iso_string(now));
+    s.Run();
+
+    listener_.SignalChange(changeType, resourceType, publicId);
   }
 
 
--- a/OrthancServer/DatabaseWrapper.h	Mon Sep 22 14:11:37 2014 +0200
+++ b/OrthancServer/DatabaseWrapper.h	Wed Sep 24 17:37:44 2014 +0200
@@ -157,7 +157,7 @@
     void LogChange(ChangeType changeType,
                    int64_t internalId,
                    ResourceType resourceType,
-                   const boost::posix_time::ptime& date = boost::posix_time::second_clock::local_time());
+                   const std::string& publicId);
 
     void GetChanges(Json::Value& target,
                     int64_t since,
--- a/OrthancServer/IServerIndexListener.h	Mon Sep 22 14:11:37 2014 +0200
+++ b/OrthancServer/IServerIndexListener.h	Wed Sep 24 17:37:44 2014 +0200
@@ -47,9 +47,10 @@
     virtual void SignalRemainingAncestor(ResourceType parentType,
                                          const std::string& publicId) = 0;
 
-    virtual void SignalResourceDeleted(ResourceType type,
-                                       const std::string& publicId) = 0;
+    virtual void SignalFileDeleted(const FileInfo& info) = 0;
 
-    virtual void SignalFileDeleted(const FileInfo& info) = 0;
+    virtual void SignalChange(ChangeType changeType,
+                              ResourceType resourceType,
+                              const std::string& publicId) = 0;
   };
 }
--- a/OrthancServer/ServerEnumerations.cpp	Mon Sep 22 14:11:37 2014 +0200
+++ b/OrthancServer/ServerEnumerations.cpp	Wed Sep 24 17:37:44 2014 +0200
@@ -231,6 +231,9 @@
       case ChangeType_StableSeries:
         return "StableSeries";
 
+      case ChangeType_Deleted:
+        return "Deleted";
+
       default:
         throw OrthancException(ErrorCode_ParameterOutOfRange);
     }
--- a/OrthancServer/ServerEnumerations.h	Mon Sep 22 14:11:37 2014 +0200
+++ b/OrthancServer/ServerEnumerations.h	Wed Sep 24 17:37:44 2014 +0200
@@ -134,7 +134,8 @@
     ChangeType_ModifiedPatient = 11,
     ChangeType_StablePatient = 12,
     ChangeType_StableStudy = 13,
-    ChangeType_StableSeries = 14
+    ChangeType_StableSeries = 14,
+    ChangeType_Deleted = 15   // Not logged in the index
   };
 
 
--- a/OrthancServer/ServerIndex.cpp	Mon Sep 22 14:11:37 2014 +0200
+++ b/OrthancServer/ServerIndex.cpp	Wed Sep 24 17:37:44 2014 +0200
@@ -61,13 +61,58 @@
     private:
       struct FileToRemove
       {
+      private:
         std::string  uuid_;
         FileContentType  type_;
 
+      public:
         FileToRemove(const FileInfo& info) : uuid_(info.GetUuid()), 
                                              type_(info.GetContentType())
         {
         }
+
+        const std::string& GetUuid() const
+        {
+          return uuid_;
+        }
+
+        FileContentType GetContentType() const 
+        {
+          return type_;
+        }
+      };
+
+      struct Change
+      {
+      private:
+        ChangeType   changeType_;
+        ResourceType resourceType_;
+        std::string  publicId_;
+
+      public:
+        Change(ChangeType changeType,
+               ResourceType resourceType,
+               const std::string&  publicId) :
+          changeType_(changeType),
+          resourceType_(resourceType),
+          publicId_(publicId)
+        {
+        }
+
+        ChangeType  GetChangeType() const
+        {
+          return changeType_;
+        }
+
+        ResourceType  GetResourceType() const
+        {
+          return resourceType_;
+        }
+
+        const std::string&  GetPublicId() const
+        {
+          return publicId_;
+        }
       };
 
       ServerContext& context_;
@@ -75,6 +120,7 @@
       ResourceType remainingType_;
       std::string remainingPublicId_;
       std::list<FileToRemove> pendingFilesToRemove_;
+      std::list<Change> pendingChanges_;
       uint64_t sizeOfFilesToRemove_;
 
     public:
@@ -105,7 +151,7 @@
                it = pendingFilesToRemove_.begin();
              it != pendingFilesToRemove_.end(); ++it)
         {
-          context_.RemoveFile(it->uuid_, it->type_);
+          context_.RemoveFile(it->GetUuid(), it->GetContentType());
         }
       }
 
@@ -137,13 +183,16 @@
         sizeOfFilesToRemove_ += info.GetCompressedSize();
       }
 
-      virtual void SignalResourceDeleted(ResourceType type,
-                                         const std::string& publicId)
+      virtual void SignalChange(ChangeType changeType,
+                                ResourceType resourceType,
+                                const std::string& publicId)
       {
-        LOG(INFO) << "Resource " << publicId << " of type " << EnumerationToString(type) << " is deleted";
+        LOG(INFO) << "Change related to resource " << publicId << " of type " 
+                  << EnumerationToString(resourceType) << ": " << EnumerationToString(changeType);
+
+        pendingChanges_.push_back(Change(changeType, resourceType, publicId));
       }
 
-
       bool HasRemainingLevel() const
       {
         return hasRemainingLevel_;
@@ -207,16 +256,22 @@
   };
 
 
-  struct ServerIndex::UnstableResourcePayload
+  class ServerIndex::UnstableResourcePayload
   {
-    Orthanc::ResourceType type_;
+  private:
+    ResourceType type_;
+    std::string publicId_;
     boost::posix_time::ptime time_;
 
-    UnstableResourcePayload() : type_(Orthanc::ResourceType_Instance)
+  public:
+    UnstableResourcePayload() : type_(ResourceType_Instance)
     {
     }
 
-    UnstableResourcePayload(Orthanc::ResourceType type) : type_(type)
+    UnstableResourcePayload(Orthanc::ResourceType type,
+                            const std::string& publicId) : 
+      type_(type),
+      publicId_(publicId)
     {
       time_ = boost::posix_time::second_clock::local_time();
     }
@@ -225,6 +280,16 @@
     {
       return (boost::posix_time::second_clock::local_time() - time_).total_seconds();
     }
+
+    ResourceType GetResourceType() const
+    {
+      return type_;
+    }
+    
+    const std::string& GetPublicId() const
+    {
+      return publicId_;
+    }
   };
 
 
@@ -604,13 +669,13 @@
       SeriesStatus seriesStatus = GetSeriesStatus(series);
       if (seriesStatus == SeriesStatus_Complete)
       {
-        db_->LogChange(ChangeType_CompletedSeries, series, ResourceType_Series);
+        db_->LogChange(ChangeType_CompletedSeries, series, ResourceType_Series, hasher.HashSeries());
       }
 
       // Mark the parent resources of this instance as unstable
-      MarkAsUnstable(series, ResourceType_Series);
-      MarkAsUnstable(study, ResourceType_Study);
-      MarkAsUnstable(patient, ResourceType_Patient);
+      MarkAsUnstable(series, ResourceType_Series, hasher.HashSeries());
+      MarkAsUnstable(study, ResourceType_Study, hasher.HashStudy());
+      MarkAsUnstable(patient, ResourceType_Patient, hasher.HashPatient());
 
       t.Commit(instanceSize);
 
@@ -1393,7 +1458,7 @@
       throw OrthancException(ErrorCode_UnknownResource);
     }
 
-    db_->LogChange(changeType, id, type);
+    db_->LogChange(changeType, id, type, publicId);
 
     transaction->Commit();
   }
@@ -1590,18 +1655,18 @@
         // Ensure that the resource is still existing before logging the change
         if (that->db_->IsExistingResource(id))
         {
-          switch (payload.type_)
+          switch (payload.GetResourceType())
           {
-            case Orthanc::ResourceType_Patient:
-              that->db_->LogChange(ChangeType_StablePatient, id, ResourceType_Patient);
+            case ResourceType_Patient:
+              that->db_->LogChange(ChangeType_StablePatient, id, ResourceType_Patient, payload.GetPublicId());
               break;
 
-            case Orthanc::ResourceType_Study:
-              that->db_->LogChange(ChangeType_StableStudy, id, ResourceType_Study);
+            case ResourceType_Study:
+              that->db_->LogChange(ChangeType_StableStudy, id, ResourceType_Study, payload.GetPublicId());
               break;
 
-            case Orthanc::ResourceType_Series:
-              that->db_->LogChange(ChangeType_StableSeries, id, ResourceType_Series);
+            case ResourceType_Series:
+              that->db_->LogChange(ChangeType_StableSeries, id, ResourceType_Series, payload.GetPublicId());
               break;
 
             default:
@@ -1618,7 +1683,8 @@
   
 
   void ServerIndex::MarkAsUnstable(int64_t id,
-                                   Orthanc::ResourceType type)
+                                   Orthanc::ResourceType type,
+                                   const std::string& publicId)
   {
     // WARNING: Before calling this method, "mutex_" must be locked.
 
@@ -1626,7 +1692,8 @@
            type == Orthanc::ResourceType_Study ||
            type == Orthanc::ResourceType_Series);
 
-    unstableResources_.AddOrMakeMostRecent(id, type);
+    UnstableResourcePayload payload(type, publicId);
+    unstableResources_.AddOrMakeMostRecent(id, payload);
     //LOG(INFO) << "Unstable resource: " << EnumerationToString(type) << " " << id;
   }
 
@@ -1787,6 +1854,4 @@
 
     return true;
   }
-
-
 }
--- a/OrthancServer/ServerIndex.h	Mon Sep 22 14:11:37 2014 +0200
+++ b/OrthancServer/ServerIndex.h	Wed Sep 24 17:37:44 2014 +0200
@@ -60,7 +60,7 @@
 
   private:
     class Transaction;
-    struct UnstableResourcePayload;
+    class UnstableResourcePayload;
 
     bool done_;
     boost::mutex mutex_;
@@ -92,7 +92,8 @@
     void StandaloneRecycling();
 
     void MarkAsUnstable(int64_t id,
-                        Orthanc::ResourceType type);
+                        Orthanc::ResourceType type,
+                        const std::string& publicId);
 
     void GetStatisticsInternal(/* out */ uint64_t& compressedSize, 
                                /* out */ uint64_t& uncompressedSize, 
--- a/Plugins/Engine/OrthancPlugins.cpp	Mon Sep 22 14:11:37 2014 +0200
+++ b/Plugins/Engine/OrthancPlugins.cpp	Wed Sep 24 17:37:44 2014 +0200
@@ -84,11 +84,13 @@
     typedef std::pair<boost::regex*, OrthancPluginRestCallback> RestCallback;
     typedef std::list<RestCallback>  RestCallbacks;
     typedef std::list<OrthancPluginOnStoredInstanceCallback>  OnStoredCallbacks;
+    typedef std::list<OrthancPluginOnChangeCallback>  OnChangeCallbacks;
 
     ServerContext& context_;
     RestCallbacks restCallbacks_;
     OrthancRestApi* restApi_;
     OnStoredCallbacks  onStoredCallbacks_;
+    OnChangeCallbacks  onChangeCallbacks_;
     bool hasStorageArea_;
     _OrthancPluginRegisterStorageArea storageArea_;
 
@@ -123,6 +125,83 @@
   }
 
 
+  static OrthancPluginResourceType Convert(ResourceType type)
+  {
+    switch (type)
+    {
+      case ResourceType_Patient:
+        return OrthancPluginResourceType_Patient;
+
+      case ResourceType_Study:
+        return OrthancPluginResourceType_Study;
+
+      case ResourceType_Series:
+        return OrthancPluginResourceType_Series;
+
+      case ResourceType_Instance:
+        return OrthancPluginResourceType_Instance;
+
+      default:
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
+
+
+  static OrthancPluginChangeType Convert(ChangeType type)
+  {
+    switch (type)
+    {
+      case ChangeType_AnonymizedPatient:
+        return OrthancPluginChangeType_AnonymizedPatient;
+
+      case ChangeType_AnonymizedSeries:
+        return OrthancPluginChangeType_AnonymizedSeries;
+
+      case ChangeType_AnonymizedStudy:
+        return OrthancPluginChangeType_AnonymizedStudy;
+
+      case ChangeType_CompletedSeries:
+        return OrthancPluginChangeType_CompletedSeries;
+
+      case ChangeType_Deleted:
+        return OrthancPluginChangeType_Deleted;
+
+      case ChangeType_ModifiedPatient:
+        return OrthancPluginChangeType_ModifiedPatient;
+
+      case ChangeType_ModifiedSeries:
+        return OrthancPluginChangeType_ModifiedSeries;
+
+      case ChangeType_ModifiedStudy:
+        return OrthancPluginChangeType_ModifiedStudy;
+
+      case ChangeType_NewInstance:
+        return OrthancPluginChangeType_NewInstance;
+
+      case ChangeType_NewPatient:
+        return OrthancPluginChangeType_NewPatient;
+
+      case ChangeType_NewSeries:
+        return OrthancPluginChangeType_NewSeries;
+
+      case ChangeType_NewStudy:
+        return OrthancPluginChangeType_NewStudy;
+
+      case ChangeType_StablePatient:
+        return OrthancPluginChangeType_StablePatient;
+
+      case ChangeType_StableSeries:
+        return OrthancPluginChangeType_StableSeries;
+
+      case ChangeType_StableStudy:
+        return OrthancPluginChangeType_StableStudy;
+
+      default:
+        throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
+
+
   OrthancPlugins::OrthancPlugins(ServerContext& context)
   {
     pimpl_.reset(new PImpl(context));
@@ -279,7 +358,7 @@
 
 
   void OrthancPlugins::SignalStoredInstance(DicomInstanceToStore& instance,
-                                                const std::string& instanceId)                                                  
+                                            const std::string& instanceId)                                                  
   {
     for (PImpl::OnStoredCallbacks::const_iterator
            callback = pimpl_->onStoredCallbacks_.begin(); 
@@ -292,6 +371,27 @@
 
 
 
+  void OrthancPlugins::SignalChange(ChangeType changeType,
+                                    ResourceType resourceType,
+                                    const std::string& publicId)
+  {
+    for (PImpl::OnChangeCallbacks::const_iterator
+           callback = pimpl_->onChangeCallbacks_.begin(); 
+         callback != pimpl_->onChangeCallbacks_.end(); ++callback)
+    {
+      try
+      {
+        (*callback) (Convert(changeType), Convert(resourceType), publicId.c_str());
+      }
+      catch (OrthancException&)
+      {
+        // This change type or resource type is not supported by the plugin SDK
+      }
+    }
+  }
+
+
+
   static void CopyToMemoryBuffer(OrthancPluginMemoryBuffer& target,
                                  const void* data,
                                  size_t size)
@@ -353,6 +453,16 @@
   }
 
 
+  void OrthancPlugins::RegisterOnChangeCallback(const void* parameters)
+  {
+    const _OrthancPluginOnChangeCallback& p = 
+      *reinterpret_cast<const _OrthancPluginOnChangeCallback*>(parameters);
+
+    LOG(INFO) << "Plugin has registered an OnChange callback";
+    pimpl_->onChangeCallbacks_.push_back(p.callback);
+  }
+
+
 
   void OrthancPlugins::AnswerBuffer(const void* parameters)
   {
@@ -777,6 +887,10 @@
         RegisterOnStoredInstanceCallback(parameters);
         return true;
 
+      case _OrthancPluginService_RegisterOnChangeCallback:
+        RegisterOnChangeCallback(parameters);
+        return true;
+
       case _OrthancPluginService_AnswerBuffer:
         AnswerBuffer(parameters);
         return true;
--- a/Plugins/Engine/OrthancPlugins.h	Mon Sep 22 14:11:37 2014 +0200
+++ b/Plugins/Engine/OrthancPlugins.h	Wed Sep 24 17:37:44 2014 +0200
@@ -53,6 +53,8 @@
 
     void RegisterOnStoredInstanceCallback(const void* parameters);
 
+    void RegisterOnChangeCallback(const void* parameters);
+
     void AnswerBuffer(const void* parameters);
 
     void Redirect(const void* parameters);
@@ -95,6 +97,10 @@
     virtual bool InvokeService(_OrthancPluginService service,
                                const void* parameters);
 
+    void SignalChange(ChangeType changeType,
+                      ResourceType resourceType,
+                      const std::string& publicId);
+
     void SignalStoredInstance(DicomInstanceToStore& instance,
                               const std::string& instanceId);
 
--- a/Plugins/OrthancCPlugin/OrthancCPlugin.h	Mon Sep 22 14:11:37 2014 +0200
+++ b/Plugins/OrthancCPlugin/OrthancCPlugin.h	Wed Sep 24 17:37:44 2014 +0200
@@ -88,7 +88,7 @@
 
 #define ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER     0
 #define ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER     8
-#define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER  3
+#define ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER  5
 
 
 
@@ -245,6 +245,7 @@
     _OrthancPluginService_RegisterRestCallback = 1000,
     _OrthancPluginService_RegisterOnStoredInstanceCallback = 1001,
     _OrthancPluginService_RegisterStorageArea = 1002,
+    _OrthancPluginService_RegisterOnChangeCallback = 1003,
 
     /* Sending answers to REST calls */
     _OrthancPluginService_AnswerBuffer = 2000,
@@ -341,6 +342,43 @@
 
 
   /**
+   * The supported type of DICOM resources.
+   **/
+  typedef enum
+  {
+    OrthancPluginResourceType_Patient = 0,     /*!< Patient */
+    OrthancPluginResourceType_Study = 1,       /*!< Study */
+    OrthancPluginResourceType_Series = 2,      /*!< Series */
+    OrthancPluginResourceType_Instance = 3     /*!< Instance */
+  } OrthancPluginResourceType;
+
+
+
+  /**
+   * The supported type of changes that can happen to DICOM resources.
+   **/
+  typedef enum
+  {
+    OrthancPluginChangeType_AnonymizedPatient = 0,  /*!< Patient resulting from an anomyization */
+    OrthancPluginChangeType_AnonymizedSeries = 1,   /*!< Series resulting from an anonymization */
+    OrthancPluginChangeType_AnonymizedStudy = 2,    /*!< Study resulting from an anomyization */
+    OrthancPluginChangeType_CompletedSeries = 3,    /*!< Series is now complete */
+    OrthancPluginChangeType_Deleted = 4,            /*!< Deleted resource */
+    OrthancPluginChangeType_ModifiedPatient = 5,    /*!< Patient resulting from a modification */
+    OrthancPluginChangeType_ModifiedSeries = 6,     /*!< Series resulting from a modification */
+    OrthancPluginChangeType_ModifiedStudy = 7,      /*!< Study resulting from a modification */
+    OrthancPluginChangeType_NewInstance = 8,        /*!< New instance received */
+    OrthancPluginChangeType_NewPatient = 9,         /*!< New patient created */
+    OrthancPluginChangeType_NewSeries = 10,         /*!< New series created */
+    OrthancPluginChangeType_NewStudy = 11,          /*!< New study created */
+    OrthancPluginChangeType_StablePatient = 12,     /*!< No new instance received for this patient */
+    OrthancPluginChangeType_StableSeries = 13,      /*!< No new instance received for this series */
+    OrthancPluginChangeType_StableStudy = 14        /*!< No new instance received for this study */
+  } OrthancPluginChangeType;
+
+
+
+  /**
    * @brief A memory buffer allocated by the core system of Orthanc.
    *
    * A memory buffer allocated by the core system of Orthanc. When the
@@ -397,6 +435,16 @@
 
 
   /**
+   * @brief Signature of a callback function that is triggered when a change happens to some DICOM resource.
+   **/
+  typedef int32_t (*OrthancPluginOnChangeCallback) (
+    OrthancPluginChangeType changeType,
+    OrthancPluginResourceType resourceType,
+    const char* resourceId);
+
+
+
+  /**
    * @brief Signature of a function to free dynamic memory.
    **/
   typedef void (*OrthancPluginFree) (void* buffer);
@@ -1642,6 +1690,33 @@
 
 
 
+  typedef struct
+  {
+    OrthancPluginOnChangeCallback callback;
+  } _OrthancPluginOnChangeCallback;
+
+  /**
+   * @brief Register a callback to monitor changes.
+   *
+   * This function registers a callback function that is called
+   * whenever a change happens to some DICOM resource.
+   * 
+   * @param context The Orthanc plugin context, as received by OrthancPluginInitialize().
+   * @param callback The callback function.
+   **/
+  ORTHANC_PLUGIN_INLINE void OrthancPluginRegisterOnChangeCallback(
+    OrthancPluginContext*          context,
+    OrthancPluginOnChangeCallback  callback)
+  {
+    _OrthancPluginOnChangeCallback params;
+    params.callback = callback;
+
+    context->InvokeService(context, _OrthancPluginService_RegisterOnChangeCallback, &params);
+  }
+
+
+
+
 #ifdef  __cplusplus
 }
 #endif
--- a/UnitTestsSources/ServerIndexTests.cpp	Mon Sep 22 14:11:37 2014 +0200
+++ b/UnitTestsSources/ServerIndexTests.cpp	Wed Sep 24 17:37:44 2014 +0200
@@ -82,13 +82,19 @@
       LOG(INFO) << "A file must be removed: " << fileUuid;
     }       
 
-    virtual void SignalResourceDeleted(ResourceType type,
-                                       const std::string& publicId)
+    virtual void SignalChange(ChangeType changeType,
+                              ResourceType resourceType,
+                              const std::string& publicId)
     {
-      deletedResources_.push_back(publicId);
-      LOG(INFO) << "A resource was removed: " << publicId;
+      if (changeType == ChangeType_Deleted)
+      {
+        deletedResources_.push_back(publicId);        
+      }
+
+      LOG(INFO) << "Change related to resource " << publicId << " of type " 
+                << EnumerationToString(resourceType) << ": " << EnumerationToString(changeType);
     }
-                         
+
   };