From be25766c5ceb8dc807e68b48aa80de51519b0402 Mon Sep 17 00:00:00 2001 From: Alexey Karandashev Date: Mon, 15 May 2023 16:08:50 +0200 Subject: [PATCH] This refactoring job is related to https://github.com/qgis/QGIS-Enhancement-Proposals/issues/272 and the original pull request for the AWS Redshift driver https://github.com/qgis/QGIS/pull/53018. - Move qgsConnectionPool_[connectionCreate|connectionDestroy|invalidateConnection|connectionIsValid|connectionToName] into their appropriate abstract classes and declare them as pure virual. - Implement the destructor and the functions above for all providers. - Refactor QgsPostgresConnPool[Group] to QgsSQLConnPool[Group], in order to reuse the template for future SQL based providers (AWS Redshift). --- src/core/providers/ogr/qgsogrconnpool.cpp | 43 ++++++ src/core/providers/ogr/qgsogrconnpool.h | 76 ++++------- src/core/providers/qgssqlconnpool.h | 124 ++++++++++++++++++ src/core/qgsconnectionpool.h | 100 ++++++++------ src/providers/hana/qgshanaconnectionpool.cpp | 17 +-- src/providers/hana/qgshanaconnectionpool.h | 67 ++++++---- src/providers/oracle/qgsoracleconnpool.h | 52 ++++---- src/providers/postgres/CMakeLists.txt | 3 +- .../postgres/qgspostgresconnpool.cpp | 44 ------- src/providers/postgres/qgspostgresconnpool.h | 57 +------- .../spatialite/qgsspatialiteconnpool.cpp | 29 ++++ .../spatialite/qgsspatialiteconnpool.h | 34 +---- 12 files changed, 361 insertions(+), 285 deletions(-) create mode 100644 src/core/providers/qgssqlconnpool.h delete mode 100644 src/providers/postgres/qgspostgresconnpool.cpp diff --git a/src/core/providers/ogr/qgsogrconnpool.cpp b/src/core/providers/ogr/qgsogrconnpool.cpp index 98c2d116237d..03c71dbb1a01 100644 --- a/src/core/providers/ogr/qgsogrconnpool.cpp +++ b/src/core/providers/ogr/qgsogrconnpool.cpp @@ -18,6 +18,43 @@ #include "qgslogger.h" + +void QgsOgrConnPoolGroup::connectionCreate( const QString &connectionInfo, QgsOgrConn *&connection ) +{ + connection = new QgsOgrConn; + + const QVariantMap parts = QgsOgrProviderMetadata().decodeUri( connectionInfo ); + const QString fullPath = parts.value( QStringLiteral( "vsiPrefix" ) ).toString() + + parts.value( QStringLiteral( "path" ) ).toString() + + parts.value( QStringLiteral( "vsiSuffix" ) ).toString(); + const QStringList openOptions = parts.value( QStringLiteral( "openOptions" ) ).toStringList(); + char **papszOpenOptions = nullptr; + for ( const QString &option : std::as_const( openOptions ) ) + { + papszOpenOptions = CSLAddString( papszOpenOptions, + option.toUtf8().constData() ); + } + connection->ds = QgsOgrProviderUtils::GDALOpenWrapper( fullPath.toUtf8().constData(), false, papszOpenOptions, nullptr ); + CSLDestroy( papszOpenOptions ); + connection->path = connectionInfo; + connection->valid = true; +} + +void QgsOgrConnPoolGroup::connectionDestroy( QgsOgrConn *connection ) +{ + destroyOgrConn( connection ); +} + +void QgsOgrConnPoolGroup::invalidateConnection( QgsOgrConn *connection ) +{ + connection->valid = false; +} + +bool QgsOgrConnPoolGroup::connectionIsValid( QgsOgrConn *connection ) +{ + return connection->valid; +} + QgsOgrConnPool *QgsOgrConnPool::sInstance = nullptr; // static public @@ -44,4 +81,10 @@ QgsOgrConnPool::~QgsOgrConnPool() QgsDebugCall; } +QString QgsOgrConnPool::connectionToName( QgsOgrConn *connection ) +{ + return connection->path; +} + + ///@endcond diff --git a/src/core/providers/ogr/qgsogrconnpool.h b/src/core/providers/ogr/qgsogrconnpool.h index aa0a6f57ed82..3458606f1b68 100644 --- a/src/core/providers/ogr/qgsogrconnpool.h +++ b/src/core/providers/ogr/qgsogrconnpool.h @@ -33,48 +33,6 @@ struct QgsOgrConn bool valid; }; -inline QString qgsConnectionPool_ConnectionToName( QgsOgrConn *c ) -{ - return c->path; -} - -inline void qgsConnectionPool_ConnectionCreate( const QString &connInfo, QgsOgrConn *&c ) -{ - c = new QgsOgrConn; - - const QVariantMap parts = QgsOgrProviderMetadata().decodeUri( connInfo ); - const QString fullPath = parts.value( QStringLiteral( "vsiPrefix" ) ).toString() - + parts.value( QStringLiteral( "path" ) ).toString() - + parts.value( QStringLiteral( "vsiSuffix" ) ).toString(); - const QStringList openOptions = parts.value( QStringLiteral( "openOptions" ) ).toStringList(); - char **papszOpenOptions = nullptr; - for ( const QString &option : openOptions ) - { - papszOpenOptions = CSLAddString( papszOpenOptions, - option.toUtf8().constData() ); - } - c->ds = QgsOgrProviderUtils::GDALOpenWrapper( fullPath.toUtf8().constData(), false, papszOpenOptions, nullptr ); - CSLDestroy( papszOpenOptions ); - c->path = connInfo; - c->valid = true; -} - -inline void qgsConnectionPool_ConnectionDestroy( QgsOgrConn *c ) -{ - QgsOgrProviderUtils::GDALCloseWrapper( c->ds ); - delete c; -} - -inline void qgsConnectionPool_InvalidateConnection( QgsOgrConn *c ) -{ - c->valid = false; -} - -inline bool qgsConnectionPool_ConnectionIsValid( QgsOgrConn *c ) -{ - return c->valid; -} - class QgsOgrConnPoolGroup : public QObject, public QgsConnectionPoolGroup { Q_OBJECT @@ -92,6 +50,18 @@ class QgsOgrConnPoolGroup : public QObject, public QgsConnectionPoolGroupds ); + delete connection; + } + protected slots: void handleConnectionExpired() { onConnectionExpired(); } void startExpirationTimer() { expirationTimer->start(); } @@ -113,7 +89,7 @@ class QgsOgrConnPoolGroup : public QObject, public QgsConnectionPoolGroup { public: - + QString connectionToName( QgsOgrConn *connection ) override; // NOTE: first call to this function initializes the // singleton. // WARNING: concurrent call from multiple threads may result @@ -140,31 +116,31 @@ class QgsOgrConnPool : public QgsConnectionPoolref(); mMutex.unlock(); } /** * \brief Decrease the reference count on the connection pool for the specified connection. - * \param connInfo The connection string. + * \param connectionInfo The connection string. */ - void unref( const QString &connInfo ) + void unref( const QString &connectionInfo ) { mMutex.lock(); - T_Groups::iterator it = mGroups.find( connInfo ); + T_Groups::iterator it = mGroups.find( connectionInfo ); if ( it == mGroups.end() ) { mMutex.unlock(); diff --git a/src/core/providers/qgssqlconnpool.h b/src/core/providers/qgssqlconnpool.h new file mode 100644 index 000000000000..8ff31788ca3c --- /dev/null +++ b/src/core/providers/qgssqlconnpool.h @@ -0,0 +1,124 @@ +/*************************************************************************** + qgssqlconnpool.h + --------------------- + begin : January 2014 + copyright : (C) 2014 by Martin Dobias + email : wonder dot sk at gmail dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef QGSSQLCONNPOOL_H +#define QGSSQLCONNPOOL_H +#define SIP_NO_FILE + +#include "qgsconnectionpool.h" +#include "qgslogger.h" + +/** + * \ingroup core + * \brief Template class for SQL based provider connection pool group. + * \note not available in Python bindings. + * \since QGIS 3.32 + */ +template +class QgsSQLConnPoolGroup : public QgsConnectionPoolGroup +{ + public: + + /** + * The descendants inherit from QObject and pass a self reference. + */ + explicit QgsSQLConnPoolGroup( const QString &name, QObject *qobject ) : + QgsConnectionPoolGroup( name ) + { + QgsConnectionPoolGroup::initTimer( qobject ); + } + + using typename QgsConnectionPoolGroup::Item; + using QgsConnectionPoolGroup::connections; + ~QgsSQLConnPoolGroup() override + { + for ( const Item &item : std::as_const( connections ) ) + { + connectionDestroy( item.connection ); + } + } + void connectionCreate( const QString &connectionInfo, T *&connection ) override + { + connection = T::connectDb( connectionInfo, true, false ); + } + + void connectionDestroy( T *connection ) override + { + connection->unref(); // will delete itself + } + + void invalidateConnection( T * ) override {} + + bool connectionIsValid( T * ) override + { + return true; + } +}; + +/** + * \ingroup core + * \brief Template class for SQL based provider connection pool. + * \note not available in Python bindings. + * \since QGIS 3.32 + */ +template +class QgsSQLConnPool : public QgsConnectionPool +{ + public: + + /** + * \returns the instance singleton \a sInstance. + */ + static QgsSQLConnPool *instance() + { + if ( !sInstance ) + sInstance = new QgsSQLConnPool(); + return sInstance; + } + + /** + * Reset the global instance of the connection pool. + */ + static void cleanupInstance() + { + delete sInstance; + sInstance = nullptr; + } + + QString connectionToName( T *connection ) override + { + return connection->connInfo(); + } + + protected: + + /** + * Constructor/Destructor implementation for the sole purpose of debugging. + */ + QgsSQLConnPool() : QgsConnectionPool() + { + QgsDebugCall; + } + + ~QgsSQLConnPool() override + { + QgsDebugCall; + } + private: + static inline QgsSQLConnPool *sInstance = nullptr; +}; + + +#endif // QGSSQLCONNPOOL_H diff --git a/src/core/qgsconnectionpool.h b/src/core/qgsconnectionpool.h index 3ffc1e34203e..61658b91bd06 100644 --- a/src/core/qgsconnectionpool.h +++ b/src/core/qgsconnectionpool.h @@ -40,14 +40,6 @@ * \ingroup core * \brief Template that stores data related to a connection to a single server or datasource. * - * It is assumed that following functions exist: - * - * - void qgsConnectionPool_ConnectionCreate(QString name, T& c) ... create a new connection - * - void qgsConnectionPool_ConnectionDestroy(T c) ... destroy the connection - * - QString qgsConnectionPool_ConnectionToName(T c) ... lookup connection's name (path) - * - void qgsConnectionPool_InvalidateConnection(T c) ... flag a connection as invalid - * - bool qgsConnectionPool_ConnectionIsValid(T c) ... return whether a connection is valid - * * Because of issues with templates and QObject's signals and slots, this class only provides helper functions for QObject-related * functionality - the place which uses the template is resonsible for: * @@ -66,7 +58,7 @@ class QgsConnectionPoolGroup struct Item { - T c; + T connection; QTime lastUsedTime; }; @@ -76,13 +68,28 @@ class QgsConnectionPoolGroup { } - ~QgsConnectionPoolGroup() - { - for ( const Item &item : std::as_const( conns ) ) - { - qgsConnectionPool_ConnectionDestroy( item.c ); - } - } + virtual ~QgsConnectionPoolGroup() = 0; + + /** + * Classes that implement this template must implement their own connection functions. + * Create a connection \a c based on connection information \a connInfo. + */ + virtual void connectionCreate( const QString &connInfo, T &c ) = 0; + + /** + * Destroy the connection \a c. + */ + virtual void connectionDestroy( T c ) = 0; + + /** + * Invalidate the connection \a c. + */ + virtual void invalidateConnection( T c ) = 0; + + /** + * \returns true if the connection \a c is valid. + */ + virtual bool connectionIsValid( T c ) = 0; //! QgsConnectionPoolGroup cannot be copied QgsConnectionPoolGroup( const QgsConnectionPoolGroup &other ) = delete; @@ -119,31 +126,31 @@ class QgsConnectionPoolGroup { QMutexLocker locker( &connMutex ); - if ( !conns.isEmpty() ) + if ( !connections.isEmpty() ) { - Item i = conns.pop(); - if ( !qgsConnectionPool_ConnectionIsValid( i.c ) ) + Item i = connections.pop(); + if ( !connectionIsValid( i.connection ) ) { - qgsConnectionPool_ConnectionDestroy( i.c ); - qgsConnectionPool_ConnectionCreate( connInfo, i.c ); + connectionDestroy( i.connection ); + connectionCreate( connInfo, i.connection ); } // no need to run if nothing can expire - if ( conns.isEmpty() ) + if ( connections.isEmpty() ) { // will call the slot directly or queue the call (if the object lives in a different thread) QMetaObject::invokeMethod( expirationTimer->parent(), "stopExpirationTimer" ); } - acquiredConns.append( i.c ); + acquiredConns.append( i.connection ); - return i.c; + return i.connection; } } T c; - qgsConnectionPool_ConnectionCreate( connInfo, c ); + connectionCreate( connInfo, c ); if ( !c ) { // we didn't get connection for some reason, so release the lock @@ -157,20 +164,20 @@ class QgsConnectionPoolGroup return c; } - void release( T conn ) + void release( T connection ) { connMutex.lock(); - acquiredConns.removeAll( conn ); - if ( !qgsConnectionPool_ConnectionIsValid( conn ) ) + acquiredConns.removeAll( connection ); + if ( !connectionIsValid( connection ) ) { - qgsConnectionPool_ConnectionDestroy( conn ); + connectionDestroy( connection ); } else { Item i; - i.c = conn; + i.connection = connection; i.lastUsedTime = QTime::currentTime(); - conns.push( i ); + connections.push( i ); if ( !expirationTimer->isActive() ) { @@ -187,13 +194,13 @@ class QgsConnectionPoolGroup void invalidateConnections() { connMutex.lock(); - for ( const Item &i : std::as_const( conns ) ) + for ( const Item &i : std::as_const( connections ) ) { - qgsConnectionPool_ConnectionDestroy( i.c ); + connectionDestroy( i.connection ); } - conns.clear(); + connections.clear(); for ( T c : std::as_const( acquiredConns ) ) - qgsConnectionPool_InvalidateConnection( c ); + invalidateConnection( c ); connMutex.unlock(); } @@ -218,9 +225,9 @@ class QgsConnectionPoolGroup // what connections have expired? QList toDelete; - for ( int i = 0; i < conns.count(); ++i ) + for ( int i = 0; i < connections.count(); ++i ) { - if ( conns.at( i ).lastUsedTime.secsTo( now ) >= CONN_POOL_EXPIRATION_TIME ) + if ( connections.at( i ).lastUsedTime.secsTo( now ) >= CONN_POOL_EXPIRATION_TIME ) toDelete.append( i ); } @@ -228,11 +235,11 @@ class QgsConnectionPoolGroup for ( int j = toDelete.count() - 1; j >= 0; --j ) { int index = toDelete[j]; - qgsConnectionPool_ConnectionDestroy( conns[index].c ); - conns.remove( index ); + connectionDestroy( connections[index].connection ); + connections.remove( index ); } - if ( conns.isEmpty() ) + if ( connections.isEmpty() ) expirationTimer->stop(); connMutex.unlock(); @@ -241,7 +248,7 @@ class QgsConnectionPoolGroup protected: QString connInfo; - QStack conns; + QStack connections; QList acquiredConns; QMutex connMutex; QSemaphore sem; @@ -249,6 +256,9 @@ class QgsConnectionPoolGroup }; +template +QgsConnectionPoolGroup::~QgsConnectionPoolGroup() {} + /** * \ingroup core @@ -285,6 +295,11 @@ class QgsConnectionPool mMutex.unlock(); } + /** + * \returns the name of the connection \a c. + */ + virtual QString connectionToName( T c ) = 0; + /** * Try to acquire a connection for a maximum of \a timeout milliseconds. * If \a timeout is a negative value the calling thread will be blocked @@ -331,7 +346,7 @@ class QgsConnectionPool void releaseConnection( T conn ) { mMutex.lock(); - typename T_Groups::iterator it = mGroups.find( qgsConnectionPool_ConnectionToName( conn ) ); + typename T_Groups::iterator it = mGroups.find( connectionToName( conn ) ); Q_ASSERT( it != mGroups.end() ); T_Group *group = *it; mMutex.unlock(); @@ -360,5 +375,4 @@ class QgsConnectionPool QMutex mMutex; }; - #endif // QGSCONNECTIONPOOL_H diff --git a/src/providers/hana/qgshanaconnectionpool.cpp b/src/providers/hana/qgshanaconnectionpool.cpp index 1f52751e8cae..052fcf263879 100644 --- a/src/providers/hana/qgshanaconnectionpool.cpp +++ b/src/providers/hana/qgshanaconnectionpool.cpp @@ -20,34 +20,29 @@ #include "qgshanautils.h" #include "qgslogger.h" -QgsHanaConnectionPoolGroup::QgsHanaConnectionPoolGroup( const QString &name ) - : QgsConnectionPoolGroup( name ) -{ - initTimer( this ); -} QBasicMutex QgsHanaConnectionPool::sMutex; std::shared_ptr QgsHanaConnectionPool::sInstance; -QgsHanaConnection *QgsHanaConnectionPool::getConnection( const QString &connInfo ) +QgsHanaConnection *QgsHanaConnectionPool::getConnection( const QString &connectionInfo ) { - std::shared_ptr instance; + std::shared_ptr instance; { QMutexLocker lock( &sMutex ); if ( !sInstance ) sInstance = std::shared_ptr( new QgsHanaConnectionPool() ); instance = sInstance; } - return instance->acquireConnection( connInfo ); + return instance->acquireConnection( connectionInfo ); } -void QgsHanaConnectionPool::returnConnection( QgsHanaConnection *conn ) +void QgsHanaConnectionPool::returnConnection( QgsHanaConnection *connection ) { QMutexLocker lock( &sMutex ); if ( sInstance ) - sInstance->releaseConnection( conn ); + sInstance->releaseConnection( connection ); else - qgsConnectionPool_ConnectionDestroy( conn ); + delete connection; } void QgsHanaConnectionPool::cleanupInstance() diff --git a/src/providers/hana/qgshanaconnectionpool.h b/src/providers/hana/qgshanaconnectionpool.h index 4032d4925140..20c7efedfb2c 100644 --- a/src/providers/hana/qgshanaconnectionpool.h +++ b/src/providers/hana/qgshanaconnectionpool.h @@ -23,39 +23,43 @@ #include #include -inline QString qgsConnectionPool_ConnectionToName( QgsHanaConnection *c ) -{ - return c->connInfo(); -} - -inline void qgsConnectionPool_ConnectionCreate( const QgsDataSourceUri &uri, QgsHanaConnection *&c ) -{ - c = QgsHanaConnection::createConnection( uri ); -} - -inline void qgsConnectionPool_ConnectionDestroy( QgsHanaConnection *c ) -{ - delete c; -} - -inline void qgsConnectionPool_InvalidateConnection( QgsHanaConnection *c ) -{ - Q_UNUSED( c ); -} - -inline bool qgsConnectionPool_ConnectionIsValid( QgsHanaConnection *c ) -{ - Q_UNUSED( c ); - return true; -} - class QgsHanaConnectionPoolGroup : public QObject, public QgsConnectionPoolGroup { Q_OBJECT public: - explicit QgsHanaConnectionPoolGroup( const QString &name ); + explicit QgsHanaConnectionPoolGroup( const QString &name ) + : QgsConnectionPoolGroup( name ) + { + initTimer( this ); + } + + ~QgsHanaConnectionPoolGroup() override + { + for ( const Item &item : std::as_const( connections ) ) + { + delete item.connection; + } + } + + void connectionCreate( const QString &uri, QgsHanaConnection *&c ) override + { + c = QgsHanaConnection::createConnection( uri ); + } + + void connectionDestroy( QgsHanaConnection *connection ) override + { + delete connection; + } + + void invalidateConnection( QgsHanaConnection * ) override {} + + + bool connectionIsValid( QgsHanaConnection * ) override + { + return true; + } protected slots: void handleConnectionExpired() { onConnectionExpired(); } @@ -70,10 +74,15 @@ class QgsHanaConnectionPool : public QgsConnectionPool { public: - static QgsHanaConnection *getConnection( const QString &connInfo ); - static void returnConnection( QgsHanaConnection *conn ); + static QgsHanaConnection *getConnection( const QString &connectionInfo ); + static void returnConnection( QgsHanaConnection *connection ); static void cleanupInstance(); + QString connectionToName( QgsHanaConnection *connection ) override + { + return connection->connInfo(); + } + protected: Q_DISABLE_COPY( QgsHanaConnectionPool ) diff --git a/src/providers/oracle/qgsoracleconnpool.h b/src/providers/oracle/qgsoracleconnpool.h index 739f53a31215..b69a2e4388d5 100644 --- a/src/providers/oracle/qgsoracleconnpool.h +++ b/src/providers/oracle/qgsoracleconnpool.h @@ -20,39 +20,32 @@ #include "qgsoracleconn.h" -inline QString qgsConnectionPool_ConnectionToName( QgsOracleConn *c ) -{ - return c->connInfo(); -} - -inline void qgsConnectionPool_ConnectionCreate( const QgsDataSourceUri &uri, QgsOracleConn *&c ) -{ - c = QgsOracleConn::connectDb( uri, false ); -} - -inline void qgsConnectionPool_ConnectionDestroy( QgsOracleConn *c ) -{ - c->disconnect(); // will delete itself -} - -inline void qgsConnectionPool_InvalidateConnection( QgsOracleConn *c ) -{ - Q_UNUSED( c ) -} - -inline bool qgsConnectionPool_ConnectionIsValid( QgsOracleConn *c ) -{ - Q_UNUSED( c ) - return true; -} - - class QgsOracleConnPoolGroup : public QObject, public QgsConnectionPoolGroup { Q_OBJECT public: explicit QgsOracleConnPoolGroup( QString name ) : QgsConnectionPoolGroup( name ) { initTimer( this ); } + ~QgsOracleConnPoolGroup() override + { + for ( const Item &item : std::as_const( connections ) ) + { + item.connection->disconnect(); // will delete itself + } + } + + void connectionCreate( const QString &connectionInfo, QgsOracleConn *&connection ) override + { + connection = QgsOracleConn::connectDb( connectionInfo, false ); + } + + void connectionDestroy( QgsOracleConn *connection ) override + { + connection->disconnect(); // will delete itself + } + + void invalidateConnection( QgsOracleConn * ) override {}; + bool connectionIsValid( QgsOracleConn * ) override { return true;}; protected slots: void handleConnectionExpired() { onConnectionExpired(); } @@ -72,6 +65,11 @@ class QgsOracleConnPool : public QgsConnectionPoolconnInfo(); + } + protected: Q_DISABLE_COPY( QgsOracleConnPool ) diff --git a/src/providers/postgres/CMakeLists.txt b/src/providers/postgres/CMakeLists.txt index b074d4d845d7..6237b6976e57 100644 --- a/src/providers/postgres/CMakeLists.txt +++ b/src/providers/postgres/CMakeLists.txt @@ -4,7 +4,6 @@ set(PG_SRCS qgspostgresprovider.cpp qgspostgresconn.cpp - qgspostgresconnpool.cpp qgspostgresdataitems.cpp qgspostgresfeatureiterator.cpp qgspostgresprojectstorage.cpp @@ -34,6 +33,7 @@ endif() set(PG_HDRS qgspostgresexpressioncompiler.h qgspostgresproviderconnection.h + qgspostgresconnpool.h ) ######################################################## @@ -94,7 +94,6 @@ set(PGRASTER_SRCS raster/qgspostgresrastershareddata.cpp raster/qgspostgresrasterutils.cpp qgspostgresconn.cpp - qgspostgresconnpool.cpp qgspostgresprovidermetadatautils.cpp ) diff --git a/src/providers/postgres/qgspostgresconnpool.cpp b/src/providers/postgres/qgspostgresconnpool.cpp deleted file mode 100644 index 44967d18bd81..000000000000 --- a/src/providers/postgres/qgspostgresconnpool.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/*************************************************************************** - qgspostgresconnpool.cpp - --------------------- - begin : January 2014 - copyright : (C) 2014 by Martin Dobias - email : wonder dot sk at gmail dot com - *************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ - -#include "qgspostgresconnpool.h" -#include "qgspostgresconn.h" -#include "qgslogger.h" - -QgsPostgresConnPool *QgsPostgresConnPool::sInstance = nullptr; - -QgsPostgresConnPool *QgsPostgresConnPool::instance() -{ - if ( !sInstance ) - sInstance = new QgsPostgresConnPool(); - return sInstance; -} - -void QgsPostgresConnPool::cleanupInstance() -{ - delete sInstance; - sInstance = nullptr; -} - -QgsPostgresConnPool::QgsPostgresConnPool() : QgsConnectionPool() -{ - QgsDebugCall; -} - -QgsPostgresConnPool::~QgsPostgresConnPool() -{ - QgsDebugCall; -} - diff --git a/src/providers/postgres/qgspostgresconnpool.h b/src/providers/postgres/qgspostgresconnpool.h index d85531d60412..507f6a51a13b 100644 --- a/src/providers/postgres/qgspostgresconnpool.h +++ b/src/providers/postgres/qgspostgresconnpool.h @@ -18,69 +18,26 @@ #include "qgsconnectionpool.h" #include "qgspostgresconn.h" +#include "qgssqlconnpool.h" -inline QString qgsConnectionPool_ConnectionToName( QgsPostgresConn *c ) -{ - return c->connInfo(); -} - -inline void qgsConnectionPool_ConnectionCreate( const QString &connInfo, QgsPostgresConn *&c ) -{ - c = QgsPostgresConn::connectDb( connInfo, true, false ); -} - -inline void qgsConnectionPool_ConnectionDestroy( QgsPostgresConn *c ) -{ - c->unref(); // will delete itself -} - -inline void qgsConnectionPool_InvalidateConnection( QgsPostgresConn *c ) -{ - Q_UNUSED( c ) -} - -inline bool qgsConnectionPool_ConnectionIsValid( QgsPostgresConn *c ) -{ - Q_UNUSED( c ) - return true; -} - - -class QgsPostgresConnPoolGroup : public QObject, public QgsConnectionPoolGroup +// QObject currently does not support templating (due to the macros Q_OBJECT, slots), +// hence this class explicitly specializes QgsSQLConnPoolGroup. +class QgsPostgresConnPoolGroup : public QObject, public QgsSQLConnPoolGroup { Q_OBJECT - public: - explicit QgsPostgresConnPoolGroup( const QString &name ) : QgsConnectionPoolGroup( name ) { initTimer( this ); } - + explicit QgsPostgresConnPoolGroup( const QString &name ) : QgsSQLConnPoolGroup( name, this ) {} protected slots: void handleConnectionExpired() { onConnectionExpired(); } void startExpirationTimer() { expirationTimer->start(); } void stopExpirationTimer() { expirationTimer->stop(); } - protected: Q_DISABLE_COPY( QgsPostgresConnPoolGroup ) - }; -//! PostgreSQL connection pool - singleton -class QgsPostgresConnPool : public QgsConnectionPool -{ - public: - static QgsPostgresConnPool *instance(); - - static void cleanupInstance(); - - protected: - Q_DISABLE_COPY( QgsPostgresConnPool ) - - private: - QgsPostgresConnPool(); - ~QgsPostgresConnPool() override; - - static QgsPostgresConnPool *sInstance; -}; +//! PostgreSQL connection pool - singleton +using QgsPostgresConnPool = QgsSQLConnPool; #endif // QGSPOSTGRESCONNPOOL_H diff --git a/src/providers/spatialite/qgsspatialiteconnpool.cpp b/src/providers/spatialite/qgsspatialiteconnpool.cpp index dfb6fa6fcec5..b4d073767ef9 100644 --- a/src/providers/spatialite/qgsspatialiteconnpool.cpp +++ b/src/providers/spatialite/qgsspatialiteconnpool.cpp @@ -18,6 +18,30 @@ #include "qgsspatialiteconnpool.h" +void QgsSpatiaLiteConnPoolGroup::connectionCreate( const QString &connectionInfo, QgsSqliteHandle *&connection ) +{ + connection = QgsSqliteHandle::openDb( connectionInfo, false ); +} + +void QgsSpatiaLiteConnPoolGroup::connectionDestroy( QgsSqliteHandle *connection ) +{ + QgsSqliteHandle::closeDb( connection ); // will delete itself +} + +void QgsSpatiaLiteConnPoolGroup::invalidateConnection( QgsSqliteHandle *connection ) +{ + /* Invalidation is used in particular by the WFS provider that uses a */ + /* temporary SpatiaLite DB and want to delete it at some point. For that */ + /* it must invalidate all handles pointing to it */ + connection->invalidate(); +} + +bool QgsSpatiaLiteConnPoolGroup::connectionIsValid( QgsSqliteHandle *connection ) +{ + return connection->isValid(); +} + + QgsSpatiaLiteConnPool *QgsSpatiaLiteConnPool::sInstance = nullptr; QgsSpatiaLiteConnPool *QgsSpatiaLiteConnPool::instance() @@ -41,3 +65,8 @@ void QgsSpatiaLiteConnPool::cleanupInstance() delete sInstance; sInstance = nullptr; } + +QString QgsSpatiaLiteConnPool::connectionToName( QgsSqliteHandle *connection ) +{ + return connection->dbPath(); +} diff --git a/src/providers/spatialite/qgsspatialiteconnpool.h b/src/providers/spatialite/qgsspatialiteconnpool.h index be3dc6d3e9da..19d1da2e72c3 100644 --- a/src/providers/spatialite/qgsspatialiteconnpool.h +++ b/src/providers/spatialite/qgsspatialiteconnpool.h @@ -19,41 +19,16 @@ #include "qgsconnectionpool.h" #include "qgsspatialiteconnection.h" -inline QString qgsConnectionPool_ConnectionToName( QgsSqliteHandle *c ) -{ - return c->dbPath(); -} - -inline void qgsConnectionPool_ConnectionCreate( const QString &connInfo, QgsSqliteHandle *&c ) -{ - c = QgsSqliteHandle::openDb( connInfo, false ); -} - -inline void qgsConnectionPool_ConnectionDestroy( QgsSqliteHandle *c ) -{ - QgsSqliteHandle::closeDb( c ); // will delete itself -} - -inline void qgsConnectionPool_InvalidateConnection( QgsSqliteHandle *c ) -{ - /* Invalidation is used in particular by the WFS provider that uses a */ - /* temporary SpatiaLite DB and want to delete it at some point. For that */ - /* it must invalidate all handles pointing to it */ - c->invalidate(); -} - -inline bool qgsConnectionPool_ConnectionIsValid( QgsSqliteHandle *c ) -{ - return c->isValid(); -} - - class QgsSpatiaLiteConnPoolGroup : public QObject, public QgsConnectionPoolGroup { Q_OBJECT public: explicit QgsSpatiaLiteConnPoolGroup( const QString &name ) : QgsConnectionPoolGroup( name ) { initTimer( this ); } + void connectionCreate( const QString &connectionInfo, QgsSqliteHandle *&connection ) override; + void connectionDestroy( QgsSqliteHandle *connection ) override; + void invalidateConnection( QgsSqliteHandle *connection ) override; + bool connectionIsValid( QgsSqliteHandle *connection ) override; protected slots: void handleConnectionExpired() { onConnectionExpired(); } @@ -81,6 +56,7 @@ class QgsSpatiaLiteConnPool : public QgsConnectionPool