Mercurial > hg > orthanc-webviewer
annotate Plugin/Cache/CacheManager.cpp @ 296:d179f3928342
removed "using namespace Orthanc"
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Sat, 30 Jan 2021 12:26:50 +0100 |
parents | fc57bf7c0c83 |
children | fb7d62e3235e |
rev | line source |
---|---|
0 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
122 | 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics |
0 | 4 * Department, University Hospital of Liege, Belgium |
293
e376158e2dbb
upgrade to year 2021
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
266
diff
changeset
|
5 * Copyright (C) 2017-2021 Osimis S.A., Belgium |
0 | 6 * |
7 * This program is free software: you can redistribute it and/or | |
8 * modify it under the terms of the GNU Affero General Public License | |
9 * as published by the Free Software Foundation, either version 3 of | |
10 * the License, or (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Affero General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Affero General Public License | |
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 **/ | |
20 | |
21 | |
22 #include "CacheManager.h" | |
23 | |
266
4e9d30c19b4b
linking against orthanc framework library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
226
diff
changeset
|
24 #include <Compatibility.h> |
4e9d30c19b4b
linking against orthanc framework library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
226
diff
changeset
|
25 #include <Toolbox.h> |
4e9d30c19b4b
linking against orthanc framework library
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
226
diff
changeset
|
26 #include <SQLite/Transaction.h> |
0 | 27 |
28 #include <boost/lexical_cast.hpp> | |
29 | |
30 | |
31 namespace OrthancPlugins | |
32 { | |
33 class CacheManager::Bundle | |
34 { | |
35 private: | |
36 uint32_t count_; | |
37 uint64_t space_; | |
38 | |
39 public: | |
40 Bundle() : count_(0), space_(0) | |
41 { | |
42 } | |
43 | |
44 Bundle(uint32_t count, | |
45 uint64_t space) : | |
46 count_(count), space_(space) | |
47 { | |
48 } | |
49 | |
50 uint32_t GetCount() const | |
51 { | |
52 return count_; | |
53 } | |
54 | |
55 uint64_t GetSpace() const | |
56 { | |
57 return space_; | |
58 } | |
59 | |
60 void Remove(uint64_t fileSize) | |
61 { | |
62 if (count_ == 0 || | |
63 space_ < fileSize) | |
64 { | |
65 throw std::runtime_error("Internal error"); | |
66 } | |
67 | |
68 count_ -= 1; | |
69 space_ -= fileSize; | |
70 } | |
71 | |
72 void Add(uint64_t fileSize) | |
73 { | |
74 count_ += 1; | |
75 space_ += fileSize; | |
76 } | |
77 }; | |
78 | |
79 | |
80 class CacheManager::BundleQuota | |
81 { | |
82 private: | |
83 uint32_t maxCount_; | |
84 uint64_t maxSpace_; | |
85 | |
86 public: | |
87 BundleQuota(uint32_t maxCount, | |
88 uint64_t maxSpace) : | |
89 maxCount_(maxCount), maxSpace_(maxSpace) | |
90 { | |
91 } | |
92 | |
93 BundleQuota() | |
94 { | |
95 // Default quota | |
96 maxCount_ = 0; // No limit on the number of files | |
97 maxSpace_ = 100 * 1024 * 1024; // Max 100MB per bundle | |
98 } | |
99 | |
100 uint32_t GetMaxCount() const | |
101 { | |
102 return maxCount_; | |
103 } | |
104 | |
105 uint64_t GetMaxSpace() const | |
106 { | |
107 return maxSpace_; | |
108 } | |
109 | |
110 bool IsSatisfied(const Bundle& bundle) const | |
111 { | |
112 if (maxCount_ != 0 && | |
113 bundle.GetCount() > maxCount_) | |
114 { | |
115 return false; | |
116 } | |
117 | |
118 if (maxSpace_ != 0 && | |
119 bundle.GetSpace() > maxSpace_) | |
120 { | |
121 return false; | |
122 } | |
123 | |
124 return true; | |
125 } | |
126 }; | |
127 | |
128 | |
129 struct CacheManager::PImpl | |
130 { | |
147
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
131 OrthancPluginContext* context_; |
0 | 132 Orthanc::SQLite::Connection& db_; |
133 Orthanc::FilesystemStorage& storage_; | |
134 | |
135 bool sanityCheck_; | |
136 Bundles bundles_; | |
137 BundleQuota defaultQuota_; | |
138 BundleQuotas quotas_; | |
139 | |
147
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
140 PImpl(OrthancPluginContext* context, |
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
141 Orthanc::SQLite::Connection& db, |
0 | 142 Orthanc::FilesystemStorage& storage) : |
147
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
143 context_(context), |
0 | 144 db_(db), |
145 storage_(storage), | |
146 sanityCheck_(false) | |
147 { | |
148 } | |
149 }; | |
150 | |
151 | |
152 const CacheManager::BundleQuota& CacheManager::GetBundleQuota(int bundleIndex) const | |
153 { | |
154 BundleQuotas::const_iterator found = pimpl_->quotas_.find(bundleIndex); | |
155 | |
156 if (found == pimpl_->quotas_.end()) | |
157 { | |
158 return pimpl_->defaultQuota_; | |
159 } | |
160 else | |
161 { | |
162 return found->second; | |
163 } | |
164 } | |
165 | |
166 | |
167 CacheManager::Bundle CacheManager::GetBundle(int bundleIndex) const | |
168 { | |
169 Bundles::const_iterator it = pimpl_->bundles_.find(bundleIndex); | |
170 | |
171 if (it == pimpl_->bundles_.end()) | |
172 { | |
173 return Bundle(); | |
174 } | |
175 else | |
176 { | |
177 return it->second; | |
178 } | |
179 } | |
180 | |
181 | |
182 void CacheManager::MakeRoom(Bundle& bundle, | |
183 std::list<std::string>& toRemove, | |
184 int bundleIndex, | |
185 const BundleQuota& quota) | |
186 { | |
187 toRemove.clear(); | |
188 | |
189 // Make room in the bundle | |
190 while (!quota.IsSatisfied(bundle)) | |
191 { | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
192 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, "SELECT seq, fileUuid, fileSize FROM Cache WHERE bundle=? ORDER BY seq"); |
0 | 193 s.BindInt(0, bundleIndex); |
194 | |
195 if (s.Step()) | |
196 { | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
197 Orthanc::SQLite::Statement t(pimpl_->db_, SQLITE_FROM_HERE, "DELETE FROM Cache WHERE seq=?"); |
0 | 198 t.BindInt64(0, s.ColumnInt64(0)); |
199 t.Run(); | |
200 | |
201 toRemove.push_back(s.ColumnString(1)); | |
202 bundle.Remove(s.ColumnInt64(2)); | |
203 } | |
204 else | |
205 { | |
206 // Should never happen | |
207 throw std::runtime_error("Internal error"); | |
208 } | |
209 } | |
210 } | |
211 | |
212 | |
213 | |
214 void CacheManager::EnsureQuota(int bundleIndex, | |
215 const BundleQuota& quota) | |
216 { | |
217 // Remove the cached files that exceed the quota | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
218 std::unique_ptr<Orthanc::SQLite::Transaction> transaction(new Orthanc::SQLite::Transaction(pimpl_->db_)); |
0 | 219 transaction->Begin(); |
220 | |
221 Bundle bundle = GetBundle(bundleIndex); | |
222 | |
223 std::list<std::string> toRemove; | |
224 MakeRoom(bundle, toRemove, bundleIndex, quota); | |
225 | |
226 transaction->Commit(); | |
227 for (std::list<std::string>::const_iterator | |
197 | 228 it = toRemove.begin(); it != toRemove.end(); ++it) |
0 | 229 { |
23
7a0af291cc90
Synchronization with Orthanc mainline
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
230 pimpl_->storage_.Remove(*it, Orthanc::FileContentType_Unknown); |
0 | 231 } |
232 | |
233 pimpl_->bundles_[bundleIndex] = bundle; | |
234 } | |
235 | |
236 | |
237 | |
238 void CacheManager::ReadBundleStatistics() | |
239 { | |
240 pimpl_->bundles_.clear(); | |
241 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
242 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, "SELECT bundle,COUNT(*),SUM(fileSize) FROM Cache GROUP BY bundle"); |
0 | 243 while (s.Step()) |
244 { | |
245 int index = s.ColumnInt(0); | |
246 Bundle bundle(static_cast<uint32_t>(s.ColumnInt(1)), | |
247 static_cast<uint64_t>(s.ColumnInt64(2))); | |
248 pimpl_->bundles_[index] = bundle; | |
249 } | |
250 } | |
251 | |
252 | |
253 | |
254 void CacheManager::SanityCheck() | |
255 { | |
256 if (!pimpl_->sanityCheck_) | |
257 { | |
258 return; | |
259 } | |
260 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
261 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, "SELECT bundle,COUNT(*),SUM(fileSize) FROM Cache GROUP BY bundle"); |
0 | 262 while (s.Step()) |
263 { | |
264 const Bundle& bundle = GetBundle(s.ColumnInt(0)); | |
265 if (bundle.GetCount() != static_cast<uint32_t>(s.ColumnInt(1)) || | |
266 bundle.GetSpace() != static_cast<uint64_t>(s.ColumnInt64(2))) | |
267 { | |
268 throw std::runtime_error("SANITY ERROR in cache: " + boost::lexical_cast<std::string>(bundle.GetCount()) | |
269 + "/" + boost::lexical_cast<std::string>(bundle.GetSpace()) | |
270 + " vs " + boost::lexical_cast<std::string>(s.ColumnInt(1)) + "/" | |
271 + boost::lexical_cast<std::string>(s.ColumnInt64(2))); | |
272 } | |
273 } | |
274 } | |
275 | |
276 | |
277 | |
147
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
278 CacheManager::CacheManager(OrthancPluginContext* context, |
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
279 Orthanc::SQLite::Connection& db, |
0 | 280 Orthanc::FilesystemStorage& storage) : |
147
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
281 pimpl_(new PImpl(context, db, storage)) |
0 | 282 { |
283 Open(); | |
284 ReadBundleStatistics(); | |
285 } | |
286 | |
287 | |
147
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
288 OrthancPluginContext* CacheManager::GetPluginContext() const |
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
289 { |
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
290 return pimpl_->context_; |
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
291 } |
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
292 |
70d1fe6d6309
Avoid hard crash if not enough memory
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
122
diff
changeset
|
293 |
0 | 294 void CacheManager::SetSanityCheckEnabled(bool enabled) |
295 { | |
296 pimpl_->sanityCheck_ = enabled; | |
297 } | |
298 | |
299 | |
300 void CacheManager::Open() | |
301 { | |
302 if (!pimpl_->db_.DoesTableExist("Cache")) | |
303 { | |
304 pimpl_->db_.Execute("CREATE TABLE Cache(seq INTEGER PRIMARY KEY, bundle INTEGER, item TEXT, fileUuid TEXT, fileSize INT);"); | |
305 pimpl_->db_.Execute("CREATE INDEX CacheBundles ON Cache(bundle);"); | |
306 pimpl_->db_.Execute("CREATE INDEX CacheIndex ON Cache(bundle, item);"); | |
307 } | |
308 | |
115
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
309 if (!pimpl_->db_.DoesTableExist("CacheProperties")) |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
310 { |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
311 pimpl_->db_.Execute("CREATE TABLE CacheProperties(property INTEGER PRIMARY KEY, value TEXT);"); |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
312 } |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
313 |
0 | 314 // Performance tuning of SQLite with PRAGMAs |
315 // http://www.sqlite.org/pragma.html | |
316 pimpl_->db_.Execute("PRAGMA SYNCHRONOUS=OFF;"); | |
317 pimpl_->db_.Execute("PRAGMA JOURNAL_MODE=WAL;"); | |
318 pimpl_->db_.Execute("PRAGMA LOCKING_MODE=EXCLUSIVE;"); | |
319 } | |
320 | |
321 | |
322 void CacheManager::Store(int bundleIndex, | |
323 const std::string& item, | |
324 const std::string& content) | |
325 { | |
326 SanityCheck(); | |
327 | |
328 const BundleQuota quota = GetBundleQuota(bundleIndex); | |
329 | |
330 if (quota.GetMaxSpace() > 0 && | |
331 content.size() > quota.GetMaxSpace()) | |
332 { | |
333 // Cannot store such a large instance into the cache, forget about it | |
334 return; | |
335 } | |
336 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
337 std::unique_ptr<Orthanc::SQLite::Transaction> transaction(new Orthanc::SQLite::Transaction(pimpl_->db_)); |
0 | 338 transaction->Begin(); |
339 | |
340 Bundle bundle = GetBundle(bundleIndex); | |
341 | |
342 std::list<std::string> toRemove; | |
343 bundle.Add(content.size()); | |
344 MakeRoom(bundle, toRemove, bundleIndex, quota); | |
345 | |
346 // Store the cached content on the disk | |
347 const char* data = content.size() ? &content[0] : NULL; | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
348 std::string uuid = Orthanc::Toolbox::GenerateUuid(); |
23
7a0af291cc90
Synchronization with Orthanc mainline
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
349 pimpl_->storage_.Create(uuid, data, content.size(), Orthanc::FileContentType_Unknown); |
0 | 350 |
351 // Remove the previous cached value. This might happen if the same | |
352 // item is accessed very quickly twice: Another factory could have | |
353 // been cached a value before the check for existence in Access(). | |
354 { | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
355 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, "SELECT seq, fileUuid, fileSize FROM Cache WHERE bundle=? AND item=?"); |
0 | 356 s.BindInt(0, bundleIndex); |
357 s.BindString(1, item); | |
358 if (s.Step()) | |
359 { | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
360 Orthanc::SQLite::Statement t(pimpl_->db_, SQLITE_FROM_HERE, "DELETE FROM Cache WHERE seq=?"); |
0 | 361 t.BindInt64(0, s.ColumnInt64(0)); |
362 t.Run(); | |
363 | |
364 toRemove.push_back(s.ColumnString(1)); | |
365 bundle.Remove(s.ColumnInt64(2)); | |
366 } | |
367 } | |
368 | |
369 { | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
370 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, "INSERT INTO Cache VALUES(NULL, ?, ?, ?, ?)"); |
0 | 371 s.BindInt(0, bundleIndex); |
372 s.BindString(1, item); | |
373 s.BindString(2, uuid); | |
374 s.BindInt64(3, content.size()); | |
375 | |
376 if (!s.Run()) | |
377 { | |
197 | 378 // Error: Remove the stored file |
379 pimpl_->storage_.Remove(uuid, Orthanc::FileContentType_Unknown); | |
0 | 380 } |
197 | 381 else |
382 { | |
383 transaction->Commit(); | |
0 | 384 |
197 | 385 pimpl_->bundles_[bundleIndex] = bundle; |
0 | 386 |
197 | 387 for (std::list<std::string>::const_iterator |
388 it = toRemove.begin(); it != toRemove.end(); ++it) | |
389 { | |
390 pimpl_->storage_.Remove(*it, Orthanc::FileContentType_Unknown); | |
391 } | |
0 | 392 } |
393 } | |
394 | |
395 SanityCheck(); | |
396 } | |
397 | |
398 | |
399 | |
400 bool CacheManager::LocateInCache(std::string& uuid, | |
401 uint64_t& size, | |
402 int bundle, | |
403 const std::string& item) | |
404 { | |
405 SanityCheck(); | |
406 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
407 std::unique_ptr<Orthanc::SQLite::Transaction> transaction(new Orthanc::SQLite::Transaction(pimpl_->db_)); |
0 | 408 transaction->Begin(); |
409 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
410 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, "SELECT seq, fileUuid, fileSize FROM Cache WHERE bundle=? AND item=?"); |
0 | 411 s.BindInt(0, bundle); |
412 s.BindString(1, item); | |
413 if (!s.Step()) | |
414 { | |
415 return false; | |
416 } | |
417 | |
418 int64_t seq = s.ColumnInt64(0); | |
419 uuid = s.ColumnString(1); | |
420 size = s.ColumnInt64(2); | |
421 | |
422 // Touch the cache to fulfill the LRU scheme. | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
423 Orthanc::SQLite::Statement t(pimpl_->db_, SQLITE_FROM_HERE, "DELETE FROM Cache WHERE seq=?"); |
0 | 424 t.BindInt64(0, seq); |
425 if (t.Run()) | |
426 { | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
427 Orthanc::SQLite::Statement u(pimpl_->db_, SQLITE_FROM_HERE, "INSERT INTO Cache VALUES(NULL, ?, ?, ?, ?)"); |
0 | 428 u.BindInt(0, bundle); |
429 u.BindString(1, item); | |
430 u.BindString(2, uuid); | |
431 u.BindInt64(3, size); | |
432 if (u.Run()) | |
433 { | |
434 // Everything was OK. Commit the changes to the cache. | |
435 transaction->Commit(); | |
436 return true; | |
437 } | |
438 } | |
439 | |
440 return false; | |
441 } | |
442 | |
443 | |
444 bool CacheManager::IsCached(int bundle, | |
445 const std::string& item) | |
446 { | |
447 std::string uuid; | |
448 uint64_t size; | |
449 return LocateInCache(uuid, size, bundle, item); | |
450 } | |
451 | |
452 | |
453 bool CacheManager::Access(std::string& content, | |
454 int bundle, | |
455 const std::string& item) | |
456 { | |
457 std::string uuid; | |
458 uint64_t size; | |
459 if (!LocateInCache(uuid, size, bundle, item)) | |
460 { | |
461 return false; | |
462 } | |
463 | |
464 bool ok; | |
465 try | |
466 { | |
295
fc57bf7c0c83
backward compatibility with Orthanc framework 1.8.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
294
diff
changeset
|
467 #if defined(ORTHANC_FRAMEWORK_VERSION_IS_ABOVE) && ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 9, 0) |
294
dca8013585d1
fix for new API of Orthanc::FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
293
diff
changeset
|
468 std::unique_ptr<Orthanc::IMemoryBuffer> buffer( |
dca8013585d1
fix for new API of Orthanc::FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
293
diff
changeset
|
469 pimpl_->storage_.Read(uuid, Orthanc::FileContentType_Unknown)); |
dca8013585d1
fix for new API of Orthanc::FilesystemStorage
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
293
diff
changeset
|
470 buffer->MoveToString(content); |
295
fc57bf7c0c83
backward compatibility with Orthanc framework 1.8.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
294
diff
changeset
|
471 #else |
fc57bf7c0c83
backward compatibility with Orthanc framework 1.8.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
294
diff
changeset
|
472 pimpl_->storage_.Read(content, uuid, Orthanc::FileContentType_Unknown); |
fc57bf7c0c83
backward compatibility with Orthanc framework 1.8.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
294
diff
changeset
|
473 #endif |
fc57bf7c0c83
backward compatibility with Orthanc framework 1.8.2
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
294
diff
changeset
|
474 |
0 | 475 ok = (content.size() == size); |
476 } | |
477 catch (std::runtime_error&) | |
478 { | |
479 ok = false; | |
480 } | |
481 | |
482 if (ok) | |
483 { | |
484 return true; | |
485 } | |
486 else | |
487 { | |
488 throw std::runtime_error("Error in the filesystem"); | |
489 } | |
490 } | |
491 | |
492 | |
493 void CacheManager::Invalidate(int bundleIndex, | |
494 const std::string& item) | |
495 { | |
496 SanityCheck(); | |
497 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
498 std::unique_ptr<Orthanc::SQLite::Transaction> transaction(new Orthanc::SQLite::Transaction(pimpl_->db_)); |
0 | 499 transaction->Begin(); |
500 | |
501 Bundle bundle = GetBundle(bundleIndex); | |
502 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
503 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, "SELECT seq, fileUuid, fileSize FROM Cache WHERE bundle=? AND item=?"); |
0 | 504 s.BindInt(0, bundleIndex); |
505 s.BindString(1, item); | |
506 if (s.Step()) | |
507 { | |
508 int64_t seq = s.ColumnInt64(0); | |
509 const std::string uuid = s.ColumnString(1); | |
510 uint64_t expectedSize = s.ColumnInt64(2); | |
511 bundle.Remove(expectedSize); | |
512 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
513 Orthanc::SQLite::Statement t(pimpl_->db_, SQLITE_FROM_HERE, "DELETE FROM Cache WHERE seq=?"); |
0 | 514 t.BindInt64(0, seq); |
515 if (t.Run()) | |
516 { | |
517 transaction->Commit(); | |
518 pimpl_->bundles_[bundleIndex] = bundle; | |
23
7a0af291cc90
Synchronization with Orthanc mainline
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
519 pimpl_->storage_.Remove(uuid, Orthanc::FileContentType_Unknown); |
0 | 520 } |
521 } | |
522 } | |
523 | |
524 | |
525 | |
526 void CacheManager::SetBundleQuota(int bundle, | |
527 uint32_t maxCount, | |
528 uint64_t maxSpace) | |
529 { | |
530 SanityCheck(); | |
531 | |
532 const BundleQuota quota(maxCount, maxSpace); | |
533 EnsureQuota(bundle, quota); | |
534 pimpl_->quotas_[bundle] = quota; | |
535 | |
536 SanityCheck(); | |
537 } | |
538 | |
539 void CacheManager::SetDefaultQuota(uint32_t maxCount, | |
540 uint64_t maxSpace) | |
541 { | |
542 SanityCheck(); | |
543 | |
544 pimpl_->defaultQuota_ = BundleQuota(maxCount, maxSpace); | |
545 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
546 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, "SELECT DISTINCT bundle FROM Cache"); |
0 | 547 while (s.Step()) |
548 { | |
549 EnsureQuota(s.ColumnInt(0), pimpl_->defaultQuota_); | |
550 } | |
551 | |
552 SanityCheck(); | |
553 } | |
554 | |
555 | |
556 void CacheManager::Clear() | |
557 { | |
558 SanityCheck(); | |
559 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
560 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, "SELECT fileUuid FROM Cache"); |
0 | 561 while (s.Step()) |
562 { | |
23
7a0af291cc90
Synchronization with Orthanc mainline
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
563 pimpl_->storage_.Remove(s.ColumnString(0), Orthanc::FileContentType_Unknown); |
0 | 564 } |
565 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
566 Orthanc::SQLite::Statement t(pimpl_->db_, SQLITE_FROM_HERE, "DELETE FROM Cache"); |
0 | 567 t.Run(); |
568 | |
569 ReadBundleStatistics(); | |
570 SanityCheck(); | |
571 } | |
572 | |
573 | |
574 | |
575 void CacheManager::Clear(int bundle) | |
576 { | |
577 SanityCheck(); | |
578 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
579 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, "SELECT fileUuid FROM Cache WHERE bundle=?"); |
0 | 580 s.BindInt(0, bundle); |
581 while (s.Step()) | |
582 { | |
23
7a0af291cc90
Synchronization with Orthanc mainline
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
583 pimpl_->storage_.Remove(s.ColumnString(0), Orthanc::FileContentType_Unknown); |
0 | 584 } |
585 | |
296
d179f3928342
removed "using namespace Orthanc"
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
295
diff
changeset
|
586 Orthanc::SQLite::Statement t(pimpl_->db_, SQLITE_FROM_HERE, "DELETE FROM Cache WHERE bundle=?"); |
0 | 587 t.BindInt(0, bundle); |
588 t.Run(); | |
589 | |
590 ReadBundleStatistics(); | |
591 SanityCheck(); | |
592 } | |
115
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
593 |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
594 |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
595 void CacheManager::SetProperty(CacheProperty property, |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
596 const std::string& value) |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
597 { |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
598 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
599 "INSERT OR REPLACE INTO CacheProperties VALUES(?, ?)"); |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
600 s.BindInt(0, property); |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
601 s.BindString(1, value); |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
602 s.Run(); |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
603 } |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
604 |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
605 |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
606 bool CacheManager::LookupProperty(std::string& target, |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
607 CacheProperty property) |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
608 { |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
609 Orthanc::SQLite::Statement s(pimpl_->db_, SQLITE_FROM_HERE, |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
610 "SELECT value FROM CacheProperties WHERE property=?"); |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
611 s.BindInt(0, property); |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
612 |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
613 if (!s.Step()) |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
614 { |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
615 return false; |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
616 } |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
617 else |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
618 { |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
619 target = s.ColumnString(0); |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
620 return true; |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
621 } |
c8ca47a67bf3
automatic clearing of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
26
diff
changeset
|
622 } |
0 | 623 } |