diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2016-08-07 14:53:57 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2016-08-12 16:54:38 +0000 |
commit | b40d005544cf4b991b797b0058a23dc61e8de5c2 (patch) | |
tree | 9ab3cbda9f719ffa2e8f68ecc140738b8879cae6 | |
parent | f5a05313757e234c35455b2e1d6fbba43bc9ace2 (diff) |
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>
-rw-r--r-- | src/qml/compiler/qv4compilationunitmapper_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilationunitmapper_unix.cpp | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilationunitmapper_win.cpp | 3 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 26 | ||||
-rw-r--r-- | tests/auto/qml/qmldiskcache/qmldiskcache.pro | 2 | ||||
-rw-r--r-- | tests/auto/qml/qmldiskcache/test.qml | 4 | ||||
-rw-r--r-- | tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp | 28 |
7 files changed, 58 insertions, 13 deletions
diff --git a/src/qml/compiler/qv4compilationunitmapper_p.h b/src/qml/compiler/qv4compilationunitmapper_p.h index 69007f4618..5b6939f1cf 100644 --- a/src/qml/compiler/qv4compilationunitmapper_p.h +++ b/src/qml/compiler/qv4compilationunitmapper_p.h @@ -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: diff --git a/src/qml/compiler/qv4compilationunitmapper_unix.cpp b/src/qml/compiler/qv4compilationunitmapper_unix.cpp index 7119acc80e..1aa3e05f5f 100644 --- a/src/qml/compiler/qv4compilationunitmapper_unix.cpp +++ b/src/qml/compiler/qv4compilationunitmapper_unix.cpp @@ -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; diff --git a/src/qml/compiler/qv4compilationunitmapper_win.cpp b/src/qml/compiler/qv4compilationunitmapper_win.cpp index d58c46c090..7e62cbfe8b 100644 --- a/src/qml/compiler/qv4compilationunitmapper_win.cpp +++ b/src/qml/compiler/qv4compilationunitmapper_win.cpp @@ -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()), diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index cc1f8ae261..35f61b4f69 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -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); diff --git a/tests/auto/qml/qmldiskcache/qmldiskcache.pro b/tests/auto/qml/qmldiskcache/qmldiskcache.pro index f2d1a04780..f98a157b6a 100644 --- a/tests/auto/qml/qmldiskcache/qmldiskcache.pro +++ b/tests/auto/qml/qmldiskcache/qmldiskcache.pro @@ -4,4 +4,6 @@ osx:CONFIG -= app_bundle SOURCES += tst_qmldiskcache.cpp +RESOURCES += test.qml + QT += core-private qml-private testlib diff --git a/tests/auto/qml/qmldiskcache/test.qml b/tests/auto/qml/qmldiskcache/test.qml new file mode 100644 index 0000000000..d632422616 --- /dev/null +++ b/tests/auto/qml/qmldiskcache/test.qml @@ -0,0 +1,4 @@ +import QtQml 2.0 +QtObject { + property int value: 20 +} diff --git a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp index dd23dfca07..8ccf4714ba 100644 --- a/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp +++ b/tests/auto/qml/qmldiskcache/tst_qmldiskcache.cpp @@ -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" |