1. 25 9月, 2017 1 次提交
    • M
      ref_store: implement `refs_peel_ref()` generically · ba1c052f
      Michael Haggerty 提交于
      We're about to stop storing packed refs in a `ref_cache`. That means
      that the only way we have left to optimize `peel_ref()` is by checking
      whether the reference being peeled is the one currently being iterated
      over (in `current_ref_iter`), and if so, using `ref_iterator_peel()`.
      But this can be done generically; it doesn't have to be implemented
      per-backend.
      
      So implement `refs_peel_ref()` in `refs.c` and remove the `peel_ref()`
      method from the refs API.
      
      This removes the last callers of a couple of functions, so delete
      them. More cleanup to come...
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      ba1c052f
  2. 14 9月, 2017 1 次提交
  3. 09 9月, 2017 6 次提交
    • M
      files_transaction_finish(): delete reflogs before references · 5e00a6c8
      Michael Haggerty 提交于
      If the deletion steps unexpectedly fail, it is less bad to leave a
      reference without its reflog than it is to leave a reflog without its
      reference, since the latter is an invalid repository state.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      5e00a6c8
    • M
      files_ref_store: use a transaction to update packed refs · dc39e099
      Michael Haggerty 提交于
      When processing a `files_ref_store` transaction, it is sometimes
      necessary to delete some references from the "packed-refs" file. Do
      that using a reference transaction conducted against the
      `packed_ref_store`.
      
      This change further decouples `files_ref_store` from
      `packed_ref_store`. It also fixes multiple problems, including the two
      revealed by test cases added in the previous commit.
      
      First, the old code didn't obtain the `packed-refs` lock until
      `files_transaction_finish()`. This means that a failure to acquire the
      `packed-refs` lock (e.g., due to contention with another process)
      wasn't detected until it was too late (problems like this are supposed
      to be detected in the "prepare" phase). The new code acquires the
      `packed-refs` lock in `files_transaction_prepare()`, the same stage of
      the processing when the loose reference locks are being acquired,
      removing another reason why the "prepare" phase might succeed and the
      "finish" phase might nevertheless fail.
      
      Second, the old code deleted the loose version of a reference before
      deleting any packed version of the same reference. This left a moment
      when another process might think that the packed version of the
      reference is current, which is incorrect. (Even worse, the packed
      version of the reference can be arbitrarily old, and might even point
      at an object that has since been garbage-collected.)
      
      Third, if a reference deletion fails to acquire the `packed-refs` lock
      altogether, then the old code might leave the repository in the
      incorrect state (possibly corrupt) described in the previous
      paragraph.
      
      Now we activate the new "packed-refs" file (sans any references that
      are being deleted) *before* deleting the corresponding loose
      references. But we hold the "packed-refs" lock until after the loose
      references have been finalized, thus preventing a simultaneous
      "pack-refs" process from packing the loose version of the reference in
      the time gap, which would otherwise defeat our attempt to delete it.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      dc39e099
    • M
      files_initial_transaction_commit(): use a transaction for packed refs · 1444bfe0
      Michael Haggerty 提交于
      Use a `packed_ref_store` transaction in the implementation of
      `files_initial_transaction_commit()` rather than using internal
      features of the packed ref store. This further decouples
      `files_ref_store` from `packed_ref_store`.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      1444bfe0
    • M
      prune_refs(): also free the linked list · 22b09cdf
      Michael Haggerty 提交于
      At least since v1.7, the elements of the `refs_to_prune` linked list
      have been leaked. Fix the leak by teaching `prune_refs()` to free the
      list elements as it processes them.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      22b09cdf
    • M
      files_pack_refs(): use a reference transaction to write packed refs · 27d03d04
      Michael Haggerty 提交于
      Now that the packed reference store supports transactions, we can use
      a transaction to write the packed versions of references that we want
      to pack. This decreases the coupling between `files_ref_store` and
      `packed_ref_store`.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      27d03d04
    • M
      packed_delete_refs(): implement method · 2fb330ca
      Michael Haggerty 提交于
      Implement `packed_delete_refs()` using a reference transaction. This
      means that `files_delete_refs()` can use `refs_delete_refs()` instead
      of `repack_without_refs()` to delete any packed references, decreasing
      the coupling between the classes.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      2fb330ca
  4. 24 8月, 2017 1 次提交
    • M
      refs: retry acquiring reference locks for 100ms · 4ff0f01c
      Michael Haggerty 提交于
      The philosophy of reference locking has been, "if another process is
      changing a reference, then whatever I'm trying to do to it will
      probably fail anyway because my old-SHA-1 value is probably no longer
      current". But this argument falls down if the other process has locked
      the reference to do something that doesn't actually change the value
      of the reference, such as `pack-refs` or `reflog expire`. There
      actually *is* a decent chance that a planned reference update will
      still be able to go through after the other process has released the
      lock.
      
      So when trying to lock an individual reference (e.g., when creating
      "refs/heads/master.lock"), if it is already locked, then retry the
      lock acquisition for approximately 100 ms before giving up. This
      should eliminate some unnecessary lock conflicts without wasting a lot
      of time.
      
      Add a configuration setting, `core.filesRefLockTimeout`, to allow this
      setting to be tweaked.
      
      Note: the function `get_files_ref_lock_timeout_ms()` cannot be private
      to the files backend because it is also used by `write_pseudoref()`
      and `delete_pseudoref()`, which are defined in `refs.c` so that they
      can be used by other reference backends.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      4ff0f01c
  5. 18 8月, 2017 1 次提交
    • M
      files-backend: cheapen refname_available check when locking refs · 8ec617c8
      Michael Haggerty 提交于
      When locking references in preparation for updating them, we need to
      check that none of the newly added references D/F conflict with
      existing references (e.g., we don't allow `refs/foo` to be added if
      `refs/foo/bar` already exists, or vice versa).
      
      Prior to 524a9fdb (refs_verify_refname_available(): use function in
      more places, 2017-04-16), conflicts with existing loose references
      were checked by looking directly in the filesystem, and then conflicts
      with existing packed references were checked by running
      `verify_refname_available_dir()` against the packed-refs cache.
      
      But that commit changed the final check to call
      `refs_verify_refname_available()` against the *whole* files ref-store,
      including both loose and packed references, with the following
      comment:
      
      > This means that those callsites now check for conflicts with all
      > references rather than just packed refs, but the performance cost
      > shouldn't be significant (and will be regained later).
      
      That comment turned out to be too sanguine. User s@kazlauskas.me
      reported that fetches involving a very large number of references in
      neighboring directories were slowed down by that change.
      
      The problem is that when fetching, each reference is updated
      individually, within its own reference transaction. This is done
      because some reference updates might succeed even though others fail.
      But every time a reference update transaction is finished,
      `clear_loose_ref_cache()` is called. So when it is time to update the
      next reference, part of the loose ref cache has to be repopulated for
      the `refs_verify_refname_available()` call. If the references are all
      in neighboring directories, then the cost of repopulating the
      reference cache increases with the number of references, resulting in
      O(N²) effort.
      
      The comment above also claims that the performance cost "will be
      regained later". The idea was that once the packed-refs were finished
      being split out into a separate ref-store, we could limit the
      `refs_verify_refname_available()` call to the packed references again.
      That is what we do now.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      8ec617c8
  6. 04 7月, 2017 1 次提交
    • M
      repack_without_refs(): don't lock or unlock the packed refs · e5cc7d7d
      Michael Haggerty 提交于
      Change `repack_without_refs()` to expect the packed-refs lock to be
      held already, and not to release the lock before returning. Change the
      callers to deal with lock management.
      
      This change makes it possible for callers to hold the packed-refs lock
      for a longer span of time, a possibility that will eventually make it
      possible to fix some longstanding races.
      
      The only semantic change here is that `repack_without_refs()` used to
      forget to release the lock in the `if (!removed)` exit path. That
      omission is now fixed.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      e5cc7d7d
  7. 24 6月, 2017 23 次提交
  8. 17 6月, 2017 1 次提交
  9. 16 6月, 2017 1 次提交
  10. 13 6月, 2017 1 次提交
    • M
      lock_packed_refs(): fix cache validity check · fed6ebeb
      Michael Haggerty 提交于
      Commit 28ed9830 (get_packed_ref_cache(): assume "packed-refs" won't
      change while locked, 2017-05-22) assumes that the "packed-refs" file
      cannot change while we hold the lock. That assumption is
      justified *if* the lock has been held the whole time since the
      "packed-refs" file was last read.
      
      But in `lock_packed_refs()`, we ourselves lock the "packed-refs" file
      and then call `get_packed_ref_cache()` to ensure that the cache agrees
      with the file. The intent is to guard against the possibility that
      another process changed the "packed-refs" file the moment before we
      locked it.
      
      This check was defeated because `get_packed_ref_cache()` saw that the
      file was locked, and therefore didn't do the `stat_validity_check()`
      that we want.
      
      The mistake was compounded with a misleading comment in
      `lock_packed_refs()` claiming that it was doing the right thing. That
      comment came from an earlier draft of the mh/packed-ref-store-prep
      patch series when the commits were in a different order.
      
      So instead:
      
      * Extract a function `validate_packed_ref_cache()` that does the
        validity check independent of whether the lock is held.
      
      * Change `get_packed_ref_cache()` to call the new function, but only
        if the lock *isn't* held.
      
      * Change `lock_packed_refs()` to call the new function in any case
        before calling `get_packed_ref_cache()`.
      
      * Fix the comment in `lock_packed_refs()`.
      Signed-off-by: NMichael Haggerty <mhagger@alum.mit.edu>
      Signed-off-by: NJunio C Hamano <gitster@pobox.com>
      fed6ebeb
  11. 23 5月, 2017 3 次提交