| 366 | } |
| 367 | |
| 368 | static int reftable_stack_reload_maybe_reuse(struct reftable_stack *st, |
| 369 | int reuse_open) |
| 370 | { |
| 371 | char **names = NULL, **names_after = NULL; |
| 372 | uint64_t deadline; |
| 373 | int64_t delay = 0; |
| 374 | int tries = 0, err; |
| 375 | int fd = -1; |
| 376 | |
| 377 | deadline = reftable_time_ms() + 3000; |
| 378 | |
| 379 | while (1) { |
| 380 | uint64_t now = reftable_time_ms(); |
| 381 | |
| 382 | /* |
| 383 | * Only look at deadlines after the first few times. This |
| 384 | * simplifies debugging in GDB. |
| 385 | */ |
| 386 | tries++; |
| 387 | if (tries > 3 && now >= deadline) |
| 388 | goto out; |
| 389 | |
| 390 | fd = open(st->list_file, O_RDONLY); |
| 391 | if (fd < 0) { |
| 392 | if (errno != ENOENT) { |
| 393 | err = REFTABLE_IO_ERROR; |
| 394 | goto out; |
| 395 | } |
| 396 | |
| 397 | REFTABLE_CALLOC_ARRAY(names, 1); |
| 398 | if (!names) { |
| 399 | err = REFTABLE_OUT_OF_MEMORY_ERROR; |
| 400 | goto out; |
| 401 | } |
| 402 | } else { |
| 403 | err = fd_read_lines(fd, &names); |
| 404 | if (err < 0) |
| 405 | goto out; |
| 406 | } |
| 407 | |
| 408 | err = reftable_stack_reload_once(st, (const char **) names, reuse_open); |
| 409 | if (!err) |
| 410 | break; |
| 411 | if (err != REFTABLE_NOT_EXIST_ERROR) |
| 412 | goto out; |
| 413 | |
| 414 | /* |
| 415 | * REFTABLE_NOT_EXIST_ERROR can be caused by a concurrent |
| 416 | * writer. Check if there was one by checking if the name list |
| 417 | * changed. |
| 418 | */ |
| 419 | err = read_lines(st->list_file, &names_after); |
| 420 | if (err < 0) |
| 421 | goto out; |
| 422 | if (names_equal((const char **) names_after, |
| 423 | (const char **) names)) { |
| 424 | err = REFTABLE_NOT_EXIST_ERROR; |
| 425 | goto out; |
no test coverage detected