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