git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v3 16/19] branch.c: use ref transaction for all ref updates

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Apr 25, 2014, 23:16 UTC
Message-ID
<535AECC5.3090100@alum.mit.edu>
In-Reply-To
<1398442494-23438-17-git-send-email-sahlberg@google.com>
On 04/25/2014 06:14 PM, Ronnie Sahlberg wrote:
Show 74 quoted lines
> Change create_branch to use a ref transaction when creating the new branch.
> ref_transaction_create will check that the ref does not already exist and fail
> otherwise meaning that we no longer need to keep a lock on the ref during the
> setup_tracking. This simplifies the code since we can now do the transaction
> in one single step.
> 
> If the forcing flag is false then use ref_transaction_create since this will
> fail if the ref already exist. Otherwise use ref_transaction_update.
> 
> This also fixes a race condition in the old code where two concurrent
> create_branch could race since the lock_any_ref_for_update/write_ref_sha1
> did not protect against the ref already existsing. I.e. one thread could end up
> overwriting a branch even if the forcing flag is false.
> 
> Signed-off-by: Ronnie Sahlberg <sahlberg@google.com>
> ---
>  branch.c | 39 +++++++++++++++++++++++++--------------
>  1 file changed, 25 insertions(+), 14 deletions(-)
> 
> diff --git a/branch.c b/branch.c
> index 660097b..23cde1e 100644
> --- a/branch.c
> +++ b/branch.c
> @@ -226,7 +226,6 @@ void create_branch(const char *head,
>  		   int force, int reflog, int clobber_head,
>  		   int quiet, enum branch_track track)
>  {
> -	struct ref_lock *lock = NULL;
>  	struct commit *commit;
>  	unsigned char sha1[20];
>  	char *real_ref, msg[PATH_MAX + 20];
> @@ -285,15 +284,6 @@ void create_branch(const char *head,
>  		die(_("Not a valid branch point: '%s'."), start_name);
>  	hashcpy(sha1, commit->object.sha1);
>  
> -	if (!dont_change_ref) {
> -		lock = lock_any_ref_for_update(ref.buf, NULL, 0, NULL);
> -		if (!lock)
> -			die_errno(_("Failed to lock ref for update"));
> -	}
> -
> -	if (reflog)
> -		log_all_ref_updates = 1;
> -
>  	if (forcing)
>  		snprintf(msg, sizeof msg, "branch: Reset to %s",
>  			 start_name);
> @@ -301,13 +291,34 @@ void create_branch(const char *head,
>  		snprintf(msg, sizeof msg, "branch: Created from %s",
>  			 start_name);
>  
> +	if (reflog)
> +		log_all_ref_updates = 1;
> +
> +	if (!dont_change_ref) {
> +		struct ref_transaction *transaction;
> +		char *err = NULL;
> +
> +		transaction = ref_transaction_begin();
> +		if (forcing) {
> +			if (!transaction ||
> +			    ref_transaction_update(transaction, ref.buf, sha1,
> +						   NULL, 0, 0) ||
> +			    ref_transaction_commit(transaction, msg, &err))
> +			  die_errno(_("%s: failed to write ref: %s"),
> +				    ref.buf, err);
> +		} else {
> +			if (!transaction ||
> +			    ref_transaction_create(transaction, ref.buf, sha1,
> +						   0) ||
> +			    ref_transaction_commit(transaction, msg, &err))
> +			  die_errno(_("%s: failed to write ref: %s"),
> +				    ref.buf, err);
> +		}
You've got some indentation problems above.

But actually, there seems like a lot of duplicated code here. Couldn't you instead do a single block with have_old set based on forcing:

    ref_transaction_update(transaction, ref.buf, sha1,
			   null_sha1, 0, !forcing)
?
Show 13 quoted lines
> +	}
> +
>  	if (real_ref && track)
>  		setup_tracking(ref.buf + 11, real_ref, track, quiet);
>  
> -	if (!dont_change_ref)
> -		if (write_ref_sha1(lock, sha1, msg) < 0)
> -			die_errno(_("Failed to write ref"));
> -
>  	strbuf_release(&ref);
>  	free(real_ref);
>  }
> 
-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
Previous: Ronnie SahlbergNext: Ronnie Sahlberg
Message 32 of 48 in “Use ref transactions from most callers”
  1. 00/19 Use ref transactions from most callersRonnie Sahlberg, Apr 25, 2014
  2. 01/19 refs.c: constify the sha arguments for ref_transaction_create|delete|updateRonnie Sahlberg, Apr 25, 2014
  3. 02/19 refs.c: allow passing NULL to ref_transaction_freeRonnie Sahlberg, Apr 25, 2014
  4. 03/19 refs.c: make ref_transaction_commit return an error stringRonnie Sahlberg, Apr 25, 2014
  5. Jonathan NiederApr 25, 2014
  6. Ronnie SahlbergApr 28, 2014
  7. 04/19 refs.c: return error string from ref_update_reject_duplicates on failureRonnie Sahlberg, Apr 25, 2014
  8. Jonathan NiederApr 25, 2014
  9. Ronnie SahlbergApr 28, 2014
  10. 05/19 update-ref.c: use the error string from _commit to print better messageRonnie Sahlberg, Apr 25, 2014
  11. Jonathan NiederApr 25, 2014
  12. Ronnie SahlbergApr 28, 2014
  13. 06/19 refs.c: make update_ref_write to return error string on failureRonnie Sahlberg, Apr 25, 2014
  14. Jonathan NiederApr 25, 2014
  15. Ronnie SahlbergApr 28, 2014
  16. 07/19 refs.c: remove the onerr argument to ref_transaction_commitRonnie Sahlberg, Apr 25, 2014
  17. Jonathan NiederApr 25, 2014
  18. Ronnie SahlbergApr 28, 2014
  19. 08/19 refs.c: change ref_transaction_update() to do error checking and return statusRonnie Sahlberg, Apr 25, 2014
  20. 09/19 refs.c: change ref_transaction_create to do error checking and return statusRonnie Sahlberg, Apr 25, 2014
  21. 10/19 refs.c: ref_transaction_delete to check for error and return statusRonnie Sahlberg, Apr 25, 2014
  22. 11/19 tag.c: use ref transactions when doing updatesRonnie Sahlberg, Apr 25, 2014
  23. Michael HaggertyApr 25, 2014
  24. Ronnie SahlbergApr 28, 2014
  25. 12/19 replace.c: use the ref transaction functions for updatesRonnie Sahlberg, Apr 25, 2014
  26. Michael HaggertyApr 25, 2014
  27. Ronnie SahlbergApr 28, 2014
  28. 13/19 commit.c: use ref transactions for updatesRonnie Sahlberg, Apr 25, 2014
  29. 14/19 sequencer.c: use ref transactions for all ref updatesRonnie Sahlberg, Apr 25, 2014
  30. 15/19 fast-import.c: change update_branch to use ref transactionsRonnie Sahlberg, Apr 25, 2014
  31. 16/19 branch.c: use ref transaction for all ref updatesRonnie Sahlberg, Apr 25, 2014
  32. Michael HaggertyApr 25, 2014
  33. Ronnie SahlbergApr 28, 2014
  34. Michael HaggertyApr 29, 2014
  35. Ronnie SahlbergApr 29, 2014
  36. Junio C HamanoApr 29, 2014
  37. 17/19 refs.c: change update_ref to use a transactionRonnie Sahlberg, Apr 25, 2014
  38. Michael HaggertyApr 25, 2014
  39. Ronnie SahlbergApr 28, 2014
  40. 18/19 refs.c: free the transaction before returning when number of updates is 0Ronnie Sahlberg, Apr 25, 2014
  41. 19/19 refs.c: pass **transaction to commit and have it clear the pointerRonnie Sahlberg, Apr 25, 2014
  42. Michael HaggertyApr 26, 2014
  43. Ronnie SahlbergApr 28, 2014
  44. Michael HaggertyApr 29, 2014
  45. Ronnie SahlbergApr 29, 2014
  46. Michael HaggertyApr 30, 2014
  47. Jonathan NiederApr 25, 2014
  48. Ronnie SahlbergApr 25, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.