ref_transaction_prepare(): new optional step for reference updates
In the future, compound reference stores will sometimes need to modify references in two different reference stores at the same time, meaning that a single logical reference transaction might have to be implemented as two internal sub-transactions. They won't want to call `ref_transaction_commit()` for the two sub-transactions one after the other, because that wouldn't be atomic (the first commit could succeed and the second one fail). Instead, they will want to prepare both sub-transactions (i.e., obtain any necessary locks and do any pre-checks), and only if both prepare steps succeed, then commit both sub-transactions. Start preparing for that day by adding a new, optional `ref_transaction_prepare()` step to the reference transaction sequence, which obtains the locks and does any prechecks, reporting any errors that occur. Also add a `ref_transaction_abort()` function that can be used to abort a sub-transaction even if it has already been prepared. That is on the side of the public-facing API. On the side of the `ref_store` VTABLE, get rid of `transaction_commit` and instead add methods `transaction_prepare`, `transaction_finish`, and `transaction_abort`. A `ref_transaction_commit()` now basically calls methods `transaction_prepare` then `transaction_finish`. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
8d4240d3c8
commit
30173b8851
@ -185,17 +185,27 @@ struct ref_update *ref_transaction_add_update(
|
||||
|
||||
/*
|
||||
* Transaction states.
|
||||
* OPEN: The transaction is in a valid state and can accept new updates.
|
||||
* An OPEN transaction can be committed.
|
||||
* CLOSED: A closed transaction is no longer active and no other operations
|
||||
* than free can be used on it in this state.
|
||||
* A transaction can either become closed by successfully committing
|
||||
* an active transaction or if there is a failure while building
|
||||
* the transaction thus rendering it failed/inactive.
|
||||
*
|
||||
* OPEN: The transaction is initialized and new updates can still be
|
||||
* added to it. An OPEN transaction can be prepared,
|
||||
* committed, freed, or aborted (freeing and aborting an open
|
||||
* transaction are equivalent).
|
||||
*
|
||||
* PREPARED: ref_transaction_prepare(), which locks all of the
|
||||
* references involved in the update and checks that the
|
||||
* update has no errors, has been called successfully for the
|
||||
* transaction. A PREPARED transaction can be committed or
|
||||
* aborted.
|
||||
*
|
||||
* CLOSED: The transaction is no longer active. A transaction becomes
|
||||
* CLOSED if there is a failure while building the transaction
|
||||
* or if a transaction is committed or aborted. A CLOSED
|
||||
* transaction can only be freed.
|
||||
*/
|
||||
enum ref_transaction_state {
|
||||
REF_TRANSACTION_OPEN = 0,
|
||||
REF_TRANSACTION_CLOSED = 1
|
||||
REF_TRANSACTION_OPEN = 0,
|
||||
REF_TRANSACTION_PREPARED = 1,
|
||||
REF_TRANSACTION_CLOSED = 2
|
||||
};
|
||||
|
||||
/*
|
||||
@ -497,6 +507,18 @@ typedef struct ref_store *ref_store_init_fn(const char *gitdir,
|
||||
|
||||
typedef int ref_init_db_fn(struct ref_store *refs, struct strbuf *err);
|
||||
|
||||
typedef int ref_transaction_prepare_fn(struct ref_store *refs,
|
||||
struct ref_transaction *transaction,
|
||||
struct strbuf *err);
|
||||
|
||||
typedef int ref_transaction_finish_fn(struct ref_store *refs,
|
||||
struct ref_transaction *transaction,
|
||||
struct strbuf *err);
|
||||
|
||||
typedef int ref_transaction_abort_fn(struct ref_store *refs,
|
||||
struct ref_transaction *transaction,
|
||||
struct strbuf *err);
|
||||
|
||||
typedef int ref_transaction_commit_fn(struct ref_store *refs,
|
||||
struct ref_transaction *transaction,
|
||||
struct strbuf *err);
|
||||
@ -600,7 +622,10 @@ struct ref_storage_be {
|
||||
const char *name;
|
||||
ref_store_init_fn *init;
|
||||
ref_init_db_fn *init_db;
|
||||
ref_transaction_commit_fn *transaction_commit;
|
||||
|
||||
ref_transaction_prepare_fn *transaction_prepare;
|
||||
ref_transaction_finish_fn *transaction_finish;
|
||||
ref_transaction_abort_fn *transaction_abort;
|
||||
ref_transaction_commit_fn *initial_transaction_commit;
|
||||
|
||||
pack_refs_fn *pack_refs;
|
||||
|
Reference in New Issue
Block a user