Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsogrconnpool.h 3 : : --------------------- 4 : : begin : May 2015 5 : : copyright : (C) 2015 by Sandro Mani 6 : : email : smani at sourcepole dot ch 7 : : *************************************************************************** 8 : : * * 9 : : * This program is free software; you can redistribute it and/or modify * 10 : : * it under the terms of the GNU General Public License as published by * 11 : : * the Free Software Foundation; either version 2 of the License, or * 12 : : * (at your option) any later version. * 13 : : * * 14 : : ***************************************************************************/ 15 : : 16 : : #ifndef QGSOGRCONNPOOL_H 17 : : #define QGSOGRCONNPOOL_H 18 : : 19 : : #include "qgsconnectionpool.h" 20 : : #include "qgsogrprovider.h" 21 : : #include <gdal.h> 22 : : #include "qgis_sip.h" 23 : : 24 : : ///@cond PRIVATE 25 : : #define SIP_NO_FILE 26 : : 27 : 87 : struct QgsOgrConn 28 : : { 29 : : QString path; 30 : : GDALDatasetH ds; 31 : : bool valid; 32 : : }; 33 : : 34 : 92 : inline QString qgsConnectionPool_ConnectionToName( QgsOgrConn *c ) 35 : : { 36 : 92 : return c->path; 37 : : } 38 : : 39 : 87 : inline void qgsConnectionPool_ConnectionCreate( const QString &connInfo, QgsOgrConn *&c ) 40 : : { 41 : 87 : c = new QgsOgrConn; 42 : : 43 : 87 : const QVariantMap parts = QgsOgrProviderMetadata().decodeUri( connInfo ); 44 : 261 : const QString fullPath = parts.value( QStringLiteral( "vsiPrefix" ) ).toString() 45 : 174 : + parts.value( QStringLiteral( "path" ) ).toString() 46 : 174 : + parts.value( QStringLiteral( "vsiSuffix" ) ).toString(); 47 : 174 : const QStringList openOptions = parts.value( QStringLiteral( "openOptions" ) ).toStringList(); 48 : 87 : char **papszOpenOptions = nullptr; 49 : 87 : for ( const QString &option : openOptions ) 50 : : { 51 : 0 : papszOpenOptions = CSLAddString( papszOpenOptions, 52 : 0 : option.toUtf8().constData() ); 53 : : } 54 : 87 : c->ds = QgsOgrProviderUtils::GDALOpenWrapper( fullPath.toUtf8().constData(), false, papszOpenOptions, nullptr ); 55 : 87 : CSLDestroy( papszOpenOptions ); 56 : 87 : c->path = connInfo; 57 : 87 : c->valid = true; 58 : 87 : } 59 : : 60 : 0 : inline void qgsConnectionPool_ConnectionDestroy( QgsOgrConn *c ) 61 : : { 62 : 0 : QgsOgrProviderUtils::GDALCloseWrapper( c->ds ); 63 : 0 : delete c; 64 : 0 : } 65 : : 66 : 0 : inline void qgsConnectionPool_InvalidateConnection( QgsOgrConn *c ) 67 : : { 68 : 0 : c->valid = false; 69 : 0 : } 70 : : 71 : 97 : inline bool qgsConnectionPool_ConnectionIsValid( QgsOgrConn *c ) 72 : : { 73 : 97 : return c->valid; 74 : : } 75 : : 76 : : class QgsOgrConnPoolGroup : public QObject, public QgsConnectionPoolGroup<QgsOgrConn *> 77 : : { 78 : : Q_OBJECT 79 : : 80 : : public: 81 : 64 : explicit QgsOgrConnPoolGroup( const QString &name ) 82 : 64 : : QgsConnectionPoolGroup<QgsOgrConn*>( name ) 83 : 128 : { 84 : 64 : initTimer( this ); 85 : 64 : } 86 : : 87 : : //! QgsOgrConnPoolGroup cannot be copied 88 : : QgsOgrConnPoolGroup( const QgsOgrConnPoolGroup &other ) = delete; 89 : : 90 : : //! QgsOgrConnPoolGroup cannot be copied 91 : : QgsOgrConnPoolGroup &operator=( const QgsOgrConnPoolGroup &other ) = delete; 92 : : 93 : 237 : void ref() { ++mRefCount; } 94 : 231 : bool unref() 95 : : { 96 : : Q_ASSERT( mRefCount > 0 ); 97 : 231 : return --mRefCount == 0; 98 : : } 99 : : 100 : : protected slots: 101 : : void handleConnectionExpired() { onConnectionExpired(); } 102 : : void startExpirationTimer() { expirationTimer->start(); } 103 : : void stopExpirationTimer() { expirationTimer->stop(); } 104 : : 105 : : private: 106 : 64 : int mRefCount = 0; 107 : : 108 : : }; 109 : : 110 : : //! Ogr connection pool - singleton 111 : : class QgsOgrConnPool : public QgsConnectionPool<QgsOgrConn *, QgsOgrConnPoolGroup> 112 : : { 113 : : public: 114 : : 115 : : // NOTE: first call to this function initializes the 116 : : // singleton. 117 : : // WARNING: concurrent call from multiple threads may result 118 : : // in multiple instances being created, and memory 119 : : // leaking at exit. 120 : : // 121 : : static QgsOgrConnPool *instance(); 122 : : 123 : : // Singleton cleanup 124 : : // 125 : : // Make sure nobody is using the instance before calling 126 : : // this function. 127 : : // 128 : : // WARNING: concurrent call from multiple threads may result 129 : : // in double-free of the instance. 130 : : // 131 : : static void cleanupInstance(); 132 : : 133 : : //! QgsOgrConnPool cannot be copied 134 : : QgsOgrConnPool( const QgsOgrConnPool &other ) = delete; 135 : : 136 : : //! QgsOgrConnPool cannot be copied 137 : : QgsOgrConnPool &operator=( const QgsOgrConnPool &other ) = delete; 138 : : 139 : : /** 140 : : * \brief Increases the reference count on the connection pool for the specified connection. 141 : : * \param connInfo The connection string. 142 : : * \note 143 : : * Any user of the connection pool needs to increase the reference count 144 : : * before it acquires any connections and decrease the reference count after 145 : : * releasing all acquired connections to ensure that all open OGR handles 146 : : * are freed when and only when no one is using the pool anymore. 147 : : */ 148 : 237 : void ref( const QString &connInfo ) 149 : : { 150 : 237 : mMutex.lock(); 151 : 237 : T_Groups::iterator it = mGroups.find( connInfo ); 152 : 237 : if ( it == mGroups.end() ) 153 : 64 : it = mGroups.insert( connInfo, new QgsOgrConnPoolGroup( connInfo ) ); 154 : 237 : it.value()->ref(); 155 : 237 : mMutex.unlock(); 156 : 237 : } 157 : : 158 : : /** 159 : : * \brief Decrease the reference count on the connection pool for the specified connection. 160 : : * \param connInfo The connection string. 161 : : */ 162 : 231 : void unref( const QString &connInfo ) 163 : : { 164 : 231 : mMutex.lock(); 165 : 231 : T_Groups::iterator it = mGroups.find( connInfo ); 166 : 231 : if ( it == mGroups.end() ) 167 : : { 168 : 0 : mMutex.unlock(); 169 : 0 : return; 170 : : } 171 : : 172 : 231 : if ( it.value()->unref() ) 173 : : { 174 : 61 : it.value()->deleteLater(); 175 : 61 : mGroups.erase( it ); 176 : 61 : } 177 : 231 : mMutex.unlock(); 178 : 231 : } 179 : : 180 : : private: 181 : : QgsOgrConnPool(); 182 : : ~QgsOgrConnPool() override; 183 : : static QgsOgrConnPool *sInstance; 184 : : }; 185 : : 186 : : ///@endcond 187 : : #endif // QGSOGRCONNPOOL_H