Enable disk cache for files coming from resources
By storing the cached data in QStandardPaths::CacheDir + "/qmlcache/" + sha1(filename) Change-Id: I6a8b4ca701019204fff362504697c3dac9f54bf1 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
f5a0531375
commit
b40d005544
|
@ -68,7 +68,7 @@ public:
|
|||
CompilationUnitMapper();
|
||||
~CompilationUnitMapper();
|
||||
|
||||
CompiledData::Unit *open(const QString &sourcePath, QString *errorString);
|
||||
CompiledData::Unit *open(const QString &cacheFilePath, const QString &sourcePath, QString *errorString);
|
||||
void close();
|
||||
|
||||
private:
|
||||
|
|
|
@ -50,13 +50,11 @@ QT_BEGIN_NAMESPACE
|
|||
|
||||
using namespace QV4;
|
||||
|
||||
CompiledData::Unit *CompilationUnitMapper::open(const QString &sourcePath, QString *errorString)
|
||||
CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, const QString &sourcePath, QString *errorString)
|
||||
{
|
||||
close();
|
||||
|
||||
QByteArray cacheFileName = QFile::encodeName(sourcePath);
|
||||
cacheFileName.append('c');
|
||||
int fd = qt_safe_open(cacheFileName.constData(), O_RDONLY);
|
||||
int fd = qt_safe_open(QFile::encodeName(cacheFileName).constData(), O_RDONLY);
|
||||
if (fd == -1) {
|
||||
*errorString = qt_error_string(errno);
|
||||
return nullptr;
|
||||
|
|
|
@ -49,13 +49,12 @@ QT_BEGIN_NAMESPACE
|
|||
|
||||
using namespace QV4;
|
||||
|
||||
CompiledData::Unit *CompilationUnitMapper::open(const QString &sourcePath, QString *errorString)
|
||||
CompiledData::Unit *CompilationUnitMapper::open(const QString &cacheFileName, const QString &sourcePath, QString *errorString)
|
||||
{
|
||||
close();
|
||||
|
||||
// ### TODO: fix up file encoding/normalization/unc handling once QFileSystemEntry
|
||||
// is exported from QtCore.
|
||||
const QString cacheFileName = sourcePath + QLatin1Char('c');
|
||||
HANDLE handle =
|
||||
#if defined(Q_OS_WINRT)
|
||||
CreateFile2(reinterpret_cast<const wchar_t*>(cacheFileName.constData()),
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QScopedValueRollback>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
#endif
|
||||
#include <private/qqmlirbuilder_p.h>
|
||||
#include <QCoreApplication>
|
||||
|
@ -321,6 +323,19 @@ bool CompilationUnit::verifyChecksum(QQmlEngine *engine,
|
|||
sizeof(data->dependencyMD5Checksum)) == 0;
|
||||
}
|
||||
|
||||
static QString cacheFilePath(const QUrl &url)
|
||||
{
|
||||
const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
|
||||
const QString localCachePath = localSourcePath + QLatin1Char('c');
|
||||
if (QFileInfo(QFileInfo(localSourcePath).dir().absolutePath()).isWritable())
|
||||
return localCachePath;
|
||||
QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
|
||||
fileNameHash.addData(localSourcePath.toUtf8());
|
||||
QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/");
|
||||
QDir::root().mkpath(directory);
|
||||
return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + QFileInfo(localCachePath).completeSuffix();
|
||||
}
|
||||
|
||||
bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
|
||||
{
|
||||
errorString->clear();
|
||||
|
@ -330,13 +345,13 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!unitUrl.isLocalFile()) {
|
||||
if (!QQmlFile::isLocalFile(unitUrl)) {
|
||||
*errorString = QStringLiteral("File has to be a local file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Foo.qml -> Foo.qmlc
|
||||
QSaveFile cacheFile(unitUrl.toLocalFile() + QLatin1Char('c'));
|
||||
QSaveFile cacheFile(cacheFilePath(unitUrl));
|
||||
if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
*errorString = cacheFile.errorString();
|
||||
return false;
|
||||
|
@ -371,7 +386,7 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
|
|||
|
||||
bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory, QString *errorString)
|
||||
{
|
||||
if (!url.isLocalFile()) {
|
||||
if (!QQmlFile::isLocalFile(url)) {
|
||||
*errorString = QStringLiteral("File has to be a local file.");
|
||||
return false;
|
||||
}
|
||||
|
@ -379,10 +394,9 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory
|
|||
const QString sourcePath = url.toLocalFile();
|
||||
QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper());
|
||||
|
||||
CompiledData::Unit *mappedUnit = cacheFile->open(sourcePath, errorString);
|
||||
if (!mappedUnit) {
|
||||
CompiledData::Unit *mappedUnit = cacheFile->open(cacheFilePath(url), sourcePath, errorString);
|
||||
if (!mappedUnit)
|
||||
return false;
|
||||
}
|
||||
|
||||
const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr;
|
||||
QScopedValueRollback<const Unit *> dataPtrChange(data, mappedUnit);
|
||||
|
|
|
@ -4,4 +4,6 @@ osx:CONFIG -= app_bundle
|
|||
|
||||
SOURCES += tst_qmldiskcache.cpp
|
||||
|
||||
RESOURCES += test.qml
|
||||
|
||||
QT += core-private qml-private testlib
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
import QtQml 2.0
|
||||
QtObject {
|
||||
property int value: 20
|
||||
}
|
|
@ -38,6 +38,9 @@
|
|||
#include <QQmlEngine>
|
||||
#include <QQmlFileSelector>
|
||||
#include <QThread>
|
||||
#include <QCryptographicHash>
|
||||
#include <QStandardPaths>
|
||||
#include <QDirIterator>
|
||||
|
||||
class tst_qmldiskcache: public QObject
|
||||
{
|
||||
|
@ -52,6 +55,7 @@ private slots:
|
|||
void recompileAfterChange();
|
||||
void fileSelectors();
|
||||
void localAliases();
|
||||
void cacheResources();
|
||||
};
|
||||
|
||||
// A wrapper around QQmlComponent to ensure the temporary reference counts
|
||||
|
@ -529,6 +533,30 @@ void tst_qmldiskcache::localAliases()
|
|||
}
|
||||
}
|
||||
|
||||
void tst_qmldiskcache::cacheResources()
|
||||
{
|
||||
const QString cacheDirectory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
|
||||
QVERIFY(QDir::root().mkpath(cacheDirectory));
|
||||
|
||||
const QString qmlCacheDirectory = cacheDirectory + QLatin1String("/qmlcache/");
|
||||
QVERIFY(QDir(qmlCacheDirectory).removeRecursively());
|
||||
QVERIFY(QDir::root().mkpath(qmlCacheDirectory));
|
||||
QVERIFY(QDir(qmlCacheDirectory).entryList(QDir::NoDotAndDotDot).isEmpty());
|
||||
|
||||
|
||||
QQmlEngine engine;
|
||||
|
||||
{
|
||||
CleanlyLoadingComponent component(&engine, QUrl("qrc:/test.qml"));
|
||||
qDebug() << component.errorString();
|
||||
QScopedPointer<QObject> obj(component.create());
|
||||
QVERIFY(!obj.isNull());
|
||||
QCOMPARE(obj->property("value").toInt(), 20);
|
||||
}
|
||||
|
||||
QCOMPARE(QDir(qmlCacheDirectory).entryList(QDir::NoDotAndDotDot | QDir::Files).count(), 1);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_qmldiskcache)
|
||||
|
||||
#include "tst_qmldiskcache.moc"
|
||||
|
|
Loading…
Reference in New Issue