comparison Framework/Plugins/DatabaseBackendAdapterV3.cpp @ 212:821d4ba83dc3

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 24 Mar 2021 15:47:14 +0100
parents
children 73cc85f3d9c1
comparison
equal deleted inserted replaced
211:d74a92ac00ea 212:821d4ba83dc3
1 /**
2 * Orthanc - A Lightweight, RESTful DICOM Store
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2021 Osimis S.A., Belgium
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 "DatabaseBackendAdapterV3.h"
23
24 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1
25 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2)
26
27 #include <OrthancException.h>
28
29 #include <stdexcept>
30 #include <list>
31 #include <string>
32 #include <cassert>
33
34 #include <boost/thread/mutex.hpp> // TODO - REMOVE
35
36
37 #define ORTHANC_PLUGINS_DATABASE_CATCH(context) \
38 catch (::Orthanc::OrthancException& e) \
39 { \
40 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); \
41 } \
42 catch (::std::runtime_error& e) \
43 { \
44 const std::string message = "Exception in database back-end: " + std::string(e.what()); \
45 OrthancPluginLogError(context, message.c_str()); \
46 return OrthancPluginErrorCode_DatabasePlugin; \
47 } \
48 catch (...) \
49 { \
50 OrthancPluginLogError(context, "Native exception"); \
51 return OrthancPluginErrorCode_DatabasePlugin; \
52 }
53
54
55 namespace OrthancDatabases
56 {
57 class DatabaseBackendAdapterV3::Output : public IDatabaseBackendOutput
58 {
59 private:
60 struct Metadata
61 {
62 int32_t metadata;
63 const char* value;
64 };
65
66 _OrthancPluginDatabaseAnswerType answerType_;
67 std::list<std::string> stringsStore_;
68
69 std::vector<OrthancPluginAttachment> attachments_;
70 std::vector<OrthancPluginChange> changes_;
71 std::vector<OrthancPluginDicomTag> tags_;
72 std::vector<OrthancPluginExportedResource> exported_;
73 std::vector<OrthancPluginDatabaseEvent> events_;
74 std::vector<int32_t> integers32_;
75 std::vector<int64_t> integers64_;
76 std::vector<OrthancPluginMatchingResource> matches_;
77 std::vector<Metadata> metadata_;
78 std::vector<std::string> stringAnswers_;
79
80 const char* StoreString(const std::string& s)
81 {
82 stringsStore_.push_back(s);
83 return stringsStore_.back().c_str();
84 }
85
86 void SetupAnswerType(_OrthancPluginDatabaseAnswerType type)
87 {
88 if (answerType_ == _OrthancPluginDatabaseAnswerType_None)
89 {
90 answerType_ = type;
91 }
92 else if (answerType_ != type)
93 {
94 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
95 }
96 }
97
98 public:
99 Output() :
100 answerType_(_OrthancPluginDatabaseAnswerType_None)
101 {
102 }
103
104 void Clear()
105 {
106 // We don't systematically clear all the vectors, in order to
107 // avoid spending unnecessary time
108
109 switch (answerType_)
110 {
111 case _OrthancPluginDatabaseAnswerType_None:
112 break;
113
114 case _OrthancPluginDatabaseAnswerType_Attachment:
115 attachments_.clear();
116 break;
117
118 case _OrthancPluginDatabaseAnswerType_Change:
119 changes_.clear();
120 break;
121
122 case _OrthancPluginDatabaseAnswerType_DicomTag:
123 tags_.clear();
124 break;
125
126 case _OrthancPluginDatabaseAnswerType_ExportedResource:
127 exported_.clear();
128 break;
129
130 case _OrthancPluginDatabaseAnswerType_Int32:
131 integers32_.clear();
132 break;
133
134 case _OrthancPluginDatabaseAnswerType_Int64:
135 integers64_.clear();
136 break;
137
138 case _OrthancPluginDatabaseAnswerType_MatchingResource:
139 matches_.clear();
140 break;
141
142 case _OrthancPluginDatabaseAnswerType_Metadata:
143 metadata_.clear();
144 break;
145
146 case _OrthancPluginDatabaseAnswerType_String:
147 stringAnswers_.clear();
148 break;
149
150 default:
151 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
152 }
153
154 answerType_ = _OrthancPluginDatabaseAnswerType_None;
155 stringsStore_.clear();
156 events_.clear();
157
158 assert(attachments_.empty());
159 assert(changes_.empty());
160 assert(tags_.empty());
161 assert(exported_.empty());
162 assert(events_.empty());
163 assert(integers32_.empty());
164 assert(integers64_.empty());
165 assert(matches_.empty());
166 assert(metadata_.empty());
167 assert(stringAnswers_.empty());
168 }
169
170
171 OrthancPluginErrorCode ReadAnswersCount(uint32_t& target) const
172 {
173 switch (answerType_)
174 {
175 case _OrthancPluginDatabaseAnswerType_None:
176 target = static_cast<uint32_t>(0);
177 break;
178
179 case _OrthancPluginDatabaseAnswerType_Attachment:
180 target = static_cast<uint32_t>(attachments_.size());
181 break;
182
183 case _OrthancPluginDatabaseAnswerType_Change:
184 target = static_cast<uint32_t>(changes_.size());
185 break;
186
187 case _OrthancPluginDatabaseAnswerType_DicomTag:
188 target = static_cast<uint32_t>(tags_.size());
189 break;
190
191 case _OrthancPluginDatabaseAnswerType_ExportedResource:
192 target = static_cast<uint32_t>(exported_.size());
193 break;
194
195 case _OrthancPluginDatabaseAnswerType_Int32:
196 target = static_cast<uint32_t>(integers32_.size());
197 break;
198
199 case _OrthancPluginDatabaseAnswerType_Int64:
200 target = static_cast<uint32_t>(integers64_.size());
201 break;
202
203 case _OrthancPluginDatabaseAnswerType_MatchingResource:
204 target = static_cast<uint32_t>(matches_.size());
205 break;
206
207 case _OrthancPluginDatabaseAnswerType_Metadata:
208 target = static_cast<uint32_t>(metadata_.size());
209 break;
210
211 case _OrthancPluginDatabaseAnswerType_String:
212 target = static_cast<uint32_t>(stringAnswers_.size());
213 break;
214
215 default:
216 return OrthancPluginErrorCode_InternalError;
217 }
218
219 return OrthancPluginErrorCode_Success;
220 }
221
222
223 OrthancPluginErrorCode ReadAnswerAttachment(OrthancPluginAttachment& target /* out */,
224 uint32_t index) const
225 {
226 if (index < attachments_.size())
227 {
228 target = attachments_[index];
229 return OrthancPluginErrorCode_Success;
230 }
231 else
232 {
233 return OrthancPluginErrorCode_ParameterOutOfRange;
234 }
235 }
236
237
238 OrthancPluginErrorCode ReadAnswerChange(OrthancPluginChange& target /* out */,
239 uint32_t index) const
240 {
241 if (index < changes_.size())
242 {
243 target = changes_[index];
244 return OrthancPluginErrorCode_Success;
245 }
246 else
247 {
248 return OrthancPluginErrorCode_ParameterOutOfRange;
249 }
250 }
251
252
253 OrthancPluginErrorCode ReadAnswerDicomTag(uint16_t& group,
254 uint16_t& element,
255 const char*& value,
256 uint32_t index) const
257 {
258 if (index < tags_.size())
259 {
260 const OrthancPluginDicomTag& tag = tags_[index];
261 group = tag.group;
262 element = tag.element;
263 value = tag.value;
264 return OrthancPluginErrorCode_Success;
265 }
266 else
267 {
268 return OrthancPluginErrorCode_ParameterOutOfRange;
269 }
270 }
271
272
273 OrthancPluginErrorCode ReadAnswerExportedResource(OrthancPluginExportedResource& target /* out */,
274 uint32_t index) const
275 {
276 if (index < exported_.size())
277 {
278 target = exported_[index];
279 return OrthancPluginErrorCode_Success;
280 }
281 else
282 {
283 return OrthancPluginErrorCode_ParameterOutOfRange;
284 }
285 }
286
287
288 OrthancPluginErrorCode ReadAnswerInt32(int32_t& target,
289 uint32_t index) const
290 {
291 if (index < integers32_.size())
292 {
293 target = integers32_[index];
294 return OrthancPluginErrorCode_Success;
295 }
296 else
297 {
298 return OrthancPluginErrorCode_ParameterOutOfRange;
299 }
300 }
301
302
303 OrthancPluginErrorCode ReadAnswerInt64(int64_t& target,
304 uint32_t index) const
305 {
306 if (index < integers64_.size())
307 {
308 target = integers64_[index];
309 return OrthancPluginErrorCode_Success;
310 }
311 else
312 {
313 return OrthancPluginErrorCode_ParameterOutOfRange;
314 }
315 }
316
317
318 OrthancPluginErrorCode ReadAnswerMatchingResource(OrthancPluginMatchingResource& target,
319 uint32_t index) const
320 {
321 if (index < matches_.size())
322 {
323 target = matches_[index];
324 return OrthancPluginErrorCode_Success;
325 }
326 else
327 {
328 return OrthancPluginErrorCode_ParameterOutOfRange;
329 }
330 }
331
332
333 OrthancPluginErrorCode ReadAnswerMetadata(int32_t& metadata,
334 const char*& value,
335 uint32_t index) const
336 {
337 if (index < metadata_.size())
338 {
339 const Metadata& tmp = metadata_[index];
340 metadata = tmp.metadata;
341 value = tmp.value;
342 return OrthancPluginErrorCode_Success;
343 }
344 else
345 {
346 return OrthancPluginErrorCode_ParameterOutOfRange;
347 }
348 }
349
350
351 OrthancPluginErrorCode ReadAnswerString(const char*& target,
352 uint32_t index) const
353 {
354 if (index < stringAnswers_.size())
355 {
356 target = stringAnswers_[index].c_str();
357 return OrthancPluginErrorCode_Success;
358 }
359 else
360 {
361 return OrthancPluginErrorCode_ParameterOutOfRange;
362 }
363 }
364
365
366 OrthancPluginErrorCode ReadEventsCount(uint32_t& target /* out */) const
367 {
368 target = static_cast<uint32_t>(events_.size());
369 return OrthancPluginErrorCode_Success;
370 }
371
372
373 OrthancPluginErrorCode ReadEvent(OrthancPluginDatabaseEvent& event /* out */,
374 uint32_t index) const
375 {
376 if (index < events_.size())
377 {
378 event = events_[index];
379 return OrthancPluginErrorCode_Success;
380 }
381 else
382 {
383 return OrthancPluginErrorCode_ParameterOutOfRange;
384 }
385 }
386
387
388 virtual void SignalDeletedAttachment(const std::string& uuid,
389 int32_t contentType,
390 uint64_t uncompressedSize,
391 const std::string& uncompressedHash,
392 int32_t compressionType,
393 uint64_t compressedSize,
394 const std::string& compressedHash) ORTHANC_OVERRIDE
395 {
396 OrthancPluginDatabaseEvent event;
397 event.type = OrthancPluginDatabaseEventType_DeletedAttachment;
398 event.content.attachment.uuid = StoreString(uuid);
399 event.content.attachment.contentType = contentType;
400 event.content.attachment.uncompressedSize = uncompressedSize;
401 event.content.attachment.uncompressedHash = StoreString(uncompressedHash);
402 event.content.attachment.compressionType = compressionType;
403 event.content.attachment.compressedSize = compressedSize;
404 event.content.attachment.compressedHash = StoreString(compressedHash);
405
406 events_.push_back(event);
407 }
408
409
410 virtual void SignalDeletedResource(const std::string& publicId,
411 OrthancPluginResourceType resourceType) ORTHANC_OVERRIDE
412 {
413 OrthancPluginDatabaseEvent event;
414 event.type = OrthancPluginDatabaseEventType_DeletedResource;
415 event.content.resource.level = resourceType;
416 event.content.resource.publicId = StoreString(publicId);
417
418 events_.push_back(event);
419 }
420
421
422 virtual void SignalRemainingAncestor(const std::string& ancestorId,
423 OrthancPluginResourceType ancestorType) ORTHANC_OVERRIDE
424 {
425 OrthancPluginDatabaseEvent event;
426 event.type = OrthancPluginDatabaseEventType_RemainingAncestor;
427 event.content.resource.level = ancestorType;
428 event.content.resource.publicId = StoreString(ancestorId);
429
430 events_.push_back(event);
431 }
432
433
434 virtual void AnswerAttachment(const std::string& uuid,
435 int32_t contentType,
436 uint64_t uncompressedSize,
437 const std::string& uncompressedHash,
438 int32_t compressionType,
439 uint64_t compressedSize,
440 const std::string& compressedHash) ORTHANC_OVERRIDE
441 {
442 SetupAnswerType(_OrthancPluginDatabaseAnswerType_Attachment);
443
444 OrthancPluginAttachment attachment;
445 attachment.uuid = StoreString(uuid);
446 attachment.contentType = contentType;
447 attachment.uncompressedSize = uncompressedSize;
448 attachment.uncompressedHash = StoreString(uncompressedHash);
449 attachment.compressionType = compressionType;
450 attachment.compressedSize = compressedSize;
451 attachment.compressedHash = StoreString(compressedHash);
452
453 attachments_.push_back(attachment);
454 }
455
456
457 virtual void AnswerChange(int64_t seq,
458 int32_t changeType,
459 OrthancPluginResourceType resourceType,
460 const std::string& publicId,
461 const std::string& date) ORTHANC_OVERRIDE
462 {
463 SetupAnswerType(_OrthancPluginDatabaseAnswerType_Change);
464
465 OrthancPluginChange change;
466 change.seq = seq;
467 change.changeType = changeType;
468 change.resourceType = resourceType;
469 change.publicId = StoreString(publicId);
470 change.date = StoreString(date);
471
472 changes_.push_back(change);
473 }
474
475
476 virtual void AnswerDicomTag(uint16_t group,
477 uint16_t element,
478 const std::string& value) ORTHANC_OVERRIDE
479 {
480 SetupAnswerType(_OrthancPluginDatabaseAnswerType_DicomTag);
481
482 OrthancPluginDicomTag tag;
483 tag.group = group;
484 tag.element = element;
485 tag.value = StoreString(value);
486
487 tags_.push_back(tag);
488 }
489
490
491 virtual void AnswerExportedResource(int64_t seq,
492 OrthancPluginResourceType resourceType,
493 const std::string& publicId,
494 const std::string& modality,
495 const std::string& date,
496 const std::string& patientId,
497 const std::string& studyInstanceUid,
498 const std::string& seriesInstanceUid,
499 const std::string& sopInstanceUid) ORTHANC_OVERRIDE
500 {
501 SetupAnswerType(_OrthancPluginDatabaseAnswerType_ExportedResource);
502
503 OrthancPluginExportedResource exported;
504 exported.seq = seq;
505 exported.resourceType = resourceType;
506 exported.publicId = StoreString(publicId);
507 exported.modality = StoreString(modality);
508 exported.date = StoreString(date);
509 exported.patientId = StoreString(patientId);
510 exported.studyInstanceUid = StoreString(studyInstanceUid);
511 exported.seriesInstanceUid = StoreString(seriesInstanceUid);
512 exported.sopInstanceUid = StoreString(sopInstanceUid);
513
514 exported_.push_back(exported);
515 }
516
517
518 virtual void AnswerMatchingResource(const std::string& resourceId) ORTHANC_OVERRIDE
519 {
520 SetupAnswerType(_OrthancPluginDatabaseAnswerType_MatchingResource);
521
522 OrthancPluginMatchingResource match;
523 match.resourceId = StoreString(resourceId);
524 match.someInstanceId = NULL;
525
526 matches_.push_back(match);
527 }
528
529
530 virtual void AnswerMatchingResource(const std::string& resourceId,
531 const std::string& someInstanceId) ORTHANC_OVERRIDE
532 {
533 SetupAnswerType(_OrthancPluginDatabaseAnswerType_MatchingResource);
534
535 OrthancPluginMatchingResource match;
536 match.resourceId = StoreString(resourceId);
537 match.someInstanceId = StoreString(someInstanceId);
538
539 matches_.push_back(match);
540 }
541
542
543 void AnswerIntegers32(const std::list<int32_t>& values)
544 {
545 SetupAnswerType(_OrthancPluginDatabaseAnswerType_Int32);
546
547 integers32_.reserve(values.size());
548 std::copy(std::begin(values), std::end(values), std::back_inserter(integers32_));
549 }
550
551
552 void AnswerIntegers64(const std::list<int64_t>& values)
553 {
554 SetupAnswerType(_OrthancPluginDatabaseAnswerType_Int64);
555
556 integers64_.reserve(values.size());
557 std::copy(std::begin(values), std::end(values), std::back_inserter(integers64_));
558 }
559
560
561 void AnswerInteger64(int64_t value)
562 {
563 SetupAnswerType(_OrthancPluginDatabaseAnswerType_Int64);
564
565 integers64_.resize(1);
566 integers64_[0] = value;
567 }
568
569
570 void AnswerMetadata(int32_t metadata,
571 const std::string& value)
572 {
573 SetupAnswerType(_OrthancPluginDatabaseAnswerType_Metadata);
574
575 Metadata tmp;
576 tmp.metadata = metadata;
577 tmp.value = StoreString(value);
578
579 metadata_.push_back(tmp);
580 }
581
582
583 void AnswerStrings(const std::list<std::string>& values)
584 {
585 SetupAnswerType(_OrthancPluginDatabaseAnswerType_String);
586
587 stringAnswers_.reserve(values.size());
588 std::copy(std::begin(values), std::end(values), std::back_inserter(stringAnswers_));
589 }
590
591
592 void AnswerString(const std::string& value)
593 {
594 SetupAnswerType(_OrthancPluginDatabaseAnswerType_String);
595
596 if (stringAnswers_.empty())
597 {
598 stringAnswers_.push_back(value);
599 }
600 else
601 {
602 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
603 }
604 }
605 };
606
607
608 IDatabaseBackendOutput* DatabaseBackendAdapterV3::Factory::CreateOutput()
609 {
610 return new DatabaseBackendAdapterV3::Output;
611 }
612
613
614 class DatabaseBackendAdapterV3::Transaction : public boost::noncopyable
615 {
616 private:
617 boost::mutex::scoped_lock lock_; // TODO - REMOVE
618 IndexBackend& backend_;
619 std::unique_ptr<Output> output_;
620
621 static boost::mutex& GetMutex() // TODO - REMOVE
622 {
623 static boost::mutex mutex_;
624 return mutex_;
625 }
626
627 public:
628 Transaction(IndexBackend& backend) :
629 lock_(GetMutex()),
630 backend_(backend),
631 output_(new Output)
632 {
633 }
634
635 ~Transaction()
636 {
637 }
638
639 IndexBackend& GetBackend() const
640 {
641 return backend_;
642 }
643
644 Output& GetOutput() const
645 {
646 return *output_;
647 }
648
649 OrthancPluginContext* GetContext() const
650 {
651 return backend_.GetContext();
652 }
653 };
654
655
656 static OrthancPluginErrorCode ReadAnswersCount(OrthancPluginDatabaseTransaction* transaction,
657 uint32_t* target /* out */)
658 {
659 assert(target != NULL);
660 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
661 return that.GetOutput().ReadAnswersCount(*target);
662 }
663
664
665 static OrthancPluginErrorCode ReadAnswerAttachment(OrthancPluginDatabaseTransaction* transaction,
666 OrthancPluginAttachment* target /* out */,
667 uint32_t index)
668 {
669 assert(target != NULL);
670 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
671 return that.GetOutput().ReadAnswerAttachment(*target, index);
672 }
673
674
675 static OrthancPluginErrorCode ReadAnswerChange(OrthancPluginDatabaseTransaction* transaction,
676 OrthancPluginChange* target /* out */,
677 uint32_t index)
678 {
679 assert(target != NULL);
680 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
681 return that.GetOutput().ReadAnswerChange(*target, index);
682 }
683
684
685 static OrthancPluginErrorCode ReadAnswerDicomTag(OrthancPluginDatabaseTransaction* transaction,
686 uint16_t* group,
687 uint16_t* element,
688 const char** value,
689 uint32_t index)
690 {
691 assert(group != NULL);
692 assert(element != NULL);
693 assert(value != NULL);
694 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
695 return that.GetOutput().ReadAnswerDicomTag(*group, *element, *value, index);
696 }
697
698
699 static OrthancPluginErrorCode ReadAnswerExportedResource(OrthancPluginDatabaseTransaction* transaction,
700 OrthancPluginExportedResource* target /* out */,
701 uint32_t index)
702 {
703 assert(target != NULL);
704 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
705 return that.GetOutput().ReadAnswerExportedResource(*target, index);
706 }
707
708
709 static OrthancPluginErrorCode ReadAnswerInt32(OrthancPluginDatabaseTransaction* transaction,
710 int32_t* target,
711 uint32_t index)
712 {
713 assert(target != NULL);
714 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
715 return that.GetOutput().ReadAnswerInt32(*target, index);
716 }
717
718
719 static OrthancPluginErrorCode ReadAnswerInt64(OrthancPluginDatabaseTransaction* transaction,
720 int64_t* target,
721 uint32_t index)
722 {
723 assert(target != NULL);
724 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
725 return that.GetOutput().ReadAnswerInt64(*target, index);
726 }
727
728
729 static OrthancPluginErrorCode ReadAnswerMatchingResource(OrthancPluginDatabaseTransaction* transaction,
730 OrthancPluginMatchingResource* target,
731 uint32_t index)
732 {
733 assert(target != NULL);
734 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
735 return that.GetOutput().ReadAnswerMatchingResource(*target, index);
736 }
737
738
739 static OrthancPluginErrorCode ReadAnswerMetadata(OrthancPluginDatabaseTransaction* transaction,
740 int32_t* metadata,
741 const char** value,
742 uint32_t index)
743 {
744 assert(metadata != NULL);
745 assert(value != NULL);
746 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
747 return that.GetOutput().ReadAnswerMetadata(*metadata, *value, index);
748 }
749
750
751 static OrthancPluginErrorCode ReadAnswerString(OrthancPluginDatabaseTransaction* transaction,
752 const char** target,
753 uint32_t index)
754 {
755 assert(target != NULL);
756 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
757 return that.GetOutput().ReadAnswerString(*target, index);
758 }
759
760
761 static OrthancPluginErrorCode ReadEventsCount(OrthancPluginDatabaseTransaction* transaction,
762 uint32_t* target /* out */)
763 {
764 assert(target != NULL);
765 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
766 return that.GetOutput().ReadEventsCount(*target);
767 }
768
769
770 static OrthancPluginErrorCode ReadEvent(OrthancPluginDatabaseTransaction* transaction,
771 OrthancPluginDatabaseEvent* event /* out */,
772 uint32_t index)
773 {
774 assert(event != NULL);
775 const DatabaseBackendAdapterV3::Transaction& that = *reinterpret_cast<const DatabaseBackendAdapterV3::Transaction*>(transaction);
776 return that.GetOutput().ReadEvent(*event, index);
777 }
778
779
780 static OrthancPluginErrorCode Open(void* database)
781 {
782 IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
783
784 try
785 {
786 backend->Open();
787 return OrthancPluginErrorCode_Success;
788 }
789 ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
790 }
791
792
793 static OrthancPluginErrorCode Close(void* database)
794 {
795 IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
796
797 try
798 {
799 backend->Close();
800 return OrthancPluginErrorCode_Success;
801 }
802 ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
803 }
804
805
806 static OrthancPluginErrorCode DestructDatabase(void* database)
807 {
808 // Nothing to delete, as this plugin uses a singleton to store backend
809 if (database == NULL)
810 {
811 return OrthancPluginErrorCode_InternalError;
812 }
813 else
814 {
815 return OrthancPluginErrorCode_Success;
816 }
817 }
818
819
820 static OrthancPluginErrorCode GetDatabaseVersion(void* database,
821 uint32_t* version)
822 {
823 IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
824
825 try
826 {
827 *version = backend->GetDatabaseVersion();
828 return OrthancPluginErrorCode_Success;
829 }
830 ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
831 }
832
833
834 static OrthancPluginErrorCode UpgradeDatabase(void* database,
835 OrthancPluginStorageArea* storageArea,
836 uint32_t targetVersion)
837 {
838 IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
839
840 try
841 {
842 backend->UpgradeDatabase(targetVersion, storageArea);
843 return OrthancPluginErrorCode_Success;
844 }
845 ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
846 }
847
848
849 static OrthancPluginErrorCode StartTransaction(void* database,
850 OrthancPluginDatabaseTransaction** target /* out */,
851 OrthancPluginDatabaseTransactionType type)
852 {
853 IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
854
855 try
856 {
857 std::unique_ptr<DatabaseBackendAdapterV3::Transaction> transaction(new DatabaseBackendAdapterV3::Transaction(*backend));
858
859 switch (type)
860 {
861 case OrthancPluginDatabaseTransactionType_ReadOnly:
862 backend->StartTransaction(TransactionType_ReadOnly);
863 break;
864
865 case OrthancPluginDatabaseTransactionType_ReadWrite:
866 backend->StartTransaction(TransactionType_ReadWrite);
867 break;
868
869 default:
870 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
871 }
872
873 *target = reinterpret_cast<OrthancPluginDatabaseTransaction*>(transaction.release());
874
875 return OrthancPluginErrorCode_Success;
876 }
877 ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
878 }
879
880
881 static OrthancPluginErrorCode DestructTransaction(OrthancPluginDatabaseTransaction* transaction)
882 {
883 if (transaction == NULL)
884 {
885 return OrthancPluginErrorCode_NullPointer;
886 }
887 else
888 {
889 delete reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
890 return OrthancPluginErrorCode_Success;
891 }
892 }
893
894
895 static OrthancPluginErrorCode Rollback(OrthancPluginDatabaseTransaction* transaction)
896 {
897 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
898
899 try
900 {
901 t->GetOutput().Clear();
902 t->GetBackend().RollbackTransaction();
903 return OrthancPluginErrorCode_Success;
904 }
905 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
906 }
907
908
909 static OrthancPluginErrorCode Commit(OrthancPluginDatabaseTransaction* transaction,
910 int64_t fileSizeDelta /* TODO - not used? */)
911 {
912 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
913
914 try
915 {
916 t->GetOutput().Clear();
917 t->GetBackend().CommitTransaction();
918 return OrthancPluginErrorCode_Success;
919 }
920 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
921 }
922
923
924 static OrthancPluginErrorCode AddAttachment(OrthancPluginDatabaseTransaction* transaction,
925 int64_t id,
926 const OrthancPluginAttachment* attachment)
927 {
928 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
929
930 try
931 {
932 t->GetOutput().Clear();
933 t->GetBackend().AddAttachment(id, *attachment);
934 return OrthancPluginErrorCode_Success;
935 }
936 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
937 }
938
939
940 static OrthancPluginErrorCode ClearChanges(OrthancPluginDatabaseTransaction* transaction)
941 {
942 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
943
944 try
945 {
946 t->GetOutput().Clear();
947 t->GetBackend().ClearChanges();
948 return OrthancPluginErrorCode_Success;
949 }
950 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
951 }
952
953
954 static OrthancPluginErrorCode ClearExportedResources(OrthancPluginDatabaseTransaction* transaction)
955 {
956 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
957
958 try
959 {
960 t->GetOutput().Clear();
961 t->GetBackend().ClearExportedResources();
962 return OrthancPluginErrorCode_Success;
963 }
964 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
965 }
966
967
968 static OrthancPluginErrorCode ClearMainDicomTags(OrthancPluginDatabaseTransaction* transaction,
969 int64_t resourceId)
970 {
971 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
972
973 try
974 {
975 t->GetOutput().Clear();
976 t->GetBackend().ClearMainDicomTags(resourceId);
977 return OrthancPluginErrorCode_Success;
978 }
979 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
980 }
981
982
983 static OrthancPluginErrorCode CreateInstance(OrthancPluginDatabaseTransaction* transaction,
984 OrthancPluginCreateInstanceResult* target /* out */,
985 const char* hashPatient,
986 const char* hashStudy,
987 const char* hashSeries,
988 const char* hashInstance)
989 {
990 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
991
992 try
993 {
994 t->GetOutput().Clear();
995
996 if (t->GetBackend().HasCreateInstance())
997 {
998 t->GetBackend().CreateInstance(*target, hashPatient, hashStudy, hashSeries, hashInstance);
999 }
1000 else
1001 {
1002 t->GetBackend().CreateInstanceGeneric(*target, hashPatient, hashStudy, hashSeries, hashInstance);
1003 }
1004
1005 return OrthancPluginErrorCode_Success;
1006 }
1007 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1008 }
1009
1010
1011 static OrthancPluginErrorCode DeleteAttachment(OrthancPluginDatabaseTransaction* transaction,
1012 int64_t id,
1013 int32_t contentType)
1014 {
1015 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1016
1017 try
1018 {
1019 t->GetOutput().Clear();
1020 t->GetBackend().DeleteAttachment(t->GetOutput(), id, contentType);
1021 return OrthancPluginErrorCode_Success;
1022 }
1023 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1024 }
1025
1026
1027 static OrthancPluginErrorCode DeleteMetadata(OrthancPluginDatabaseTransaction* transaction,
1028 int64_t id,
1029 int32_t metadataType)
1030 {
1031 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1032
1033 try
1034 {
1035 t->GetOutput().Clear();
1036 t->GetBackend().DeleteMetadata(id, metadataType);
1037 return OrthancPluginErrorCode_Success;
1038 }
1039 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1040 }
1041
1042
1043 static OrthancPluginErrorCode DeleteResource(OrthancPluginDatabaseTransaction* transaction,
1044 int64_t id)
1045 {
1046 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1047
1048 try
1049 {
1050 t->GetOutput().Clear();
1051 t->GetBackend().DeleteResource(t->GetOutput(), id);
1052 return OrthancPluginErrorCode_Success;
1053 }
1054 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1055 }
1056
1057
1058 static OrthancPluginErrorCode GetAllMetadata(OrthancPluginDatabaseTransaction* transaction,
1059 int64_t id)
1060 {
1061 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1062
1063 try
1064 {
1065 t->GetOutput().Clear();
1066
1067 std::map<int32_t, std::string> values;
1068 t->GetBackend().GetAllMetadata(values, id);
1069
1070 for (std::map<int32_t, std::string>::const_iterator it = values.begin(); it != values.end(); ++it)
1071 {
1072 t->GetOutput().AnswerMetadata(it->first, it->second);
1073 }
1074
1075 return OrthancPluginErrorCode_Success;
1076 }
1077 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1078 }
1079
1080
1081 static OrthancPluginErrorCode GetAllPublicIds(OrthancPluginDatabaseTransaction* transaction,
1082 OrthancPluginResourceType resourceType)
1083 {
1084 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1085
1086 try
1087 {
1088 t->GetOutput().Clear();
1089
1090 std::list<std::string> values;
1091 t->GetBackend().GetAllPublicIds(values, resourceType);
1092 t->GetOutput().AnswerStrings(values);
1093
1094 return OrthancPluginErrorCode_Success;
1095 }
1096 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1097 }
1098
1099
1100 static OrthancPluginErrorCode GetAllPublicIdsWithLimit(OrthancPluginDatabaseTransaction* transaction,
1101 OrthancPluginResourceType resourceType,
1102 uint64_t since,
1103 uint64_t limit)
1104 {
1105 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1106
1107 try
1108 {
1109 t->GetOutput().Clear();
1110
1111 std::list<std::string> values;
1112 t->GetBackend().GetAllPublicIds(values, resourceType, since, limit);
1113 t->GetOutput().AnswerStrings(values);
1114
1115 return OrthancPluginErrorCode_Success;
1116 }
1117 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1118 }
1119
1120
1121 static OrthancPluginErrorCode GetChanges(OrthancPluginDatabaseTransaction* transaction,
1122 uint8_t* targetDone /* out */,
1123 int64_t since,
1124 uint32_t maxResults)
1125 {
1126 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1127
1128 try
1129 {
1130 t->GetOutput().Clear();
1131
1132 bool done;
1133 t->GetBackend().GetChanges(t->GetOutput(), done, since, maxResults);
1134 *targetDone = (done ? 1 : 0);
1135
1136 return OrthancPluginErrorCode_Success;
1137 }
1138 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1139 }
1140
1141
1142 static OrthancPluginErrorCode GetChildrenInternalId(OrthancPluginDatabaseTransaction* transaction,
1143 int64_t id)
1144 {
1145 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1146
1147 try
1148 {
1149 t->GetOutput().Clear();
1150
1151 std::list<int64_t> values;
1152 t->GetBackend().GetChildrenInternalId(values, id);
1153 t->GetOutput().AnswerIntegers64(values);
1154
1155 return OrthancPluginErrorCode_Success;
1156 }
1157 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1158 }
1159
1160
1161 static OrthancPluginErrorCode GetChildrenMetadata(OrthancPluginDatabaseTransaction* transaction,
1162 int64_t resourceId,
1163 int32_t metadata)
1164 {
1165 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1166
1167 try
1168 {
1169 t->GetOutput().Clear();
1170
1171 std::list<std::string> values;
1172 t->GetBackend().GetChildrenMetadata(values, resourceId, metadata);
1173 t->GetOutput().AnswerStrings(values);
1174
1175 return OrthancPluginErrorCode_Success;
1176 }
1177 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1178 }
1179
1180
1181 static OrthancPluginErrorCode GetChildrenPublicId(OrthancPluginDatabaseTransaction* transaction,
1182 int64_t id)
1183 {
1184 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1185
1186 try
1187 {
1188 t->GetOutput().Clear();
1189
1190 std::list<std::string> values;
1191 t->GetBackend().GetChildrenPublicId(values, id);
1192 t->GetOutput().AnswerStrings(values);
1193
1194 return OrthancPluginErrorCode_Success;
1195 }
1196 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1197 }
1198
1199
1200 static OrthancPluginErrorCode GetExportedResources(OrthancPluginDatabaseTransaction* transaction,
1201 uint8_t* targetDone /* out */,
1202 int64_t since,
1203 uint32_t maxResults)
1204 {
1205 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1206
1207 try
1208 {
1209 t->GetOutput().Clear();
1210
1211 bool done;
1212 t->GetBackend().GetExportedResources(t->GetOutput(), done, since, maxResults);
1213 *targetDone = (done ? 1 : 0);
1214
1215 return OrthancPluginErrorCode_Success;
1216 }
1217 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1218 }
1219
1220
1221 static OrthancPluginErrorCode GetLastChange(OrthancPluginDatabaseTransaction* transaction)
1222 {
1223 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1224
1225 try
1226 {
1227 t->GetOutput().Clear();
1228 t->GetBackend().GetLastChange(t->GetOutput());
1229 return OrthancPluginErrorCode_Success;
1230 }
1231 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1232 }
1233
1234
1235 static OrthancPluginErrorCode GetLastChangeIndex(OrthancPluginDatabaseTransaction* transaction,
1236 int64_t* target)
1237 {
1238 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1239
1240 try
1241 {
1242 t->GetOutput().Clear();
1243 *target = t->GetBackend().GetLastChangeIndex();
1244 return OrthancPluginErrorCode_Success;
1245 }
1246 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1247 }
1248
1249
1250 static OrthancPluginErrorCode GetLastExportedResource(OrthancPluginDatabaseTransaction* transaction)
1251 {
1252 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1253
1254 try
1255 {
1256 t->GetOutput().Clear();
1257 t->GetBackend().GetLastExportedResource(t->GetOutput());
1258 return OrthancPluginErrorCode_Success;
1259 }
1260 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1261 }
1262
1263
1264 static OrthancPluginErrorCode GetMainDicomTags(OrthancPluginDatabaseTransaction* transaction,
1265 int64_t id)
1266 {
1267 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1268
1269 try
1270 {
1271 t->GetOutput().Clear();
1272 t->GetBackend().GetMainDicomTags(t->GetOutput(), id);
1273 return OrthancPluginErrorCode_Success;
1274 }
1275 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1276 }
1277
1278
1279 static OrthancPluginErrorCode GetPublicId(OrthancPluginDatabaseTransaction* transaction,
1280 int64_t id)
1281 {
1282 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1283
1284 try
1285 {
1286 t->GetOutput().Clear();
1287 t->GetOutput().AnswerString(t->GetBackend().GetPublicId(id));
1288 return OrthancPluginErrorCode_Success;
1289 }
1290 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1291 }
1292
1293
1294 static OrthancPluginErrorCode GetResourcesCount(OrthancPluginDatabaseTransaction* transaction,
1295 uint64_t* target /* out */,
1296 OrthancPluginResourceType resourceType)
1297 {
1298 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1299
1300 try
1301 {
1302 t->GetOutput().Clear();
1303 *target = t->GetBackend().GetResourcesCount(resourceType);
1304 return OrthancPluginErrorCode_Success;
1305 }
1306 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1307 }
1308
1309
1310 static OrthancPluginErrorCode GetResourceType(OrthancPluginDatabaseTransaction* transaction,
1311 OrthancPluginResourceType* target /* out */,
1312 uint64_t resourceId)
1313 {
1314 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1315
1316 try
1317 {
1318 t->GetOutput().Clear();
1319 *target = t->GetBackend().GetResourceType(resourceId);
1320 return OrthancPluginErrorCode_Success;
1321 }
1322 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1323 }
1324
1325
1326 static OrthancPluginErrorCode GetTotalCompressedSize(OrthancPluginDatabaseTransaction* transaction,
1327 uint64_t* target /* out */)
1328 {
1329 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1330
1331 try
1332 {
1333 t->GetOutput().Clear();
1334 *target = t->GetBackend().GetTotalCompressedSize();
1335 return OrthancPluginErrorCode_Success;
1336 }
1337 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1338 }
1339
1340
1341 static OrthancPluginErrorCode GetTotalUncompressedSize(OrthancPluginDatabaseTransaction* transaction,
1342 uint64_t* target /* out */)
1343 {
1344 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1345
1346 try
1347 {
1348 t->GetOutput().Clear();
1349 *target = t->GetBackend().GetTotalUncompressedSize();
1350 return OrthancPluginErrorCode_Success;
1351 }
1352 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1353 }
1354
1355
1356 static OrthancPluginErrorCode IsDiskSizeAbove(OrthancPluginDatabaseTransaction* transaction,
1357 uint8_t* target,
1358 uint64_t threshold)
1359 {
1360 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1361
1362 try
1363 {
1364 t->GetOutput().Clear();
1365 bool above = (t->GetBackend().GetTotalCompressedSize() >= threshold);
1366 *target = (above ? 1 : 0);
1367 return OrthancPluginErrorCode_Success;
1368 }
1369 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1370 }
1371
1372
1373 static OrthancPluginErrorCode IsExistingResource(OrthancPluginDatabaseTransaction* transaction,
1374 uint8_t* target,
1375 int64_t resourceId)
1376 {
1377 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1378
1379 try
1380 {
1381 t->GetOutput().Clear();
1382 bool exists = t->GetBackend().IsExistingResource(resourceId);
1383 *target = (exists ? 1 : 0);
1384 return OrthancPluginErrorCode_Success;
1385 }
1386 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1387 }
1388
1389
1390 static OrthancPluginErrorCode IsProtectedPatient(OrthancPluginDatabaseTransaction* transaction,
1391 uint8_t* target,
1392 int64_t resourceId)
1393 {
1394 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1395
1396 try
1397 {
1398 t->GetOutput().Clear();
1399 bool isProtected = t->GetBackend().IsProtectedPatient(resourceId);
1400 *target = (isProtected ? 1 : 0);
1401 return OrthancPluginErrorCode_Success;
1402 }
1403 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1404 }
1405
1406
1407 static OrthancPluginErrorCode ListAvailableAttachments(OrthancPluginDatabaseTransaction* transaction,
1408 int64_t resourceId)
1409 {
1410 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1411
1412 try
1413 {
1414 t->GetOutput().Clear();
1415
1416 std::list<int32_t> values;
1417 t->GetBackend().ListAvailableAttachments(values, resourceId);
1418 t->GetOutput().AnswerIntegers32(values);
1419 return OrthancPluginErrorCode_Success;
1420 }
1421 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1422 }
1423
1424
1425 static OrthancPluginErrorCode LogChange(OrthancPluginDatabaseTransaction* transaction,
1426 int32_t changeType,
1427 int64_t resourceId,
1428 OrthancPluginResourceType resourceType,
1429 const char* date)
1430 {
1431 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1432
1433 try
1434 {
1435 t->GetOutput().Clear();
1436 t->GetBackend().LogChange(changeType, resourceId, resourceType, date);
1437 return OrthancPluginErrorCode_Success;
1438 }
1439 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1440 }
1441
1442
1443 static OrthancPluginErrorCode LogExportedResource(OrthancPluginDatabaseTransaction* transaction,
1444 OrthancPluginResourceType resourceType,
1445 const char* publicId,
1446 const char* modality,
1447 const char* date,
1448 const char* patientId,
1449 const char* studyInstanceUid,
1450 const char* seriesInstanceUid,
1451 const char* sopInstanceUid)
1452 {
1453 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1454
1455 try
1456 {
1457 OrthancPluginExportedResource exported;
1458 exported.seq = 0;
1459 exported.resourceType = resourceType;
1460 exported.publicId = publicId;
1461 exported.modality = modality;
1462 exported.date = date;
1463 exported.patientId = patientId;
1464 exported.studyInstanceUid = studyInstanceUid;
1465 exported.seriesInstanceUid = seriesInstanceUid;
1466 exported.sopInstanceUid = sopInstanceUid;
1467
1468 t->GetOutput().Clear();
1469 t->GetBackend().LogExportedResource(exported);
1470 return OrthancPluginErrorCode_Success;
1471 }
1472 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1473 }
1474
1475
1476 static OrthancPluginErrorCode LookupAttachment(OrthancPluginDatabaseTransaction* transaction,
1477 int64_t resourceId,
1478 int32_t contentType)
1479 {
1480 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1481
1482 try
1483 {
1484 t->GetOutput().Clear();
1485 t->GetBackend().LookupAttachment(t->GetOutput(), resourceId, contentType);
1486 return OrthancPluginErrorCode_Success;
1487 }
1488 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1489 }
1490
1491
1492 static OrthancPluginErrorCode LookupGlobalProperty(OrthancPluginDatabaseTransaction* transaction,
1493 int32_t property)
1494 {
1495 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1496
1497 try
1498 {
1499 t->GetOutput().Clear();
1500
1501 std::string s;
1502 if (t->GetBackend().LookupGlobalProperty(s, property))
1503 {
1504 t->GetOutput().AnswerString(s);
1505 }
1506
1507 return OrthancPluginErrorCode_Success;
1508 }
1509 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1510 }
1511
1512
1513 static OrthancPluginErrorCode LookupMetadata(OrthancPluginDatabaseTransaction* transaction,
1514 int64_t id,
1515 int32_t metadata)
1516 {
1517 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1518
1519 try
1520 {
1521 t->GetOutput().Clear();
1522
1523 std::string s;
1524 if (t->GetBackend().LookupMetadata(s, id, metadata))
1525 {
1526 t->GetOutput().AnswerString(s);
1527 }
1528
1529 return OrthancPluginErrorCode_Success;
1530 }
1531 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1532 }
1533
1534
1535 static OrthancPluginErrorCode LookupParent(OrthancPluginDatabaseTransaction* transaction,
1536 int64_t id)
1537 {
1538 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1539
1540 try
1541 {
1542 t->GetOutput().Clear();
1543
1544 int64_t parentId;
1545 if (t->GetBackend().LookupParent(parentId, id))
1546 {
1547 t->GetOutput().AnswerInteger64(parentId);
1548 }
1549
1550 return OrthancPluginErrorCode_Success;
1551 }
1552 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1553 }
1554
1555
1556 static OrthancPluginErrorCode LookupResource(OrthancPluginDatabaseTransaction* transaction,
1557 uint8_t* isExisting /* out */,
1558 int64_t* id /* out */,
1559 OrthancPluginResourceType* type /* out */,
1560 const char* publicId)
1561 {
1562 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1563
1564 try
1565 {
1566 t->GetOutput().Clear();
1567
1568 if (t->GetBackend().LookupResource(*id, *type, publicId))
1569 {
1570 *isExisting = 1;
1571 }
1572 else
1573 {
1574 *isExisting = 0;
1575 }
1576
1577 return OrthancPluginErrorCode_Success;
1578 }
1579 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1580 }
1581
1582
1583 static OrthancPluginErrorCode LookupResources(OrthancPluginDatabaseTransaction* transaction,
1584 uint32_t constraintsCount,
1585 const OrthancPluginDatabaseConstraint* constraints,
1586 OrthancPluginResourceType queryLevel,
1587 uint32_t limit,
1588 uint8_t requestSomeInstanceId)
1589 {
1590 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1591
1592 try
1593 {
1594 t->GetOutput().Clear();
1595
1596 std::vector<Orthanc::DatabaseConstraint> lookup;
1597 lookup.reserve(constraintsCount);
1598
1599 for (uint32_t i = 0; i < constraintsCount; i++)
1600 {
1601 lookup.push_back(Orthanc::DatabaseConstraint(constraints[i]));
1602 }
1603
1604 t->GetBackend().LookupResources(t->GetOutput(), lookup, queryLevel, limit, (requestSomeInstanceId != 0));
1605 return OrthancPluginErrorCode_Success;
1606 }
1607 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1608 }
1609
1610
1611 static OrthancPluginErrorCode LookupResourceAndParent(OrthancPluginDatabaseTransaction* transaction,
1612 uint8_t* isExisting /* out */,
1613 int64_t* id /* out */,
1614 OrthancPluginResourceType* type /* out */,
1615 const char* publicId)
1616 {
1617 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1618
1619 try
1620 {
1621 t->GetOutput().Clear();
1622
1623 std::string parent;
1624 if (t->GetBackend().LookupResourceAndParent(*id, *type, parent, publicId))
1625 {
1626 *isExisting = 1;
1627
1628 if (!parent.empty())
1629 {
1630 t->GetOutput().AnswerString(parent);
1631 }
1632 }
1633 else
1634 {
1635 *isExisting = 0;
1636 }
1637
1638 return OrthancPluginErrorCode_Success;
1639 }
1640 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1641 }
1642
1643
1644 static OrthancPluginErrorCode SelectPatientToRecycle(OrthancPluginDatabaseTransaction* transaction)
1645 {
1646 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1647
1648 try
1649 {
1650 t->GetOutput().Clear();
1651
1652 int64_t id;
1653 if (t->GetBackend().SelectPatientToRecycle(id))
1654 {
1655 t->GetOutput().AnswerInteger64(id);
1656 }
1657
1658 return OrthancPluginErrorCode_Success;
1659 }
1660 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1661 }
1662
1663
1664 static OrthancPluginErrorCode SelectPatientToRecycle2(OrthancPluginDatabaseTransaction* transaction,
1665 int64_t patientIdToAvoid)
1666 {
1667 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1668
1669 try
1670 {
1671 t->GetOutput().Clear();
1672
1673 int64_t id;
1674 if (t->GetBackend().SelectPatientToRecycle(id, patientIdToAvoid))
1675 {
1676 t->GetOutput().AnswerInteger64(id);
1677 }
1678
1679 return OrthancPluginErrorCode_Success;
1680 }
1681 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1682 }
1683
1684
1685 static OrthancPluginErrorCode SetGlobalProperty(OrthancPluginDatabaseTransaction* transaction,
1686 int32_t property,
1687 const char* value)
1688 {
1689 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1690
1691 try
1692 {
1693 t->GetOutput().Clear();
1694 t->GetBackend().SetGlobalProperty(property, value);
1695 return OrthancPluginErrorCode_Success;
1696 }
1697 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1698 }
1699
1700
1701 static OrthancPluginErrorCode SetMetadata(OrthancPluginDatabaseTransaction* transaction,
1702 int64_t id,
1703 int32_t metadata,
1704 const char* value)
1705 {
1706 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1707
1708 try
1709 {
1710 t->GetOutput().Clear();
1711 t->GetBackend().SetMetadata(id, metadata, value);
1712 return OrthancPluginErrorCode_Success;
1713 }
1714 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1715 }
1716
1717
1718 static OrthancPluginErrorCode SetProtectedPatient(OrthancPluginDatabaseTransaction* transaction,
1719 int64_t id,
1720 uint8_t isProtected)
1721 {
1722 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1723
1724 try
1725 {
1726 t->GetOutput().Clear();
1727 t->GetBackend().SetProtectedPatient(id, (isProtected != 0));
1728 return OrthancPluginErrorCode_Success;
1729 }
1730 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1731 }
1732
1733
1734 static OrthancPluginErrorCode SetResourcesContent(OrthancPluginDatabaseTransaction* transaction,
1735 uint32_t countIdentifierTags,
1736 const OrthancPluginResourcesContentTags* identifierTags,
1737 uint32_t countMainDicomTags,
1738 const OrthancPluginResourcesContentTags* mainDicomTags,
1739 uint32_t countMetadata,
1740 const OrthancPluginResourcesContentMetadata* metadata)
1741 {
1742 DatabaseBackendAdapterV3::Transaction* t = reinterpret_cast<DatabaseBackendAdapterV3::Transaction*>(transaction);
1743
1744 try
1745 {
1746 t->GetOutput().Clear();
1747 t->GetBackend().SetResourcesContent(countIdentifierTags, identifierTags,
1748 countMainDicomTags, mainDicomTags,
1749 countMetadata, metadata);
1750 return OrthancPluginErrorCode_Success;
1751 }
1752 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1753 }
1754
1755
1756 void DatabaseBackendAdapterV3::Register(IndexBackend& database)
1757 {
1758 OrthancPluginDatabaseBackendV3 params;
1759 memset(&params, 0, sizeof(params));
1760
1761 params.readAnswersCount = ReadAnswersCount;
1762 params.readAnswerAttachment = ReadAnswerAttachment;
1763 params.readAnswerChange = ReadAnswerChange;
1764 params.readAnswerDicomTag = ReadAnswerDicomTag;
1765 params.readAnswerExportedResource = ReadAnswerExportedResource;
1766 params.readAnswerInt32 = ReadAnswerInt32;
1767 params.readAnswerInt64 = ReadAnswerInt64;
1768 params.readAnswerMatchingResource = ReadAnswerMatchingResource;
1769 params.readAnswerMetadata = ReadAnswerMetadata;
1770 params.readAnswerString = ReadAnswerString;
1771
1772 params.readEventsCount = ReadEventsCount;
1773 params.readEvent = ReadEvent;
1774
1775 params.open = Open;
1776 params.close = Close;
1777 params.destructDatabase = DestructDatabase;
1778 params.getDatabaseVersion = GetDatabaseVersion;
1779 params.upgradeDatabase = UpgradeDatabase;
1780 params.startTransaction = StartTransaction;
1781 params.destructTransaction = DestructTransaction;
1782 params.rollback = Rollback;
1783 params.commit = Commit;
1784
1785 params.addAttachment = AddAttachment;
1786 params.clearChanges = ClearChanges;
1787 params.clearExportedResources = ClearExportedResources;
1788 params.clearMainDicomTags = ClearMainDicomTags;
1789 params.createInstance = CreateInstance;
1790 params.deleteAttachment = DeleteAttachment;
1791 params.deleteMetadata = DeleteMetadata;
1792 params.deleteResource = DeleteResource;
1793 params.getAllMetadata = GetAllMetadata;
1794 params.getAllPublicIds = GetAllPublicIds;
1795 params.getAllPublicIdsWithLimit = GetAllPublicIdsWithLimit;
1796 params.getChanges = GetChanges;
1797 params.getChildrenInternalId = GetChildrenInternalId;
1798 params.getChildrenMetadata = GetChildrenMetadata;
1799 params.getChildrenPublicId = GetChildrenPublicId;
1800 params.getExportedResources = GetExportedResources;
1801 params.getLastChange = GetLastChange;
1802 params.getLastChangeIndex = GetLastChangeIndex;
1803 params.getLastExportedResource = GetLastExportedResource;
1804 params.getMainDicomTags = GetMainDicomTags;
1805 params.getPublicId = GetPublicId;
1806 params.getResourcesCount = GetResourcesCount;
1807 params.getResourceType = GetResourceType;
1808 params.getTotalCompressedSize = GetTotalCompressedSize;
1809 params.getTotalUncompressedSize = GetTotalUncompressedSize;
1810 params.isDiskSizeAbove = IsDiskSizeAbove;
1811 params.isExistingResource = IsExistingResource;
1812 params.isProtectedPatient = IsProtectedPatient;
1813 params.listAvailableAttachments = ListAvailableAttachments;
1814 params.logChange = LogChange;
1815 params.logExportedResource = LogExportedResource;
1816 params.lookupAttachment = LookupAttachment;
1817 params.lookupGlobalProperty = LookupGlobalProperty;
1818 params.lookupMetadata = LookupMetadata;
1819 params.lookupParent = LookupParent;
1820 params.lookupResource = LookupResource;
1821 params.lookupResources = LookupResources;
1822 params.lookupResourceAndParent = LookupResourceAndParent;
1823 params.selectPatientToRecycle = SelectPatientToRecycle;
1824 params.selectPatientToRecycle2 = SelectPatientToRecycle2;
1825 params.setGlobalProperty = SetGlobalProperty;
1826 params.setMetadata = SetMetadata;
1827 params.setProtectedPatient = SetProtectedPatient;
1828 params.setResourcesContent = SetResourcesContent;
1829
1830 OrthancPluginContext* context = database.GetContext();
1831
1832 if (OrthancPluginRegisterDatabaseBackendV3(context, &params, sizeof(params), &database) != OrthancPluginErrorCode_Success)
1833 {
1834 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Unable to register the database backend");
1835 }
1836
1837 database.SetOutputFactory(new Factory);
1838 }
1839 }
1840
1841 # endif
1842 #endif