QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 
18 #include "qgsrangerequestcache.h"
19 
20 #include <QtDebug>
21 #include <QFile>
22 #include <QDir>
23 #include <QDateTime>
24 
26 {
27 
28 }
29 
30 QByteArray QgsRangeRequestCache::entry( const QNetworkRequest &request )
31 {
32  QString hash = rangeFileName( request );
33  QByteArray arr = readFile( hash );
34  return arr;
35 }
36 
37 bool QgsRangeRequestCache::hasEntry( const QNetworkRequest &request )
38 {
39  QDir dir( mCacheDir );
40  return dir.exists( rangeFileName( request ) );
41 }
42 
43 void QgsRangeRequestCache::registerEntry( const QNetworkRequest &request, QByteArray data )
44 {
45  QString hash = rangeFileName( request );
46  writeFile( hash, data );
47  expire();
48 }
49 
51 {
52  QDir dir( mCacheDir );
53  for ( QFileInfo info : dir.entryInfoList() )
54  {
55  removeFile( info.filePath() );
56  }
57 }
58 
59 bool QgsRangeRequestCache::setCacheDirectory( const QString &path )
60 {
61  QString cachePath = path;
62  if ( !cachePath.endsWith( QDir::separator() ) )
63  {
64  cachePath.push_back( QDir::separator() );
65  }
66  mCacheDir = cachePath;
67 
68  if ( !QDir().mkpath( mCacheDir ) )
69  {
70  mError = QObject::tr( "Unable to create cache directory \"%1\"" ).arg( mCacheDir );
71  return false;
72  }
73  return true;
74 }
75 
76 void QgsRangeRequestCache::setCacheSize( qint64 cacheSize )
77 {
78  mMaxDataSize = cacheSize;
79  expire();
80 }
81 
82 QString QgsRangeRequestCache::rangeFileName( const QNetworkRequest &request ) const
83 {
84  return mCacheDir + QStringLiteral( "%1-%2" ).arg( qHash( request.url().toString() ) ).arg( QString::fromUtf8( request.rawHeader( "Range" ) ) );
85 }
86 
87 QByteArray QgsRangeRequestCache::readFile( const QString &fileName )
88 {
89  QFile file( fileName );
90  if ( !file.open( QFile::OpenModeFlag::ReadOnly ) )
91  {
92  mError = QObject::tr( "Unable to read cache file \"%1\"" ).arg( fileName );
93  return QByteArray();
94  }
95  return file.readAll();
96 }
97 
98 bool QgsRangeRequestCache::writeFile( const QString &fileName, QByteArray data )
99 {
100  QFile file( fileName );
101  if ( !file.open( QFile::OpenModeFlag::WriteOnly ) )
102  {
103  mError = QObject::tr( "Unable to open cache file \"%1\"" ).arg( fileName );
104  return false;
105  }
106  qint64 written = file.write( data );
107  file.close();
108  if ( written != data.size() )
109  {
110  mError = QObject::tr( "Unable to write to cache file \"%1\", error: \"%2\"" ).arg( fileName, file.errorString() );
111  return false;
112  }
113  return true;
114 }
115 
116 bool QgsRangeRequestCache::removeFile( const QString &fileName )
117 {
118  if ( fileName.isEmpty() )
119  return false;
120  bool wasRemoved = QFile::remove( fileName );
121  if ( !wasRemoved )
122  {
123  mError = QObject::tr( "Unable to remove cache file \"%1\"" ).arg( fileName );
124  }
125  return wasRemoved;
126 }
127 
128 void QgsRangeRequestCache::expire()
129 {
130  QFileInfoList filesList = cacheEntries();
131  qint64 totalSize = 0;
132  for ( QFileInfo &info : filesList )
133  {
134  totalSize += info.size();
135  }
136  while ( totalSize > mMaxDataSize )
137  {
138  QFileInfo info = filesList.back();
139  filesList.pop_back();
140  totalSize -= info.size();
141  removeFile( info.filePath() );
142  }
143 }
144 
145 QFileInfoList QgsRangeRequestCache::cacheEntries()
146 {
147  QStringList list;
148  QDir dir( mCacheDir );
149  QFileInfoList filesList = dir.entryInfoList( QDir::Filter::Files, QDir::SortFlags() );
150  std::sort( filesList.begin(), filesList.end(), []( QFileInfo & f1, QFileInfo & f2 )
151  {
152  QDateTime t1 = f1.fileTime( QFile::FileTime::FileAccessTime );
153  if ( !t1.isValid() )
154  t1 = f1.fileTime( QFile::FileTime::FileBirthTime );
155  QDateTime t2 = f2.fileTime( QFile::FileTime::FileAccessTime );
156  if ( !t2.isValid() )
157  t2 = f2.fileTime( QFile::FileTime::FileBirthTime );
158  return t1 > t2;
159  } );
160  return filesList;
161 }
QgsRangeRequestCache::QgsRangeRequestCache
QgsRangeRequestCache()
Constructor.
Definition: qgsrangerequestcache.cpp:25
QgsRangeRequestCache::clear
void clear()
Clears the cache removing all of the files.
Definition: qgsrangerequestcache.cpp:50
QgsRangeRequestCache::hasEntry
bool hasEntry(const QNetworkRequest &request)
Checks whether the range request exists in the cache.
Definition: qgsrangerequestcache.cpp:37
qHash
uint qHash(const QVariant &variant)
Hash for QVariant.
Definition: qgis.cpp:217
QgsRangeRequestCache::entry
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 ...
Definition: qgsrangerequestcache.cpp:30
QgsRangeRequestCache::setCacheDirectory
bool setCacheDirectory(const QString &path)
Set the Cache Directory object.
Definition: qgsrangerequestcache.cpp:59
qgsrangerequestcache.h
QgsRangeRequestCache::setCacheSize
void setCacheSize(qint64 maxBytes)
Sets the cache size.
Definition: qgsrangerequestcache.cpp:76
QgsRangeRequestCache::registerEntry
void registerEntry(const QNetworkRequest &request, QByteArray data)
Adds the range request data into the cache.
Definition: qgsrangerequestcache.cpp:43