[PATCH 08/13] memtx: allow snapshot iterator to fail

Vladimir Davydov vdavydov.dev at gmail.com
Sat Aug 10 13:03:35 MSK 2019


Memtx iterators never fail, that's why the snapshot iterator interface
doesn't support failures. However, once we introduce snapshot iterator
support for vinyl, we will need a way to handle errors in the API.
---
 src/box/index.h        |  3 ++-
 src/box/memtx_engine.c | 22 ++++++++++++----------
 src/box/memtx_hash.c   | 14 +++++++++-----
 src/box/memtx_tree.c   | 14 +++++++++-----
 src/box/sequence.c     | 24 ++++++++++++++----------
 5 files changed, 46 insertions(+), 31 deletions(-)

diff --git a/src/box/index.h b/src/box/index.h
index 89b5e134..86148023 100644
--- a/src/box/index.h
+++ b/src/box/index.h
@@ -293,7 +293,8 @@ struct snapshot_iterator {
 	 * Returns a pointer to the tuple data and its
 	 * size or NULL if EOF.
 	 */
-	const char *(*next)(struct snapshot_iterator *, uint32_t *size);
+	int (*next)(struct snapshot_iterator *,
+		    const char **data, uint32_t *size);
 	/**
 	 * Destroy the iterator.
 	 */
diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c
index ec667e7a..87806775 100644
--- a/src/box/memtx_engine.c
+++ b/src/box/memtx_engine.c
@@ -575,25 +575,27 @@ checkpoint_f(va_list ap)
 	ERROR_INJECT_SLEEP(ERRINJ_SNAP_WRITE_DELAY);
 	struct checkpoint_entry *entry;
 	rlist_foreach_entry(entry, &ckpt->entries, link) {
+		int rc;
 		uint32_t size;
 		const char *data;
 		struct snapshot_iterator *it = entry->iterator;
-		for (data = it->next(it, &size); data != NULL;
-		     data = it->next(it, &size)) {
+		while ((rc = it->next(it, &data, &size)) == 0 && data != NULL) {
 			if (checkpoint_write_tuple(&snap, entry->space_id,
-					entry->group_id, data, size) != 0) {
-				xlog_close(&snap, false);
-				return -1;
-			}
+					entry->group_id, data, size) != 0)
+				goto fail;
 		}
+		if (rc != 0)
+			goto fail;
 	}
-	if (xlog_flush(&snap) < 0) {
-		xlog_close(&snap, false);
-		return -1;
-	}
+	if (xlog_flush(&snap) < 0)
+		goto fail;
+
 	xlog_close(&snap, false);
 	say_info("done");
 	return 0;
+fail:
+	xlog_close(&snap, false);
+	return -1;
 }
 
 static int
diff --git a/src/box/memtx_hash.c b/src/box/memtx_hash.c
index 2762d973..920f1032 100644
--- a/src/box/memtx_hash.c
+++ b/src/box/memtx_hash.c
@@ -424,8 +424,9 @@ hash_snapshot_iterator_free(struct snapshot_iterator *iterator)
  * Virtual method of snapshot iterator.
  * @sa index_vtab::create_snapshot_iterator.
  */
-static const char *
-hash_snapshot_iterator_next(struct snapshot_iterator *iterator, uint32_t *size)
+static int
+hash_snapshot_iterator_next(struct snapshot_iterator *iterator,
+			    const char **data, uint32_t *size)
 {
 	assert(iterator->free == hash_snapshot_iterator_free);
 	struct hash_snapshot_iterator *it =
@@ -433,9 +434,12 @@ hash_snapshot_iterator_next(struct snapshot_iterator *iterator, uint32_t *size)
 	struct light_index_core *hash_table = &it->index->hash_table;
 	struct tuple **res = light_index_iterator_get_and_next(hash_table,
 							       &it->iterator);
-	if (res == NULL)
-		return NULL;
-	return tuple_data_range(*res, size);
+	if (res == NULL) {
+		*data = NULL;
+		return 0;
+	}
+	*data = tuple_data_range(*res, size);
+	return 0;
 }
 
 /**
diff --git a/src/box/memtx_tree.c b/src/box/memtx_tree.c
index 77223a6d..831a2715 100644
--- a/src/box/memtx_tree.c
+++ b/src/box/memtx_tree.c
@@ -1220,8 +1220,9 @@ tree_snapshot_iterator_free(struct snapshot_iterator *iterator)
 	free(iterator);
 }
 
-static const char *
-tree_snapshot_iterator_next(struct snapshot_iterator *iterator, uint32_t *size)
+static int
+tree_snapshot_iterator_next(struct snapshot_iterator *iterator,
+			    const char **data, uint32_t *size)
 {
 	assert(iterator->free == tree_snapshot_iterator_free);
 	struct tree_snapshot_iterator *it =
@@ -1229,10 +1230,13 @@ tree_snapshot_iterator_next(struct snapshot_iterator *iterator, uint32_t *size)
 	struct memtx_tree *tree = &it->index->tree;
 	struct memtx_tree_data *res = memtx_tree_iterator_get_elem(tree,
 							&it->tree_iterator);
-	if (res == NULL)
-		return NULL;
+	if (res == NULL) {
+		*data = NULL;
+		return 0;
+	}
 	memtx_tree_iterator_next(tree, &it->tree_iterator);
-	return tuple_data_range(res->tuple, size);
+	*data = tuple_data_range(res->tuple, size);
+	return 0;
 }
 
 /**
diff --git a/src/box/sequence.c b/src/box/sequence.c
index 1aacc505..5ebfa274 100644
--- a/src/box/sequence.c
+++ b/src/box/sequence.c
@@ -311,27 +311,31 @@ struct sequence_data_iterator {
 #define SEQUENCE_TUPLE_BUF_SIZE		(mp_sizeof_array(2) + \
 					 2 * mp_sizeof_uint(UINT64_MAX))
 
-static const char *
-sequence_data_iterator_next(struct snapshot_iterator *base, uint32_t *size)
+static int
+sequence_data_iterator_next(struct snapshot_iterator *base,
+			    const char **data, uint32_t *size)
 {
 	struct sequence_data_iterator *iter =
 		(struct sequence_data_iterator *)base;
 
-	struct sequence_data *data =
+	struct sequence_data *sd =
 		light_sequence_iterator_get_and_next(&sequence_data_index,
 						     &iter->iter);
-	if (data == NULL)
-		return NULL;
+	if (sd == NULL) {
+		*data = NULL;
+		return 0;
+	}
 
 	char *buf_end = iter->tuple;
 	buf_end = mp_encode_array(buf_end, 2);
-	buf_end = mp_encode_uint(buf_end, data->id);
-	buf_end = (data->value >= 0 ?
-		   mp_encode_uint(buf_end, data->value) :
-		   mp_encode_int(buf_end, data->value));
+	buf_end = mp_encode_uint(buf_end, sd->id);
+	buf_end = (sd->value >= 0 ?
+		   mp_encode_uint(buf_end, sd->value) :
+		   mp_encode_int(buf_end, sd->value));
 	assert(buf_end <= iter->tuple + SEQUENCE_TUPLE_BUF_SIZE);
+	*data = iter->tuple;
 	*size = buf_end - iter->tuple;
-	return iter->tuple;
+	return 0;
 }
 
 static void
-- 
2.20.1




More information about the Tarantool-patches mailing list