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