From 97e5d31706db2e95af74a3f2f1df4de541cde240 Mon Sep 17 00:00:00 2001 From: "Juergen E. Fischer" Date: Thu, 3 Dec 2015 18:59:00 +0100 Subject: [PATCH] add oracle connection pooling --- src/providers/oracle/CMakeLists.txt | 2 + .../oracle/qgsoraclecolumntypethread.cpp | 5 +- src/providers/oracle/qgsoracleconnpool.cpp | 35 ++++++++ src/providers/oracle/qgsoracleconnpool.h | 84 +++++++++++++++++++ .../oracle/qgsoraclefeatureiterator.cpp | 5 +- .../oracle/qgsoraclenewconnection.cpp | 5 +- src/providers/oracle/qgsoracleprovider.cpp | 6 +- .../oracle/qgsoraclesourceselect.cpp | 1 - src/providers/oracle/qgsoraclesourceselect.h | 3 +- src/providers/oracle/qgsoracletablecache.cpp | 4 +- 10 files changed, 137 insertions(+), 13 deletions(-) create mode 100644 src/providers/oracle/qgsoracleconnpool.cpp create mode 100644 src/providers/oracle/qgsoracleconnpool.h diff --git a/src/providers/oracle/CMakeLists.txt b/src/providers/oracle/CMakeLists.txt index 135540432105..f74303c2c267 100644 --- a/src/providers/oracle/CMakeLists.txt +++ b/src/providers/oracle/CMakeLists.txt @@ -13,6 +13,7 @@ SET(ORACLE_SRCS qgsoracletablemodel.cpp qgsoraclecolumntypethread.cpp qgsoraclefeatureiterator.cpp + qgsoracleconnpool.cpp ) SET(ORACLE_MOC_HDRS @@ -23,6 +24,7 @@ SET(ORACLE_MOC_HDRS qgsoraclenewconnection.h qgsoracletablemodel.h qgsoraclecolumntypethread.h + qgsoracleconnpool.h ) diff --git a/src/providers/oracle/qgsoraclecolumntypethread.cpp b/src/providers/oracle/qgsoraclecolumntypethread.cpp index 74cc477e2154..97be65d63be0 100644 --- a/src/providers/oracle/qgsoraclecolumntypethread.cpp +++ b/src/providers/oracle/qgsoraclecolumntypethread.cpp @@ -17,6 +17,7 @@ email : jef at norbit dot de #include "qgsoraclecolumntypethread.h" #include "qgslogger.h" +#include "qgsoracleconnpool.h" #include @@ -40,7 +41,7 @@ void QgsOracleColumnTypeThread::run() mStopped = false; QgsDataSourceURI uri = QgsOracleConn::connUri( mName ); - QgsOracleConn *conn = QgsOracleConn::connectDb( uri ); + QgsOracleConn *conn = QgsOracleConnPool::instance()->acquireConnection( uri.connectionInfo() ); if ( !conn ) { QgsDebugMsg( "Connection failed - " + uri.connectionInfo() ); @@ -92,5 +93,5 @@ void QgsOracleColumnTypeThread::run() emit progress( 0, 0 ); emit progressMessage( tr( "Table retrieval finished." ) ); - conn->disconnect(); + QgsOracleConnPool::instance()->releaseConnection( conn ); } diff --git a/src/providers/oracle/qgsoracleconnpool.cpp b/src/providers/oracle/qgsoracleconnpool.cpp new file mode 100644 index 000000000000..e5e5fd31a77d --- /dev/null +++ b/src/providers/oracle/qgsoracleconnpool.cpp @@ -0,0 +1,35 @@ +/*************************************************************************** + qgsoracleconnpool.cpp + --------------------- + begin : November 2015 + copyright : (C) 2015 by Juergen E. Fischer + email : jef at norbit dot de + *************************************************************************** + * * + * 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 "qgsoracleconnpool.h" +#include "qgsoracleconn.h" + +QgsOracleConnPool QgsOracleConnPool::sInstance; + +QgsOracleConnPool* QgsOracleConnPool::instance() +{ + return &sInstance; +} + +QgsOracleConnPool::QgsOracleConnPool() : QgsConnectionPool() +{ + QgsDebugCall; +} + +QgsOracleConnPool::~QgsOracleConnPool() +{ + QgsDebugCall; +} + diff --git a/src/providers/oracle/qgsoracleconnpool.h b/src/providers/oracle/qgsoracleconnpool.h new file mode 100644 index 000000000000..2c5004d80378 --- /dev/null +++ b/src/providers/oracle/qgsoracleconnpool.h @@ -0,0 +1,84 @@ +/*************************************************************************** + qgsoracleonnpool.h + --------------------- + begin : November 2015 + copyright : (C) 2015 by Juergen Fischer + email : jef at norbit dot de + *************************************************************************** + * * + * 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 QGSORACLECONNPOOL_H +#define QGSORACLECONNPOOL_H + +#include "qgsconnectionpool.h" +#include "qgsoracleconn.h" + + +inline QString qgsConnectionPool_ConnectionToName( QgsOracleConn* c ) +{ + return c->connInfo(); +} + +inline void qgsConnectionPool_ConnectionCreate( QgsDataSourceURI uri, QgsOracleConn*& c ) +{ + c = QgsOracleConn::connectDb( uri ); +} + +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 ); } + + protected slots: + void handleConnectionExpired() { onConnectionExpired(); } + void startExpirationTimer() { expirationTimer->start(); } + void stopExpirationTimer() { expirationTimer->stop(); } + + protected: + Q_DISABLE_COPY( QgsOracleConnPoolGroup ) + +}; + +/** Oracle connection pool - singleton */ +class QgsOracleConnPool : public QgsConnectionPool +{ + public: + static QgsOracleConnPool* instance(); + + protected: + Q_DISABLE_COPY( QgsOracleConnPool ) + + private: + QgsOracleConnPool(); + ~QgsOracleConnPool(); + + static QgsOracleConnPool sInstance; +}; + + +#endif // QGSORACLECONNPOOL_H diff --git a/src/providers/oracle/qgsoraclefeatureiterator.cpp b/src/providers/oracle/qgsoraclefeatureiterator.cpp index 518a80da3279..f187cb0b961e 100644 --- a/src/providers/oracle/qgsoraclefeatureiterator.cpp +++ b/src/providers/oracle/qgsoraclefeatureiterator.cpp @@ -15,6 +15,7 @@ #include "qgsoraclefeatureiterator.h" #include "qgsoracleprovider.h" +#include "qgsoracleconnpool.h" #include "qgslogger.h" #include "qgsmessagelog.h" @@ -26,7 +27,7 @@ QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleFeatureSource* sour : QgsAbstractFeatureIteratorFromSource( source, ownSource, request ) , mRewind( false ) { - mConnection = QgsOracleConn::connectDb( mSource->mUri.connectionInfo() ); + mConnection = QgsOracleConnPool::instance()->acquireConnection( mSource->mUri.connectionInfo() ); if ( !mConnection ) { close(); @@ -269,7 +270,7 @@ bool QgsOracleFeatureIterator::close() mQry.finish(); if ( mConnection ) - mConnection->disconnect(); + QgsOracleConnPool::instance()->releaseConnection( mConnection ); mConnection = 0; iteratorClosed(); diff --git a/src/providers/oracle/qgsoraclenewconnection.cpp b/src/providers/oracle/qgsoraclenewconnection.cpp index b72f8382f3fd..0443cf5e5eef 100644 --- a/src/providers/oracle/qgsoraclenewconnection.cpp +++ b/src/providers/oracle/qgsoraclenewconnection.cpp @@ -23,6 +23,7 @@ #include "qgscontexthelp.h" #include "qgsdatasourceuri.h" #include "qgsoracletablemodel.h" +#include "qgsoracleconnpool.h" QgsOracleNewConnection::QgsOracleNewConnection( QWidget *parent, const QString& connName, Qt::WindowFlags fl ) : QDialog( parent, fl ), mOriginalConnName( connName ) @@ -138,7 +139,7 @@ void QgsOracleNewConnection::on_btnConnect_clicked() if ( !txtOptions->text().isEmpty() ) uri.setParam( "dboptions", txtOptions->text() ); - QgsOracleConn *conn = QgsOracleConn::connectDb( uri ); + QgsOracleConn *conn = QgsOracleConnPool::instance()->acquireConnection( uri.connectionInfo() ); if ( conn ) { @@ -148,7 +149,7 @@ void QgsOracleNewConnection::on_btnConnect_clicked() tr( "Connection to %1 was successful" ).arg( txtDatabase->text() ) ); // free connection resources - conn->disconnect(); + QgsOracleConnPool::instance()->releaseConnection( conn ); } else { diff --git a/src/providers/oracle/qgsoracleprovider.cpp b/src/providers/oracle/qgsoracleprovider.cpp index 73bb085b8f61..d75c6187f693 100644 --- a/src/providers/oracle/qgsoracleprovider.cpp +++ b/src/providers/oracle/qgsoracleprovider.cpp @@ -33,6 +33,7 @@ #include "qgsoraclesourceselect.h" #include "qgsoracledataitems.h" #include "qgsoraclefeatureiterator.h" +#include "qgsoracleconnpool.h" #include #include @@ -69,7 +70,7 @@ QgsOracleProvider::QgsOracleProvider( QString const & uri ) mRequestedGeomType = mUri.wkbType(); mUseEstimatedMetadata = mUri.useEstimatedMetadata(); - mConnection = QgsOracleConn::connectDb( mUri ); + mConnection = QgsOracleConnPool::instance()->acquireConnection( mUri.connectionInfo() ); if ( !mConnection ) { return; @@ -210,7 +211,7 @@ QgsAbstractFeatureSource *QgsOracleProvider::featureSource() const void QgsOracleProvider::disconnectDb() { if ( mConnection ) - mConnection->disconnect(); + QgsOracleConnPool::instance()->releaseConnection( mConnection ); mConnection = 0; } @@ -2973,7 +2974,6 @@ QGISEXTERN bool deleteLayer( const QString& uri, QString& errCause ) if ( !conn ) { errCause = QObject::tr( "Connection to database failed" ); - conn->disconnect(); return false; } diff --git a/src/providers/oracle/qgsoraclesourceselect.cpp b/src/providers/oracle/qgsoraclesourceselect.cpp index fc81ebbf09b6..2aeac672dc3d 100644 --- a/src/providers/oracle/qgsoraclesourceselect.cpp +++ b/src/providers/oracle/qgsoraclesourceselect.cpp @@ -439,7 +439,6 @@ QgsOracleSourceSelect::~QgsOracleSourceSelect() if ( mColumnTypeThread ) { mColumnTypeThread->stop(); - mColumnTypeThread->wait(); finishList(); } diff --git a/src/providers/oracle/qgsoraclesourceselect.h b/src/providers/oracle/qgsoraclesourceselect.h index c0dc9dac6454..ed40dc0e6b49 100644 --- a/src/providers/oracle/qgsoraclesourceselect.h +++ b/src/providers/oracle/qgsoraclesourceselect.h @@ -22,6 +22,7 @@ #include "qgsdbfilterproxymodel.h" #include "qgsoracletablemodel.h" #include "qgscontexthelp.h" +#include "qgsoracleconnpool.h" #include #include @@ -56,7 +57,7 @@ class QgsOracleSourceSelectDelegate : public QItemDelegate void setConnectionInfo( const QgsDataSourceURI& connInfo ) { mConnInfo = connInfo; } protected: - void setConn( QgsOracleConn *conn ) const { if ( mConn ) mConn->disconnect(); mConn = conn; } + void setConn( QgsOracleConn *conn ) const { if ( mConn ) QgsOracleConnPool::instance()->releaseConnection( mConn ); mConn = conn; } QgsOracleConn* conn() const { diff --git a/src/providers/oracle/qgsoracletablecache.cpp b/src/providers/oracle/qgsoracletablecache.cpp index dc38370fdaf9..a09c5ccfe842 100644 --- a/src/providers/oracle/qgsoracletablecache.cpp +++ b/src/providers/oracle/qgsoracletablecache.cpp @@ -274,7 +274,7 @@ void _testTableCache() // fetch QgsDataSourceURI uri = QgsOracleConn::connUri( connName ); - QgsOracleConn* c = QgsOracleConn::connectDb( uri.connectionInfo() ); + QgsOracleConn* c = QgsOracleConnectionPool::instance()->acquireConnection( uri.connectionInfo() ); if ( !c ) return; @@ -289,7 +289,7 @@ void _testTableCache() c->retrieveLayerTypes( layerProperty, useEstimated, onlyExisting ); } - c->disconnect(); + QgsOracleConnPool::instance()->releaseConnection( c ); // save