Commit Diff


commit - 19d1f1cc0a2180730219a5fe24580c6d7fbcc239
commit + 9d3859b246977c307a22f5930755fe77e374a634
blob - /dev/null
blob + ef4c9a3b00ba95f922529c664fba6272afae9bce (mode 644)
--- /dev/null
+++ 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).
blob - 19c6ff9ea0a91c380eee5c3501bf795e4f785776
blob + 40c47a3cab0f55c48af16ff8dea1e2e7fbae0524
--- src/box/vinyl.c
+++ src/box/vinyl.c
@@ -3257,7 +3257,7 @@ vinyl_engine_collect_garbage(struct engine *engine, co
 	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;
blob - 40270bf78949b625a3af6775563fc70a5fbbe5b3
blob + b9cb67bb700a06c4896a145cc69ca3ce20f558a4
--- src/box/vy_log.c
+++ 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, boo
 	 * 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);
blob - c98cb37f736fc04f215aaac85a69f3b38ba6491a
blob + 603298fef8e66bba920aabd6107914dadfd8cff9
--- src/box/vy_log.h
+++ 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.