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>

Michael Haggerty committed May 22, 2017 at 16:17 UTC 30173b8851bb7203de938a638386cb9e6d7c501b
4 files changed +253 -53
refs.c
+71 -3
@@ -853,6 +853,19 @@ void ref_transaction_free(struct ref_transaction *transaction)
853 if (!transaction)
854 return;
855
856 + switch (transaction->state) {
857 + case REF_TRANSACTION_OPEN:
858 + case REF_TRANSACTION_CLOSED:
859 + /* OK */
860 + break;
861 + case REF_TRANSACTION_PREPARED:
862 + die("BUG: free called on a prepared reference transaction");
863 + break;
864 + default:
865 + die("BUG: unexpected reference transaction state");
866 + break;
867 + }
868 +
869 for (i = 0; i < transaction->nr; i++) {
870 free(transaction->updates[i]->msg);
871 free(transaction->updates[i]);
@@ -1689,8 +1702,8 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
1702 refs_heads_master, logmsg);
1703 }
1704
1692 -int ref_transaction_commit(struct ref_transaction *transaction,
1693 - struct strbuf *err)
1705 +int ref_transaction_prepare(struct ref_transaction *transaction,
1706 + struct strbuf *err)
1707 {
1708 struct ref_store *refs = transaction->ref_store;
1709
@@ -1698,6 +1711,9 @@ int ref_transaction_commit(struct ref_transaction *transaction,
1711 case REF_TRANSACTION_OPEN:
1712 /* Good. */
1713 break;
1714 + case REF_TRANSACTION_PREPARED:
1715 + die("BUG: prepare called twice on reference transaction");
1716 + break;
1717 case REF_TRANSACTION_CLOSED:
1718 die("BUG: prepare called on a closed reference transaction");
1719 break;
@@ -1712,7 +1728,59 @@ int ref_transaction_commit(struct ref_transaction *transaction,
1728 return -1;
1729 }
1730
1715 - return refs->be->transaction_commit(refs, transaction, err);
1731 + return refs->be->transaction_prepare(refs, transaction, err);
1732 +}
1733 +
1734 +int ref_transaction_abort(struct ref_transaction *transaction,
1735 + struct strbuf *err)
1736 +{
1737 + struct ref_store *refs = transaction->ref_store;
1738 + int ret = 0;
1739 +
1740 + switch (transaction->state) {
1741 + case REF_TRANSACTION_OPEN:
1742 + /* No need to abort explicitly. */
1743 + break;
1744 + case REF_TRANSACTION_PREPARED:
1745 + ret = refs->be->transaction_abort(refs, transaction, err);
1746 + break;
1747 + case REF_TRANSACTION_CLOSED:
1748 + die("BUG: abort called on a closed reference transaction");
1749 + break;
1750 + default:
1751 + die("BUG: unexpected reference transaction state");
1752 + break;
1753 + }
1754 +
1755 + ref_transaction_free(transaction);
1756 + return ret;
1757 +}
1758 +
1759 +int ref_transaction_commit(struct ref_transaction *transaction,
1760 + struct strbuf *err)
1761 +{
1762 + struct ref_store *refs = transaction->ref_store;
1763 + int ret;
1764 +
1765 + switch (transaction->state) {
1766 + case REF_TRANSACTION_OPEN:
1767 + /* Need to prepare first. */
1768 + ret = ref_transaction_prepare(transaction, err);
1769 + if (ret)
1770 + return ret;
1771 + break;
1772 + case REF_TRANSACTION_PREPARED:
1773 + /* Fall through to finish. */
1774 + break;
1775 + case REF_TRANSACTION_CLOSED:
1776 + die("BUG: commit called on a closed reference transaction");
1777 + break;
1778 + default:
1779 + die("BUG: unexpected reference transaction state");
1780 + break;
1781 + }
1782 +
1783 + return refs->be->transaction_finish(refs, transaction, err);
1784 }
1785
1786 int refs_verify_refname_available(struct ref_store *refs,
refs.h
+97 -27
@@ -143,30 +143,71 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
143 int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
144
145 /*
146 - * A ref_transaction represents a collection of ref updates
147 - * that should succeed or fail together.
146 + * A ref_transaction represents a collection of reference updates that
147 + * should succeed or fail together.
148 *
149 * Calling sequence
150 * ----------------
151 + *
152 * - Allocate and initialize a `struct ref_transaction` by calling
153 * `ref_transaction_begin()`.
154 *
154 - * - List intended ref updates by calling functions like
155 - * `ref_transaction_update()` and `ref_transaction_create()`.
156 - *
157 - * - Call `ref_transaction_commit()` to execute the transaction.
158 - * If this succeeds, the ref updates will have taken place and
159 - * the transaction cannot be rolled back.
160 - *
161 - * - Instead of `ref_transaction_commit`, use
162 - * `initial_ref_transaction_commit()` if the ref database is known
163 - * to be empty (e.g. during clone). This is likely to be much
164 - * faster.
165 - *
166 - * - At any time call `ref_transaction_free()` to discard the
167 - * transaction and free associated resources. In particular,
168 - * this rolls back the transaction if it has not been
169 - * successfully committed.
155 + * - Specify the intended ref updates by calling one or more of the
156 + * following functions:
157 + * - `ref_transaction_update()`
158 + * - `ref_transaction_create()`
159 + * - `ref_transaction_delete()`
160 + * - `ref_transaction_verify()`
161 + *
162 + * - Then either:
163 + *
164 + * - Optionally call `ref_transaction_prepare()` to prepare the
165 + * transaction. This locks all references, checks preconditions,
166 + * etc. but doesn't finalize anything. If this step fails, the
167 + * transaction has been closed and can only be freed. If this step
168 + * succeeds, then `ref_transaction_commit()` is almost certain to
169 + * succeed. However, you can still call `ref_transaction_abort()`
170 + * if you decide not to commit the transaction after all.
171 + *
172 + * - Call `ref_transaction_commit()` to execute the transaction,
173 + * make the changes permanent, and release all locks. If you
174 + * haven't already called `ref_transaction_prepare()`, then
175 + * `ref_transaction_commit()` calls it for you.
176 + *
177 + * Or
178 + *
179 + * - Call `initial_ref_transaction_commit()` if the ref database is
180 + * known to be empty and have no other writers (e.g. during
181 + * clone). This is likely to be much faster than
182 + * `ref_transaction_commit()`. `ref_transaction_prepare()` should
183 + * *not* be called before `initial_ref_transaction_commit()`.
184 + *
185 + * - Then finally, call `ref_transaction_free()` to free the
186 + * `ref_transaction` data structure.
187 + *
188 + * At any time before calling `ref_transaction_commit()`, you can call
189 + * `ref_transaction_abort()` to abort the transaction, rollback any
190 + * locks, and free any associated resources (including the
191 + * `ref_transaction` data structure).
192 + *
193 + * Putting it all together, a complete reference update looks like
194 + *
195 + * struct ref_transaction *transaction;
196 + * struct strbuf err = STRBUF_INIT;
197 + * int ret = 0;
198 + *
199 + * transaction = ref_store_transaction_begin(refs, &err);
200 + * if (!transaction ||
201 + * ref_transaction_update(...) ||
202 + * ref_transaction_create(...) ||
203 + * ...etc... ||
204 + * ref_transaction_commit(transaction, &err)) {
205 + * error("%s", err.buf);
206 + * ret = -1;
207 + * }
208 + * ref_transaction_free(transaction);
209 + * strbuf_release(&err);
210 + * return ret;
211 *
212 * Error handling
213 * --------------
@@ -183,8 +224,9 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
224 * -------
225 *
226 * Note that no locks are taken, and no refs are read, until
186 - * `ref_transaction_commit` is called. So `ref_transaction_verify`
187 - * won't report a verification failure until the commit is attempted.
227 + * `ref_transaction_prepare()` or `ref_transaction_commit()` is
228 + * called. So, for example, `ref_transaction_verify()` won't report a
229 + * verification failure until the commit is attempted.
230 */
231 struct ref_transaction;
232
@@ -523,19 +565,47 @@ int ref_transaction_verify(struct ref_transaction *transaction,
565 unsigned int flags,
566 struct strbuf *err);
567
526 -/*
527 - * Commit all of the changes that have been queued in transaction, as
528 - * atomically as possible.
529 - *
530 - * Returns 0 for success, or one of the below error codes for errors.
531 - */
568 /* Naming conflict (for example, the ref names A and A/B conflict). */
569 #define TRANSACTION_NAME_CONFLICT -1
570 /* All other errors. */
571 #define TRANSACTION_GENERIC_ERROR -2
572 +
573 +/*
574 + * Perform the preparatory stages of commiting `transaction`. Acquire
575 + * any needed locks, check preconditions, etc.; basically, do as much
576 + * as possible to ensure that the transaction will be able to go
577 + * through, stopping just short of making any irrevocable or
578 + * user-visible changes. The updates that this function prepares can
579 + * be finished up by calling `ref_transaction_commit()` or rolled back
580 + * by calling `ref_transaction_abort()`.
581 + *
582 + * On success, return 0 and leave the transaction in "prepared" state.
583 + * On failure, abort the transaction, write an error message to `err`,
584 + * and return one of the `TRANSACTION_*` constants.
585 + *
586 + * Callers who don't need such fine-grained control over commiting
587 + * reference transactions should just call `ref_transaction_commit()`.
588 + */
589 +int ref_transaction_prepare(struct ref_transaction *transaction,
590 + struct strbuf *err);
591 +
592 +/*
593 + * Commit all of the changes that have been queued in transaction, as
594 + * atomically as possible. On success, return 0 and leave the
595 + * transaction in "closed" state. On failure, roll back the
596 + * transaction, write an error message to `err`, and return one of the
597 + * `TRANSACTION_*` constants
598 + */
599 int ref_transaction_commit(struct ref_transaction *transaction,
600 struct strbuf *err);
601
602 +/*
603 + * Abort `transaction`, which has been begun and possibly prepared,
604 + * but not yet committed.
605 + */
606 +int ref_transaction_abort(struct ref_transaction *transaction,
607 + struct strbuf *err);
608 +
609 /*
610 * Like ref_transaction_commit(), but optimized for creating
611 * references when originally initializing a repository (e.g., by "git
@@ -551,7 +621,7 @@ int initial_ref_transaction_commit(struct ref_transaction *transaction,
621 struct strbuf *err);
622
623 /*
554 - * Free an existing transaction and all associated data.
624 + * Free `*transaction` and all associated data.
625 */
626 void ref_transaction_free(struct ref_transaction *transaction);
627
refs/files-backend.c
+50 -13
@@ -2855,22 +2855,19 @@ static void files_transaction_cleanup(struct ref_transaction *transaction)
2855 transaction->state = REF_TRANSACTION_CLOSED;
2856 }
2857
2858 -static int files_transaction_commit(struct ref_store *ref_store,
2859 - struct ref_transaction *transaction,
2860 - struct strbuf *err)
2858 +static int files_transaction_prepare(struct ref_store *ref_store,
2859 + struct ref_transaction *transaction,
2860 + struct strbuf *err)
2861 {
2862 struct files_ref_store *refs =
2863 files_downcast(ref_store, REF_STORE_WRITE,
2864 - "ref_transaction_commit");
2864 + "ref_transaction_prepare");
2865 size_t i;
2866 int ret = 0;
2867 - struct string_list refs_to_delete = STRING_LIST_INIT_NODUP;
2868 - struct string_list_item *ref_to_delete;
2867 struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
2868 char *head_ref = NULL;
2869 int head_type;
2870 struct object_id head_oid;
2873 - struct strbuf sb = STRBUF_INIT;
2871
2872 assert(err);
2873
@@ -2934,6 +2931,8 @@ static int files_transaction_commit(struct ref_store *ref_store,
2931 * that new values are valid, and write new values to the
2932 * lockfiles, ready to be activated. Only keep one lockfile
2933 * open at a time to avoid running out of file descriptors.
2934 + * Note that lock_ref_for_update() might append more updates
2935 + * to the transaction.
2936 */
2937 for (i = 0; i < transaction->nr; i++) {
2938 struct ref_update *update = transaction->updates[i];
@@ -2941,7 +2940,38 @@ static int files_transaction_commit(struct ref_store *ref_store,
2940 ret = lock_ref_for_update(refs, update, transaction,
2941 head_ref, &affected_refnames, err);
2942 if (ret)
2944 - goto cleanup;
2943 + break;
2944 + }
2945 +
2946 +cleanup:
2947 + free(head_ref);
2948 + string_list_clear(&affected_refnames, 0);
2949 +
2950 + if (ret)
2951 + files_transaction_cleanup(transaction);
2952 + else
2953 + transaction->state = REF_TRANSACTION_PREPARED;
2954 +
2955 + return ret;
2956 +}
2957 +
2958 +static int files_transaction_finish(struct ref_store *ref_store,
2959 + struct ref_transaction *transaction,
2960 + struct strbuf *err)
2961 +{
2962 + struct files_ref_store *refs =
2963 + files_downcast(ref_store, 0, "ref_transaction_finish");
2964 + size_t i;
2965 + int ret = 0;
2966 + struct string_list refs_to_delete = STRING_LIST_INIT_NODUP;
2967 + struct string_list_item *ref_to_delete;
2968 + struct strbuf sb = STRBUF_INIT;
2969 +
2970 + assert(err);
2971 +
2972 + if (!transaction->nr) {
2973 + transaction->state = REF_TRANSACTION_CLOSED;
2974 + return 0;
2975 }
2976
2977 /* Perform updates first so live commits remain referenced */
@@ -3022,7 +3052,6 @@ static int files_transaction_commit(struct ref_store *ref_store,
3052
3053 cleanup:
3054 files_transaction_cleanup(transaction);
3025 - strbuf_release(&sb);
3055
3056 for (i = 0; i < transaction->nr; i++) {
3057 struct ref_update *update = transaction->updates[i];
@@ -3039,13 +3068,19 @@ cleanup:
3068 }
3069 }
3070
3071 + strbuf_release(&sb);
3072 string_list_clear(&refs_to_delete, 0);
3043 - free(head_ref);
3044 - string_list_clear(&affected_refnames, 0);
3045 -
3073 return ret;
3074 }
3075
3076 +static int files_transaction_abort(struct ref_store *ref_store,
3077 + struct ref_transaction *transaction,
3078 + struct strbuf *err)
3079 +{
3080 + files_transaction_cleanup(transaction);
3081 + return 0;
3082 +}
3083 +
3084 static int ref_present(const char *refname,
3085 const struct object_id *oid, int flags, void *cb_data)
3086 {
@@ -3316,7 +3351,9 @@ struct ref_storage_be refs_be_files = {
3351 "files",
3352 files_ref_store_create,
3353 files_init_db,
3319 - files_transaction_commit,
3354 + files_transaction_prepare,
3355 + files_transaction_finish,
3356 + files_transaction_abort,
3357 files_initial_transaction_commit,
3358
3359 files_pack_refs,
refs/refs-internal.h
+35 -10
@@ -185,17 +185,27 @@ struct ref_update *ref_transaction_add_update(
185
186 /*
187 * Transaction states.
188 - * OPEN: The transaction is in a valid state and can accept new updates.
189 - * An OPEN transaction can be committed.
190 - * CLOSED: A closed transaction is no longer active and no other operations
191 - * than free can be used on it in this state.
192 - * A transaction can either become closed by successfully committing
193 - * an active transaction or if there is a failure while building
194 - * the transaction thus rendering it failed/inactive.
188 + *
189 + * OPEN: The transaction is initialized and new updates can still be
190 + * added to it. An OPEN transaction can be prepared,
191 + * committed, freed, or aborted (freeing and aborting an open
192 + * transaction are equivalent).
193 + *
194 + * PREPARED: ref_transaction_prepare(), which locks all of the
195 + * references involved in the update and checks that the
196 + * update has no errors, has been called successfully for the
197 + * transaction. A PREPARED transaction can be committed or
198 + * aborted.
199 + *
200 + * CLOSED: The transaction is no longer active. A transaction becomes
201 + * CLOSED if there is a failure while building the transaction
202 + * or if a transaction is committed or aborted. A CLOSED
203 + * transaction can only be freed.
204 */
205 enum ref_transaction_state {
197 - REF_TRANSACTION_OPEN = 0,
198 - REF_TRANSACTION_CLOSED = 1
206 + REF_TRANSACTION_OPEN = 0,
207 + REF_TRANSACTION_PREPARED = 1,
208 + REF_TRANSACTION_CLOSED = 2
209 };
210
211 /*
@@ -497,6 +507,18 @@ typedef struct ref_store *ref_store_init_fn(const char *gitdir,
507
508 typedef int ref_init_db_fn(struct ref_store *refs, struct strbuf *err);
509
510 +typedef int ref_transaction_prepare_fn(struct ref_store *refs,
511 + struct ref_transaction *transaction,
512 + struct strbuf *err);
513 +
514 +typedef int ref_transaction_finish_fn(struct ref_store *refs,
515 + struct ref_transaction *transaction,
516 + struct strbuf *err);
517 +
518 +typedef int ref_transaction_abort_fn(struct ref_store *refs,
519 + struct ref_transaction *transaction,
520 + struct strbuf *err);
521 +
522 typedef int ref_transaction_commit_fn(struct ref_store *refs,
523 struct ref_transaction *transaction,
524 struct strbuf *err);
@@ -600,7 +622,10 @@ struct ref_storage_be {
622 const char *name;
623 ref_store_init_fn *init;
624 ref_init_db_fn *init_db;
603 - ref_transaction_commit_fn *transaction_commit;
625 +
626 + ref_transaction_prepare_fn *transaction_prepare;
627 + ref_transaction_finish_fn *transaction_finish;
628 + ref_transaction_abort_fn *transaction_abort;
629 ref_transaction_commit_fn *initial_transaction_commit;
630
631 pack_refs_fn *pack_refs;