git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Michael Haggerty <mhagger@alum.mit.edu>
To: Ronnie Sahlberg <sahlberg@google.com>
Cc: "git@vger.kernel.org" <git@vger.kernel.org>
Subject: Re: [PATCH v3 16/19] branch.c: use ref transaction for all ref updates
Date: Tue, 29 Apr 2014 11:35:23 +0200	[thread overview]
Message-ID: <535F725B.5000102@alum.mit.edu> (raw)
In-Reply-To: <CAL=YDWkJKOM7eo7cknMH4MAAYJ=Ds9PVjUvufHzrBu=neucf4g@mail.gmail.com>

On 04/28/2014 09:16 PM, Ronnie Sahlberg wrote:
> On Fri, Apr 25, 2014 at 4:16 PM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
>> On 04/25/2014 06:14 PM, Ronnie Sahlberg wrote:
>>> 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)
>>
>> ?
> 
> Done, thanks.
> 
> 
> I am not sure how I feel about using _update to create new refs
> since we already have ref_transaction_create for that purpose.
> 
> ref_transaction_update can either be used to update an existing ref
> or it can be used to create new refs, either by passing have_old==0
> or by passing old_sha1==null_sha1 and have_old==1

Hold onto your socks then, because I think in the future update() should
get a have_new parameter too.  That way it can also be used to verify
the current value of a reference by passing have_old=1, have_new=0
without also re-setting the reference unnecessarily like now.  Though I
admit, have_old=have_new=0 might *not* be so useful :-)

> Maybe the api would be cleaner if we would change it so that update
> and create does
> not overlap and thus change _update so that it can only modify refs
> that must already exist ?

I have no compunctions about using update() to create or delete a
reference.  My point of view is that update() is the general case, and
create() and delete() are special-cases that exist only for the
convenience of callers.  For example, our future pluggable backends
might only have to implement update(), and the other two functions could
delegate to it at the abstract layer.

Plus, making this stricter would make it impossible to eliminate
duplicate code like in the example above, which is itself evidence that
update() is a useful abstraction.

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

  reply	other threads:[~2014-04-29  9:35 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-25 16:14 [PATCH v3 00/19] Use ref transactions from most callers Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 01/19] refs.c: constify the sha arguments for ref_transaction_create|delete|update Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 02/19] refs.c: allow passing NULL to ref_transaction_free Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 03/19] refs.c: make ref_transaction_commit return an error string Ronnie Sahlberg
2014-04-25 22:10   ` Jonathan Nieder
2014-04-28 17:46     ` Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 04/19] refs.c: return error string from ref_update_reject_duplicates on failure Ronnie Sahlberg
2014-04-25 22:12   ` Jonathan Nieder
2014-04-28 18:23     ` Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 05/19] update-ref.c: use the error string from _commit to print better message Ronnie Sahlberg
2014-04-25 22:36   ` Jonathan Nieder
2014-04-28 15:11     ` Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 06/19] refs.c: make update_ref_write to return error string on failure Ronnie Sahlberg
2014-04-25 22:45   ` Jonathan Nieder
2014-04-28 18:23     ` Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 07/19] refs.c: remove the onerr argument to ref_transaction_commit Ronnie Sahlberg
2014-04-25 22:47   ` Jonathan Nieder
2014-04-28 18:27     ` Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 08/19] refs.c: change ref_transaction_update() to do error checking and return status Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 09/19] refs.c: change ref_transaction_create " Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 10/19] refs.c: ref_transaction_delete to check for error " Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 11/19] tag.c: use ref transactions when doing updates Ronnie Sahlberg
2014-04-25 22:58   ` Michael Haggerty
2014-04-28 15:15     ` Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 12/19] replace.c: use the ref transaction functions for updates Ronnie Sahlberg
2014-04-25 23:00   ` Michael Haggerty
2014-04-28 15:17     ` Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 13/19] commit.c: use ref transactions " Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 14/19] sequencer.c: use ref transactions for all ref updates Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 15/19] fast-import.c: change update_branch to use ref transactions Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 16/19] branch.c: use ref transaction for all ref updates Ronnie Sahlberg
2014-04-25 23:16   ` Michael Haggerty
2014-04-28 19:16     ` Ronnie Sahlberg
2014-04-29  9:35       ` Michael Haggerty [this message]
2014-04-29 15:11         ` Ronnie Sahlberg
2014-04-29 17:15         ` Junio C Hamano
2014-04-25 16:14 ` [PATCH v3 17/19] refs.c: change update_ref to use a transaction Ronnie Sahlberg
2014-04-25 23:28   ` Michael Haggerty
2014-04-28 18:33     ` Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 18/19] refs.c: free the transaction before returning when number of updates is 0 Ronnie Sahlberg
2014-04-25 16:14 ` [PATCH v3 19/19] refs.c: pass **transaction to commit and have it clear the pointer Ronnie Sahlberg
2014-04-26  1:31   ` Michael Haggerty
2014-04-28 17:59     ` Ronnie Sahlberg
2014-04-29  9:25       ` Michael Haggerty
2014-04-29 18:58         ` Ronnie Sahlberg
2014-04-30 14:20           ` Michael Haggerty
2014-04-25 21:53 ` [PATCH v3 00/19] Use ref transactions from most callers Jonathan Nieder
2014-04-25 22:04   ` Ronnie Sahlberg

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=535F725B.5000102@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).