25#include <QStorageInfo>
27#include "moc_qgsnetworkdiskcache.cpp"
30ExpirableNetworkDiskCache QgsNetworkDiskCache::sDiskCache;
32QMutex QgsNetworkDiskCache::sDiskCacheMutex;
34QHash<QUrl, QVariantMap> QgsNetworkDiskCache::sPendingRequestHeaders;
36QgsNetworkDiskCache::QgsNetworkDiskCache( QObject *parent )
37 : QNetworkDiskCache( parent )
42 const QMutexLocker lock( &sDiskCacheMutex );
43 sPendingRequestHeaders.insert( url, headers );
48 const QMutexLocker lock( &sDiskCacheMutex );
49 return sPendingRequestHeaders.contains( url );
54 const QMutexLocker lock( &sDiskCacheMutex );
55 sPendingRequestHeaders.remove( url );
61 const QNetworkCacheMetaData cachedMetadata =
metaData( request.url() );
62 if ( !cachedMetadata.isValid() )
66 const QNetworkCacheMetaData::RawHeaderList rawHeaders = cachedMetadata.rawHeaders();
67 for (
const QNetworkCacheMetaData::RawHeader &cachedHeader : rawHeaders )
69 if ( cachedHeader.first.compare(
"vary", Qt::CaseInsensitive ) == 0 )
71 const QString varyValue = QString::fromUtf8( cachedHeader.second ).trimmed();
74 if ( varyValue ==
'*' )
81 const QStringList varyHeaderNames = varyValue.split(
',' );
82 for (
const QString &headerName : varyHeaderNames )
84 const QString normalizedHeaderName = headerName.trimmed().toLower();
85 const QByteArray currentHeaderValue = request.rawHeader( normalizedHeaderName.toUtf8() );
86 const QByteArray originalCachedHeaderValue = originalCachedHeaders.value( normalizedHeaderName ).toByteArray();
87 if ( currentHeaderValue != originalCachedHeaderValue )
102 const QMutexLocker lock( &sDiskCacheMutex );
103 return sDiskCache.cacheDirectory();
108 const QMutexLocker lock( &sDiskCacheMutex );
109 sDiskCache.setCacheDirectory( cacheDir );
114 const QMutexLocker lock( &sDiskCacheMutex );
115 return sDiskCache.maximumCacheSize();
120 const QMutexLocker lock( &sDiskCacheMutex );
128 sDiskCache.setMaximumCacheSize( size );
133 const QMutexLocker lock( &sDiskCacheMutex );
134 return sDiskCache.cacheSize();
139 const QMutexLocker lock( &sDiskCacheMutex );
140 return sDiskCache.metaData( url );
145 const QMutexLocker lock( &sDiskCacheMutex );
146 sDiskCache.updateMetaData(
metaData );
151 const QMutexLocker lock( &sDiskCacheMutex );
152 return sDiskCache.data( url );
157 const QMutexLocker lock( &sDiskCacheMutex );
158 return sDiskCache.remove( url );
163 const QMutexLocker lock( &sDiskCacheMutex );
166 for (
const QNetworkCacheMetaData::RawHeader &header :
metaData.rawHeaders() )
168 if ( header.first.compare(
"vary", Qt::CaseInsensitive ) == 0 && QString::fromUtf8( header.second ).trimmed() ==
"*" )
174 QNetworkCacheMetaData modifiedMeta =
metaData;
176 if ( sPendingRequestHeaders.contains(
metaData.url() ) )
178 QNetworkCacheMetaData::AttributesMap attributes = modifiedMeta.attributes();
180 modifiedMeta.setAttributes( attributes );
183 return sDiskCache.prepare( modifiedMeta );
188 const QMutexLocker lock( &sDiskCacheMutex );
189 sDiskCache.insert( device );
194 const QMutexLocker lock( &sDiskCacheMutex );
195 return sDiskCache.fileMetaData( fileName );
200 const QMutexLocker lock( &sDiskCacheMutex );
201 return sDiskCache.runExpire();
206 const QMutexLocker lock( &sDiskCacheMutex );
207 return sDiskCache.clear();
212 std::function<qint64(
const QString & )> dirSize;
213 dirSize = [&dirSize](
const QString &dirPath ) -> qint64 {
217 const QStringList filePaths = dir.entryList( QDir::Files | QDir::System | QDir::Hidden );
218 for (
const QString &filePath : filePaths )
220 QFileInfo fi( dir, filePath );
224 const QStringList childDirPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::NoSymLinks );
225 for (
const QString &childDirPath : childDirPaths )
227 size += dirSize( dirPath + QDir::separator() + childDirPath );
234 QStorageInfo storageInfo( cacheDir );
235 bytesFree = storageInfo.bytesFree() + dirSize( cacheDir );
239 qint64 available10MB = bytesFree / 1024 / ( 1024LL * 10 );
240 qint64 cacheSize10MB = 0;
241 if ( available10MB > 2500 )
248 if ( available10MB > 700 )
251 cacheSize10MB += ( available10MB - 700 ) * 0.025;
254 if ( available10MB > 50 )
257 cacheSize10MB += ( available10MB - 50 ) * 0.075;
261#if defined( Q_OS_ANDROID )
265 cacheSize10MB += std::max( 2LL,
static_cast<qint64
>( available10MB * 0.16 ) );
268 cacheSize10MB += std::max( 5LL,
static_cast<qint64
>( available10MB * 0.30 ) );
271 cacheSize = cacheSize10MB * 10 * 1024 * 1024;
277 static qint64 sCacheSize = 0;
278 static std::once_flag initialized;
void setCacheDirectory(const QString &cacheDir)
void removePendingRequestForUrl(const QUrl &url) const
Removes a pending (ongoing) request in place for the specified url.
QIODevice * data(const QUrl &url) override
void updateMetaData(const QNetworkCacheMetaData &metaData) override
QNetworkCacheMetaData metaData(const QUrl &url) override
qint64 maximumCacheSize() const
bool hasInvalidMatchForRequest(const QNetworkRequest &request)
Returns true if the cache has a matching but invalid entry for a request.
QNetworkCacheMetaData fileMetaData(const QString &fileName) const
bool hasPendingRequestForUrl(const QUrl &url) const
Returns true if there is a pending (ongoing) request in place for the specified url.
void insertPendingRequestHeaders(const QUrl &url, const QVariantMap &headers)
Registers the original request headers for a pending request to the specified url.
void insert(QIODevice *device) override
QIODevice * prepare(const QNetworkCacheMetaData &metaData) override
bool remove(const QUrl &url) override
void setMaximumCacheSize(qint64 size)
qint64 cacheSize() const override
QString cacheDirectory() const
static qint64 smartCacheSize(const QString &path)
Returns a smart cache size, in bytes, based on available free space.
@ AttributeOriginalHeaders
Internal ID used to store original request headers, used when checking against previously cached resp...
void determineSmartCacheSize(const QString &cacheDir, qint64 &cacheSize)