Skip to content

Commit

Permalink
Move tile cache to a new file
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Sep 9, 2016
1 parent 02a9211 commit 267f263
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 35 deletions.
1 change: 1 addition & 0 deletions src/providers/wms/CMakeLists.txt
Expand Up @@ -9,6 +9,7 @@ SET (WMS_SRCS
qgswmssourceselect.cpp
qgswmsconnection.cpp
qgswmsdataitems.cpp
qgstilecache.cpp
qgstilescalewidget.cpp
qgswmtsdimensions.cpp
qgsxyzconnection.cpp
Expand Down
57 changes: 57 additions & 0 deletions src/providers/wms/qgstilecache.cpp
@@ -0,0 +1,57 @@
/***************************************************************************
qgstilecache.h
--------------------------------------
Date : September 2016
Copyright : (C) 2016 by Martin Dobias
Email : wonder dot sk at gmail 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 "qgstilecache.h"

#include "qgsnetworkaccessmanager.h"

#include <QAbstractNetworkCache>
#include <QImage>

QCache<QUrl, QImage> QgsTileCache::sTileCache( 256 );
QMutex QgsTileCache::sTileCacheMutex;


void QgsTileCache::insertTile( const QUrl& url, const QImage& image )
{
QMutexLocker locker( &sTileCacheMutex );
sTileCache.insert( url, new QImage( image ) );
}

bool QgsTileCache::tile( const QUrl& url, QImage& image )
{
QMutexLocker locker( &sTileCacheMutex );
if ( QImage* i = sTileCache.object( url ) )
{
image = *i;
return true;
}
else if ( QgsNetworkAccessManager::instance()->cache()->metaData( url ).isValid() )
{
if ( QIODevice* data = QgsNetworkAccessManager::instance()->cache()->data( url ) )
{
QByteArray imageData = data->readAll();
delete data;

image = QImage::fromData( imageData );

// cache it as well (mutex is already locked)
sTileCache.insert( url, new QImage( image ) );

return true;
}
}
return false;
}
56 changes: 56 additions & 0 deletions src/providers/wms/qgstilecache.h
@@ -0,0 +1,56 @@
/***************************************************************************
qgstilecache.h
--------------------------------------
Date : September 2016
Copyright : (C) 2016 by Martin Dobias
Email : wonder dot sk at gmail 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 QGSTILECACHE_H
#define QGSTILECACHE_H


#include <QCache>
#include <QMutex>

class QImage;
class QUrl;

/** A simple tile cache implementation. Tiles are cached according to their URL.
* There is a small in-memory cache and a secondary caching in the local disk.
* The in-memory cache is there to save CPU time otherwise wasted to read and
* uncompress data saved on the disk.
*
* The class is thread safe (its methods can be called from any thread).
*/
class QgsTileCache
{
public:

//! Add a tile image with given URL to the cache
static void insertTile( const QUrl& url, const QImage& image );

//! Try to access a tile and load it into "image" argument
//! @returns true if the tile exists in the cache
static bool tile( const QUrl& url, QImage& image );

//! how many tiles are stored in the in-memory cache
static int totalCost() { return sTileCache.totalCost(); }
//! how many tiles can be stored in the in-memory cache
static int maxCost() { return sTileCache.maxCost(); }

private:
//! in-memory cache
static QCache<QUrl, QImage> sTileCache;
//! mutex to protect the in-memory cache
static QMutex sTileCacheMutex;
};

#endif // QGSTILECACHE_H
40 changes: 5 additions & 35 deletions src/providers/wms/qgswmsprovider.cpp
Expand Up @@ -40,6 +40,7 @@
#include "qgsmessagelog.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsnetworkreplyparser.h"
#include "qgstilecache.h"
#include "qgsgml.h"
#include "qgsgmlschema.h"
#include "qgswmscapabilities.h"
Expand Down Expand Up @@ -501,35 +502,6 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, in
return draw( viewExtent, pixelWidth, pixelHeight, nullptr );
}

#include <QCache>
static QCache<QUrl, QImage> sTileCache( 256 );
static QMutex sTileCacheMutex;

static bool _fetchCachedTileImage( const QUrl& url, QImage& localImage )
{
QMutexLocker locker( &sTileCacheMutex );
if ( QImage* i = sTileCache.object( url ) )
{
localImage = *i;
return true;
}
else if ( QgsNetworkAccessManager::instance()->cache()->metaData( url ).isValid() )
{
if ( QIODevice* data = QgsNetworkAccessManager::instance()->cache()->data( url ) )
{
QByteArray imageData = data->readAll();
delete data;

localImage = QImage::fromData( imageData );

// cache it as well (mutex is already locked)
sTileCache.insert( url, new QImage( localImage ) );

return true;
}
}
return false;
}

static bool _fuzzyContainsRect( const QRectF& r1, const QRectF& r2 )
{
Expand Down Expand Up @@ -581,7 +553,7 @@ void QgsWmsProvider::fetchOtherResTiles( QgsTileMode tileMode, const QgsRectangl
Q_FOREACH ( const TileRequest& r, requests )
{
QImage localImage;
if ( !_fetchCachedTileImage( r.url, localImage ) )
if ( ! QgsTileCache::tile( r.url, localImage ) )
continue;

double cr = viewExtent.width() / imageWidth;
Expand Down Expand Up @@ -785,7 +757,7 @@ QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, i
Q_FOREACH ( const TileRequest& r, requests )
{
QImage localImage;
if ( _fetchCachedTileImage( r.url, localImage ) )
if ( QgsTileCache::tile( r.url, localImage ) )
{
double cr = viewExtent.width() / image->width();

Expand Down Expand Up @@ -880,7 +852,7 @@ QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, i
handler.downloadBlocking();
}

qDebug( "TILE CACHE total: %d / %d ", sTileCache.totalCost(), sTileCache.maxCost() );
qDebug( "TILE CACHE total: %d / %d ", QgsTileCache::totalCost(), QgsTileCache::maxCost() );

#if 0
const QgsWmsStatistics::Stat& stat = QgsWmsStatistics::statForUri( dataSourceUri() );
Expand Down Expand Up @@ -3909,9 +3881,7 @@ void QgsWmsTiledImageDownloadHandler::tileReplyFinished()
.arg( r.width() ).arg( r.height() ) );
#endif

sTileCacheMutex.lock();
sTileCache.insert( reply->url(), new QImage( myLocalImage ) );
sTileCacheMutex.unlock();
QgsTileCache::insertTile( reply->url(), myLocalImage );

if ( mFeedback )
mFeedback->onNewData();
Expand Down

0 comments on commit 267f263

Please sign in to comment.