Mercurial > hg > orthanc-databases
comparison Framework/Plugins/StorageBackend.cpp @ 242:b97a537f4613
MySQL: Support of range reads for the storage area
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 13 Apr 2021 17:00:02 +0200 |
parents | 0a9b48d19643 |
children | 02cd7254c949 |
comparison
equal
deleted
inserted
replaced
241:a063bbf10a3e | 242:b97a537f4613 |
---|---|
83 return *manager_; | 83 return *manager_; |
84 } | 84 } |
85 } | 85 } |
86 | 86 |
87 | 87 |
88 void StorageBackend::Accessor::Create(const std::string& uuid, | 88 void StorageBackend::AccessorBase::Create(const std::string& uuid, |
89 const void* content, | 89 const void* content, |
90 size_t size, | 90 size_t size, |
91 OrthancPluginContentType type) | 91 OrthancPluginContentType type) |
92 { | 92 { |
93 DatabaseManager::Transaction transaction(manager_, TransactionType_ReadWrite); | 93 DatabaseManager::Transaction transaction(manager_, TransactionType_ReadWrite); |
94 | 94 |
95 { | 95 { |
96 DatabaseManager::CachedStatement statement( | 96 DatabaseManager::CachedStatement statement( |
111 | 111 |
112 transaction.Commit(); | 112 transaction.Commit(); |
113 } | 113 } |
114 | 114 |
115 | 115 |
116 void StorageBackend::Accessor::Read(StorageBackend::IFileContentVisitor& visitor, | 116 void StorageBackend::AccessorBase::ReadWhole(StorageBackend::IFileContentVisitor& visitor, |
117 const std::string& uuid, | 117 const std::string& uuid, |
118 OrthancPluginContentType type) | 118 OrthancPluginContentType type) |
119 { | 119 { |
120 DatabaseManager::Transaction transaction(manager_, TransactionType_ReadOnly); | 120 DatabaseManager::Transaction transaction(manager_, TransactionType_ReadOnly); |
121 | 121 |
122 { | 122 { |
123 DatabaseManager::CachedStatement statement( | 123 DatabaseManager::CachedStatement statement( |
168 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database, "Could not read attachment from the storage area"); | 168 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database, "Could not read attachment from the storage area"); |
169 } | 169 } |
170 } | 170 } |
171 | 171 |
172 | 172 |
173 void StorageBackend::Accessor::Remove(const std::string& uuid, | 173 void StorageBackend::AccessorBase::ReadRange(IFileContentVisitor& visitor, |
174 OrthancPluginContentType type) | 174 const std::string& uuid, |
175 OrthancPluginContentType type, | |
176 uint64_t start, | |
177 uint64_t length) | |
178 { | |
179 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | |
180 } | |
181 | |
182 | |
183 void StorageBackend::AccessorBase::Remove(const std::string& uuid, | |
184 OrthancPluginContentType type) | |
175 { | 185 { |
176 DatabaseManager::Transaction transaction(manager_, TransactionType_ReadWrite); | 186 DatabaseManager::Transaction transaction(manager_, TransactionType_ReadWrite); |
177 | 187 |
178 { | 188 { |
179 DatabaseManager::CachedStatement statement( | 189 DatabaseManager::CachedStatement statement( |
210 { | 220 { |
211 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | 221 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); |
212 } | 222 } |
213 else | 223 else |
214 { | 224 { |
215 StorageBackend::Accessor accessor(*backend_); | 225 std::unique_ptr<StorageBackend::IAccessor> accessor(backend_->CreateAccessor()); |
216 accessor.Create(uuid, content, static_cast<size_t>(size), type); | 226 accessor->Create(uuid, content, static_cast<size_t>(size), type); |
217 return OrthancPluginErrorCode_Success; | 227 return OrthancPluginErrorCode_Success; |
218 } | 228 } |
219 } | 229 } |
220 ORTHANC_PLUGINS_DATABASE_CATCH; | 230 ORTHANC_PLUGINS_DATABASE_CATCH; |
221 } | 231 } |
235 public: | 245 public: |
236 Visitor(OrthancPluginMemoryBuffer64* target) : | 246 Visitor(OrthancPluginMemoryBuffer64* target) : |
237 target_(target), | 247 target_(target), |
238 success_(false) | 248 success_(false) |
239 { | 249 { |
250 if (target == NULL) | |
251 { | |
252 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
253 } | |
240 } | 254 } |
241 | 255 |
242 virtual bool IsSuccess() const ORTHANC_OVERRIDE | 256 virtual bool IsSuccess() const ORTHANC_OVERRIDE |
243 { | 257 { |
244 return success_; | 258 return success_; |
267 | 281 |
268 success_ = true; | 282 success_ = true; |
269 } | 283 } |
270 } | 284 } |
271 }; | 285 }; |
272 | 286 |
287 | |
273 try | 288 try |
274 { | 289 { |
275 if (backend_.get() == NULL) | 290 if (backend_.get() == NULL) |
276 { | 291 { |
277 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | 292 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); |
278 } | 293 } |
279 else if (target == NULL) | |
280 { | |
281 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
282 } | |
283 else | 294 else |
284 { | 295 { |
285 Visitor visitor(target); | 296 Visitor visitor(target); |
286 | 297 |
287 { | 298 { |
288 StorageBackend::Accessor accessor(*backend_); | 299 std::unique_ptr<StorageBackend::IAccessor> accessor(backend_->CreateAccessor()); |
289 accessor.Read(visitor, uuid, type); | 300 accessor->ReadWhole(visitor, uuid, type); |
301 } | |
302 | |
303 return OrthancPluginErrorCode_Success; | |
304 } | |
305 } | |
306 ORTHANC_PLUGINS_DATABASE_CATCH; | |
307 } | |
308 | |
309 | |
310 static OrthancPluginErrorCode StorageReadRange(OrthancPluginMemoryBuffer64* target, | |
311 const char* uuid, | |
312 OrthancPluginContentType type, | |
313 uint64_t start) | |
314 { | |
315 class Visitor : public StorageBackend::IFileContentVisitor | |
316 { | |
317 private: | |
318 OrthancPluginMemoryBuffer64* target_; // This buffer is already allocated by the Orthanc core | |
319 bool success_; | |
320 | |
321 public: | |
322 Visitor(OrthancPluginMemoryBuffer64* target) : | |
323 target_(target), | |
324 success_(false) | |
325 { | |
326 if (target == NULL) | |
327 { | |
328 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
329 } | |
330 } | |
331 | |
332 virtual bool IsSuccess() const ORTHANC_OVERRIDE | |
333 { | |
334 return success_; | |
335 } | |
336 | |
337 virtual void Assign(const std::string& content) ORTHANC_OVERRIDE | |
338 { | |
339 if (success_) | |
340 { | |
341 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
342 } | |
343 else | |
344 { | |
345 if (content.size() != target_->size) | |
346 { | |
347 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
348 } | |
349 | |
350 if (!content.empty()) | |
351 { | |
352 memcpy(target_->data, content.c_str(), content.size()); | |
353 } | |
354 | |
355 success_ = true; | |
356 } | |
357 } | |
358 }; | |
359 | |
360 | |
361 try | |
362 { | |
363 if (backend_.get() == NULL) | |
364 { | |
365 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
366 } | |
367 else | |
368 { | |
369 Visitor visitor(target); | |
370 | |
371 { | |
372 std::unique_ptr<StorageBackend::IAccessor> accessor(backend_->CreateAccessor()); | |
373 accessor->ReadRange(visitor, uuid, type, start, target->size); | |
290 } | 374 } |
291 | 375 |
292 return OrthancPluginErrorCode_Success; | 376 return OrthancPluginErrorCode_Success; |
293 } | 377 } |
294 } | 378 } |
375 else | 459 else |
376 { | 460 { |
377 Visitor visitor(data, size); | 461 Visitor visitor(data, size); |
378 | 462 |
379 { | 463 { |
380 StorageBackend::Accessor accessor(*backend_); | 464 std::unique_ptr<StorageBackend::IAccessor> accessor(backend_->CreateAccessor()); |
381 accessor.Read(visitor, uuid, type); | 465 accessor->ReadWhole(visitor, uuid, type); |
382 } | 466 } |
383 | 467 |
384 return OrthancPluginErrorCode_Success; | 468 return OrthancPluginErrorCode_Success; |
385 } | 469 } |
386 } | 470 } |
397 { | 481 { |
398 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | 482 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); |
399 } | 483 } |
400 else | 484 else |
401 { | 485 { |
402 StorageBackend::Accessor accessor(*backend_); | 486 std::unique_ptr<StorageBackend::IAccessor> accessor(backend_->CreateAccessor()); |
403 accessor.Remove(uuid, type); | 487 accessor->Remove(uuid, type); |
404 return OrthancPluginErrorCode_Success; | 488 return OrthancPluginErrorCode_Success; |
405 } | 489 } |
406 } | 490 } |
407 ORTHANC_PLUGINS_DATABASE_CATCH; | 491 ORTHANC_PLUGINS_DATABASE_CATCH; |
408 } | 492 } |
432 | 516 |
433 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 | 517 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 |
434 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 0) | 518 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 0) |
435 if (OrthancPluginCheckVersionAdvanced(context, 1, 9, 0) == 1) | 519 if (OrthancPluginCheckVersionAdvanced(context, 1, 9, 0) == 1) |
436 { | 520 { |
437 OrthancPluginRegisterStorageArea2(context_, StorageCreate, StorageReadWhole, | 521 OrthancPluginStorageReadRange readRange = NULL; |
438 NULL /* TODO - StorageReadRange */, StorageRemove); | 522 if (backend_->HasReadRange()) |
523 { | |
524 readRange = StorageReadRange; | |
525 } | |
526 | |
527 OrthancPluginRegisterStorageArea2(context_, StorageCreate, StorageReadWhole, readRange, StorageRemove); | |
439 hasLoadedV2 = true; | 528 hasLoadedV2 = true; |
440 } | 529 } |
441 # endif | 530 # endif |
442 #endif | 531 #endif |
443 | 532 |
454 backend_.reset(NULL); | 543 backend_.reset(NULL); |
455 context_ = NULL; | 544 context_ = NULL; |
456 } | 545 } |
457 | 546 |
458 | 547 |
459 void StorageBackend::Accessor::ReadToString(std::string& target, | 548 class StorageBackend::StringVisitor : public StorageBackend::IFileContentVisitor |
460 const std::string& uuid, | 549 { |
461 OrthancPluginContentType type) | 550 private: |
462 { | 551 std::string& target_; |
463 class Visitor : public StorageBackend::IFileContentVisitor | 552 bool success_; |
464 { | 553 |
465 private: | 554 public: |
466 std::string& target_; | 555 StringVisitor(std::string& target) : |
467 bool success_; | 556 target_(target), |
468 | 557 success_(false) |
469 public: | 558 { |
470 Visitor(std::string& target) : | 559 } |
471 target_(target), | 560 |
472 success_(false) | 561 virtual bool IsSuccess() const ORTHANC_OVERRIDE |
473 { | 562 { |
474 } | 563 return success_; |
475 | 564 } |
476 virtual bool IsSuccess() const ORTHANC_OVERRIDE | 565 |
477 { | 566 virtual void Assign(const std::string& content) ORTHANC_OVERRIDE |
478 return success_; | 567 { |
479 } | 568 if (success_) |
480 | 569 { |
481 virtual void Assign(const std::string& content) ORTHANC_OVERRIDE | 570 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); |
482 { | 571 } |
483 if (success_) | 572 else |
484 { | 573 { |
485 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | 574 target_.assign(content); |
486 } | 575 success_ = true; |
487 else | 576 } |
488 { | 577 } |
489 target_.assign(content); | 578 }; |
490 success_ = true; | |
491 } | |
492 } | |
493 }; | |
494 | 579 |
495 | 580 |
496 Visitor visitor(target); | 581 void StorageBackend::ReadWholeToString(std::string& target, |
497 Read(visitor, uuid, type); | 582 IAccessor& accessor, |
583 const std::string& uuid, | |
584 OrthancPluginContentType type) | |
585 { | |
586 StringVisitor visitor(target); | |
587 accessor.ReadWhole(visitor, uuid, type); | |
588 | |
589 if (!visitor.IsSuccess()) | |
590 { | |
591 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
592 } | |
593 } | |
594 | |
595 | |
596 void StorageBackend::ReadRangeToString(std::string& target, | |
597 IAccessor& accessor, | |
598 const std::string& uuid, | |
599 OrthancPluginContentType type, | |
600 uint64_t start, | |
601 uint64_t length) | |
602 { | |
603 StringVisitor visitor(target); | |
604 accessor.ReadRange(visitor, uuid, type, start, length); | |
605 | |
606 if (!visitor.IsSuccess()) | |
607 { | |
608 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
609 } | |
498 } | 610 } |
499 } | 611 } |