Skip to content

Commit 72c9830

Browse files
committedMay 26, 2015
Merge pull request #2069 from manisandro/ogrpool
Add connection pool for OGR provider
2 parents f31abe4 + b4f4663 commit 72c9830

File tree

9 files changed

+191
-13
lines changed

9 files changed

+191
-13
lines changed
 

‎src/core/qgsconnectionpool.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
* - void qgsConnectionPool_ConnectionCreate(QString name, T& c) ... create a new connection
3838
* - void qgsConnectionPool_ConnectionDestroy(T c) ... destroy the connection
3939
* - QString qgsConnectionPool_ConnectionToName(T c) ... lookup connection's name (path)
40+
* - void qgsConnectionPool_InvalidateConnection(T c) ... flag a connection as invalid
41+
* - bool qgsConnectionPool_ConnectionIsValid(T c) ... return whether a connection is valid
4042
*
4143
* Because of issues with templates and QObject's signals and slots, this class only provides helper functions for QObject-related
4244
* functionality - the place which uses the template is resonsible for:
@@ -87,6 +89,11 @@ class QgsConnectionPoolGroup
8789
if ( !conns.isEmpty() )
8890
{
8991
Item i = conns.pop();
92+
if ( !qgsConnectionPool_ConnectionIsValid( i.c ) )
93+
{
94+
qgsConnectionPool_ConnectionDestroy( i.c );
95+
qgsConnectionPool_ConnectionCreate( connInfo, i.c );
96+
}
9097

9198
// no need to run if nothing can expire
9299
if ( conns.isEmpty() )
@@ -95,6 +102,8 @@ class QgsConnectionPoolGroup
95102
QMetaObject::invokeMethod( expirationTimer->parent(), "stopExpirationTimer" );
96103
}
97104

105+
acquiredConns.append( i.c );
106+
98107
return i.c;
99108
}
100109
}
@@ -108,11 +117,14 @@ class QgsConnectionPoolGroup
108117
return 0;
109118
}
110119

120+
acquiredConns.append( c );
111121
return c;
112122
}
113123

114124
void release( T conn )
115125
{
126+
acquiredConns.removeAll( conn );
127+
116128
connMutex.lock();
117129
Item i;
118130
i.c = conn;
@@ -130,6 +142,18 @@ class QgsConnectionPoolGroup
130142
sem.release(); // this can unlock a thread waiting in acquire()
131143
}
132144

145+
void invalidateConnections()
146+
{
147+
connMutex.lock();
148+
foreach ( Item i, conns )
149+
{
150+
qgsConnectionPool_InvalidateConnection( i.c );
151+
}
152+
foreach ( T c, acquiredConns )
153+
qgsConnectionPool_InvalidateConnection( c );
154+
connMutex.unlock();
155+
}
156+
133157
protected:
134158

135159
void initTimer( QObject* parent )
@@ -174,6 +198,7 @@ class QgsConnectionPoolGroup
174198

175199
QString connInfo;
176200
QStack<Item> conns;
201+
QList<T> acquiredConns;
177202
QMutex connMutex;
178203
QSemaphore sem;
179204
QTimer* expirationTimer;
@@ -232,8 +257,6 @@ class QgsConnectionPool
232257

233258
protected:
234259
T_Groups mGroups;
235-
236-
private:
237260
QMutex mMutex;
238261
};
239262

‎src/providers/ogr/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

2-
SET (OGR_SRCS qgsogrprovider.cpp qgsogrdataitems.cpp qgsogrfeatureiterator.cpp qgsogrgeometrysimplifier.cpp)
2+
SET (OGR_SRCS qgsogrprovider.cpp qgsogrdataitems.cpp qgsogrfeatureiterator.cpp qgsogrgeometrysimplifier.cpp qgsogrconnpool.cpp)
33

4-
SET(OGR_MOC_HDRS qgsogrprovider.h qgsogrdataitems.h)
4+
SET(OGR_MOC_HDRS qgsogrprovider.h qgsogrdataitems.h qgsogrconnpool.h)
55

66
########################################################
77
# Build

‎src/providers/ogr/qgsogrconnpool.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/***************************************************************************
2+
qgsogrconnpool.cpp
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+
#include "qgsogrconnpool.h"
17+
18+
19+
QgsOgrConnPool* QgsOgrConnPool::instance()
20+
{
21+
static QgsOgrConnPool sInstance;
22+
return &sInstance;
23+
}
24+
25+
QgsOgrConnPool::QgsOgrConnPool() : QgsConnectionPool<QgsOgrConn*, QgsOgrConnPoolGroup>()
26+
{
27+
QgsDebugCall;
28+
}
29+
30+
QgsOgrConnPool::~QgsOgrConnPool()
31+
{
32+
QgsDebugCall;
33+
}
34+
35+
void QgsOgrConnPool::invalidateHandles( const QString& connInfo )
36+
{
37+
mMutex.lock();
38+
if ( mGroups.contains( connInfo ) )
39+
mGroups[connInfo]->invalidateConnections();
40+
mMutex.unlock();
41+
}

‎src/providers/ogr/qgsogrconnpool.h

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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 <ogr_api.h>
21+
22+
23+
struct QgsOgrConn
24+
{
25+
QString path;
26+
OGRDataSourceH ds;
27+
bool valid;
28+
};
29+
30+
inline QString qgsConnectionPool_ConnectionToName( QgsOgrConn* c )
31+
{
32+
return c->path;
33+
}
34+
35+
inline void qgsConnectionPool_ConnectionCreate( QString connInfo, QgsOgrConn*& c )
36+
{
37+
c = new QgsOgrConn;
38+
c->ds = OGROpen( connInfo.toUtf8().constData(), false, NULL );
39+
c->path = connInfo;
40+
c->valid = true;
41+
}
42+
43+
inline void qgsConnectionPool_ConnectionDestroy( QgsOgrConn* c )
44+
{
45+
OGR_DS_Destroy( c->ds );
46+
delete c;
47+
}
48+
49+
inline void qgsConnectionPool_InvalidateConnection( QgsOgrConn* c )
50+
{
51+
c->valid = false;
52+
}
53+
54+
inline bool qgsConnectionPool_ConnectionIsValid( QgsOgrConn* c )
55+
{
56+
return c->valid;
57+
}
58+
59+
class QgsOgrConnPoolGroup : public QObject, public QgsConnectionPoolGroup<QgsOgrConn*>
60+
{
61+
Q_OBJECT
62+
63+
public:
64+
QgsOgrConnPoolGroup( QString name ) : QgsConnectionPoolGroup<QgsOgrConn*>( name ) { initTimer( this ); }
65+
66+
protected slots:
67+
void handleConnectionExpired() { onConnectionExpired(); }
68+
void startExpirationTimer() { expirationTimer->start(); }
69+
void stopExpirationTimer() { expirationTimer->stop(); }
70+
71+
protected:
72+
Q_DISABLE_COPY( QgsOgrConnPoolGroup )
73+
74+
};
75+
76+
/** Ogr connection pool - singleton */
77+
class QgsOgrConnPool : public QgsConnectionPool<QgsOgrConn*, QgsOgrConnPoolGroup>
78+
{
79+
public:
80+
static QgsOgrConnPool* instance();
81+
82+
void invalidateHandles( const QString& connInfo );
83+
84+
protected:
85+
Q_DISABLE_COPY( QgsOgrConnPool )
86+
87+
private:
88+
QgsOgrConnPool();
89+
~QgsOgrConnPool();
90+
};
91+
92+
93+
#endif // QGSOGRCONNPOOL_H

‎src/providers/ogr/qgsogrfeatureiterator.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,26 @@
3535

3636
QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
3737
: QgsAbstractFeatureIteratorFromSource<QgsOgrFeatureSource>( source, ownSource, request )
38-
, ogrDataSource( 0 )
3938
, ogrLayer( 0 )
4039
, mSubsetStringSet( false )
4140
, mGeometrySimplifier( NULL )
4241
{
4342
mFeatureFetched = false;
4443

45-
ogrDataSource = OGROpen( TO8F( mSource->mFilePath ), false, NULL );
44+
mConn = QgsOgrConnPool::instance()->acquireConnection( mSource->mFilePath );
4645

4746
if ( mSource->mLayerName.isNull() )
4847
{
49-
ogrLayer = OGR_DS_GetLayer( ogrDataSource, mSource->mLayerIndex );
48+
ogrLayer = OGR_DS_GetLayer( mConn->ds, mSource->mLayerIndex );
5049
}
5150
else
5251
{
53-
ogrLayer = OGR_DS_GetLayerByName( ogrDataSource, TO8( mSource->mLayerName ) );
52+
ogrLayer = OGR_DS_GetLayerByName( mConn->ds, TO8( mSource->mLayerName ) );
5453
}
5554

5655
if ( !mSource->mSubsetString.isEmpty() )
5756
{
58-
ogrLayer = QgsOgrUtils::setSubsetString( ogrLayer, ogrDataSource, mSource->mEncoding, mSource->mSubsetString );
57+
ogrLayer = QgsOgrUtils::setSubsetString( ogrLayer, mConn->ds, mSource->mEncoding, mSource->mSubsetString );
5958
mSubsetStringSet = true;
6059
}
6160

@@ -215,13 +214,13 @@ bool QgsOgrFeatureIterator::close()
215214

216215
if ( mSubsetStringSet )
217216
{
218-
OGR_DS_ReleaseResultSet( ogrDataSource, ogrLayer );
217+
OGR_DS_ReleaseResultSet( mConn->ds, ogrLayer );
219218
}
220219

221-
OGR_DS_Destroy( ogrDataSource );
220+
QgsOgrConnPool::instance()->releaseConnection( mConn );
221+
mConn = 0;
222222

223223
mClosed = true;
224-
ogrDataSource = 0;
225224
return true;
226225
}
227226

‎src/providers/ogr/qgsogrfeatureiterator.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define QGSOGRFEATUREITERATOR_H
1717

1818
#include "qgsfeatureiterator.h"
19+
#include "qgsogrconnpool.h"
1920

2021
#include <ogr_api.h>
2122

@@ -71,7 +72,7 @@ class QgsOgrFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsOgr
7172

7273
bool mFeatureFetched;
7374

74-
OGRDataSourceH ogrDataSource;
75+
QgsOgrConn* mConn;
7576
OGRLayerH ogrLayer;
7677

7778
bool mSubsetStringSet;

‎src/providers/ogr/qgsogrprovider.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,7 @@ OGRwkbGeometryType QgsOgrProvider::getOgrGeomType( OGRLayerH ogrLayer )
741741

742742
void QgsOgrProvider::loadFields()
743743
{
744+
QgsOgrConnPool::instance()->invalidateHandles( filePath() );
744745
//the attribute fields need to be read again when the encoding changes
745746
mAttributeFields.clear();
746747

@@ -2522,6 +2523,8 @@ void QgsOgrProvider::recalculateFeatureCount()
25222523
{
25232524
OGR_L_SetSpatialFilter( ogrLayer, filter );
25242525
}
2526+
2527+
QgsOgrConnPool::instance()->invalidateHandles( filePath() );
25252528
}
25262529

25272530
OGRwkbGeometryType QgsOgrProvider::ogrWkbSingleFlatten( OGRwkbGeometryType type )

‎src/providers/postgres/qgspostgresconnpool.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ inline void qgsConnectionPool_ConnectionDestroy( QgsPostgresConn* c )
3636
c->unref(); // will delete itself
3737
}
3838

39+
inline void qgsConnectionPool_InvalidateConnection( QgsPostgresConn* c )
40+
{
41+
}
42+
43+
inline bool qgsConnectionPool_ConnectionIsValid( QgsPostgresConn* c )
44+
{
45+
return true;
46+
}
47+
3948

4049
class QgsPostgresConnPoolGroup : public QObject, public QgsConnectionPoolGroup<QgsPostgresConn*>
4150
{

‎src/providers/spatialite/qgsspatialiteconnpool.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ inline void qgsConnectionPool_ConnectionDestroy( QgsSqliteHandle* c )
3535
QgsSqliteHandle::closeDb( c ); // will delete itself
3636
}
3737

38+
inline void qgsConnectionPool_InvalidateConnection( QgsSqliteHandle* c )
39+
{
40+
}
41+
42+
inline bool qgsConnectionPool_ConnectionIsValid( QgsSqliteHandle* c )
43+
{
44+
return true;
45+
}
46+
3847

3948
class QgsSpatiaLiteConnPoolGroup : public QObject, public QgsConnectionPoolGroup<QgsSqliteHandle*>
4049
{

0 commit comments

Comments
 (0)