mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Revert "Merge pull request #3886 from pblottiere/servermultithread"
This reverts commit 350a2b513446462120946241cf7fb1bb67ca828b, reversing changes made to 590a981195289be702bc7bf5382ece25a09ae6bb.
This commit is contained in:
parent
350a2b5134
commit
3e80a52995
@ -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;
|
||||
};
|
@ -27,5 +27,4 @@
|
||||
%Include qgswmsprojectparser.sip
|
||||
%Include qgswfsprojectparser.sip
|
||||
%Include qgsconfigcache.sip
|
||||
%Include qgsserversettings.sip
|
||||
%Include qgsserver.sip
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
|
@ -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( "))" ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
|
@ -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:
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
}
|
@ -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
|
@ -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> ¶meters
|
||||
, 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
|
||||
|
@ -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
|
||||
);
|
||||
|
||||
|
@ -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> ¶meters
|
||||
, 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
|
||||
|
@ -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
|
||||
);
|
||||
|
||||
|
@ -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> ¶meters
|
||||
, 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();
|
||||
|
@ -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> ¶meters
|
||||
, 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 );
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
@ -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
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user