From ea7af7f345f832e9ae137e7a4d2480a8e5394994 Mon Sep 17 00:00:00 2001
From: Vladimir Davydov <vdavydov.dev@gmail.com>
Date: Wed, 12 Jul 2017 17:06:36 +0300
Subject: [PATCH] vinyl: zap include_deleted flag argument of
 vy_recovery_iterate

This flag is needed to skip records corresponding to dropped and
incomplete runs on recovery, because given VY_LOG_CREATE_RUN the
vy_recovery_iterate() callback can't tell if the run is used or
going to be dropped. This flag needlessly complicates the code of
vy_recovery_iterate(), which is supposed to simply replay all records
recovered from the log, not try to be smart. Let's get rid of it and
instead add a hint to vy_log_record indicating that a run created by
VY_LOG_CREATE_RUN is going to be dropped.
---
 src/box/vinyl.c    |  8 ++++----
 src/box/vy_index.c | 14 ++++++++++++++
 src/box/vy_log.c   | 40 ++++++----------------------------------
 src/box/vy_log.h   | 12 +++++++-----
 4 files changed, 31 insertions(+), 43 deletions(-)

diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index 477d2d9254..fc68f592db 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -5796,7 +5796,7 @@ vy_join(struct vy_env *env, struct vclock *vclock, struct xstream *stream)
 	recovery = vy_recovery_new(vclock_sum(vclock), true);
 	if (recovery == NULL)
 		goto out_join_cord;
-	rc = vy_recovery_iterate(recovery, false, vy_join_cb, ctx);
+	rc = vy_recovery_iterate(recovery, vy_join_cb, ctx);
 	vy_recovery_delete(recovery);
 	/* Send the last range. */
 	if (rc == 0)
@@ -5923,7 +5923,7 @@ vy_gc(struct vy_env *env, struct vy_recovery *recovery,
 		.gc_mask = gc_mask,
 		.gc_lsn = gc_lsn,
 	};
-	vy_recovery_iterate(recovery, true, vy_gc_cb, &arg);
+	vy_recovery_iterate(recovery, vy_gc_cb, &arg);
 }
 
 void
@@ -5977,7 +5977,7 @@ vy_backup_cb(const struct vy_log_record *record, void *cb_arg)
 		arg->index_id = record->index_id;
 	}
 
-	if (record->type != VY_LOG_CREATE_RUN)
+	if (record->type != VY_LOG_CREATE_RUN || record->is_dropped)
 		goto out;
 
 	char path[PATH_MAX];
@@ -6015,7 +6015,7 @@ vy_backup(struct vy_env *env, struct vclock *vclock,
 		.cb = cb,
 		.cb_arg = cb_arg,
 	};
-	int rc = vy_recovery_iterate(recovery, false, vy_backup_cb, &arg);
+	int rc = vy_recovery_iterate(recovery, vy_backup_cb, &arg);
 	vy_recovery_delete(recovery);
 	return rc;
 }
diff --git a/src/box/vy_index.c b/src/box/vy_index.c
index 403f546010..89e458dbf8 100644
--- a/src/box/vy_index.c
+++ b/src/box/vy_index.c
@@ -416,7 +416,11 @@ vy_index_recovery_cb(const struct vy_log_record *record, void *cb_arg)
 		assert(record->index_lsn == index->opts.lsn);
 		index->is_dropped = true;
 		break;
+	case VY_LOG_PREPARE_RUN:
+		break;
 	case VY_LOG_CREATE_RUN:
+		if (record->is_dropped)
+			break;
 		assert(record->index_lsn == index->opts.lsn);
 		run = vy_run_new(record->run_id);
 		if (run == NULL)
@@ -436,6 +440,8 @@ vy_index_recovery_cb(const struct vy_log_record *record, void *cb_arg)
 			goto out;
 		}
 		break;
+	case VY_LOG_DROP_RUN:
+		break;
 	case VY_LOG_INSERT_RANGE:
 		assert(record->index_lsn == index->opts.lsn);
 		range = vy_range_new(record->range_id, begin, end,
@@ -531,6 +537,14 @@ vy_index_recover(struct vy_index *index, struct vy_recovery *recovery,
 		return vy_index_init_range_tree(index);
 	}
 
+	if (index->is_dropped) {
+		/*
+		 * Initial range is not stored in the metadata log
+		 * for dropped indexes, but we need it for recovery.
+		 */
+		return vy_index_init_range_tree(index);
+	}
+
 	/*
 	 * Account ranges to the index and check that the range tree
 	 * does not have holes or overlaps.
diff --git a/src/box/vy_log.c b/src/box/vy_log.c
index 965a83a192..2c7aa84c7b 100644
--- a/src/box/vy_log.c
+++ b/src/box/vy_log.c
@@ -975,8 +975,7 @@ vy_log_create(const struct vclock *vclock, struct vy_recovery *recovery)
 		.dir = &vy_log.dir,
 		.vclock = vclock,
 	};
-	if (vy_recovery_iterate(recovery, true,
-				vy_log_rotate_cb_func, &arg) < 0)
+	if (vy_recovery_iterate(recovery, vy_log_rotate_cb_func, &arg) < 0)
 		goto err_write_xlog;
 
 	if (!xlog_is_open(&xlog))
@@ -2009,7 +2008,7 @@ vy_recovery_cb_call(vy_recovery_cb cb, void *cb_arg,
 
 static int
 vy_recovery_iterate_index(struct vy_index_recovery_info *index,
-		bool include_deleted, vy_recovery_cb cb, void *cb_arg)
+			  vy_recovery_cb cb, void *cb_arg)
 {
 	struct vy_range_recovery_info *range;
 	struct vy_slice_recovery_info *slice;
@@ -2034,29 +2033,6 @@ vy_recovery_iterate_index(struct vy_index_recovery_info *index,
 			return -1;
 	}
 
-	if (!include_deleted && index->is_dropped) {
-		/*
-		 * Do not load the index as it is going to be
-		 * dropped on WAL recovery anyway. Just create
-		 * an initial range to make vy_get() happy.
-		 */
-		vy_log_record_init(&record);
-		record.type = VY_LOG_INSERT_RANGE;
-		record.index_lsn = index->index_lsn;
-		record.range_id = INT64_MAX; /* fake id */
-		record.begin = record.end = NULL;
-		if (vy_recovery_cb_call(cb, cb_arg, &record) != 0)
-			return -1;
-
-		vy_log_record_init(&record);
-		record.type = VY_LOG_DROP_INDEX;
-		record.index_lsn = index->index_lsn;
-		if (vy_recovery_cb_call(cb, cb_arg, &record) != 0)
-			return -1;
-
-		return 0;
-	}
-
 	if (index->dump_lsn >= 0) {
 		vy_log_record_init(&record);
 		record.type = VY_LOG_DUMP_INDEX;
@@ -2067,10 +2043,6 @@ vy_recovery_iterate_index(struct vy_index_recovery_info *index,
 	}
 
 	rlist_foreach_entry(run, &index->runs, in_index) {
-		if (!include_deleted &&
-		    (run->is_dropped || run->is_incomplete))
-			continue;
-
 		vy_log_record_init(&record);
 		if (run->is_incomplete) {
 			record.type = VY_LOG_PREPARE_RUN;
@@ -2080,6 +2052,7 @@ vy_recovery_iterate_index(struct vy_index_recovery_info *index,
 		}
 		record.index_lsn = index->index_lsn;
 		record.run_id = run->id;
+		record.is_dropped = run->is_dropped;
 		if (vy_recovery_cb_call(cb, cb_arg, &record) != 0)
 			return -1;
 
@@ -2132,7 +2105,7 @@ vy_recovery_iterate_index(struct vy_index_recovery_info *index,
 }
 
 int
-vy_recovery_iterate(struct vy_recovery *recovery, bool include_deleted,
+vy_recovery_iterate(struct vy_recovery *recovery,
 		    vy_recovery_cb cb, void *cb_arg)
 {
 	mh_int_t i;
@@ -2146,8 +2119,7 @@ vy_recovery_iterate(struct vy_recovery *recovery, bool include_deleted,
 		 */
 		if (index->is_dropped && rlist_empty(&index->runs))
 			continue;
-		if (vy_recovery_iterate_index(index, include_deleted,
-					      cb, cb_arg) < 0)
+		if (vy_recovery_iterate_index(index, cb, cb_arg) < 0)
 			return -1;
 	}
 	return 0;
@@ -2161,5 +2133,5 @@ vy_recovery_load_index(struct vy_recovery *recovery, int64_t index_lsn,
 	index = vy_recovery_lookup_index(recovery, index_lsn);
 	if (index == NULL)
 		return 0;
-	return vy_recovery_iterate_index(index, false, cb, cb_arg);
+	return vy_recovery_iterate_index(index, cb, cb_arg);
 }
diff --git a/src/box/vy_log.h b/src/box/vy_log.h
index 06881fcb1a..953dd2938f 100644
--- a/src/box/vy_log.h
+++ b/src/box/vy_log.h
@@ -176,6 +176,12 @@ struct vy_log_record {
 	int64_t run_id;
 	/** Unique ID of the run slice. */
 	int64_t slice_id;
+	/**
+	 * For VY_LOG_CREATE_RUN record: hint that the run
+	 * is dropped, i.e. there is a VY_LOG_DROP_RUN record
+	 * following this one.
+	 */
+	bool is_dropped;
 	/**
 	 * Msgpack key for start of the range/slice.
 	 * NULL if the range/slice starts from -inf.
@@ -369,13 +375,9 @@ typedef int
  * slices of a range always go right after the range, in the
  * chronological order, while an index's runs go after the index
  * and before its ranges.
- *
- * If @include_deleted is set, this function will also iterate over
- * deleted objects, issuing the corresponding "delete" record for each
- * of them.
  */
 int
-vy_recovery_iterate(struct vy_recovery *recovery, bool include_deleted,
+vy_recovery_iterate(struct vy_recovery *recovery,
 		    vy_recovery_cb cb, void *cb_arg);
 
 /**
-- 
GitLab