Mercurial > hg > orthanc-databases
comparison Framework/Plugins/DatabaseBackendAdapterV3.cpp @ 374:4a3985088723 db-protobuf
moved class IndexConnectionsPool out of DatabaseBackendAdapterV3
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 28 Mar 2023 14:51:17 +0200 |
parents | be7de633695c |
children | 9db9e0275ec0 |
comparison
equal
deleted
inserted
replaced
373:be7de633695c | 374:4a3985088723 |
---|---|
23 #include "DatabaseBackendAdapterV3.h" | 23 #include "DatabaseBackendAdapterV3.h" |
24 | 24 |
25 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 | 25 #if defined(ORTHANC_PLUGINS_VERSION_IS_ABOVE) // Macro introduced in Orthanc 1.3.1 |
26 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) | 26 # if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 9, 2) |
27 | 27 |
28 #include "IndexConnectionsPool.h" | |
29 | |
28 #include <Logging.h> | 30 #include <Logging.h> |
29 #include <MultiThreading/SharedMessageQueue.h> | |
30 #include <OrthancException.h> | 31 #include <OrthancException.h> |
31 | 32 |
32 #include <stdexcept> | 33 #include <stdexcept> |
33 #include <list> | 34 #include <list> |
34 #include <string> | 35 #include <string> |
80 target.push_back(*it); | 81 target.push_back(*it); |
81 } | 82 } |
82 } | 83 } |
83 | 84 |
84 | 85 |
85 class DatabaseBackendAdapterV3::Adapter : public boost::noncopyable | |
86 { | |
87 private: | |
88 class ManagerReference : public Orthanc::IDynamicObject | |
89 { | |
90 private: | |
91 DatabaseManager* manager_; | |
92 | |
93 public: | |
94 ManagerReference(DatabaseManager& manager) : | |
95 manager_(&manager) | |
96 { | |
97 } | |
98 | |
99 DatabaseManager& GetManager() | |
100 { | |
101 assert(manager_ != NULL); | |
102 return *manager_; | |
103 } | |
104 }; | |
105 | |
106 std::unique_ptr<IndexBackend> backend_; | |
107 OrthancPluginContext* context_; | |
108 boost::shared_mutex connectionsMutex_; | |
109 size_t countConnections_; | |
110 std::list<DatabaseManager*> connections_; | |
111 Orthanc::SharedMessageQueue availableConnections_; | |
112 | |
113 public: | |
114 Adapter(IndexBackend* backend, | |
115 size_t countConnections) : | |
116 backend_(backend), | |
117 countConnections_(countConnections) | |
118 { | |
119 if (countConnections == 0) | |
120 { | |
121 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, | |
122 "There must be a non-zero number of connections to the database"); | |
123 } | |
124 else if (backend == NULL) | |
125 { | |
126 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); | |
127 } | |
128 else | |
129 { | |
130 context_ = backend_->GetContext(); | |
131 } | |
132 } | |
133 | |
134 ~Adapter() | |
135 { | |
136 for (std::list<DatabaseManager*>::iterator | |
137 it = connections_.begin(); it != connections_.end(); ++it) | |
138 { | |
139 assert(*it != NULL); | |
140 delete *it; | |
141 } | |
142 } | |
143 | |
144 OrthancPluginContext* GetContext() const | |
145 { | |
146 return context_; | |
147 } | |
148 | |
149 void OpenConnections() | |
150 { | |
151 boost::unique_lock<boost::shared_mutex> lock(connectionsMutex_); | |
152 | |
153 if (connections_.size() == 0) | |
154 { | |
155 assert(backend_.get() != NULL); | |
156 | |
157 { | |
158 std::unique_ptr<DatabaseManager> manager(new DatabaseManager(backend_->CreateDatabaseFactory())); | |
159 manager->GetDatabase(); // Make sure to open the database connection | |
160 | |
161 backend_->ConfigureDatabase(*manager); | |
162 connections_.push_back(manager.release()); | |
163 } | |
164 | |
165 for (size_t i = 1; i < countConnections_; i++) | |
166 { | |
167 connections_.push_back(new DatabaseManager(backend_->CreateDatabaseFactory())); | |
168 connections_.back()->GetDatabase(); // Make sure to open the database connection | |
169 } | |
170 | |
171 for (std::list<DatabaseManager*>::iterator | |
172 it = connections_.begin(); it != connections_.end(); ++it) | |
173 { | |
174 assert(*it != NULL); | |
175 availableConnections_.Enqueue(new ManagerReference(**it)); | |
176 } | |
177 } | |
178 else | |
179 { | |
180 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
181 } | |
182 } | |
183 | |
184 void CloseConnections() | |
185 { | |
186 boost::unique_lock<boost::shared_mutex> lock(connectionsMutex_); | |
187 | |
188 if (connections_.size() != countConnections_) | |
189 { | |
190 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); | |
191 } | |
192 else if (availableConnections_.GetSize() != countConnections_) | |
193 { | |
194 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database, "Some connections are still in use, bug in the Orthanc core"); | |
195 } | |
196 else | |
197 { | |
198 for (std::list<DatabaseManager*>::iterator | |
199 it = connections_.begin(); it != connections_.end(); ++it) | |
200 { | |
201 assert(*it != NULL); | |
202 (*it)->Close(); | |
203 } | |
204 } | |
205 } | |
206 | |
207 class DatabaseAccessor : public boost::noncopyable | |
208 { | |
209 private: | |
210 boost::shared_lock<boost::shared_mutex> lock_; | |
211 Adapter& adapter_; | |
212 DatabaseManager* manager_; | |
213 | |
214 public: | |
215 DatabaseAccessor(Adapter& adapter) : | |
216 lock_(adapter.connectionsMutex_), | |
217 adapter_(adapter), | |
218 manager_(NULL) | |
219 { | |
220 for (;;) | |
221 { | |
222 std::unique_ptr<Orthanc::IDynamicObject> manager(adapter.availableConnections_.Dequeue(100)); | |
223 if (manager.get() != NULL) | |
224 { | |
225 manager_ = &dynamic_cast<ManagerReference&>(*manager).GetManager(); | |
226 return; | |
227 } | |
228 } | |
229 } | |
230 | |
231 ~DatabaseAccessor() | |
232 { | |
233 assert(manager_ != NULL); | |
234 adapter_.availableConnections_.Enqueue(new ManagerReference(*manager_)); | |
235 } | |
236 | |
237 IndexBackend& GetBackend() const | |
238 { | |
239 return *adapter_.backend_; | |
240 } | |
241 | |
242 DatabaseManager& GetManager() const | |
243 { | |
244 assert(manager_ != NULL); | |
245 return *manager_; | |
246 } | |
247 }; | |
248 }; | |
249 | |
250 | |
251 class DatabaseBackendAdapterV3::Output : public IDatabaseBackendOutput | 86 class DatabaseBackendAdapterV3::Output : public IDatabaseBackendOutput |
252 { | 87 { |
253 private: | 88 private: |
254 struct Metadata | 89 struct Metadata |
255 { | 90 { |
800 | 635 |
801 | 636 |
802 class DatabaseBackendAdapterV3::Transaction : public boost::noncopyable | 637 class DatabaseBackendAdapterV3::Transaction : public boost::noncopyable |
803 { | 638 { |
804 private: | 639 private: |
805 Adapter& adapter_; | 640 IndexConnectionsPool& pool_; |
806 std::unique_ptr<Adapter::DatabaseAccessor> accessor_; | 641 std::unique_ptr<IndexConnectionsPool::Accessor> accessor_; |
807 std::unique_ptr<Output> output_; | 642 std::unique_ptr<Output> output_; |
808 | 643 |
809 public: | 644 public: |
810 Transaction(Adapter& adapter) : | 645 Transaction(IndexConnectionsPool& pool) : |
811 adapter_(adapter), | 646 pool_(pool), |
812 accessor_(new Adapter::DatabaseAccessor(adapter)), | 647 accessor_(new IndexConnectionsPool::Accessor(pool)), |
813 output_(new Output) | 648 output_(new Output) |
814 { | 649 { |
815 } | 650 } |
816 | 651 |
817 ~Transaction() | 652 ~Transaction() |
959 } | 794 } |
960 | 795 |
961 | 796 |
962 static OrthancPluginErrorCode Open(void* database) | 797 static OrthancPluginErrorCode Open(void* database) |
963 { | 798 { |
964 DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database); | 799 IndexConnectionsPool* pool = reinterpret_cast<IndexConnectionsPool*>(database); |
965 | 800 |
966 try | 801 try |
967 { | 802 { |
968 adapter->OpenConnections(); | 803 pool->OpenConnections(); |
969 return OrthancPluginErrorCode_Success; | 804 return OrthancPluginErrorCode_Success; |
970 } | 805 } |
971 ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetContext()); | 806 ORTHANC_PLUGINS_DATABASE_CATCH(pool->GetContext()); |
972 } | 807 } |
973 | 808 |
974 | 809 |
975 static OrthancPluginErrorCode Close(void* database) | 810 static OrthancPluginErrorCode Close(void* database) |
976 { | 811 { |
977 DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database); | 812 IndexConnectionsPool* pool = reinterpret_cast<IndexConnectionsPool*>(database); |
978 | 813 |
979 try | 814 try |
980 { | 815 { |
981 adapter->CloseConnections(); | 816 pool->CloseConnections(); |
982 return OrthancPluginErrorCode_Success; | 817 return OrthancPluginErrorCode_Success; |
983 } | 818 } |
984 ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetContext()); | 819 ORTHANC_PLUGINS_DATABASE_CATCH(pool->GetContext()); |
985 } | 820 } |
986 | 821 |
987 | 822 |
988 static OrthancPluginErrorCode DestructDatabase(void* database) | 823 static OrthancPluginErrorCode DestructDatabase(void* database) |
989 { | 824 { |
990 DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database); | 825 IndexConnectionsPool* pool = reinterpret_cast<IndexConnectionsPool*>(database); |
991 | 826 |
992 if (adapter == NULL) | 827 if (pool == NULL) |
993 { | 828 { |
994 return OrthancPluginErrorCode_InternalError; | 829 return OrthancPluginErrorCode_InternalError; |
995 } | 830 } |
996 else | 831 else |
997 { | 832 { |
999 { | 834 { |
1000 isBackendInUse_ = false; | 835 isBackendInUse_ = false; |
1001 } | 836 } |
1002 else | 837 else |
1003 { | 838 { |
1004 OrthancPluginLogError(adapter->GetContext(), "More than one index backend was registered, internal error"); | 839 OrthancPluginLogError(pool->GetContext(), "More than one index backend was registered, internal error"); |
1005 } | 840 } |
1006 | 841 |
1007 delete adapter; | 842 delete pool; |
1008 | 843 |
1009 return OrthancPluginErrorCode_Success; | 844 return OrthancPluginErrorCode_Success; |
1010 } | 845 } |
1011 } | 846 } |
1012 | 847 |
1013 | 848 |
1014 static OrthancPluginErrorCode GetDatabaseVersion(void* database, | 849 static OrthancPluginErrorCode GetDatabaseVersion(void* database, |
1015 uint32_t* version) | 850 uint32_t* version) |
1016 { | 851 { |
1017 DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database); | 852 IndexConnectionsPool* pool = reinterpret_cast<IndexConnectionsPool*>(database); |
1018 | 853 |
1019 try | 854 try |
1020 { | 855 { |
1021 DatabaseBackendAdapterV3::Adapter::DatabaseAccessor accessor(*adapter); | 856 IndexConnectionsPool::Accessor accessor(*pool); |
1022 *version = accessor.GetBackend().GetDatabaseVersion(accessor.GetManager()); | 857 *version = accessor.GetBackend().GetDatabaseVersion(accessor.GetManager()); |
1023 return OrthancPluginErrorCode_Success; | 858 return OrthancPluginErrorCode_Success; |
1024 } | 859 } |
1025 ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetContext()); | 860 ORTHANC_PLUGINS_DATABASE_CATCH(pool->GetContext()); |
1026 } | 861 } |
1027 | 862 |
1028 | 863 |
1029 static OrthancPluginErrorCode UpgradeDatabase(void* database, | 864 static OrthancPluginErrorCode UpgradeDatabase(void* database, |
1030 OrthancPluginStorageArea* storageArea, | 865 OrthancPluginStorageArea* storageArea, |
1031 uint32_t targetVersion) | 866 uint32_t targetVersion) |
1032 { | 867 { |
1033 DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database); | 868 IndexConnectionsPool* pool = reinterpret_cast<IndexConnectionsPool*>(database); |
1034 | 869 |
1035 try | 870 try |
1036 { | 871 { |
1037 DatabaseBackendAdapterV3::Adapter::DatabaseAccessor accessor(*adapter); | 872 IndexConnectionsPool::Accessor accessor(*pool); |
1038 accessor.GetBackend().UpgradeDatabase(accessor.GetManager(), targetVersion, storageArea); | 873 accessor.GetBackend().UpgradeDatabase(accessor.GetManager(), targetVersion, storageArea); |
1039 return OrthancPluginErrorCode_Success; | 874 return OrthancPluginErrorCode_Success; |
1040 } | 875 } |
1041 ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetContext()); | 876 ORTHANC_PLUGINS_DATABASE_CATCH(pool->GetContext()); |
1042 } | 877 } |
1043 | 878 |
1044 | 879 |
1045 static OrthancPluginErrorCode HasRevisionsSupport(void* database, | 880 static OrthancPluginErrorCode HasRevisionsSupport(void* database, |
1046 uint8_t* target) | 881 uint8_t* target) |
1047 { | 882 { |
1048 DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database); | 883 IndexConnectionsPool* pool = reinterpret_cast<IndexConnectionsPool*>(database); |
1049 | 884 |
1050 try | 885 try |
1051 { | 886 { |
1052 DatabaseBackendAdapterV3::Adapter::DatabaseAccessor accessor(*adapter); | 887 IndexConnectionsPool::Accessor accessor(*pool); |
1053 *target = (accessor.GetBackend().HasRevisionsSupport() ? 1 : 0); | 888 *target = (accessor.GetBackend().HasRevisionsSupport() ? 1 : 0); |
1054 return OrthancPluginErrorCode_Success; | 889 return OrthancPluginErrorCode_Success; |
1055 } | 890 } |
1056 ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetContext()); | 891 ORTHANC_PLUGINS_DATABASE_CATCH(pool->GetContext()); |
1057 } | 892 } |
1058 | 893 |
1059 | 894 |
1060 static OrthancPluginErrorCode StartTransaction(void* database, | 895 static OrthancPluginErrorCode StartTransaction(void* database, |
1061 OrthancPluginDatabaseTransaction** target /* out */, | 896 OrthancPluginDatabaseTransaction** target /* out */, |
1062 OrthancPluginDatabaseTransactionType type) | 897 OrthancPluginDatabaseTransactionType type) |
1063 { | 898 { |
1064 DatabaseBackendAdapterV3::Adapter* adapter = reinterpret_cast<DatabaseBackendAdapterV3::Adapter*>(database); | 899 IndexConnectionsPool* pool = reinterpret_cast<IndexConnectionsPool*>(database); |
1065 | 900 |
1066 try | 901 try |
1067 { | 902 { |
1068 std::unique_ptr<DatabaseBackendAdapterV3::Transaction> transaction(new DatabaseBackendAdapterV3::Transaction(*adapter)); | 903 std::unique_ptr<DatabaseBackendAdapterV3::Transaction> transaction(new DatabaseBackendAdapterV3::Transaction(*pool)); |
1069 | 904 |
1070 switch (type) | 905 switch (type) |
1071 { | 906 { |
1072 case OrthancPluginDatabaseTransactionType_ReadOnly: | 907 case OrthancPluginDatabaseTransactionType_ReadOnly: |
1073 transaction->GetManager().StartTransaction(TransactionType_ReadOnly); | 908 transaction->GetManager().StartTransaction(TransactionType_ReadOnly); |
1083 | 918 |
1084 *target = reinterpret_cast<OrthancPluginDatabaseTransaction*>(transaction.release()); | 919 *target = reinterpret_cast<OrthancPluginDatabaseTransaction*>(transaction.release()); |
1085 | 920 |
1086 return OrthancPluginErrorCode_Success; | 921 return OrthancPluginErrorCode_Success; |
1087 } | 922 } |
1088 ORTHANC_PLUGINS_DATABASE_CATCH(adapter->GetContext()); | 923 ORTHANC_PLUGINS_DATABASE_CATCH(pool->GetContext()); |
1089 } | 924 } |
1090 | 925 |
1091 | 926 |
1092 static OrthancPluginErrorCode DestructTransaction(OrthancPluginDatabaseTransaction* transaction) | 927 static OrthancPluginErrorCode DestructTransaction(OrthancPluginDatabaseTransaction* transaction) |
1093 { | 928 { |
2075 | 1910 |
2076 OrthancPluginContext* context = protection->GetContext(); | 1911 OrthancPluginContext* context = protection->GetContext(); |
2077 | 1912 |
2078 if (OrthancPluginRegisterDatabaseBackendV3( | 1913 if (OrthancPluginRegisterDatabaseBackendV3( |
2079 context, ¶ms, sizeof(params), maxDatabaseRetries, | 1914 context, ¶ms, sizeof(params), maxDatabaseRetries, |
2080 new Adapter(protection.release(), countConnections)) != OrthancPluginErrorCode_Success) | 1915 new IndexConnectionsPool(protection.release(), countConnections)) != OrthancPluginErrorCode_Success) |
2081 { | 1916 { |
2082 delete backend; | 1917 delete backend; |
2083 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Unable to register the database backend"); | 1918 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError, "Unable to register the database backend"); |
2084 } | 1919 } |
2085 | 1920 |