Revert "Merge pull request #3886 from pblottiere/servermultithread"

This reverts commit 350a2b513446462120946241cf7fb1bb67ca828b, reversing
changes made to 590a981195289be702bc7bf5382ece25a09ae6bb.
This commit is contained in:
rldhont 2017-01-09 14:05:28 +01:00
parent 350a2b5134
commit 3e80a52995
26 changed files with 80 additions and 1057 deletions

View File

@ -1,89 +0,0 @@
/***************************************************************************
qgsserversettings.sip
---------------------
begin : December 19, 2016
copyright : (C) 2016 by Paul Blottiere
email : paul dot blottiere at oslandia dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/** \ingroup server
* QgsServerSettings provides a way to retrieve settings by prioritizing
* according to environment variables, ini file and default values.
* @note added in QGIS 3.0
*/
class QgsServerSettings
{
%TypeHeaderCode
#include "qgsserversettings.h"
%End
public:
/** Constructor.
*/
QgsServerSettings();
/** Load settings according to current environment variables.
*/
void load();
/** Log a summary of settings curently loaded.
*/
void logSummary() const;
/** Returns the ini file loaded by QSetting.
* @return the path of the ini file or an empty string if none is loaded.
*/
QString iniFile() const;
/** Returns the maximum number of threads to use.
* @return the number of threads.
*/
int maxThreads() const;
/** Returns parallel rendering setting.
* @return true if parallel rendering is activated, false otherwise.
*/
bool parallelRendering() const;
/** Returns the log level.
* @return the log level.
*/
QgsMessageLog::MessageLevel logLevel() const;
/** Returns the log file.
* @return the path of the log file or an empty string if none is defined.
*/
QString logFile() const;
/** Returns the QGS project file to use.
* @return the path of the QGS project or an empty string if none is defined.
*/
QString projectFile() const;
/**
* Returns the maximum number of cached layers.
* @return the number of cached layers.
*/
int maxCacheLayers() const;
/** Returns the cache size.
* @return the cache size.
*/
qint64 cacheSize() const;
/** Returns the cache directory.
* @return the directory.
*/
QString cacheDirectory() const;
};

View File

@ -27,5 +27,4 @@
%Include qgswmsprojectparser.sip
%Include qgswfsprojectparser.sip
%Include qgsconfigcache.sip
%Include qgsserversettings.sip
%Include qgsserver.sip

View File

@ -29,7 +29,6 @@ SET ( qgis_mapserv_SRCS
qgswmsserver.cpp
qgswfsserver.cpp
qgswcsserver.cpp
qgsserversettings.cpp
qgsmapserviceexception.cpp
qgsmslayercache.cpp
qgsmslayerbuilder.cpp
@ -68,7 +67,6 @@ SET (qgis_mapserv_MOC_HDRS
# qgshttptransaction.h
qgsmslayercache.h
qgsserverlogger.h
qgsserversettings.h
qgsserverstreamingdevice.h
)

View File

@ -22,25 +22,12 @@
#include <QStringList>
void QgsAccessControl::resolveFilterFeatures( const QList<QgsMapLayer*> &layers )
{
Q_FOREACH ( QgsMapLayer* l, layers )
{
if ( l->type() == QgsMapLayer::LayerType::VectorLayer )
{
const QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( l );
mFilterFeaturesExpressions[vl->id()] = resolveFilterFeatures( vl );
}
}
mResolved = true;
}
QString QgsAccessControl::resolveFilterFeatures( const QgsVectorLayer* layer ) const
//! Filter the features of the layer
void QgsAccessControl::filterFeatures( const QgsVectorLayer* layer, QgsFeatureRequest& featureRequest ) const
{
QStringList expressions = QStringList();
QgsAccessControlFilterMap::const_iterator acIterator;
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
{
QString expression = acIterator.value()->layerFilterExpression( layer );
@ -49,34 +36,9 @@ QString QgsAccessControl::resolveFilterFeatures( const QgsVectorLayer* layer ) c
expressions.append( expression );
}
}
QString expression;
if ( !expressions.isEmpty() )
{
expression = QStringLiteral( "((" ).append( expressions.join( QStringLiteral( ") AND (" ) ) ).append( "))" );
}
return expression;
}
//! Filter the features of the layer
void QgsAccessControl::filterFeatures( const QgsVectorLayer* layer, QgsFeatureRequest& featureRequest ) const
{
QString expression;
if ( mResolved && mFilterFeaturesExpressions.keys().contains( layer->id() ) )
{
expression = mFilterFeaturesExpressions[layer->id()];
}
else
{
expression = resolveFilterFeatures( layer );
}
if ( !expression.isEmpty() )
{
featureRequest.setFilterExpression( expression );
featureRequest.setFilterExpression( QStringLiteral( "((" ).append( expressions.join( QStringLiteral( ") AND (" ) ) ).append( "))" ) );
}
}

View File

@ -40,15 +40,12 @@ class SERVER_EXPORT QgsAccessControl : public QgsFeatureFilterProvider
QgsAccessControl()
{
mPluginsAccessControls = new QgsAccessControlFilterMap();
mResolved = false;
}
//! Constructor
QgsAccessControl( const QgsAccessControl& copy )
{
mPluginsAccessControls = new QgsAccessControlFilterMap( *copy.mPluginsAccessControls );
mFilterFeaturesExpressions = copy.mFilterFeaturesExpressions;
mResolved = copy.mResolved;
}
@ -57,11 +54,6 @@ class SERVER_EXPORT QgsAccessControl : public QgsFeatureFilterProvider
delete mPluginsAccessControls;
}
/** Resolve features' filter of layers
* @param layers to filter
*/
void resolveFilterFeatures( const QList<QgsMapLayer*> &layers );
/** Filter the features of the layer
* @param layer the layer to control
* @param filterFeatures the request to fill
@ -130,13 +122,8 @@ class SERVER_EXPORT QgsAccessControl : public QgsFeatureFilterProvider
void registerAccessControl( QgsAccessControlFilter* accessControl, int priority = 0 );
private:
QString resolveFilterFeatures( const QgsVectorLayer* layer ) const;
//! The AccessControl plugins registry
QgsAccessControlFilterMap* mPluginsAccessControls;
QMap<QString, QString> mFilterFeaturesExpressions;
bool mResolved;
};
#endif

View File

@ -21,7 +21,6 @@
#include "qgsmaplayer.h"
#include "qgsvectorlayer.h"
#include "qgslogger.h"
#include "qgsserversettings.h"
#include <QFile>
QgsMSLayerCache* QgsMSLayerCache::instance()
@ -33,8 +32,20 @@ QgsMSLayerCache* QgsMSLayerCache::instance()
}
QgsMSLayerCache::QgsMSLayerCache()
: mProjectMaxLayers( 100 )
: mProjectMaxLayers( 0 )
{
mDefaultMaxLayers = 100;
//max layer from environment variable overrides default
char* maxLayerEnv = getenv( "MAX_CACHE_LAYERS" );
if ( maxLayerEnv )
{
bool conversionOk = false;
int maxLayerInt = QString( maxLayerEnv ).toInt( &conversionOk );
if ( conversionOk )
{
mDefaultMaxLayers = maxLayerInt;
}
}
QObject::connect( &mFileSystemWatcher, SIGNAL( fileChanged( const QString& ) ), this, SLOT( removeProjectFileLayers( const QString& ) ) );
}
@ -48,11 +59,6 @@ QgsMSLayerCache::~QgsMSLayerCache()
mEntries.clear();
}
void QgsMSLayerCache::setMaxCacheLayers( int maxCacheLayers )
{
mDefaultMaxLayers = maxCacheLayers;
}
void QgsMSLayerCache::insertLayer( const QString& url, const QString& layerName, QgsMapLayer* layer, const QString& configFile, const QList<QString>& tempFiles )
{
QgsMessageLog::logMessage( "Layer cache: insert Layer '" + layerName + "' configFile: " + configFile, QStringLiteral( "Server" ), QgsMessageLog::INFO );

View File

@ -56,13 +56,6 @@ class QgsMSLayerCache: public QObject
static QgsMSLayerCache* instance();
~QgsMSLayerCache();
/**
* Set the maximum number of layers in cache.
* @param maxCacheLayers the number of layers in cache
* @note added in QGIS 3.0
*/
void setMaxCacheLayers( int maxCacheLayers );
/** Inserts a new layer into the cash
@param url the layer datasource
@param layerName the layer name (to distinguish between different layers in a request using the same datasource

View File

@ -19,7 +19,6 @@
#define QGSOWSSERVER_H
#include "qgsrequesthandler.h"
#include "qgsserversettings.h"
#ifdef HAVE_SERVER_PYTHON_PLUGINS
#include "qgsaccesscontrol.h"
#endif
@ -33,15 +32,13 @@ class QgsOWSServer
public:
QgsOWSServer(
const QString& configFilePath
, const QgsServerSettings& settings
, const QMap<QString, QString>& parameters
, QgsRequestHandler* rh
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, QgsAccessControl* ac
, const QgsAccessControl* ac
#endif
)
: mSettings( settings )
, mParameters( parameters )
: mParameters( parameters )
, mRequestHandler( rh )
, mConfigFilePath( configFilePath )
#ifdef HAVE_SERVER_PYTHON_PLUGINS
@ -61,13 +58,12 @@ class QgsOWSServer
QgsOWSServer() {}
protected:
QgsServerSettings mSettings;
QMap<QString, QString> mParameters;
QgsRequestHandler* mRequestHandler;
QString mConfigFilePath;
#ifdef HAVE_SERVER_PYTHON_PLUGINS
//! The access control helper
QgsAccessControl* mAccessControl;
const QgsAccessControl* mAccessControl;
/** Apply filter strings from the access control to the layers.
* @param layer the concerned layer

View File

@ -21,7 +21,6 @@
//for CMAKE_INSTALL_PREFIX
#include "qgsconfig.h"
#include "qgsserver.h"
#include "qgsmslayercache.h"
#include "qgsmapsettings.h"
#include "qgsauthmanager.h"
@ -68,7 +67,6 @@ QgsServerInterfaceImpl*QgsServer::sServerInterface = nullptr;
// Initialization must run once for all servers
bool QgsServer::sInitialised = false;
bool QgsServer::sCaptureOutput = true;
QgsServerSettings QgsServer::sSettings;
@ -105,8 +103,12 @@ void QgsServer::setupNetworkAccessManager()
QSettings settings;
QgsNetworkAccessManager *nam = QgsNetworkAccessManager::instance();
QNetworkDiskCache *cache = new QNetworkDiskCache( nullptr );
qint64 cacheSize = sSettings.cacheSize();
QString cacheDirectory = sSettings.cacheDirectory();
QString cacheDirectory = settings.value( QStringLiteral( "cache/directory" ) ).toString();
if ( cacheDirectory.isEmpty() )
cacheDirectory = QgsApplication::qgisSettingsDirPath() + "cache";
qint64 cacheSize = settings.value( QStringLiteral( "cache/size" ), 50 * 1024 * 1024 ).toULongLong();
QgsMessageLog::logMessage( QStringLiteral( "setCacheDirectory: %1" ).arg( cacheDirectory ), QStringLiteral( "Server" ), QgsMessageLog::INFO );
QgsMessageLog::logMessage( QStringLiteral( "setMaximumCacheSize: %1" ).arg( cacheSize ), QStringLiteral( "Server" ), QgsMessageLog::INFO );
cache->setCacheDirectory( cacheDirectory );
cache->setMaximumCacheSize( cacheSize );
QgsMessageLog::logMessage( QStringLiteral( "cacheDirectory: %1" ).arg( cache->cacheDirectory() ), QStringLiteral( "Server" ), QgsMessageLog::INFO );
@ -239,7 +241,7 @@ void QgsServer::printRequestInfos()
QString QgsServer::configPath( const QString& defaultConfigPath, const QMap<QString, QString>& parameters )
{
QString cfPath( defaultConfigPath );
QString projectFile = sSettings.projectFile();
QString projectFile = getenv( "QGIS_PROJECT_FILE" );
if ( !projectFile.isEmpty() )
{
cfPath = projectFile;
@ -272,7 +274,16 @@ bool QgsServer::init( )
return false;
}
// init core application
QgsServerLogger::instance();
QString optionsPath = getenv( "QGIS_OPTIONS_PATH" );
if ( !optionsPath.isEmpty() )
{
QgsMessageLog::logMessage( "Options PATH: " + optionsPath, QStringLiteral( "Server" ), QgsMessageLog::INFO );
QSettings::setDefaultFormat( QSettings::IniFormat );
QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, optionsPath );
}
QCoreApplication::setOrganizationName( QgsApplication::QGIS_ORGANIZATION_NAME );
QCoreApplication::setOrganizationDomain( QgsApplication::QGIS_ORGANIZATION_DOMAIN );
QCoreApplication::setApplicationName( QgsApplication::QGIS_APPLICATION_NAME );
@ -284,29 +295,12 @@ bool QgsServer::init( )
QgsApplication::setPrefixPath( CMAKE_INSTALL_PREFIX, true );
#endif
// skip gdal ecw drivers
#if defined(SERVER_SKIP_ECW)
QgsMessageLog::logMessage( "Skipping GDAL ECW drivers in server.", "Server", QgsMessageLog::INFO );
QgsApplication::skipGdalDriver( "ECW" );
QgsApplication::skipGdalDriver( "JP2ECW" );
#endif
// reload settings to take into account QCoreApplication and QgsApplication
// configuration
sSettings.load();
// init and configure logger
QgsServerLogger::instance();
QgsServerLogger::instance()->setLogLevel( sSettings.logLevel() );
QgsServerLogger::instance()->setLogFile( sSettings.logFile() );
// init and configure cache
QgsMSLayerCache::instance();
QgsMSLayerCache::instance()->setMaxCacheLayers( sSettings.maxCacheLayers() );
// log settings currently used
sSettings.logSummary();
setupNetworkAccessManager();
QDomImplementation::setInvalidDataPolicy( QDomImplementation::DropInvalidChars );
@ -372,7 +366,6 @@ void QgsServer::putenv( const QString &var, const QString &val )
#else
setenv( var.toStdString().c_str(), val.toStdString().c_str(), 1 );
#endif
sSettings.load( var );
}
/**
@ -435,7 +428,7 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
// Copy the parameters map
QMap<QString, QString> parameterMap( theRequestHandler->parameterMap() );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
QgsAccessControl* accessControl = nullptr;
const QgsAccessControl* accessControl = nullptr;
accessControl = sServerInterface->accessControls();
#endif
@ -486,7 +479,6 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
{
QgsWCSServer wcsServer(
configFilePath
, sSettings
, parameterMap
, p
, theRequestHandler.data()
@ -513,7 +505,6 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
{
QgsWfsServer wfsServer(
configFilePath
, sSettings
, parameterMap
, p
, theRequestHandler.data()
@ -540,7 +531,6 @@ QPair<QByteArray, QByteArray> QgsServer::handleRequest( const QString& queryStri
{
QgsWmsServer wmsServer(
configFilePath
, sSettings
, parameterMap
, p
, theRequestHandler.data()

View File

@ -34,7 +34,6 @@
#include "qgscapabilitiescache.h"
#include "qgsmapsettings.h"
#include "qgsmessagelog.h"
#include "qgsserversettings.h"
#ifdef HAVE_SERVER_PYTHON_PLUGINS
#include "qgsserverplugins.h"
@ -126,8 +125,6 @@ class SERVER_EXPORT QgsServer
//! Initialization must run once for all servers
static bool sInitialised;
static bool sCaptureOutput;
static QgsServerSettings sSettings;
};
#endif // QGSSERVER_H

View File

@ -103,7 +103,7 @@ class SERVER_EXPORT QgsServerInterface
virtual void registerAccessControl( QgsAccessControlFilter* accessControl, int priority = 0 ) = 0;
//! Gets the registred access control filters
virtual QgsAccessControl* accessControls() const = 0;
virtual const QgsAccessControl* accessControls() const = 0;
//! Return an enrironment variable, used to pass environment variables to python
virtual QString getEnv( const QString& name ) const = 0;

View File

@ -55,7 +55,7 @@ class QgsServerInterfaceImpl : public QgsServerInterface
/** Gets the helper over all the registered access control filters
* @return the access control helper
*/
QgsAccessControl* accessControls() const override { return mAccessControls; }
const QgsAccessControl* accessControls() const override { return mAccessControls; }
QString getEnv( const QString& name ) const override;
QString configFilePath() override { return mConfigFilePath; }
void setConfigFilePath( const QString& configFilePath ) override;

View File

@ -39,33 +39,28 @@ QgsServerLogger::QgsServerLogger()
: mLogFile( nullptr )
, mLogLevel( QgsMessageLog::NONE )
{
//logfile
QString filePath = getenv( "QGIS_SERVER_LOG_FILE" );
if ( filePath.isEmpty() )
return;
mLogFile.setFileName( filePath );
if ( mLogFile.open( QIODevice::Append ) )
{
mTextStream.setDevice( &mLogFile );
}
//log level
char* logLevelChar = getenv( "QGIS_SERVER_LOG_LEVEL" );
if ( logLevelChar )
{
mLogLevel = static_cast<QgsMessageLog::MessageLevel>( atoi( logLevelChar ) );
}
connect( QgsApplication::messageLog(), SIGNAL( messageReceived( QString, QString, QgsMessageLog::MessageLevel ) ), this,
SLOT( logMessage( QString, QString, QgsMessageLog::MessageLevel ) ) );
}
void QgsServerLogger::setLogLevel( QgsMessageLog::MessageLevel level )
{
mLogLevel = level;
}
void QgsServerLogger::setLogFile( const QString& f )
{
if ( ! f.isEmpty() )
{
if ( mLogFile.exists() )
{
mTextStream.flush();
mLogFile.close();
}
mLogFile.setFileName( f );
if ( mLogFile.open( QIODevice::Append ) )
{
mTextStream.setDevice( &mLogFile );
}
}
}
void QgsServerLogger::logMessage( const QString& message, const QString& tag, QgsMessageLog::MessageLevel level )
{
Q_UNUSED( tag );

View File

@ -38,23 +38,9 @@ class QgsServerLogger: public QObject
/**
* Get the current log level
* @return the log level
* @note added in QGIS 3.0
*/
QgsMessageLog::MessageLevel logLevel() const { return mLogLevel; }
/**
* Set the current log level
* @param level the log level
* @note added in QGIS 3.0
*/
void setLogLevel( QgsMessageLog::MessageLevel level );
/**
* Set the current log file
*/
void setLogFile( const QString& f );
public slots:
/**

View File

@ -1,307 +0,0 @@
/***************************************************************************
qgsserversettings.cpp
---------------------
begin : December 19, 2016
copyright : (C) 2016 by Paul Blottiere
email : paul dot blottiere at oslandia dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsserversettings.h"
#include "qgsapplication.h"
#include <QSettings>
#include <iostream>
QgsServerSettings::QgsServerSettings()
{
load();
}
void QgsServerSettings::initSettings()
{
mSettings.clear();
// options path
const Setting sOptPath = { QgsServerSettingsEnv::QGIS_OPTIONS_PATH,
QgsServerSettingsEnv::DEFAULT_VALUE,
"Override the default path for user configuration",
"",
QVariant::String,
QVariant( "" ),
QVariant()
};
mSettings[ sOptPath.envVar ] = sOptPath;
// parallel rendering
const Setting sParRend = { QgsServerSettingsEnv::QGIS_SERVER_PARALLEL_RENDERING,
QgsServerSettingsEnv::DEFAULT_VALUE,
"Activate/Deactivate parallel rendering for WMS getMap request",
"/qgis/parallel_rendering",
QVariant::Bool,
QVariant( false ),
QVariant()
};
mSettings[ sParRend.envVar ] = sParRend;
// max threads
const Setting sMaxThreads = { QgsServerSettingsEnv::QGIS_SERVER_MAX_THREADS,
QgsServerSettingsEnv::DEFAULT_VALUE,
"Number of threads to use when parallel rendering is activated",
"/qgis/max_threads",
QVariant::Int,
QVariant( -1 ),
QVariant()
};
mSettings[ sMaxThreads.envVar ] = sMaxThreads;
// log level
const Setting sLogLevel = { QgsServerSettingsEnv::QGIS_SERVER_LOG_LEVEL,
QgsServerSettingsEnv::DEFAULT_VALUE,
"Log level",
"",
QVariant::Int,
QVariant( QgsMessageLog::NONE ),
QVariant()
};
mSettings[ sLogLevel.envVar ] = sLogLevel;
// log file
const Setting sLogFile = { QgsServerSettingsEnv::QGIS_SERVER_LOG_FILE,
QgsServerSettingsEnv::DEFAULT_VALUE,
"Log file",
"",
QVariant::String,
QVariant( "" ),
QVariant()
};
mSettings[ sLogFile.envVar ] = sLogFile;
// project file
const Setting sProject = { QgsServerSettingsEnv::QGIS_PROJECT_FILE,
QgsServerSettingsEnv::DEFAULT_VALUE,
"QGIS project file",
"",
QVariant::String,
QVariant( "" ),
QVariant()
};
mSettings[ sProject.envVar ] = sProject;
// max cache layers
const Setting sMaxCacheLayers = { QgsServerSettingsEnv::MAX_CACHE_LAYERS,
QgsServerSettingsEnv::DEFAULT_VALUE,
"Specify the maximum number of cached layers",
"",
QVariant::Int,
QVariant( 100 ),
QVariant()
};
mSettings[ sMaxCacheLayers.envVar ] = sMaxCacheLayers;
// cache directory
const Setting sCacheDir = { QgsServerSettingsEnv::QGIS_SERVER_CACHE_DIRECTORY,
QgsServerSettingsEnv::DEFAULT_VALUE,
"Specify the cache directory",
"/cache/directory",
QVariant::String,
QVariant( QgsApplication::qgisSettingsDirPath() + "cache" ),
QVariant()
};
mSettings[ sCacheDir.envVar ] = sCacheDir;
// cache size
const Setting sCacheSize = { QgsServerSettingsEnv::QGIS_SERVER_CACHE_SIZE,
QgsServerSettingsEnv::DEFAULT_VALUE,
"Specify the cache size",
"/cache/size",
QVariant::LongLong,
QVariant( 50*1024*1024 ),
QVariant()
};
mSettings[ sCacheSize.envVar ] = sCacheSize;
}
void QgsServerSettings::load()
{
// init settings each time to take into account QgsApplication and
// QCoreApplication configuration for some default values
initSettings();
// store environment variables
QMap<QgsServerSettingsEnv::EnvVar, QString> env = getEnv();
// load QSettings if QGIS_OPTIONS_PATH is defined
loadQSettings( env[ QgsServerSettingsEnv::QGIS_OPTIONS_PATH ] );
// prioritize values: 'env var' -> 'ini file' -> 'default value'
prioritize( env );
}
bool QgsServerSettings::load( const QString& envVarName )
{
bool rc( false );
const QMetaEnum metaEnum( QMetaEnum::fromType<QgsServerSettingsEnv::EnvVar>() );
const int value = metaEnum.keyToValue( envVarName.toStdString().c_str() );
if ( value >= 0 )
{
const QString envValue( getenv( envVarName.toStdString().c_str() ) );
prioritize( QMap<QgsServerSettingsEnv::EnvVar, QString> { {( QgsServerSettingsEnv::EnvVar ) value, envValue } } );
rc = true;
}
return rc;
}
QMap<QgsServerSettingsEnv::EnvVar, QString> QgsServerSettings::getEnv() const
{
QMap<QgsServerSettingsEnv::EnvVar, QString> env;
const QMetaEnum metaEnum( QMetaEnum::fromType<QgsServerSettingsEnv::EnvVar>() );
for ( int i = 0; i < metaEnum.keyCount(); i++ )
{
env[( QgsServerSettingsEnv::EnvVar ) metaEnum.value( i )] = getenv( metaEnum.key( i ) );
}
return env;
}
QVariant QgsServerSettings::value( QgsServerSettingsEnv::EnvVar envVar ) const
{
if ( mSettings[ envVar ].src == QgsServerSettingsEnv::DEFAULT_VALUE )
{
return mSettings[ envVar ].defaultVal;
}
else
{
return mSettings[ envVar ].val;
}
}
void QgsServerSettings::loadQSettings( const QString& envOptPath ) const
{
if ( ! envOptPath.isEmpty() )
{
QSettings::setDefaultFormat( QSettings::IniFormat );
QSettings::setPath( QSettings::IniFormat, QSettings::UserScope, envOptPath );
}
}
void QgsServerSettings::prioritize( const QMap<QgsServerSettingsEnv::EnvVar, QString>& env )
{
for ( QgsServerSettingsEnv::EnvVar e : env.keys() )
{
Setting s = mSettings[ e ];
QVariant varValue;
if ( ! env.value( e ).isEmpty() )
{
varValue.setValue( env.value( e ) );
}
if ( ! varValue.isNull() && varValue.canConvert( s.type ) )
{
s.val = varValue;
s.src = QgsServerSettingsEnv::ENVIRONMENT_VARIABLE;
}
else if ( ! s.iniKey.isEmpty() && QSettings().contains( s.iniKey ) && QSettings().value( s.iniKey ).canConvert( s.type ) )
{
s.val = QSettings().value( s.iniKey );
s.src = QgsServerSettingsEnv::INI_FILE;
}
else
{
s.val = QVariant();
s.src = QgsServerSettingsEnv::DEFAULT_VALUE;
}
// an empty string can be returned from QSettings. In this case, we want
// to use the default value
if ( s.type == QVariant::String && s.val.toString().isEmpty() )
{
s.val = QVariant();
s.src = QgsServerSettingsEnv::DEFAULT_VALUE;
}
mSettings[ e ] = s;
}
}
void QgsServerSettings::logSummary() const
{
const QMetaEnum metaEnumSrc( QMetaEnum::fromType<QgsServerSettingsEnv::Source>() );
const QMetaEnum metaEnumEnv( QMetaEnum::fromType<QgsServerSettingsEnv::EnvVar>() );
QgsMessageLog::logMessage( "Qgis Server Settings: ", "Server", QgsMessageLog::INFO );
for ( Setting s : mSettings )
{
const QString src = metaEnumSrc.valueToKey( s.src );
const QString var = metaEnumEnv.valueToKey( s.envVar );
const QString msg = " - " + var + " / '" + s.iniKey + "' (" + s.descr + "): '" + value( s.envVar ).toString() + "' (read from " + src + ")";
QgsMessageLog::logMessage( msg, "Server", QgsMessageLog::INFO );
}
if ( ! iniFile().isEmpty() )
{
const QString msg = "Ini file used to initialize settings: " + iniFile();
QgsMessageLog::logMessage( msg, "Server", QgsMessageLog::INFO );
}
}
// getter
QString QgsServerSettings::iniFile() const
{
return QSettings().fileName();
}
bool QgsServerSettings::parallelRendering() const
{
return value( QgsServerSettingsEnv::QGIS_SERVER_PARALLEL_RENDERING ).toBool();
}
int QgsServerSettings::maxThreads() const
{
return value( QgsServerSettingsEnv::QGIS_SERVER_MAX_THREADS ).toInt();
}
QString QgsServerSettings::logFile() const
{
return value( QgsServerSettingsEnv::QGIS_SERVER_LOG_FILE ).toString();
}
QgsMessageLog::MessageLevel QgsServerSettings::logLevel() const
{
return static_cast<QgsMessageLog::MessageLevel>( value( QgsServerSettingsEnv::QGIS_SERVER_LOG_LEVEL ).toInt() );
}
int QgsServerSettings::maxCacheLayers() const
{
return value( QgsServerSettingsEnv::MAX_CACHE_LAYERS ).toInt();
}
QString QgsServerSettings::projectFile() const
{
return value( QgsServerSettingsEnv::QGIS_PROJECT_FILE ).toString();
}
qint64 QgsServerSettings::cacheSize() const
{
return value( QgsServerSettingsEnv::QGIS_SERVER_CACHE_SIZE ).toLongLong();
}
QString QgsServerSettings::cacheDirectory() const
{
return value( QgsServerSettingsEnv::QGIS_SERVER_CACHE_DIRECTORY ).toString();
}

View File

@ -1,153 +0,0 @@
/***************************************************************************
qgsserversettings.h
-------------------
begin : December 19, 2016
copyright : (C) 2016 by Paul Blottiere
email : paul dot blottiere at oslandia dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSSERVERSETTINGS_H
#define QGSSERVERSETTINGS_H
#include <QObject>
#include <QMetaEnum>
#include "qgsmessagelog.h"
/**
* QgsServerSettingsEnv provides some enum describing the environment
* currently supported for configuration.
* @note added in QGIS 3.0
*/
class QgsServerSettingsEnv : public QObject
{
Q_OBJECT
public:
enum Source
{
DEFAULT_VALUE,
ENVIRONMENT_VARIABLE,
INI_FILE
};
Q_ENUM( Source )
enum EnvVar
{
QGIS_OPTIONS_PATH,
QGIS_SERVER_PARALLEL_RENDERING,
QGIS_SERVER_MAX_THREADS,
QGIS_SERVER_LOG_LEVEL,
QGIS_SERVER_LOG_FILE,
QGIS_PROJECT_FILE,
MAX_CACHE_LAYERS,
QGIS_SERVER_CACHE_DIRECTORY,
QGIS_SERVER_CACHE_SIZE
};
Q_ENUM( EnvVar )
};
/** \ingroup server
* QgsServerSettings provides a way to retrieve settings by prioritizing
* according to environment variables, ini file and default values.
* @note added in QGIS 3.0
*/
class SERVER_EXPORT QgsServerSettings
{
public:
struct Setting
{
QgsServerSettingsEnv::EnvVar envVar;
QgsServerSettingsEnv::Source src;
QString descr;
QString iniKey;
QVariant::Type type;
QVariant defaultVal;
QVariant val;
};
/** Constructor.
*/
QgsServerSettings();
/** Load settings according to current environment variables.
*/
void load();
/** Load setting for a specific environment variable name.
* @return true if loading is successful, false in case of an invalid name.
*/
bool load( const QString& envVarName );
/** Log a summary of settings curently loaded.
*/
void logSummary() const;
/** Returns the ini file loaded by QSetting.
* @return the path of the ini file or an empty string if none is loaded.
*/
QString iniFile() const;
/** Returns parallel rendering setting.
* @return true if parallel rendering is activated, false otherwise.
*/
bool parallelRendering() const;
/** Returns the maximum number of threads to use.
* @return the number of threads.
*/
int maxThreads() const;
/**
* Returns the maximum number of cached layers.
* @return the number of cached layers.
*/
int maxCacheLayers() const;
/** Returns the log level.
* @return the log level.
*/
QgsMessageLog::MessageLevel logLevel() const;
/** Returns the QGS project file to use.
* @return the path of the QGS project or an empty string if none is defined.
*/
QString projectFile() const;
/** Returns the log file.
* @return the path of the log file or an empty string if none is defined.
*/
QString logFile() const;
/** Returns the cache size.
* @return the cache size.
*/
qint64 cacheSize() const;
/** Returns the cache directory.
* @return the directory.
*/
QString cacheDirectory() const;
private:
void initSettings();
QVariant value( QgsServerSettingsEnv::EnvVar envVar ) const;
QMap<QgsServerSettingsEnv::EnvVar, QString> getEnv() const;
void loadQSettings( const QString& envOptPath ) const;
void prioritize( const QMap<QgsServerSettingsEnv::EnvVar, QString>& env );
QMap< QgsServerSettingsEnv::EnvVar, Setting > mSettings;
};
#endif

View File

@ -40,17 +40,15 @@ static const QString OGC_NAMESPACE = QStringLiteral( "http://www.opengis.net/ogc
QgsWCSServer::QgsWCSServer(
const QString& configFilePath
, const QgsServerSettings& settings
, QMap<QString, QString> &parameters
, QgsWCSProjectParser* pp
, QgsRequestHandler* rh
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, QgsAccessControl* accessControl
, const QgsAccessControl* accessControl
#endif
)
: QgsOWSServer(
configFilePath
, settings
, parameters
, rh
#ifdef HAVE_SERVER_PYTHON_PLUGINS
@ -66,7 +64,6 @@ QgsWCSServer::QgsWCSServer(
QgsWCSServer::QgsWCSServer()
: QgsOWSServer(
QString()
, QgsServerSettings()
, QMap<QString, QString>()
, nullptr
#ifdef HAVE_SERVER_PYTHON_PLUGINS

View File

@ -38,12 +38,11 @@ class QgsWCSServer: public QgsOWSServer
//! Constructor. Takes parameter map and a pointer to a renderer object (does not take ownership)
QgsWCSServer(
const QString& configFilePath
, const QgsServerSettings& settings
, QMap<QString, QString>& parameters
, QgsWCSProjectParser* pp
, QgsRequestHandler* rh
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, QgsAccessControl* accessControl
, const QgsAccessControl* accessControl
#endif
);

View File

@ -64,17 +64,15 @@ static const QString QGS_NAMESPACE = QStringLiteral( "http://www.qgis.org/gml" )
QgsWfsServer::QgsWfsServer(
const QString& configFilePath
, const QgsServerSettings& settings
, QMap<QString, QString> &parameters
, QgsWfsProjectParser* cp
, QgsRequestHandler* rh
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, QgsAccessControl* accessControl
, const QgsAccessControl* accessControl
#endif
)
: QgsOWSServer(
configFilePath
, settings
, parameters
, rh
#ifdef HAVE_SERVER_PYTHON_PLUGINS
@ -89,7 +87,6 @@ QgsWfsServer::QgsWfsServer(
QgsWfsServer::QgsWfsServer()
: QgsOWSServer(
QString()
, QgsServerSettings()
, QMap<QString, QString>()
, nullptr
#ifdef HAVE_SERVER_PYTHON_PLUGINS

View File

@ -59,12 +59,11 @@ class QgsWfsServer: public QgsOWSServer
//! Constructor. Takes parameter map and a pointer to a renderer object (does not take ownership)
QgsWfsServer(
const QString& configFilePath
, const QgsServerSettings& settings
, QMap<QString, QString>& parameters
, QgsWfsProjectParser* cp
, QgsRequestHandler* rh
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, QgsAccessControl* accessControl
, const QgsAccessControl* accessControl
#endif
);

View File

@ -54,8 +54,6 @@
#include "qgsaccesscontrol.h"
#include "qgsfeaturerequest.h"
#include "qgsmaprenderercustompainterjob.h"
#include "qgsmaprendererparalleljob.h"
#include "qgsserversettings.h"
#include <QImage>
#include <QPainter>
@ -72,73 +70,18 @@
#include <QUrl>
#include <QPaintEngine>
QgsMapRendererJobProxy::QgsMapRendererJobProxy(
bool parallelRendering
, int maxThreads
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, QgsAccessControl* accessControl
#endif
)
:
mParallelRendering( parallelRendering )
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, mAccessControl( accessControl )
#endif
{
if ( mParallelRendering )
{
QgsApplication::setMaxThreads( maxThreads );
QgsMessageLog::logMessage( QStringLiteral( "Parallel rendering activated with %1 threads" ).arg( maxThreads ), QStringLiteral( "server" ), QgsMessageLog::INFO );
}
else
{
QgsMessageLog::logMessage( QStringLiteral( "Parallel rendering deactivated" ), QStringLiteral( "server" ), QgsMessageLog::INFO );
}
}
void QgsMapRendererJobProxy::render( const QgsMapSettings& mapSettings, QImage* image )
{
if ( mParallelRendering )
{
QgsMapRendererParallelJob renderJob( mapSettings );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
renderJob.setFeatureFilterProvider( mAccessControl );
#endif
renderJob.start();
renderJob.waitForFinished();
*image = renderJob.renderedImage();
mPainter.reset( new QPainter( image ) );
}
else
{
mPainter.reset( new QPainter( image ) );
QgsMapRendererCustomPainterJob renderJob( mapSettings, mPainter.data() );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
renderJob.setFeatureFilterProvider( mAccessControl );
#endif
renderJob.renderSynchronously();
}
}
QPainter* QgsMapRendererJobProxy::takePainter()
{
return mPainter.take();
}
QgsWmsServer::QgsWmsServer(
const QString& configFilePath
, const QgsServerSettings& settings
, QMap<QString, QString> &parameters
, QgsWmsConfigParser* cp
, QgsRequestHandler* rh
, QgsCapabilitiesCache* capCache
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, QgsAccessControl* accessControl
, const QgsAccessControl* accessControl
#endif
)
: QgsOWSServer(
configFilePath
, settings
, parameters
, rh
#ifdef HAVE_SERVER_PYTHON_PLUGINS
@ -156,7 +99,6 @@ QgsWmsServer::QgsWmsServer(
QgsWmsServer::QgsWmsServer()
: QgsOWSServer(
QString()
, QgsServerSettings()
, QMap<QString, QString>()
, nullptr
#ifdef HAVE_SERVER_PYTHON_PLUGINS
@ -1053,9 +995,10 @@ QImage* QgsWmsServer::getLegendGraphics()
}
void QgsWmsServer::runHitTest( const QgsMapSettings& mapSettings, HitTest& hitTest )
void QgsWmsServer::runHitTest( const QgsMapSettings& mapSettings, QPainter* painter, HitTest& hitTest )
{
QgsRenderContext context = QgsRenderContext::fromMapSettings( mapSettings );
context.setPainter( painter ); // we are not going to draw anything, but we still need a working painter
Q_FOREACH ( const QString& layerID, mapSettings.layerIds() )
{
@ -1466,6 +1409,9 @@ QImage* QgsWmsServer::getMap( QgsMapSettings& mapSettings, HitTest* hitTest )
QStringList layersList, stylesList, layerIdList;
QImage* theImage = initializeRendering( layersList, stylesList, layerIdList, mapSettings );
QPainter thePainter( theImage );
thePainter.setRenderHint( QPainter::Antialiasing ); //make it look nicer
QStringList layerSetIds = mapSettings.layerIds();
QStringList highlightLayersId = QgsWmsConfigParser::addHighlightLayers( mParameters, layerSetIds );
@ -1506,40 +1452,36 @@ QImage* QgsWmsServer::getMap( QgsMapSettings& mapSettings, HitTest* hitTest )
applyOpacities( layersList, bkVectorRenderers, bkRasterRenderers, labelTransparencies, labelBufferTransparencies );
QScopedPointer<QPainter> painter;
if ( hitTest )
{
runHitTest( mapSettings, *hitTest );
painter.reset( new QPainter() );
}
runHitTest( mapSettings, &thePainter, *hitTest );
else
{
QgsMapRendererCustomPainterJob renderJob( mapSettings, &thePainter );
#ifdef HAVE_SERVER_PYTHON_PLUGINS
mAccessControl->resolveFilterFeatures( mapSettings.layers() );
renderJob.setFeatureFilterProvider( mAccessControl );
#endif
QgsMapRendererJobProxy renderJob( mSettings.parallelRendering(), mSettings.maxThreads()
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, mAccessControl
#endif
);
renderJob.render( mapSettings, theImage );
painter.reset( renderJob.takePainter() );
renderJob.renderSynchronously();
}
if ( mConfigParser )
{
//draw configuration format specific overlay items
mConfigParser->drawOverlays( painter.data(), theImage->dotsPerMeterX() / 1000.0 * 25.4, theImage->width(), theImage->height() );
mConfigParser->drawOverlays( &thePainter, theImage->dotsPerMeterX() / 1000.0 * 25.4, theImage->width(), theImage->height() );
}
restoreOpacities( bkVectorRenderers, bkRasterRenderers, labelTransparencies, labelBufferTransparencies );
clearFeatureSelections( selectedLayerIdList );
QgsWmsConfigParser::removeHighlightLayers( highlightLayersId );
// QgsMessageLog::logMessage( "clearing filters" );
if ( !hitTest )
QgsProject::instance()->removeAllMapLayers();
painter->end();
//#ifdef QGISDEBUG
// theImage->save( QDir::tempPath() + QDir::separator() + "lastrender.png" );
//#endif
thePainter.end();
//test if width / height ratio of image is the same as the ratio of WIDTH / HEIGHT parameters. If not, the image has to be scaled (required by WMS spec)
int widthParam = mParameters.value( "WIDTH", "0" ).toInt();

View File

@ -43,8 +43,6 @@ class QgsVectorLayer;
class QgsSymbol;
class QgsSymbol;
class QgsAccessControl;
class QgsMapRendererJob;
class QgsServerSettings;
class QColor;
class QFile;
@ -54,45 +52,6 @@ class QPaintDevice;
class QPainter;
class QStandardItem;
/** \ingroup server
* This class provides a proxy for sequential or parallel map render job by
* reading qsettings.
* @note added in QGIS 3.0
*/
class QgsMapRendererJobProxy
{
public:
/** Constructor.
* @param accessControl Does not take ownership of QgsAccessControl
*/
QgsMapRendererJobProxy(
bool parallelRendering
, int maxThreads
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, QgsAccessControl* accessControl
#endif
);
/** Sequential or parallel map rendering according to qsettings.
* @param mapSettings passed to MapRendererJob
* @param the rendered image
*/
void render( const QgsMapSettings& mapSettings, QImage* image );
/** Take ownership of the painter used for rendering.
* @return painter
*/
QPainter* takePainter();
private:
bool mParallelRendering;
#ifdef HAVE_SERVER_PYTHON_PLUGINS
QgsAccessControl* mAccessControl;
#endif
QScopedPointer<QPainter> mPainter;
};
/** This class handles all the wms server requests. The parameters and values have to be passed in the form of
a map<QString, QString>. This map is usually generated by a subclass of QgsWMSRequestHandler, which makes QgsWMSServer
independent from any server side technology*/
@ -105,13 +64,12 @@ class QgsWmsServer: public QgsOWSServer
QgsConfigParser and QgsCapabilitiesCache*/
QgsWmsServer(
const QString& configFilePath
, const QgsServerSettings& settings
, QMap<QString, QString> &parameters
, QgsWmsConfigParser* cp
, QgsRequestHandler* rh
, QgsCapabilitiesCache* capCache
#ifdef HAVE_SERVER_PYTHON_PLUGINS
, QgsAccessControl* accessControl
, const QgsAccessControl* accessControl
#endif
);
@ -232,7 +190,7 @@ class QgsWmsServer: public QgsOWSServer
QStringList layerSet( const QStringList& layersList, const QStringList& stylesList, const QgsCoordinateReferenceSystem& destCRS, double scaleDenominator = -1 ) const;
//! Record which symbols would be used if the map was in the current configuration of renderer. This is useful for content-based legend
void runHitTest( const QgsMapSettings& mapSettings, HitTest& hitTest );
void runHitTest( const QgsMapSettings& mapSettings, QPainter* painter, HitTest& hitTest );
//! Record which symbols within one layer would be rendered with the given renderer context
void runHitTestLayer( QgsVectorLayer* vl, SymbolSet& usedSymbols, QgsRenderContext& context );

View File

@ -166,7 +166,6 @@ ENDIF (WITH_APIDOC)
IF (WITH_SERVER)
ADD_PYTHON_TEST(PyQgsServer test_qgsserver.py)
ADD_PYTHON_TEST(PyQgsServerSettings test_qgsserver_settings.py)
ADD_PYTHON_TEST(PyQgsServerAccessControl test_qgsserver_accesscontrol.py)
ADD_PYTHON_TEST(PyQgsServerWFST test_qgsserver_wfst.py)
ADD_PYTHON_TEST(PyQgsOfflineEditingWFS test_offline_editing_wfs.py)

View File

@ -1,214 +0,0 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsServerSettings.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Paul Blottiere'
__date__ = '20/12/2016'
__copyright__ = 'Copyright 2016, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import os
from qgis.PyQt.QtCore import QCoreApplication
from utilities import unitTestDataPath
from qgis.testing import unittest
from qgis.core import QgsApplication
from qgis.server import QgsServerSettings
class TestQgsServerSettings(unittest.TestCase):
def setUp(self):
self.settings = QgsServerSettings()
self.testdata_path = unitTestDataPath("qgis_server_settings")
def tearDown(self):
pass
def test_env_parallel_rendering(self):
env = "QGIS_SERVER_PARALLEL_RENDERING"
# test parallel rendering value from environment variable
os.environ[env] = "1"
self.settings.load()
self.assertTrue(self.settings.parallelRendering())
os.environ.pop(env)
os.environ[env] = "0"
self.settings.load()
self.assertFalse(self.settings.parallelRendering())
os.environ.pop(env)
def test_env_log_level(self):
env = "QGIS_SERVER_LOG_LEVEL"
# test log level value from environment variable
os.environ[env] = "3"
self.settings.load()
self.assertEqual(self.settings.logLevel(), 3)
os.environ.pop(env)
os.environ[env] = "1"
self.settings.load()
self.assertEqual(self.settings.logLevel(), 1)
os.environ.pop(env)
def test_env_log_file(self):
env = "QGIS_SERVER_LOG_FILE"
# test parallel rendering value from environment variable
os.environ[env] = "/tmp/qgisserv.log"
self.settings.load()
self.assertEqual(self.settings.logFile(), "/tmp/qgisserv.log")
os.environ.pop(env)
os.environ[env] = "/tmp/qserv.log"
self.settings.load()
self.assertEqual(self.settings.logFile(), "/tmp/qserv.log")
os.environ.pop(env)
def test_env_project_file(self):
env = "QGIS_PROJECT_FILE"
# test parallel rendering value from environment variable
os.environ[env] = "/tmp/myproject.qgs"
self.settings.load()
self.assertEqual(self.settings.projectFile(), "/tmp/myproject.qgs")
os.environ.pop(env)
os.environ[env] = "/tmp/myproject2.qgs"
self.settings.load()
self.assertEqual(self.settings.projectFile(), "/tmp/myproject2.qgs")
os.environ.pop(env)
def test_env_max_cache_layers(self):
env = "MAX_CACHE_LAYERS"
# test parallel rendering value from environment variable
os.environ[env] = "3"
self.settings.load()
self.assertEqual(self.settings.maxCacheLayers(), 3)
os.environ.pop(env)
os.environ[env] = "100"
self.settings.load()
self.assertEqual(self.settings.maxCacheLayers(), 100)
os.environ.pop(env)
def test_env_max_threads(self):
env = "QGIS_SERVER_MAX_THREADS"
# test parallel rendering value from environment variable
os.environ[env] = "3"
self.settings.load()
self.assertEqual(self.settings.maxThreads(), 3)
os.environ.pop(env)
os.environ[env] = "5"
self.settings.load()
self.assertEqual(self.settings.maxThreads(), 5)
os.environ.pop(env)
def test_env_cache_size(self):
env = "QGIS_SERVER_CACHE_SIZE"
self.assertEqual(self.settings.cacheSize(), 50 * 1024 * 1024)
os.environ[env] = "1024"
self.settings.load()
self.assertEqual(self.settings.cacheSize(), 1024)
os.environ.pop(env)
def test_env_cache_directory(self):
env = "QGIS_SERVER_CACHE_DIRECTORY"
os.environ[env] = "/tmp/fake"
self.settings.load()
self.assertEqual(self.settings.cacheDirectory(), "/tmp/fake")
os.environ.pop(env)
def test_priority(self):
env = "QGIS_OPTIONS_PATH"
dpath = "conf0"
ini = "{0}.ini".format(os.path.join(self.testdata_path, dpath))
QCoreApplication.setOrganizationName(dpath)
# load settings
os.environ[env] = self.testdata_path
self.settings.load()
# test conf
self.assertTrue(self.settings.parallelRendering())
self.assertEqual(self.settings.maxThreads(), 3)
# set environment variables and test priority
env_pr = "QGIS_SERVER_PARALLEL_RENDERING"
os.environ[env_pr] = "0"
env_mt = "QGIS_SERVER_MAX_THREADS"
os.environ[env_mt] = "5"
self.settings.load()
self.assertFalse(self.settings.parallelRendering())
self.assertEqual(self.settings.maxThreads(), 5)
# clear environment
os.environ.pop(env)
os.environ.pop(env_pr)
os.environ.pop(env_mt)
def test_options_path_conf0(self):
env = "QGIS_OPTIONS_PATH"
dpath = "conf0"
ini = "{0}.ini".format(os.path.join(self.testdata_path, dpath))
QCoreApplication.setOrganizationName(dpath)
# load settings
os.environ[env] = self.testdata_path
self.settings.load()
# test ini file
self.assertEqual(ini, self.settings.iniFile())
# test conf
self.assertTrue(self.settings.parallelRendering())
self.assertEqual(self.settings.maxThreads(), 3)
self.assertEqual(self.settings.cacheSize(), 52428800)
# default value when an empty string is indicated in ini file
self.assertEqual(self.settings.cacheDirectory(), "cache")
# clear environment
os.environ.pop(env)
def test_options_path_conf1(self):
env = "QGIS_OPTIONS_PATH"
dpath = "conf1"
ini = "{0}.ini".format(os.path.join(self.testdata_path, dpath))
QCoreApplication.setOrganizationName(dpath)
# load settings
os.environ[env] = self.testdata_path
self.settings.load()
# test ini file
self.assertEqual(ini, self.settings.iniFile())
# test conf
self.assertFalse(self.settings.parallelRendering())
self.assertEqual(self.settings.maxThreads(), 5)
self.assertEqual(self.settings.cacheSize(), 52428800)
self.assertEqual(self.settings.cacheDirectory(), "/tmp/mycache")
# clear environment
os.environ.pop(env)
if __name__ == '__main__':
unittest.main()

View File

@ -1,7 +0,0 @@
[cache]
directory=
size=@Variant(\0\0\0\x81\0\0\0\0\x3 \0\0)
[qgis]
parallel_rendering=true
max_threads=3

View File

@ -1,7 +0,0 @@
[cache]
directory=/tmp/mycache
size=@Variant(\0\0\0\x81\0\0\0\0\x3 \0\0)
[qgis]
parallel_rendering=false
max_threads=5