reftable/stack: refactor stack reloading to have common exit path

The `reftable_stack_reload_maybe_reuse()` function is responsible for
reloading the reftable list from disk. The function is quite hard to
follow though because it has a bunch of different exit paths, many of
which have to free the same set of resources.

Refactor the function to have a common exit path. While at it, touch up
the style of this function a bit to match our usual coding style better.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Patrick Steinhardt
2024-01-11 11:06:39 +01:00
committed by Junio C Hamano
parent a26002b628
commit 3c94bd8dfb

View File

@ -304,69 +304,67 @@ static int tv_cmp(struct timeval *a, struct timeval *b)
static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st, static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st,
int reuse_open) int reuse_open)
{ {
struct timeval deadline = { 0 }; char **names = NULL, **names_after = NULL;
int err = gettimeofday(&deadline, NULL); struct timeval deadline;
int64_t delay = 0; int64_t delay = 0;
int tries = 0; int tries = 0, err;
err = gettimeofday(&deadline, NULL);
if (err < 0) if (err < 0)
return err; goto out;
deadline.tv_sec += 3; deadline.tv_sec += 3;
while (1) {
char **names = NULL;
char **names_after = NULL;
struct timeval now = { 0 };
int err = gettimeofday(&now, NULL);
int err2 = 0;
if (err < 0) {
return err;
}
/* Only look at deadlines after the first few times. This while (1) {
simplifies debugging in GDB */ struct timeval now;
err = gettimeofday(&now, NULL);
if (err < 0)
goto out;
/*
* Only look at deadlines after the first few times. This
* simplifies debugging in GDB.
*/
tries++; tries++;
if (tries > 3 && tv_cmp(&now, &deadline) >= 0) { if (tries > 3 && tv_cmp(&now, &deadline) >= 0)
break; goto out;
}
err = read_lines(st->list_file, &names); err = read_lines(st->list_file, &names);
if (err < 0) { if (err < 0)
free_names(names); goto out;
return err;
}
err = reftable_stack_reload_once(st, names, reuse_open); err = reftable_stack_reload_once(st, names, reuse_open);
if (err == 0) { if (!err)
free_names(names);
break; break;
} if (err != REFTABLE_NOT_EXIST_ERROR)
if (err != REFTABLE_NOT_EXIST_ERROR) { goto out;
free_names(names);
return err;
}
/* err == REFTABLE_NOT_EXIST_ERROR can be caused by a concurrent /*
writer. Check if there was one by checking if the name list * REFTABLE_NOT_EXIST_ERROR can be caused by a concurrent
changed. * writer. Check if there was one by checking if the name list
* changed.
*/ */
err2 = read_lines(st->list_file, &names_after); err = read_lines(st->list_file, &names_after);
if (err2 < 0) { if (err < 0)
free_names(names); goto out;
return err2; if (names_equal(names_after, names)) {
err = REFTABLE_NOT_EXIST_ERROR;
goto out;
} }
if (names_equal(names_after, names)) {
free_names(names);
free_names(names_after);
return err;
}
free_names(names); free_names(names);
names = NULL;
free_names(names_after); free_names(names_after);
names_after = NULL;
delay = delay + (delay * rand()) / RAND_MAX + 1; delay = delay + (delay * rand()) / RAND_MAX + 1;
sleep_millisec(delay); sleep_millisec(delay);
} }
return 0; out:
free_names(names);
free_names(names_after);
return err;
} }
/* -1 = error /* -1 = error