diff options
author | Gatis Paeglis <gatis.paeglis@qt.io> | 2016-12-02 12:31:15 +0100 |
---|---|---|
committer | Gatis Paeglis <gatis.paeglis@qt.io> | 2016-12-16 16:29:04 +0000 |
commit | 3522fbe467130fade14b491b9af25cb22dedb183 (patch) | |
tree | 1b37814077da2bfbac581ca978eb078783488a6a /src/lib/qotaclientasync.cpp | |
parent | 58216f77bdaac79d43dd611675862c40ae25dfea (diff) |
Remove process locking and refactor singal handling
1) refactor signal handling for tracking default
revision in its own signal. This allows to remove
an unnecessary indirection and helps to improve
revision-change-handling when the deployment list
has changed.
2) remove multi-process locking..
.. as it was based on incorrect assumptions on
how concurrency is handled by OSTree.
OSTree has API to lock the sysroot, but not the
repository itself. As we can not lock the repo
and writes to the repo are atomic, reading from
the repo in general is safe. Except when the data
has been read, there is no guarantee that the data
won't disapear under us (because some other process
has done repo pruning).
Concurrent writing to the repo is handled by OSTree.
When we deploy new sysroot version via "ostree deploy",
it locks the sysroot with the sysroot locking API, so
we don't need to do any additinal locking.
Change-Id: Ide593f9bfbe93827093a6693eeb10cc3b315e000
Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
Diffstat (limited to 'src/lib/qotaclientasync.cpp')
-rw-r--r-- | src/lib/qotaclientasync.cpp | 140 |
1 files changed, 55 insertions, 85 deletions
diff --git a/src/lib/qotaclientasync.cpp b/src/lib/qotaclientasync.cpp index 9623bc7..c62fdd0 100644 --- a/src/lib/qotaclientasync.cpp +++ b/src/lib/qotaclientasync.cpp @@ -42,7 +42,7 @@ QT_BEGIN_NAMESPACE #define OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT "(a{sv}tayay" OSTREE_COMMIT_GVARIANT_STRING "aya" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT "a" OSTREE_STATIC_DELTA_FALLBACK_FORMAT ")" QOtaClientAsync::QOtaClientAsync() : - m_sysroot(ostree_sysroot_new(0)) + m_sysroot(ostree_sysroot_new_default()) { // async mapper connect(this, &QOtaClientAsync::initialize, this, &QOtaClientAsync::_initialize); @@ -55,7 +55,7 @@ QOtaClientAsync::QOtaClientAsync() : QOtaClientAsync::~QOtaClientAsync() { - g_object_unref (m_sysroot); + ostree_sysroot_unload (m_sysroot); } static void parseErrorString(QString *error) @@ -144,61 +144,37 @@ QJsonDocument QOtaClientAsync::info(QOtaClientPrivate::QueryTarget target, bool return jsonInfo; } -bool QOtaClientAsync::multiprocessLock(const QString &method) -{ - qCDebug(qota) << QTime::currentTime().toString() << method << "- waiting for lock..."; - GError *error = nullptr; - ostree_sysroot_lock (m_sysroot, &error); - if (emitGError(error)) - return false; - qCDebug(qota) << QTime::currentTime().toString() << "lock acquired"; - return true; -} - -void QOtaClientAsync::multiprocessUnlock() -{ - ostree_sysroot_unlock (m_sysroot); - qCDebug(qota) << QTime::currentTime().toString() << "lock released"; -} - -QString QOtaClientAsync::defaultRevision() -{ - g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (m_sysroot); - OstreeDeployment *firstDeployment = (OstreeDeployment*)deployments->pdata[0]; - return QLatin1String(ostree_deployment_get_csum (firstDeployment)); -} - void QOtaClientAsync::_initialize() { - if (!multiprocessLock(QStringLiteral("_initialize"))) + GError *error = nullptr; + if (!ostree_sysroot_load (m_sysroot, 0, &error) || + !ostree_sysroot_get_repo (m_sysroot, &m_repo, 0, &error)) { + emitGError(error); + emit initializeFinished(false); return; + } - // intentionally let the initialization to complete, even if some errors occur. - GError *error = nullptr; - ostree_sysroot_load (m_sysroot, 0, &error); - emitGError(error); - ostree_sysroot_get_repo (m_sysroot, &m_repo, 0, &error); - emitGError(error); + handleRevisionChanges(); - OstreeDeployment *bootedDeployment = (OstreeDeployment*)ostree_sysroot_get_booted_deployment (m_sysroot); - QString bootedRev = QLatin1String(ostree_deployment_get_csum (bootedDeployment)); bool ok = true; - QJsonDocument bootedInfo = info(QOtaClientPrivate::QueryTarget::Booted, &ok); - QString defaultRev = defaultRevision(); // prepopulate with what we think is on the remote server (head of the local repo) QString remoteRev = ostree(QStringLiteral("ostree rev-parse linux/qt"), &ok); - QJsonDocument remoteInfo = info(QOtaClientPrivate::QueryTarget::Remote, &ok, remoteRev); - - resetRollbackState(); + QJsonDocument remoteInfo; + if (ok) remoteInfo = info(QOtaClientPrivate::QueryTarget::Remote, &ok, remoteRev); + if (!ok) { + emit initializeFinished(false); + return; + } emit remoteInfoChanged(remoteRev, remoteInfo); - emit initializeFinished(defaultRev, bootedRev, bootedInfo); - multiprocessUnlock(); + + OstreeDeployment *bootedDeployment = (OstreeDeployment*)ostree_sysroot_get_booted_deployment (m_sysroot); + QString bootedRev = QLatin1String(ostree_deployment_get_csum (bootedDeployment)); + QJsonDocument bootedInfo = info(QOtaClientPrivate::QueryTarget::Booted, &ok); + emit initializeFinished(ok, bootedRev, bootedInfo); } void QOtaClientAsync::_fetchRemoteInfo() { - if (!multiprocessLock(QStringLiteral("_fetchRemoteInfo"))) - return; QString remoteRev; QJsonDocument remoteInfo; bool ok = true; @@ -208,7 +184,6 @@ void QOtaClientAsync::_fetchRemoteInfo() if (ok) remoteInfo = info(QOtaClientPrivate::QueryTarget::Remote, &ok, remoteRev); if (ok) emit remoteInfoChanged(remoteRev, remoteInfo); emit fetchRemoteInfoFinished(ok); - multiprocessUnlock(); } bool QOtaClientAsync::deployCommit(const QString &commit) @@ -235,26 +210,23 @@ bool QOtaClientAsync::deployCommit(const QString &commit) void QOtaClientAsync::_update(const QString &updateToRev) { - if (!multiprocessLock(QStringLiteral("_update"))) - return; bool ok = true; - QString defaultRev; GError *error = nullptr; emit statusStringChanged(QStringLiteral("Checking for missing objects...")); ostree(QString(QStringLiteral("ostree pull qt-os:%1")).arg(updateToRev), &ok, true); - multiprocessUnlock(); - if (!ok || deployCommit(updateToRev)) - goto out; - - ostree_sysroot_load (m_sysroot, 0, &error); - if (emitGError(error)) + if (!ok || !deployCommit(updateToRev)) { + emit updateFinished(false); return; + } - resetRollbackState(); - defaultRev = defaultRevision(); + if (!ostree_sysroot_load (m_sysroot, 0, &error)) { + emitGError(error); + emit updateFinished(false); + return; + } -out: - emit updateFinished(defaultRev, ok); + handleRevisionChanges(); + emit updateFinished(ok); } int QOtaClientAsync::rollbackIndex() @@ -270,25 +242,21 @@ int QOtaClientAsync::rollbackIndex() return 1; } -void QOtaClientAsync::resetRollbackState() +void QOtaClientAsync::handleRevisionChanges() { - int index = rollbackIndex(); - if (index == -1) - return; - g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (m_sysroot); - OstreeDeployment *rollbackDeployment = (OstreeDeployment*)deployments->pdata[index]; - QString rollbackRev = QLatin1String(ostree_deployment_get_csum (rollbackDeployment)); - bool ok = true; - QJsonDocument rollbackInfo = info(QOtaClientPrivate::QueryTarget::Rollback, &ok, rollbackRev); - emit rollbackChanged(rollbackRev, rollbackInfo, deployments->len); -} + OstreeDeployment *firstDeployment = (OstreeDeployment*)deployments->pdata[0]; + QString defaultRev(QLatin1String(ostree_deployment_get_csum (firstDeployment))); + emit defaultRevisionChanged(defaultRev); -void QOtaClientAsync::emitRollbackFailed(const QString &error) -{ - emit errorOccurred(error); - emit rollbackFinished(QStringLiteral(""), false); - multiprocessUnlock(); + int index = rollbackIndex(); + if (index != -1) { + OstreeDeployment *rollbackDeployment = (OstreeDeployment*)deployments->pdata[index]; + QString rollbackRev(QLatin1String(ostree_deployment_get_csum (rollbackDeployment))); + bool ok = true; + QJsonDocument rollbackInfo = info(QOtaClientPrivate::QueryTarget::Rollback, &ok, rollbackRev); + emit rollbackInfoChanged(rollbackRev, rollbackInfo, deployments->len); + } } bool QOtaClientAsync::emitGError(GError *error) @@ -297,22 +265,23 @@ bool QOtaClientAsync::emitGError(GError *error) return false; emit errorOccurred(QString::fromLatin1((error->message))); - multiprocessUnlock(); + g_error_free (error); return true; } void QOtaClientAsync::_rollback() { - if (!multiprocessLock(QStringLiteral("_rollback"))) - return; GError *error = nullptr; - ostree_sysroot_load (m_sysroot, 0, &error); - if (emitGError(error)) + if (!ostree_sysroot_load (m_sysroot, 0, &error)) { + emitGError(error); + emit rollbackFinished(false); return; + } int index = rollbackIndex(); if (index == -1) { - emitRollbackFailed(QStringLiteral("At least 2 system versions required for rollback")); + emit errorOccurred(QStringLiteral("At least 2 system versions required for rollback")); + emit rollbackFinished(false); return; } @@ -328,14 +297,12 @@ void QOtaClientAsync::_rollback() // atomically update bootloader configuration if (!ostree_sysroot_write_deployments (m_sysroot, newDeployments, 0, &error)) { emitGError(error); - emitRollbackFailed(QStringLiteral("Failed to update bootloader configuration")); + emit rollbackFinished(false); return; } - resetRollbackState(); - QString defaultRev = defaultRevision(); - emit rollbackFinished(defaultRev, true); - multiprocessUnlock(); + handleRevisionChanges(); + emit rollbackFinished(true); } bool QOtaClientAsync::extractPackage(const QString &packagePath, QString *updateToRev) @@ -413,6 +380,9 @@ void QOtaClientAsync::_updateOffline(const QString &packagePath) if (!extractPackage(packagePath, &rev) || !deployCommit(rev)) success = false; + if (success) + handleRevisionChanges(); + emit updateOfflineFinished(success); } |