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