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

  • From: Vladimir Davydov <vdavydov.dev@xxxxxxxxx>
  • To: tarantool-patches@xxxxxxxxxxxxx
  • Date: Sat, 10 Aug 2019 13:03:35 +0300

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


Other related posts: