summaryrefslogtreecommitdiff
path: root/src/network/access/qnetworkdiskcache.cpp
diff options
context:
space:
mode:
authorMårten Nordheim <marten.nordheim@qt.io>2023-03-03 16:52:34 +0100
committerMårten Nordheim <marten.nordheim@qt.io>2023-03-13 17:29:11 +0100
commit9c27e165993cf673e48f6514ffc210f046c9d5fc (patch)
tree4b9c95532e58a5b5d7fb8f7a62b4896a50755ad1 /src/network/access/qnetworkdiskcache.cpp
parent80eba4bb944cc08651ecb01553492786ec3f4ec1 (diff)
downloadqtbase-9c27e165993cf673e48f6514ffc210f046c9d5fc.tar.gz
QNetworkDiskCache: use QSaveFile
QTemporaryFile is not designed to promote temporary files to non-temporary files. So, it, quite importantly, does not care if the content of the files are flushed to disk before renaming it into its 'final' destination. This is what QSaveFile is for. This was much more time-consuming than intended since I had to debug this quirk about calling size(). Fixes: QTBUG-111397 Change-Id: I15b300f6a5748ad3a0be983545ea621269a12ecd Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit e5f295c8a458dcd336f7cf3768ca62aded69e659)
Diffstat (limited to 'src/network/access/qnetworkdiskcache.cpp')
-rw-r--r--src/network/access/qnetworkdiskcache.cpp51
1 files changed, 17 insertions, 34 deletions
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index 6b52b8d49a..cf6f0a9b14 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -21,7 +21,6 @@
#include <memory>
#define CACHE_POSTFIX ".d"_L1
-#define PREPARED_SLASH "prepared/"_L1
#define CACHE_VERSION 8
#define DATA_DIR "data"_L1
@@ -173,13 +172,13 @@ QIODevice *QNetworkDiskCache::prepare(const QNetworkCacheMetaData &metaData)
cacheItem->data.open(QBuffer::ReadWrite);
device = &(cacheItem->data);
} else {
- QString templateName = d->tmpCacheFileName();
+ QString fileName = d->cacheFileName(cacheItem->metaData.url());
QT_TRY {
- cacheItem->file = new QTemporaryFile(templateName, &cacheItem->data);
+ cacheItem->file = new QSaveFile(fileName, &cacheItem->data);
} QT_CATCH(...) {
cacheItem->file = nullptr;
}
- if (!cacheItem->file || !cacheItem->file->open()) {
+ if (!cacheItem->file || !cacheItem->file->open(QFileDevice::WriteOnly)) {
qWarning("QNetworkDiskCache::prepare() unable to open temporary file");
cacheItem.reset();
return nullptr;
@@ -219,7 +218,6 @@ void QNetworkDiskCache::insert(QIODevice *device)
void QNetworkDiskCachePrivate::prepareLayout()
{
QDir helper;
- helper.mkpath(cacheDirectory + PREPARED_SLASH);
//Create directory and subdirectories 0-F
helper.mkpath(dataDirectory);
@@ -248,9 +246,8 @@ void QNetworkDiskCachePrivate::storeItem(QCacheItem *cacheItem)
currentCacheSize = q->expire();
if (!cacheItem->file) {
- QString templateName = tmpCacheFileName();
- cacheItem->file = new QTemporaryFile(templateName, &cacheItem->data);
- if (cacheItem->file->open()) {
+ cacheItem->file = new QSaveFile(fileName, &cacheItem->data);
+ if (cacheItem->file->open(QFileDevice::WriteOnly)) {
cacheItem->writeHeader(cacheItem->file);
cacheItem->writeCompressedData(cacheItem->file);
}
@@ -258,13 +255,15 @@ void QNetworkDiskCachePrivate::storeItem(QCacheItem *cacheItem)
if (cacheItem->file
&& cacheItem->file->isOpen()
- && cacheItem->file->error() == QFile::NoError) {
- cacheItem->file->setAutoRemove(false);
- // ### use atomic rename rather then remove & rename
- if (cacheItem->file->rename(fileName))
- currentCacheSize += cacheItem->file->size();
- else
- cacheItem->file->setAutoRemove(true);
+ && cacheItem->file->error() == QFileDevice::NoError) {
+ // We have to call size() here instead of inside the if-body because
+ // commit() invalidates the file-engine, and size() will create a new
+ // one, pointing at an empty filename.
+ qint64 size = cacheItem->file->size();
+ if (cacheItem->file->commit())
+ currentCacheSize += size;
+ // Delete and unset the QSaveFile, it's invalid now.
+ delete std::exchange(cacheItem->file, nullptr);
}
if (cacheItem->metaData.url() == lastItem.metaData.url())
lastItem.reset();
@@ -509,16 +508,6 @@ qint64 QNetworkDiskCache::expire()
QString name = i.value();
QFile file(name);
- if (name.contains(PREPARED_SLASH)) {
- for (QCacheItem *item : std::as_const(d->inserting)) {
- if (item && item->file && item->file->fileName() == name) {
- delete item->file;
- item->file = nullptr;
- break;
- }
- }
- }
-
qint64 size = file.size();
file.remove();
totalSize -= size;
@@ -569,12 +558,6 @@ QString QNetworkDiskCachePrivate::uniqueFileName(const QUrl &url)
return pathFragment;
}
-QString QNetworkDiskCachePrivate::tmpCacheFileName() const
-{
- //The subdirectory is presumed to be already read for use.
- return cacheDirectory + PREPARED_SLASH + "XXXXXX"_L1 + CACHE_POSTFIX;
-}
-
/*!
Generates fully qualified path of cached resource from a URL.
*/
@@ -625,7 +608,7 @@ enum
CurrentCacheVersion = CACHE_VERSION
};
-void QCacheItem::writeHeader(QFile *device) const
+void QCacheItem::writeHeader(QFileDevice *device) const
{
QDataStream out(device);
@@ -637,7 +620,7 @@ void QCacheItem::writeHeader(QFile *device) const
out << compressed;
}
-void QCacheItem::writeCompressedData(QFile *device) const
+void QCacheItem::writeCompressedData(QFileDevice *device) const
{
QDataStream out(device);
@@ -648,7 +631,7 @@ void QCacheItem::writeCompressedData(QFile *device) const
Returns \c false if the file is a cache file,
but is an older version and should be removed otherwise true.
*/
-bool QCacheItem::read(QFile *device, bool readData)
+bool QCacheItem::read(QFileDevice *device, bool readData)
{
reset();