QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsrangerequestcache.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsrangerequestcache.cpp
3 --------------------
4 begin : April 2022
5 copyright : (C) 2022 by Belgacem Nedjima
6 email : belgacem dot nedjima at gmail dot com
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
19
20#include "qgsnetworkdiskcache.h"
21
22#include <QDateTime>
23#include <QDir>
24#include <QFile>
25#include <QString>
26#include <QtDebug>
27
28using namespace Qt::StringLiterals;
29
32
33QByteArray QgsRangeRequestCache::entry( const QNetworkRequest &request )
34{
35 QString hash = rangeFileName( request );
36 QByteArray arr = readFile( hash );
37 return arr;
38}
39
40bool QgsRangeRequestCache::hasEntry( const QNetworkRequest &request )
41{
42 QDir dir( mCacheDir );
43 return dir.exists( rangeFileName( request ) );
44}
45
46void QgsRangeRequestCache::registerEntry( const QNetworkRequest &request, QByteArray data )
47{
48 QString hash = rangeFileName( request );
49 writeFile( hash, data );
50 expire();
51}
52
54{
55 QDir dir( mCacheDir );
56 for ( QFileInfo info : dir.entryInfoList() )
57 {
58 removeFile( info.filePath() );
59 }
60}
61
62bool QgsRangeRequestCache::setCacheDirectory( const QString &path )
63{
64 QString cachePath = path;
65 if ( !cachePath.endsWith( QDir::separator() ) )
66 {
67 cachePath.push_back( QDir::separator() );
68 }
69 mCacheDir = cachePath;
70
71 if ( !QDir().mkpath( mCacheDir ) )
72 {
73 mError = QObject::tr( "Unable to create cache directory \"%1\"" ).arg( mCacheDir );
74 return false;
75 }
76 return true;
77}
78
79void QgsRangeRequestCache::setCacheSize( qint64 cacheSize )
80{
81 if ( cacheSize == 0 )
82 {
83 // Calculate maximum cache size based on available free space
84 cacheSize = QgsNetworkDiskCache::smartCacheSize( mCacheDir );
85 }
86
87 mMaxDataSize = cacheSize;
88 expire();
89}
90
91QString QgsRangeRequestCache::rangeFileName( const QNetworkRequest &request ) const
92{
93 return mCacheDir + u"%1-%2"_s.arg( qHash( request.url().toString() ) ).arg( QString::fromUtf8( request.rawHeader( "Range" ) ) );
94}
95
96QByteArray QgsRangeRequestCache::readFile( const QString &fileName )
97{
98 QFile file( fileName );
99 if ( !file.open( QFile::OpenModeFlag::ReadOnly ) )
100 {
101 mError = QObject::tr( "Unable to read cache file \"%1\"" ).arg( fileName );
102 return QByteArray();
103 }
104 return file.readAll();
105}
106
107bool QgsRangeRequestCache::writeFile( const QString &fileName, QByteArray data )
108{
109 QFile file( fileName );
110 if ( !file.open( QFile::OpenModeFlag::WriteOnly ) )
111 {
112 mError = QObject::tr( "Unable to open cache file \"%1\"" ).arg( fileName );
113 return false;
114 }
115 qint64 written = file.write( data );
116 file.close();
117 if ( written != data.size() )
118 {
119 mError = QObject::tr( "Unable to write to cache file \"%1\", error: \"%2\"" ).arg( fileName, file.errorString() );
120 return false;
121 }
122 return true;
123}
124
125bool QgsRangeRequestCache::removeFile( const QString &fileName )
126{
127 if ( fileName.isEmpty() )
128 return false;
129 bool wasRemoved = QFile::remove( fileName );
130 if ( !wasRemoved )
131 {
132 mError = QObject::tr( "Unable to remove cache file \"%1\"" ).arg( fileName );
133 }
134 return wasRemoved;
135}
136
137void QgsRangeRequestCache::expire()
138{
139 QFileInfoList filesList = cacheEntries();
140 qint64 totalSize = 0;
141 for ( QFileInfo &info : filesList )
142 {
143 totalSize += info.size();
144 }
145 while ( totalSize > mMaxDataSize )
146 {
147 QFileInfo info = filesList.back();
148 filesList.pop_back();
149 totalSize -= info.size();
150 removeFile( info.filePath() );
151 }
152}
153
154QFileInfoList QgsRangeRequestCache::cacheEntries()
155{
156 QDir dir( mCacheDir );
157 QFileInfoList filesList = dir.entryInfoList( QDir::Filter::Files, QDir::SortFlags() );
158 std::sort( filesList.begin(), filesList.end(), []( QFileInfo &f1, QFileInfo &f2 ) {
159 QDateTime t1 = f1.fileTime( QFile::FileTime::FileAccessTime );
160 if ( !t1.isValid() )
161 t1 = f1.fileTime( QFile::FileTime::FileBirthTime );
162 QDateTime t2 = f2.fileTime( QFile::FileTime::FileAccessTime );
163 if ( !t2.isValid() )
164 t2 = f2.fileTime( QFile::FileTime::FileBirthTime );
165 return t1 > t2;
166 } );
167 return filesList;
168}
static qint64 smartCacheSize(const QString &path)
Returns a smart cache size, in bytes, based on available free space.
void clear()
Clears the cache removing all of the files.
bool hasEntry(const QNetworkRequest &request)
Checks whether the range request exists in the cache.
bool setCacheDirectory(const QString &path)
Set the Cache Directory object.
QByteArray entry(const QNetworkRequest &request)
Returns the range request data stored in the cache and an empty byte array if the data is not in the ...
void registerEntry(const QNetworkRequest &request, QByteArray data)
Adds the range request data into the cache.
void setCacheSize(qint64 maxBytes)
Sets the cache size.
uint qHash(const QVariant &variant)
Hash for QVariant.
Definition qgis.cpp:611