diff options
author | Michael Haggerty <mhagger@alum.mit.edu> | 2015-05-11 12:35:26 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-05-14 14:51:51 -0700 |
commit | f4ab4f3ab117cf375ae7bb8908c7b5ad687342b1 (patch) | |
tree | b24e6af2887c9c5f8b2904bf46e47cdb7d7b4cdc /refs.c | |
parent | 044b6a9efecf9941073b99ced4cb2881b18aee62 (diff) | |
download | git-f4ab4f3ab117cf375ae7bb8908c7b5ad687342b1.tar.gz |
lock_packed_refs(): allow retries when acquiring the packed-refs lockmh/lockfile-retry
Currently, there is only one attempt to acquire any lockfile, and if
the lock is held by another process, the locking attempt fails
immediately.
This is not such a limitation for loose reference files. First, they
don't take long to rewrite. Second, most reference updates have a
known "old" value, so if another process is updating a reference at
the same moment that we are trying to lock it, then probably the
expected "old" value will not longer be valid, and the update will
fail anyway.
But these arguments do not hold for packed-refs:
* The packed-refs file can be large and take significant time to
rewrite.
* Many references are stored in a single packed-refs file, so it could
be that the other process was changing a different reference than
the one that we are interested in.
Therefore, it is much more likely for there to be spurious lock
conflicts in connection to the packed-refs file, resulting in
unnecessary command failures.
So, if the first attempt to lock the packed-refs file fails, continue
retrying for a configurable length of time before giving up. The
default timeout is 1 second.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refs.c')
-rw-r--r-- | refs.c | 12 |
1 files changed, 11 insertions, 1 deletions
@@ -2431,9 +2431,19 @@ static int write_packed_entry_fn(struct ref_entry *entry, void *cb_data) /* This should return a meaningful errno on failure */ int lock_packed_refs(int flags) { + static int timeout_configured = 0; + static int timeout_value = 1000; + struct packed_ref_cache *packed_ref_cache; - if (hold_lock_file_for_update(&packlock, git_path("packed-refs"), flags) < 0) + if (!timeout_configured) { + git_config_get_int("core.packedrefstimeout", &timeout_value); + timeout_configured = 1; + } + + if (hold_lock_file_for_update_timeout( + &packlock, git_path("packed-refs"), + flags, timeout_value) < 0) return -1; /* * Get the current packed-refs while holding the lock. If the |