mirror of
https://github.com/ostreedev/ostree.git
synced 2025-01-05 13:18:17 +03:00
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.
This commit is contained in:
parent
5bf4b1dabc
commit
c987534595
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user