Skip to content
Permalink
Browse files

[GDAL provider] Make sure that setEditable(true) invalides cached GDA…

…L handles to get proper refresh (fixes #20104)
  • Loading branch information
rouault committed Oct 14, 2018
1 parent 0816a29 commit e7d15b64951da2d7efba0d32e40cb294aefcd9db
Showing with 49 additions and 3 deletions.
  1. +3 −3 src/providers/gdal/qgsgdalprovider.cpp
  2. +46 −0 tests/src/providers/testqgsgdalprovider.cpp
@@ -490,7 +490,6 @@ QgsGdalProvider::~QgsGdalProvider()
}


// This was used by raster layer to reload data
void QgsGdalProvider::closeDataset()
{
if ( !mValid )
@@ -504,6 +503,8 @@ void QgsGdalProvider::closeDataset()

GDALClose( mGdalDataset );
mGdalDataset = nullptr;

closeCachedGdalHandlesFor( this );
}

QString QgsGdalProvider::htmlMetadata()
@@ -2956,8 +2957,7 @@ bool QgsGdalProvider::remove()
if ( mGdalDataset )
{
GDALDriverH driver = GDALGetDatasetDriver( mGdalDataset );
GDALClose( mGdalDataset );
mGdalDataset = nullptr;
closeDataset();

CPLErrorReset();
CPLErr err = GDALDeleteDataset( driver, dataSourceUri( true ).toUtf8().constData() );
@@ -54,6 +54,7 @@ class TestQgsGdalProvider : public QObject
void bandName(); // test band name based on `gtiff` tags (#7317)
void bandNameNoDescription(); // test band name for when no description or tags available (#16047)
void bandNameWithDescription(); // test band name for when description available (#16047)
void interactionBetweenRasterChangeAndCache(); // test that updading a raster invalidates the GDAL dataset cache (#20104)

private:
QString mTestDataDir;
@@ -275,5 +276,50 @@ void TestQgsGdalProvider::bandNameWithDescription()
delete provider;
}

void TestQgsGdalProvider::interactionBetweenRasterChangeAndCache()
{
double geoTransform[6] = { 0, 2, 0, 0, 0, -2};
QgsCoordinateReferenceSystem crs;
QString filename = QStringLiteral( "/vsimem/temp.tif" );

// Create a all-0 dataset
auto provider = QgsRasterDataProvider::create(
QStringLiteral( "gdal" ), filename, "GTiff", 1, Qgis::Byte, 1, 1, geoTransform, crs );
delete provider;

// Open it
provider = dynamic_cast< QgsRasterDataProvider * >(
QgsProviderRegistry::instance()->createProvider(
QStringLiteral( "gdal" ), filename, QgsDataProvider::ProviderOptions() ) );
QVERIFY( provider );
auto rp = dynamic_cast< QgsRasterDataProvider * >( provider );
QVERIFY( rp );

// Create a first clone, and destroys it
auto rpClone = dynamic_cast< QgsRasterDataProvider *>( rp->clone() );
QVERIFY( rpClone );
QCOMPARE( rpClone->sample( QgsPointXY( 0.5, -0.5 ), 1 ), 0.0 );
delete rpClone;
// Now the main provider should have a cached GDAL dataset corresponding
// to the one that was used by rpClone

// Modify the raster
rp->setEditable( true );
auto rblock = new QgsRasterBlock( Qgis::Byte, 1, 1 );
rblock->setValue( 0, 0, 255 );
rp->writeBlock( rblock, 1, 0, 0 );
delete rblock;
rp->setEditable( false );

// Creates a new clone, and check that we get an updated sample value
rpClone = dynamic_cast< QgsRasterDataProvider *>( rp->clone() );
QVERIFY( rpClone );
QCOMPARE( rpClone->sample( QgsPointXY( 0.5, -0.5 ), 1 ), 255.0 );
delete rpClone;

provider->remove();
delete provider;
}

QGSTEST_MAIN( TestQgsGdalProvider )
#include "testqgsgdalprovider.moc"

0 comments on commit e7d15b6

Please sign in to comment.
You can’t perform that action at this time.