Skip to content

Commit

Permalink
Merge pull request #2611 from mhugent/shapefile_sbn_remove
Browse files Browse the repository at this point in the history
Cleanup sbn file if gdal did not already remove it. Fixes bug #13319
  • Loading branch information
mhugent committed Jan 4, 2016
2 parents aacb37d + 09e23ee commit 1c464d6
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 128 deletions.
7 changes: 6 additions & 1 deletion src/providers/ogr/qgsogrconnpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,12 @@ class QgsOgrConnPool : public QgsConnectionPool<QgsOgrConn*, QgsOgrConnPoolGroup
{
mMutex.lock();
T_Groups::iterator it = mGroups.find( connInfo );
Q_ASSERT( it != mGroups.end() );
if ( it == mGroups.end() )
{
mMutex.unlock();
return;
}

if ( it.value()->unref() )
{
delete it.value();
Expand Down
269 changes: 142 additions & 127 deletions src/providers/ogr/qgsogrprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,97 +350,7 @@ QgsOgrProvider::QgsOgrProvider( QString const & uri )
}
}
bool openReadOnly = false;
// Try to open using VSIFileHandler
// see http://trac.osgeo.org/gdal/wiki/UserDocs/ReadInZip
QString vsiPrefix = QgsZipItem::vsiPrefix( uri );
if ( vsiPrefix != "" )
{
// GDAL>=1.8.0 has write support for zip, but read and write operations
// cannot be interleaved, so for now just use read-only.
openReadOnly = true;
if ( !mFilePath.startsWith( vsiPrefix ) )
{
mFilePath = vsiPrefix + mFilePath;
setDataSourceUri( mFilePath );
}
QgsDebugMsg( QString( "Trying %1 syntax, mFilePath= %2" ).arg( vsiPrefix, mFilePath ) );
}
QgsDebugMsg( "mFilePath: " + mFilePath );
QgsDebugMsg( "mLayerIndex: " + QString::number( mLayerIndex ) );
QgsDebugMsg( "mLayerName: " + mLayerName );
QgsDebugMsg( "mSubsetString: " + mSubsetString );
CPLSetConfigOption( "OGR_ORGANIZE_POLYGONS", "ONLY_CCW" ); // "SKIP" returns MULTIPOLYGONs for multiringed POLYGONs
if ( mFilePath.startsWith( "MySQL:" ) && !mLayerName.isEmpty() && !mFilePath.endsWith( ",tables=" + mLayerName ) )
{
mFilePath += ",tables=" + mLayerName;
}
// first try to open in update mode (unless specified otherwise)
if ( !openReadOnly )
ogrDataSource = OGROpen( TO8F( mFilePath ), true, &ogrDriver );
if ( ogrDataSource )
{
mWriteAccess = true;
}
else
{
QgsDebugMsg( "OGR failed to opened in update mode, trying in read-only mode" );
// try to open read-only
ogrDataSource = OGROpen( TO8F( mFilePath ), false, &ogrDriver );
//TODO Need to set a flag or something to indicate that the layer
//TODO is in read-only mode, otherwise edit ops will fail
//TODO: capabilities() should now reflect this; need to test.
}
if ( ogrDataSource )
{
QgsDebugMsg( "OGR opened using Driver " + QString( OGR_Dr_GetName( ogrDriver ) ) );
ogrDriverName = OGR_Dr_GetName( ogrDriver );
// We get the layer which was requested by the uri. The layername
// has precedence over the layerid if both are given.
if ( mLayerName.isNull() )
{
ogrOrigLayer = OGR_DS_GetLayer( ogrDataSource, mLayerIndex );
}
else
{
ogrOrigLayer = OGR_DS_GetLayerByName( ogrDataSource, TO8( mLayerName ) );
}
ogrLayer = ogrOrigLayer;
if ( ogrLayer )
{
// check that the initial encoding setting is fit for this layer
setEncoding( encoding() );
mValid = setSubsetString( mSubsetString );
if ( mValid )
{
QgsDebugMsg( "Data source is valid" );
}
else
{
QgsMessageLog::logMessage( tr( "Data source is invalid (%1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ), tr( "OGR" ) );
}
}
else
{
QgsMessageLog::logMessage( tr( "Data source is invalid, no layer found (%1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ), tr( "OGR" ) );
}
}
else
{
QgsMessageLog::logMessage( tr( "Data source is invalid (%1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ), tr( "OGR" ) );
}
open();
mNativeTypes
<< QgsVectorDataProvider::NativeType( tr( "Whole number (integer)" ), "integer", QVariant::Int, 1, 10 )
Expand All @@ -464,24 +374,7 @@ QgsOgrProvider::QgsOgrProvider( QString const & uri )

QgsOgrProvider::~QgsOgrProvider()
{
if ( ogrLayer != ogrOrigLayer )
{
OGR_DS_ReleaseResultSet( ogrDataSource, ogrLayer );
}

if ( ogrDataSource )
{
OGR_DS_Destroy( ogrDataSource );
}
ogrDataSource = nullptr;

if ( extent_ )
{
free( extent_ );
extent_ = nullptr;
}

QgsOgrConnPool::unrefS( mFilePath );
close();
}

QgsAbstractFeatureSource* QgsOgrProvider::featureSource() const
Expand Down Expand Up @@ -2659,6 +2552,27 @@ QString QgsOgrUtils::quotedValue( const QVariant& value )

bool QgsOgrProvider::syncToDisc()
{
//for shapefiles, remove spatial index files and create a new index
bool shapeIndex = false;
if ( ogrDriverName == "ESRI Shapefile" )
{
QString sbnIndexFile;
QFileInfo fi( mFilePath );
int suffixLength = fi.suffix().length();
sbnIndexFile = mFilePath;
sbnIndexFile.chop( suffixLength );
sbnIndexFile.append( "sbn" );

if ( QFile::exists( sbnIndexFile ) )
{
shapeIndex = true;
close();
QgsOgrConnPool::instance()->invalidateConnections( mFilePath );
QFile::remove( sbnIndexFile );
open();
}
}

if ( OGR_L_SyncToDisk( ogrLayer ) != OGRERR_NONE )
{
pushError( tr( "OGR error syncing to disk: %1" ).arg( CPLGetLastErrorMsg() ) );
Expand All @@ -2669,25 +2583,9 @@ bool QgsOgrProvider::syncToDisc()

mShapefileMayBeCorrupted = false;

//for shapefiles: is there already a spatial index?
if ( !mFilePath.isEmpty() )
if ( shapeIndex )
{
QFileInfo fi( mFilePath );

//remove the suffix and add .qix
int suffixLength = fi.suffix().length();
if ( suffixLength > 0 )
{
QString indexFilePath = mFilePath;
indexFilePath.chop( suffixLength );
indexFilePath.append( "qix" );
QFile indexFile( indexFilePath );
if ( indexFile.exists() ) //there is already a spatial index file
{
//the already existing spatial index is removed automatically by OGR
return createSpatialIndex();
}
}
return createSpatialIndex();
}

return true;
Expand Down Expand Up @@ -2787,6 +2685,123 @@ OGRLayerH QgsOgrUtils::setSubsetString( OGRLayerH layer, OGRDataSourceH ds, QTex
return OGR_DS_ExecuteSQL( ds, sql.constData(), nullptr, nullptr );
}

void QgsOgrProvider::open()
{
bool openReadOnly = false;

// Try to open using VSIFileHandler
// see http://trac.osgeo.org/gdal/wiki/UserDocs/ReadInZip
QString vsiPrefix = QgsZipItem::vsiPrefix( dataSourceUri() );
if ( vsiPrefix != "" )
{
// GDAL>=1.8.0 has write support for zip, but read and write operations
// cannot be interleaved, so for now just use read-only.
openReadOnly = true;
if ( !mFilePath.startsWith( vsiPrefix ) )
{
mFilePath = vsiPrefix + mFilePath;
setDataSourceUri( mFilePath );
}
QgsDebugMsg( QString( "Trying %1 syntax, mFilePath= %2" ).arg( vsiPrefix, mFilePath ) );
}

QgsDebugMsg( "mFilePath: " + mFilePath );
QgsDebugMsg( "mLayerIndex: " + QString::number( mLayerIndex ) );
QgsDebugMsg( "mLayerName: " + mLayerName );
QgsDebugMsg( "mSubsetString: " + mSubsetString );
CPLSetConfigOption( "OGR_ORGANIZE_POLYGONS", "ONLY_CCW" ); // "SKIP" returns MULTIPOLYGONs for multiringed POLYGONs

if ( mFilePath.startsWith( "MySQL:" ) && !mLayerName.isEmpty() && !mFilePath.endsWith( ",tables=" + mLayerName ) )
{
mFilePath += ",tables=" + mLayerName;
}

// first try to open in update mode (unless specified otherwise)
if ( !openReadOnly )
ogrDataSource = OGROpen( TO8F( mFilePath ), true, &ogrDriver );

if ( ogrDataSource )
{
mWriteAccess = true;
}
else
{
QgsDebugMsg( "OGR failed to opened in update mode, trying in read-only mode" );

// try to open read-only
ogrDataSource = OGROpen( TO8F( mFilePath ), false, &ogrDriver );

//TODO Need to set a flag or something to indicate that the layer
//TODO is in read-only mode, otherwise edit ops will fail
//TODO: capabilities() should now reflect this; need to test.
}

if ( ogrDataSource )
{
QgsDebugMsg( "OGR opened using Driver " + QString( OGR_Dr_GetName( ogrDriver ) ) );

ogrDriverName = OGR_Dr_GetName( ogrDriver );

// We get the layer which was requested by the uri. The layername
// has precedence over the layerid if both are given.
if ( mLayerName.isNull() )
{
ogrOrigLayer = OGR_DS_GetLayer( ogrDataSource, mLayerIndex );
}
else
{
ogrOrigLayer = OGR_DS_GetLayerByName( ogrDataSource, TO8( mLayerName ) );
}

ogrLayer = ogrOrigLayer;
if ( ogrLayer )
{
// check that the initial encoding setting is fit for this layer
setEncoding( encoding() );

mValid = setSubsetString( mSubsetString );
if ( mValid )
{
QgsDebugMsg( "Data source is valid" );
}
else
{
QgsMessageLog::logMessage( tr( "Data source is invalid (%1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ), tr( "OGR" ) );
}
}
else
{
QgsMessageLog::logMessage( tr( "Data source is invalid, no layer found (%1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ), tr( "OGR" ) );
}
}
else
{
QgsMessageLog::logMessage( tr( "Data source is invalid (%1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ), tr( "OGR" ) );
}
}

void QgsOgrProvider::close()
{
if ( ogrLayer != ogrOrigLayer )
{
OGR_DS_ReleaseResultSet( ogrDataSource, ogrLayer );
}

if ( ogrDataSource )
{
OGR_DS_Destroy( ogrDataSource );
}
ogrDataSource = nullptr;

if ( extent_ )
{
free( extent_ );
extent_ = nullptr;
}

QgsOgrConnPool::unrefS( mFilePath );
}

// ---------------------------------------------------------------------------

QGISEXTERN QgsVectorLayerImport::ImportError createEmptyLayer(
Expand Down
3 changes: 3 additions & 0 deletions src/providers/ogr/qgsogrprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ class QgsOgrProvider : public QgsVectorDataProvider
/** Clean shapefile from features which are marked as deleted */
void repack();

void open();
void close();

private:
unsigned char *getGeometryPointer( OGRFeatureH fet );
QString ogrWkbGeometryTypeName( OGRwkbGeometryType type ) const;
Expand Down

0 comments on commit 1c464d6

Please sign in to comment.