Skip to content

Commit

Permalink
server: make capabilities cache size configurable and add a note when…
Browse files Browse the repository at this point in the history
… all slots are taken
  • Loading branch information
jef-n committed Mar 29, 2023
1 parent 7136793 commit 715f043
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 10 deletions.
2 changes: 1 addition & 1 deletion python/server/auto_generated/qgscapabilitiescache.sip.in
Expand Up @@ -20,7 +20,7 @@ A cache for capabilities xml documents (by configuration file path)
#include "qgscapabilitiescache.h"
%End
public:
QgsCapabilitiesCache();
QgsCapabilitiesCache( int size );

const QDomDocument *searchCapabilitiesDocument( const QString &configFilePath, const QString &key );
%Docstring
Expand Down
10 changes: 10 additions & 0 deletions python/server/auto_generated/qgsserversettings.sip.in
Expand Up @@ -64,6 +64,7 @@ Provides some enum describing the environment currently supported for configurat
QGIS_SERVER_PROJECT_CACHE_STRATEGY,
QGIS_SERVER_ALLOWED_EXTRA_SQL_TOKENS,
QGIS_SERVER_APPLICATION_NAME,
QGIS_SERVER_CAPABILITIES_CACHE_SIZE,
};
};

Expand Down Expand Up @@ -357,6 +358,15 @@ by setting the environment variable QGIS_SERVER_APPLICATION_NAME.
Returns the string representation of a setting.

.. versionadded:: 3.16
%End

int capabilitiesCacheSize() const;
%Docstring
Returns the maximum number of project capabilities to cache.
The default value is 40 and the value can be changed
by setting the environment variable QGIS_SERVER_CAPABILITIES_CACHE_SIZE.

.. versionadded:: 3.31
%End

};
Expand Down
8 changes: 6 additions & 2 deletions src/server/qgscapabilitiescache.cpp
Expand Up @@ -25,9 +25,11 @@
#endif

#include "qgslogger.h"
#include "qgsserversettings.h"
#include "qgsmessagelog.h"


QgsCapabilitiesCache::QgsCapabilitiesCache()
QgsCapabilitiesCache::QgsCapabilitiesCache( int size ): mCacheSize( size )
{
QObject::connect( &mFileSystemWatcher, &QFileSystemWatcher::fileChanged, this, &QgsCapabilitiesCache::removeChangedEntry );

Expand All @@ -52,12 +54,14 @@ const QDomDocument *QgsCapabilitiesCache::searchCapabilitiesDocument( const QStr

void QgsCapabilitiesCache::insertCapabilitiesDocument( const QString &configFilePath, const QString &key, const QDomDocument *doc )
{
if ( mCachedCapabilities.size() > 40 )
if ( mCachedCapabilities.size() > mCacheSize )
{
//remove another cache entry to avoid memory problems
const QHash<QString, QHash<QString, QDomDocument> >::iterator capIt = mCachedCapabilities.begin();
mFileSystemWatcher.removePath( capIt.key() );
mCachedCapabilities.erase( capIt );

QgsMessageLog::logMessage( QStringLiteral( "Removed cached WMS capabilities document because all %1 cache slots were taken" ).arg( mCacheSize ), QStringLiteral( "Server" ) );
}

if ( !mCachedCapabilities.contains( configFilePath ) )
Expand Down
4 changes: 3 additions & 1 deletion src/server/qgscapabilitiescache.h
Expand Up @@ -26,6 +26,7 @@
#include <QTimer>

#include "qgis_server.h"
#include "qgsserversettings.h"

/**
* \ingroup server
Expand All @@ -35,7 +36,7 @@ class SERVER_EXPORT QgsCapabilitiesCache : public QObject
{
Q_OBJECT
public:
QgsCapabilitiesCache();
QgsCapabilitiesCache( int size );

/**
* Returns cached capabilities document (or 0 if document for configuration file not in cache)
Expand Down Expand Up @@ -64,6 +65,7 @@ class SERVER_EXPORT QgsCapabilitiesCache : public QObject
QHash< QString, QDateTime> mCachedCapabilitiesTimestamps;
QFileSystemWatcher mFileSystemWatcher;
QTimer mTimer;
int mCacheSize;

private slots:
//! Removes changed entry from this cache
Expand Down
2 changes: 1 addition & 1 deletion src/server/qgsserver.cpp
Expand Up @@ -352,7 +352,7 @@ bool QgsServer::init()
sConfigFilePath = new QString( defaultConfigFilePath );

//create cache for capabilities XML
sCapabilitiesCache = new QgsCapabilitiesCache();
sCapabilitiesCache = new QgsCapabilitiesCache( sSettings()->capabilitiesCacheSize() );

QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Roman" ) << QStringLiteral( "Bold" ) );

Expand Down
20 changes: 20 additions & 0 deletions src/server/qgsserversettings.cpp
Expand Up @@ -389,6 +389,15 @@ void QgsServerSettings::initSettings()
};
mSettings[ sApplicationName.envVar ] = sApplicationName;

const Setting sCapabilitiesCacheSize = { QgsServerSettingsEnv::QGIS_SERVER_CAPABILITIES_CACHE_SIZE,
QgsServerSettingsEnv::DEFAULT_VALUE,
QStringLiteral( "The QGIS Server capabilities cache size" ),
QStringLiteral( "/qgis/capabilities_cache_size" ),
QVariant::Int,
QVariant( 40 ),
QVariant()
};
mSettings[ sCapabilitiesCacheSize.envVar ] = sCapabilitiesCacheSize;
}

void QgsServerSettings::load()
Expand Down Expand Up @@ -709,3 +718,14 @@ QString QgsServerSettings::applicationName() const
{
return value( QgsServerSettingsEnv::QGIS_SERVER_APPLICATION_NAME ).toString().trimmed();
}

int QgsServerSettings::capabilitiesCacheSize() const
{
bool ok;
int size = value( QgsServerSettingsEnv::QGIS_SERVER_CAPABILITIES_CACHE_SIZE ).toInt( &ok );
if ( ok && size >= 1 )
return size;

QgsMessageLog::logMessage( QStringLiteral( "Invalid capabilities cache size, expecting integer - defaulting to 40" ), "Server", Qgis::MessageLevel::Warning );
return 40;
}
10 changes: 10 additions & 0 deletions src/server/qgsserversettings.h
Expand Up @@ -82,6 +82,7 @@ class SERVER_EXPORT QgsServerSettingsEnv : public QObject
QGIS_SERVER_PROJECT_CACHE_STRATEGY, //! Set the project cache strategy. Possible values are 'filesystem', 'periodic' or 'off' (since QGIS 3.26).
QGIS_SERVER_ALLOWED_EXTRA_SQL_TOKENS, //! Adds these tokens to the list of allowed tokens that the services accept when filtering features (since QGIS 3.28).
QGIS_SERVER_APPLICATION_NAME, //! Define the QGIS Server application name (since QGIS 3.30).
QGIS_SERVER_CAPABILITIES_CACHE_SIZE, //! Define the QGIS Server capabilities cache size (since QGIS 3.31)
};
Q_ENUM( EnvVar )
};
Expand Down Expand Up @@ -356,6 +357,15 @@ class SERVER_EXPORT QgsServerSettings
*/
static QString name( QgsServerSettingsEnv::EnvVar env );

/**
* Returns the maximum number of project capabilities to cache.
* The default value is 40 and the value can be changed
* by setting the environment variable QGIS_SERVER_CAPABILITIES_CACHE_SIZE.
*
* \since QGIS 3.31
*/
int capabilitiesCacheSize() const;

private:
void initSettings();
QVariant value( QgsServerSettingsEnv::EnvVar envVar, bool actual = false ) const;
Expand Down
2 changes: 1 addition & 1 deletion tests/src/server/wfs/test_qgsserver_wfs_getfeature.cpp
Expand Up @@ -51,9 +51,9 @@ void TestQgsServerWfsGetFeature::cleanupTestCase()
void TestQgsServerWfsGetFeature::nullValueProperty()
{
// init server iface
QgsCapabilitiesCache cache;
QgsServiceRegistry registry;
QgsServerSettings settings;
QgsCapabilitiesCache cache( settings.capabilitiesCacheSize() );
QgsServerInterfaceImpl interface( &cache, &registry, &settings );

// init project
Expand Down
4 changes: 2 additions & 2 deletions tests/src/server/wms/test_qgsserver_wms_dxf.cpp
Expand Up @@ -73,9 +73,9 @@ void TestQgsServerWmsDxf::use_title_as_layername_true()
QgsMapLayer *layer = project.layerStore()->mapLayersByName( "testlayer èé" )[0];
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );

QgsCapabilitiesCache cache;
QgsServiceRegistry registry;
QgsServerSettings settings;
QgsCapabilitiesCache cache( settings.capabilitiesCacheSize() );
QgsServerInterfaceImpl interface( &cache, &registry, &settings );

QgsWms::QgsWmsRenderContext context( &project, &interface );
Expand Down Expand Up @@ -121,9 +121,9 @@ void TestQgsServerWmsDxf::use_title_as_layername_false()
QgsMapLayer *layer = project.layerStore()->mapLayersByName( "testlayer èé" )[0];
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );

QgsCapabilitiesCache cache;
QgsServiceRegistry registry;
QgsServerSettings settings;
QgsCapabilitiesCache cache( settings.capabilitiesCacheSize() );
QgsServerInterfaceImpl interface( &cache, &registry, &settings );

QgsWms::QgsWmsRenderContext context( &project, &interface );
Expand Down
2 changes: 1 addition & 1 deletion tests/src/server/wms/test_qgsserver_wms_restorer.cpp
Expand Up @@ -57,9 +57,9 @@ void TestQgsServerWmsRestorer::restorer_layer()
const QgsWms::QgsWmsParameters parameters( query );

// init context
QgsCapabilitiesCache cache;
QgsServiceRegistry registry;
QgsServerSettings settings;
QgsCapabilitiesCache cache( settings.capabilitiesCacheSize() );
QgsServerInterfaceImpl interface( &cache, &registry, &settings );

QgsWms::QgsWmsRenderContext context( &project, &interface );
Expand Down
2 changes: 1 addition & 1 deletion tests/src/server/wms/test_qgsserver_wms_vector_tile.cpp
Expand Up @@ -71,9 +71,9 @@ void TestQgsServerWmsVectorTile::opacity()
const QgsWms::QgsWmsParameters parameters( query );

// init wms renderer
QgsCapabilitiesCache cache;
QgsServiceRegistry registry;
QgsServerSettings settings;
QgsCapabilitiesCache cache( settings.capabilitiesCacheSize() );
QgsServerInterfaceImpl interface( &cache, &registry, &settings );

QgsWms::QgsWmsRenderContext context( &project, &interface );
Expand Down

0 comments on commit 715f043

Please sign in to comment.