Mercurial > hg > orthanc-databases
changeset 255:d663d9e44f8d
reintroduction of IDatabaseFactory into DatabaseManager
line wrap: on
line diff
--- a/Framework/Common/DatabaseManager.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/Common/DatabaseManager.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -159,30 +159,54 @@ } - DatabaseManager::DatabaseManager(IDatabase* database) : - database_(database) + DatabaseManager::DatabaseManager(IDatabaseFactory* factory) : + factory_(factory), + dialect_(Dialect_Unknown) { - if (database == NULL) + if (factory == NULL) { throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); } - - dialect_ = database->GetDialect(); } IDatabase& DatabaseManager::GetDatabase() { + assert(factory_.get() != NULL); + if (database_.get() == NULL) { - throw Orthanc::OrthancException(Orthanc::ErrorCode_DatabaseUnavailable); + database_.reset(factory_->Open()); + + if (database_.get() == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + dialect_ = database_->GetDialect(); + if (dialect_ == Dialect_Unknown) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + } + + return *database_; + } + + + Dialect DatabaseManager::GetDialect() const + { + if (database_.get() == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } else { - return *database_; + assert(dialect_ != Dialect_Unknown); + return dialect_; } } - + void DatabaseManager::StartTransaction(TransactionType type) {
--- a/Framework/Common/DatabaseManager.h Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/Common/DatabaseManager.h Wed Apr 14 17:57:08 2021 +0200 @@ -21,7 +21,7 @@ #pragma once -#include "IDatabase.h" +#include "IDatabaseFactory.h" #include "StatementLocation.h" #include <Compatibility.h> // For std::unique_ptr<> @@ -39,12 +39,17 @@ * * This class maintains a list of precompiled statements. At any * time, this class handles 0 or 1 active transaction. + * + * "DatabaseManager" takes a "IDatabaseFactory" as input, in order + * to be able to automatically re-open the database connection if + * the latter gets lost. **/ class DatabaseManager : public boost::noncopyable { private: typedef std::map<StatementLocation, IPrecompiledStatement*> CachedStatements; + std::unique_ptr<IDatabaseFactory> factory_; std::unique_ptr<IDatabase> database_; std::unique_ptr<ITransaction> transaction_; CachedStatements cachedStatements_; @@ -62,7 +67,7 @@ void ReleaseImplicitTransaction(); public: - explicit DatabaseManager(IDatabase* database); // Takes ownership + explicit DatabaseManager(IDatabaseFactory* factory); // Takes ownership ~DatabaseManager() { @@ -71,10 +76,7 @@ IDatabase& GetDatabase(); - Dialect GetDialect() const - { - return dialect_; - } + Dialect GetDialect() const; void Close();
--- a/Framework/Common/DatabasesEnumerations.h Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/Common/DatabasesEnumerations.h Wed Apr 14 17:57:08 2021 +0200 @@ -38,7 +38,8 @@ { Dialect_MySQL, Dialect_PostgreSQL, - Dialect_SQLite + Dialect_SQLite, + Dialect_Unknown }; enum TransactionType
--- a/Framework/MySQL/MySQLDatabase.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/MySQL/MySQLDatabase.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -661,31 +661,38 @@ } - MySQLDatabase* MySQLDatabase::OpenDatabaseConnection(const MySQLParameters& parameters) + class MySQLDatabase::Factory : public RetryDatabaseFactory { - class Factory : public RetryDatabaseFactory - { - private: - const MySQLParameters& parameters_; + private: + MySQLParameters parameters_; - protected: - virtual IDatabase* TryOpen() - { - std::unique_ptr<MySQLDatabase> db(new MySQLDatabase(parameters_)); - db->Open(); - db->ExecuteMultiLines("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE", false); - return db.release(); - } + protected: + virtual IDatabase* TryOpen() + { + std::unique_ptr<MySQLDatabase> db(new MySQLDatabase(parameters_)); + db->Open(); + db->ExecuteMultiLines("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE", false); + return db.release(); + } - public: - explicit Factory(const MySQLParameters& parameters) : - RetryDatabaseFactory(parameters.GetMaxConnectionRetries(), - parameters.GetConnectionRetryInterval()), - parameters_(parameters) - { - } - }; + public: + explicit Factory(const MySQLParameters& parameters) : + RetryDatabaseFactory(parameters.GetMaxConnectionRetries(), + parameters.GetConnectionRetryInterval()), + parameters_(parameters) + { + } + }; + + IDatabaseFactory* MySQLDatabase::CreateDatabaseFactory(const MySQLParameters& parameters) + { + return new Factory(parameters); + } + + + MySQLDatabase* MySQLDatabase::CreateDatabaseConnection(const MySQLParameters& parameters) + { Factory factory(parameters); return dynamic_cast<MySQLDatabase*>(factory.Open()); }
--- a/Framework/MySQL/MySQLDatabase.h Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/MySQL/MySQLDatabase.h Wed Apr 14 17:57:08 2021 +0200 @@ -25,7 +25,7 @@ # error MySQL support must be enabled to use this file #endif -#include "../Common/IDatabase.h" +#include "../Common/IDatabaseFactory.h" #include "MySQLParameters.h" #include <mysql.h> @@ -37,6 +37,8 @@ class MySQLDatabase : public IDatabase { private: + class Factory; + MySQLParameters parameters_; MYSQL *mysql_; @@ -119,6 +121,8 @@ ~TransientAdvisoryLock(); }; - static MySQLDatabase* OpenDatabaseConnection(const MySQLParameters& parameters); + static IDatabaseFactory* CreateDatabaseFactory(const MySQLParameters& parameters); + + static MySQLDatabase* CreateDatabaseConnection(const MySQLParameters& parameters); }; }
--- a/Framework/Plugins/DatabaseBackendAdapterV3.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/Plugins/DatabaseBackendAdapterV3.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -154,14 +154,17 @@ assert(backend_.get() != NULL); { - std::unique_ptr<DatabaseManager> manager(new DatabaseManager(backend_->OpenDatabaseConnection())); + std::unique_ptr<DatabaseManager> manager(new DatabaseManager(backend_->CreateDatabaseFactory())); + manager->GetDatabase(); // Make sure to open the database connection + backend_->ConfigureDatabase(*manager); connections_.push_back(manager.release()); } for (size_t i = 1; i < countConnections_; i++) { - connections_.push_back(new DatabaseManager(backend_->OpenDatabaseConnection())); + connections_.push_back(new DatabaseManager(backend_->CreateDatabaseFactory())); + connections_.back()->GetDatabase(); // Make sure to open the database connection } for (std::list<DatabaseManager*>::iterator
--- a/Framework/Plugins/IDatabaseBackend.h Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/Plugins/IDatabaseBackend.h Wed Apr 14 17:57:08 2021 +0200 @@ -39,7 +39,7 @@ virtual OrthancPluginContext* GetContext() = 0; - virtual IDatabase* OpenDatabaseConnection() = 0; + virtual IDatabaseFactory* CreateDatabaseFactory() = 0; // This function is invoked once, even if multiple connections are open virtual void ConfigureDatabase(DatabaseManager& database) = 0;
--- a/Framework/Plugins/IndexBackend.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/Plugins/IndexBackend.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -2527,7 +2527,7 @@ DatabaseManager* IndexBackend::CreateSingleDatabaseManager(IDatabaseBackend& backend) { - std::unique_ptr<DatabaseManager> manager(new DatabaseManager(backend.OpenDatabaseConnection())); + std::unique_ptr<DatabaseManager> manager(new DatabaseManager(backend.CreateDatabaseFactory())); backend.ConfigureDatabase(*manager); return manager.release(); }
--- a/Framework/Plugins/StorageBackend.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/Plugins/StorageBackend.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -56,36 +56,11 @@ namespace OrthancDatabases { - void StorageBackend::SetDatabase(IDatabase* database) + StorageBackend::StorageBackend(IDatabaseFactory* factory) : + manager_(factory) { - if (database == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); - } - else if (manager_.get() != NULL) - { - delete database; - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - manager_.reset(new DatabaseManager(database)); - } } - DatabaseManager& StorageBackend::GetManager() - { - if (manager_.get() == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - else - { - return *manager_; - } - } - - void StorageBackend::AccessorBase::Create(const std::string& uuid, const void* content, size_t size,
--- a/Framework/Plugins/StorageBackend.h Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/Plugins/StorageBackend.h Wed Apr 14 17:57:08 2021 +0200 @@ -74,11 +74,9 @@ private: class StringVisitor; - boost::mutex mutex_; - std::unique_ptr<DatabaseManager> manager_; + boost::mutex mutex_; + DatabaseManager manager_; - DatabaseManager& GetManager(); - protected: class AccessorBase : public IAccessor { @@ -89,7 +87,7 @@ public: explicit AccessorBase(StorageBackend& backend) : lock_(backend.mutex_), - manager_(backend.GetManager()) + manager_(backend.manager_) { } @@ -117,11 +115,11 @@ OrthancPluginContentType type) ORTHANC_OVERRIDE; }; - void SetDatabase(IDatabase* database); // Takes ownership - virtual bool HasReadRange() const = 0; public: + StorageBackend(IDatabaseFactory* factory); // Takes ownership + virtual ~StorageBackend() { }
--- a/Framework/PostgreSQL/PostgreSQLDatabase.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/PostgreSQL/PostgreSQLDatabase.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -325,30 +325,37 @@ } - PostgreSQLDatabase* PostgreSQLDatabase::OpenDatabaseConnection(const PostgreSQLParameters& parameters) + class PostgreSQLDatabase::Factory : public RetryDatabaseFactory { - class Factory : public RetryDatabaseFactory + private: + PostgreSQLParameters parameters_; + + protected: + virtual IDatabase* TryOpen() { - private: - const PostgreSQLParameters& parameters_; + std::unique_ptr<PostgreSQLDatabase> db(new PostgreSQLDatabase(parameters_)); + db->Open(); + return db.release(); + } + + public: + explicit Factory(const PostgreSQLParameters& parameters) : + RetryDatabaseFactory(parameters.GetMaxConnectionRetries(), + parameters.GetConnectionRetryInterval()), + parameters_(parameters) + { + } + }; - protected: - virtual IDatabase* TryOpen() - { - std::unique_ptr<PostgreSQLDatabase> db(new PostgreSQLDatabase(parameters_)); - db->Open(); - return db.release(); - } - - public: - explicit Factory(const PostgreSQLParameters& parameters) : - RetryDatabaseFactory(parameters.GetMaxConnectionRetries(), - parameters.GetConnectionRetryInterval()), - parameters_(parameters) - { - } - }; + IDatabaseFactory* PostgreSQLDatabase::CreateDatabaseFactory(const PostgreSQLParameters& parameters) + { + return new Factory(parameters); + } + + + PostgreSQLDatabase* PostgreSQLDatabase::CreateDatabaseConnection(const PostgreSQLParameters& parameters) + { Factory factory(parameters); return dynamic_cast<PostgreSQLDatabase*>(factory.Open()); }
--- a/Framework/PostgreSQL/PostgreSQLDatabase.h Wed Apr 14 15:33:57 2021 +0200 +++ b/Framework/PostgreSQL/PostgreSQLDatabase.h Wed Apr 14 17:57:08 2021 +0200 @@ -26,7 +26,7 @@ #endif #include "PostgreSQLParameters.h" -#include "../Common/IDatabase.h" +#include "../Common/IDatabaseFactory.h" namespace OrthancDatabases { @@ -36,6 +36,8 @@ friend class PostgreSQLStatement; friend class PostgreSQLLargeObject; + class Factory; + PostgreSQLParameters parameters_; void* pg_; /* Object of type "PGconn*" */ @@ -90,6 +92,8 @@ ~TransientAdvisoryLock(); }; - static PostgreSQLDatabase* OpenDatabaseConnection(const PostgreSQLParameters& parameters); + static IDatabaseFactory* CreateDatabaseFactory(const PostgreSQLParameters& parameters); + + static PostgreSQLDatabase* CreateDatabaseConnection(const PostgreSQLParameters& parameters); }; }
--- a/MySQL/Plugins/MySQLIndex.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/MySQL/Plugins/MySQLIndex.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -45,9 +45,9 @@ } - IDatabase* MySQLIndex::OpenDatabaseConnection() + IDatabaseFactory* MySQLIndex::CreateDatabaseFactory() { - return MySQLDatabase::OpenDatabaseConnection(parameters_); + return MySQLDatabase::CreateDatabaseFactory(parameters_); }
--- a/MySQL/Plugins/MySQLIndex.h Wed Apr 14 15:33:57 2021 +0200 +++ b/MySQL/Plugins/MySQLIndex.h Wed Apr 14 17:57:08 2021 +0200 @@ -41,7 +41,7 @@ clearAll_ = clear; } - virtual IDatabase* OpenDatabaseConnection() ORTHANC_OVERRIDE; + virtual IDatabaseFactory* CreateDatabaseFactory() ORTHANC_OVERRIDE; virtual void ConfigureDatabase(DatabaseManager& database) ORTHANC_OVERRIDE;
--- a/MySQL/Plugins/MySQLStorageArea.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/MySQL/Plugins/MySQLStorageArea.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -87,17 +87,14 @@ MySQLStorageArea::MySQLStorageArea(const MySQLParameters& parameters, - bool clearAll) + bool clearAll) : + StorageBackend(MySQLDatabase::CreateDatabaseFactory(parameters)) { - std::unique_ptr<MySQLDatabase> database(MySQLDatabase::OpenDatabaseConnection(parameters)); - - if (database.get() == NULL) { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + AccessorBase accessor(*this); + MySQLDatabase& database = dynamic_cast<MySQLDatabase&>(accessor.GetManager().GetDatabase()); + ConfigureDatabase(database, parameters, clearAll); } - - ConfigureDatabase(*database, parameters, clearAll); - SetDatabase(database.release()); }
--- a/MySQL/UnitTests/UnitTestsMain.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/MySQL/UnitTests/UnitTestsMain.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -157,7 +157,7 @@ TEST(MySQL, StorageArea) { std::unique_ptr<OrthancDatabases::MySQLDatabase> database( - OrthancDatabases::MySQLDatabase::OpenDatabaseConnection(globalParameters_)); + OrthancDatabases::MySQLDatabase::CreateDatabaseConnection(globalParameters_)); OrthancDatabases::MySQLStorageArea storageArea(globalParameters_, true /* clear database */); @@ -214,7 +214,7 @@ TEST(MySQL, StorageReadRange) { std::unique_ptr<OrthancDatabases::MySQLDatabase> database( - OrthancDatabases::MySQLDatabase::OpenDatabaseConnection(globalParameters_)); + OrthancDatabases::MySQLDatabase::CreateDatabaseConnection(globalParameters_)); OrthancDatabases::MySQLStorageArea storageArea(globalParameters_, true /* clear database */);
--- a/PostgreSQL/Plugins/PostgreSQLIndex.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/PostgreSQL/Plugins/PostgreSQLIndex.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -54,9 +54,9 @@ } - IDatabase* PostgreSQLIndex::OpenDatabaseConnection() + IDatabaseFactory* PostgreSQLIndex::CreateDatabaseFactory() { - return PostgreSQLDatabase::OpenDatabaseConnection(parameters_); + return PostgreSQLDatabase::CreateDatabaseFactory(parameters_); }
--- a/PostgreSQL/Plugins/PostgreSQLIndex.h Wed Apr 14 15:33:57 2021 +0200 +++ b/PostgreSQL/Plugins/PostgreSQLIndex.h Wed Apr 14 17:57:08 2021 +0200 @@ -41,7 +41,7 @@ clearAll_ = clear; } - virtual IDatabase* OpenDatabaseConnection() ORTHANC_OVERRIDE; + virtual IDatabaseFactory* CreateDatabaseFactory() ORTHANC_OVERRIDE; virtual void ConfigureDatabase(DatabaseManager& manager) ORTHANC_OVERRIDE;
--- a/PostgreSQL/Plugins/PostgreSQLStorageArea.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/PostgreSQL/Plugins/PostgreSQLStorageArea.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -70,16 +70,13 @@ PostgreSQLStorageArea::PostgreSQLStorageArea(const PostgreSQLParameters& parameters, - bool clearAll) + bool clearAll) : + StorageBackend(PostgreSQLDatabase::CreateDatabaseFactory(parameters)) { - std::unique_ptr<PostgreSQLDatabase> database(PostgreSQLDatabase::OpenDatabaseConnection(parameters)); - - if (database.get() == NULL) { - throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + AccessorBase accessor(*this); + PostgreSQLDatabase& database = dynamic_cast<PostgreSQLDatabase&>(accessor.GetManager().GetDatabase()); + ConfigureDatabase(database, parameters, clearAll); } - - ConfigureDatabase(*database, parameters, clearAll); - SetDatabase(database.release()); } }
--- a/PostgreSQL/UnitTests/PostgreSQLTests.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/PostgreSQL/UnitTests/PostgreSQLTests.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -358,7 +358,7 @@ TEST(PostgreSQL, StorageArea) { - std::unique_ptr<PostgreSQLDatabase> database(PostgreSQLDatabase::OpenDatabaseConnection(globalParameters_)); + std::unique_ptr<PostgreSQLDatabase> database(PostgreSQLDatabase::CreateDatabaseConnection(globalParameters_)); PostgreSQLStorageArea storageArea(globalParameters_, true /* clear database */); @@ -413,7 +413,7 @@ TEST(PostgreSQL, StorageReadRange) { std::unique_ptr<OrthancDatabases::PostgreSQLDatabase> database( - OrthancDatabases::PostgreSQLDatabase::OpenDatabaseConnection(globalParameters_)); + OrthancDatabases::PostgreSQLDatabase::CreateDatabaseConnection(globalParameters_)); OrthancDatabases::PostgreSQLStorageArea storageArea(globalParameters_, true /* clear database */);
--- a/SQLite/Plugins/SQLiteIndex.cpp Wed Apr 14 15:33:57 2021 +0200 +++ b/SQLite/Plugins/SQLiteIndex.cpp Wed Apr 14 17:57:08 2021 +0200 @@ -34,33 +34,53 @@ namespace OrthancDatabases { - IDatabase* SQLiteIndex::OpenDatabaseConnection() + IDatabaseFactory* SQLiteIndex::CreateDatabaseFactory() { - std::unique_ptr<SQLiteDatabase> db(new SQLiteDatabase); - - if (path_.empty()) + class Factory : public IDatabaseFactory { - db->OpenInMemory(); - } - else - { - db->Open(path_); - } + private: + std::string path_; + bool fast_; + + public: + Factory(const std::string& path, + bool fast) : + path_(path), + fast_(fast) + { + } + + virtual IDatabase* Open() ORTHANC_OVERRIDE + { + std::unique_ptr<SQLiteDatabase> db(new SQLiteDatabase); - db->Execute("PRAGMA ENCODING=\"UTF-8\";"); + if (path_.empty()) + { + db->OpenInMemory(); + } + else + { + db->Open(path_); + } + + db->Execute("PRAGMA ENCODING=\"UTF-8\";"); - if (fast_) - { - // Performance tuning of SQLite with PRAGMAs - // http://www.sqlite.org/pragma.html - db->Execute("PRAGMA SYNCHRONOUS=NORMAL;"); - db->Execute("PRAGMA JOURNAL_MODE=WAL;"); - db->Execute("PRAGMA LOCKING_MODE=EXCLUSIVE;"); - db->Execute("PRAGMA WAL_AUTOCHECKPOINT=1000;"); - //db->Execute("PRAGMA TEMP_STORE=memory"); - } + if (fast_) + { + // Performance tuning of SQLite with PRAGMAs + // http://www.sqlite.org/pragma.html + db->Execute("PRAGMA SYNCHRONOUS=NORMAL;"); + db->Execute("PRAGMA JOURNAL_MODE=WAL;"); + db->Execute("PRAGMA LOCKING_MODE=EXCLUSIVE;"); + db->Execute("PRAGMA WAL_AUTOCHECKPOINT=1000;"); + //db->Execute("PRAGMA TEMP_STORE=memory"); + } - return db.release(); + return db.release(); + } + }; + + return new Factory(path_, fast_); }
--- a/SQLite/Plugins/SQLiteIndex.h Wed Apr 14 15:33:57 2021 +0200 +++ b/SQLite/Plugins/SQLiteIndex.h Wed Apr 14 17:57:08 2021 +0200 @@ -42,7 +42,7 @@ fast_ = fast; } - virtual IDatabase* OpenDatabaseConnection() ORTHANC_OVERRIDE; + virtual IDatabaseFactory* CreateDatabaseFactory() ORTHANC_OVERRIDE; virtual void ConfigureDatabase(DatabaseManager& manager) ORTHANC_OVERRIDE;