Skip to content

Commit

Permalink
This refactoring job is related to qgis/QGIS-Enhancement-Proposals#272
Browse files Browse the repository at this point in the history
…and the original pull request for the AWS Redshift driver #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).
  • Loading branch information
Alexey Karandashev committed Jun 1, 2023
1 parent 01e7a71 commit 4d4ab90
Show file tree
Hide file tree
Showing 12 changed files with 331 additions and 255 deletions.
43 changes: 43 additions & 0 deletions src/core/providers/ogr/qgsogrconnpool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,43 @@

#include "qgslogger.h"


void QgsOgrConnPoolGroup::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;
}

void QgsOgrConnPoolGroup::connectionDestroy( QgsOgrConn *c )
{
destroyOgrConn( c );
}

void QgsOgrConnPoolGroup::invalidateConnection( QgsOgrConn *c )
{
c->valid = false;
}

bool QgsOgrConnPoolGroup::connectionIsValid( QgsOgrConn *c )
{
return c->valid;
}

QgsOgrConnPool *QgsOgrConnPool::sInstance = nullptr;

// static public
Expand All @@ -44,4 +81,10 @@ QgsOgrConnPool::~QgsOgrConnPool()
QgsDebugCall;
}

QString QgsOgrConnPool::connectionToName( QgsOgrConn *c )
{
return c->path;
}


///@endcond
62 changes: 19 additions & 43 deletions src/core/providers/ogr/qgsogrconnpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<QgsOgrConn *>
{
Q_OBJECT
Expand All @@ -92,13 +50,31 @@ class QgsOgrConnPoolGroup : public QObject, public QgsConnectionPoolGroup<QgsOgr
//! QgsOgrConnPoolGroup cannot be copied
QgsOgrConnPoolGroup &operator=( const QgsOgrConnPoolGroup &other ) = delete;

~QgsOgrConnPoolGroup() override
{
for ( const Item &item : std::as_const( conns ) )
{
destroyOgrConn( item.c );
}
}

void connectionCreate( const QString &connInfo, QgsOgrConn *&c ) override;
void connectionDestroy( QgsOgrConn *c ) override;
void invalidateConnection( QgsOgrConn *c ) override;
bool connectionIsValid( QgsOgrConn *c ) override;
void ref() { ++mRefCount; }
bool unref()
{
Q_ASSERT( mRefCount > 0 );
return --mRefCount == 0;
}

inline void destroyOgrConn( QgsOgrConn *c )
{
QgsOgrProviderUtils::GDALCloseWrapper( c->ds );
delete c;
}

protected slots:
void handleConnectionExpired() { onConnectionExpired(); }
void startExpirationTimer() { expirationTimer->start(); }
Expand All @@ -113,7 +89,7 @@ class QgsOgrConnPoolGroup : public QObject, public QgsConnectionPoolGroup<QgsOgr
class QgsOgrConnPool : public QgsConnectionPool<QgsOgrConn *, QgsOgrConnPoolGroup>
{
public:

QString connectionToName( QgsOgrConn *c ) override;
// NOTE: first call to this function initializes the
// singleton.
// WARNING: concurrent call from multiple threads may result
Expand Down
124 changes: 124 additions & 0 deletions src/core/providers/qgssqlconnpool.h
Original file line number Diff line number Diff line change
@@ -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
* \since QGIS 3.32
* \brief Template class for SQL based provider connection pool group.
* \note not available in Python bindings.
*/
template<typename T>
class QgsSQLConnPoolGroup : public QgsConnectionPoolGroup<T *>
{
public:

/**
* The descendants inherit from QObject and pass a self reference.
*/
explicit QgsSQLConnPoolGroup( const QString &name, QObject *qobject ) :
QgsConnectionPoolGroup<T*>( name )
{
QgsConnectionPoolGroup<T *>::initTimer( qobject );
}

using typename QgsConnectionPoolGroup<T *>::Item;
using QgsConnectionPoolGroup<T *>::conns;
~QgsSQLConnPoolGroup() override
{
for ( const Item &item : std::as_const( conns ) )
{
connectionDestroy( item.c );
}
}
void connectionCreate( const QString &connInfo, T *&c ) override
{
c = T::connectDb( connInfo, true, false );
}

void connectionDestroy( T *c ) override
{
c->unref(); // will delete itself
}

void invalidateConnection( T * ) override {}

bool connectionIsValid( T * ) override
{
return true;
}
};

/**
* \ingroup core
* \since QGIS 3.32
* \brief Template class for SQL based provider connection pool.
* \note not available in Python bindings.
*/
template<typename T, typename T_Group>
class QgsSQLConnPool : public QgsConnectionPool<T *, T_Group>
{
public:

/**
* \returns the instance singleton \a sInstance.
*/
static QgsSQLConnPool<T, T_Group> *instance()
{
if ( !sInstance )
sInstance = new QgsSQLConnPool<T, T_Group>();
return sInstance;
}

/**
* Reset the global instance of the connection pool.
*/
static void cleanupInstance()
{
delete sInstance;
sInstance = nullptr;
}

QString connectionToName( T *c ) override
{
return c->connInfo();
}

protected:

/**
* Constructor/Destructor implementation for the sole purpose of debugging.
*/
QgsSQLConnPool<T, T_Group>() : QgsConnectionPool<T *, T_Group>()
{
QgsDebugCall;
}

~QgsSQLConnPool<T, T_Group>() override
{
QgsDebugCall;
}
private:
static inline QgsSQLConnPool<T, T_Group> *sInstance = nullptr;
};


#endif // QGSSQLCONNPOOL_H
Loading

0 comments on commit 4d4ab90

Please sign in to comment.