From 8dc972b4deca8a5da8582a15f86929037581cfdb Mon Sep 17 00:00:00 2001 From: Simon Quigley Date: Sat, 25 Jan 2025 12:40:39 -0600 Subject: [PATCH] Move the database initialization to db_common --- cpp/ci_logic.cpp | 154 +--------------------------------------------- cpp/ci_logic.h | 4 -- cpp/db_common.cpp | 148 ++++++++++++++++++++++++++++++++++++++++++-- cpp/db_common.h | 1 + 4 files changed, 147 insertions(+), 160 deletions(-) diff --git a/cpp/ci_logic.cpp b/cpp/ci_logic.cpp index b3c4116..e5e1add 100644 --- a/cpp/ci_logic.cpp +++ b/cpp/ci_logic.cpp @@ -18,6 +18,7 @@ #include "lubuntuci_lib.h" #include "common.h" #include "utilities.h" +#include "db_common.h" #include #include @@ -273,157 +274,6 @@ YAML::Node CiLogic::load_yaml_config(const fs::path &config_path) { return YAML::LoadFile(config_path.string()); } -/** - * init_database(): - * If the DB connection name is known, reuse it. Otherwise, create it. - */ -bool CiLogic::init_database(const QString& connectionName, const QString& databasePath) { - // Initialize the base connection in the main thread - if (QSqlDatabase::contains(connectionName)) { - QSqlDatabase::removeDatabase(connectionName); - } - - QSqlDatabase baseDb = QSqlDatabase::addDatabase("QSQLITE", connectionName); - baseDb.setDatabaseName(databasePath); - - if (!baseDb.open()) { - log_error("Cannot open database: " + baseDb.lastError().text().toStdString()); - return false; - } - - // Apply PRAGMAs - QSqlQuery pragmaQuery(baseDb); - pragmaQuery.exec("PRAGMA journal_mode = WAL;"); - pragmaQuery.exec("PRAGMA synchronous = NORMAL;"); - pragmaQuery.exec("PRAGMA foreign_keys = ON;"); - - // Run the schema creation (or migration) statements - QStringList sqlStatements = QString(R"( - CREATE TABLE IF NOT EXISTS person ( - id INTEGER PRIMARY KEY, - username TEXT NOT NULL, - logo_url TEXT - ); - - CREATE TABLE IF NOT EXISTS person_token ( - id INTEGER PRIMARY KEY, - person_id INTEGER NOT NULL, - token TEXT NOT NULL, - expiry_date TEXT NOT NULL, - FOREIGN KEY (person_id) REFERENCES person(id) ON DELETE CASCADE - ); - - CREATE TABLE IF NOT EXISTS package ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL, - large INTEGER NOT NULL DEFAULT 0, - upstream_url TEXT NOT NULL, - packaging_branch TEXT NOT NULL, - packaging_url TEXT NOT NULL - ); - - CREATE TABLE IF NOT EXISTS release ( - id INTEGER PRIMARY KEY, - version INTEGER NOT NULL UNIQUE, - codename TEXT NOT NULL UNIQUE, - isDefault INTEGER NOT NULL DEFAULT 0 - ); - - CREATE TABLE IF NOT EXISTS branch ( - id INTEGER PRIMARY KEY, - name TEXT NOT NULL, - upload_target TEXT NOT NULL, - upload_target_ssh TEXT NOT NULL - ); - - INSERT INTO branch (name, upload_target, upload_target_ssh) - SELECT 'unstable', 'ppa:lubuntu-ci/unstable-ci-proposed', 'ssh-ppa:lubuntu-ci/unstable-ci-proposed' - WHERE NOT EXISTS (SELECT 1 FROM branch WHERE name='unstable'); - - CREATE TABLE IF NOT EXISTS git_commit ( - id INTEGER PRIMARY KEY, - commit_hash TEXT NOT NULL, - commit_summary TEXT NOT NULL, - commit_message TEXT NOT NULL, - commit_datetime DATETIME NOT NULL, - commit_author TEXT NOT NULL, - commit_committer TEXT NOT NULL - ); - - CREATE TABLE IF NOT EXISTS packageconf ( - id INTEGER PRIMARY KEY, - upstream_version TEXT, - ppa_revision INTEGER, - package_id INTEGER NOT NULL, - release_id INTEGER NOT NULL, - branch_id INTEGER NOT NULL, - packaging_commit_id INTEGER, - upstream_commit_id INTEGER, - FOREIGN KEY (package_id) REFERENCES package(id) ON DELETE CASCADE, - FOREIGN KEY (release_id) REFERENCES release(id) ON DELETE CASCADE, - FOREIGN KEY (branch_id) REFERENCES branch(id) ON DELETE CASCADE, - FOREIGN KEY (packaging_commit_id) REFERENCES git_commit(id) ON DELETE CASCADE, - FOREIGN KEY (upstream_commit_id) REFERENCES git_commit(id) ON DELETE CASCADE - ); - - CREATE TABLE IF NOT EXISTS jobstatus ( - id INTEGER PRIMARY KEY, - build_score INTEGER NOT NULL, - name TEXT NOT NULL UNIQUE, - display_name TEXT NOT NULL - ); - - INSERT OR IGNORE INTO jobstatus (build_score, name, display_name) - VALUES - (80, 'pull', 'Pull'), - (70, 'tarball', 'Create Tarball'), - (60, 'source_build', 'Source Build'), - (50, 'upload', 'Upload'), - (40, 'source_check', 'Source Check'), - (30, 'build_check', 'Build Check'), - (20, 'lintian', 'Lintian'), - (10, 'britney', 'Britney'); - - CREATE TABLE IF NOT EXISTS task ( - id INTEGER PRIMARY KEY, - packageconf_id INTEGER NOT NULL, - jobstatus_id INTEGER NOT NULL, - queue_time INTEGER DEFAULT 0, - start_time INTEGER DEFAULT 0, - finish_time INTEGER DEFAULT 0, - successful INTEGER, - log TEXT, - FOREIGN KEY (packageconf_id) REFERENCES packageconf(id), - FOREIGN KEY (jobstatus_id) REFERENCES jobstatus(id) - ); - - CREATE TABLE IF NOT EXISTS packageconf_jobstatus_id ( - id INTEGER PRIMARY KEY, - packageconf_id INTEGER NOT NULL, - jobstatus_id INTEGER NOT NULL, - task_id INTEGER NOT NULL, - FOREIGN KEY (packageconf_id) REFERENCES packageconf(id), - FOREIGN KEY (jobstatus_id) REFERENCES jobstatus(id), - FOREIGN KEY (task_id) REFERENCES task(id) - ); - - )").split(';', Qt::SkipEmptyParts); - - { - QSqlQuery query(baseDb); - for (const QString &statement : sqlStatements) { - QString trimmed = statement.trimmed(); - if (!trimmed.isEmpty() && !query.exec(trimmed)) { - std::cout << "Failed to execute SQL: " << trimmed.toStdString() - << "\nError: " << query.lastError().text().toStdString() << "\n"; - return false; - } - } - } - - return true; -} - /** * init_global(): * 1. Reads all *.yaml in /srv/lubuntu-ci/repos/ci-tools/configs/ @@ -438,7 +288,7 @@ void CiLogic::init_global() { Release _tmp_rel; ensure_git_inited(); - if (!init_database()) return; + if (!init_database("/srv/lubuntu-ci/repos/ci-tools/lubuntu_ci.db")) return; if (branches.empty() || packages.empty() || releases.empty() || packageconfs.empty()) { YAML::Node g_config; diff --git a/cpp/ci_logic.h b/cpp/ci_logic.h index b71f180..ea26a40 100644 --- a/cpp/ci_logic.h +++ b/cpp/ci_logic.h @@ -103,10 +103,6 @@ class CiLogic { std::vector branches; private: - // Initialize the database - bool init_database(const QString& connectionName = "LubuntuCIConnection", - const QString& databasePath = "/srv/lubuntu-ci/repos/ci-tools/lubuntu_ci.db"); - void debuild_package(const fs::path &packaging_dir, std::shared_ptr log); QSqlDatabase p_db; diff --git a/cpp/db_common.cpp b/cpp/db_common.cpp index 24ec71b..b6c7819 100644 --- a/cpp/db_common.cpp +++ b/cpp/db_common.cpp @@ -17,16 +17,18 @@ #include #include #include +#include #include #include -std::mutex connection_mutex_; -static std::atomic thread_id_counter{10}; +static std::mutex connection_mutex_; +static std::atomic thread_id_counter{1}; +static QString shared_database_path; QSqlDatabase get_thread_connection() { std::lock_guard lock(connection_mutex_); thread_local unsigned int thread_unique_id = thread_id_counter.fetch_add(1); - QString connection_name = QString("LubuntuCIConnection_%1").arg(thread_unique_id); + QString connection_name = QString("CIConn_%1").arg(thread_unique_id); // Check if the connection already exists for this thread if (QSqlDatabase::contains(connection_name)) { @@ -40,7 +42,7 @@ QSqlDatabase get_thread_connection() { } QSqlDatabase thread_db = QSqlDatabase::addDatabase("QSQLITE", connection_name); - thread_db.setDatabaseName("/srv/lubuntu-ci/repos/ci-tools/lubuntu_ci.db"); + 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()); @@ -48,3 +50,141 @@ QSqlDatabase get_thread_connection() { return thread_db; } + +bool init_database(const QString& database_path) { + shared_database_path = database_path; + + // Apply PRAGMAs + { + QSqlQuery pragma_query(get_thread_connection()); + pragma_query.exec("PRAGMA journal_mode = WAL;"); + pragma_query.exec("PRAGMA synchronous = NORMAL;"); + pragma_query.exec("PRAGMA foreign_keys = ON;"); + } + + // Run the schema creation (or migration) statements + QStringList sql_statements = QString(R"( + CREATE TABLE IF NOT EXISTS person ( + id INTEGER PRIMARY KEY, + username TEXT NOT NULL, + logo_url TEXT + ); + + CREATE TABLE IF NOT EXISTS person_token ( + id INTEGER PRIMARY KEY, + person_id INTEGER NOT NULL, + token TEXT NOT NULL, + expiry_date TEXT NOT NULL, + FOREIGN KEY (person_id) REFERENCES person(id) ON DELETE CASCADE + ); + + CREATE TABLE IF NOT EXISTS package ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + large INTEGER NOT NULL DEFAULT 0, + upstream_url TEXT NOT NULL, + packaging_branch TEXT NOT NULL, + packaging_url TEXT NOT NULL + ); + + CREATE TABLE IF NOT EXISTS release ( + id INTEGER PRIMARY KEY, + version INTEGER NOT NULL UNIQUE, + codename TEXT NOT NULL UNIQUE, + isDefault INTEGER NOT NULL DEFAULT 0 + ); + + CREATE TABLE IF NOT EXISTS branch ( + id INTEGER PRIMARY KEY, + name TEXT NOT NULL, + upload_target TEXT NOT NULL, + upload_target_ssh TEXT NOT NULL + ); + + INSERT INTO branch (name, upload_target, upload_target_ssh) + SELECT 'unstable', 'ppa:lubuntu-ci/unstable-ci-proposed', 'ssh-ppa:lubuntu-ci/unstable-ci-proposed' + WHERE NOT EXISTS (SELECT 1 FROM branch WHERE name='unstable'); + + CREATE TABLE IF NOT EXISTS git_commit ( + id INTEGER PRIMARY KEY, + commit_hash TEXT NOT NULL, + commit_summary TEXT NOT NULL, + commit_message TEXT NOT NULL, + commit_datetime DATETIME NOT NULL, + commit_author TEXT NOT NULL, + commit_committer TEXT NOT NULL + ); + + CREATE TABLE IF NOT EXISTS packageconf ( + id INTEGER PRIMARY KEY, + upstream_version TEXT, + ppa_revision INTEGER, + package_id INTEGER NOT NULL, + release_id INTEGER NOT NULL, + branch_id INTEGER NOT NULL, + packaging_commit_id INTEGER, + upstream_commit_id INTEGER, + FOREIGN KEY (package_id) REFERENCES package(id) ON DELETE CASCADE, + FOREIGN KEY (release_id) REFERENCES release(id) ON DELETE CASCADE, + FOREIGN KEY (branch_id) REFERENCES branch(id) ON DELETE CASCADE, + FOREIGN KEY (packaging_commit_id) REFERENCES git_commit(id) ON DELETE CASCADE, + FOREIGN KEY (upstream_commit_id) REFERENCES git_commit(id) ON DELETE CASCADE + ); + + CREATE TABLE IF NOT EXISTS jobstatus ( + id INTEGER PRIMARY KEY, + build_score INTEGER NOT NULL, + name TEXT NOT NULL UNIQUE, + display_name TEXT NOT NULL + ); + + INSERT OR IGNORE INTO jobstatus (build_score, name, display_name) + VALUES + (80, 'pull', 'Pull'), + (70, 'tarball', 'Create Tarball'), + (60, 'source_build', 'Source Build'), + (50, 'upload', 'Upload'), + (40, 'source_check', 'Source Check'), + (30, 'build_check', 'Build Check'), + (20, 'lintian', 'Lintian'), + (10, 'britney', 'Britney'); + + CREATE TABLE IF NOT EXISTS task ( + id INTEGER PRIMARY KEY, + packageconf_id INTEGER NOT NULL, + jobstatus_id INTEGER NOT NULL, + queue_time INTEGER DEFAULT 0, + start_time INTEGER DEFAULT 0, + finish_time INTEGER DEFAULT 0, + successful INTEGER, + log TEXT, + FOREIGN KEY (packageconf_id) REFERENCES packageconf(id), + FOREIGN KEY (jobstatus_id) REFERENCES jobstatus(id) + ); + + CREATE TABLE IF NOT EXISTS packageconf_jobstatus_id ( + id INTEGER PRIMARY KEY, + packageconf_id INTEGER NOT NULL, + jobstatus_id INTEGER NOT NULL, + task_id INTEGER NOT NULL, + FOREIGN KEY (packageconf_id) REFERENCES packageconf(id), + FOREIGN KEY (jobstatus_id) REFERENCES jobstatus(id), + FOREIGN KEY (task_id) REFERENCES task(id) + ); + + )").split(';', Qt::SkipEmptyParts); + + { + for (const QString &statement : sql_statements) { + QSqlQuery query(get_thread_connection()); + QString trimmed = statement.trimmed(); + if (!trimmed.isEmpty() && !query.exec(trimmed)) { + qDebug() << "Failed to execute SQL: " << trimmed + << "\nError: " << query.lastError().text(); + return false; + } + } + } + + return true; +} diff --git a/cpp/db_common.h b/cpp/db_common.h index 90f22ca..63c6141 100644 --- a/cpp/db_common.h +++ b/cpp/db_common.h @@ -19,5 +19,6 @@ #include QSqlDatabase get_thread_connection(); +bool init_database(const QString& database_path); #endif // DB_COMMON_H