QGIS API Documentation 3.99.0-Master (21b3aa880ba)
Loading...
Searching...
No Matches
qgsnetworkdiskcache.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsnetworkdiskcache.cpp - Thread-safe interface for QNetworkDiskCache
3 -------------------
4 begin : 2016-03-05
5 copyright : (C) 2016 by Juergen E. Fischer
6 email : jef at norbit dot de
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18
19#include "qgsnetworkdiskcache.h"
20
21#include <mutex>
22
23#include <QStorageInfo>
24
25#include "moc_qgsnetworkdiskcache.cpp"
26
28ExpirableNetworkDiskCache QgsNetworkDiskCache::sDiskCache;
30QMutex QgsNetworkDiskCache::sDiskCacheMutex;
31
32QgsNetworkDiskCache::QgsNetworkDiskCache( QObject *parent )
33 : QNetworkDiskCache( parent )
34{
35}
36
38{
39 const QMutexLocker lock( &sDiskCacheMutex );
40 return sDiskCache.cacheDirectory();
41}
42
43void QgsNetworkDiskCache::setCacheDirectory( const QString &cacheDir )
44{
45 const QMutexLocker lock( &sDiskCacheMutex );
46 sDiskCache.setCacheDirectory( cacheDir );
47}
48
50{
51 const QMutexLocker lock( &sDiskCacheMutex );
52 return sDiskCache.maximumCacheSize();
53}
54
56{
57 const QMutexLocker lock( &sDiskCacheMutex );
58
59 if ( size == 0 )
60 {
61 // Calculate maximum cache size based on available free space
62 size = smartCacheSize( sDiskCache.cacheDirectory() );
63 }
64
65 sDiskCache.setMaximumCacheSize( size );
66}
67
69{
70 const QMutexLocker lock( &sDiskCacheMutex );
71 return sDiskCache.cacheSize();
72}
73
74QNetworkCacheMetaData QgsNetworkDiskCache::metaData( const QUrl &url )
75{
76 const QMutexLocker lock( &sDiskCacheMutex );
77 return sDiskCache.metaData( url );
78}
79
80void QgsNetworkDiskCache::updateMetaData( const QNetworkCacheMetaData &metaData )
81{
82 const QMutexLocker lock( &sDiskCacheMutex );
83 sDiskCache.updateMetaData( metaData );
84}
85
86QIODevice *QgsNetworkDiskCache::data( const QUrl &url )
87{
88 const QMutexLocker lock( &sDiskCacheMutex );
89 return sDiskCache.data( url );
90}
91
92bool QgsNetworkDiskCache::remove( const QUrl &url )
93{
94 const QMutexLocker lock( &sDiskCacheMutex );
95 return sDiskCache.remove( url );
96}
97
98QIODevice *QgsNetworkDiskCache::prepare( const QNetworkCacheMetaData &metaData )
99{
100 const QMutexLocker lock( &sDiskCacheMutex );
101 return sDiskCache.prepare( metaData );
102}
103
104void QgsNetworkDiskCache::insert( QIODevice *device )
105{
106 const QMutexLocker lock( &sDiskCacheMutex );
107 sDiskCache.insert( device );
108}
109
110QNetworkCacheMetaData QgsNetworkDiskCache::fileMetaData( const QString &fileName ) const
111{
112 const QMutexLocker lock( &sDiskCacheMutex );
113 return sDiskCache.fileMetaData( fileName );
114}
115
117{
118 const QMutexLocker lock( &sDiskCacheMutex );
119 return sDiskCache.runExpire();
120}
121
123{
124 const QMutexLocker lock( &sDiskCacheMutex );
125 return sDiskCache.clear();
126}
127
128void determineSmartCacheSize( const QString &cacheDir, qint64 &cacheSize )
129{
130 std::function<qint64( const QString & )> dirSize;
131 dirSize = [&dirSize]( const QString & dirPath ) -> qint64
132 {
133 qint64 size = 0;
134 QDir dir( dirPath );
135
136 const QStringList filePaths = dir.entryList( QDir::Files | QDir::System | QDir::Hidden );
137 for ( const QString &filePath : filePaths )
138 {
139 QFileInfo fi( dir, filePath );
140 size += fi.size();
141 }
142
143 const QStringList childDirPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::NoSymLinks );
144 for ( const QString &childDirPath : childDirPaths )
145 {
146 size += dirSize( dirPath + QDir::separator() + childDirPath );
147 }
148
149 return size;
150 };
151
152 qint64 bytesFree;
153 QStorageInfo storageInfo( cacheDir );
154 bytesFree = storageInfo.bytesFree() + dirSize( cacheDir );
155
156 // NOLINTBEGIN(bugprone-narrowing-conversions)
157 // Logic taken from Firefox's smart cache size handling
158 qint64 available10MB = bytesFree / 1024 / ( 1024LL * 10 );
159 qint64 cacheSize10MB = 0;
160 if ( available10MB > 2500 )
161 {
162 // Cap the cache size to 1GB
163 cacheSize10MB = 100;
164 }
165 else
166 {
167 if ( available10MB > 700 )
168 {
169 // Add 2.5% of the free space above 7GB
170 cacheSize10MB += ( available10MB - 700 ) * 0.025;
171 available10MB = 700;
172 }
173 if ( available10MB > 50 )
174 {
175 // Add 7.5% of free space between 500MB to 7GB
176 cacheSize10MB += ( available10MB - 50 ) * 0.075;
177 available10MB = 50;
178 }
179
180#if defined( Q_OS_ANDROID )
181 // On Android, smaller/older devices may have very little storage
182
183 // Add 16% of free space up to 500 MB
184 cacheSize10MB += std::max( 2LL, static_cast<qint64>( available10MB * 0.16 ) );
185#else \
186 // Add 30% of free space up to 500 MB
187 cacheSize10MB += std::max( 5LL, static_cast<qint64>( available10MB * 0.30 ) );
188#endif
189 }
190 cacheSize = cacheSize10MB * 10 * 1024 * 1024;
191 // NOLINTEND(bugprone-narrowing-conversions)
192}
193
194qint64 QgsNetworkDiskCache::smartCacheSize( const QString &cacheDir )
195{
196 static qint64 sCacheSize = 0;
197 static std::once_flag initialized;
198 std::call_once( initialized, determineSmartCacheSize, cacheDir, sCacheSize );
199 return sCacheSize;
200}
void setCacheDirectory(const QString &cacheDir)
QIODevice * data(const QUrl &url) override
void updateMetaData(const QNetworkCacheMetaData &metaData) override
QNetworkCacheMetaData metaData(const QUrl &url) override
qint64 maximumCacheSize() const
QNetworkCacheMetaData fileMetaData(const QString &fileName) const
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.
void determineSmartCacheSize(const QString &cacheDir, qint64 &cacheSize)