Commit 664ecc45 authored by Aleix Pol Gonzalez's avatar Aleix Pol Gonzalez 🐧
Browse files

snap: run snap jobs synchronously on a separate thread

Rather than using runAsync, which seems to get confused when executing
in parallel.
We limit to 1 thread to make sure we don't run into the same problem.

CCBUG: 427244
parent be1ca46c
add_subdirectory(libsnapclient) add_subdirectory(libsnapclient)
add_library(snap-backend MODULE SnapResource.cpp SnapBackend.cpp SnapTransaction.cpp snapui.qrc) add_library(snap-backend MODULE SnapResource.cpp SnapBackend.cpp SnapTransaction.cpp snapui.qrc)
target_link_libraries(snap-backend Qt5::Core KF5::CoreAddons KF5::ConfigCore Discover::Common Snapd::Core) target_link_libraries(snap-backend Qt5::Core Qt5::Concurrent KF5::CoreAddons KF5::ConfigCore Discover::Common Snapd::Core)
if ("${Snapd_VERSION}" VERSION_GREATER 1.40) if ("${Snapd_VERSION}" VERSION_GREATER 1.40)
target_compile_definitions(snap-backend PRIVATE -DSNAP_COMMON_IDS -DSNAP_CHANNELS) target_compile_definitions(snap-backend PRIVATE -DSNAP_COMMON_IDS -DSNAP_CHANNELS)
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
#include <QTimer> #include <QTimer>
#include <QAction> #include <QAction>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QtConcurrentMap>
#include <QtConcurrentRun>
#include <QFuture>
#include <QFutureWatcher>
#include "utils.h" #include "utils.h"
...@@ -65,9 +69,16 @@ SnapBackend::SnapBackend(QObject* parent) ...@@ -65,9 +69,16 @@ SnapBackend::SnapBackend(QObject* parent)
refreshStates(); refreshStates();
SourcesModel::global()->addSourcesBackend(new SnapSourcesBackend(this)); SourcesModel::global()->addSourcesBackend(new SnapSourcesBackend(this));
m_threadPool.setMaxThreadCount(1);
} }
SnapBackend::~SnapBackend() = default; SnapBackend::~SnapBackend()
{
Q_EMIT shuttingDown();
m_threadPool.waitForDone(80000);
m_threadPool.clear();
}
int SnapBackend::updatesCount() const int SnapBackend::updatesCount() const
{ {
...@@ -127,23 +138,24 @@ template <class T> ...@@ -127,23 +138,24 @@ template <class T>
ResultsStream* SnapBackend::populateJobsWithFilter(const QVector<T*>& jobs, std::function<bool(const QSharedPointer<QSnapdSnap>& s)>& filter) ResultsStream* SnapBackend::populateJobsWithFilter(const QVector<T*>& jobs, std::function<bool(const QSharedPointer<QSnapdSnap>& s)>& filter)
{ {
auto stream = new ResultsStream(QStringLiteral("Snap-populate")); auto stream = new ResultsStream(QStringLiteral("Snap-populate"));
stream->setProperty("remaining", jobs.count()); auto future = QtConcurrent::run(&m_threadPool, [this, jobs] () {
for(auto job : jobs) { for (auto job : jobs) {
connect(job, &T::complete, stream, [stream, this, job, filter]() { connect(this, &SnapBackend::shuttingDown, job, &T::cancel);
const int remaining = stream->property("remaining").toInt() - 1; job->runSync();
stream->setProperty("remaining", remaining); }
});
auto watcher = new QFutureWatcher<void>(this);
watcher->setFuture(future);
connect(watcher, &QFutureWatcher<void>::finished, watcher, &QObject::deleteLater);
connect(watcher, &QFutureWatcher<void>::finished, stream, [this, jobs, filter, stream] {
QVector<AbstractResource*> ret;
for (auto job : jobs) {
if (job->error()) { if (job->error()) {
qDebug() << "error:" << job->error() << job->errorString(); qDebug() << "error:" << job->error() << job->errorString();
if (remaining == 0) continue;
stream->finish();
return;
} }
QVector<AbstractResource*> ret;
QVector<SnapResource*> resources;
ret.reserve(job->snapCount());
resources.reserve(job->snapCount());
for (int i=0, c=job->snapCount(); i<c; ++i) { for (int i=0, c=job->snapCount(); i<c; ++i) {
QSharedPointer<QSnapdSnap> snap(job->snap(i)); QSharedPointer<QSnapdSnap> snap(job->snap(i));
...@@ -151,28 +163,21 @@ ResultsStream* SnapBackend::populateJobsWithFilter(const QVector<T*>& jobs, std: ...@@ -151,28 +163,21 @@ ResultsStream* SnapBackend::populateJobsWithFilter(const QVector<T*>& jobs, std:
continue; continue;
const auto snapname = snap->name(); const auto snapname = snap->name();
SnapResource* res = m_resources.value(snapname); SnapResource*& res = m_resources[snapname];
if (!res) { if (!res) {
res = new SnapResource(snap, AbstractResource::None, this); res = new SnapResource(snap, AbstractResource::None, this);
Q_ASSERT(res->packageName() == snapname); Q_ASSERT(res->packageName() == snapname);
resources += res;
} else { } else {
res->setSnap(snap); res->setSnap(snap);
} }
ret += res; ret += res;
} }
}
foreach(SnapResource* res, resources) if (!ret.isEmpty())
m_resources[res->packageName()] = res; Q_EMIT stream->resourcesFound(ret);
stream->finish();
if (!ret.isEmpty()) });
Q_EMIT stream->resourcesFound(ret);
if (remaining == 0)
stream->finish();
});
job->runAsync();
}
return stream; return stream;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <resources/AbstractResourcesBackend.h> #include <resources/AbstractResourcesBackend.h>
#include <QVariantList> #include <QVariantList>
#include <QVector> #include <QVector>
#include <QThreadPool>
#include <Snapd/Client> #include <Snapd/Client>
#include <functional> #include <functional>
...@@ -42,6 +43,9 @@ public: ...@@ -42,6 +43,9 @@ public:
QSnapdClient* client() { return &m_client; } QSnapdClient* client() { return &m_client; }
void refreshStates(); void refreshStates();
Q_SIGNALS:
void shuttingDown();
private: private:
void setFetching(bool fetching); void setFetching(bool fetching);
...@@ -64,6 +68,7 @@ private: ...@@ -64,6 +68,7 @@ private:
bool m_valid = true; bool m_valid = true;
bool m_fetching = false; bool m_fetching = false;
QSnapdClient m_client; QSnapdClient m_client;
QThreadPool m_threadPool;
}; };
#endif // SNAPBACKEND_H #endif // SNAPBACKEND_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment