Skip to content

Commit

Permalink
[GRASS] windows fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
blazek committed Jun 21, 2015
1 parent 33b49ff commit 61d81f0
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 74 deletions.
89 changes: 18 additions & 71 deletions src/providers/grass/qgis.r.in.cpp
Expand Up @@ -28,10 +28,6 @@ extern "C"
#include <grass/gis.h>
#include <grass/raster.h>
#include <grass/display.h>

#ifdef _MSC_VER
#include <float.h>
#endif
}

#include <QByteArray>
Expand Down Expand Up @@ -62,62 +58,6 @@ extern "C"
#define G_unopen_cell Rast_unopen
#endif

// Bad, bad, bad
// http://lists.qt-project.org/pipermail/interest/2012-May/002110.html
// http://lists.qt-project.org/pipermail/interest/2012-May/002117.html
// TODO: This is just test if it works on Windows
QByteArray readData( QFile & file, qint32 size )
{
QByteArray byteArray;
forever
{
byteArray += file.read( size - byteArray.size() );
if ( byteArray.size() == size )
{
break;
}
}
return byteArray;
}

bool readBool( QFile & file )
{
QDataStream dataStream( readData( file, sizeof( bool ) ) );
bool value;
dataStream >> value;
return value;
}

qint32 readQint32( QFile & file )
{
QDataStream dataStream( readData( file, sizeof( qint32 ) ) );
qint32 value;
dataStream >> value;
return value;
}

quint32 readQuint32( QFile & file )
{
QDataStream dataStream( readData( file, sizeof( quint32 ) ) );
quint32 value;
dataStream >> value;
return value;
}

QgsRectangle readRectangle( QFile & file )
{
QDataStream dataStream( readData( file, 4*sizeof( double ) ) );
QgsRectangle rectangle;
dataStream >> rectangle;
return rectangle;
}

QByteArray readByteArray( QFile & file )
{
quint32 size = readQuint32( file );
return readData( file, size );
}

int main( int argc, char **argv )
{
char *name;
Expand All @@ -136,20 +76,25 @@ int main( int argc, char **argv )

name = map->answer;

#ifdef Q_OS_WIN32
_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);
setvbuf (stdin, NULL, _IONBF, BUFSIZ);
// setting _IONBF on stdout works on windows correctly, data written immediately even without fflush(stdout)
setvbuf (stdout, NULL, _IONBF, BUFSIZ);
#endif

QFile stdinFile;
stdinFile.open( stdin, QIODevice::ReadOnly );
//QDataStream stdinStream( &stdinFile );
QDataStream stdinStream( &stdinFile );

QFile stdoutFile;
stdoutFile.open( stdout, QIODevice::WriteOnly );
QDataStream stdoutStream( &stdoutFile );

QgsRectangle extent;
qint32 rows, cols;
//stdinStream >> extent >> cols >> rows;
extent = readRectangle( stdinFile );
cols = readQint32( stdinFile );
rows = readQint32( stdinFile );
stdinStream >> extent >> cols >> rows;

QString err = QgsGrass::setRegion( &window, extent, rows, cols );
if ( !err.isEmpty() )
Expand All @@ -161,8 +106,7 @@ int main( int argc, char **argv )

QGis::DataType qgis_type;
qint32 type;
//stdinStream >> type;
type = readQint32( stdinFile );
stdinStream >> type;
qgis_type = ( QGis::DataType )type;

RASTER_MAP_TYPE grass_type;
Expand Down Expand Up @@ -196,13 +140,13 @@ int main( int argc, char **argv )
QByteArray byteArray;
for ( int row = 0; row < rows; row++ )
{
//stdinStream >> isCanceled;
isCanceled = readBool( stdinFile );
stdinStream >> isCanceled;
if ( isCanceled )
{
break;
}
byteArray = readByteArray( stdinFile );
stdinStream >> byteArray;

if ( byteArray.size() != expectedSize )
{
G_fatal_error( "Wrong byte array size, expected %d bytes, got %d, row %d / %d", expectedSize, byteArray.size(), row, rows );
Expand Down Expand Up @@ -234,11 +178,14 @@ int main( int argc, char **argv )
G_put_raster_row( cf, buf, grass_type );

#ifndef Q_OS_WIN
// Because stdin is somewhere buffered on Windows (not clear if in QProcess or by Windows)
// we cannot in QgsGrassImport wait for this because it hangs. Setting _IONBF on stdin does not help
// and there is no flush() on QProcess.
// OTOH, smaller stdin buffer is probably blocking QgsGrassImport so that the import can be canceled immediately.
stdoutStream << ( bool )true; // row written
stdoutFile.flush();
#endif
}
//G_fatal_error( "%s", msg.toAscii().data() );

if ( isCanceled )
{
Expand Down
12 changes: 12 additions & 0 deletions src/providers/grass/qgis.v.in.cpp
Expand Up @@ -104,6 +104,12 @@ int main( int argc, char **argv )
if ( G_parser( argc, argv ) )
exit( EXIT_FAILURE );

#ifdef Q_OS_WIN32
_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);
setvbuf (stdin, NULL, _IONBF, BUFSIZ);
setvbuf (stdout, NULL, _IONBF, BUFSIZ);
#endif
QFile stdinFile;
stdinFile.open( stdin, QIODevice::ReadOnly );
QDataStream stdinStream( &stdinFile );
Expand Down Expand Up @@ -179,8 +185,11 @@ int main( int argc, char **argv )
{
exitIfCanceled( stdinStream, isPolygon, tmpName, tmpMap, finalName, finalMap );
stdinStream >> feature;
#ifndef Q_OS_WIN
// cannot be used on Windows, see notes in qgis.r.in
stdoutStream << ( bool )true; // feature received
stdoutFile.flush();
#endif
if ( !feature.isValid() )
{
break;
Expand Down Expand Up @@ -251,6 +260,7 @@ int main( int argc, char **argv )
attributes.insert( 0, QVariant( feature.id() ) );
try
{
// TODO: inserting row is extremely slow on Windows (at least with SQLite), v.in.ogr is fast
QgsGrass::insertRow( driver, QString( fieldInfo->table ), attributes );
}
catch ( QgsGrass::Exception &e )
Expand Down Expand Up @@ -336,8 +346,10 @@ int main( int argc, char **argv )
{
exitIfCanceled( stdinStream, isPolygon, tmpName, tmpMap, finalName, finalMap );
stdinStream >> feature;
#ifndef Q_OS_WIN
stdoutStream << ( bool )true; // feature received
stdoutFile.flush();
#endif
if ( !feature.isValid() )
{
break;
Expand Down
13 changes: 13 additions & 0 deletions src/providers/grass/qgsgrass.cpp
Expand Up @@ -131,11 +131,19 @@ bool QgsGrassObject::setFromUri( const QString& uri )
QString QgsGrassObject::elementShort() const
{
if ( mType == Raster )
#if GRASS_VERSION_MAJOR < 7
return "rast";
#else
return "raster";
#endif
else if ( mType == Group )
return "group";
else if ( mType == Vector )
#if GRASS_VERSION_MAJOR < 7
return "vect";
#else
return "vector";
#endif
else if ( mType == Region )
return "region";
else
Expand Down Expand Up @@ -1606,6 +1614,7 @@ QProcess GRASS_LIB_EXPORT *QgsGrass::startModule( const QString& gisdbase, const
process->setEnvironment( environment );

QgsDebugMsg( module + " " + arguments.join( " " ) );
//process->start( module, arguments, QProcess::Unbuffered );
process->start( module, arguments );
if ( !process->waitForStarted() )
{
Expand Down Expand Up @@ -1953,7 +1962,11 @@ bool GRASS_LIB_EXPORT QgsGrass::deleteObject( const QgsGrassObject & object )
QString cmd = "g.remove";
QStringList arguments;

#if GRASS_VERSION_MAJOR < 7
arguments << object.elementShort() + "=" + object.name();
#else
arguments << "-f" << "type=" + object.elementShort() << "name=" + object.name();
#endif

try
{
Expand Down
22 changes: 19 additions & 3 deletions src/providers/grass/qgsgrassimport.cpp
Expand Up @@ -264,6 +264,9 @@ bool QgsGrassRasterImport::import()
outStream << false; // not canceled
outStream << byteArray;

// Without waitForBytesWritten() it does not finish ok on Windows (process timeout)
process->waitForBytesWritten(-1);

#ifndef Q_OS_WIN
// wait until the row is written to allow quick cancel (don't send data to buffer)
process->waitForReadyRead();
Expand Down Expand Up @@ -440,6 +443,7 @@ bool QgsGrassVectorImport::import()
}

QDataStream outStream( process );
process->setReadChannel( QProcess::StandardOutput );

QGis::WkbType wkbType = mProvider->geometryType();
bool isPolygon = QGis::singleType( QGis::flatType( wkbType ) ) == QGis::WKBPolygon;
Expand Down Expand Up @@ -475,29 +479,41 @@ bool QgsGrassVectorImport::import()
outStream << false; // not canceled
outStream << feature;

// Without waitForBytesWritten() it does not finish ok on Windows (data lost)
process->waitForBytesWritten(-1);

#ifndef Q_OS_WIN
// wait until the feature is written to allow quick cancel (don't send data to buffer)
process->waitForReadyRead();
bool result;
outStream >> result;
#endif
}
feature = QgsFeature(); // indicate end by invalid feature
outStream << false; // not canceled
outStream << feature;

process->waitForBytesWritten(-1);
QgsDebugMsg( "features sent" );
#ifndef Q_OS_WIN
process->waitForReadyRead();
bool result;
outStream >> result;
#endif
}
iterator.close();

process->setReadChannel( QProcess::StandardOutput );
// Close write channel before waiting for response to avoid stdin buffer problem on Windows
process->closeWriteChannel();

QgsDebugMsg( "waitForReadyRead" );
bool result;
process->waitForReadyRead();
outStream >> result;
QgsDebugMsg( QString( "result = %1" ).arg( result ) );

process->closeWriteChannel();
process->waitForFinished( 5000 );
QgsDebugMsg( "waitForFinished" );
process->waitForFinished( 30000 );

QString stdoutString = process->readAllStandardOutput().data();
QString stderrString = process->readAllStandardError().data();
Expand Down

0 comments on commit 61d81f0

Please sign in to comment.