QGIS API Documentation 3.41.0-Master (fda2aa46e9a)
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#include "moc_qgsnetworkdiskcache.cpp"
21
22#include <QStorageInfo>
23#include <mutex>
24
26ExpirableNetworkDiskCache QgsNetworkDiskCache::sDiskCache;
28QMutex QgsNetworkDiskCache::sDiskCacheMutex;
29
30QgsNetworkDiskCache::QgsNetworkDiskCache( QObject *parent )
31 : QNetworkDiskCache( parent )
32{
33}
34
36{
37 const QMutexLocker lock( &sDiskCacheMutex );
38 return sDiskCache.cacheDirectory();
39}
40
41void QgsNetworkDiskCache::setCacheDirectory( const QString &cacheDir )
42{
43 const QMutexLocker lock( &sDiskCacheMutex );
44 sDiskCache.setCacheDirectory( cacheDir );
45}
46
48{
49 const QMutexLocker lock( &sDiskCacheMutex );
50 return sDiskCache.maximumCacheSize();
51}
52
54{
55 const QMutexLocker lock( &sDiskCacheMutex );
56
57 if ( size == 0 )
58 {
59 // Calculate maximum cache size based on available free space
60 size = smartCacheSize( sDiskCache.cacheDirectory() );
61 }
62
63 sDiskCache.setMaximumCacheSize( size );
64}
65
67{
68 const QMutexLocker lock( &sDiskCacheMutex );
69 return sDiskCache.cacheSize();
70}
71
72QNetworkCacheMetaData QgsNetworkDiskCache::metaData( const QUrl &url )
73{
74 const QMutexLocker lock( &sDiskCacheMutex );
75 return sDiskCache.metaData( url );
76}
77
78void QgsNetworkDiskCache::updateMetaData( const QNetworkCacheMetaData &metaData )
79{
80 const QMutexLocker lock( &sDiskCacheMutex );
81 sDiskCache.updateMetaData( metaData );
82}
83
84QIODevice *QgsNetworkDiskCache::data( const QUrl &url )
85{
86 const QMutexLocker lock( &sDiskCacheMutex );
87 return sDiskCache.data( url );
88}
89
90bool QgsNetworkDiskCache::remove( const QUrl &url )
91{
92 const QMutexLocker lock( &sDiskCacheMutex );
93 return sDiskCache.remove( url );
94}
95
96QIODevice *QgsNetworkDiskCache::prepare( const QNetworkCacheMetaData &metaData )
97{
98 const QMutexLocker lock( &sDiskCacheMutex );
99 return sDiskCache.prepare( metaData );
100}
101
102void QgsNetworkDiskCache::insert( QIODevice *device )
103{
104 const QMutexLocker lock( &sDiskCacheMutex );
105 sDiskCache.insert( device );
106}
107
108QNetworkCacheMetaData QgsNetworkDiskCache::fileMetaData( const QString &fileName ) const
109{
110 const QMutexLocker lock( &sDiskCacheMutex );
111 return sDiskCache.fileMetaData( fileName );
112}
113
115{
116 const QMutexLocker lock( &sDiskCacheMutex );
117 return sDiskCache.runExpire();
118}
119
121{
122 const QMutexLocker lock( &sDiskCacheMutex );
123 return sDiskCache.clear();
124}
125
126qint64 QgsNetworkDiskCache::smartCacheSize( const QString &cacheDir )
127{
128 static qint64 cacheSize = 0;
129 static std::once_flag initialized;
130 std::call_once( initialized, [ = ]
131 {
132 std::function<qint64( const QString & )> dirSize;
133 dirSize = [&dirSize]( const QString & dirPath ) -> qint64
134 {
135 qint64 size = 0;
136 QDir dir( dirPath );
137
138 const QStringList filePaths = dir.entryList( QDir::Files | QDir::System | QDir::Hidden );
139 for ( const QString &filePath : filePaths )
140 {
141 QFileInfo fi( dir, filePath );
142 size += fi.size();
143 }
144
145 const QStringList childDirPaths = dir.entryList( QDir::Dirs | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::NoSymLinks );
146 for ( const QString &childDirPath : childDirPaths )
147 {
148 size += dirSize( dirPath + QDir::separator() + childDirPath );
149 }
150
151 return size;
152 };
153
154 qint64 bytesFree;
155 QStorageInfo storageInfo( cacheDir );
156 bytesFree = storageInfo.bytesFree() + dirSize( cacheDir );
157
158 // NOLINTBEGIN(bugprone-narrowing-conversions)
159 // Logic taken from Firefox's smart cache size handling
160 qint64 available10MB = bytesFree / 1024 / ( 1024LL * 10 );
161 qint64 cacheSize10MB = 0;
162 if ( available10MB > 2500 )
163 {
164 // Cap the cache size to 1GB
165 cacheSize10MB = 100;
166 }
167 else
168 {
169 if ( available10MB > 700 )
170 {
171 // Add 2.5% of the free space above 7GB
172 cacheSize10MB += ( available10MB - 700 ) * 0.025;
173 available10MB = 700;
174 }
175 if ( available10MB > 50 )
176 {
177 // Add 7.5% of free space between 500MB to 7GB
178 cacheSize10MB += ( available10MB - 50 ) * 0.075;
179 available10MB = 50;
180 }
181
182#if defined( Q_OS_ANDROID )
183 // On Android, smaller/older devices may have very little storage
184
185 // Add 16% of free space up to 500 MB
186 cacheSize10MB += std::max( 2LL, static_cast<qint64>( available10MB * 0.16 ) );
187#else
188 // Add 30% of free space up to 500 MB
189 cacheSize10MB += std::max( 5LL, static_cast<qint64>( available10MB * 0.30 ) );
190#endif
191 }
192 cacheSize = cacheSize10MB * 10 * 1024 * 1024;
193 // NOLINTEND(bugprone-narrowing-conversions)
194 } );
195
196 return cacheSize;
197}
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.