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 }