comparison OrthancServer/ServerIndex.cpp @ 278:771f12042be9

more efficient determination of storage size for recycling
author Sebastien Jodogne <s.jodogne@gmail.com>
date Sun, 09 Dec 2012 21:51:57 +0100
parents d384af918264
children 4eea080e6e7a
comparison
equal deleted inserted replaced
277:58f969933720 278:771f12042be9
58 ServerContext& context_; 58 ServerContext& context_;
59 bool hasRemainingLevel_; 59 bool hasRemainingLevel_;
60 ResourceType remainingType_; 60 ResourceType remainingType_;
61 std::string remainingPublicId_; 61 std::string remainingPublicId_;
62 std::list<std::string> pendingFilesToRemove_; 62 std::list<std::string> pendingFilesToRemove_;
63 uint64_t sizeOfFilesToRemove_;
63 64
64 public: 65 public:
65 ServerIndexListener(ServerContext& context) : 66 ServerIndexListener(ServerContext& context) :
66 context_(context), 67 context_(context)
67 hasRemainingLevel_(false) 68 {
68 { 69 Reset();
69 assert(ResourceType_Patient < ResourceType_Study && 70 assert(ResourceType_Patient < ResourceType_Study &&
70 ResourceType_Study < ResourceType_Series && 71 ResourceType_Study < ResourceType_Series &&
71 ResourceType_Series < ResourceType_Instance); 72 ResourceType_Series < ResourceType_Instance);
72 } 73 }
73 74
74 void Reset() 75 void Reset()
75 { 76 {
77 sizeOfFilesToRemove_ = 0;
76 hasRemainingLevel_ = false; 78 hasRemainingLevel_ = false;
77 pendingFilesToRemove_.clear(); 79 pendingFilesToRemove_.clear();
80 }
81
82 uint64_t GetSizeOfFilesToRemove()
83 {
84 return sizeOfFilesToRemove_;
78 } 85 }
79 86
80 void CommitFilesToRemove() 87 void CommitFilesToRemove()
81 { 88 {
82 for (std::list<std::string>::iterator 89 for (std::list<std::string>::iterator
110 117
111 virtual void SignalFileDeleted(const FileInfo& info) 118 virtual void SignalFileDeleted(const FileInfo& info)
112 { 119 {
113 assert(Toolbox::IsUuid(info.GetUuid())); 120 assert(Toolbox::IsUuid(info.GetUuid()));
114 pendingFilesToRemove_.push_back(info.GetUuid()); 121 pendingFilesToRemove_.push_back(info.GetUuid());
122 sizeOfFilesToRemove_ += info.GetCompressedSize();
115 } 123 }
116 124
117 bool HasRemainingLevel() const 125 bool HasRemainingLevel() const
118 { 126 {
119 return hasRemainingLevel_; 127 return hasRemainingLevel_;
132 } 140 }
133 }; 141 };
134 } 142 }
135 143
136 144
145 class ServerIndex::Transaction
146 {
147 private:
148 ServerIndex& index_;
149 std::auto_ptr<SQLite::Transaction> transaction_;
150 bool isCommitted_;
151
152 public:
153 Transaction(ServerIndex& index) :
154 index_(index),
155 isCommitted_(false)
156 {
157 assert(index_.currentStorageSize_ == index_.db_->GetTotalCompressedSize());
158
159 index_.listener_->Reset();
160 transaction_.reset(index_.db_->StartTransaction());
161 transaction_->Begin();
162 }
163
164 void Commit(uint64_t sizeOfAddedFiles)
165 {
166 if (!isCommitted_)
167 {
168 transaction_->Commit();
169
170 // We can remove the files once the SQLite transaction has
171 // been successfully committed. Some files might have to be
172 // deleted because of recycling.
173 index_.listener_->CommitFilesToRemove();
174
175 index_.currentStorageSize_ += sizeOfAddedFiles;
176
177 assert(index_.currentStorageSize_ >= index_.listener_->GetSizeOfFilesToRemove());
178 index_.currentStorageSize_ -= index_.listener_->GetSizeOfFilesToRemove();
179
180 assert(index_.currentStorageSize_ == index_.db_->GetTotalCompressedSize());
181
182 isCommitted_ = true;
183 }
184 }
185 };
186
187
137 bool ServerIndex::DeleteResource(Json::Value& target, 188 bool ServerIndex::DeleteResource(Json::Value& target,
138 const std::string& uuid, 189 const std::string& uuid,
139 ResourceType expectedType) 190 ResourceType expectedType)
140 { 191 {
141 boost::mutex::scoped_lock lock(mutex_); 192 boost::mutex::scoped_lock lock(mutex_);
142 listener_->Reset(); 193 listener_->Reset();
143 194
144 std::auto_ptr<SQLite::Transaction> t(db_->StartTransaction()); 195 Transaction t(*this);
145 t->Begin();
146 196
147 int64_t id; 197 int64_t id;
148 ResourceType type; 198 ResourceType type;
149 if (!db_->LookupResource(uuid, id, type) || 199 if (!db_->LookupResource(uuid, id, type) ||
150 expectedType != type) 200 expectedType != type)
167 else 217 else
168 { 218 {
169 target["RemainingAncestor"] = Json::nullValue; 219 target["RemainingAncestor"] = Json::nullValue;
170 } 220 }
171 221
172 t->Commit(); 222 t.Commit(0);
173
174 // We can remove the files once the SQLite transaction has been
175 // successfully committed
176 listener_->CommitFilesToRemove();
177 223
178 return true; 224 return true;
179 } 225 }
180 226
181 227
218 } 264 }
219 265
220 db_.reset(new DatabaseWrapper(p.string() + "/index", *listener_)); 266 db_.reset(new DatabaseWrapper(p.string() + "/index", *listener_));
221 } 267 }
222 268
269 currentStorageSize_ = db_->GetTotalCompressedSize();
270
223 // Initial recycling if the parameters have changed since the last 271 // Initial recycling if the parameters have changed since the last
224 // execution of Orthanc 272 // execution of Orthanc
225 StandaloneRecycling(); 273 StandaloneRecycling();
226 274
227 unsigned int sleep; 275 unsigned int sleep;
257 305
258 DicomInstanceHasher hasher(dicomSummary); 306 DicomInstanceHasher hasher(dicomSummary);
259 307
260 try 308 try
261 { 309 {
262 std::auto_ptr<SQLite::Transaction> t(db_->StartTransaction()); 310 Transaction t(*this);
263 t->Begin();
264 311
265 int64_t patient, study, series, instance; 312 int64_t patient, study, series, instance;
266 ResourceType type; 313 ResourceType type;
267 bool isNewSeries = false; 314 bool isNewSeries = false;
268 315
367 if (seriesStatus == SeriesStatus_Complete) 414 if (seriesStatus == SeriesStatus_Complete)
368 { 415 {
369 db_->LogChange(ChangeType_CompletedSeries, series, ResourceType_Series); 416 db_->LogChange(ChangeType_CompletedSeries, series, ResourceType_Series);
370 } 417 }
371 418
372 t->Commit(); 419 t.Commit(instanceSize);
373
374 // We can remove the files once the SQLite transaction has been
375 // successfully committed. Some files might have to be deleted
376 // because of recycling.
377 listener_->CommitFilesToRemove();
378 420
379 return StoreStatus_Success; 421 return StoreStatus_Success;
380 } 422 }
381 catch (OrthancException& e) 423 catch (OrthancException& e)
382 { 424 {
393 static const uint64_t MB = 1024 * 1024; 435 static const uint64_t MB = 1024 * 1024;
394 436
395 boost::mutex::scoped_lock lock(mutex_); 437 boost::mutex::scoped_lock lock(mutex_);
396 target = Json::objectValue; 438 target = Json::objectValue;
397 439
398 uint64_t cs = db_->GetTotalCompressedSize(); 440 uint64_t cs = currentStorageSize_;
441 assert(cs == db_->GetTotalCompressedSize());
399 uint64_t us = db_->GetTotalUncompressedSize(); 442 uint64_t us = db_->GetTotalUncompressedSize();
400 target["TotalDiskSpace"] = boost::lexical_cast<std::string>(cs); 443 target["TotalDiskSpace"] = boost::lexical_cast<std::string>(cs);
401 target["TotalUncompressedSize"] = boost::lexical_cast<std::string>(us); 444 target["TotalUncompressedSize"] = boost::lexical_cast<std::string>(us);
402 target["TotalDiskSpaceMB"] = boost::lexical_cast<unsigned int>(cs / MB); 445 target["TotalDiskSpaceMB"] = boost::lexical_cast<unsigned int>(cs / MB);
403 target["TotalUncompressedSizeMB"] = boost::lexical_cast<unsigned int>(us / MB); 446 target["TotalUncompressedSizeMB"] = boost::lexical_cast<unsigned int>(us / MB);
766 809
767 bool ServerIndex::IsRecyclingNeeded(uint64_t instanceSize) 810 bool ServerIndex::IsRecyclingNeeded(uint64_t instanceSize)
768 { 811 {
769 if (maximumStorageSize_ != 0) 812 if (maximumStorageSize_ != 0)
770 { 813 {
771 uint64_t currentSize = db_->GetTotalCompressedSize(); 814 uint64_t currentSize = currentStorageSize_ - listener_->GetSizeOfFilesToRemove();
815 assert(db_->GetTotalCompressedSize() == currentSize);
816
772 if (currentSize + instanceSize > maximumStorageSize_) 817 if (currentSize + instanceSize > maximumStorageSize_)
773 { 818 {
774 return true; 819 return true;
775 } 820 }
776 } 821 }
869 } 914 }
870 915
871 void ServerIndex::StandaloneRecycling() 916 void ServerIndex::StandaloneRecycling()
872 { 917 {
873 // WARNING: No mutex here, do not include this as a public method 918 // WARNING: No mutex here, do not include this as a public method
874 std::auto_ptr<SQLite::Transaction> t(db_->StartTransaction()); 919 Transaction t(*this);
875 t->Begin();
876 Recycle(0, ""); 920 Recycle(0, "");
877 t->Commit(); 921 t.Commit(0);
878 listener_->CommitFilesToRemove();
879 } 922 }
880 923
881 924
882 bool ServerIndex::IsProtectedPatient(const std::string& publicId) 925 bool ServerIndex::IsProtectedPatient(const std::string& publicId)
883 { 926 {