Skip to content

Commit

Permalink
[WFS provider] Add short-lived in-memory cache for DescribeFeatureTyp…
Browse files Browse the repository at this point in the history
…e and GetFeature COUNT=1 queries
  • Loading branch information
rouault committed Jan 3, 2023
1 parent d469574 commit 678d88a
Showing 1 changed file with 69 additions and 1 deletion.
70 changes: 69 additions & 1 deletion src/providers/wfs/qgsbasenetworkrequest.cpp
Expand Up @@ -22,12 +22,45 @@
#include "qgsapplication.h"
#include "qgsvariantutils.h"

#include <QCache>
#include <QEventLoop>
#include <QNetworkCacheMetaData>
#include <QCryptographicHash> // just for testing file:// fake_qgis_http_endpoint hack
#include <QFuture>
#include <QtConcurrent>

static QMutex gMemoryCacheMmutex;
static QCache<QUrl, std::pair<QDateTime, QByteArray>> gCache( 10 * 1024 * 1024 );

static QByteArray getFromMemoryCache( const QUrl &url )
{
QMutexLocker lock( &gMemoryCacheMmutex );
const std::pair<QDateTime, QByteArray> *entry = gCache.object( url );
if ( entry )
{
QgsSettings s;
const int delayOfCachingInSecs = s.value( QStringLiteral( "qgis/wfsMemoryCacheDelay" ), 60 ).toInt();
if ( entry->first.secsTo( QDateTime::currentDateTime() ) < delayOfCachingInSecs )
{
QgsDebugMsgLevel( QStringLiteral( "Reusing cached response from memory cache for %1" ).arg( url.toString() ), 4 );
return entry->second;
}
}
return QByteArray();
}

static void insertIntoMemoryCache( const QUrl &url, const QByteArray &response )
{
QMutexLocker lock( &gMemoryCacheMmutex );
if ( response.size() <= gCache.maxCost() )
{
std::pair<QDateTime, QByteArray> *entry = new std::pair<QDateTime, QByteArray>();
entry->first = QDateTime::currentDateTime();
entry->second = response;
gCache.insert( url, entry, response.size() );
}
}

QgsBaseNetworkRequest::QgsBaseNetworkRequest( const QgsAuthorizationSettings &auth, const QString &translatedComponent )
: mAuth( auth )
, mTranslatedComponent( translatedComponent )
Expand Down Expand Up @@ -58,6 +91,17 @@ bool QgsBaseNetworkRequest::sendGET( const QUrl &url, const QString &acceptHeade
mForceRefresh = forceRefresh;
mResponse.clear();

if ( synchronous )
{
mResponse = getFromMemoryCache( url );
if ( !mResponse.isEmpty() )
{
emit downloadProgress( mResponse.size(), mResponse.size() );
emit downloadFinished();
return true;
}
}

QUrl modifiedUrl( url );

// Specific code for testing
Expand Down Expand Up @@ -254,7 +298,31 @@ bool QgsBaseNetworkRequest::sendGET( const QUrl &url, const QString &acceptHeade
{
downloaderFunction();
}
return success && mErrorMessage.isEmpty();

if ( !success || !mErrorMessage.isEmpty() )
{
return false;
}

if ( synchronous )
{
// Insert response of requests GetCapabilities, DescribeFeatureType or GetFeature
// with a COUNT=1 into a short-lived memory cache, as they are emitted
// repeatedly in interactive scenarios when adding a WFS layer.
QString urlString = url.toString();
if ( urlString.contains( QStringLiteral( "REQUEST=GetCapabilities" ) ) ||
urlString.contains( QStringLiteral( "REQUEST=DescribeFeatureType" ) ) ||
( urlString.contains( QStringLiteral( "REQUEST=GetFeature" ) ) && urlString.contains( QStringLiteral( "COUNT=1" ) ) ) )
{
QgsSettings s;
if ( s.value( QStringLiteral( "qgis/wfsMemoryCacheAllowed" ), true ).toBool() )
{
insertIntoMemoryCache( url, mResponse );
}
}
}

return true;
}

bool QgsBaseNetworkRequest::sendPOST( const QUrl &url, const QString &contentTypeHeader, const QByteArray &data )
Expand Down

0 comments on commit 678d88a

Please sign in to comment.