Mercurial > hg > orthanc
comparison OrthancServer/Plugins/Engine/OrthancPluginDatabaseV4.cpp @ 5083:75e949689c08 attach-custom-data
PluginDatabaseV4 to handle customData
author | Alain Mazy <am@osimis.io> |
---|---|
date | Wed, 14 Sep 2022 17:11:45 +0200 |
parents | |
children | 8279eaab0d1d |
comparison
equal
deleted
inserted
replaced
5082:4af5f496a0dd | 5083:75e949689c08 |
---|---|
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-2022 Osimis S.A., Belgium | |
6 * Copyright (C) 2021-2022 Sebastien Jodogne, ICTEAM UCLouvain, Belgium | |
7 * | |
8 * This program is free software: you can redistribute it and/or | |
9 * modify it under the terms of the GNU General Public License as | |
10 * published by the Free Software Foundation, either version 3 of the | |
11 * License, or (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, but | |
14 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 **/ | |
21 | |
22 | |
23 #include "../../Sources/PrecompiledHeadersServer.h" | |
24 #include "OrthancPluginDatabaseV4.h" | |
25 | |
26 #if ORTHANC_ENABLE_PLUGINS != 1 | |
27 # error The plugin support is disabled | |
28 #endif | |
29 | |
30 #include "../../../OrthancFramework/Sources/Logging.h" | |
31 #include "../../../OrthancFramework/Sources/OrthancException.h" | |
32 #include "../../Sources/Database/ResourcesContent.h" | |
33 #include "../../Sources/Database/VoidDatabaseListener.h" | |
34 #include "PluginsEnumerations.h" | |
35 | |
36 #include <cassert> | |
37 | |
38 | |
39 #define CHECK_FUNCTION_EXISTS(backend, func) \ | |
40 if (backend.func == NULL) \ | |
41 { \ | |
42 throw OrthancException( \ | |
43 ErrorCode_DatabasePlugin, "Missing primitive: " #func "()"); \ | |
44 } | |
45 | |
46 namespace Orthanc | |
47 { | |
48 class OrthancPluginDatabaseV4::Transaction : public IDatabaseWrapper::ITransaction | |
49 { | |
50 private: | |
51 OrthancPluginDatabaseV4& that_; | |
52 IDatabaseListener& listener_; | |
53 OrthancPluginDatabaseTransaction* transaction_; | |
54 | |
55 | |
56 void CheckSuccess(OrthancPluginErrorCode code) const | |
57 { | |
58 that_.CheckSuccess(code); | |
59 } | |
60 | |
61 | |
62 static FileInfo Convert(const OrthancPluginAttachment& attachment) | |
63 { | |
64 std::string customData; | |
65 return FileInfo(attachment.uuid, | |
66 static_cast<FileContentType>(attachment.contentType), | |
67 attachment.uncompressedSize, | |
68 attachment.uncompressedHash, | |
69 static_cast<CompressionType>(attachment.compressionType), | |
70 attachment.compressedSize, | |
71 attachment.compressedHash, | |
72 customData); | |
73 } | |
74 | |
75 static FileInfo Convert(const OrthancPluginAttachment2& attachment) | |
76 { | |
77 return FileInfo(attachment.uuid, | |
78 static_cast<FileContentType>(attachment.contentType), | |
79 attachment.uncompressedSize, | |
80 attachment.uncompressedHash, | |
81 static_cast<CompressionType>(attachment.compressionType), | |
82 attachment.compressedSize, | |
83 attachment.compressedHash, | |
84 attachment.customData); | |
85 } | |
86 | |
87 void ReadStringAnswers(std::list<std::string>& target) | |
88 { | |
89 uint32_t count; | |
90 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
91 | |
92 target.clear(); | |
93 for (uint32_t i = 0; i < count; i++) | |
94 { | |
95 const char* value = NULL; | |
96 CheckSuccess(that_.backend_.readAnswerString(transaction_, &value, i)); | |
97 if (value == NULL) | |
98 { | |
99 throw OrthancException(ErrorCode_DatabasePlugin); | |
100 } | |
101 else | |
102 { | |
103 target.push_back(value); | |
104 } | |
105 } | |
106 } | |
107 | |
108 | |
109 bool ReadSingleStringAnswer(std::string& target) | |
110 { | |
111 uint32_t count; | |
112 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
113 | |
114 if (count == 0) | |
115 { | |
116 return false; | |
117 } | |
118 else if (count == 1) | |
119 { | |
120 const char* value = NULL; | |
121 CheckSuccess(that_.backend_.readAnswerString(transaction_, &value, 0)); | |
122 if (value == NULL) | |
123 { | |
124 throw OrthancException(ErrorCode_DatabasePlugin); | |
125 } | |
126 else | |
127 { | |
128 target.assign(value); | |
129 return true; | |
130 } | |
131 } | |
132 else | |
133 { | |
134 throw OrthancException(ErrorCode_DatabasePlugin); | |
135 } | |
136 } | |
137 | |
138 | |
139 bool ReadSingleInt64Answer(int64_t& target) | |
140 { | |
141 uint32_t count; | |
142 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
143 | |
144 if (count == 0) | |
145 { | |
146 return false; | |
147 } | |
148 else if (count == 1) | |
149 { | |
150 CheckSuccess(that_.backend_.readAnswerInt64(transaction_, &target, 0)); | |
151 return true; | |
152 } | |
153 else | |
154 { | |
155 throw OrthancException(ErrorCode_DatabasePlugin); | |
156 } | |
157 } | |
158 | |
159 | |
160 ExportedResource ReadAnswerExportedResource(uint32_t answerIndex) | |
161 { | |
162 OrthancPluginExportedResource exported; | |
163 CheckSuccess(that_.backend_.readAnswerExportedResource(transaction_, &exported, answerIndex)); | |
164 | |
165 if (exported.publicId == NULL || | |
166 exported.modality == NULL || | |
167 exported.date == NULL || | |
168 exported.patientId == NULL || | |
169 exported.studyInstanceUid == NULL || | |
170 exported.seriesInstanceUid == NULL || | |
171 exported.sopInstanceUid == NULL) | |
172 { | |
173 throw OrthancException(ErrorCode_DatabasePlugin); | |
174 } | |
175 else | |
176 { | |
177 return ExportedResource(exported.seq, | |
178 Plugins::Convert(exported.resourceType), | |
179 exported.publicId, | |
180 exported.modality, | |
181 exported.date, | |
182 exported.patientId, | |
183 exported.studyInstanceUid, | |
184 exported.seriesInstanceUid, | |
185 exported.sopInstanceUid); | |
186 } | |
187 } | |
188 | |
189 | |
190 ServerIndexChange ReadAnswerChange(uint32_t answerIndex) | |
191 { | |
192 OrthancPluginChange change; | |
193 CheckSuccess(that_.backend_.readAnswerChange(transaction_, &change, answerIndex)); | |
194 | |
195 if (change.publicId == NULL || | |
196 change.date == NULL) | |
197 { | |
198 throw OrthancException(ErrorCode_DatabasePlugin); | |
199 } | |
200 else | |
201 { | |
202 return ServerIndexChange(change.seq, | |
203 static_cast<ChangeType>(change.changeType), | |
204 Plugins::Convert(change.resourceType), | |
205 change.publicId, | |
206 change.date); | |
207 } | |
208 } | |
209 | |
210 | |
211 void CheckNoEvent() | |
212 { | |
213 uint32_t count; | |
214 CheckSuccess(that_.backend_.readEventsCount(transaction_, &count)); | |
215 if (count != 0) | |
216 { | |
217 throw OrthancException(ErrorCode_DatabasePlugin); | |
218 } | |
219 } | |
220 | |
221 | |
222 void ProcessEvents(bool isDeletingAttachment) | |
223 { | |
224 uint32_t count; | |
225 CheckSuccess(that_.backend_.readEventsCount(transaction_, &count)); | |
226 | |
227 for (uint32_t i = 0; i < count; i++) | |
228 { | |
229 OrthancPluginDatabaseEvent2 event; | |
230 CheckSuccess(that_.backend_.readEvent2(transaction_, &event, i)); | |
231 | |
232 switch (event.type) | |
233 { | |
234 case OrthancPluginDatabaseEventType_DeletedAttachment: | |
235 listener_.SignalAttachmentDeleted(Convert(event.content.attachment)); | |
236 break; | |
237 | |
238 case OrthancPluginDatabaseEventType_DeletedResource: | |
239 if (isDeletingAttachment) | |
240 { | |
241 // This event should only be triggered by "DeleteResource()" | |
242 throw OrthancException(ErrorCode_DatabasePlugin); | |
243 } | |
244 else | |
245 { | |
246 listener_.SignalResourceDeleted(Plugins::Convert(event.content.resource.level), event.content.resource.publicId); | |
247 } | |
248 break; | |
249 | |
250 case OrthancPluginDatabaseEventType_RemainingAncestor: | |
251 if (isDeletingAttachment) | |
252 { | |
253 // This event should only triggered by "DeleteResource()" | |
254 throw OrthancException(ErrorCode_DatabasePlugin); | |
255 } | |
256 else | |
257 { | |
258 listener_.SignalRemainingAncestor(Plugins::Convert(event.content.resource.level), event.content.resource.publicId); | |
259 } | |
260 break; | |
261 | |
262 default: | |
263 break; // Unhandled event | |
264 } | |
265 } | |
266 } | |
267 | |
268 | |
269 public: | |
270 Transaction(OrthancPluginDatabaseV4& that, | |
271 IDatabaseListener& listener, | |
272 OrthancPluginDatabaseTransactionType type) : | |
273 that_(that), | |
274 listener_(listener) | |
275 { | |
276 CheckSuccess(that.backend_.startTransaction(that.database_, &transaction_, type)); | |
277 if (transaction_ == NULL) | |
278 { | |
279 throw OrthancException(ErrorCode_DatabasePlugin); | |
280 } | |
281 } | |
282 | |
283 | |
284 virtual ~Transaction() | |
285 { | |
286 OrthancPluginErrorCode code = that_.backend_.destructTransaction(transaction_); | |
287 if (code != OrthancPluginErrorCode_Success) | |
288 { | |
289 // Don't throw exception in destructors | |
290 that_.errorDictionary_.LogError(code, true); | |
291 } | |
292 } | |
293 | |
294 | |
295 virtual void Rollback() ORTHANC_OVERRIDE | |
296 { | |
297 CheckSuccess(that_.backend_.rollback(transaction_)); | |
298 CheckNoEvent(); | |
299 } | |
300 | |
301 | |
302 virtual void Commit(int64_t fileSizeDelta) ORTHANC_OVERRIDE | |
303 { | |
304 CheckSuccess(that_.backend_.commit(transaction_, fileSizeDelta)); | |
305 CheckNoEvent(); | |
306 } | |
307 | |
308 | |
309 virtual void AddAttachment(int64_t id, | |
310 const FileInfo& attachment, | |
311 int64_t revision) ORTHANC_OVERRIDE | |
312 { | |
313 OrthancPluginAttachment2 tmp; | |
314 tmp.uuid = attachment.GetUuid().c_str(); | |
315 tmp.contentType = static_cast<int32_t>(attachment.GetContentType()); | |
316 tmp.uncompressedSize = attachment.GetUncompressedSize(); | |
317 tmp.uncompressedHash = attachment.GetUncompressedMD5().c_str(); | |
318 tmp.compressionType = static_cast<int32_t>(attachment.GetCompressionType()); | |
319 tmp.compressedSize = attachment.GetCompressedSize(); | |
320 tmp.compressedHash = attachment.GetCompressedMD5().c_str(); | |
321 tmp.customData = attachment.GetCustomData().c_str(); | |
322 | |
323 CheckSuccess(that_.backend_.addAttachment2(transaction_, id, &tmp, revision)); | |
324 CheckNoEvent(); | |
325 } | |
326 | |
327 | |
328 virtual void ClearChanges() ORTHANC_OVERRIDE | |
329 { | |
330 CheckSuccess(that_.backend_.clearChanges(transaction_)); | |
331 CheckNoEvent(); | |
332 } | |
333 | |
334 | |
335 virtual void ClearExportedResources() ORTHANC_OVERRIDE | |
336 { | |
337 CheckSuccess(that_.backend_.clearExportedResources(transaction_)); | |
338 CheckNoEvent(); | |
339 } | |
340 | |
341 | |
342 virtual void DeleteAttachment(int64_t id, | |
343 FileContentType attachment) ORTHANC_OVERRIDE | |
344 { | |
345 CheckSuccess(that_.backend_.deleteAttachment(transaction_, id, static_cast<int32_t>(attachment))); | |
346 ProcessEvents(true); | |
347 } | |
348 | |
349 | |
350 virtual void DeleteMetadata(int64_t id, | |
351 MetadataType type) ORTHANC_OVERRIDE | |
352 { | |
353 CheckSuccess(that_.backend_.deleteMetadata(transaction_, id, static_cast<int32_t>(type))); | |
354 CheckNoEvent(); | |
355 } | |
356 | |
357 | |
358 virtual void DeleteResource(int64_t id) ORTHANC_OVERRIDE | |
359 { | |
360 CheckSuccess(that_.backend_.deleteResource(transaction_, id)); | |
361 ProcessEvents(false); | |
362 } | |
363 | |
364 | |
365 virtual void GetAllMetadata(std::map<MetadataType, std::string>& target, | |
366 int64_t id) ORTHANC_OVERRIDE | |
367 { | |
368 CheckSuccess(that_.backend_.getAllMetadata(transaction_, id)); | |
369 CheckNoEvent(); | |
370 | |
371 uint32_t count; | |
372 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
373 | |
374 target.clear(); | |
375 for (uint32_t i = 0; i < count; i++) | |
376 { | |
377 int32_t metadata; | |
378 const char* value = NULL; | |
379 CheckSuccess(that_.backend_.readAnswerMetadata(transaction_, &metadata, &value, i)); | |
380 | |
381 if (value == NULL) | |
382 { | |
383 throw OrthancException(ErrorCode_DatabasePlugin); | |
384 } | |
385 else | |
386 { | |
387 target[static_cast<MetadataType>(metadata)] = value; | |
388 } | |
389 } | |
390 } | |
391 | |
392 | |
393 virtual void GetAllPublicIds(std::list<std::string>& target, | |
394 ResourceType resourceType) ORTHANC_OVERRIDE | |
395 { | |
396 CheckSuccess(that_.backend_.getAllPublicIds(transaction_, Plugins::Convert(resourceType))); | |
397 CheckNoEvent(); | |
398 | |
399 ReadStringAnswers(target); | |
400 } | |
401 | |
402 | |
403 virtual void GetAllPublicIds(std::list<std::string>& target, | |
404 ResourceType resourceType, | |
405 size_t since, | |
406 size_t limit) ORTHANC_OVERRIDE | |
407 { | |
408 CheckSuccess(that_.backend_.getAllPublicIdsWithLimit( | |
409 transaction_, Plugins::Convert(resourceType), | |
410 static_cast<uint64_t>(since), static_cast<uint64_t>(limit))); | |
411 CheckNoEvent(); | |
412 | |
413 ReadStringAnswers(target); | |
414 } | |
415 | |
416 | |
417 virtual void GetChanges(std::list<ServerIndexChange>& target /*out*/, | |
418 bool& done /*out*/, | |
419 int64_t since, | |
420 uint32_t maxResults) ORTHANC_OVERRIDE | |
421 { | |
422 uint8_t tmpDone = true; | |
423 CheckSuccess(that_.backend_.getChanges(transaction_, &tmpDone, since, maxResults)); | |
424 CheckNoEvent(); | |
425 | |
426 done = (tmpDone != 0); | |
427 | |
428 uint32_t count; | |
429 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
430 | |
431 target.clear(); | |
432 for (uint32_t i = 0; i < count; i++) | |
433 { | |
434 target.push_back(ReadAnswerChange(i)); | |
435 } | |
436 } | |
437 | |
438 | |
439 virtual void GetChildrenInternalId(std::list<int64_t>& target, | |
440 int64_t id) ORTHANC_OVERRIDE | |
441 { | |
442 CheckSuccess(that_.backend_.getChildrenInternalId(transaction_, id)); | |
443 CheckNoEvent(); | |
444 | |
445 uint32_t count; | |
446 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
447 | |
448 target.clear(); | |
449 for (uint32_t i = 0; i < count; i++) | |
450 { | |
451 int64_t value; | |
452 CheckSuccess(that_.backend_.readAnswerInt64(transaction_, &value, i)); | |
453 target.push_back(value); | |
454 } | |
455 } | |
456 | |
457 | |
458 virtual void GetChildrenPublicId(std::list<std::string>& target, | |
459 int64_t id) ORTHANC_OVERRIDE | |
460 { | |
461 CheckSuccess(that_.backend_.getChildrenPublicId(transaction_, id)); | |
462 CheckNoEvent(); | |
463 | |
464 ReadStringAnswers(target); | |
465 } | |
466 | |
467 | |
468 virtual void GetExportedResources(std::list<ExportedResource>& target /*out*/, | |
469 bool& done /*out*/, | |
470 int64_t since, | |
471 uint32_t maxResults) ORTHANC_OVERRIDE | |
472 { | |
473 uint8_t tmpDone = true; | |
474 CheckSuccess(that_.backend_.getExportedResources(transaction_, &tmpDone, since, maxResults)); | |
475 CheckNoEvent(); | |
476 | |
477 done = (tmpDone != 0); | |
478 | |
479 uint32_t count; | |
480 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
481 | |
482 target.clear(); | |
483 for (uint32_t i = 0; i < count; i++) | |
484 { | |
485 target.push_back(ReadAnswerExportedResource(i)); | |
486 } | |
487 } | |
488 | |
489 | |
490 virtual void GetLastChange(std::list<ServerIndexChange>& target /*out*/) ORTHANC_OVERRIDE | |
491 { | |
492 CheckSuccess(that_.backend_.getLastChange(transaction_)); | |
493 CheckNoEvent(); | |
494 | |
495 uint32_t count; | |
496 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
497 | |
498 target.clear(); | |
499 if (count == 1) | |
500 { | |
501 target.push_back(ReadAnswerChange(0)); | |
502 } | |
503 else if (count > 1) | |
504 { | |
505 throw OrthancException(ErrorCode_DatabasePlugin); | |
506 } | |
507 } | |
508 | |
509 | |
510 virtual void GetLastExportedResource(std::list<ExportedResource>& target /*out*/) ORTHANC_OVERRIDE | |
511 { | |
512 CheckSuccess(that_.backend_.getLastExportedResource(transaction_)); | |
513 CheckNoEvent(); | |
514 | |
515 uint32_t count; | |
516 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
517 | |
518 target.clear(); | |
519 if (count == 1) | |
520 { | |
521 target.push_back(ReadAnswerExportedResource(0)); | |
522 } | |
523 else if (count > 1) | |
524 { | |
525 throw OrthancException(ErrorCode_DatabasePlugin); | |
526 } | |
527 } | |
528 | |
529 | |
530 virtual void GetMainDicomTags(DicomMap& target, | |
531 int64_t id) ORTHANC_OVERRIDE | |
532 { | |
533 CheckSuccess(that_.backend_.getMainDicomTags(transaction_, id)); | |
534 CheckNoEvent(); | |
535 | |
536 uint32_t count; | |
537 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
538 | |
539 target.Clear(); | |
540 for (uint32_t i = 0; i < count; i++) | |
541 { | |
542 uint16_t group, element; | |
543 const char* value = NULL; | |
544 CheckSuccess(that_.backend_.readAnswerDicomTag(transaction_, &group, &element, &value, i)); | |
545 | |
546 if (value == NULL) | |
547 { | |
548 throw OrthancException(ErrorCode_DatabasePlugin); | |
549 } | |
550 else | |
551 { | |
552 target.SetValue(group, element, std::string(value), false); | |
553 } | |
554 } | |
555 } | |
556 | |
557 | |
558 virtual std::string GetPublicId(int64_t resourceId) ORTHANC_OVERRIDE | |
559 { | |
560 CheckSuccess(that_.backend_.getPublicId(transaction_, resourceId)); | |
561 CheckNoEvent(); | |
562 | |
563 std::string s; | |
564 if (ReadSingleStringAnswer(s)) | |
565 { | |
566 return s; | |
567 } | |
568 else | |
569 { | |
570 throw OrthancException(ErrorCode_InexistentItem); | |
571 } | |
572 } | |
573 | |
574 | |
575 virtual uint64_t GetResourcesCount(ResourceType resourceType) ORTHANC_OVERRIDE | |
576 { | |
577 uint64_t value; | |
578 CheckSuccess(that_.backend_.getResourcesCount(transaction_, &value, Plugins::Convert(resourceType))); | |
579 CheckNoEvent(); | |
580 return value; | |
581 } | |
582 | |
583 | |
584 virtual ResourceType GetResourceType(int64_t resourceId) ORTHANC_OVERRIDE | |
585 { | |
586 OrthancPluginResourceType type; | |
587 CheckSuccess(that_.backend_.getResourceType(transaction_, &type, resourceId)); | |
588 CheckNoEvent(); | |
589 return Plugins::Convert(type); | |
590 } | |
591 | |
592 | |
593 virtual uint64_t GetTotalCompressedSize() ORTHANC_OVERRIDE | |
594 { | |
595 uint64_t s; | |
596 CheckSuccess(that_.backend_.getTotalCompressedSize(transaction_, &s)); | |
597 CheckNoEvent(); | |
598 return s; | |
599 } | |
600 | |
601 | |
602 virtual uint64_t GetTotalUncompressedSize() ORTHANC_OVERRIDE | |
603 { | |
604 uint64_t s; | |
605 CheckSuccess(that_.backend_.getTotalUncompressedSize(transaction_, &s)); | |
606 CheckNoEvent(); | |
607 return s; | |
608 } | |
609 | |
610 | |
611 virtual bool IsExistingResource(int64_t internalId) ORTHANC_OVERRIDE | |
612 { | |
613 uint8_t b; | |
614 CheckSuccess(that_.backend_.isExistingResource(transaction_, &b, internalId)); | |
615 CheckNoEvent(); | |
616 return (b != 0); | |
617 } | |
618 | |
619 | |
620 virtual bool IsProtectedPatient(int64_t internalId) ORTHANC_OVERRIDE | |
621 { | |
622 uint8_t b; | |
623 CheckSuccess(that_.backend_.isProtectedPatient(transaction_, &b, internalId)); | |
624 CheckNoEvent(); | |
625 return (b != 0); | |
626 } | |
627 | |
628 | |
629 virtual void ListAvailableAttachments(std::set<FileContentType>& target, | |
630 int64_t id) ORTHANC_OVERRIDE | |
631 { | |
632 CheckSuccess(that_.backend_.listAvailableAttachments(transaction_, id)); | |
633 CheckNoEvent(); | |
634 | |
635 uint32_t count; | |
636 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
637 | |
638 target.clear(); | |
639 for (uint32_t i = 0; i < count; i++) | |
640 { | |
641 int32_t value; | |
642 CheckSuccess(that_.backend_.readAnswerInt32(transaction_, &value, i)); | |
643 target.insert(static_cast<FileContentType>(value)); | |
644 } | |
645 } | |
646 | |
647 | |
648 virtual void LogChange(int64_t internalId, | |
649 const ServerIndexChange& change) ORTHANC_OVERRIDE | |
650 { | |
651 CheckSuccess(that_.backend_.logChange(transaction_, static_cast<int32_t>(change.GetChangeType()), | |
652 internalId, Plugins::Convert(change.GetResourceType()), | |
653 change.GetDate().c_str())); | |
654 CheckNoEvent(); | |
655 } | |
656 | |
657 | |
658 virtual void LogExportedResource(const ExportedResource& resource) ORTHANC_OVERRIDE | |
659 { | |
660 CheckSuccess(that_.backend_.logExportedResource(transaction_, Plugins::Convert(resource.GetResourceType()), | |
661 resource.GetPublicId().c_str(), | |
662 resource.GetModality().c_str(), | |
663 resource.GetDate().c_str(), | |
664 resource.GetPatientId().c_str(), | |
665 resource.GetStudyInstanceUid().c_str(), | |
666 resource.GetSeriesInstanceUid().c_str(), | |
667 resource.GetSopInstanceUid().c_str())); | |
668 CheckNoEvent(); | |
669 } | |
670 | |
671 | |
672 virtual bool LookupAttachment(FileInfo& attachment, | |
673 int64_t& revision, | |
674 int64_t id, | |
675 FileContentType contentType) ORTHANC_OVERRIDE | |
676 { | |
677 CheckSuccess(that_.backend_.lookupAttachment(transaction_, &revision, id, static_cast<int32_t>(contentType))); | |
678 CheckNoEvent(); | |
679 | |
680 uint32_t count; | |
681 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
682 | |
683 if (count == 0) | |
684 { | |
685 return false; | |
686 } | |
687 else if (count == 1) | |
688 { | |
689 OrthancPluginAttachment2 tmp; | |
690 CheckSuccess(that_.backend_.readAnswerAttachment2(transaction_, &tmp, 0)); | |
691 attachment = Convert(tmp); | |
692 return true; | |
693 } | |
694 else | |
695 { | |
696 throw OrthancException(ErrorCode_DatabasePlugin); | |
697 } | |
698 } | |
699 | |
700 | |
701 virtual bool LookupGlobalProperty(std::string& target, | |
702 GlobalProperty property, | |
703 bool shared) ORTHANC_OVERRIDE | |
704 { | |
705 const char* id = (shared ? "" : that_.serverIdentifier_.c_str()); | |
706 | |
707 CheckSuccess(that_.backend_.lookupGlobalProperty(transaction_, id, static_cast<int32_t>(property))); | |
708 CheckNoEvent(); | |
709 return ReadSingleStringAnswer(target); | |
710 } | |
711 | |
712 | |
713 virtual bool LookupMetadata(std::string& target, | |
714 int64_t& revision, | |
715 int64_t id, | |
716 MetadataType type) ORTHANC_OVERRIDE | |
717 { | |
718 CheckSuccess(that_.backend_.lookupMetadata(transaction_, &revision, id, static_cast<int32_t>(type))); | |
719 CheckNoEvent(); | |
720 return ReadSingleStringAnswer(target); | |
721 } | |
722 | |
723 | |
724 virtual bool LookupParent(int64_t& parentId, | |
725 int64_t resourceId) ORTHANC_OVERRIDE | |
726 { | |
727 uint8_t existing; | |
728 CheckSuccess(that_.backend_.lookupParent(transaction_, &existing, &parentId, resourceId)); | |
729 CheckNoEvent(); | |
730 return (existing != 0); | |
731 } | |
732 | |
733 | |
734 virtual bool LookupResource(int64_t& id, | |
735 ResourceType& type, | |
736 const std::string& publicId) ORTHANC_OVERRIDE | |
737 { | |
738 uint8_t existing; | |
739 OrthancPluginResourceType t; | |
740 CheckSuccess(that_.backend_.lookupResource(transaction_, &existing, &id, &t, publicId.c_str())); | |
741 CheckNoEvent(); | |
742 | |
743 if (existing == 0) | |
744 { | |
745 return false; | |
746 } | |
747 else | |
748 { | |
749 type = Plugins::Convert(t); | |
750 return true; | |
751 } | |
752 } | |
753 | |
754 | |
755 virtual bool SelectPatientToRecycle(int64_t& internalId) ORTHANC_OVERRIDE | |
756 { | |
757 uint8_t available; | |
758 CheckSuccess(that_.backend_.selectPatientToRecycle(transaction_, &available, &internalId)); | |
759 CheckNoEvent(); | |
760 return (available != 0); | |
761 } | |
762 | |
763 | |
764 virtual bool SelectPatientToRecycle(int64_t& internalId, | |
765 int64_t patientIdToAvoid) ORTHANC_OVERRIDE | |
766 { | |
767 uint8_t available; | |
768 CheckSuccess(that_.backend_.selectPatientToRecycle2(transaction_, &available, &internalId, patientIdToAvoid)); | |
769 CheckNoEvent(); | |
770 return (available != 0); | |
771 } | |
772 | |
773 | |
774 virtual void SetGlobalProperty(GlobalProperty property, | |
775 bool shared, | |
776 const std::string& value) ORTHANC_OVERRIDE | |
777 { | |
778 const char* id = (shared ? "" : that_.serverIdentifier_.c_str()); | |
779 | |
780 CheckSuccess(that_.backend_.setGlobalProperty(transaction_, id, static_cast<int32_t>(property), value.c_str())); | |
781 CheckNoEvent(); | |
782 } | |
783 | |
784 | |
785 virtual void ClearMainDicomTags(int64_t id) ORTHANC_OVERRIDE | |
786 { | |
787 CheckSuccess(that_.backend_.clearMainDicomTags(transaction_, id)); | |
788 CheckNoEvent(); | |
789 } | |
790 | |
791 | |
792 virtual void SetMetadata(int64_t id, | |
793 MetadataType type, | |
794 const std::string& value, | |
795 int64_t revision) ORTHANC_OVERRIDE | |
796 { | |
797 CheckSuccess(that_.backend_.setMetadata(transaction_, id, static_cast<int32_t>(type), value.c_str(), revision)); | |
798 CheckNoEvent(); | |
799 } | |
800 | |
801 | |
802 virtual void SetProtectedPatient(int64_t internalId, | |
803 bool isProtected) ORTHANC_OVERRIDE | |
804 { | |
805 CheckSuccess(that_.backend_.setProtectedPatient(transaction_, internalId, (isProtected ? 1 : 0))); | |
806 CheckNoEvent(); | |
807 } | |
808 | |
809 | |
810 virtual bool IsDiskSizeAbove(uint64_t threshold) ORTHANC_OVERRIDE | |
811 { | |
812 uint8_t tmp; | |
813 CheckSuccess(that_.backend_.isDiskSizeAbove(transaction_, &tmp, threshold)); | |
814 CheckNoEvent(); | |
815 return (tmp != 0); | |
816 } | |
817 | |
818 | |
819 virtual void ApplyLookupResources(std::list<std::string>& resourcesId, | |
820 std::list<std::string>* instancesId, // Can be NULL if not needed | |
821 const std::vector<DatabaseConstraint>& lookup, | |
822 ResourceType queryLevel, | |
823 size_t limit) ORTHANC_OVERRIDE | |
824 { | |
825 std::vector<OrthancPluginDatabaseConstraint> constraints; | |
826 std::vector< std::vector<const char*> > constraintsValues; | |
827 | |
828 constraints.resize(lookup.size()); | |
829 constraintsValues.resize(lookup.size()); | |
830 | |
831 for (size_t i = 0; i < lookup.size(); i++) | |
832 { | |
833 lookup[i].EncodeForPlugins(constraints[i], constraintsValues[i]); | |
834 } | |
835 | |
836 CheckSuccess(that_.backend_.lookupResources(transaction_, lookup.size(), | |
837 (lookup.empty() ? NULL : &constraints[0]), | |
838 Plugins::Convert(queryLevel), | |
839 limit, (instancesId == NULL ? 0 : 1))); | |
840 CheckNoEvent(); | |
841 | |
842 uint32_t count; | |
843 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
844 | |
845 resourcesId.clear(); | |
846 | |
847 if (instancesId != NULL) | |
848 { | |
849 instancesId->clear(); | |
850 } | |
851 | |
852 for (uint32_t i = 0; i < count; i++) | |
853 { | |
854 OrthancPluginMatchingResource resource; | |
855 CheckSuccess(that_.backend_.readAnswerMatchingResource(transaction_, &resource, i)); | |
856 | |
857 if (resource.resourceId == NULL) | |
858 { | |
859 throw OrthancException(ErrorCode_DatabasePlugin); | |
860 } | |
861 | |
862 resourcesId.push_back(resource.resourceId); | |
863 | |
864 if (instancesId != NULL) | |
865 { | |
866 if (resource.someInstanceId == NULL) | |
867 { | |
868 throw OrthancException(ErrorCode_DatabasePlugin); | |
869 } | |
870 else | |
871 { | |
872 instancesId->push_back(resource.someInstanceId); | |
873 } | |
874 } | |
875 } | |
876 } | |
877 | |
878 | |
879 virtual bool CreateInstance(CreateInstanceResult& result, /* out */ | |
880 int64_t& instanceId, /* out */ | |
881 const std::string& patient, | |
882 const std::string& study, | |
883 const std::string& series, | |
884 const std::string& instance) ORTHANC_OVERRIDE | |
885 { | |
886 OrthancPluginCreateInstanceResult output; | |
887 memset(&output, 0, sizeof(output)); | |
888 | |
889 CheckSuccess(that_.backend_.createInstance(transaction_, &output, patient.c_str(), | |
890 study.c_str(), series.c_str(), instance.c_str())); | |
891 CheckNoEvent(); | |
892 | |
893 instanceId = output.instanceId; | |
894 | |
895 if (output.isNewInstance) | |
896 { | |
897 result.isNewPatient_ = output.isNewPatient; | |
898 result.isNewStudy_ = output.isNewStudy; | |
899 result.isNewSeries_ = output.isNewSeries; | |
900 result.patientId_ = output.patientId; | |
901 result.studyId_ = output.studyId; | |
902 result.seriesId_ = output.seriesId; | |
903 return true; | |
904 } | |
905 else | |
906 { | |
907 return false; | |
908 } | |
909 | |
910 } | |
911 | |
912 | |
913 virtual void SetResourcesContent(const ResourcesContent& content) ORTHANC_OVERRIDE | |
914 { | |
915 std::vector<OrthancPluginResourcesContentTags> identifierTags; | |
916 std::vector<OrthancPluginResourcesContentTags> mainDicomTags; | |
917 std::vector<OrthancPluginResourcesContentMetadata> metadata; | |
918 | |
919 identifierTags.reserve(content.GetListTags().size()); | |
920 mainDicomTags.reserve(content.GetListTags().size()); | |
921 metadata.reserve(content.GetListMetadata().size()); | |
922 | |
923 for (ResourcesContent::ListTags::const_iterator | |
924 it = content.GetListTags().begin(); it != content.GetListTags().end(); ++it) | |
925 { | |
926 OrthancPluginResourcesContentTags tmp; | |
927 tmp.resource = it->resourceId_; | |
928 tmp.group = it->tag_.GetGroup(); | |
929 tmp.element = it->tag_.GetElement(); | |
930 tmp.value = it->value_.c_str(); | |
931 | |
932 if (it->isIdentifier_) | |
933 { | |
934 identifierTags.push_back(tmp); | |
935 } | |
936 else | |
937 { | |
938 mainDicomTags.push_back(tmp); | |
939 } | |
940 } | |
941 | |
942 for (ResourcesContent::ListMetadata::const_iterator | |
943 it = content.GetListMetadata().begin(); it != content.GetListMetadata().end(); ++it) | |
944 { | |
945 OrthancPluginResourcesContentMetadata tmp; | |
946 tmp.resource = it->resourceId_; | |
947 tmp.metadata = it->metadata_; | |
948 tmp.value = it->value_.c_str(); | |
949 metadata.push_back(tmp); | |
950 } | |
951 | |
952 assert(identifierTags.size() + mainDicomTags.size() == content.GetListTags().size() && | |
953 metadata.size() == content.GetListMetadata().size()); | |
954 | |
955 CheckSuccess(that_.backend_.setResourcesContent(transaction_, | |
956 identifierTags.size(), | |
957 (identifierTags.empty() ? NULL : &identifierTags[0]), | |
958 mainDicomTags.size(), | |
959 (mainDicomTags.empty() ? NULL : &mainDicomTags[0]), | |
960 metadata.size(), | |
961 (metadata.empty() ? NULL : &metadata[0]))); | |
962 CheckNoEvent(); | |
963 } | |
964 | |
965 | |
966 virtual void GetChildrenMetadata(std::list<std::string>& target, | |
967 int64_t resourceId, | |
968 MetadataType metadata) ORTHANC_OVERRIDE | |
969 { | |
970 CheckSuccess(that_.backend_.getChildrenMetadata(transaction_, resourceId, static_cast<int32_t>(metadata))); | |
971 CheckNoEvent(); | |
972 ReadStringAnswers(target); | |
973 } | |
974 | |
975 | |
976 virtual int64_t GetLastChangeIndex() ORTHANC_OVERRIDE | |
977 { | |
978 int64_t tmp; | |
979 CheckSuccess(that_.backend_.getLastChangeIndex(transaction_, &tmp)); | |
980 CheckNoEvent(); | |
981 return tmp; | |
982 } | |
983 | |
984 | |
985 virtual bool LookupResourceAndParent(int64_t& id, | |
986 ResourceType& type, | |
987 std::string& parentPublicId, | |
988 const std::string& publicId) ORTHANC_OVERRIDE | |
989 { | |
990 uint8_t isExisting; | |
991 OrthancPluginResourceType tmpType; | |
992 CheckSuccess(that_.backend_.lookupResourceAndParent(transaction_, &isExisting, &id, &tmpType, publicId.c_str())); | |
993 CheckNoEvent(); | |
994 | |
995 if (isExisting) | |
996 { | |
997 type = Plugins::Convert(tmpType); | |
998 | |
999 uint32_t count; | |
1000 CheckSuccess(that_.backend_.readAnswersCount(transaction_, &count)); | |
1001 | |
1002 if (count > 1) | |
1003 { | |
1004 throw OrthancException(ErrorCode_DatabasePlugin); | |
1005 } | |
1006 | |
1007 switch (type) | |
1008 { | |
1009 case ResourceType_Patient: | |
1010 // A patient has no parent | |
1011 if (count == 1) | |
1012 { | |
1013 throw OrthancException(ErrorCode_DatabasePlugin); | |
1014 } | |
1015 break; | |
1016 | |
1017 case ResourceType_Study: | |
1018 case ResourceType_Series: | |
1019 case ResourceType_Instance: | |
1020 if (count == 0) | |
1021 { | |
1022 throw OrthancException(ErrorCode_DatabasePlugin); | |
1023 } | |
1024 else | |
1025 { | |
1026 const char* value = NULL; | |
1027 CheckSuccess(that_.backend_.readAnswerString(transaction_, &value, 0)); | |
1028 if (value == NULL) | |
1029 { | |
1030 throw OrthancException(ErrorCode_DatabasePlugin); | |
1031 } | |
1032 else | |
1033 { | |
1034 parentPublicId.assign(value); | |
1035 } | |
1036 } | |
1037 break; | |
1038 | |
1039 default: | |
1040 throw OrthancException(ErrorCode_DatabasePlugin); | |
1041 } | |
1042 | |
1043 return true; | |
1044 } | |
1045 else | |
1046 { | |
1047 return false; | |
1048 } | |
1049 } | |
1050 }; | |
1051 | |
1052 | |
1053 void OrthancPluginDatabaseV4::CheckSuccess(OrthancPluginErrorCode code) const | |
1054 { | |
1055 if (code != OrthancPluginErrorCode_Success) | |
1056 { | |
1057 errorDictionary_.LogError(code, true); | |
1058 throw OrthancException(static_cast<ErrorCode>(code)); | |
1059 } | |
1060 } | |
1061 | |
1062 | |
1063 OrthancPluginDatabaseV4::OrthancPluginDatabaseV4(SharedLibrary& library, | |
1064 PluginsErrorDictionary& errorDictionary, | |
1065 const OrthancPluginDatabaseBackendV4* backend, | |
1066 size_t backendSize, | |
1067 void* database, | |
1068 const std::string& serverIdentifier) : | |
1069 library_(library), | |
1070 errorDictionary_(errorDictionary), | |
1071 database_(database), | |
1072 serverIdentifier_(serverIdentifier) | |
1073 { | |
1074 CLOG(INFO, PLUGINS) << "Identifier of this Orthanc server for the global properties " | |
1075 << "of the custom database: \"" << serverIdentifier << "\""; | |
1076 | |
1077 if (backendSize >= sizeof(backend_)) | |
1078 { | |
1079 memcpy(&backend_, backend, sizeof(backend_)); | |
1080 } | |
1081 else | |
1082 { | |
1083 // Not all the primitives are implemented by the plugin | |
1084 memset(&backend_, 0, sizeof(backend_)); | |
1085 memcpy(&backend_, backend, backendSize); | |
1086 } | |
1087 | |
1088 // Sanity checks | |
1089 CHECK_FUNCTION_EXISTS(backend_, readAnswersCount); | |
1090 CHECK_FUNCTION_EXISTS(backend_, readAnswerAttachment2); | |
1091 CHECK_FUNCTION_EXISTS(backend_, readAnswerChange); | |
1092 CHECK_FUNCTION_EXISTS(backend_, readAnswerDicomTag); | |
1093 CHECK_FUNCTION_EXISTS(backend_, readAnswerExportedResource); | |
1094 CHECK_FUNCTION_EXISTS(backend_, readAnswerInt32); | |
1095 CHECK_FUNCTION_EXISTS(backend_, readAnswerInt64); | |
1096 CHECK_FUNCTION_EXISTS(backend_, readAnswerMatchingResource); | |
1097 CHECK_FUNCTION_EXISTS(backend_, readAnswerMetadata); | |
1098 CHECK_FUNCTION_EXISTS(backend_, readAnswerString); | |
1099 | |
1100 CHECK_FUNCTION_EXISTS(backend_, readEventsCount); | |
1101 CHECK_FUNCTION_EXISTS(backend_, readEvent2); | |
1102 | |
1103 CHECK_FUNCTION_EXISTS(backend_, open); | |
1104 CHECK_FUNCTION_EXISTS(backend_, close); | |
1105 CHECK_FUNCTION_EXISTS(backend_, destructDatabase); | |
1106 CHECK_FUNCTION_EXISTS(backend_, getDatabaseVersion); | |
1107 CHECK_FUNCTION_EXISTS(backend_, upgradeDatabase); | |
1108 CHECK_FUNCTION_EXISTS(backend_, startTransaction); | |
1109 CHECK_FUNCTION_EXISTS(backend_, destructTransaction); | |
1110 CHECK_FUNCTION_EXISTS(backend_, hasRevisionsSupport); | |
1111 CHECK_FUNCTION_EXISTS(backend_, hasAttachmentCustomDataSupport); // new in v4 | |
1112 | |
1113 CHECK_FUNCTION_EXISTS(backend_, rollback); | |
1114 CHECK_FUNCTION_EXISTS(backend_, commit); | |
1115 | |
1116 CHECK_FUNCTION_EXISTS(backend_, addAttachment2); | |
1117 CHECK_FUNCTION_EXISTS(backend_, clearChanges); | |
1118 CHECK_FUNCTION_EXISTS(backend_, clearExportedResources); | |
1119 CHECK_FUNCTION_EXISTS(backend_, clearMainDicomTags); | |
1120 CHECK_FUNCTION_EXISTS(backend_, createInstance); | |
1121 CHECK_FUNCTION_EXISTS(backend_, deleteAttachment); | |
1122 CHECK_FUNCTION_EXISTS(backend_, deleteMetadata); | |
1123 CHECK_FUNCTION_EXISTS(backend_, deleteResource); | |
1124 CHECK_FUNCTION_EXISTS(backend_, getAllMetadata); | |
1125 CHECK_FUNCTION_EXISTS(backend_, getAllPublicIds); | |
1126 CHECK_FUNCTION_EXISTS(backend_, getAllPublicIdsWithLimit); | |
1127 CHECK_FUNCTION_EXISTS(backend_, getChanges); | |
1128 CHECK_FUNCTION_EXISTS(backend_, getChildrenInternalId); | |
1129 CHECK_FUNCTION_EXISTS(backend_, getChildrenMetadata); | |
1130 CHECK_FUNCTION_EXISTS(backend_, getChildrenPublicId); | |
1131 CHECK_FUNCTION_EXISTS(backend_, getExportedResources); | |
1132 CHECK_FUNCTION_EXISTS(backend_, getLastChange); | |
1133 CHECK_FUNCTION_EXISTS(backend_, getLastChangeIndex); | |
1134 CHECK_FUNCTION_EXISTS(backend_, getLastExportedResource); | |
1135 CHECK_FUNCTION_EXISTS(backend_, getMainDicomTags); | |
1136 CHECK_FUNCTION_EXISTS(backend_, getPublicId); | |
1137 CHECK_FUNCTION_EXISTS(backend_, getResourceType); | |
1138 CHECK_FUNCTION_EXISTS(backend_, getResourcesCount); | |
1139 CHECK_FUNCTION_EXISTS(backend_, getTotalCompressedSize); | |
1140 CHECK_FUNCTION_EXISTS(backend_, getTotalUncompressedSize); | |
1141 CHECK_FUNCTION_EXISTS(backend_, isDiskSizeAbove); | |
1142 CHECK_FUNCTION_EXISTS(backend_, isExistingResource); | |
1143 CHECK_FUNCTION_EXISTS(backend_, isProtectedPatient); | |
1144 CHECK_FUNCTION_EXISTS(backend_, listAvailableAttachments); | |
1145 CHECK_FUNCTION_EXISTS(backend_, logChange); | |
1146 CHECK_FUNCTION_EXISTS(backend_, logExportedResource); | |
1147 CHECK_FUNCTION_EXISTS(backend_, lookupAttachment); | |
1148 CHECK_FUNCTION_EXISTS(backend_, lookupGlobalProperty); | |
1149 CHECK_FUNCTION_EXISTS(backend_, lookupMetadata); | |
1150 CHECK_FUNCTION_EXISTS(backend_, lookupParent); | |
1151 CHECK_FUNCTION_EXISTS(backend_, lookupResource); | |
1152 CHECK_FUNCTION_EXISTS(backend_, lookupResourceAndParent); | |
1153 CHECK_FUNCTION_EXISTS(backend_, lookupResources); | |
1154 CHECK_FUNCTION_EXISTS(backend_, selectPatientToRecycle); | |
1155 CHECK_FUNCTION_EXISTS(backend_, selectPatientToRecycle2); | |
1156 CHECK_FUNCTION_EXISTS(backend_, setGlobalProperty); | |
1157 CHECK_FUNCTION_EXISTS(backend_, setMetadata); | |
1158 CHECK_FUNCTION_EXISTS(backend_, setProtectedPatient); | |
1159 CHECK_FUNCTION_EXISTS(backend_, setResourcesContent); | |
1160 } | |
1161 | |
1162 | |
1163 OrthancPluginDatabaseV4::~OrthancPluginDatabaseV4() | |
1164 { | |
1165 if (database_ != NULL) | |
1166 { | |
1167 OrthancPluginErrorCode code = backend_.destructDatabase(database_); | |
1168 if (code != OrthancPluginErrorCode_Success) | |
1169 { | |
1170 // Don't throw exception in destructors | |
1171 errorDictionary_.LogError(code, true); | |
1172 } | |
1173 } | |
1174 } | |
1175 | |
1176 | |
1177 void OrthancPluginDatabaseV4::Open() | |
1178 { | |
1179 CheckSuccess(backend_.open(database_)); | |
1180 } | |
1181 | |
1182 | |
1183 void OrthancPluginDatabaseV4::Close() | |
1184 { | |
1185 CheckSuccess(backend_.close(database_)); | |
1186 } | |
1187 | |
1188 | |
1189 IDatabaseWrapper::ITransaction* OrthancPluginDatabaseV4::StartTransaction(TransactionType type, | |
1190 IDatabaseListener& listener) | |
1191 { | |
1192 switch (type) | |
1193 { | |
1194 case TransactionType_ReadOnly: | |
1195 return new Transaction(*this, listener, OrthancPluginDatabaseTransactionType_ReadOnly); | |
1196 | |
1197 case TransactionType_ReadWrite: | |
1198 return new Transaction(*this, listener, OrthancPluginDatabaseTransactionType_ReadWrite); | |
1199 | |
1200 default: | |
1201 throw OrthancException(ErrorCode_InternalError); | |
1202 } | |
1203 } | |
1204 | |
1205 | |
1206 unsigned int OrthancPluginDatabaseV4::GetDatabaseVersion() | |
1207 { | |
1208 uint32_t version = 0; | |
1209 CheckSuccess(backend_.getDatabaseVersion(database_, &version)); | |
1210 return version; | |
1211 } | |
1212 | |
1213 | |
1214 void OrthancPluginDatabaseV4::Upgrade(unsigned int targetVersion, | |
1215 IStorageArea& storageArea) | |
1216 { | |
1217 VoidDatabaseListener listener; | |
1218 | |
1219 if (backend_.upgradeDatabase != NULL) | |
1220 { | |
1221 Transaction transaction(*this, listener, OrthancPluginDatabaseTransactionType_ReadWrite); | |
1222 | |
1223 OrthancPluginErrorCode code = backend_.upgradeDatabase( | |
1224 database_, reinterpret_cast<OrthancPluginStorageArea*>(&storageArea), | |
1225 static_cast<uint32_t>(targetVersion)); | |
1226 | |
1227 if (code == OrthancPluginErrorCode_Success) | |
1228 { | |
1229 transaction.Commit(0); | |
1230 } | |
1231 else | |
1232 { | |
1233 transaction.Rollback(); | |
1234 errorDictionary_.LogError(code, true); | |
1235 throw OrthancException(static_cast<ErrorCode>(code)); | |
1236 } | |
1237 } | |
1238 } | |
1239 | |
1240 | |
1241 bool OrthancPluginDatabaseV4::HasRevisionsSupport() const | |
1242 { | |
1243 // WARNING: This method requires "Open()" to have been called | |
1244 uint8_t hasRevisions; | |
1245 CheckSuccess(backend_.hasRevisionsSupport(database_, &hasRevisions)); | |
1246 return (hasRevisions != 0); | |
1247 } | |
1248 | |
1249 bool OrthancPluginDatabaseV4::HasAttachmentCustomDataSupport() const | |
1250 { | |
1251 // WARNING: This method requires "Open()" to have been called | |
1252 uint8_t hasAttachmentCustomDataSupport; | |
1253 CheckSuccess(backend_.hasAttachmentCustomDataSupport(database_, &hasAttachmentCustomDataSupport)); | |
1254 return (hasAttachmentCustomDataSupport != 0); | |
1255 } | |
1256 } |