changeset 268:4bc02e2254ec

preparing ServerIndex for recycling
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 07 Dec 2012 13:43:35 +0100
parents a08dca15790e
children f6fdf5abe751
files Core/Enumerations.h Core/OrthancException.cpp OrthancServer/DatabaseWrapper.cpp OrthancServer/DatabaseWrapper.h OrthancServer/ServerIndex.cpp OrthancServer/ServerIndex.h UnitTests/ServerIndex.cpp
diffstat 7 files changed, 74 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/Core/Enumerations.h	Fri Dec 07 13:19:42 2012 +0100
+++ b/Core/Enumerations.h	Fri Dec 07 13:43:35 2012 +0100
@@ -55,7 +55,8 @@
     ErrorCode_BadFileFormat,
     ErrorCode_Timeout,
     ErrorCode_UnknownResource,
-    ErrorCode_IncompatibleDatabaseVersion
+    ErrorCode_IncompatibleDatabaseVersion,
+    ErrorCode_FullStorage
   };
 
   enum PixelFormat
--- a/Core/OrthancException.cpp	Fri Dec 07 13:19:42 2012 +0100
+++ b/Core/OrthancException.cpp	Fri Dec 07 13:43:35 2012 +0100
@@ -93,6 +93,9 @@
       case ErrorCode_IncompatibleDatabaseVersion:
         return "Incompatible version of the database";
 
+      case ErrorCode_FullStorage:
+        return "The file storage is full";
+
       case ErrorCode_Custom:
       default:
         return "???";
--- a/OrthancServer/DatabaseWrapper.cpp	Fri Dec 07 13:19:42 2012 +0100
+++ b/OrthancServer/DatabaseWrapper.cpp	Fri Dec 07 13:43:35 2012 +0100
@@ -795,6 +795,26 @@
     }    
   }
 
+  bool DatabaseWrapper::SelectPatientToRecycle(int64_t& internalId,
+                                               int64_t patientIdToAvoid)
+  {
+    SQLite::Statement s(db_, SQLITE_FROM_HERE,
+                        "SELECT patientId FROM PatientRecyclingOrder "
+                        "WHERE patientId != ? ORDER BY seq ASC LIMIT 1");
+    s.BindInt(0, patientIdToAvoid);
+
+    if (!s.Step())
+    {
+      // No patient remaining or all the patients are protected
+      return false;
+    }
+    else
+    {
+      internalId = s.ColumnInt(0);
+      return true;
+    }   
+  }
+
   bool DatabaseWrapper::IsProtectedPatient(int64_t internalId)
   {
     SQLite::Statement s(db_, SQLITE_FROM_HERE,
--- a/OrthancServer/DatabaseWrapper.h	Fri Dec 07 13:19:42 2012 +0100
+++ b/OrthancServer/DatabaseWrapper.h	Fri Dec 07 13:43:35 2012 +0100
@@ -181,6 +181,9 @@
 
     bool SelectPatientToRecycle(int64_t& internalId);
 
+    bool SelectPatientToRecycle(int64_t& internalId,
+                                int64_t patientIdToAvoid);
+
     bool IsProtectedPatient(int64_t internalId);
 
     void SetProtectedPatient(int64_t internalId, 
--- a/OrthancServer/ServerIndex.cpp	Fri Dec 07 13:19:42 2012 +0100
+++ b/OrthancServer/ServerIndex.cpp	Fri Dec 07 13:43:35 2012 +0100
@@ -139,7 +139,6 @@
                                    ResourceType expectedType)
   {
     boost::mutex::scoped_lock lock(mutex_);
-
     listener_->Reset();
 
     std::auto_ptr<SQLite::Transaction> t(db_->StartTransaction());
@@ -248,6 +247,7 @@
                                  const std::string& remoteAet)
   {
     boost::mutex::scoped_lock lock(mutex_);
+    listener_->Reset();
 
     DicomInstanceHasher hasher(dicomSummary);
 
@@ -267,6 +267,16 @@
         return StoreStatus_AlreadyStored;
       }
 
+      // Ensure there is enough room in the storage for the new instance
+      uint64_t instanceSize = 0;
+      for (Attachments::const_iterator it = attachments.begin();
+           it != attachments.end(); it++)
+      {
+        instanceSize += it->GetCompressedSize();
+      }
+
+      Recycle(instanceSize, hasher.HashPatient());
+
       // Create the instance
       instance = db_->CreateResource(hasher.HashInstance(), ResourceType_Instance);
 
@@ -355,11 +365,17 @@
 
       t->Commit();
 
+      // We can remove the files once the SQLite transaction has been
+      // successfully committed. Some files might have to be deleted
+      // because of recycling.
+      listener_->CommitFilesToRemove();
+
       return StoreStatus_Success;
     }
     catch (OrthancException& e)
     {
-      LOG(ERROR) << "EXCEPTION2 [" << e.What() << "]" << " " << db_->GetErrorMessage();  
+      LOG(ERROR) << "EXCEPTION [" << e.What() << "]" 
+                 << " (SQLite status: " << db_->GetErrorMessage() << ")";
     }
 
     return StoreStatus_Failure;
@@ -740,4 +756,23 @@
     db_->GetLastExportedResource(target);
     return true;
   }
+
+
+  bool ServerIndex::IsRecyclingNeeded(uint64_t instanceSize)
+  {
+    return false;
+  }
+
+  
+  void ServerIndex::Recycle(uint64_t instanceSize,
+                            const std::string& newPatientId)
+  {
+    if (!IsRecyclingNeeded(instanceSize))
+    {
+      return;
+    }
+
+
+    //throw OrthancException(ErrorCode_FullStorage);
+  }  
 }
--- a/OrthancServer/ServerIndex.h	Fri Dec 07 13:19:42 2012 +0100
+++ b/OrthancServer/ServerIndex.h	Fri Dec 07 13:43:35 2012 +0100
@@ -67,6 +67,11 @@
 
     SeriesStatus GetSeriesStatus(int id);
 
+    bool IsRecyclingNeeded(uint64_t instanceSize);
+
+    void Recycle(uint64_t instanceSize,
+                 const std::string& newPatientId);
+
   public:
     typedef std::list<FileInfo> Attachments;
 
--- a/UnitTests/ServerIndex.cpp	Fri Dec 07 13:19:42 2012 +0100
+++ b/UnitTests/ServerIndex.cpp	Fri Dec 07 13:43:35 2012 +0100
@@ -369,10 +369,12 @@
   int64_t p;
   ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[0]);
   index.DeleteResource(p);
+  ASSERT_TRUE(index.SelectPatientToRecycle(p, patients[1])); ASSERT_EQ(p, patients[4]);
   ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[1]);
   index.DeleteResource(p);
   ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[4]);
   index.DeleteResource(p);
+  ASSERT_FALSE(index.SelectPatientToRecycle(p, patients[2]));
   ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[2]);
   index.DeleteResource(p);
   // "patients[3]" is still protected
@@ -384,6 +386,8 @@
 
   index.SetProtectedPatient(patients[3], false);
   ASSERT_EQ(1u, index.GetTableRecordCount("PatientRecyclingOrder")); 
+  ASSERT_FALSE(index.SelectPatientToRecycle(p, patients[3]));
+  ASSERT_TRUE(index.SelectPatientToRecycle(p, patients[2]));
   ASSERT_TRUE(index.SelectPatientToRecycle(p)); ASSERT_EQ(p, patients[3]);
   index.DeleteResource(p);