diff --git a/changelogs/unreleased/gh-10128-vy-invalid-vylog-fix.md b/changelogs/unreleased/gh-10128-vy-invalid-vylog-fix.md new file mode 100644 index 0000000000000000000000000000000000000000..ef4c9a3b00ba95f922529c664fba6272afae9bce --- /dev/null +++ b/changelogs/unreleased/gh-10128-vy-invalid-vylog-fix.md @@ -0,0 +1,4 @@ +## bugfix/vinyl + +* Fixed a bug when recovery failed with the error "Invalid VYLOG file: Run XXXX + forgotten but not registered" (gh-10128). diff --git a/src/box/vinyl.c b/src/box/vinyl.c index 19c6ff9ea0a91c380eee5c3501bf795e4f785776..40c47a3cab0f55c48af16ff8dea1e2e7fbae0524 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -3257,7 +3257,7 @@ vinyl_engine_collect_garbage(struct engine *engine, const struct vclock *vclock) vy_log_collect_garbage(vclock); /* Cleanup run files. */ - struct vy_recovery *recovery = vy_recovery_new(vy_log_signature(), 0); + struct vy_recovery *recovery = vy_recovery_new(-1, 0); if (recovery == NULL) { say_error("failed to recover vylog for garbage collection"); return; diff --git a/src/box/vy_log.c b/src/box/vy_log.c index 40270bf78949b625a3af6775563fc70a5fbbe5b3..b9cb67bb700a06c4896a145cc69ca3ce20f558a4 100644 --- a/src/box/vy_log.c +++ b/src/box/vy_log.c @@ -1003,8 +1003,7 @@ static int vy_log_rebootstrap(void) { struct vy_recovery *recovery; - recovery = vy_recovery_new(vclock_sum(&vy_log.last_checkpoint), - VY_RECOVERY_ABORT_REBOOTSTRAP); + recovery = vy_recovery_new(-1, VY_RECOVERY_ABORT_REBOOTSTRAP); if (recovery == NULL) return -1; @@ -1169,8 +1168,7 @@ vy_log_begin_recovery(const struct vclock *vclock, bool force_recovery) * failed, and we need to mark rebootstrap as aborted. */ struct vy_recovery *recovery; - recovery = vy_recovery_new(vclock_sum(&vy_log.last_checkpoint), - VY_RECOVERY_ABORT_REBOOTSTRAP); + recovery = vy_recovery_new(-1, VY_RECOVERY_ABORT_REBOOTSTRAP); if (recovery == NULL) return NULL; @@ -2463,6 +2461,7 @@ vy_recovery_new_locked(int64_t signature, int flags) int rc; struct vy_recovery *recovery; + assert(signature >= 0); assert(latch_owner(&vy_log.latch) == fiber()); /* * Before proceeding to log recovery, make sure that all @@ -2490,6 +2489,8 @@ vy_recovery_new(int64_t signature, int flags) { /* Lock out concurrent writers while we are loading the log. */ latch_lock(&vy_log.latch); + if (signature < 0) + signature = vclock_sum(&vy_log.last_checkpoint); struct vy_recovery *recovery; recovery = vy_recovery_new_locked(signature, flags); latch_unlock(&vy_log.latch); diff --git a/src/box/vy_log.h b/src/box/vy_log.h index c98cb37f736fc04f215aaac85a69f3b38ba6491a..603298fef8e66bba920aabd6107914dadfd8cff9 100644 --- a/src/box/vy_log.h +++ b/src/box/vy_log.h @@ -593,6 +593,15 @@ enum vy_recovery_flag { * Create a recovery context from the metadata log created * by checkpoint with the given signature. * + * If the signature is -1, the function loads the metadata log corresponding + * to the last created checkpoint. Note, it isn't quite the same as passing + * vy_log_signature(). The latter opens a time window for a log rotation so + * it may load a stale metadata log while using -1 locks out concurrent log + * rotation and thus guarantees that the function loads the latest log. + * This is important if the caller writes new log records asynchronously + * (with vy_log_tx_try_commit()) basing on the recovered state and expects + * them to be recovered on the next execution. + * * For valid values of @flags, see vy_recovery_flag. * * Returns NULL on failure.