changeset 201:bee20e978835

refactoring of delete
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 27 Nov 2012 17:36:19 +0100
parents 9c58b2b03cf0
children 1650557bd81a
files Core/FileStorage.cpp OrthancExplorer/explorer.js OrthancServer/ServerEnumerations.cpp OrthancServer/ServerEnumerations.h OrthancServer/ServerIndex.cpp OrthancServer/ServerIndex.h OrthancServer/main.cpp
diffstat 7 files changed, 155 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/Core/FileStorage.cpp	Tue Nov 27 16:49:22 2012 +0100
+++ b/Core/FileStorage.cpp	Tue Nov 27 17:36:19 2012 +0100
@@ -40,6 +40,7 @@
 #include "Uuid.h"
 
 #include <boost/filesystem/fstream.hpp>
+#include <glog/logging.h>
 
 static std::string ToString(const boost::filesystem::path& p)
 {
@@ -275,6 +276,7 @@
 
   void FileStorage::Remove(const std::string& uuid)
   {
+    LOG(INFO) << "Deleting file " << uuid;
     namespace fs = boost::filesystem;
 
     fs::path p = GetPath(uuid);
--- a/OrthancExplorer/explorer.js	Tue Nov 27 16:49:22 2012 +0100
+++ b/OrthancExplorer/explorer.js	Tue Nov 27 17:36:19 2012 +0100
@@ -557,7 +557,7 @@
       if (ancestor == null)
         $.mobile.changePage('#find-patients');
       else
-        $.mobile.changePage('#' + ancestor.Type + '?uuid=' + ancestor.ID);
+        $.mobile.changePage('#' + ancestor.Type.toLowerCase() + '?uuid=' + ancestor.ID);
     }
   });
 }
--- a/OrthancServer/ServerEnumerations.cpp	Tue Nov 27 16:49:22 2012 +0100
+++ b/OrthancServer/ServerEnumerations.cpp	Tue Nov 27 17:36:19 2012 +0100
@@ -56,6 +56,27 @@
     }
   }
 
+  const char* GetBasePath(ResourceType type)
+  {
+    switch (type)
+    {
+    case ResourceType_Patient:
+      return "patients";
+
+    case ResourceType_Study:
+      return "studies";
+
+    case ResourceType_Series:
+      return "series";
+
+    case ResourceType_Instance:
+      return "instances";
+      
+    default:
+      throw OrthancException(ErrorCode_ParameterOutOfRange);
+    }
+  }
+
   const char* ToString(SeriesStatus status)
   {
     switch (status)
--- a/OrthancServer/ServerEnumerations.h	Tue Nov 27 16:49:22 2012 +0100
+++ b/OrthancServer/ServerEnumerations.h	Tue Nov 27 17:36:19 2012 +0100
@@ -88,5 +88,7 @@
 
   const char* ToString(ResourceType type);
 
+  const char* GetBasePath(ResourceType type);
+
   const char* ToString(SeriesStatus status);
 }
--- a/OrthancServer/ServerIndex.cpp	Tue Nov 27 16:49:22 2012 +0100
+++ b/OrthancServer/ServerIndex.cpp	Tue Nov 27 17:36:19 2012 +0100
@@ -53,18 +53,84 @@
 {
   namespace Internals
   {
+    class ServerIndexListenerTodo : public IServerIndexListener
+    {
+    private:
+      FileStorage& fileStorage_;
+      bool hasRemainingLevel_;
+      ResourceType remainingType_;
+      std::string remainingPublicId_;
+
+    public:
+      ServerIndexListenerTodo(FileStorage& fileStorage) : 
+        fileStorage_(fileStorage),
+        hasRemainingLevel_(false)
+      {
+        assert(ResourceType_Patient < ResourceType_Study &&
+               ResourceType_Study < ResourceType_Series &&
+               ResourceType_Series < ResourceType_Instance);
+      }
+
+      void Reset()
+      {
+        hasRemainingLevel_ = false;
+      }
+
+      virtual void SignalRemainingAncestor(ResourceType parentType,
+                                           const std::string& publicId)
+      {
+        LOG(INFO) << "Remaining ancestor \"" << publicId << "\" (" << parentType << ")";
+
+        if (hasRemainingLevel_)
+        {
+          if (parentType < remainingType_)
+          {
+            remainingType_ = parentType;
+            remainingPublicId_ = publicId;
+          }
+        }
+        else
+        {
+          hasRemainingLevel_ = true;
+          remainingType_ = parentType;
+          remainingPublicId_ = publicId;
+        }        
+      }
+
+      virtual void SignalFileDeleted(const std::string& fileUuid)
+      {
+        assert(Toolbox::IsUuid(fileUuid));
+        fileStorage_.Remove(fileUuid);
+      }
+
+      bool HasRemainingLevel() const
+      {
+        return hasRemainingLevel_;
+      }
+
+      ResourceType GetRemainingType() const
+      {
+        assert(HasRemainingLevel());
+        return remainingType_;
+      }
+
+      const std::string& GetRemainingPublicId() const
+      {
+        assert(HasRemainingLevel());
+        return remainingPublicId_;
+      }                                 
+    };
+
+
     class DeleteFromFileStorageFunction : public SQLite::IScalarFunction
     {
     private:
-      std::auto_ptr<FileStorage> fileStorage_;
+      FileStorage& fileStorage_;
 
     public:
-      DeleteFromFileStorageFunction(const std::string& path)
+      DeleteFromFileStorageFunction(FileStorage& fileStorage) : 
+        fileStorage_(fileStorage)
       {
-        if (path != ":memory:")
-        {
-          fileStorage_.reset(new FileStorage(path));
-        }
       }
 
       virtual const char* GetName() const
@@ -79,18 +145,12 @@
 
       virtual void Compute(SQLite::FunctionContext& context)
       {
-        if (fileStorage_.get() == NULL)
-        {
-          // In-memory index, for unit tests
-          return;
-        }
-
         std::string fileUuid = context.GetStringValue(0);
         LOG(INFO) << "Removing file [" << fileUuid << "]";
 
         if (Toolbox::IsUuid(fileUuid))
         {
-          fileStorage_->Remove(fileUuid);
+          fileStorage_.Remove(fileUuid);
         }
       }
     };
@@ -350,6 +410,46 @@
   {
     boost::mutex::scoped_lock scoped_lock(mutex_);
 
+
+    {
+      listener2_->Reset();
+
+      std::auto_ptr<SQLite::Transaction> t(db2_->StartTransaction());
+      t->Begin();
+
+      int64_t id;
+      ResourceType type;
+      if (!db2_->LookupResource(uuid, id, type))
+      {
+        return false;
+      }
+      
+      db2_->DeleteResource(id);
+
+      if (listener2_->HasRemainingLevel())
+      {
+        ResourceType type = listener2_->GetRemainingType();
+        const std::string& uuid = listener2_->GetRemainingPublicId();
+
+        target["RemainingAncestor"] = Json::Value(Json::objectValue);
+        target["RemainingAncestor"]["Path"] = std::string(GetBasePath(type)) + "/" + uuid;
+        target["RemainingAncestor"]["Type"] = ToString(type);
+        target["RemainingAncestor"]["ID"] = uuid;
+      }
+      else
+      {
+        target["RemainingAncestor"] = Json::nullValue;
+      }
+
+      std::cout << target << std::endl;
+
+      t->Commit();
+
+      return true;
+    }
+
+
+
     deletedLevels_->Clear();
 
     SQLite::Statement s(db_, "DELETE FROM " + tableName + " WHERE uuid=?");
@@ -385,42 +485,23 @@
   }
 
 
-  namespace Internals
+  ServerIndex::ServerIndex(FileStorage& fileStorage,
+                           const std::string& dbPath)
   {
-    class ServerIndexListenerTodo : public IServerIndexListener
-    {
-    public:
-      virtual void SignalRemainingAncestor(ResourceType parentType,
-                                           const std::string& publicId)
-      {
-        LOG(INFO) << "Remaning ancestor \"" << publicId << "\" (" << parentType << ")";
-      }
+    listener2_.reset(new Internals::ServerIndexListenerTodo(fileStorage));
 
-      virtual void SignalFileDeleted(const std::string& fileUuid)
-      {
-        LOG(INFO) << "Deleted file " << fileUuid;
-      }
-                                 
-    };
-  }
-
-
-  ServerIndex::ServerIndex(const std::string& storagePath)
-  {
-    listener2_.reset(new Internals::ServerIndexListenerTodo);
-
-    if (storagePath == ":memory:")
+    if (dbPath == ":memory:")
     {
       db_.OpenInMemory();
       db2_.reset(new DatabaseWrapper(*listener2_));
     }
     else
     {
-      boost::filesystem::path p = storagePath;
+      boost::filesystem::path p = dbPath;
 
       try
       {
-        boost::filesystem::create_directories(storagePath);
+        boost::filesystem::create_directories(p);
       }
       catch (boost::filesystem::filesystem_error)
       {
@@ -432,7 +513,7 @@
       db_.Open(p.string());
     }
 
-    db_.Register(new Internals::DeleteFromFileStorageFunction(storagePath));
+    db_.Register(new Internals::DeleteFromFileStorageFunction(fileStorage));
     deletedLevels_ = (Internals::SignalDeletedLevelFunction*) 
       db_.Register(new Internals::SignalDeletedLevelFunction);
 
--- a/OrthancServer/ServerIndex.h	Tue Nov 27 16:49:22 2012 +0100
+++ b/OrthancServer/ServerIndex.h	Tue Nov 27 17:36:19 2012 +0100
@@ -47,6 +47,7 @@
   namespace Internals
   {
     class SignalDeletedLevelFunction;
+    class ServerIndexListenerTodo;
   }
 
 
@@ -56,7 +57,7 @@
     SQLite::Connection db_;
     boost::mutex mutex_;
 
-    std::auto_ptr<IServerIndexListener> listener2_;
+    std::auto_ptr<Internals::ServerIndexListenerTodo> listener2_;
     std::auto_ptr<DatabaseWrapper> db2_;
 
     // DO NOT delete the following one, SQLite::Connection will do it automatically
@@ -114,7 +115,8 @@
     SeriesStatus GetSeriesStatus(int id);
 
   public:
-    ServerIndex(const std::string& storagePath);
+    ServerIndex(FileStorage& fileStorage,
+                const std::string& dbPath);
 
     StoreStatus Store(const DicomMap& dicomSummary,
                       const std::string& fileUuid,
--- a/OrthancServer/main.cpp	Tue Nov 27 16:49:22 2012 +0100
+++ b/OrthancServer/main.cpp	Tue Nov 27 17:36:19 2012 +0100
@@ -217,9 +217,10 @@
       OrthancInitialize();
     }
 
-    std::string storageDirectory = GetGlobalStringParameter("StorageDirectory", "OrthancStorage");
-    ServerIndex index(storageDirectory);
-    MyDicomStoreFactory storeScp(index, storageDirectory);
+    boost::filesystem::path storageDirectory = GetGlobalStringParameter("StorageDirectory", "OrthancStorage");
+    FileStorage storage(storageDirectory.string());
+    ServerIndex index(storage, storageDirectory.string());
+    MyDicomStoreFactory storeScp(index, storageDirectory.string());
 
     {
       // DICOM server
@@ -257,7 +258,7 @@
       httpServer.RegisterHandler(new FilesystemHttpHandler("/app", ORTHANC_PATH "/OrthancExplorer"));
 #endif
 
-      httpServer.RegisterHandler(new OrthancRestApi(index, storageDirectory));
+      httpServer.RegisterHandler(new OrthancRestApi(index, storageDirectory.string()));
 
       // GO !!!
       httpServer.Start();