diff --git a/Server/Components/Databases/database_connection.cpp b/Server/Components/Databases/database_connection.cpp index 3975d7c11..fc7bbffab 100644 --- a/Server/Components/Databases/database_connection.cpp +++ b/Server/Components/Databases/database_connection.cpp @@ -42,14 +42,55 @@ IDatabaseResultSet* DatabaseConnection::executeQuery(StringView query) IDatabaseResultSet* ret(parentDatabasesComponent->createResultSet()); if (ret) { - // TODO: Properly handle errors parentDatabasesComponent->logQuery("[log_sqlite_queries]: %.*s", PRINT_VIEW(query)); - if (sqlite3_exec(databaseConnectionHandle, query.data(), queryStepExecuted, ret, nullptr) != SQLITE_OK) + char *sqlError = nullptr; + int sqlRet = 999; + sqlRet = sqlite3_exec(databaseConnectionHandle, query.data(), queryStepExecuted, ret, &sqlError); + if(sqlRet == SQLITE_BUSY) { - parentDatabasesComponent->log(LogLevel::Error, "[log_sqlite]: Error executing query."); - parentDatabasesComponent->freeResultSet(*ret); - ret = nullptr; + int sqlRetries = 5; + while (sqlRetries-- > 0) { + parentDatabasesComponent->log(LogLevel::Error, "[log_sqlite]: Error executing query. Database is busy, retrying..."); + sqlite3_sleep(100); + sqlRet = sqlite3_exec(databaseConnectionHandle, query.data(), queryStepExecuted, ret, &sqlError); + if (sqlRet != SQLITE_OK) + { + if(sqlRet != SQLITE_BUSY) + { + if(sqlError) + { + parentDatabasesComponent->log(LogLevel::Error, "[log_sqlite]: Error executing query. %s", sqlError); + } + else + { + parentDatabasesComponent->log(LogLevel::Error, "[log_sqlite]: Error executing query."); + } + break; + } + } + else + { + break; + } + } } + else + { + if(sqlRet != SQLITE_OK) + { + if(sqlError) + { + parentDatabasesComponent->log(LogLevel::Error, "[log_sqlite]: Error executing query. %s", sqlError); + } + else + { + parentDatabasesComponent->log(LogLevel::Error, "[log_sqlite]: Error executing query."); + } + parentDatabasesComponent->freeResultSet(*ret); + ret = nullptr; + } + } + sqlite3_free(sqlError); } else { diff --git a/Server/Components/Databases/databases_component.cpp b/Server/Components/Databases/databases_component.cpp index e709409c9..680f69c1f 100644 --- a/Server/Components/Databases/databases_component.cpp +++ b/Server/Components/Databases/databases_component.cpp @@ -28,6 +28,7 @@ void DatabasesComponent::onLoad(ICore* c) core_ = c; logSQLite_ = core_->getConfig().getBool("logging.log_sqlite"); logSQLiteQueries_ = core_->getConfig().getBool("logging.log_sqlite_queries"); + SQLiteTimeout_ = core_->getConfig().getInt("sqlite_timeout"); } /// To optionally log things from connections. @@ -68,12 +69,21 @@ IDatabaseConnection* DatabasesComponent::open(StringView path, int flags) sqlite3* database_connection_handle(nullptr); if (sqlite3_open_v2(path.data(), &database_connection_handle, flags, nullptr) == SQLITE_OK) { + if(SQLiteTimeout_ && *SQLiteTimeout_) + { + sqlite3_busy_timeout(database_connection_handle, *SQLiteTimeout_); + } ret = databaseConnections.emplace(this, database_connection_handle); if (!ret) { sqlite3_close_v2(database_connection_handle); } } + else + { + this->log(LogLevel::Error, "[log_sqlite]: Cannot open database '%s'. %s", path.data(), sqlite3_errmsg(database_connection_handle)); + sqlite3_close_v2(database_connection_handle); + } return ret; } diff --git a/Server/Components/Databases/databases_component.hpp b/Server/Components/Databases/databases_component.hpp index 45ca0459a..edbfd50fe 100644 --- a/Server/Components/Databases/databases_component.hpp +++ b/Server/Components/Databases/databases_component.hpp @@ -26,6 +26,7 @@ class DatabasesComponent final : public IDatabasesComponent, public NoCopy bool* logSQLite_; bool* logSQLiteQueries_; + int* SQLiteTimeout_; ICore* core_;