From 46ca72323018c9e31878bc7629e303fc6c05d073 Mon Sep 17 00:00:00 2001 From: Arttu Tarkiainen Date: Wed, 8 Feb 2023 15:53:06 +0200 Subject: Metadata cache: register items by renaming instead of copying This is much more efficient than recursively copying the contents of each downloaded repository entry. Testing on a Linux debug build with a large amount of components, a rough estimate of the time reduction for performing update of an almost empty cache was over 60 percent. Task-number: QTIFW-2971 Change-Id: I866514af092f9c4b5e322562d6f972c57c8c03f5 Reviewed-by: Katja Marttila Reviewed-by: Qt CI Bot --- src/libs/installer/genericdatacache.cpp | 38 ++++++++++++++++++++++++++++----- src/libs/installer/genericdatacache.h | 7 +++++- src/libs/installer/metadatajob_p.h | 2 +- 3 files changed, 40 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/libs/installer/genericdatacache.cpp b/src/libs/installer/genericdatacache.cpp index fd264ce63..d8db99600 100644 --- a/src/libs/installer/genericdatacache.cpp +++ b/src/libs/installer/genericdatacache.cpp @@ -119,6 +119,16 @@ CacheableItem::~CacheableItem() calling \l{sync()}. */ +/*! + \enum GenericDataCache::RegisterMode + This enum holds the possible values for modes of registering items to cache. + + \value Copy + The contents of the item are copied to the cache. + \value Move + The contents of the item are move to the cache. +*/ + /*! \fn template QInstaller::GenericDataCache::GenericDataCache() @@ -417,13 +427,14 @@ T *GenericDataCache::itemByPath(const QString &path) const the new \a item replaces a previous item with the same checksum. The cache takes ownership of the object pointed by \a item. The contents of the - item are copied to the cache with a subdirectory name that matches the checksum - of the item. + item are copied or moved to the cache with a subdirectory name that matches the checksum + of the item. The \c mode decides how the contents of the item are registered, either by + copying or moving. Returns \c true on success or \c false if the item could not be registered. */ template -bool GenericDataCache::registerItem(T *item, bool replace) +bool GenericDataCache::registerItem(T *item, bool replace, RegisterMode mode) { QMutexLocker _(&m_mutex); if (m_invalidated) { @@ -455,10 +466,27 @@ bool GenericDataCache::registerItem(T *item, bool replace) const QString newPath = m_path + QDir::separator() + QString::fromLatin1(item->checksum()); try { // A directory is in the way but it isn't registered to the current cache, remove. - if (QDir().exists(newPath)) + QDir dir; + if (dir.exists(newPath)) QInstaller::removeDirectory(newPath); - QInstaller::copyDirectoryContents(item->path(), newPath); + switch (mode) { + case Copy: + QInstaller::copyDirectoryContents(item->path(), newPath); + break; + case Move: + // First, try moving the top level directory + if (!dir.rename(item->path(), newPath)) { + qCDebug(lcDeveloperBuild) << "Failed to rename directory" << item->path() + << "to" << newPath << ". Trying again."; + // If that does not work, fallback to moving the contents one by one + QInstaller::moveDirectoryContents(item->path(), newPath); + } + break; + default: + throw Error(QCoreApplication::translate("GenericDataCache", + "Unknown register mode selected!")); + } } catch (const Error &e) { setErrorString(QCoreApplication::translate("GenericDataCache", "Error while copying item to path \"%1\": %2").arg(newPath, e.message())); diff --git a/src/libs/installer/genericdatacache.h b/src/libs/installer/genericdatacache.h index 2bdf6697e..5c1732334 100644 --- a/src/libs/installer/genericdatacache.h +++ b/src/libs/installer/genericdatacache.h @@ -64,6 +64,11 @@ template class INSTALLER_EXPORT GenericDataCache { public: + enum RegisterMode { + Copy = 0, + Move = 1 + }; + GenericDataCache(); explicit GenericDataCache(const QString &path, const QString &type, const QString &version); ~GenericDataCache(); @@ -85,7 +90,7 @@ public: T *itemByChecksum(const QByteArray &checksum) const; T *itemByPath(const QString &path) const; - bool registerItem(T *item, bool replace = false); + bool registerItem(T *item, bool replace = false, RegisterMode mode = Copy); bool removeItem(const QByteArray &checksum); QList obsoleteItems() const; diff --git a/src/libs/installer/metadatajob_p.h b/src/libs/installer/metadatajob_p.h index ef2729dbb..5340e5d1c 100644 --- a/src/libs/installer/metadatajob_p.h +++ b/src/libs/installer/metadatajob_p.h @@ -140,7 +140,7 @@ public: QStringList registeredKeys; bool success = true; for (auto *meta : qAsConst(*m_updates)) { - if (!m_cache->registerItem(meta, true)) { + if (!m_cache->registerItem(meta, true, GenericDataCache::Move)) { success = false; break; } -- cgit v1.2.3