Skip to content
Permalink
Browse files
Update of providers' feature iterators
Currently providers do not support concurrent access of more iterators at once, so keep pointer to the currently active iterator and auto-close previous iterator when a new one is requested.
Auto-close iterators when all features have been set.
Auto-close iterators when the provider is deleted.
  • Loading branch information
wonder-sk committed Jan 16, 2013
1 parent de3f07e commit a6c5fd875bc73e4775b825640a7cedcc2f5a8832
@@ -1084,7 +1084,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
//annotation form for this layer
QString mAnnotationForm;

QgsFeatureIterator mLayerIterator; // temporary
QgsFeatureIterator mLayerIterator; // temporary: to support old API
friend class QgsVectorLayerFeatureIterator;
#if 0
bool mFetching;
@@ -108,6 +108,7 @@ bool QgsVectorLayerFeatureIterator::nextFeature( QgsFeature& f )
return true;
}

close();
return false;
}

@@ -9,6 +9,11 @@
QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTextProvider* p, const QgsFeatureRequest& request )
: QgsAbstractFeatureIterator( request ), P( p )
{
// make sure that only one iterator is active
if ( P->mActiveIterator )
P->mActiveIterator->close();
P->mActiveIterator = this;

rewind();
}

@@ -93,6 +98,7 @@ bool QgsDelimitedTextFeatureIterator::nextFeature( QgsFeature& feature )
// loaded, display them now.
P->handleInvalidLines();

close();
return false;
}

@@ -117,6 +123,9 @@ bool QgsDelimitedTextFeatureIterator::close()
if ( mClosed )
return false;

// tell provider that this iterator is not active anymore
P->mActiveIterator = 0;

mClosed = true;
return true;
}
@@ -148,6 +148,7 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
, mShowInvalidLines( false )
, mCrs()
, mWkbType( QGis::WKBUnknown )
, mActiveIterator( 0 )
{
QUrl url = QUrl::fromEncoded( uri.toAscii() );

@@ -449,6 +450,9 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )

QgsDelimitedTextProvider::~QgsDelimitedTextProvider()
{
if ( mActiveIterator )
mActiveIterator->close();

if ( mFile )
mFile->close();
delete mFile;
@@ -219,4 +219,5 @@ class QgsDelimitedTextProvider : public QgsVectorDataProvider
QStringList splitLine( QString line ) { return splitLine( line, mDelimiterType, mDelimiter ); }

friend class QgsDelimitedTextFeatureIterator;
QgsDelimitedTextFeatureIterator* mActiveIterator;
};
@@ -13,6 +13,11 @@
QgsGPXFeatureIterator::QgsGPXFeatureIterator( QgsGPXProvider* p, const QgsFeatureRequest& request )
: QgsAbstractFeatureIterator( request ), P( p )
{
// make sure that only one iterator is active
if ( P->mActiveIterator )
P->mActiveIterator->close();
P->mActiveIterator = this;

rewind();
}

@@ -50,6 +55,9 @@ bool QgsGPXFeatureIterator::close()

// nothing to do

// tell provider that this iterator is not active anymore
P->mActiveIterator = 0;

mClosed = true;
return true;
}
@@ -67,7 +75,9 @@ bool QgsGPXFeatureIterator::nextFeature( QgsFeature& feature )

if ( mRequest.filterType() == QgsFeatureRequest::FilterFid )
{
return readFid( feature );
bool res = readFid( feature );
close();
return res;
}


@@ -111,6 +121,7 @@ bool QgsGPXFeatureIterator::nextFeature( QgsFeature& feature )
}
}

close();
return false;
}

@@ -66,6 +66,7 @@ const QString GPX_DESCRIPTION = QObject::tr( "GPS eXchange format provider" );

QgsGPXProvider::QgsGPXProvider( QString uri ) :
QgsVectorDataProvider( uri )
, mActiveIterator( 0 )
{
// assume that it won't work
mValid = false;
@@ -110,6 +111,9 @@ QgsGPXProvider::QgsGPXProvider( QString uri ) :

QgsGPXProvider::~QgsGPXProvider()
{
if ( mActiveIterator )
mActiveIterator->close();

QgsGPSData::releaseData( mFileName );
}

@@ -28,6 +28,7 @@ class QFile;
class QDomDocument;
class QgsGPSData;

class QgsGPXFeatureIterator;

/**
\class QgsGPXProvider
@@ -171,4 +172,5 @@ class QgsGPXProvider : public QgsVectorDataProvider
wkbPoint mWKBpt;

friend class QgsGPXFeatureIterator;
QgsGPXFeatureIterator* mActiveIterator;
};
@@ -21,6 +21,11 @@ extern "C"
QgsGrassFeatureIterator::QgsGrassFeatureIterator( QgsGrassProvider* p, const QgsFeatureRequest& request )
: QgsAbstractFeatureIterator( request ), P( p )
{
// make sure that only one iterator is active
if ( P->mActiveIterator )
P->mActiveIterator->close();
P->mActiveIterator = this;

// check if outdated and update if necessary
P->ensureUpdated();

@@ -127,10 +132,16 @@ bool QgsGrassFeatureIterator::nextFeature( QgsFeature& feature )
QgsDebugMsgLevel( "entered.", 3 );

if ( P->isEdited() || P->isFrozen() || !P->mValid )
{
close();
return false;
}

if ( P->mCidxFieldIndex < 0 || mNextCidx >= P->mCidxFieldNumCats )
{
close();
return false; // No features, no features in this layer
}

bool filterById = mRequest.filterType() == QgsFeatureRequest::FilterFid;

@@ -154,7 +165,10 @@ bool QgsGrassFeatureIterator::nextFeature( QgsFeature& feature )
break;
}
if ( !found )
{
close();
return false; // No more features
}
#if QGISDEBUG > 3
QgsDebugMsg( QString( "cat = %1 type = %2 id = %3" ).arg( cat ).arg( type ).arg( id ) );
#endif
@@ -209,6 +223,9 @@ bool QgsGrassFeatureIterator::close()

free( mSelection );

// tell provider that this iterator is not active anymore
P->mActiveIterator = 0;

mClosed = true;
return true;
}
@@ -73,6 +73,7 @@ static QString GRASS_DESCRIPTION = "Grass provider"; // XXX verify this

QgsGrassProvider::QgsGrassProvider( QString uri )
: QgsVectorDataProvider( uri )
, mActiveIterator( 0 )
{
QgsDebugMsg( QString( "QgsGrassProvider URI: %1" ).arg( uri ) );

@@ -256,6 +257,10 @@ void QgsGrassProvider::update( void )
QgsGrassProvider::~QgsGrassProvider()
{
QgsDebugMsg( "entered." );

if ( mActiveIterator )
mActiveIterator->close();

closeLayer( mLayerId );
}

@@ -18,6 +18,9 @@

class QgsFeature;
class QgsField;

class QgsGrassFeatureIterator;

#include <QDateTime>

#include "qgsvectordataprovider.h"
@@ -638,6 +641,7 @@ class GRASS_LIB_EXPORT QgsGrassProvider : public QgsVectorDataProvider
static std::vector<GMAP> mMaps; // Map

friend class QgsGrassFeatureIterator;
QgsGrassFeatureIterator* mActiveIterator;
};

#endif // QGSGRASSPROVIDER_H
@@ -9,6 +9,11 @@
QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryProvider* p, const QgsFeatureRequest& request )
: QgsAbstractFeatureIterator( request ), P( p ), mSelectRectGeom( NULL )
{
// make sure that only one iterator is active
if ( P->mActiveIterator )
P->mActiveIterator->close();
P->mActiveIterator = this;

if ( mRequest.filterType() == QgsFeatureRequest::FilterRect && mRequest.flags() & QgsFeatureRequest::ExactIntersect )
{
mSelectRectGeom = QgsGeometry::fromRect( request.filterRect() );
@@ -85,6 +90,9 @@ bool QgsMemoryFeatureIterator::nextFeatureUsingList( QgsFeature& feature )
feature = P->mFeatures[*mFeatureIdListIterator];
mFeatureIdListIterator++;
}
else
close();

return hasFeature;
}

@@ -131,6 +139,8 @@ bool QgsMemoryFeatureIterator::nextFeatureTraverseAll( QgsFeature& feature )
feature.setValid( true );
feature.setFields( &P->mFields ); // allow name-based attribute lookups
}
else
close();

return hasFeature;
}
@@ -156,6 +166,9 @@ bool QgsMemoryFeatureIterator::close()
delete mSelectRectGeom;
mSelectRectGeom = NULL;

// tell provider that this iterator is not active anymore
P->mActiveIterator = 0;

mClosed = true;
return true;
}
@@ -31,8 +31,9 @@ static const QString TEXT_PROVIDER_KEY = "memory";
static const QString TEXT_PROVIDER_DESCRIPTION = "Memory provider";

QgsMemoryProvider::QgsMemoryProvider( QString uri )
: QgsVectorDataProvider( uri ),
mSpatialIndex( NULL )
: QgsVectorDataProvider( uri )
, mSpatialIndex( NULL )
, mActiveIterator( 0 )
{
// Initialize the geometry with the uri to support old style uri's
// (ie, just 'point', 'line', 'polygon')
@@ -138,6 +139,9 @@ QgsMemoryProvider::QgsMemoryProvider( QString uri )

QgsMemoryProvider::~QgsMemoryProvider()
{
if ( mActiveIterator )
mActiveIterator->close();

delete mSpatialIndex;
}

@@ -21,6 +21,8 @@ typedef QMap<QgsFeatureId, QgsFeature> QgsFeatureMap;

class QgsSpatialIndex;

class QgsMemoryFeatureIterator;

class QgsMemoryProvider : public QgsVectorDataProvider
{
Q_OBJECT
@@ -167,4 +169,5 @@ class QgsMemoryProvider : public QgsVectorDataProvider
QgsSpatialIndex* mSpatialIndex;

friend class QgsMemoryFeatureIterator;
QgsMemoryFeatureIterator* mActiveIterator;
};
@@ -19,6 +19,11 @@
QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrProvider* p, const QgsFeatureRequest& request )
: QgsAbstractFeatureIterator( request ), P( p )
{
// make sure that only one iterator is active
if ( P->mActiveIterator )
P->mActiveIterator->close();
P->mActiveIterator = this;

// set the selection rectangle pointer to 0
mSelectionRectangle = 0;

@@ -85,24 +90,24 @@ bool QgsOgrFeatureIterator::nextFeature( QgsFeature& feature )

if ( mRequest.filterType() == QgsFeatureRequest::FilterFid )
{
// make sure that only one next feature call returns a valid feature!
if ( mFeatureFetched )
return false;

OGRFeatureH fet = OGR_L_GetFeature( P->ogrLayer, FID_TO_NUMBER( mRequest.filterFid() ) );
if ( !fet )
{
close();
return false;
}

// skip features without geometry
if ( !OGR_F_GetGeometryRef( fet ) && !P->mFetchFeaturesWithoutGeom )
{
OGR_F_Destroy( fet );
close();
return false;
}

readFeature( fet, feature );
feature.setValid( true );
mFeatureFetched = true;
close(); // the feature has been read: we have finished here
return true;
}

@@ -148,9 +153,7 @@ bool QgsOgrFeatureIterator::nextFeature( QgsFeature& feature )

QgsDebugMsg( "Feature is null" );

// probably should reset reading here
rewind();

close();
return false;
}

@@ -177,6 +180,9 @@ bool QgsOgrFeatureIterator::close()
mSelectionRectangle = 0;
}

// tell provider that this iterator is not active anymore
P->mActiveIterator = 0;

mClosed = true;
return true;
}
@@ -201,6 +201,7 @@ QgsOgrProvider::QgsOgrProvider( QString const & uri )
, ogrDriver( 0 )
, valid( false )
, featuresCounted( -1 )
, mActiveIterator( 0 )
{
QgsCPLErrorHandler handler;

@@ -345,6 +346,9 @@ QgsOgrProvider::QgsOgrProvider( QString const & uri )

QgsOgrProvider::~QgsOgrProvider()
{
if ( mActiveIterator )
mActiveIterator->close();

if ( ogrLayer != ogrOrigLayer )
{
OGR_DS_ReleaseResultSet( ogrDataSource, ogrLayer );

0 comments on commit a6c5fd8

Please sign in to comment.