mirror of
https://github.com/git/git
synced 2024-10-02 14:45:21 +00:00
Merge branch 'mh/ref-lock-entry'
The code to acquire a lock on a reference (e.g. while accepting a push from a client) used to immediately fail when the reference is already locked---now it waits for a very short while and retries, which can make it succeed if the lock holder was holding it during a read-only operation. * mh/ref-lock-entry: refs: retry acquiring reference locks for 100ms
This commit is contained in:
commit
f2dd90fc1c
|
@ -776,6 +776,12 @@ core.commentChar::
|
||||||
If set to "auto", `git-commit` would select a character that is not
|
If set to "auto", `git-commit` would select a character that is not
|
||||||
the beginning character of any line in existing commit messages.
|
the beginning character of any line in existing commit messages.
|
||||||
|
|
||||||
|
core.filesRefLockTimeout::
|
||||||
|
The length of time, in milliseconds, to retry when trying to
|
||||||
|
lock an individual reference. Value 0 means not to retry at
|
||||||
|
all; -1 means to try indefinitely. Default is 100 (i.e.,
|
||||||
|
retry for 100ms).
|
||||||
|
|
||||||
core.packedRefsTimeout::
|
core.packedRefsTimeout::
|
||||||
The length of time, in milliseconds, to retry when trying to
|
The length of time, in milliseconds, to retry when trying to
|
||||||
lock the `packed-refs` file. Value 0 means not to retry at
|
lock the `packed-refs` file. Value 0 means not to retry at
|
||||||
|
|
24
refs.c
24
refs.c
|
@ -579,6 +579,21 @@ enum ref_type ref_type(const char *refname)
|
||||||
return REF_TYPE_NORMAL;
|
return REF_TYPE_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long get_files_ref_lock_timeout_ms(void)
|
||||||
|
{
|
||||||
|
static int configured = 0;
|
||||||
|
|
||||||
|
/* The default timeout is 100 ms: */
|
||||||
|
static int timeout_ms = 100;
|
||||||
|
|
||||||
|
if (!configured) {
|
||||||
|
git_config_get_int("core.filesreflocktimeout", &timeout_ms);
|
||||||
|
configured = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeout_ms;
|
||||||
|
}
|
||||||
|
|
||||||
static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
|
static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
|
||||||
const unsigned char *old_sha1, struct strbuf *err)
|
const unsigned char *old_sha1, struct strbuf *err)
|
||||||
{
|
{
|
||||||
|
@ -591,7 +606,9 @@ static int write_pseudoref(const char *pseudoref, const unsigned char *sha1,
|
||||||
strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
|
strbuf_addf(&buf, "%s\n", sha1_to_hex(sha1));
|
||||||
|
|
||||||
filename = git_path("%s", pseudoref);
|
filename = git_path("%s", pseudoref);
|
||||||
fd = hold_lock_file_for_update(&lock, filename, LOCK_DIE_ON_ERROR);
|
fd = hold_lock_file_for_update_timeout(&lock, filename,
|
||||||
|
LOCK_DIE_ON_ERROR,
|
||||||
|
get_files_ref_lock_timeout_ms());
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
strbuf_addf(err, "could not open '%s' for writing: %s",
|
strbuf_addf(err, "could not open '%s' for writing: %s",
|
||||||
filename, strerror(errno));
|
filename, strerror(errno));
|
||||||
|
@ -634,8 +651,9 @@ static int delete_pseudoref(const char *pseudoref, const unsigned char *old_sha1
|
||||||
int fd;
|
int fd;
|
||||||
unsigned char actual_old_sha1[20];
|
unsigned char actual_old_sha1[20];
|
||||||
|
|
||||||
fd = hold_lock_file_for_update(&lock, filename,
|
fd = hold_lock_file_for_update_timeout(
|
||||||
LOCK_DIE_ON_ERROR);
|
&lock, filename, LOCK_DIE_ON_ERROR,
|
||||||
|
get_files_ref_lock_timeout_ms());
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
die_errno(_("Could not open '%s' for writing"), filename);
|
die_errno(_("Could not open '%s' for writing"), filename);
|
||||||
if (read_ref(pseudoref, actual_old_sha1))
|
if (read_ref(pseudoref, actual_old_sha1))
|
||||||
|
|
|
@ -537,7 +537,9 @@ static int lock_raw_ref(struct files_ref_store *refs,
|
||||||
if (!lock->lk)
|
if (!lock->lk)
|
||||||
lock->lk = xcalloc(1, sizeof(struct lock_file));
|
lock->lk = xcalloc(1, sizeof(struct lock_file));
|
||||||
|
|
||||||
if (hold_lock_file_for_update(lock->lk, ref_file.buf, LOCK_NO_DEREF) < 0) {
|
if (hold_lock_file_for_update_timeout(
|
||||||
|
lock->lk, ref_file.buf, LOCK_NO_DEREF,
|
||||||
|
get_files_ref_lock_timeout_ms()) < 0) {
|
||||||
if (errno == ENOENT && --attempts_remaining > 0) {
|
if (errno == ENOENT && --attempts_remaining > 0) {
|
||||||
/*
|
/*
|
||||||
* Maybe somebody just deleted one of the
|
* Maybe somebody just deleted one of the
|
||||||
|
@ -865,7 +867,9 @@ static int create_reflock(const char *path, void *cb)
|
||||||
{
|
{
|
||||||
struct lock_file *lk = cb;
|
struct lock_file *lk = cb;
|
||||||
|
|
||||||
return hold_lock_file_for_update(lk, path, LOCK_NO_DEREF) < 0 ? -1 : 0;
|
return hold_lock_file_for_update_timeout(
|
||||||
|
lk, path, LOCK_NO_DEREF,
|
||||||
|
get_files_ref_lock_timeout_ms()) < 0 ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -61,6 +61,12 @@
|
||||||
*/
|
*/
|
||||||
#define REF_DELETED_LOOSE 0x200
|
#define REF_DELETED_LOOSE 0x200
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the length of time to retry acquiring a loose reference lock
|
||||||
|
* before giving up, in milliseconds:
|
||||||
|
*/
|
||||||
|
long get_files_ref_lock_timeout_ms(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true iff refname is minimally safe. "Safe" here means that
|
* Return true iff refname is minimally safe. "Safe" here means that
|
||||||
* deleting a loose reference by this name will not do any damage, for
|
* deleting a loose reference by this name will not do any damage, for
|
||||||
|
|
Loading…
Reference in a new issue