From db6535c45d6300afa64c179085f7952e6c114fd2 Mon Sep 17 00:00:00 2001
From: Vladimir Davydov <vdavydov@tarantool.org>
Date: Fri, 19 Aug 2022 17:49:57 +0300
Subject: [PATCH] index: store copy of index_def in index_read_view

To implement all iterator types for memtx tree and hash index read
views, we need to have the key definition. We can't just use the key
definition stored in the index directly, because, despite the fact that
a read view keeps a reference the index, its index definition may still
be changed by alter (when compatible changes happen).

To solve this problem, let's store a copy of the index definition in
memtx tree and hash index read views. The index definition also contains
the index name, which will be useful for exporting the read view to Lua.

Needed for https://github.com/tarantool/tarantool-ee/issues/197

NO_DOC=internal
NO_TEST=ee
NO_CHANGELOG=internal
---
 src/box/index.cc      | 20 ++++++++++++++++++++
 src/box/index.h       | 19 ++++++++++++++-----
 src/box/memtx_hash.cc |  5 ++++-
 src/box/memtx_tree.cc |  5 ++++-
 src/box/sequence.c    |  5 ++++-
 5 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/src/box/index.cc b/src/box/index.cc
index 3058e668a5..74eeeaa3ad 100644
--- a/src/box/index.cc
+++ b/src/box/index.cc
@@ -603,6 +603,26 @@ index_delete(struct index *index)
 	index_def_delete(def);
 }
 
+int
+index_read_view_create(struct index_read_view *rv,
+		       const struct index_read_view_vtab *vtab,
+		       struct index_def *def)
+{
+	rv->vtab = vtab;
+	rv->def = index_def_dup(def);
+	if (rv->def == NULL)
+		return -1;
+	return 0;
+}
+
+void
+index_read_view_delete(struct index_read_view *rv)
+{
+	struct index_def *def = rv->def;
+	rv->vtab->free(rv);
+	index_def_delete(def);
+}
+
 /* }}} */
 
 /* {{{ Virtual method stubs */
diff --git a/src/box/index.h b/src/box/index.h
index 8a392b67a0..b3f5e79a5c 100644
--- a/src/box/index.h
+++ b/src/box/index.h
@@ -571,6 +571,8 @@ struct index_read_view_vtab {
 struct index_read_view {
 	/** Virtual function table. */
 	const struct index_read_view_vtab *vtab;
+	/** Copy of the index definition. */
+	struct index_def *def;
 };
 
 /** Iterator over an index read view. */
@@ -821,11 +823,18 @@ index_end_build(struct index *index)
 	index->vtab->end_build(index);
 }
 
-static inline void
-index_read_view_delete(struct index_read_view *rv)
-{
-	rv->vtab->free(rv);
-}
+/**
+ * Initialize an index read view instance.
+ * Note, this function copies the given index definition.
+ */
+int
+index_read_view_create(struct index_read_view *rv,
+		       const struct index_read_view_vtab *vtab,
+		       struct index_def *def);
+
+/** Free an index read view instance. */
+void
+index_read_view_delete(struct index_read_view *rv);
 
 static inline struct index_read_view_iterator *
 index_read_view_create_iterator(struct index_read_view *rv,
diff --git a/src/box/memtx_hash.cc b/src/box/memtx_hash.cc
index 25f6fd32cd..3c3b666075 100644
--- a/src/box/memtx_hash.cc
+++ b/src/box/memtx_hash.cc
@@ -562,9 +562,12 @@ memtx_hash_index_create_read_view(struct index *base)
 	struct memtx_hash_index *index = (struct memtx_hash_index *)base;
 	struct hash_read_view *rv =
 		(struct hash_read_view *)xmalloc(sizeof(*rv));
+	if (index_read_view_create(&rv->base, &vtab, base->def) != 0) {
+		free(rv);
+		return NULL;
+	}
 	struct space *space = space_cache_find(base->def->space_id);
 	memtx_tx_snapshot_cleaner_create(&rv->cleaner, space);
-	rv->base.vtab = &vtab;
 	rv->index = index;
 	index_ref(base);
 	light_index_view_create(&rv->view, &index->hash_table);
diff --git a/src/box/memtx_tree.cc b/src/box/memtx_tree.cc
index 02c5e24c50..9c5dddb059 100644
--- a/src/box/memtx_tree.cc
+++ b/src/box/memtx_tree.cc
@@ -1782,9 +1782,12 @@ memtx_tree_index_create_read_view(struct index *base)
 		(struct memtx_tree_index<USE_HINT> *)base;
 	struct tree_read_view<USE_HINT> *rv =
 		(struct tree_read_view<USE_HINT> *)xmalloc(sizeof(*rv));
+	if (index_read_view_create(&rv->base, &vtab, base->def) != 0) {
+		free(rv);
+		return NULL;
+	}
 	struct space *space = space_cache_find(base->def->space_id);
 	memtx_tx_snapshot_cleaner_create(&rv->cleaner, space);
-	rv->base.vtab = &vtab;
 	rv->index = index;
 	index_ref(base);
 	memtx_tree_view_create(&rv->tree_view, &index->tree);
diff --git a/src/box/sequence.c b/src/box/sequence.c
index f6eefd4bc1..9db36fe7c3 100644
--- a/src/box/sequence.c
+++ b/src/box/sequence.c
@@ -396,7 +396,10 @@ sequence_data_read_view_create(struct index *index)
 		.create_iterator = sequence_data_iterator_create,
 	};
 	struct sequence_data_read_view *rv = xmalloc(sizeof(*rv));
-	rv->base.vtab = &vtab;
+	if (index_read_view_create(&rv->base, &vtab, index->def) != 0) {
+		free(rv);
+		return NULL;
+	}
 	light_sequence_view_create(&rv->view, &sequence_data_index);
 	return (struct index_read_view *)rv;
 }
-- 
GitLab