summaryrefslogtreecommitdiffstats
path: root/src/libs/installer
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-10-26 15:02:18 +0300
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2022-11-14 17:27:20 +0200
commit869fafed0ca087c56015088f2ab7d530a4a79e76 (patch)
tree9f0b7c2570bf7e04dceef893ac38c21cba14a2c0 /src/libs/installer
parentc5500a34e21f548533dea60d7c912882c56fe801 (diff)
Metadata cache: clear cache in a separate thread
This removes the visible blocked UI while clearing cache items, which takes some time. Disable controls on the dialog and show a basic progress bar while the clearing is in progress. Also add basic access serialization to GenericDataCache<T> class public methods. It is still possible that the user closes the settings dialog with other means before the clearing in a separate thread was completed, and we want to avoid crashing to race conditions in such case. If the user manages to navigate forward in installer pages, to fetch metadata again, it wouldn't still work correctly though. Task-number: QTIFW-2815 Change-Id: Ic2c0feac44aff69c458105cf0f559e8693fc0d69 Reviewed-by: Iikka Eklund <iikka.eklund@qt.io> Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src/libs/installer')
-rw-r--r--src/libs/installer/genericdatacache.cpp68
-rw-r--r--src/libs/installer/genericdatacache.h5
2 files changed, 52 insertions, 21 deletions
diff --git a/src/libs/installer/genericdatacache.cpp b/src/libs/installer/genericdatacache.cpp
index 1b33976c8..b70cbcb0b 100644
--- a/src/libs/installer/genericdatacache.cpp
+++ b/src/libs/installer/genericdatacache.cpp
@@ -174,6 +174,7 @@ GenericDataCache<T>::~GenericDataCache()
template<typename T>
void GenericDataCache<T>::setType(const QString &type)
{
+ QMutexLocker _(&m_mutex);
m_type = type;
}
@@ -186,6 +187,7 @@ void GenericDataCache<T>::setType(const QString &type)
template<typename T>
void GenericDataCache<T>::setVersion(const QString &version)
{
+ QMutexLocker _(&m_mutex);
m_version = version;
}
@@ -200,6 +202,7 @@ void GenericDataCache<T>::setVersion(const QString &version)
template <typename T>
bool GenericDataCache<T>::initialize()
{
+ QMutexLocker _(&m_mutex);
Q_ASSERT(m_items.isEmpty());
if (m_path.isEmpty()) {
@@ -247,6 +250,7 @@ bool GenericDataCache<T>::initialize()
template <typename T>
bool GenericDataCache<T>::clear()
{
+ QMutexLocker _(&m_mutex);
if (m_invalidated) {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot clear invalidated cache."));
@@ -286,6 +290,7 @@ bool GenericDataCache<T>::clear()
template<typename T>
bool GenericDataCache<T>::sync()
{
+ QMutexLocker _(&m_mutex);
if (m_invalidated) {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot synchronize invalidated cache."));
@@ -303,6 +308,7 @@ bool GenericDataCache<T>::sync()
template<typename T>
bool GenericDataCache<T>::isValid() const
{
+ QMutexLocker _(&m_mutex);
return !m_invalidated;
}
@@ -314,6 +320,7 @@ bool GenericDataCache<T>::isValid() const
template<typename T>
QString GenericDataCache<T>::errorString() const
{
+ QMutexLocker _(&m_mutex);
return m_error;
}
@@ -325,6 +332,7 @@ QString GenericDataCache<T>::errorString() const
template <typename T>
QString GenericDataCache<T>::path() const
{
+ QMutexLocker _(&m_mutex);
return m_path;
}
@@ -337,6 +345,7 @@ QString GenericDataCache<T>::path() const
template <typename T>
void GenericDataCache<T>::setPath(const QString &path)
{
+ QMutexLocker _(&m_mutex);
if (!m_invalidated)
toDisk();
@@ -352,6 +361,7 @@ void GenericDataCache<T>::setPath(const QString &path)
template <typename T>
QList<T *> GenericDataCache<T>::items() const
{
+ QMutexLocker _(&m_mutex);
if (m_invalidated) {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot retrieve items from invalidated cache."));
@@ -369,6 +379,7 @@ QList<T *> GenericDataCache<T>::items() const
template <typename T>
T *GenericDataCache<T>::itemByChecksum(const QByteArray &checksum) const
{
+ QMutexLocker _(&m_mutex);
if (m_invalidated) {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot retrieve item from invalidated cache."));
@@ -387,6 +398,7 @@ T *GenericDataCache<T>::itemByChecksum(const QByteArray &checksum) const
template <typename T>
T *GenericDataCache<T>::itemByPath(const QString &path) const
{
+ QMutexLocker _(&m_mutex);
auto it = std::find_if(m_items.constBegin(), m_items.constEnd(),
[&](T *item) {
return (QDir::fromNativeSeparators(path) == QDir::fromNativeSeparators(item->path()));
@@ -413,6 +425,7 @@ T *GenericDataCache<T>::itemByPath(const QString &path) const
template <typename T>
bool GenericDataCache<T>::registerItem(T *item, bool replace)
{
+ QMutexLocker _(&m_mutex);
if (m_invalidated) {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot register item to invalidated cache."));
@@ -430,7 +443,7 @@ bool GenericDataCache<T>::registerItem(T *item, bool replace)
}
if (m_items.contains(item->checksum())) {
if (replace) {// replace existing item including contents on disk
- removeItem(item->checksum());
+ remove(item->checksum());
} else {
setErrorString(QCoreApplication::translate("GenericDataCache",
"Cannot register item with checksum %1. An item with the same checksum "
@@ -470,26 +483,8 @@ bool GenericDataCache<T>::registerItem(T *item, bool replace)
template <typename T>
bool GenericDataCache<T>::removeItem(const QByteArray &checksum)
{
- if (m_invalidated) {
- setErrorString(QCoreApplication::translate("GenericDataCache",
- "Cannot remove item from invalidated cache."));
- return false;
- }
- QScopedPointer<T> item(m_items.take(checksum));
- if (!item) {
- setErrorString(QCoreApplication::translate("GenericDataCache",
- "Cannot remove item specified by checksum %1: no such item exists.").arg(QLatin1String(checksum)));
- return false;
- }
-
- try {
- QInstaller::removeDirectory(item->path());
- } catch (const Error &e) {
- setErrorString(QCoreApplication::translate("GenericDataCache",
- "Error while removing directory \"%1\": %2").arg(item->path(), e.message()));
- return false;
- }
- return true;
+ QMutexLocker _(&m_mutex);
+ return remove(checksum);
}
/*!
@@ -500,6 +495,7 @@ bool GenericDataCache<T>::removeItem(const QByteArray &checksum)
template<typename T>
QList<T *> GenericDataCache<T>::obsoleteItems() const
{
+ QMutexLocker _(&m_mutex);
const QList<T *> obsoletes = QtConcurrent::blockingFiltered(m_items.values(),
[&](T *item1) {
if (item1->isActive()) // We can skip the iteration for active entries
@@ -638,6 +634,36 @@ bool GenericDataCache<T>::toDisk()
return true;
}
+/*!
+ \fn template <typename T> QInstaller::GenericDataCache<T>::remove(const QByteArray &checksum)
+
+ \internal
+*/
+template<typename T>
+bool GenericDataCache<T>::remove(const QByteArray &checksum)
+{
+ if (m_invalidated) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot remove item from invalidated cache."));
+ return false;
+ }
+ QScopedPointer<T> item(m_items.take(checksum));
+ if (!item) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Cannot remove item specified by checksum %1: no such item exists.").arg(QLatin1String(checksum)));
+ return false;
+ }
+
+ try {
+ QInstaller::removeDirectory(item->path());
+ } catch (const Error &e) {
+ setErrorString(QCoreApplication::translate("GenericDataCache",
+ "Error while removing directory \"%1\": %2").arg(item->path(), e.message()));
+ return false;
+ }
+ return true;
+}
+
template class GenericDataCache<Metadata>;
} // namespace QInstaller
diff --git a/src/libs/installer/genericdatacache.h b/src/libs/installer/genericdatacache.h
index 5042ed9a4..2bdf6697e 100644
--- a/src/libs/installer/genericdatacache.h
+++ b/src/libs/installer/genericdatacache.h
@@ -33,6 +33,7 @@
#include "lockfile.h"
#include <QHash>
+#include <QMutex>
#include <QScopedPointer>
namespace QInstaller {
@@ -96,8 +97,12 @@ private:
bool fromDisk();
bool toDisk();
+ bool remove(const QByteArray &checksum);
+
private:
QScopedPointer<KDUpdater::LockFile> m_lock;
+ mutable QMutex m_mutex;
+
QHash<QByteArray, T *> m_items;
QString m_path;
QString m_type;