Mercurial > hg > orthanc
comparison OrthancServer/Sources/Database/SQLiteDatabaseWrapper.cpp @ 4589:bec74e29f86b db-changes
attaching the listener to transactions in IDatabaseWrapper
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 12 Mar 2021 15:33:47 +0100 |
parents | 9224e107d613 |
children | ff8170d17d90 |
comparison
equal
deleted
inserted
replaced
4588:94147ce2f097 | 4589:bec74e29f86b |
---|---|
45 #include <stdio.h> | 45 #include <stdio.h> |
46 #include <boost/lexical_cast.hpp> | 46 #include <boost/lexical_cast.hpp> |
47 | 47 |
48 namespace Orthanc | 48 namespace Orthanc |
49 { | 49 { |
50 namespace Internals | 50 class SQLiteDatabaseWrapper::SignalFileDeleted : public SQLite::IScalarFunction |
51 { | 51 { |
52 class SignalFileDeleted : public SQLite::IScalarFunction | 52 private: |
53 { | 53 SQLiteDatabaseWrapper& sqlite_; |
54 private: | 54 |
55 IDatabaseListener& listener_; | 55 public: |
56 | 56 SignalFileDeleted(SQLiteDatabaseWrapper& sqlite) : |
57 public: | 57 sqlite_(sqlite) |
58 SignalFileDeleted(IDatabaseListener& listener) : | 58 { |
59 listener_(listener) | 59 } |
60 { | 60 |
61 } | 61 virtual const char* GetName() const ORTHANC_OVERRIDE |
62 | 62 { |
63 virtual const char* GetName() const ORTHANC_OVERRIDE | 63 return "SignalFileDeleted"; |
64 { | 64 } |
65 return "SignalFileDeleted"; | 65 |
66 } | 66 virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE |
67 | 67 { |
68 virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE | 68 return 7; |
69 { | 69 } |
70 return 7; | 70 |
71 } | 71 virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE |
72 | 72 { |
73 virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE | 73 if (sqlite_.listener_ != NULL) |
74 { | 74 { |
75 std::string uncompressedMD5, compressedMD5; | 75 std::string uncompressedMD5, compressedMD5; |
76 | 76 |
77 if (!context.IsNullValue(5)) | 77 if (!context.IsNullValue(5)) |
78 { | 78 { |
89 static_cast<uint64_t>(context.GetInt64Value(2)), | 89 static_cast<uint64_t>(context.GetInt64Value(2)), |
90 uncompressedMD5, | 90 uncompressedMD5, |
91 static_cast<CompressionType>(context.GetIntValue(3)), | 91 static_cast<CompressionType>(context.GetIntValue(3)), |
92 static_cast<uint64_t>(context.GetInt64Value(4)), | 92 static_cast<uint64_t>(context.GetInt64Value(4)), |
93 compressedMD5); | 93 compressedMD5); |
94 | 94 |
95 listener_.SignalAttachmentDeleted(info); | 95 sqlite_.listener_->SignalAttachmentDeleted(info); |
96 } | 96 } |
97 }; | 97 } |
98 | 98 }; |
99 class SignalResourceDeleted : public SQLite::IScalarFunction | 99 |
100 { | 100 |
101 private: | 101 class SQLiteDatabaseWrapper::SignalResourceDeleted : public SQLite::IScalarFunction |
102 IDatabaseListener& listener_; | 102 { |
103 | 103 private: |
104 public: | 104 SQLiteDatabaseWrapper& sqlite_; |
105 SignalResourceDeleted(IDatabaseListener& listener) : | 105 |
106 listener_(listener) | 106 public: |
107 { | 107 SignalResourceDeleted(SQLiteDatabaseWrapper& sqlite) : |
108 } | 108 sqlite_(sqlite) |
109 | 109 { |
110 virtual const char* GetName() const ORTHANC_OVERRIDE | 110 } |
111 { | 111 |
112 return "SignalResourceDeleted"; | 112 virtual const char* GetName() const ORTHANC_OVERRIDE |
113 } | 113 { |
114 | 114 return "SignalResourceDeleted"; |
115 virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE | 115 } |
116 { | 116 |
117 return 2; | 117 virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE |
118 } | 118 { |
119 | 119 return 2; |
120 virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE | 120 } |
121 { | 121 |
122 listener_.SignalResourceDeleted(static_cast<ResourceType>(context.GetIntValue(1)), | 122 virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE |
123 context.GetStringValue(0)); | 123 { |
124 } | 124 if (sqlite_.listener_ != NULL) |
125 }; | 125 { |
126 | 126 sqlite_.listener_->SignalResourceDeleted(static_cast<ResourceType>(context.GetIntValue(1)), |
127 class SignalRemainingAncestor : public SQLite::IScalarFunction | 127 context.GetStringValue(0)); |
128 { | 128 } |
129 private: | 129 } |
130 bool hasRemainingAncestor_; | 130 }; |
131 std::string remainingPublicId_; | 131 |
132 ResourceType remainingType_; | 132 |
133 | 133 class SQLiteDatabaseWrapper::SignalRemainingAncestor : public SQLite::IScalarFunction |
134 public: | 134 { |
135 SignalRemainingAncestor() : | 135 private: |
136 hasRemainingAncestor_(false) | 136 bool hasRemainingAncestor_; |
137 { | 137 std::string remainingPublicId_; |
138 } | 138 ResourceType remainingType_; |
139 | 139 |
140 void Reset() | 140 public: |
141 { | 141 SignalRemainingAncestor() : |
142 hasRemainingAncestor_ = false; | 142 hasRemainingAncestor_(false) |
143 } | 143 { |
144 | 144 } |
145 virtual const char* GetName() const ORTHANC_OVERRIDE | 145 |
146 { | 146 void Reset() |
147 return "SignalRemainingAncestor"; | 147 { |
148 } | 148 hasRemainingAncestor_ = false; |
149 | 149 } |
150 virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE | 150 |
151 { | 151 virtual const char* GetName() const ORTHANC_OVERRIDE |
152 return 2; | 152 { |
153 } | 153 return "SignalRemainingAncestor"; |
154 | 154 } |
155 virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE | 155 |
156 { | 156 virtual unsigned int GetCardinality() const ORTHANC_OVERRIDE |
157 CLOG(TRACE, SQLITE) << "There exists a remaining ancestor with public ID \"" | 157 { |
158 << context.GetStringValue(0) << "\" of type " | 158 return 2; |
159 << context.GetIntValue(1); | 159 } |
160 | 160 |
161 if (!hasRemainingAncestor_ || | 161 virtual void Compute(SQLite::FunctionContext& context) ORTHANC_OVERRIDE |
162 remainingType_ >= context.GetIntValue(1)) | 162 { |
163 { | 163 CLOG(TRACE, SQLITE) << "There exists a remaining ancestor with public ID \"" |
164 hasRemainingAncestor_ = true; | 164 << context.GetStringValue(0) << "\" of type " |
165 remainingPublicId_ = context.GetStringValue(0); | 165 << context.GetIntValue(1); |
166 remainingType_ = static_cast<ResourceType>(context.GetIntValue(1)); | 166 |
167 } | 167 if (!hasRemainingAncestor_ || |
168 } | 168 remainingType_ >= context.GetIntValue(1)) |
169 | 169 { |
170 bool HasRemainingAncestor() const | 170 hasRemainingAncestor_ = true; |
171 { | 171 remainingPublicId_ = context.GetStringValue(0); |
172 return hasRemainingAncestor_; | 172 remainingType_ = static_cast<ResourceType>(context.GetIntValue(1)); |
173 } | 173 } |
174 | 174 } |
175 const std::string& GetRemainingAncestorId() const | 175 |
176 { | 176 bool HasRemainingAncestor() const |
177 assert(hasRemainingAncestor_); | 177 { |
178 return remainingPublicId_; | 178 return hasRemainingAncestor_; |
179 } | 179 } |
180 | 180 |
181 ResourceType GetRemainingAncestorType() const | 181 const std::string& GetRemainingAncestorId() const |
182 { | 182 { |
183 assert(hasRemainingAncestor_); | 183 assert(hasRemainingAncestor_); |
184 return remainingType_; | 184 return remainingPublicId_; |
185 } | 185 } |
186 }; | 186 |
187 } | 187 ResourceType GetRemainingAncestorType() const |
188 { | |
189 assert(hasRemainingAncestor_); | |
190 return remainingType_; | |
191 } | |
192 }; | |
188 | 193 |
189 | 194 |
190 void SQLiteDatabaseWrapper::GetChangesInternal(std::list<ServerIndexChange>& target, | 195 void SQLiteDatabaseWrapper::GetChangesInternal(std::list<ServerIndexChange>& target, |
191 bool& done, | 196 bool& done, |
192 SQLite::Statement& s, | 197 SQLite::Statement& s, |
434 } | 439 } |
435 | 440 |
436 t.Commit(); | 441 t.Commit(); |
437 } | 442 } |
438 | 443 |
439 signalRemainingAncestor_ = new Internals::SignalRemainingAncestor; | 444 signalRemainingAncestor_ = dynamic_cast<SignalRemainingAncestor*>(db_.Register(new SignalRemainingAncestor)); |
440 db_.Register(signalRemainingAncestor_); | 445 db_.Register(new SignalFileDeleted(*this)); |
446 db_.Register(new SignalResourceDeleted(*this)); | |
441 } | 447 } |
442 | 448 |
443 | 449 |
444 static void ExecuteUpgradeScript(SQLite::Connection& db, | 450 static void ExecuteUpgradeScript(SQLite::Connection& db, |
445 ServerResources::FileResourceId script) | 451 ServerResources::FileResourceId script) |
501 version_ = 6; | 507 version_ = 6; |
502 } | 508 } |
503 } | 509 } |
504 | 510 |
505 | 511 |
506 void SQLiteDatabaseWrapper::SetListener(IDatabaseListener& listener) | |
507 { | |
508 listener_ = &listener; | |
509 db_.Register(new Internals::SignalFileDeleted(listener)); | |
510 db_.Register(new Internals::SignalResourceDeleted(listener)); | |
511 } | |
512 | |
513 | |
514 void SQLiteDatabaseWrapper::ClearTable(const std::string& tableName) | 512 void SQLiteDatabaseWrapper::ClearTable(const std::string& tableName) |
515 { | 513 { |
516 db_.Execute("DELETE FROM " + tableName); | 514 db_.Execute("DELETE FROM " + tableName); |
517 } | 515 } |
518 | 516 |
601 SQLiteDatabaseWrapper& that_; | 599 SQLiteDatabaseWrapper& that_; |
602 std::unique_ptr<SQLite::Transaction> transaction_; | 600 std::unique_ptr<SQLite::Transaction> transaction_; |
603 int64_t initialDiskSize_; | 601 int64_t initialDiskSize_; |
604 | 602 |
605 public: | 603 public: |
606 ReadWriteTransaction(SQLiteDatabaseWrapper& that) : | 604 ReadWriteTransaction(SQLiteDatabaseWrapper& that, |
605 IDatabaseListener& listener) : | |
607 that_(that), | 606 that_(that), |
608 transaction_(new SQLite::Transaction(that_.db_)) | 607 transaction_(new SQLite::Transaction(that_.db_)) |
609 { | 608 { |
609 assert(that_.listener_ == NULL); | |
610 that_.listener_ = &listener; // TODO - STORE IN TRANSACTION | |
611 | |
610 #if defined(NDEBUG) | 612 #if defined(NDEBUG) |
611 // Release mode | 613 // Release mode |
612 initialDiskSize_ = 0; | 614 initialDiskSize_ = 0; |
613 #else | 615 #else |
614 // Debug mode | 616 // Debug mode |
615 initialDiskSize_ = static_cast<int64_t>(that_.GetTotalCompressedSize()); | 617 initialDiskSize_ = static_cast<int64_t>(that_.GetTotalCompressedSize()); |
616 #endif | 618 #endif |
617 } | 619 } |
618 | 620 |
621 virtual ~ReadWriteTransaction() | |
622 { | |
623 assert(that_.listener_ != NULL); | |
624 that_.listener_ = NULL; // TODO - STORE IN TRANSACTION | |
625 } | |
626 | |
619 void Begin() | 627 void Begin() |
620 { | 628 { |
621 transaction_->Begin(); | 629 transaction_->Begin(); |
622 } | 630 } |
623 | 631 |
636 }; | 644 }; |
637 | 645 |
638 | 646 |
639 class SQLiteDatabaseWrapper::ReadOnlyTransaction : public IDatabaseWrapper::ITransaction | 647 class SQLiteDatabaseWrapper::ReadOnlyTransaction : public IDatabaseWrapper::ITransaction |
640 { | 648 { |
649 private: | |
650 SQLiteDatabaseWrapper& that_; | |
651 | |
641 public: | 652 public: |
653 ReadOnlyTransaction(SQLiteDatabaseWrapper& that, | |
654 IDatabaseListener& listener) : | |
655 that_(that) | |
656 { | |
657 assert(that_.listener_ == NULL); | |
658 that_.listener_ = &listener; | |
659 } | |
660 | |
661 virtual ~ReadOnlyTransaction() | |
662 { | |
663 assert(that_.listener_ != NULL); | |
664 that_.listener_ = NULL; | |
665 } | |
666 | |
642 virtual void Rollback() ORTHANC_OVERRIDE | 667 virtual void Rollback() ORTHANC_OVERRIDE |
643 { | 668 { |
644 } | 669 } |
645 | 670 |
646 virtual void Commit(int64_t fileSizeDelta /* only used in debug */) ORTHANC_OVERRIDE | 671 virtual void Commit(int64_t fileSizeDelta /* only used in debug */) ORTHANC_OVERRIDE |
651 } | 676 } |
652 } | 677 } |
653 }; | 678 }; |
654 | 679 |
655 | 680 |
656 IDatabaseWrapper::ITransaction* SQLiteDatabaseWrapper::StartTransaction(TransactionType type) | 681 IDatabaseWrapper::ITransaction* SQLiteDatabaseWrapper::StartTransaction(TransactionType type, |
682 IDatabaseListener& listener) | |
657 { | 683 { |
658 switch (type) | 684 switch (type) |
659 { | 685 { |
660 case TransactionType_ReadOnly: | 686 case TransactionType_ReadOnly: |
661 return new ReadOnlyTransaction; // This is a no-op transaction in SQLite (thanks to mutex) | 687 return new ReadOnlyTransaction(*this, listener); // This is a no-op transaction in SQLite (thanks to mutex) |
662 | 688 |
663 case TransactionType_ReadWrite: | 689 case TransactionType_ReadWrite: |
664 { | 690 { |
665 std::unique_ptr<ReadWriteTransaction> transaction; | 691 std::unique_ptr<ReadWriteTransaction> transaction; |
666 transaction.reset(new ReadWriteTransaction(*this)); | 692 transaction.reset(new ReadWriteTransaction(*this, listener)); |
667 transaction->Begin(); | 693 transaction->Begin(); |
668 return transaction.release(); | 694 return transaction.release(); |
669 } | 695 } |
670 | 696 |
671 default: | 697 default: |