Skip to content

Commit 350a2b5

Browse files
authored
Merge pull request #3886 from pblottiere/servermultithread
[server] parallel map rendering
2 parents 590a981 + f7729b3 commit 350a2b5

26 files changed

+1055
-78
lines changed

python/server/qgsserversettings.sip

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/***************************************************************************
2+
qgsserversettings.sip
3+
---------------------
4+
begin : December 19, 2016
5+
copyright : (C) 2016 by Paul Blottiere
6+
email : paul dot blottiere at oslandia dot com
7+
8+
***************************************************************************/
9+
10+
/***************************************************************************
11+
* *
12+
* This program is free software; you can redistribute it and/or modify *
13+
* it under the terms of the GNU General Public License as published by *
14+
* the Free Software Foundation; either version 2 of the License, or *
15+
* (at your option) any later version. *
16+
* *
17+
***************************************************************************/
18+
19+
20+
/** \ingroup server
21+
* QgsServerSettings provides a way to retrieve settings by prioritizing
22+
* according to environment variables, ini file and default values.
23+
* @note added in QGIS 3.0
24+
*/
25+
class QgsServerSettings
26+
{
27+
%TypeHeaderCode
28+
#include "qgsserversettings.h"
29+
%End
30+
31+
public:
32+
/** Constructor.
33+
*/
34+
QgsServerSettings();
35+
36+
/** Load settings according to current environment variables.
37+
*/
38+
void load();
39+
40+
/** Log a summary of settings curently loaded.
41+
*/
42+
void logSummary() const;
43+
44+
/** Returns the ini file loaded by QSetting.
45+
* @return the path of the ini file or an empty string if none is loaded.
46+
*/
47+
QString iniFile() const;
48+
49+
/** Returns the maximum number of threads to use.
50+
* @return the number of threads.
51+
*/
52+
int maxThreads() const;
53+
54+
/** Returns parallel rendering setting.
55+
* @return true if parallel rendering is activated, false otherwise.
56+
*/
57+
bool parallelRendering() const;
58+
59+
/** Returns the log level.
60+
* @return the log level.
61+
*/
62+
QgsMessageLog::MessageLevel logLevel() const;
63+
64+
/** Returns the log file.
65+
* @return the path of the log file or an empty string if none is defined.
66+
*/
67+
QString logFile() const;
68+
69+
/** Returns the QGS project file to use.
70+
* @return the path of the QGS project or an empty string if none is defined.
71+
*/
72+
QString projectFile() const;
73+
74+
/**
75+
* Returns the maximum number of cached layers.
76+
* @return the number of cached layers.
77+
*/
78+
int maxCacheLayers() const;
79+
80+
/** Returns the cache size.
81+
* @return the cache size.
82+
*/
83+
qint64 cacheSize() const;
84+
85+
/** Returns the cache directory.
86+
* @return the directory.
87+
*/
88+
QString cacheDirectory() const;
89+
};

python/server/server.sip

+1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@
2727
%Include qgswmsprojectparser.sip
2828
%Include qgswfsprojectparser.sip
2929
%Include qgsconfigcache.sip
30+
%Include qgsserversettings.sip
3031
%Include qgsserver.sip

src/server/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ SET ( qgis_mapserv_SRCS
2929
qgswmsserver.cpp
3030
qgswfsserver.cpp
3131
qgswcsserver.cpp
32+
qgsserversettings.cpp
3233
qgsmapserviceexception.cpp
3334
qgsmslayercache.cpp
3435
qgsmslayerbuilder.cpp
@@ -67,6 +68,7 @@ SET (qgis_mapserv_MOC_HDRS
6768
# qgshttptransaction.h
6869
qgsmslayercache.h
6970
qgsserverlogger.h
71+
qgsserversettings.h
7072
qgsserverstreamingdevice.h
7173
)
7274

src/server/qgsaccesscontrol.cpp

+41-3
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,25 @@
2222

2323
#include <QStringList>
2424

25+
void QgsAccessControl::resolveFilterFeatures( const QList<QgsMapLayer*> &layers )
26+
{
27+
Q_FOREACH ( QgsMapLayer* l, layers )
28+
{
29+
if ( l->type() == QgsMapLayer::LayerType::VectorLayer )
30+
{
31+
const QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( l );
32+
mFilterFeaturesExpressions[vl->id()] = resolveFilterFeatures( vl );
33+
}
34+
}
2535

26-
//! Filter the features of the layer
27-
void QgsAccessControl::filterFeatures( const QgsVectorLayer* layer, QgsFeatureRequest& featureRequest ) const
36+
mResolved = true;
37+
}
38+
39+
QString QgsAccessControl::resolveFilterFeatures( const QgsVectorLayer* layer ) const
2840
{
2941
QStringList expressions = QStringList();
3042
QgsAccessControlFilterMap::const_iterator acIterator;
43+
3144
for ( acIterator = mPluginsAccessControls->constBegin(); acIterator != mPluginsAccessControls->constEnd(); ++acIterator )
3245
{
3346
QString expression = acIterator.value()->layerFilterExpression( layer );
@@ -36,9 +49,34 @@ void QgsAccessControl::filterFeatures( const QgsVectorLayer* layer, QgsFeatureRe
3649
expressions.append( expression );
3750
}
3851
}
52+
53+
QString expression;
3954
if ( !expressions.isEmpty() )
4055
{
41-
featureRequest.setFilterExpression( QStringLiteral( "((" ).append( expressions.join( QStringLiteral( ") AND (" ) ) ).append( "))" ) );
56+
expression = QStringLiteral( "((" ).append( expressions.join( QStringLiteral( ") AND (" ) ) ).append( "))" );
57+
}
58+
59+
return expression;
60+
}
61+
62+
//! Filter the features of the layer
63+
void QgsAccessControl::filterFeatures( const QgsVectorLayer* layer, QgsFeatureRequest& featureRequest ) const
64+
{
65+
66+
QString expression;
67+
68+
if ( mResolved && mFilterFeaturesExpressions.keys().contains( layer->id() ) )
69+
{
70+
expression = mFilterFeaturesExpressions[layer->id()];
71+
}
72+
else
73+
{
74+
expression = resolveFilterFeatures( layer );
75+
}
76+
77+
if ( !expression.isEmpty() )
78+
{
79+
featureRequest.setFilterExpression( expression );
4280
}
4381
}
4482

src/server/qgsaccesscontrol.h

+13
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@ class SERVER_EXPORT QgsAccessControl : public QgsFeatureFilterProvider
4040
QgsAccessControl()
4141
{
4242
mPluginsAccessControls = new QgsAccessControlFilterMap();
43+
mResolved = false;
4344
}
4445

4546
//! Constructor
4647
QgsAccessControl( const QgsAccessControl& copy )
4748
{
4849
mPluginsAccessControls = new QgsAccessControlFilterMap( *copy.mPluginsAccessControls );
50+
mFilterFeaturesExpressions = copy.mFilterFeaturesExpressions;
51+
mResolved = copy.mResolved;
4952
}
5053

5154

@@ -54,6 +57,11 @@ class SERVER_EXPORT QgsAccessControl : public QgsFeatureFilterProvider
5457
delete mPluginsAccessControls;
5558
}
5659

60+
/** Resolve features' filter of layers
61+
* @param layers to filter
62+
*/
63+
void resolveFilterFeatures( const QList<QgsMapLayer*> &layers );
64+
5765
/** Filter the features of the layer
5866
* @param layer the layer to control
5967
* @param filterFeatures the request to fill
@@ -122,8 +130,13 @@ class SERVER_EXPORT QgsAccessControl : public QgsFeatureFilterProvider
122130
void registerAccessControl( QgsAccessControlFilter* accessControl, int priority = 0 );
123131

124132
private:
133+
QString resolveFilterFeatures( const QgsVectorLayer* layer ) const;
134+
125135
//! The AccessControl plugins registry
126136
QgsAccessControlFilterMap* mPluginsAccessControls;
137+
138+
QMap<QString, QString> mFilterFeaturesExpressions;
139+
bool mResolved;
127140
};
128141

129142
#endif

src/server/qgsmslayercache.cpp

+7-13
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "qgsmaplayer.h"
2222
#include "qgsvectorlayer.h"
2323
#include "qgslogger.h"
24+
#include "qgsserversettings.h"
2425
#include <QFile>
2526

2627
QgsMSLayerCache* QgsMSLayerCache::instance()
@@ -32,20 +33,8 @@ QgsMSLayerCache* QgsMSLayerCache::instance()
3233
}
3334

3435
QgsMSLayerCache::QgsMSLayerCache()
35-
: mProjectMaxLayers( 0 )
36+
: mProjectMaxLayers( 100 )
3637
{
37-
mDefaultMaxLayers = 100;
38-
//max layer from environment variable overrides default
39-
char* maxLayerEnv = getenv( "MAX_CACHE_LAYERS" );
40-
if ( maxLayerEnv )
41-
{
42-
bool conversionOk = false;
43-
int maxLayerInt = QString( maxLayerEnv ).toInt( &conversionOk );
44-
if ( conversionOk )
45-
{
46-
mDefaultMaxLayers = maxLayerInt;
47-
}
48-
}
4938
QObject::connect( &mFileSystemWatcher, SIGNAL( fileChanged( const QString& ) ), this, SLOT( removeProjectFileLayers( const QString& ) ) );
5039
}
5140

@@ -59,6 +48,11 @@ QgsMSLayerCache::~QgsMSLayerCache()
5948
mEntries.clear();
6049
}
6150

51+
void QgsMSLayerCache::setMaxCacheLayers( int maxCacheLayers )
52+
{
53+
mDefaultMaxLayers = maxCacheLayers;
54+
}
55+
6256
void QgsMSLayerCache::insertLayer( const QString& url, const QString& layerName, QgsMapLayer* layer, const QString& configFile, const QList<QString>& tempFiles )
6357
{
6458
QgsMessageLog::logMessage( "Layer cache: insert Layer '" + layerName + "' configFile: " + configFile, QStringLiteral( "Server" ), QgsMessageLog::INFO );

src/server/qgsmslayercache.h

+7
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ class QgsMSLayerCache: public QObject
5656
static QgsMSLayerCache* instance();
5757
~QgsMSLayerCache();
5858

59+
/**
60+
* Set the maximum number of layers in cache.
61+
* @param maxCacheLayers the number of layers in cache
62+
* @note added in QGIS 3.0
63+
*/
64+
void setMaxCacheLayers( int maxCacheLayers );
65+
5966
/** Inserts a new layer into the cash
6067
@param url the layer datasource
6168
@param layerName the layer name (to distinguish between different layers in a request using the same datasource

src/server/qgsowsserver.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define QGSOWSSERVER_H
2020

2121
#include "qgsrequesthandler.h"
22+
#include "qgsserversettings.h"
2223
#ifdef HAVE_SERVER_PYTHON_PLUGINS
2324
#include "qgsaccesscontrol.h"
2425
#endif
@@ -32,13 +33,15 @@ class QgsOWSServer
3233
public:
3334
QgsOWSServer(
3435
const QString& configFilePath
36+
, const QgsServerSettings& settings
3537
, const QMap<QString, QString>& parameters
3638
, QgsRequestHandler* rh
3739
#ifdef HAVE_SERVER_PYTHON_PLUGINS
38-
, const QgsAccessControl* ac
40+
, QgsAccessControl* ac
3941
#endif
4042
)
41-
: mParameters( parameters )
43+
: mSettings( settings )
44+
, mParameters( parameters )
4245
, mRequestHandler( rh )
4346
, mConfigFilePath( configFilePath )
4447
#ifdef HAVE_SERVER_PYTHON_PLUGINS
@@ -58,12 +61,13 @@ class QgsOWSServer
5861
QgsOWSServer() {}
5962

6063
protected:
64+
QgsServerSettings mSettings;
6165
QMap<QString, QString> mParameters;
6266
QgsRequestHandler* mRequestHandler;
6367
QString mConfigFilePath;
6468
#ifdef HAVE_SERVER_PYTHON_PLUGINS
6569
//! The access control helper
66-
const QgsAccessControl* mAccessControl;
70+
QgsAccessControl* mAccessControl;
6771

6872
/** Apply filter strings from the access control to the layers.
6973
* @param layer the concerned layer

0 commit comments

Comments
 (0)