# HG changeset patch # User Sebastien Jodogne # Date 1355086317 -3600 # Node ID 771f12042be92e63dcf62a19fdd300d1d9f34332 # Parent 58f96993372082d677dc322c3737b651405adb11 more efficient determination of storage size for recycling diff -r 58f969933720 -r 771f12042be9 OrthancServer/ServerIndex.cpp --- a/OrthancServer/ServerIndex.cpp Sun Dec 09 15:03:17 2012 +0100 +++ b/OrthancServer/ServerIndex.cpp Sun Dec 09 21:51:57 2012 +0100 @@ -60,12 +60,13 @@ ResourceType remainingType_; std::string remainingPublicId_; std::list pendingFilesToRemove_; + uint64_t sizeOfFilesToRemove_; public: ServerIndexListener(ServerContext& context) : - context_(context), - hasRemainingLevel_(false) + context_(context) { + Reset(); assert(ResourceType_Patient < ResourceType_Study && ResourceType_Study < ResourceType_Series && ResourceType_Series < ResourceType_Instance); @@ -73,10 +74,16 @@ void Reset() { + sizeOfFilesToRemove_ = 0; hasRemainingLevel_ = false; pendingFilesToRemove_.clear(); } + uint64_t GetSizeOfFilesToRemove() + { + return sizeOfFilesToRemove_; + } + void CommitFilesToRemove() { for (std::list::iterator @@ -112,6 +119,7 @@ { assert(Toolbox::IsUuid(info.GetUuid())); pendingFilesToRemove_.push_back(info.GetUuid()); + sizeOfFilesToRemove_ += info.GetCompressedSize(); } bool HasRemainingLevel() const @@ -134,6 +142,49 @@ } + class ServerIndex::Transaction + { + private: + ServerIndex& index_; + std::auto_ptr transaction_; + bool isCommitted_; + + public: + Transaction(ServerIndex& index) : + index_(index), + isCommitted_(false) + { + assert(index_.currentStorageSize_ == index_.db_->GetTotalCompressedSize()); + + index_.listener_->Reset(); + transaction_.reset(index_.db_->StartTransaction()); + transaction_->Begin(); + } + + void Commit(uint64_t sizeOfAddedFiles) + { + if (!isCommitted_) + { + transaction_->Commit(); + + // We can remove the files once the SQLite transaction has + // been successfully committed. Some files might have to be + // deleted because of recycling. + index_.listener_->CommitFilesToRemove(); + + index_.currentStorageSize_ += sizeOfAddedFiles; + + assert(index_.currentStorageSize_ >= index_.listener_->GetSizeOfFilesToRemove()); + index_.currentStorageSize_ -= index_.listener_->GetSizeOfFilesToRemove(); + + assert(index_.currentStorageSize_ == index_.db_->GetTotalCompressedSize()); + + isCommitted_ = true; + } + } + }; + + bool ServerIndex::DeleteResource(Json::Value& target, const std::string& uuid, ResourceType expectedType) @@ -141,8 +192,7 @@ boost::mutex::scoped_lock lock(mutex_); listener_->Reset(); - std::auto_ptr t(db_->StartTransaction()); - t->Begin(); + Transaction t(*this); int64_t id; ResourceType type; @@ -169,11 +219,7 @@ target["RemainingAncestor"] = Json::nullValue; } - t->Commit(); - - // We can remove the files once the SQLite transaction has been - // successfully committed - listener_->CommitFilesToRemove(); + t.Commit(0); return true; } @@ -220,6 +266,8 @@ db_.reset(new DatabaseWrapper(p.string() + "/index", *listener_)); } + currentStorageSize_ = db_->GetTotalCompressedSize(); + // Initial recycling if the parameters have changed since the last // execution of Orthanc StandaloneRecycling(); @@ -259,8 +307,7 @@ try { - std::auto_ptr t(db_->StartTransaction()); - t->Begin(); + Transaction t(*this); int64_t patient, study, series, instance; ResourceType type; @@ -369,12 +416,7 @@ db_->LogChange(ChangeType_CompletedSeries, series, ResourceType_Series); } - 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(); + t.Commit(instanceSize); return StoreStatus_Success; } @@ -395,7 +437,8 @@ boost::mutex::scoped_lock lock(mutex_); target = Json::objectValue; - uint64_t cs = db_->GetTotalCompressedSize(); + uint64_t cs = currentStorageSize_; + assert(cs == db_->GetTotalCompressedSize()); uint64_t us = db_->GetTotalUncompressedSize(); target["TotalDiskSpace"] = boost::lexical_cast(cs); target["TotalUncompressedSize"] = boost::lexical_cast(us); @@ -768,7 +811,9 @@ { if (maximumStorageSize_ != 0) { - uint64_t currentSize = db_->GetTotalCompressedSize(); + uint64_t currentSize = currentStorageSize_ - listener_->GetSizeOfFilesToRemove(); + assert(db_->GetTotalCompressedSize() == currentSize); + if (currentSize + instanceSize > maximumStorageSize_) { return true; @@ -871,11 +916,9 @@ void ServerIndex::StandaloneRecycling() { // WARNING: No mutex here, do not include this as a public method - std::auto_ptr t(db_->StartTransaction()); - t->Begin(); + Transaction t(*this); Recycle(0, ""); - t->Commit(); - listener_->CommitFilesToRemove(); + t.Commit(0); } diff -r 58f969933720 -r 771f12042be9 OrthancServer/ServerIndex.h --- a/OrthancServer/ServerIndex.h Sun Dec 09 15:03:17 2012 +0100 +++ b/OrthancServer/ServerIndex.h Sun Dec 09 21:51:57 2012 +0100 @@ -51,17 +51,18 @@ class ServerIndexListener; } - - class ServerIndex : public boost::noncopyable { private: + class Transaction; + boost::mutex mutex_; boost::thread flushThread_; std::auto_ptr listener_; std::auto_ptr db_; + uint64_t currentStorageSize_; uint64_t maximumStorageSize_; unsigned int maximumPatients_;