From c97454e828b8eabda7a1617eefe6f47e92decc00 Mon Sep 17 00:00:00 2001 From: Simon Quigley Date: Mon, 27 Jan 2025 01:00:33 -0600 Subject: [PATCH] Attempt to set max concurrent connections manually --- cpp/db_common.cpp | 70 +++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/cpp/db_common.cpp b/cpp/db_common.cpp index 2d5d7a6..4f3fbdc 100644 --- a/cpp/db_common.cpp +++ b/cpp/db_common.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -26,8 +27,11 @@ #include // get_thread_connection and init_database +constexpr int MAX_CONNECTIONS = 5; static std::mutex connection_mutex_; +static std::condition_variable connection_cv_; static std::atomic thread_id_counter{1}; +static int active_connections = 0; static QString shared_database_path; static int get_delay(int attempt) { @@ -40,34 +44,54 @@ QSqlDatabase get_thread_connection() { bool passed = false; int attempt = 0; while (!passed) { - std::lock_guard lock(connection_mutex_); - thread_local unsigned int thread_unique_id = thread_id_counter.fetch_add(1); - connection_name = QString("CIConn_%1").arg(thread_unique_id); - - // Check if the connection already exists for this thread - attempt++; - if (QSqlDatabase::contains(connection_name)) { - QSqlDatabase db = QSqlDatabase::database(connection_name); - if (!db.isOpen()) { - if (!db.open()) { - std::string last_error_text = db.lastError().text().toStdString(); - if (last_error_text.contains("unable to open database file")) { - std::this_thread::sleep_for(std::chrono::milliseconds(get_delay(attempt))); - continue; - } - throw std::runtime_error(std::format("Failed to open thread-specific database connection: {}", last_error_text)); - } - } - return db; + { + std::unique_lock lock(connection_mutex_); + connection_cv_.wait(lock, [] { return active_connections < MAX_CONNECTIONS; }); + active_connections++; } - thread_db = QSqlDatabase::addDatabase("QSQLITE", connection_name); - thread_db.setDatabaseName(shared_database_path); + try { + thread_local unsigned int thread_unique_id = thread_id_counter.fetch_add(1); + connection_name = QString("CIConn_%1").arg(thread_unique_id); - if (!thread_db.open()) throw std::runtime_error("Failed to open new database connection for thread: " + thread_db.lastError().text().toStdString()); - passed = true; + // Check if the connection already exists for this thread + attempt++; + if (QSqlDatabase::contains(connection_name)) { + QSqlDatabase db = QSqlDatabase::database(connection_name); + if (!db.isOpen()) { + if (!db.open()) { + std::string last_error_text = db.lastError().text().toStdString(); + if (last_error_text.contains("unable to open database file")) { + std::this_thread::sleep_for(std::chrono::milliseconds(get_delay(attempt))); + continue; + } + throw std::runtime_error(std::format("Failed to open thread-specific database connection: {}", last_error_text)); + } + } + return db; + } + + thread_db = QSqlDatabase::addDatabase("QSQLITE", connection_name); + thread_db.setDatabaseName(shared_database_path); + + if (!thread_db.open()) throw std::runtime_error("Failed to open new database connection for thread: " + thread_db.lastError().text().toStdString()); + passed = true; + } catch (...) { + { + std::lock_guard lock(connection_mutex_); + active_connections--; + } + connection_cv_.notify_one(); + throw; + } } + { + std::lock_guard lock(connection_mutex_); + active_connections--; + } + connection_cv_.notify_one(); + return thread_db; }