From: Michael Haggerty <mhagger@alum.mit.edu>
To: Ronnie Sahlberg <sahlberg@google.com>, git@vger.kernel.org
Subject: Re: [PATCH v10 24/44] fetch.c: use a single ref transaction for all ref updates
Date: Sat, 17 May 2014 17:05:05 +0200 [thread overview]
Message-ID: <53777AA1.1020107@alum.mit.edu> (raw)
In-Reply-To: <1400261852-31303-25-git-send-email-sahlberg@google.com>
On 05/16/2014 07:37 PM, Ronnie Sahlberg wrote:
> Change store_updated_refs to use a single ref transaction for all refs that
> are updated during the fetch. This makes the fetch more atomic when update
> failures occur.
>
> Since ref update failures will now no longer occur in the code path for
> updating a single ref in s_update_ref, we no longer have as detailed error
> message logging the exact reference and the ref log action as in the old cod
s/cod/code/ ?
> Instead since we fail the entire transaction we log a much more generic
> message. But since we commit the transaction using MSG_ON_ERR we will log
> an error containing the ref name if either locking of writing the ref would
s/of/or/ ?
s/would/would fail,/ ?
> so the regression in the log message is minor.
>
> This will also change the order in which errors are checked for and logged
> which may alter which error will be logged if there are multiple errors
> occuring during a fetch.
s/occuring/occurring/
>
> For example, assume we have a fetch for two refs that both would fail.
> Where the first ref would fail with ENOTDIR due to a directory in the ref
> path not existing, and the second ref in the fetch would fail due to
> the check in update_logical_ref():
> if (current_branch &&
> !strcmp(ref->name, current_branch->name) &&
> !(update_head_ok || is_bare_repository()) &&
> !is_null_sha1(ref->old_sha1)) {
> /*
> * If this is the head, and it's not okay to update
> * the head, and the old value of the head isn't empty...
> */
>
> In the old code since we would update the refs one ref at a time we would
> first fail the ENOTDIR and then fail the second update of HEAD as well.
> But since the first ref failed with ENOTDIR we would eventually fail the who
s/who/whole/
> fetch with STORE_REF_ERROR_DF_CONFLICT
>
> In the new code, since we defer committing the transaction until all refs
> have been processed, we would now detect that the second ref was bad and
> rollback the transaction before we would even try start writing the update t
s/try/try to/
s/t$/to/
> disk and thus we would not return STORE_REF_ERROR_DF_CONFLICT for this case.
>
> I think this new behaviour is more correct, since if there was a problem
> we would not even try to commit the transaction but need to highlight this
> change in how/what errors are reported.
> This change in what error is returned only occurs if there are multiple
> refs that fail to update and only some, but not all, of them fail due to
> ENOTDIR.
Thanks for the detailed explanation. The change in behavior seems
reasonable to me.
>
> Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
> ---
> builtin/fetch.c | 34 ++++++++++++++++------------------
> 1 file changed, 16 insertions(+), 18 deletions(-)
>
> diff --git a/builtin/fetch.c b/builtin/fetch.c
> index 8cf70cd..5b0cc31 100644
> --- a/builtin/fetch.c
> +++ b/builtin/fetch.c
> @@ -45,6 +45,7 @@ static struct transport *gsecondary;
> static const char *submodule_prefix = "";
> static const char *recurse_submodules_default;
> static int shown_url;
> +static struct ref_transaction *transaction;
>
> static int option_parse_recurse_submodules(const struct option *opt,
> const char *arg, int unset)
> @@ -373,27 +374,13 @@ static int s_update_ref(const char *action,
> struct ref *ref,
> int check_old)
> {
> - char msg[1024];
> - char *rla = getenv("GIT_REFLOG_ACTION");
> - struct ref_transaction *transaction;
> -
> if (dry_run)
> return 0;
> - if (!rla)
> - rla = default_rla.buf;
> - snprintf(msg, sizeof(msg), "%s: %s", rla, action);
>
> - errno = 0;
> - transaction = ref_transaction_begin();
> - if (!transaction ||
> - ref_transaction_update(transaction, ref->name, ref->new_sha1,
> - ref->old_sha1, 0, check_old, NULL) ||
> - ref_transaction_commit(transaction, msg, NULL)) {
> - ref_transaction_free(transaction);
> - return errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
> - STORE_REF_ERROR_OTHER;
> - }
> - ref_transaction_free(transaction);
> + if (ref_transaction_update(transaction, ref->name, ref->new_sha1,
> + ref->old_sha1, 0, check_old, NULL))
> + return STORE_REF_ERROR_OTHER;
> +
> return 0;
> }
>
> @@ -565,6 +552,13 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
> goto abort;
> }
>
> + errno = 0;
> + transaction = ref_transaction_begin();
> + if (!transaction) {
> + rc = error(_("cannot start ref transaction\n"));
> + goto abort;
> + }
> +
> /*
> * We do a pass for each fetch_head_status type in their enum order, so
> * merged entries are written before not-for-merge. That lets readers
> @@ -676,6 +670,10 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
> }
> }
> }
> + if (ref_transaction_commit(transaction, "fetch_ref transaction", NULL))
> + rc |= errno == ENOTDIR ? STORE_REF_ERROR_DF_CONFLICT :
> + STORE_REF_ERROR_OTHER;
> + ref_transaction_free(transaction);
>
> if (rc & STORE_REF_ERROR_DF_CONFLICT)
> error(_("some local refs could not be updated; try running\n"
>
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
next prev parent reply other threads:[~2014-05-17 15:05 UTC|newest]
Thread overview: 65+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-16 17:36 [PATCH v10 00/44] Use ref transactions for all ref updates Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 01/44] refs.c: constify the sha arguments for ref_transaction_create|delete|update Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 02/44] refs.c: allow passing NULL to ref_transaction_free Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 03/44] refs.c: add a strbuf argument to ref_transaction_commit for error logging Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 04/44] refs.c: add an err argument to repack_without_refs Ronnie Sahlberg
2014-05-17 12:40 ` Michael Haggerty
2014-05-27 19:21 ` Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 05/44] refs.c: make ref_update_reject_duplicates take a strbuf argument for errors Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 06/44] refs.c: add an err argument to delete_ref_loose Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 07/44] refs.c: make update_ref_write update a strbuf on failure Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 08/44] update-ref.c: log transaction error from the update_ref Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 09/44] refs.c: remove the onerr argument to ref_transaction_commit Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 10/44] refs.c: change ref_transaction_update() to do error checking and return status Ronnie Sahlberg
2014-05-16 17:36 ` [PATCH v10 11/44] refs.c: change ref_transaction_create " Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 12/44] refs.c: ref_transaction_delete to check for error " Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 13/44] tag.c: use ref transactions when doing updates Ronnie Sahlberg
2014-05-17 13:09 ` Michael Haggerty
2014-05-19 17:16 ` Ronnie Sahlberg
2014-05-19 18:03 ` Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 14/44] replace.c: use the ref transaction functions for updates Ronnie Sahlberg
2014-05-17 13:14 ` Michael Haggerty
2014-05-19 18:04 ` Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 15/44] commit.c: use ref transactions " Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 16/44] sequencer.c: use ref transactions for all ref updates Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 17/44] fast-import.c: change update_branch to use ref transactions Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 18/44] branch.c: use ref transaction for all ref updates Ronnie Sahlberg
2014-05-17 13:33 ` Michael Haggerty
2014-05-19 17:22 ` Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 19/44] refs.c: change update_ref to use a transaction Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 20/44] refs.c: free the transaction before returning when number of updates is 0 Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 21/44] refs.c: ref_transaction_commit should not free the transaction Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 22/44] fetch.c: clear errno before calling functions that might set it Ronnie Sahlberg
2014-05-17 14:56 ` Michael Haggerty
2014-05-27 19:14 ` Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 23/44] fetch.c: change s_update_ref to use a ref transaction Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 24/44] fetch.c: use a single ref transaction for all ref updates Ronnie Sahlberg
2014-05-17 15:05 ` Michael Haggerty [this message]
2014-05-17 15:17 ` Michael Haggerty
2014-05-16 17:37 ` [PATCH v10 25/44] receive-pack.c: use a reference transaction for updating the refs Ronnie Sahlberg
2014-05-17 15:35 ` Michael Haggerty
2014-05-19 19:02 ` Ronnie Sahlberg
2014-05-23 13:49 ` Michael Haggerty
2014-05-23 16:14 ` Ronnie Sahlberg
2014-05-23 21:02 ` Michael Haggerty
2014-05-27 19:30 ` Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 26/44] fast-import.c: use a ref transaction when dumping tags Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 27/44] walker.c: use ref transaction for ref updates Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 28/44] refs.c: make write_ref_sha1 static Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 29/44] refs.c: make lock_ref_sha1 static Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 30/44] refs.c: add transaction.status and track OPEN/CLOSED/ERROR Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 31/44] refs.c: remove the update_ref_lock function Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 32/44] refs.c: remove the update_ref_write function Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 33/44] refs.c: remove lock_ref_sha1 Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 34/44] refs.c: make prune_ref use a transaction to delete the ref Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 35/44] refs.c: make delete_ref use a transaction Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 36/44] refs.c: pass the ref log message to _create/delete/update instead of _commit Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 37/44] refs.c: pass NULL as *flags to read_ref_full Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 38/44] refs.c: pack all refs before we start to rename a ref Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 39/44] refs.c: move the check for valid refname to lock_ref_sha1_basic Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 40/44] refs.c: call lock_ref_sha1_basic directly from commit Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 41/44] refs.c: add a new flag for transaction delete for refs we know are packed only Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 42/44] refs.c: pass a skip list to name_conflict_fn Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 43/44] refs.c: make rename_ref use a transaction Ronnie Sahlberg
2014-05-16 17:37 ` [PATCH v10 44/44] refs.c: remove forward declaration of write_ref_sha1 Ronnie Sahlberg
2014-05-16 18:39 ` [PATCH v10 00/44] Use ref transactions for all ref updates Jonathan Nieder
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53777AA1.1020107@alum.mit.edu \
--to=mhagger@alum.mit.edu \
--cc=git@vger.kernel.org \
--cc=sahlberg@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).