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:

committed by
Junio C Hamano

parent
a26002b628
commit
3c94bd8dfb
@ -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,
|
||||
int reuse_open)
|
||||
{
|
||||
struct timeval deadline = { 0 };
|
||||
int err = gettimeofday(&deadline, NULL);
|
||||
char **names = NULL, **names_after = NULL;
|
||||
struct timeval deadline;
|
||||
int64_t delay = 0;
|
||||
int tries = 0;
|
||||
int tries = 0, err;
|
||||
|
||||
err = gettimeofday(&deadline, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
goto out;
|
||||
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
|
||||
simplifies debugging in GDB */
|
||||
while (1) {
|
||||
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++;
|
||||
if (tries > 3 && tv_cmp(&now, &deadline) >= 0) {
|
||||
break;
|
||||
}
|
||||
if (tries > 3 && tv_cmp(&now, &deadline) >= 0)
|
||||
goto out;
|
||||
|
||||
err = read_lines(st->list_file, &names);
|
||||
if (err < 0) {
|
||||
free_names(names);
|
||||
return err;
|
||||
}
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = reftable_stack_reload_once(st, names, reuse_open);
|
||||
if (err == 0) {
|
||||
free_names(names);
|
||||
if (!err)
|
||||
break;
|
||||
}
|
||||
if (err != REFTABLE_NOT_EXIST_ERROR) {
|
||||
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
|
||||
changed.
|
||||
*/
|
||||
err2 = read_lines(st->list_file, &names_after);
|
||||
if (err2 < 0) {
|
||||
free_names(names);
|
||||
return err2;
|
||||
}
|
||||
if (err != REFTABLE_NOT_EXIST_ERROR)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* REFTABLE_NOT_EXIST_ERROR can be caused by a concurrent
|
||||
* writer. Check if there was one by checking if the name list
|
||||
* changed.
|
||||
*/
|
||||
err = read_lines(st->list_file, &names_after);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
if (names_equal(names_after, names)) {
|
||||
free_names(names);
|
||||
free_names(names_after);
|
||||
return err;
|
||||
err = REFTABLE_NOT_EXIST_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
free_names(names);
|
||||
names = NULL;
|
||||
free_names(names_after);
|
||||
names_after = NULL;
|
||||
|
||||
delay = delay + (delay * rand()) / RAND_MAX + 1;
|
||||
sleep_millisec(delay);
|
||||
}
|
||||
|
||||
return 0;
|
||||
out:
|
||||
free_names(names);
|
||||
free_names(names_after);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* -1 = error
|
||||
|
Reference in New Issue
Block a user