summaryrefslogtreecommitdiffstats
path: root/src/libs/installer
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-10-26 12:46:51 +0300
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-11-11 11:13:07 +0000
commit2d001a3d8d4cde6264e9073e8d586d1e9855abd8 (patch)
treecbd724dd17a158bca63278d950f9fe4304bb91d2 /src/libs/installer
parent2f2a7c52ebf172cf1462121f8b35d016dde2adde (diff)
Metadatajob: update cache asynchronously
Refactor the updating to run in a separate thread, with QFuture -based handling of the result. This removes the visible blocking of UI while updating the cache. Task-number: QTIFW-2815 Change-Id: I67bc1aed8465ca12925b9f80effadf4be7017cea Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src/libs/installer')
-rw-r--r--src/libs/installer/metadatajob.cpp76
-rw-r--r--src/libs/installer/metadatajob.h4
-rw-r--r--src/libs/installer/metadatajob_p.h75
3 files changed, 106 insertions, 49 deletions
diff --git a/src/libs/installer/metadatajob.cpp b/src/libs/installer/metadatajob.cpp
index 659648e1a..c28770192 100644
--- a/src/libs/installer/metadatajob.cpp
+++ b/src/libs/installer/metadatajob.cpp
@@ -100,6 +100,7 @@ MetadataJob::MetadataJob(QObject *parent)
connect(&m_xmlTask, &QFutureWatcherBase::finished, this, &MetadataJob::xmlTaskFinished);
connect(&m_metadataTask, &QFutureWatcherBase::finished, this, &MetadataJob::metadataTaskFinished);
connect(&m_metadataTask, &QFutureWatcherBase::progressValueChanged, this, &MetadataJob::progressChanged);
+ connect(&m_updateCacheTask, &QFutureWatcherBase::finished, this, &MetadataJob::updateCacheTaskFinished);
}
MetadataJob::~MetadataJob()
@@ -337,47 +338,15 @@ void MetadataJob::startUnzipRepositoryTask(const Repository &repo)
watcher->setFuture(QtConcurrent::run(&UnzipArchiveTask::doTask, task));
}
-bool MetadataJob::updateCache()
+void MetadataJob::startUpdateCacheTask()
{
const int toRegisterCount = m_fetchedMetadata.count();
if (toRegisterCount > 0)
emit infoMessage(this, tr("Updating local cache with %n new items...",
nullptr, toRegisterCount));
- // Register items from current run to cache
- QStringList registeredKeys;
- bool success = true;
- for (auto *meta : qAsConst(m_fetchedMetadata)) {
- if (!m_metaFromCache.registerItem(meta, true)) {
- success = false;
- break;
- }
- meta->setPersistentRepositoryPath(meta->repository().url());
- registeredKeys.append(m_fetchedMetadata.key(meta));
- }
- // Remove items whose ownership was transferred to cache
- for (auto &key : qAsConst(registeredKeys))
- m_fetchedMetadata.remove(key);
-
- // Bail out if there was error while registering items
- if (!success) {
- emitFinishedWithError(QInstaller::CacheError, m_metaFromCache.errorString() + u' '
- + tr("Clearing the cache directory and restarting the application may solve this."));
- m_metaFromCache.sync();
- return false;
- }
-
- // ...and clean up obsolete cached items
- const QList<Metadata *> obsolete = m_metaFromCache.obsoleteItems();
- for (auto *meta : obsolete)
- m_metaFromCache.removeItem(meta->checksum());
-
- if (!m_metaFromCache.sync()) {
- emitFinishedWithError(QInstaller::CacheError, m_metaFromCache.errorString() + u' '
- + tr("Clearing the cache directory and restarting the application may solve this."));
- return false;
- }
- return true;
+ UpdateCacheTask *task = new UpdateCacheTask(m_metaFromCache, m_fetchedMetadata);
+ m_updateCacheTask.setFuture(QtConcurrent::run(&UpdateCacheTask::doTask, task));
}
/*
@@ -544,12 +513,10 @@ void MetadataJob::xmlTaskFinished()
if (!fetchMetaDataPackages()) {
// No new metadata packages to fetch, still need to update the cache
// for refreshed repositories.
- if (updateCache())
- emitFinished();
+ startUpdateCacheTask();
}
} else {
- if (updateCache())
- emitFinished();
+ startUpdateCacheTask();
}
} else if (status == XmlDownloadRetry) {
QMetaObject::invokeMethod(this, "doStart", Qt::QueuedConnection);
@@ -579,13 +546,8 @@ void MetadataJob::unzipTaskFinished()
m_unzipTasks.remove(watcher);
delete watcher;
- if (m_unzipTasks.isEmpty()) {
- if (!updateCache())
- return;
-
- setProcessedAmount(100);
- emitFinished();
- }
+ if (m_unzipTasks.isEmpty())
+ startUpdateCacheTask();
}
void MetadataJob::progressChanged(int progress)
@@ -627,8 +589,7 @@ void MetadataJob::metadataTaskFinished()
watcher->setFuture(QtConcurrent::run(&UnzipArchiveTask::doTask, task));
}
} else {
- if (updateCache())
- emitFinished();
+ startUpdateCacheTask();
}
}
} catch (const TaskException &e) {
@@ -643,6 +604,25 @@ void MetadataJob::metadataTaskFinished()
}
}
+void MetadataJob::updateCacheTaskFinished()
+{
+ try {
+ m_updateCacheTask.waitForFinished();
+ } catch (const CacheTaskException &e) {
+ emitFinishedWithError(QInstaller::CacheError, e.message());
+ } catch (const QUnhandledException &e) {
+ emitFinishedWithError(QInstaller::CacheError, QLatin1String(e.what()));
+ } catch (...) {
+ emitFinishedWithError(QInstaller::CacheError, tr("Unknown exception during updating cache."));
+ }
+
+ if (error() != Job::NoError)
+ return;
+
+ setProcessedAmount(100);
+ emitFinished();
+}
+
// -- private
diff --git a/src/libs/installer/metadatajob.h b/src/libs/installer/metadatajob.h
index c0412b9cd..9e8116124 100644
--- a/src/libs/installer/metadatajob.h
+++ b/src/libs/installer/metadatajob.h
@@ -83,6 +83,7 @@ private slots:
void xmlTaskFinished();
void unzipTaskFinished();
void metadataTaskFinished();
+ void updateCacheTaskFinished();
void progressChanged(int progress);
void setProgressTotalAmount(int maximum);
void unzipRepositoryTaskFinished();
@@ -91,7 +92,7 @@ private slots:
private:
bool fetchMetaDataPackages();
void startUnzipRepositoryTask(const Repository &repo);
- bool updateCache();
+ void startUpdateCacheTask();
void resetCacheRepositories();
void reset();
void resetCompressedFetch();
@@ -117,6 +118,7 @@ private:
TempPathDeleter m_tempDirDeleter;
QFutureWatcher<FileTaskResult> m_xmlTask;
QFutureWatcher<FileTaskResult> m_metadataTask;
+ QFutureWatcher<void> m_updateCacheTask;
QHash<QFutureWatcher<void> *, QObject*> m_unzipTasks;
QHash<QFutureWatcher<void> *, QObject*> m_unzipRepositoryTasks;
DownloadType m_downloadType;
diff --git a/src/libs/installer/metadatajob_p.h b/src/libs/installer/metadatajob_p.h
index 2456a971e..5a4fcad2d 100644
--- a/src/libs/installer/metadatajob_p.h
+++ b/src/libs/installer/metadatajob_p.h
@@ -99,6 +99,81 @@ private:
QString m_targetDir;
};
+class CacheTaskException : public QException
+{
+public:
+ CacheTaskException() {}
+ explicit CacheTaskException(const QString &message)
+ : m_message(message)
+ {}
+ ~CacheTaskException() {}
+
+ void raise() const override { throw *this; }
+ QString message() const { return m_message; }
+ CacheTaskException *clone() const override { return new CacheTaskException(*this); }
+
+private:
+ QString m_message;
+};
+
+class UpdateCacheTask : public AbstractTask<void>
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(UpdateCacheTask)
+
+public:
+ UpdateCacheTask(GenericDataCache<Metadata> &cache, QHash<QString, Metadata *> &updates)
+ : m_cache(&cache)
+ , m_updates(&updates)
+ {}
+
+ void doTask(QFutureInterface<void> &fi) override
+ {
+ fi.reportStarted();
+ fi.setExpectedResultCount(1);
+
+ // Register items from current run to cache
+ QStringList registeredKeys;
+ bool success = true;
+ for (auto *meta : qAsConst(*m_updates)) {
+ if (!m_cache->registerItem(meta, true)) {
+ success = false;
+ break;
+ }
+ meta->setPersistentRepositoryPath(meta->repository().url());
+ registeredKeys.append(m_updates->key(meta));
+ }
+ // Remove items whose ownership was transferred to cache
+ for (auto &key : qAsConst(registeredKeys))
+ m_updates->remove(key);
+
+ // Bail out if there was error while registering items
+ if (!success) {
+ fi.reportException(UnzipArchiveException(m_cache->errorString() + u' '
+ + MetadataJob::tr("Clearing the cache directory and restarting the application may solve this.")));
+ m_cache->sync();
+ fi.reportFinished();
+ return;
+ }
+
+ // ...and clean up obsolete cached items
+ const QList<Metadata *> obsolete = m_cache->obsoleteItems();
+ for (auto *meta : obsolete)
+ m_cache->removeItem(meta->checksum());
+
+ if (!m_cache->sync()) {
+ fi.reportException(UnzipArchiveException(m_cache->errorString() + u' '
+ + MetadataJob::tr("Clearing the cache directory and restarting the application may solve this.")));
+ }
+
+ fi.reportFinished();
+ }
+
+private:
+ GenericDataCache<Metadata> *const m_cache;
+ QHash<QString, Metadata *> *const m_updates;
+};
+
} // namespace QInstaller
#endif // METADATAJOB_P_H