diff options
author | Luca BRUNO <luca.bruno@coreos.com> | 2021-10-01 16:04:02 +0000 |
---|---|---|
committer | Luca BRUNO <luca.bruno@coreos.com> | 2021-10-05 12:23:22 +0000 |
commit | c9875345959fb4a028a7596b643d922a952277d0 (patch) | |
tree | 9fde928d4c10a451b6d91fe5b1a91368fa50f00c /src | |
parent | 5bf4b1dabc12d6caee4f4899c9388a48bb4a72a3 (diff) | |
download | ostree-c9875345959fb4a028a7596b643d922a952277d0.tar.gz |
repo/private: allow committing/aborting through a transaction guard
This enhances the auto-transaction logic, augmenting the scope of a
transaction guard.
It allows committing or aborting a transaction through its guard.
It also supports tracking the completion status of a transaction
guard, avoiding double commits/aborts, while retaining the auto-cleanup
logic.
Diffstat (limited to 'src')
-rw-r--r-- | src/libostree/ostree-repo-commit.c | 10 | ||||
-rw-r--r-- | src/libostree/ostree-repo-private.h | 65 | ||||
-rw-r--r-- | src/libostree/ostree-repo.c | 112 | ||||
-rw-r--r-- | src/libostree/ostree-sysroot-cleanup.c | 4 |
4 files changed, 156 insertions, 35 deletions
diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index c87e8de8..8ac963e7 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -1672,14 +1672,18 @@ ostree_repo_prepare_transaction (OstreeRepo *self, GCancellable *cancellable, GError **error) { + g_assert (self != NULL); + guint64 reserved_bytes = 0; g_return_val_if_fail (self->in_transaction == FALSE, FALSE); g_debug ("Preparing transaction in repository %p", self); - /* Set up to abort the transaction if we return early from this function. */ - g_autoptr(_OstreeRepoAutoTransaction) txn = self; + /* Set up to abort the transaction if we return early from this function. + * This needs to be manually built here due to a circular dependency. */ + g_autoptr(OstreeRepoAutoTransaction) txn = g_malloc(sizeof(OstreeRepoAutoTransaction)); + txn->repo = self; (void) txn; /* Add use to silence static analysis */ memset (&self->txn.stats, 0, sizeof (OstreeRepoTransactionStats)); @@ -1736,7 +1740,7 @@ ostree_repo_prepare_transaction (OstreeRepo *self, return FALSE; /* Success: do not abort the transaction when returning. */ - txn = NULL; (void) txn; + txn->repo = NULL; (void) txn; if (out_transaction_resume) *out_transaction_resume = ret_transaction_resume; diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 67f755bd..a2666dec 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -229,36 +229,6 @@ struct OstreeRepo { OstreeRepo *parent_repo; }; -/* Taken from flatpak; may be made into public API later */ -typedef OstreeRepo _OstreeRepoAutoTransaction; -static inline void -_ostree_repo_auto_transaction_cleanup (void *p) -{ - if (p == NULL) - return; - g_return_if_fail (OSTREE_IS_REPO (p)); - - OstreeRepo *repo = p; - g_autoptr(GError) error = NULL; - - if (!ostree_repo_abort_transaction (repo, NULL, &error)) - g_warning("Failed to auto-cleanup OSTree transaction: %s", error->message); - - g_object_unref (repo); -} - -static inline _OstreeRepoAutoTransaction * -_ostree_repo_auto_transaction_start (OstreeRepo *repo, - GCancellable *cancellable, - GError **error) -{ - if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) - return NULL; - - return (_OstreeRepoAutoTransaction *) g_object_ref (repo); -} -G_DEFINE_AUTOPTR_CLEANUP_FUNC (_OstreeRepoAutoTransaction, _ostree_repo_auto_transaction_cleanup) - typedef struct { dev_t dev; ino_t ino; @@ -544,4 +514,39 @@ _ostree_repo_verify_bindings (const char *collection_id, GVariant *commit, GError **error); +/** + * OstreeRepoAutoTransaction: + * + * A transaction guard for a specific #OstreeRepo. It can be explicitly + * completed through abort/commit. If the guard has not been completed + * beforehand, on cleanup it is automatically aborted. + * + * Taken from flatpak; may be made into public API later + */ +typedef struct +{ + OstreeRepo *repo; +} OstreeRepoAutoTransaction; + +OstreeRepoAutoTransaction * +_ostree_repo_auto_transaction_start (OstreeRepo *repo, + GCancellable *cancellable, + GError **error); + +gboolean +_ostree_repo_auto_transaction_abort (OstreeRepoAutoTransaction *txn, + GCancellable *cancellable, + GError **error); + +gboolean +_ostree_repo_auto_transaction_commit (OstreeRepoAutoTransaction *txn, + OstreeRepoTransactionStats *out_stats, + GCancellable *cancellable, + GError **error); + +void +_ostree_repo_auto_transaction_cleanup (void *p); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoAutoTransaction, _ostree_repo_auto_transaction_cleanup); + G_END_DECLS diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 42d2b0e0..772eae26 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -711,6 +711,118 @@ ostree_repo_auto_lock_cleanup (OstreeRepoAutoLock *auto_lock) } } + +/** + * _ostree_repo_auto_transaction_start: + * @repo: an #OsreeRepo object + * @cancellable: Cancellable + * @error: a #GError + * + * Start a transaction and return a guard for it. + * + * Returns: (transfer full): an #OsreeRepoAutoTransaction guard on success, + * %NULL otherwise. + */ +OstreeRepoAutoTransaction * +_ostree_repo_auto_transaction_start (OstreeRepo *repo, + GCancellable *cancellable, + GError **error) +{ + g_assert (repo != NULL); + + if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error)) + return NULL; + + OstreeRepoAutoTransaction *txn = g_malloc(sizeof(OstreeRepoAutoTransaction)); + txn->repo = g_object_ref (repo); + + return g_steal_pointer (&txn); +} + +/** + * _ostree_repo_auto_transaction_abort: + * @txn: an #OsreeRepoAutoTransaction guard + * @cancellable: Cancellable + * @error: a #GError + * + * Abort a transaction, marking the related guard as completed. + * + * Returns: %TRUE on successful commit, %FALSE otherwise. + */ +gboolean +_ostree_repo_auto_transaction_abort (OstreeRepoAutoTransaction *txn, + GCancellable *cancellable, + GError **error) +{ + g_assert (txn != NULL); + + if (txn->repo == NULL) { + return glnx_throw (error, "transaction already completed"); + } + + if (!ostree_repo_abort_transaction (txn->repo, cancellable, error)) + return FALSE; + + g_clear_object (&txn->repo); + + return TRUE; +} + +/** + * _ostree_repo_auto_transaction_commit: + * @txn: an #OsreeRepoAutoTransaction guard + * @cancellable: Cancellable + * @error: a #GError + * + * Commit a transaction, marking the related guard as completed. + * + * Returns: %TRUE on successful aborting, %FALSE otherwise. + */ +gboolean +_ostree_repo_auto_transaction_commit (OstreeRepoAutoTransaction *txn, + OstreeRepoTransactionStats *out_stats, + GCancellable *cancellable, + GError **error) +{ + g_assert (txn != NULL); + + if (txn->repo == NULL) { + return glnx_throw (error, "transaction already completed"); + } + + if (!ostree_repo_commit_transaction (txn->repo, out_stats, cancellable, error)) + return FALSE; + + g_clear_object (&txn->repo); + + return TRUE; +} + +/** + * _ostree_repo_auto_transaction_cleanup: + * @p: pointer to an #OsreeRepoAutoTransaction guard + * + * Destroy a transaction guard. If the transaction has not yet been completed, + * it gets aborted. + */ +void +_ostree_repo_auto_transaction_cleanup (void *p) +{ + if (p == NULL) + return; + + OstreeRepoAutoTransaction *txn = p; + // Auto-abort only if transaction has not already been aborted/committed. + if (txn->repo != NULL) + { + g_autoptr(GError) error = NULL; + if (!_ostree_repo_auto_transaction_abort (txn, NULL, &error)) { + g_warning("Failed to auto-cleanup OSTree transaction: %s", error->message); + g_clear_object (&txn->repo); + } + } +} + static GFile * get_remotes_d_dir (OstreeRepo *self, GFile *sysroot); diff --git a/src/libostree/ostree-sysroot-cleanup.c b/src/libostree/ostree-sysroot-cleanup.c index 91381cb0..c22a6851 100644 --- a/src/libostree/ostree-sysroot-cleanup.c +++ b/src/libostree/ostree-sysroot-cleanup.c @@ -445,7 +445,7 @@ generate_deployment_refs (OstreeSysroot *self, cancellable, error)) return FALSE; - g_autoptr(_OstreeRepoAutoTransaction) txn = + g_autoptr(OstreeRepoAutoTransaction) txn = _ostree_repo_auto_transaction_start (repo, cancellable, error); if (!txn) return FALSE; @@ -458,7 +458,7 @@ generate_deployment_refs (OstreeSysroot *self, ostree_repo_transaction_set_refspec (repo, refname, ostree_deployment_get_csum (deployment)); } - if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error)) + if (!_ostree_repo_auto_transaction_commit (txn, NULL, cancellable, error)) return FALSE; return TRUE; |