comparison SQLite/Plugins/IndexPlugin.cpp @ 212:821d4ba83dc3

reorganization
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 24 Mar 2021 15:47:14 +0100
parents d74a92ac00ea
children c2e4a909de0e
comparison
equal deleted inserted replaced
211:d74a92ac00ea 212:821d4ba83dc3
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/ 19 **/
20 20
21 21
22 #include "SQLiteIndex.h" 22 #include "SQLiteIndex.h"
23 #include "../../Framework/Plugins/DatabaseBackendAdapterV3.h"
23 #include "../../Framework/Plugins/PluginInitialization.h" 24 #include "../../Framework/Plugins/PluginInitialization.h"
24 25
25 #include <Compatibility.h> // For std::unique_ptr<> 26 #include <Compatibility.h> // For std::unique_ptr<>
26 #include <Logging.h> 27 #include <Logging.h>
27 28
28 static std::unique_ptr<OrthancDatabases::SQLiteIndex> backend_; 29 static std::unique_ptr<OrthancDatabases::SQLiteIndex> backend_;
29
30
31
32 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1
33 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2)
34
35
36 #define ORTHANC_PLUGINS_DATABASE_CATCH(context) \
37 catch (::Orthanc::OrthancException& e) \
38 { \
39 return static_cast<OrthancPluginErrorCode>(e.GetErrorCode()); \
40 } \
41 catch (::std::runtime_error& e) \
42 { \
43 const std::string message = "Exception in database back-end: " + std::string(e.what()); \
44 OrthancPluginLogError(context, message.c_str()); \
45 return OrthancPluginErrorCode_DatabasePlugin; \
46 } \
47 catch (...) \
48 { \
49 OrthancPluginLogError(context, "Native exception"); \
50 return OrthancPluginErrorCode_DatabasePlugin; \
51 }
52
53
54
55 namespace OrthancDatabases
56 {
57 class 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 class Factory : public IDatabaseBackendOutput::IFactory
609 {
610 public:
611 Factory()
612 {
613 }
614
615 virtual IDatabaseBackendOutput* CreateOutput()
616 {
617 return new Output;
618 }
619 };
620
621
622 class Transaction : public boost::noncopyable
623 {
624 private:
625 boost::mutex::scoped_lock lock_; // TODO - REMOVE
626 IndexBackend& backend_;
627 std::unique_ptr<Output> output_;
628
629 static boost::mutex& GetMutex() // TODO - REMOVE
630 {
631 static boost::mutex mutex_;
632 return mutex_;
633 }
634
635 public:
636 Transaction(IndexBackend& backend) :
637 lock_(GetMutex()),
638 backend_(backend),
639 output_(new Output)
640 {
641 }
642
643 ~Transaction()
644 {
645 }
646
647 IndexBackend& GetBackend() const
648 {
649 return backend_;
650 }
651
652 Output& GetOutput() const
653 {
654 return *output_;
655 }
656
657 OrthancPluginContext* GetContext() const
658 {
659 return backend_.GetContext();
660 }
661 };
662
663
664 static OrthancPluginErrorCode ReadAnswersCount(OrthancPluginDatabaseTransaction* transaction,
665 uint32_t* target /* out */)
666 {
667 assert(target != NULL);
668 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
669 return that.GetOutput().ReadAnswersCount(*target);
670 }
671
672
673 static OrthancPluginErrorCode ReadAnswerAttachment(OrthancPluginDatabaseTransaction* transaction,
674 OrthancPluginAttachment* target /* out */,
675 uint32_t index)
676 {
677 assert(target != NULL);
678 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
679 return that.GetOutput().ReadAnswerAttachment(*target, index);
680 }
681
682
683 static OrthancPluginErrorCode ReadAnswerChange(OrthancPluginDatabaseTransaction* transaction,
684 OrthancPluginChange* target /* out */,
685 uint32_t index)
686 {
687 assert(target != NULL);
688 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
689 return that.GetOutput().ReadAnswerChange(*target, index);
690 }
691
692
693 static OrthancPluginErrorCode ReadAnswerDicomTag(OrthancPluginDatabaseTransaction* transaction,
694 uint16_t* group,
695 uint16_t* element,
696 const char** value,
697 uint32_t index)
698 {
699 assert(group != NULL);
700 assert(element != NULL);
701 assert(value != NULL);
702 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
703 return that.GetOutput().ReadAnswerDicomTag(*group, *element, *value, index);
704 }
705
706
707 static OrthancPluginErrorCode ReadAnswerExportedResource(OrthancPluginDatabaseTransaction* transaction,
708 OrthancPluginExportedResource* target /* out */,
709 uint32_t index)
710 {
711 assert(target != NULL);
712 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
713 return that.GetOutput().ReadAnswerExportedResource(*target, index);
714 }
715
716
717 static OrthancPluginErrorCode ReadAnswerInt32(OrthancPluginDatabaseTransaction* transaction,
718 int32_t* target,
719 uint32_t index)
720 {
721 assert(target != NULL);
722 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
723 return that.GetOutput().ReadAnswerInt32(*target, index);
724 }
725
726
727 static OrthancPluginErrorCode ReadAnswerInt64(OrthancPluginDatabaseTransaction* transaction,
728 int64_t* target,
729 uint32_t index)
730 {
731 assert(target != NULL);
732 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
733 return that.GetOutput().ReadAnswerInt64(*target, index);
734 }
735
736
737 static OrthancPluginErrorCode ReadAnswerMatchingResource(OrthancPluginDatabaseTransaction* transaction,
738 OrthancPluginMatchingResource* target,
739 uint32_t index)
740 {
741 assert(target != NULL);
742 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
743 return that.GetOutput().ReadAnswerMatchingResource(*target, index);
744 }
745
746
747 static OrthancPluginErrorCode ReadAnswerMetadata(OrthancPluginDatabaseTransaction* transaction,
748 int32_t* metadata,
749 const char** value,
750 uint32_t index)
751 {
752 assert(metadata != NULL);
753 assert(value != NULL);
754 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
755 return that.GetOutput().ReadAnswerMetadata(*metadata, *value, index);
756 }
757
758
759 static OrthancPluginErrorCode ReadAnswerString(OrthancPluginDatabaseTransaction* transaction,
760 const char** target,
761 uint32_t index)
762 {
763 assert(target != NULL);
764 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
765 return that.GetOutput().ReadAnswerString(*target, index);
766 }
767
768
769 static OrthancPluginErrorCode ReadEventsCount(OrthancPluginDatabaseTransaction* transaction,
770 uint32_t* target /* out */)
771 {
772 assert(target != NULL);
773 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
774 return that.GetOutput().ReadEventsCount(*target);
775 }
776
777
778 static OrthancPluginErrorCode ReadEvent(OrthancPluginDatabaseTransaction* transaction,
779 OrthancPluginDatabaseEvent* event /* out */,
780 uint32_t index)
781 {
782 assert(event != NULL);
783 const Transaction& that = *reinterpret_cast<const Transaction*>(transaction);
784 return that.GetOutput().ReadEvent(*event, index);
785 }
786
787
788 static OrthancPluginErrorCode Open(void* database)
789 {
790 IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
791
792 try
793 {
794 backend->Open();
795 return OrthancPluginErrorCode_Success;
796 }
797 ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
798 }
799
800
801 static OrthancPluginErrorCode Close(void* database)
802 {
803 IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
804
805 try
806 {
807 backend->Close();
808 return OrthancPluginErrorCode_Success;
809 }
810 ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
811 }
812
813
814 static OrthancPluginErrorCode DestructDatabase(void* database)
815 {
816 // Nothing to delete, as this plugin uses a singleton to store backend
817 if (database == NULL)
818 {
819 return OrthancPluginErrorCode_InternalError;
820 }
821 else
822 {
823 return OrthancPluginErrorCode_Success;
824 }
825 }
826
827
828 static OrthancPluginErrorCode GetDatabaseVersion(void* database,
829 uint32_t* version)
830 {
831 IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
832
833 try
834 {
835 *version = backend->GetDatabaseVersion();
836 return OrthancPluginErrorCode_Success;
837 }
838 ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
839 }
840
841
842 static OrthancPluginErrorCode UpgradeDatabase(void* database,
843 OrthancPluginStorageArea* storageArea,
844 uint32_t targetVersion)
845 {
846 IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
847
848 try
849 {
850 backend->UpgradeDatabase(targetVersion, storageArea);
851 return OrthancPluginErrorCode_Success;
852 }
853 ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
854 }
855
856
857 static OrthancPluginErrorCode StartTransaction(void* database,
858 OrthancPluginDatabaseTransaction** target /* out */,
859 OrthancPluginDatabaseTransactionType type)
860 {
861 IndexBackend* backend = reinterpret_cast<IndexBackend*>(database);
862
863 try
864 {
865 std::unique_ptr<Transaction> transaction(new Transaction(*backend));
866
867 switch (type)
868 {
869 case OrthancPluginDatabaseTransactionType_ReadOnly:
870 backend->StartTransaction(TransactionType_ReadOnly);
871 break;
872
873 case OrthancPluginDatabaseTransactionType_ReadWrite:
874 backend->StartTransaction(TransactionType_ReadWrite);
875 break;
876
877 default:
878 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
879 }
880
881 *target = reinterpret_cast<OrthancPluginDatabaseTransaction*>(transaction.release());
882
883 return OrthancPluginErrorCode_Success;
884 }
885 ORTHANC_PLUGINS_DATABASE_CATCH(backend->GetContext());
886 }
887
888
889 static OrthancPluginErrorCode DestructTransaction(OrthancPluginDatabaseTransaction* transaction)
890 {
891 if (transaction == NULL)
892 {
893 return OrthancPluginErrorCode_NullPointer;
894 }
895 else
896 {
897 delete reinterpret_cast<Transaction*>(transaction);
898 return OrthancPluginErrorCode_Success;
899 }
900 }
901
902
903 static OrthancPluginErrorCode Rollback(OrthancPluginDatabaseTransaction* transaction)
904 {
905 Transaction* t = reinterpret_cast<Transaction*>(transaction);
906
907 try
908 {
909 t->GetOutput().Clear();
910 t->GetBackend().RollbackTransaction();
911 return OrthancPluginErrorCode_Success;
912 }
913 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
914 }
915
916
917 static OrthancPluginErrorCode Commit(OrthancPluginDatabaseTransaction* transaction,
918 int64_t fileSizeDelta /* TODO - not used? */)
919 {
920 Transaction* t = reinterpret_cast<Transaction*>(transaction);
921
922 try
923 {
924 t->GetOutput().Clear();
925 t->GetBackend().CommitTransaction();
926 return OrthancPluginErrorCode_Success;
927 }
928 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
929 }
930
931
932 static OrthancPluginErrorCode AddAttachment(OrthancPluginDatabaseTransaction* transaction,
933 int64_t id,
934 const OrthancPluginAttachment* attachment)
935 {
936 Transaction* t = reinterpret_cast<Transaction*>(transaction);
937
938 try
939 {
940 t->GetOutput().Clear();
941 t->GetBackend().AddAttachment(id, *attachment);
942 return OrthancPluginErrorCode_Success;
943 }
944 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
945 }
946
947
948 static OrthancPluginErrorCode ClearChanges(OrthancPluginDatabaseTransaction* transaction)
949 {
950 Transaction* t = reinterpret_cast<Transaction*>(transaction);
951
952 try
953 {
954 t->GetOutput().Clear();
955 t->GetBackend().ClearChanges();
956 return OrthancPluginErrorCode_Success;
957 }
958 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
959 }
960
961
962 static OrthancPluginErrorCode ClearExportedResources(OrthancPluginDatabaseTransaction* transaction)
963 {
964 Transaction* t = reinterpret_cast<Transaction*>(transaction);
965
966 try
967 {
968 t->GetOutput().Clear();
969 t->GetBackend().ClearExportedResources();
970 return OrthancPluginErrorCode_Success;
971 }
972 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
973 }
974
975
976 static OrthancPluginErrorCode ClearMainDicomTags(OrthancPluginDatabaseTransaction* transaction,
977 int64_t resourceId)
978 {
979 Transaction* t = reinterpret_cast<Transaction*>(transaction);
980
981 try
982 {
983 t->GetOutput().Clear();
984 t->GetBackend().ClearMainDicomTags(resourceId);
985 return OrthancPluginErrorCode_Success;
986 }
987 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
988 }
989
990
991 static OrthancPluginErrorCode CreateInstance(OrthancPluginDatabaseTransaction* transaction,
992 OrthancPluginCreateInstanceResult* target /* out */,
993 const char* hashPatient,
994 const char* hashStudy,
995 const char* hashSeries,
996 const char* hashInstance)
997 {
998 Transaction* t = reinterpret_cast<Transaction*>(transaction);
999
1000 try
1001 {
1002 t->GetOutput().Clear();
1003
1004 if (t->GetBackend().HasCreateInstance())
1005 {
1006 t->GetBackend().CreateInstance(*target, hashPatient, hashStudy, hashSeries, hashInstance);
1007 }
1008 else
1009 {
1010 t->GetBackend().CreateInstanceGeneric(*target, hashPatient, hashStudy, hashSeries, hashInstance);
1011 }
1012
1013 return OrthancPluginErrorCode_Success;
1014 }
1015 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1016 }
1017
1018
1019 static OrthancPluginErrorCode DeleteAttachment(OrthancPluginDatabaseTransaction* transaction,
1020 int64_t id,
1021 int32_t contentType)
1022 {
1023 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1024
1025 try
1026 {
1027 t->GetOutput().Clear();
1028 t->GetBackend().DeleteAttachment(t->GetOutput(), id, contentType);
1029 return OrthancPluginErrorCode_Success;
1030 }
1031 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1032 }
1033
1034
1035 static OrthancPluginErrorCode DeleteMetadata(OrthancPluginDatabaseTransaction* transaction,
1036 int64_t id,
1037 int32_t metadataType)
1038 {
1039 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1040
1041 try
1042 {
1043 t->GetOutput().Clear();
1044 t->GetBackend().DeleteMetadata(id, metadataType);
1045 return OrthancPluginErrorCode_Success;
1046 }
1047 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1048 }
1049
1050
1051 static OrthancPluginErrorCode DeleteResource(OrthancPluginDatabaseTransaction* transaction,
1052 int64_t id)
1053 {
1054 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1055
1056 try
1057 {
1058 t->GetOutput().Clear();
1059 t->GetBackend().DeleteResource(t->GetOutput(), id);
1060 return OrthancPluginErrorCode_Success;
1061 }
1062 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1063 }
1064
1065
1066 static OrthancPluginErrorCode GetAllMetadata(OrthancPluginDatabaseTransaction* transaction,
1067 int64_t id)
1068 {
1069 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1070
1071 try
1072 {
1073 t->GetOutput().Clear();
1074
1075 std::map<int32_t, std::string> values;
1076 t->GetBackend().GetAllMetadata(values, id);
1077
1078 for (std::map<int32_t, std::string>::const_iterator it = values.begin(); it != values.end(); ++it)
1079 {
1080 t->GetOutput().AnswerMetadata(it->first, it->second);
1081 }
1082
1083 return OrthancPluginErrorCode_Success;
1084 }
1085 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1086 }
1087
1088
1089 static OrthancPluginErrorCode GetAllPublicIds(OrthancPluginDatabaseTransaction* transaction,
1090 OrthancPluginResourceType resourceType)
1091 {
1092 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1093
1094 try
1095 {
1096 t->GetOutput().Clear();
1097
1098 std::list<std::string> values;
1099 t->GetBackend().GetAllPublicIds(values, resourceType);
1100 t->GetOutput().AnswerStrings(values);
1101
1102 return OrthancPluginErrorCode_Success;
1103 }
1104 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1105 }
1106
1107
1108 static OrthancPluginErrorCode GetAllPublicIdsWithLimit(OrthancPluginDatabaseTransaction* transaction,
1109 OrthancPluginResourceType resourceType,
1110 uint64_t since,
1111 uint64_t limit)
1112 {
1113 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1114
1115 try
1116 {
1117 t->GetOutput().Clear();
1118
1119 std::list<std::string> values;
1120 t->GetBackend().GetAllPublicIds(values, resourceType, since, limit);
1121 t->GetOutput().AnswerStrings(values);
1122
1123 return OrthancPluginErrorCode_Success;
1124 }
1125 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1126 }
1127
1128
1129 static OrthancPluginErrorCode GetChanges(OrthancPluginDatabaseTransaction* transaction,
1130 uint8_t* targetDone /* out */,
1131 int64_t since,
1132 uint32_t maxResults)
1133 {
1134 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1135
1136 try
1137 {
1138 t->GetOutput().Clear();
1139
1140 bool done;
1141 t->GetBackend().GetChanges(t->GetOutput(), done, since, maxResults);
1142 *targetDone = (done ? 1 : 0);
1143
1144 return OrthancPluginErrorCode_Success;
1145 }
1146 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1147 }
1148
1149
1150 static OrthancPluginErrorCode GetChildrenInternalId(OrthancPluginDatabaseTransaction* transaction,
1151 int64_t id)
1152 {
1153 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1154
1155 try
1156 {
1157 t->GetOutput().Clear();
1158
1159 std::list<int64_t> values;
1160 t->GetBackend().GetChildrenInternalId(values, id);
1161 t->GetOutput().AnswerIntegers64(values);
1162
1163 return OrthancPluginErrorCode_Success;
1164 }
1165 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1166 }
1167
1168
1169 static OrthancPluginErrorCode GetChildrenMetadata(OrthancPluginDatabaseTransaction* transaction,
1170 int64_t resourceId,
1171 int32_t metadata)
1172 {
1173 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1174
1175 try
1176 {
1177 t->GetOutput().Clear();
1178
1179 std::list<std::string> values;
1180 t->GetBackend().GetChildrenMetadata(values, resourceId, metadata);
1181 t->GetOutput().AnswerStrings(values);
1182
1183 return OrthancPluginErrorCode_Success;
1184 }
1185 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1186 }
1187
1188
1189 static OrthancPluginErrorCode GetChildrenPublicId(OrthancPluginDatabaseTransaction* transaction,
1190 int64_t id)
1191 {
1192 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1193
1194 try
1195 {
1196 t->GetOutput().Clear();
1197
1198 std::list<std::string> values;
1199 t->GetBackend().GetChildrenPublicId(values, id);
1200 t->GetOutput().AnswerStrings(values);
1201
1202 return OrthancPluginErrorCode_Success;
1203 }
1204 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1205 }
1206
1207
1208 static OrthancPluginErrorCode GetExportedResources(OrthancPluginDatabaseTransaction* transaction,
1209 uint8_t* targetDone /* out */,
1210 int64_t since,
1211 uint32_t maxResults)
1212 {
1213 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1214
1215 try
1216 {
1217 t->GetOutput().Clear();
1218
1219 bool done;
1220 t->GetBackend().GetExportedResources(t->GetOutput(), done, since, maxResults);
1221 *targetDone = (done ? 1 : 0);
1222
1223 return OrthancPluginErrorCode_Success;
1224 }
1225 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1226 }
1227
1228
1229 static OrthancPluginErrorCode GetLastChange(OrthancPluginDatabaseTransaction* transaction)
1230 {
1231 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1232
1233 try
1234 {
1235 t->GetOutput().Clear();
1236 t->GetBackend().GetLastChange(t->GetOutput());
1237 return OrthancPluginErrorCode_Success;
1238 }
1239 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1240 }
1241
1242
1243 static OrthancPluginErrorCode GetLastChangeIndex(OrthancPluginDatabaseTransaction* transaction,
1244 int64_t* target)
1245 {
1246 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1247
1248 try
1249 {
1250 t->GetOutput().Clear();
1251 *target = t->GetBackend().GetLastChangeIndex();
1252 return OrthancPluginErrorCode_Success;
1253 }
1254 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1255 }
1256
1257
1258 static OrthancPluginErrorCode GetLastExportedResource(OrthancPluginDatabaseTransaction* transaction)
1259 {
1260 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1261
1262 try
1263 {
1264 t->GetOutput().Clear();
1265 t->GetBackend().GetLastExportedResource(t->GetOutput());
1266 return OrthancPluginErrorCode_Success;
1267 }
1268 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1269 }
1270
1271
1272 static OrthancPluginErrorCode GetMainDicomTags(OrthancPluginDatabaseTransaction* transaction,
1273 int64_t id)
1274 {
1275 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1276
1277 try
1278 {
1279 t->GetOutput().Clear();
1280 t->GetBackend().GetMainDicomTags(t->GetOutput(), id);
1281 return OrthancPluginErrorCode_Success;
1282 }
1283 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1284 }
1285
1286
1287 static OrthancPluginErrorCode GetPublicId(OrthancPluginDatabaseTransaction* transaction,
1288 int64_t id)
1289 {
1290 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1291
1292 try
1293 {
1294 t->GetOutput().Clear();
1295 t->GetOutput().AnswerString(t->GetBackend().GetPublicId(id));
1296 return OrthancPluginErrorCode_Success;
1297 }
1298 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1299 }
1300
1301
1302 static OrthancPluginErrorCode GetResourcesCount(OrthancPluginDatabaseTransaction* transaction,
1303 uint64_t* target /* out */,
1304 OrthancPluginResourceType resourceType)
1305 {
1306 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1307
1308 try
1309 {
1310 t->GetOutput().Clear();
1311 *target = t->GetBackend().GetResourcesCount(resourceType);
1312 return OrthancPluginErrorCode_Success;
1313 }
1314 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1315 }
1316
1317
1318 static OrthancPluginErrorCode GetResourceType(OrthancPluginDatabaseTransaction* transaction,
1319 OrthancPluginResourceType* target /* out */,
1320 uint64_t resourceId)
1321 {
1322 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1323
1324 try
1325 {
1326 t->GetOutput().Clear();
1327 *target = t->GetBackend().GetResourceType(resourceId);
1328 return OrthancPluginErrorCode_Success;
1329 }
1330 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1331 }
1332
1333
1334 static OrthancPluginErrorCode GetTotalCompressedSize(OrthancPluginDatabaseTransaction* transaction,
1335 uint64_t* target /* out */)
1336 {
1337 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1338
1339 try
1340 {
1341 t->GetOutput().Clear();
1342 *target = t->GetBackend().GetTotalCompressedSize();
1343 return OrthancPluginErrorCode_Success;
1344 }
1345 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1346 }
1347
1348
1349 static OrthancPluginErrorCode GetTotalUncompressedSize(OrthancPluginDatabaseTransaction* transaction,
1350 uint64_t* target /* out */)
1351 {
1352 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1353
1354 try
1355 {
1356 t->GetOutput().Clear();
1357 *target = t->GetBackend().GetTotalUncompressedSize();
1358 return OrthancPluginErrorCode_Success;
1359 }
1360 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1361 }
1362
1363
1364 static OrthancPluginErrorCode IsDiskSizeAbove(OrthancPluginDatabaseTransaction* transaction,
1365 uint8_t* target,
1366 uint64_t threshold)
1367 {
1368 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1369
1370 try
1371 {
1372 t->GetOutput().Clear();
1373 bool above = (t->GetBackend().GetTotalCompressedSize() >= threshold);
1374 *target = (above ? 1 : 0);
1375 return OrthancPluginErrorCode_Success;
1376 }
1377 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1378 }
1379
1380
1381 static OrthancPluginErrorCode IsExistingResource(OrthancPluginDatabaseTransaction* transaction,
1382 uint8_t* target,
1383 int64_t resourceId)
1384 {
1385 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1386
1387 try
1388 {
1389 t->GetOutput().Clear();
1390 bool exists = t->GetBackend().IsExistingResource(resourceId);
1391 *target = (exists ? 1 : 0);
1392 return OrthancPluginErrorCode_Success;
1393 }
1394 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1395 }
1396
1397
1398 static OrthancPluginErrorCode IsProtectedPatient(OrthancPluginDatabaseTransaction* transaction,
1399 uint8_t* target,
1400 int64_t resourceId)
1401 {
1402 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1403
1404 try
1405 {
1406 t->GetOutput().Clear();
1407 bool isProtected = t->GetBackend().IsProtectedPatient(resourceId);
1408 *target = (isProtected ? 1 : 0);
1409 return OrthancPluginErrorCode_Success;
1410 }
1411 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1412 }
1413
1414
1415 static OrthancPluginErrorCode ListAvailableAttachments(OrthancPluginDatabaseTransaction* transaction,
1416 int64_t resourceId)
1417 {
1418 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1419
1420 try
1421 {
1422 t->GetOutput().Clear();
1423
1424 std::list<int32_t> values;
1425 t->GetBackend().ListAvailableAttachments(values, resourceId);
1426 t->GetOutput().AnswerIntegers32(values);
1427 return OrthancPluginErrorCode_Success;
1428 }
1429 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1430 }
1431
1432
1433 static OrthancPluginErrorCode LogChange(OrthancPluginDatabaseTransaction* transaction,
1434 int32_t changeType,
1435 int64_t resourceId,
1436 OrthancPluginResourceType resourceType,
1437 const char* date)
1438 {
1439 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1440
1441 try
1442 {
1443 t->GetOutput().Clear();
1444 t->GetBackend().LogChange(changeType, resourceId, resourceType, date);
1445 return OrthancPluginErrorCode_Success;
1446 }
1447 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1448 }
1449
1450
1451 static OrthancPluginErrorCode LogExportedResource(OrthancPluginDatabaseTransaction* transaction,
1452 OrthancPluginResourceType resourceType,
1453 const char* publicId,
1454 const char* modality,
1455 const char* date,
1456 const char* patientId,
1457 const char* studyInstanceUid,
1458 const char* seriesInstanceUid,
1459 const char* sopInstanceUid)
1460 {
1461 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1462
1463 try
1464 {
1465 OrthancPluginExportedResource exported;
1466 exported.seq = 0;
1467 exported.resourceType = resourceType;
1468 exported.publicId = publicId;
1469 exported.modality = modality;
1470 exported.date = date;
1471 exported.patientId = patientId;
1472 exported.studyInstanceUid = studyInstanceUid;
1473 exported.seriesInstanceUid = seriesInstanceUid;
1474 exported.sopInstanceUid = sopInstanceUid;
1475
1476 t->GetOutput().Clear();
1477 t->GetBackend().LogExportedResource(exported);
1478 return OrthancPluginErrorCode_Success;
1479 }
1480 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1481 }
1482
1483
1484 static OrthancPluginErrorCode LookupAttachment(OrthancPluginDatabaseTransaction* transaction,
1485 int64_t resourceId,
1486 int32_t contentType)
1487 {
1488 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1489
1490 try
1491 {
1492 t->GetOutput().Clear();
1493 t->GetBackend().LookupAttachment(t->GetOutput(), resourceId, contentType);
1494 return OrthancPluginErrorCode_Success;
1495 }
1496 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1497 }
1498
1499
1500 static OrthancPluginErrorCode LookupGlobalProperty(OrthancPluginDatabaseTransaction* transaction,
1501 int32_t property)
1502 {
1503 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1504
1505 try
1506 {
1507 t->GetOutput().Clear();
1508
1509 std::string s;
1510 if (t->GetBackend().LookupGlobalProperty(s, property))
1511 {
1512 t->GetOutput().AnswerString(s);
1513 }
1514
1515 return OrthancPluginErrorCode_Success;
1516 }
1517 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1518 }
1519
1520
1521 static OrthancPluginErrorCode LookupMetadata(OrthancPluginDatabaseTransaction* transaction,
1522 int64_t id,
1523 int32_t metadata)
1524 {
1525 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1526
1527 try
1528 {
1529 t->GetOutput().Clear();
1530
1531 std::string s;
1532 if (t->GetBackend().LookupMetadata(s, id, metadata))
1533 {
1534 t->GetOutput().AnswerString(s);
1535 }
1536
1537 return OrthancPluginErrorCode_Success;
1538 }
1539 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1540 }
1541
1542
1543 static OrthancPluginErrorCode LookupParent(OrthancPluginDatabaseTransaction* transaction,
1544 int64_t id)
1545 {
1546 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1547
1548 try
1549 {
1550 t->GetOutput().Clear();
1551
1552 int64_t parentId;
1553 if (t->GetBackend().LookupParent(parentId, id))
1554 {
1555 t->GetOutput().AnswerInteger64(parentId);
1556 }
1557
1558 return OrthancPluginErrorCode_Success;
1559 }
1560 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1561 }
1562
1563
1564 static OrthancPluginErrorCode LookupResource(OrthancPluginDatabaseTransaction* transaction,
1565 uint8_t* isExisting /* out */,
1566 int64_t* id /* out */,
1567 OrthancPluginResourceType* type /* out */,
1568 const char* publicId)
1569 {
1570 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1571
1572 try
1573 {
1574 t->GetOutput().Clear();
1575
1576 if (t->GetBackend().LookupResource(*id, *type, publicId))
1577 {
1578 *isExisting = 1;
1579 }
1580 else
1581 {
1582 *isExisting = 0;
1583 }
1584
1585 return OrthancPluginErrorCode_Success;
1586 }
1587 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1588 }
1589
1590
1591 static OrthancPluginErrorCode LookupResources(OrthancPluginDatabaseTransaction* transaction,
1592 uint32_t constraintsCount,
1593 const OrthancPluginDatabaseConstraint* constraints,
1594 OrthancPluginResourceType queryLevel,
1595 uint32_t limit,
1596 uint8_t requestSomeInstanceId)
1597 {
1598 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1599
1600 try
1601 {
1602 t->GetOutput().Clear();
1603
1604 std::vector<Orthanc::DatabaseConstraint> lookup;
1605 lookup.reserve(constraintsCount);
1606
1607 for (uint32_t i = 0; i < constraintsCount; i++)
1608 {
1609 lookup.push_back(Orthanc::DatabaseConstraint(constraints[i]));
1610 }
1611
1612 t->GetBackend().LookupResources(t->GetOutput(), lookup, queryLevel, limit, (requestSomeInstanceId != 0));
1613 return OrthancPluginErrorCode_Success;
1614 }
1615 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1616 }
1617
1618
1619 static OrthancPluginErrorCode LookupResourceAndParent(OrthancPluginDatabaseTransaction* transaction,
1620 uint8_t* isExisting /* out */,
1621 int64_t* id /* out */,
1622 OrthancPluginResourceType* type /* out */,
1623 const char* publicId)
1624 {
1625 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1626
1627 try
1628 {
1629 t->GetOutput().Clear();
1630
1631 std::string parent;
1632 if (t->GetBackend().LookupResourceAndParent(*id, *type, parent, publicId))
1633 {
1634 *isExisting = 1;
1635
1636 if (!parent.empty())
1637 {
1638 t->GetOutput().AnswerString(parent);
1639 }
1640 }
1641 else
1642 {
1643 *isExisting = 0;
1644 }
1645
1646 return OrthancPluginErrorCode_Success;
1647 }
1648 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1649 }
1650
1651
1652 static OrthancPluginErrorCode SelectPatientToRecycle(OrthancPluginDatabaseTransaction* transaction)
1653 {
1654 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1655
1656 try
1657 {
1658 t->GetOutput().Clear();
1659
1660 int64_t id;
1661 if (t->GetBackend().SelectPatientToRecycle(id))
1662 {
1663 t->GetOutput().AnswerInteger64(id);
1664 }
1665
1666 return OrthancPluginErrorCode_Success;
1667 }
1668 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1669 }
1670
1671
1672 static OrthancPluginErrorCode SelectPatientToRecycle2(OrthancPluginDatabaseTransaction* transaction,
1673 int64_t patientIdToAvoid)
1674 {
1675 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1676
1677 try
1678 {
1679 t->GetOutput().Clear();
1680
1681 int64_t id;
1682 if (t->GetBackend().SelectPatientToRecycle(id, patientIdToAvoid))
1683 {
1684 t->GetOutput().AnswerInteger64(id);
1685 }
1686
1687 return OrthancPluginErrorCode_Success;
1688 }
1689 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1690 }
1691
1692
1693 static OrthancPluginErrorCode SetGlobalProperty(OrthancPluginDatabaseTransaction* transaction,
1694 int32_t property,
1695 const char* value)
1696 {
1697 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1698
1699 try
1700 {
1701 t->GetOutput().Clear();
1702 t->GetBackend().SetGlobalProperty(property, value);
1703 return OrthancPluginErrorCode_Success;
1704 }
1705 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1706 }
1707
1708
1709 static OrthancPluginErrorCode SetMetadata(OrthancPluginDatabaseTransaction* transaction,
1710 int64_t id,
1711 int32_t metadata,
1712 const char* value)
1713 {
1714 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1715
1716 try
1717 {
1718 t->GetOutput().Clear();
1719 t->GetBackend().SetMetadata(id, metadata, value);
1720 return OrthancPluginErrorCode_Success;
1721 }
1722 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1723 }
1724
1725
1726 static OrthancPluginErrorCode SetProtectedPatient(OrthancPluginDatabaseTransaction* transaction,
1727 int64_t id,
1728 uint8_t isProtected)
1729 {
1730 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1731
1732 try
1733 {
1734 t->GetOutput().Clear();
1735 t->GetBackend().SetProtectedPatient(id, (isProtected != 0));
1736 return OrthancPluginErrorCode_Success;
1737 }
1738 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1739 }
1740
1741
1742 static OrthancPluginErrorCode SetResourcesContent(OrthancPluginDatabaseTransaction* transaction,
1743 uint32_t countIdentifierTags,
1744 const OrthancPluginResourcesContentTags* identifierTags,
1745 uint32_t countMainDicomTags,
1746 const OrthancPluginResourcesContentTags* mainDicomTags,
1747 uint32_t countMetadata,
1748 const OrthancPluginResourcesContentMetadata* metadata)
1749 {
1750 Transaction* t = reinterpret_cast<Transaction*>(transaction);
1751
1752 try
1753 {
1754 t->GetOutput().Clear();
1755 t->GetBackend().SetResourcesContent(countIdentifierTags, identifierTags,
1756 countMainDicomTags, mainDicomTags,
1757 countMetadata, metadata);
1758 return OrthancPluginErrorCode_Success;
1759 }
1760 ORTHANC_PLUGINS_DATABASE_CATCH(t->GetContext());
1761 }
1762
1763
1764 static void RegisterV3(IndexBackend& database)
1765 {
1766 OrthancPluginDatabaseBackendV3 params;
1767 memset(&params, 0, sizeof(params));
1768
1769 params.readAnswersCount = ReadAnswersCount;
1770 params.readAnswerAttachment = ReadAnswerAttachment;
1771 params.readAnswerChange = ReadAnswerChange;
1772 params.readAnswerDicomTag = ReadAnswerDicomTag;
1773 params.readAnswerExportedResource = ReadAnswerExportedResource;
1774 params.readAnswerInt32 = ReadAnswerInt32;
1775 params.readAnswerInt64 = ReadAnswerInt64;
1776 params.readAnswerMatchingResource = ReadAnswerMatchingResource;
1777 params.readAnswerMetadata = ReadAnswerMetadata;
1778 params.readAnswerString = ReadAnswerString;
1779
1780 params.readEventsCount = ReadEventsCount;
1781 params.readEvent = ReadEvent;
1782
1783 params.open = Open;
1784 params.close = Close;
1785 params.destructDatabase = DestructDatabase;
1786 params.getDatabaseVersion = GetDatabaseVersion;
1787 params.upgradeDatabase = UpgradeDatabase;
1788 params.startTransaction = StartTransaction;
1789 params.destructTransaction = DestructTransaction;
1790 params.rollback = Rollback;
1791 params.commit = Commit;
1792
1793 params.addAttachment = AddAttachment;
1794 params.clearChanges = ClearChanges;
1795 params.clearExportedResources = ClearExportedResources;
1796 params.clearMainDicomTags = ClearMainDicomTags;
1797 params.createInstance = CreateInstance;
1798 params.deleteAttachment = DeleteAttachment;
1799 params.deleteMetadata = DeleteMetadata;
1800 params.deleteResource = DeleteResource;
1801 params.getAllMetadata = GetAllMetadata;
1802 params.getAllPublicIds = GetAllPublicIds;
1803 params.getAllPublicIdsWithLimit = GetAllPublicIdsWithLimit;
1804 params.getChanges = GetChanges;
1805 params.getChildrenInternalId = GetChildrenInternalId;
1806 params.getChildrenMetadata = GetChildrenMetadata;
1807 params.getChildrenPublicId = GetChildrenPublicId;
1808 params.getExportedResources = GetExportedResources;
1809 params.getLastChange = GetLastChange;
1810 params.getLastChangeIndex = GetLastChangeIndex;
1811 params.getLastExportedResource = GetLastExportedResource;
1812 params.getMainDicomTags = GetMainDicomTags;
1813 params.getPublicId = GetPublicId;
1814 params.getResourcesCount = GetResourcesCount;
1815 params.getResourceType = GetResourceType;
1816 params.getTotalCompressedSize = GetTotalCompressedSize;
1817 params.getTotalUncompressedSize = GetTotalUncompressedSize;
1818 params.isDiskSizeAbove = IsDiskSizeAbove;
1819 params.isExistingResource = IsExistingResource;
1820 params.isProtectedPatient = IsProtectedPatient;
1821 params.listAvailableAttachments = ListAvailableAttachments;
1822 params.logChange = LogChange;
1823 params.logExportedResource = LogExportedResource;
1824 params.lookupAttachment = LookupAttachment;
1825 params.lookupGlobalProperty = LookupGlobalProperty;
1826 params.lookupMetadata = LookupMetadata;
1827 params.lookupParent = LookupParent;
1828 params.lookupResource = LookupResource;
1829 params.lookupResources = LookupResources;
1830 params.lookupResourceAndParent = LookupResourceAndParent;
1831 params.selectPatientToRecycle = SelectPatientToRecycle;
1832 params.selectPatientToRecycle2 = SelectPatientToRecycle2;
1833 params.setGlobalProperty = SetGlobalProperty;
1834 params.setMetadata = SetMetadata;
1835 params.setProtectedPatient = SetProtectedPatient;
1836 params.setResourcesContent = SetResourcesContent;
1837
1838 OrthancPluginContext* context = database.GetContext();
1839
1840 if (OrthancPluginRegisterDatabaseBackendV3(context, &params, sizeof(params), &database) != OrthancPluginErrorCode_Success)
1841 {
1842 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Unable to register the database backend");
1843 }
1844
1845 database.SetOutputFactory(new Factory);
1846 }
1847 }
1848
1849 # endif
1850 #endif
1851
1852 30
1853 31
1854 extern "C" 32 extern "C"
1855 { 33 {
1856 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) 34 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context)
1893 71
1894 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 72 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1
1895 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) 73 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2)
1896 if (OrthancPluginCheckVersionAdvanced(context, 1, 9, 2) == 1) 74 if (OrthancPluginCheckVersionAdvanced(context, 1, 9, 2) == 1)
1897 { 75 {
1898 RegisterV3(*backend_); 76 OrthancDatabases::DatabaseBackendAdapterV3::Register(*backend_);
1899 hasLoadedV3 = true; 77 hasLoadedV3 = true;
1900 } 78 }
1901 # endif 79 # endif
1902 #endif 80 #endif
1903 81