[patches] [PATCH 1/1] vinyl: use vinyl iterators virtuality to remove 'if' in next()

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Sat Feb 17 12:52:38 MSK 2018


The first reason of the patch is that vinyl iterators are virtual
already, and 'if's about constant index attributes (like index->id)
can be replaced by new next() implementation. Now in next() index->id
is checked to detect necessity of primary index lookup.

Lets split next() in 2 functions: primary_next() and secondary_next()
to remove 'if'.

The second reason, that in #2129 logic of secondary index lookup
complicates a lot. For example, there is raw idea to do not add
statements into a cache before looking up in a primary index, because
after #2129 any tuple, read from a secondary index, can be dirty.

Needed for #2129

Signed-off-by: Vladislav Shpilevoy <v.shpilevoy at tarantool.org>
---
 src/box/vinyl.c | 55 +++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 41 insertions(+), 14 deletions(-)

diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index 03ad2bf4a..992ceca37 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -3823,10 +3823,11 @@ vinyl_iterator_close(struct vinyl_iterator *it)
 }
 
 static int
-vinyl_iterator_next(struct iterator *base, struct tuple **ret)
+vinyl_iterator_primary_next(struct iterator *base, struct tuple **ret)
 {
-	assert(base->next = vinyl_iterator_next);
+	assert(base->next = vinyl_iterator_primary_next);
 	struct vinyl_iterator *it = (struct vinyl_iterator *)base;
+	assert(it->index->id == 0);
 	struct tuple *tuple;
 
 	if ((*it->rv)->is_aborted ||
@@ -3843,21 +3844,44 @@ vinyl_iterator_next(struct iterator *base, struct tuple **ret)
 		*ret = NULL;
 		return 0;
 	}
+	*ret = tuple_bless(tuple);
+	if (*ret != NULL)
+		return 0;
+fail:
+	vinyl_iterator_close(it);
+	return -1;
+}
 
-	if (it->index->id > 0) {
-		/* Get the full tuple from the primary index. */
-		if (vy_index_get(it->index->pk, it->tx, it->rv,
-				 tuple, &tuple) != 0)
-			goto fail;
-	} else {
-		tuple_ref(tuple);
+static int
+vinyl_iterator_secondary_next(struct iterator *base, struct tuple **ret)
+{
+	assert(base->next = vinyl_iterator_secondary_next);
+	struct vinyl_iterator *it = (struct vinyl_iterator *)base;
+	assert(it->index->id > 0);
+	struct tuple *tuple;
+
+	if ((*it->rv)->is_aborted ||
+	    (it->tx != NULL && it->tx->state == VINYL_TX_ABORT)) {
+		goto fail;
 	}
-	*ret = tuple_bless(tuple);
-	tuple_unref(tuple);
-	if (*ret == NULL)
+
+	if (vy_read_iterator_next(&it->iterator, &tuple) != 0)
 		goto fail;
 
-	return 0;
+	if (tuple == NULL) {
+		/* EOF. Close the iterator immediately. */
+		vinyl_iterator_close(it);
+		*ret = NULL;
+		return 0;
+	}
+	/* Get the full tuple from the primary index. */
+	if (vy_index_get(it->index->pk, it->tx, it->rv,
+			 tuple, &tuple) != 0)
+		goto fail;
+	*ret = tuple_bless(tuple);
+	tuple_unref(tuple);
+	if (*ret != NULL)
+		return 0;
 fail:
 	vinyl_iterator_close(it);
 	return -1;
@@ -3916,7 +3940,10 @@ vinyl_index_create_iterator(struct index *base, enum iterator_type type,
 		goto err_key;
 
 	iterator_create(&it->base, base);
-	it->base.next = vinyl_iterator_next;
+	if (index->id == 0)
+		it->base.next = vinyl_iterator_primary_next;
+	else
+		it->base.next = vinyl_iterator_secondary_next;
 	it->base.free = vinyl_iterator_free;
 
 	it->env = env;
-- 
2.14.3 (Apple Git-98)




More information about the Tarantool-patches mailing list