comparison Framework/Plugins/IndexConnectionsPool.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
children 3d6886f3e5b3
comparison
equal deleted inserted replaced
373:be7de633695c 374:4a3985088723
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 Affero General Public License
10 * as published by the Free Software Foundation, either version 3 of
11 * the 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 * Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 **/
21
22
23 #include "IndexConnectionsPool.h"
24
25 namespace OrthancDatabases
26 {
27 class IndexConnectionsPool::ManagerReference : public Orthanc::IDynamicObject
28 {
29 private:
30 DatabaseManager* manager_;
31
32 public:
33 ManagerReference(DatabaseManager& manager) :
34 manager_(&manager)
35 {
36 }
37
38 DatabaseManager& GetManager()
39 {
40 assert(manager_ != NULL);
41 return *manager_;
42 }
43 };
44
45
46 IndexConnectionsPool::IndexConnectionsPool(IndexBackend* backend,
47 size_t countConnections) :
48 backend_(backend),
49 countConnections_(countConnections)
50 {
51 if (countConnections == 0)
52 {
53 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange,
54 "There must be a non-zero number of connections to the database");
55 }
56 else if (backend == NULL)
57 {
58 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
59 }
60 else
61 {
62 context_ = backend_->GetContext();
63 }
64 }
65
66
67 IndexConnectionsPool::~IndexConnectionsPool()
68 {
69 for (std::list<DatabaseManager*>::iterator
70 it = connections_.begin(); it != connections_.end(); ++it)
71 {
72 assert(*it != NULL);
73 delete *it;
74 }
75 }
76
77
78 void IndexConnectionsPool::OpenConnections()
79 {
80 boost::unique_lock<boost::shared_mutex> lock(connectionsMutex_);
81
82 if (connections_.size() == 0)
83 {
84 assert(backend_.get() != NULL);
85
86 {
87 std::unique_ptr<DatabaseManager> manager(new DatabaseManager(backend_->CreateDatabaseFactory()));
88 manager->GetDatabase(); // Make sure to open the database connection
89
90 backend_->ConfigureDatabase(*manager);
91 connections_.push_back(manager.release());
92 }
93
94 for (size_t i = 1; i < countConnections_; i++)
95 {
96 connections_.push_back(new DatabaseManager(backend_->CreateDatabaseFactory()));
97 connections_.back()->GetDatabase(); // Make sure to open the database connection
98 }
99
100 for (std::list<DatabaseManager*>::iterator
101 it = connections_.begin(); it != connections_.end(); ++it)
102 {
103 assert(*it != NULL);
104 availableConnections_.Enqueue(new ManagerReference(**it));
105 }
106 }
107 else
108 {
109 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
110 }
111 }
112
113
114 void IndexConnectionsPool::CloseConnections()
115 {
116 boost::unique_lock<boost::shared_mutex> lock(connectionsMutex_);
117
118 if (connections_.size() != countConnections_)
119 {
120 throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
121 }
122 else if (availableConnections_.GetSize() != countConnections_)
123 {
124 throw Orthanc::OrthancException(Orthanc::ErrorCode_Database, "Some connections are still in use, bug in the Orthanc core");
125 }
126 else
127 {
128 for (std::list<DatabaseManager*>::iterator
129 it = connections_.begin(); it != connections_.end(); ++it)
130 {
131 assert(*it != NULL);
132 (*it)->Close();
133 }
134 }
135 }
136
137
138 IndexConnectionsPool::Accessor::Accessor(IndexConnectionsPool& pool) :
139 lock_(pool.connectionsMutex_),
140 pool_(pool),
141 manager_(NULL)
142 {
143 for (;;)
144 {
145 std::unique_ptr<Orthanc::IDynamicObject> manager(pool.availableConnections_.Dequeue(100));
146 if (manager.get() != NULL)
147 {
148 manager_ = &dynamic_cast<ManagerReference&>(*manager).GetManager();
149 return;
150 }
151 }
152 }
153
154
155 IndexConnectionsPool::Accessor::~Accessor()
156 {
157 assert(manager_ != NULL);
158 pool_.availableConnections_.Enqueue(new ManagerReference(*manager_));
159 }
160
161
162 IndexBackend& IndexConnectionsPool::Accessor::GetBackend() const
163 {
164 return *pool_.backend_;
165 }
166
167
168 DatabaseManager& IndexConnectionsPool::Accessor::GetManager() const
169 {
170 assert(manager_ != NULL);
171 return *manager_;
172 }
173 }