Skip to content

Commit

Permalink
[Server][Feature][needs-docs] Using QByteArray in Cache Manager, fixi…
Browse files Browse the repository at this point in the history
…ng capabilities pointer and enhancing tests
  • Loading branch information
rldhont committed Aug 20, 2018
1 parent 9bd23b5 commit 066f84f
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 26 deletions.
7 changes: 7 additions & 0 deletions src/server/qgsservercachefilter.cpp
Expand Up @@ -54,3 +54,10 @@ bool QgsServerCacheFilter::deleteCachedDocument( const QgsProject *project, cons
Q_UNUSED( key );
return false;
}

//! Deletes all cached documents for a QGIS project
bool QgsServerCacheFilter::deleteCachedDocuments( const QgsProject *project ) const
{
Q_UNUSED( project );
return false;
}
7 changes: 7 additions & 0 deletions src/server/qgsservercachefilter.h
Expand Up @@ -80,6 +80,13 @@ class SERVER_EXPORT QgsServerCacheFilter
*/
virtual bool deleteCachedDocument( const QgsProject *project, const QgsServerRequest &request, const QString &key ) const;

/**
* Deletes all cached documents for a QGIS project
* \param project the project used to generate the document to provide path
* \returns true if the documents have been deleted
*/
virtual bool deleteCachedDocuments( const QgsProject *project ) const;

private:

//! The server interface
Expand Down
24 changes: 17 additions & 7 deletions src/server/qgsservercachemanager.cpp
Expand Up @@ -19,22 +19,18 @@
#include "qgsservercachemanager.h"

//! Returns cached document (or 0 if document not in cache) like capabilities
const QDomDocument *QgsServerCacheManager::getCachedDocument( const QgsProject *project, const QgsServerRequest &request, const QString &key ) const
QByteArray QgsServerCacheManager::getCachedDocument( const QgsProject *project, const QgsServerRequest &request, const QString &key ) const
{
QgsServerCacheFilterMap::const_iterator scIterator;
for ( scIterator = mPluginsServerCaches->constBegin(); scIterator != mPluginsServerCaches->constEnd(); ++scIterator )
{
QByteArray content = scIterator.value()->getCachedDocument( project, request, key );
if ( !content.isEmpty() )
{
QDomDocument doc;
if ( doc.setContent( content ) )
{
return &doc;
}
return content;
}
}
return nullptr;
return QByteArray();
}

//! Updates or inserts the document in cache like capabilities
Expand Down Expand Up @@ -65,6 +61,20 @@ bool QgsServerCacheManager::deleteCachedDocument( const QgsProject *project, con
return false;
}

//! Deletes all cached documents for a QGIS Project
bool QgsServerCacheManager::deleteCachedDocuments( const QgsProject *project ) const
{
QgsServerCacheFilterMap::const_iterator scIterator;
for ( scIterator = mPluginsServerCaches->constBegin(); scIterator != mPluginsServerCaches->constEnd(); ++scIterator )
{
if ( scIterator.value()->deleteCachedDocuments( project ) )
{
return true;
}
}
return false;
}

//! Register a new access control filter
void QgsServerCacheManager::registerServerCache( QgsServerCacheFilter *serverCache, int priority )
{
Expand Down
9 changes: 8 additions & 1 deletion src/server/qgsservercachemanager.h
Expand Up @@ -73,7 +73,7 @@ class SERVER_EXPORT QgsServerCacheManager
* \param key the key provided by the access control to identify differents documents for the same request
* \returns the cached document or 0 if no corresponding document found
*/
const QDomDocument *getCachedDocument( const QgsProject *project, const QgsServerRequest &request, const QString &key ) const;
QByteArray getCachedDocument( const QgsProject *project, const QgsServerRequest &request, const QString &key ) const;

/**
* Updates or inserts the document in cache like capabilities
Expand All @@ -94,6 +94,13 @@ class SERVER_EXPORT QgsServerCacheManager
*/
bool deleteCachedDocument( const QgsProject *project, const QgsServerRequest &request, const QString &key ) const;

/**
* Deletes all cached documents for a QGIS project
* \param project the project used to generate the document to provide path
* \returns true if the document has been deleted
*/
bool deleteCachedDocuments( const QgsProject *project ) const;

/**
* Register a server cache filter
* \param serverCache the server cache to add
Expand Down
16 changes: 13 additions & 3 deletions src/server/services/wcs/qgswcsgetcapabilities.cpp
Expand Up @@ -46,12 +46,17 @@ namespace QgsWcs

QDomDocument doc;
QString cacheKey = cacheKeyList.join( QStringLiteral( "-" ) );
const QDomDocument *capabilitiesDocument;
const QDomDocument *capabilitiesDocument = nullptr;

QgsServerCacheManager *cacheManager = serverIface->cacheManager();
if ( cacheManager && cache )
{
capabilitiesDocument = cacheManager->getCachedDocument( project, request, cacheKey );
QByteArray content = cacheManager->getCachedDocument( project, request, cacheKey );
if ( !content.isEmpty() && doc.setContent( content ) )
{
doc = doc.cloneNode().toDocument();
capabilitiesDocument = &doc;
}
}

if ( !capabilitiesDocument ) //capabilities xml not in cache. Create a new one
Expand All @@ -62,7 +67,12 @@ namespace QgsWcs
{
if ( cacheManager->setCachedDocument( &doc, project, request, cacheKey ) )
{
capabilitiesDocument = cacheManager->getCachedDocument( project, request, cacheKey );
QByteArray content = cacheManager->getCachedDocument( project, request, cacheKey );
if ( !content.isEmpty() && doc.setContent( content ) )
{
doc = doc.cloneNode().toDocument();
capabilitiesDocument = &doc;
}
}
}
if ( !capabilitiesDocument )
Expand Down
16 changes: 13 additions & 3 deletions src/server/services/wfs/qgswfsgetcapabilities.cpp
Expand Up @@ -50,12 +50,17 @@ namespace QgsWfs

QDomDocument doc;
QString cacheKey = cacheKeyList.join( QStringLiteral( "-" ) );
const QDomDocument *capabilitiesDocument;
const QDomDocument *capabilitiesDocument = nullptr;

QgsServerCacheManager *cacheManager = serverIface->cacheManager();
if ( cacheManager && cache )
{
capabilitiesDocument = cacheManager->getCachedDocument( project, request, cacheKey );
QByteArray content = cacheManager->getCachedDocument( project, request, cacheKey );
if ( !content.isEmpty() && doc.setContent( content ) )
{
doc = doc.cloneNode().toDocument();
capabilitiesDocument = &doc;
}
}

if ( !capabilitiesDocument ) //capabilities xml not in cache. Create a new one
Expand All @@ -66,7 +71,12 @@ namespace QgsWfs
{
if ( cacheManager->setCachedDocument( &doc, project, request, cacheKey ) )
{
capabilitiesDocument = cacheManager->getCachedDocument( project, request, cacheKey );
QByteArray content = cacheManager->getCachedDocument( project, request, cacheKey );
if ( !content.isEmpty() && doc.setContent( content ) )
{
doc = doc.cloneNode().toDocument();
capabilitiesDocument = &doc;
}
}
}
if ( !capabilitiesDocument )
Expand Down
16 changes: 13 additions & 3 deletions src/server/services/wfs/qgswfsgetcapabilities_1_0_0.cpp
Expand Up @@ -52,12 +52,17 @@ namespace QgsWfs

QDomDocument doc;
QString cacheKey = cacheKeyList.join( QStringLiteral( "-" ) );
const QDomDocument *capabilitiesDocument;
const QDomDocument *capabilitiesDocument = nullptr;

QgsServerCacheManager *cacheManager = serverIface->cacheManager();
if ( cacheManager && cache )
{
capabilitiesDocument = cacheManager->getCachedDocument( project, request, cacheKey );
QByteArray content = cacheManager->getCachedDocument( project, request, cacheKey );
if ( !content.isEmpty() && doc.setContent( content ) )
{
doc = doc.cloneNode().toDocument();
capabilitiesDocument = &doc;
}
}

if ( !capabilitiesDocument ) //capabilities xml not in cache. Create a new one
Expand All @@ -68,7 +73,12 @@ namespace QgsWfs
{
if ( cacheManager->setCachedDocument( &doc, project, request, cacheKey ) )
{
capabilitiesDocument = cacheManager->getCachedDocument( project, request, cacheKey );
QByteArray content = cacheManager->getCachedDocument( project, request, cacheKey );
if ( !content.isEmpty() && doc.setContent( content ) )
{
doc = doc.cloneNode().toDocument();
capabilitiesDocument = &doc;
}
}
}
if ( !capabilitiesDocument )
Expand Down
28 changes: 23 additions & 5 deletions src/server/services/wms/qgswmsgetcapabilities.cpp
Expand Up @@ -107,15 +107,27 @@ namespace QgsWms

QDomDocument doc;
QString cacheKey = cacheKeyList.join( QStringLiteral( "-" ) );
const QDomDocument *capabilitiesDocument;
const QDomDocument *capabilitiesDocument = nullptr;

QgsServerCacheManager *cacheManager = serverIface->cacheManager();
if ( cacheManager && cache )
{
QByteArray content;
if ( cacheKeyList.count() == 2 )
capabilitiesDocument = cacheManager->getCachedDocument( project, request, QStringLiteral( "" ) );
content = cacheManager->getCachedDocument( project, request, QStringLiteral( "" ) );
else if ( cacheKeyList.count() > 2 )
capabilitiesDocument = cacheManager->getCachedDocument( project, request, cacheKeyList.at( 3 ) );
content = cacheManager->getCachedDocument( project, request, cacheKeyList.at( 3 ) );

if ( !content.isEmpty() && doc.setContent( content ) )
{
QgsMessageLog::logMessage( QStringLiteral( "Found capabilities document in cache manager" ) );
doc = doc.cloneNode().toDocument();
capabilitiesDocument = &doc;
}
else
{
QgsMessageLog::logMessage( QStringLiteral( "Capabilities document not found in cache manager" ) );
}
}

if ( !capabilitiesDocument ) //capabilities xml not in cache plugins
Expand All @@ -130,15 +142,21 @@ namespace QgsWms
{
if ( cacheManager )
{
QByteArray content;
if ( cacheKeyList.count() == 2 &&
cacheManager->setCachedDocument( &doc, project, request, QStringLiteral( "" ) ) )
{
capabilitiesDocument = cacheManager->getCachedDocument( project, request, QStringLiteral( "" ) );
content = cacheManager->getCachedDocument( project, request, QStringLiteral( "" ) );
}
else if ( cacheKeyList.count() > 2 &&
cacheManager->setCachedDocument( &doc, project, request, cacheKeyList.at( 3 ) ) )
{
capabilitiesDocument = cacheManager->getCachedDocument( project, request, cacheKeyList.at( 3 ) );
content = cacheManager->getCachedDocument( project, request, cacheKeyList.at( 3 ) );
}
if ( !content.isEmpty() && doc.setContent( content ) )
{
doc = doc.cloneNode().toDocument();
capabilitiesDocument = &doc;
}
}
else
Expand Down
77 changes: 73 additions & 4 deletions tests/src/python/test_qgsserver_cachemanager.py
Expand Up @@ -26,7 +26,7 @@
from qgis.testing import unittest
from utilities import unitTestDataPath
from qgis.server import QgsServer, QgsServerCacheFilter, QgsServerRequest, QgsBufferServerRequest, QgsBufferServerResponse
from qgis.core import QgsApplication, QgsFontUtils
from qgis.core import QgsApplication, QgsFontUtils, QgsProject
from qgis.PyQt.QtCore import QFile, QByteArray
from qgis.PyQt.QtXml import QDomDocument

Expand Down Expand Up @@ -71,6 +71,22 @@ def setCachedDocument(self, doc, project, request, key):
f.write(doc.toString())
return os.path.exists(os.path.join(self._cache_dir, m.hexdigest() + ".xml"))

def deleteCachedDocument(self, project, request, key):
m = hashlib.md5()
paramMap = request.parameters()
urlParam = "&".join(["%s=%s" % (k, paramMap[k]) for k in paramMap.keys()])
m.update(urlParam.encode('utf8'))
if os.path.exists(os.path.join(self._cache_dir, m.hexdigest() + ".xml")):
os.remove(os.path.join(self._cache_dir, m.hexdigest() + ".xml"))
return not os.path.exists(os.path.join(self._cache_dir, m.hexdigest() + ".xml"))

def deleteCachedDocuments(self, project):
filelist = [f for f in os.listdir(self._cache_dir) if f.endswith(".xml")]
for f in filelist:
os.remove(os.path.join(self._cache_dir, f))
filelist = [f for f in os.listdir(self._cache_dir) if f.endswith(".xml")]
return len(filelist) == 0


class TestQgsServerCacheManager(unittest.TestCase):

Expand Down Expand Up @@ -101,9 +117,7 @@ def setUpClass(cls):
@classmethod
def tearDownClass(cls):
"""Run after all tests"""
filelist = [f for f in os.listdir(cls._servercache._cache_dir) if f.endswith(".xml")]
for f in filelist:
os.remove(os.path.join(cls._servercache._cache_dir, f))
#cls._servercache.deleteCachedDocuments(None)
del cls._server
cls._app.exitQgis

Expand Down Expand Up @@ -140,14 +154,69 @@ def test_getcapabilities(self):
project = self._project_path
assert os.path.exists(project), "Project file not found: " + project

# without cache
query_string = '?MAP=%s&SERVICE=WMS&VERSION=1.3.0&REQUEST=%s' % (urllib.parse.quote(project), 'GetCapabilities')
header, body = self._execute_request(query_string)
doc = QDomDocument("wms_getcapabilities_130.xml")
doc.setContent(body)
# with cache
header, body = self._execute_request(query_string)

# without cache
query_string = '?MAP=%s&SERVICE=WMS&VERSION=1.1.1&REQUEST=%s' % (urllib.parse.quote(project), 'GetCapabilities')
header, body = self._execute_request(query_string)
# with cache
header, body = self._execute_request(query_string)

# without cache
query_string = '?MAP=%s&SERVICE=WFS&VERSION=1.1.0&REQUEST=%s' % (urllib.parse.quote(project), 'GetCapabilities')
header, body = self._execute_request(query_string)
# with cache
header, body = self._execute_request(query_string)

# without cache
query_string = '?MAP=%s&SERVICE=WFS&VERSION=1.0.0&REQUEST=%s' % (urllib.parse.quote(project), 'GetCapabilities')
header, body = self._execute_request(query_string)
# with cache
header, body = self._execute_request(query_string)

# without cache
query_string = '?MAP=%s&SERVICE=WCS&VERSION=1.0.0&REQUEST=%s' % (urllib.parse.quote(project), 'GetCapabilities')
header, body = self._execute_request(query_string)
# with cache
header, body = self._execute_request(query_string)

filelist = [f for f in os.listdir(self._servercache._cache_dir) if f.endswith(".xml")]
self.assertEqual(len(filelist), 5, 'Not enough file in cache')

cacheManager = self._server_iface.cacheManager()

self.assertTrue(cacheManager.deleteCachedDocuments(None), 'deleteCachedDocuments does not retrun True')

filelist = [f for f in os.listdir(self._servercache._cache_dir) if f.endswith(".xml")]
self.assertEqual(len(filelist), 0, 'All files in cache are not deleted ')

prj = QgsProject()
prj.read(project)

query_string = '?MAP=%s&SERVICE=WMS&VERSION=1.3.0&REQUEST=%s' % (urllib.parse.quote(project), 'GetCapabilities')
request = QgsBufferServerRequest(query_string, QgsServerRequest.GetMethod, {}, None)

cContent = cacheManager.getCachedDocument(prj, request, '')

self.assertTrue(cContent.isEmpty(), 'getCachedDocument is not None')

self.assertTrue(cacheManager.setCachedDocument(doc, prj, request, ''), 'setCachedDocument false')

cContent = cacheManager.getCachedDocument(prj, request, '')

self.assertFalse(cContent.isEmpty(), 'getCachedDocument is empty')

cDoc = QDomDocument("wms_getcapabilities_130.xml")
self.assertTrue(cDoc.setContent(cContent), 'cachedDocument not XML doc')
self.assertEqual(doc.documentElement().tagName(), cDoc.documentElement().tagName(), 'cachedDocument not equal to provide document')

self.assertTrue(cacheManager.deleteCachedDocuments(None), 'deleteCachedDocuments does not retrun True')


if __name__ == "__main__":
Expand Down

0 comments on commit 066f84f

Please sign in to comment.