Skip to content

Commit 8f3d44d

Browse files
committed
[OGR provider] Allow opening (GeoPackage) datasets with many layers
Currently each time you instanciate a QgsOgrProvider layer, a GDAL dataset is created. In the case of GeoPackage, this means a SQLite connection and a file handle. As GDAL enables Spatialite function on GeoPackage connections, we are bound to Spatialite limits, and Spatialite has a hard limit on a maximum of 64 simultaneous connections. Thus we cannot open more than 64 layers of the same GeoPackage. This commits enables sharing of the same GDALDataset object among several QgsOgrProvider object. Care is made to reuse a GDALDataset object only if the QgsOgrProvider do not point to the same layer. Mutexes are also taken to allow safe instanciation and use of QgsOgrProvider objects from multiple threads (but a same QgsOgrProvider should not be used by more than one thread at a time)
1 parent e59f1d5 commit 8f3d44d

File tree

6 files changed

+1678
-527
lines changed

6 files changed

+1678
-527
lines changed

src/providers/ogr/qgsogrconnpool.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ inline void qgsConnectionPool_ConnectionCreate( const QString &connInfo, QgsOgrC
3737
{
3838
c = new QgsOgrConn;
3939
QString filePath = connInfo.left( connInfo.indexOf( QLatin1String( "|" ) ) );
40-
c->ds = GDALOpenEx( filePath.toUtf8().constData(), GDAL_OF_VECTOR, nullptr, nullptr, nullptr );
40+
c->ds = QgsOgrProviderUtils::GDALOpenWrapper( filePath.toUtf8().constData(), false, nullptr, nullptr );
4141
c->path = connInfo;
4242
c->valid = true;
4343
}

src/providers/ogr/qgsogrdataitems.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ QgsOgrLayerItem::QgsOgrLayerItem( QgsDataItem *parent,
5454

5555
OGRRegisterAll();
5656
GDALDriverH hDriver;
57-
GDALDatasetH hDataSource = QgsOgrProviderUtils::GDALOpenWrapper( mPath.toUtf8().constData(), true, false, &hDriver );
57+
GDALDatasetH hDataSource = QgsOgrProviderUtils::GDALOpenWrapper( mPath.toUtf8().constData(), true, nullptr, &hDriver );
5858

5959
if ( hDataSource )
6060
{
@@ -408,7 +408,7 @@ QVector<QgsDataItem *> QgsOgrDataCollectionItem::createChildren()
408408
QVector<QgsDataItem *> children;
409409

410410
GDALDriverH hDriver;
411-
GDALDatasetH hDataSource = QgsOgrProviderUtils::GDALOpenWrapper( mPath.toUtf8().constData(), false, false, &hDriver );
411+
GDALDatasetH hDataSource = QgsOgrProviderUtils::GDALOpenWrapper( mPath.toUtf8().constData(), false, nullptr, &hDriver );
412412
if ( !hDataSource )
413413
return children;
414414
int numLayers = GDALDatasetGetLayerCount( hDataSource );
@@ -639,7 +639,7 @@ QGISEXTERN QgsDataItem *dataItem( QString path, QgsDataItem *parentItem )
639639
// do not print errors, but write to debug
640640
CPLPushErrorHandler( CPLQuietErrorHandler );
641641
CPLErrorReset();
642-
OGRDataSourceH hDataSource = QgsOgrProviderUtils::GDALOpenWrapper( path.toUtf8().constData(), false, false, &hDriver );
642+
OGRDataSourceH hDataSource = QgsOgrProviderUtils::GDALOpenWrapper( path.toUtf8().constData(), false, nullptr, &hDriver );
643643
CPLPopErrorHandler();
644644

645645
if ( ! hDataSource )

src/providers/ogr/qgsogrfeatureiterator.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrFeatureSource *source, bool
4747
, mFilterFids( mRequest.filterFids() )
4848
, mFilterFidsIt( mFilterFids.constBegin() )
4949
{
50-
mConn = QgsOgrConnPool::instance()->acquireConnection( mSource->mDataSource );
50+
//QgsDebugMsg( "Feature iterator of " + mSource->mLayerName + ": acquiring connection");
51+
mConn = QgsOgrConnPool::instance()->acquireConnection( QgsOgrProviderUtils::connectionPoolId( mSource->mDataSource ) );
5152
if ( !mConn->ds )
5253
{
5354
return;
@@ -316,7 +317,10 @@ bool QgsOgrFeatureIterator::close()
316317
}
317318

318319
if ( mConn )
320+
{
321+
//QgsDebugMsg( "Feature iterator of " + mSource->mLayerName + ": releasing connection");
319322
QgsOgrConnPool::instance()->releaseConnection( mConn );
323+
}
320324

321325
mConn = nullptr;
322326
ogrLayer = nullptr;
@@ -437,12 +441,12 @@ QgsOgrFeatureSource::QgsOgrFeatureSource( const QgsOgrProvider *p )
437441
{
438442
for ( int i = ( p->mFirstFieldIsFid ) ? 1 : 0; i < mFields.size(); i++ )
439443
mFieldsWithoutFid.append( mFields.at( i ) );
440-
QgsOgrConnPool::instance()->ref( mDataSource );
444+
QgsOgrConnPool::instance()->ref( QgsOgrProviderUtils::connectionPoolId( mDataSource ) );
441445
}
442446

443447
QgsOgrFeatureSource::~QgsOgrFeatureSource()
444448
{
445-
QgsOgrConnPool::instance()->unref( mDataSource );
449+
QgsOgrConnPool::instance()->unref( QgsOgrProviderUtils::connectionPoolId( mDataSource ) );
446450
}
447451

448452
QgsFeatureIterator QgsOgrFeatureSource::getFeatures( const QgsFeatureRequest &request )

0 commit comments

Comments
 (0)