Mercurial > hg > orthanc-databases
view Framework/Plugins/DynamicIndexConnectionsPool.cpp @ 722:845c3dcb723e sql-opti
cleanup
author | Alain Mazy <am@orthanc.team> |
---|---|
date | Mon, 11 Aug 2025 18:20:50 +0200 |
parents | bcea50e40d6e |
children | c76a214a3954 |
line wrap: on
line source
/** * Orthanc - A Lightweight, RESTful DICOM Store * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics * Department, University Hospital of Liege, Belgium * Copyright (C) 2017-2023 Osimis S.A., Belgium * Copyright (C) 2024-2025 Orthanc Team SRL, Belgium * Copyright (C) 2021-2025 Sebastien Jodogne, ICTEAM UCLouvain, Belgium * * This program is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ #include "DynamicIndexConnectionsPool.h" #include <Logging.h> namespace OrthancDatabases { void DynamicIndexConnectionsPool::PerformPoolHousekeeping() { CleanupOldConnections(); OrthancPluginSetMetricsValue(OrthancPlugins::GetGlobalContext(), "orthanc_index_active_connections_count", maxConnectionsCount_ - connectionsSemaphore_.GetAvailableResourcesCount(), OrthancPluginMetricsType_Default); } DynamicIndexConnectionsPool::DynamicIndexConnectionsPool(IndexBackend* backend, size_t maxConnectionsCount, unsigned int houseKeepingDelaySeconds) : BaseIndexConnectionsPool(backend, houseKeepingDelaySeconds), maxConnectionsCount_(maxConnectionsCount), connectionsSemaphore_(maxConnectionsCount), availableConnectionsSemaphore_(0) { if (maxConnectionsCount == 0) { throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange, "There must be a non-zero number of connections to the database"); } } DynamicIndexConnectionsPool::~DynamicIndexConnectionsPool() { boost::mutex::scoped_lock lock(connectionsMutex_); for (std::list<DatabaseManager*>::iterator it = connections_.begin(); it != connections_.end(); ++it) { assert(*it != NULL); delete *it; } } void DynamicIndexConnectionsPool::OpenConnections(bool hasIdentifierTags, const std::list<IdentifierTag>& identifierTags) { assert(backend_.get() != NULL); DynamicIndexConnectionsPool::Accessor accessor(*this); backend_->ConfigureDatabase(accessor.GetManager(), hasIdentifierTags, identifierTags); StartHousekeepingThread(); } void DynamicIndexConnectionsPool::CloseConnections() { StopHousekeepingThread(); boost::mutex::scoped_lock lock(connectionsMutex_); for (std::list<DatabaseManager*>::iterator it = connections_.begin(); it != connections_.end(); ++it) { assert(*it != NULL); (*it)->Close(); } } DatabaseManager* DynamicIndexConnectionsPool::GetConnection() { if (availableConnectionsSemaphore_.TryAcquire(1)) // there is a connection directly available, take it { // LOG(INFO) << "--- Reusing an available connection"; boost::mutex::scoped_lock lock(connectionsMutex_); std::unique_ptr<DatabaseManager> manager(availableConnections_.front()); availableConnections_.pop_front(); return manager.release(); } else if (connectionsSemaphore_.TryAcquire(1)) // no connection directly available, check if we can create a new one { // LOG(INFO) << "--- Creating a new connection"; boost::mutex::scoped_lock lock(connectionsMutex_); connections_.push_back(new DatabaseManager(backend_->CreateDatabaseFactory())); connections_.back()->GetDatabase(); // Make sure to open the database connection // no need to push it in the availableConnections since it is being used immediately return connections_.back(); } else // unable to get a connection now { return NULL; } } void DynamicIndexConnectionsPool::CleanupOldConnections() { boost::mutex::scoped_lock lock(connectionsMutex_); while (availableConnectionsSemaphore_.TryAcquire(1)) { DatabaseManager* manager = availableConnections_.front(); if (manager->GetElapsedSecondsSinceLastUse() > 60 || manager->GetElapsedSecondsSinceCreation() > 3600) { // LOG(INFO) << "--- Deleting an old connection"; availableConnections_.pop_front(); connections_.remove(manager); delete manager; connectionsSemaphore_.Release(1); } else { availableConnectionsSemaphore_.Release(1); // we have not consumed it break; } } } void DynamicIndexConnectionsPool::ReleaseConnection(DatabaseManager* manager) { boost::mutex::scoped_lock lock(connectionsMutex_); availableConnections_.push_front(manager); availableConnectionsSemaphore_.Release(1); } }