diff --git a/src/box/index.cc b/src/box/index.cc index eba9c8c0b60865ef7b8068e554dd5febca045dbf..02a6cc56a8165a26cc8c8259e43810a1802c6b7f 100644 --- a/src/box/index.cc +++ b/src/box/index.cc @@ -757,8 +757,8 @@ generic_index_create_iterator(struct index *base, enum iterator_type type, } -struct snapshot_iterator * -generic_index_create_snapshot_iterator(struct index *index) +struct index_read_view * +generic_index_create_read_view(struct index *index) { diag_set(UnsupportedIndexFeature, index->def, "consistent read view"); return NULL; diff --git a/src/box/index.h b/src/box/index.h index 13a6fc757dbf185757c00b28577799c66e894fb9..6bb88d51ff1a63da081aab0fefed341598f48813 100644 --- a/src/box/index.h +++ b/src/box/index.h @@ -45,6 +45,8 @@ struct tuple; struct engine; struct space; struct index; +struct index_read_view; +struct index_read_view_iterator; struct index_def; struct key_def; struct info_handler; @@ -359,24 +361,6 @@ iterator_next_internal(struct iterator *it, struct tuple **ret); void iterator_delete(struct iterator *it); -/** - * Snapshot iterator. - * \sa index::create_snapshot_iterator(). - */ -struct snapshot_iterator { - /** - * Iterate to the next tuple in the snapshot. - * Returns a pointer to the tuple data and its - * size or NULL if EOF. - */ - int (*next)(struct snapshot_iterator *, - const char **data, uint32_t *size); - /** - * Destroy the iterator. - */ - void (*free)(struct snapshot_iterator *); -}; - /** * Check that the key has correct part count and correct part size * for use in an index iterator. @@ -512,12 +496,8 @@ struct index_vtab { struct iterator *(*create_iterator)(struct index *index, enum iterator_type type, const char *key, uint32_t part_count); - /** - * Create an ALL iterator with personal read view so further - * index modifications will not affect the iteration results. - * Must be destroyed by iterator_delete() after usage. - */ - struct snapshot_iterator *(*create_snapshot_iterator)(struct index *); + /** Create an index read view. */ + struct index_read_view *(*create_read_view)(struct index *index); /** Introspection (index:stat()) */ void (*stat)(struct index *, struct info_handler *); /** @@ -567,6 +547,52 @@ struct index { struct rlist full_scans; }; +/** Index read view virtual function table. */ +struct index_read_view_vtab { + /** Free an index read view instance. */ + void + (*free)(struct index_read_view *rv); + /** Create an index read view iterator. */ + struct index_read_view_iterator * + (*create_iterator)(struct index_read_view *rv, enum iterator_type type, + const char *key, uint32_t part_count); +}; + +/** + * Index read view. + * + * An index read view is a frozen image of the index at the time of the read + * view creation. It only has read-only methods. The API is similar to the API + * of an index, but a read view returns raw data (not wrapped in struct tuple). + * + * Note about multi-threading: a read view may only be created and destroyed in + * the tx thread, but it may be used in any other thread. + */ +struct index_read_view { + /** Virtual function table. */ + const struct index_read_view_vtab *vtab; +}; + +/** Iterator over an index read view. */ +struct index_read_view_iterator { + /** Free an index read view iterator instance. */ + void + (*free)(struct index_read_view_iterator *iterator); + /** + * Iterate to the next tuple in the read view. + * + * The tuple data and size are returned in the data and size arguments. + * Note, the tuple may be allocated from the fiber region so one should + * call region_truncate after using the data. On EOF the data is set to + * NULL. + * + * Returns 0 on success. On error returns -1 and sets diag. + */ + int + (*next_raw)(struct index_read_view_iterator *iterator, + const char **data, uint32_t *size); +}; + /** * Check if replacement of an old tuple with a new one is * allowed. @@ -747,10 +773,10 @@ index_create_iterator(struct index *index, enum iterator_type type, return index->vtab->create_iterator(index, type, key, part_count); } -static inline struct snapshot_iterator * -index_create_snapshot_iterator(struct index *index) +static inline struct index_read_view * +index_create_read_view(struct index *index) { - return index->vtab->create_snapshot_iterator(index); + return index->vtab->create_read_view(index); } static inline void @@ -795,6 +821,33 @@ 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); +} + +static inline struct index_read_view_iterator * +index_read_view_create_iterator(struct index_read_view *rv, + enum iterator_type type, + const char *key, uint32_t part_count) +{ + return rv->vtab->create_iterator(rv, type, key, part_count); +} + +static inline void +index_read_view_iterator_delete(struct index_read_view_iterator *iterator) +{ + iterator->free(iterator); +} + +static inline int +index_read_view_iterator_next_raw(struct index_read_view_iterator *iterator, + const char **data, uint32_t *size) +{ + return iterator->next_raw(iterator, data, size); +} + /* * Virtual method stubs. */ @@ -820,7 +873,8 @@ int generic_index_get(struct index *, const char *, uint32_t, struct tuple **); int generic_index_replace(struct index *, struct tuple *, struct tuple *, enum dup_replace_mode, struct tuple **, struct tuple **); -struct snapshot_iterator *generic_index_create_snapshot_iterator(struct index *); +struct index_read_view * +generic_index_create_read_view(struct index *index); void generic_index_stat(struct index *, struct info_handler *); void generic_index_compact(struct index *); void generic_index_reset_stat(struct index *); diff --git a/src/box/memtx_bitset.cc b/src/box/memtx_bitset.cc index 654be6a20c488973238607a27294c07e43587834..c96316b0bcd37cdfc15ddb35347398f891c9f862 100644 --- a/src/box/memtx_bitset.cc +++ b/src/box/memtx_bitset.cc @@ -502,8 +502,7 @@ static const struct index_vtab memtx_bitset_index_vtab = { /* .get = */ generic_index_get, /* .replace = */ memtx_bitset_index_replace, /* .create_iterator = */ memtx_bitset_index_create_iterator, - /* .create_snapshot_iterator = */ - generic_index_create_snapshot_iterator, + /* .create_read_view = */ generic_index_create_read_view, /* .stat = */ generic_index_stat, /* .compact = */ generic_index_compact, /* .reset_stat = */ generic_index_reset_stat, diff --git a/src/box/memtx_engine.cc b/src/box/memtx_engine.cc index 5a495ecf95c79f7dd8aec89e72ad196f19db11d8..ed29450cbe5ce6c5442b288f87540ba629e66165 100644 --- a/src/box/memtx_engine.cc +++ b/src/box/memtx_engine.cc @@ -654,7 +654,7 @@ checkpoint_write_tuple(struct xlog *l, uint32_t space_id, uint32_t group_id, struct checkpoint_entry { uint32_t space_id; uint32_t group_id; - struct snapshot_iterator *iterator; + struct index_read_view *rv; struct rlist link; }; @@ -711,7 +711,7 @@ checkpoint_delete(struct checkpoint *ckpt) { struct checkpoint_entry *entry, *tmp; rlist_foreach_entry_safe(entry, &ckpt->entries, link, tmp) { - entry->iterator->free(entry->iterator); + index_read_view_delete(entry->rv); free(entry); } memtx_allocators_close_read_view(ckpt->rv); @@ -768,8 +768,8 @@ checkpoint_add_space(struct space *sp, void *data) entry->space_id = space_id(sp); entry->group_id = space_group_id(sp); - entry->iterator = index_create_snapshot_iterator(pk); - if (entry->iterator == NULL) + entry->rv = index_create_read_view(pk); + if (entry->rv == NULL) return -1; return 0; @@ -827,13 +827,24 @@ checkpoint_f(va_list ap) int rc; uint32_t size; const char *data; - struct snapshot_iterator *it = entry->iterator; - while ((rc = it->next(it, &data, &size)) == 0 && data != NULL) { - if (checkpoint_write_tuple(&snap, entry->space_id, - entry->group_id, data, size) != 0) - goto fail; + struct index_read_view_iterator *it = + index_read_view_create_iterator(entry->rv, ITER_ALL, + NULL, 0); + if (it == NULL) + goto fail; + while (true) { + rc = index_read_view_iterator_next_raw(it, &data, + &size); + if (rc != 0 || data == NULL) + break; + rc = checkpoint_write_tuple(&snap, entry->space_id, + entry->group_id, + data, size); + if (rc != 0) + break; fiber_gc(); } + index_read_view_iterator_delete(it); if (rc != 0) goto fail; } @@ -990,7 +1001,7 @@ memtx_engine_backup(struct engine *engine, const struct vclock *vclock, struct memtx_join_entry { struct rlist in_ctx; uint32_t space_id; - struct snapshot_iterator *iterator; + struct index_read_view *rv; }; struct memtx_join_ctx { @@ -1028,8 +1039,8 @@ memtx_join_add_space(struct space *space, void *arg) return -1; } entry->space_id = space_id(space); - entry->iterator = index_create_snapshot_iterator(pk); - if (entry->iterator == NULL) { + entry->rv = index_create_read_view(pk); + if (entry->rv == NULL) { free(entry); return -1; } @@ -1084,16 +1095,26 @@ memtx_join_f(va_list ap) struct memtx_join_ctx *ctx = va_arg(ap, struct memtx_join_ctx *); struct memtx_join_entry *entry; rlist_foreach_entry(entry, &ctx->entries, in_ctx) { - struct snapshot_iterator *it = entry->iterator; + struct index_read_view_iterator *it = + index_read_view_create_iterator(entry->rv, ITER_ALL, + NULL, 0); + if (it == NULL) + return -1; int rc; uint32_t size; const char *data; - while ((rc = it->next(it, &data, &size)) == 0 && data != NULL) { - if (memtx_join_send_tuple(ctx->stream, entry->space_id, - data, size) != 0) - return -1; + while (true) { + rc = index_read_view_iterator_next_raw(it, &data, + &size); + if (rc != 0 || data == NULL) + break; + rc = memtx_join_send_tuple(ctx->stream, entry->space_id, + data, size); + if (rc != 0) + break; fiber_gc(); } + index_read_view_iterator_delete(it); if (rc != 0) return -1; } @@ -1129,7 +1150,7 @@ memtx_engine_complete_join(struct engine *engine, void *arg) struct memtx_join_ctx *ctx = (struct memtx_join_ctx *)arg; struct memtx_join_entry *entry, *next; rlist_foreach_entry_safe(entry, &ctx->entries, in_ctx, next) { - entry->iterator->free(entry->iterator); + index_read_view_delete(entry->rv); free(entry); } memtx_allocators_close_read_view(ctx->rv); diff --git a/src/box/memtx_hash.cc b/src/box/memtx_hash.cc index f38535d086528071d608a4ea81bfd4eab9b61f93..c6ab4756544446d31dcc93354e438c87a33dac5c 100644 --- a/src/box/memtx_hash.cc +++ b/src/box/memtx_hash.cc @@ -465,54 +465,66 @@ memtx_hash_index_create_iterator(struct index *base, enum iterator_type type, return (struct iterator *)it; } -struct hash_snapshot_iterator { - struct snapshot_iterator base; +/** Read view implementation. */ +struct hash_read_view { + /** Base class. */ + struct index_read_view base; + /** Read view index. Ref counter incremented. */ struct memtx_hash_index *index; + /** Light read view. */ struct light_index_view view; - struct light_index_iterator iterator; + /** Used for clarifying read view tuples. */ struct memtx_tx_snapshot_cleaner cleaner; }; -/** - * Destroy read view and free snapshot iterator. - * Virtual method of snapshot iterator. - * @sa index_vtab::create_snapshot_iterator. - */ +/** Read view iterator implementation. */ +struct hash_read_view_iterator { + /** Base class. */ + struct index_read_view_iterator base; + /** Read view. */ + struct hash_read_view *rv; + /** Light iterator. */ + struct light_index_iterator iterator; +}; + static void -hash_snapshot_iterator_free(struct snapshot_iterator *iterator) +hash_read_view_free(struct index_read_view *base) { - assert(iterator->free == hash_snapshot_iterator_free); - struct hash_snapshot_iterator *it = - (struct hash_snapshot_iterator *) iterator; - light_index_view_destroy(&it->view); - index_unref(&it->index->base); - memtx_tx_snapshot_cleaner_destroy(&it->cleaner); + struct hash_read_view *rv = (struct hash_read_view *)base; + light_index_view_destroy(&rv->view); + index_unref(&rv->index->base); + memtx_tx_snapshot_cleaner_destroy(&rv->cleaner); + TRASH(rv); + free(rv); +} + +static void +hash_read_view_iterator_free(struct index_read_view_iterator *iterator) +{ + assert(iterator->free == hash_read_view_iterator_free); + TRASH(iterator); free(iterator); } -/** - * Get next tuple from snapshot iterator. - * Virtual method of snapshot iterator. - * @sa index_vtab::create_snapshot_iterator. - */ +/** Implementation of next_raw index_read_view_iterator callback. */ static int -hash_snapshot_iterator_next(struct snapshot_iterator *iterator, - const char **data, uint32_t *size) +hash_read_view_iterator_next_raw(struct index_read_view_iterator *iterator, + const char **data, uint32_t *size) { - assert(iterator->free == hash_snapshot_iterator_free); - struct hash_snapshot_iterator *it = - (struct hash_snapshot_iterator *) iterator; + assert(iterator->free == hash_read_view_iterator_free); + struct hash_read_view_iterator *it = + (struct hash_read_view_iterator *)iterator; while (true) { struct tuple **res = light_index_view_iterator_get_and_next( - &it->view, &it->iterator); + &it->rv->view, &it->iterator); if (res == NULL) { *data = NULL; return 0; } struct tuple *tuple = *res; - tuple = memtx_tx_snapshot_clarify(&it->cleaner, tuple); + tuple = memtx_tx_snapshot_clarify(&it->rv->cleaner, tuple); if (tuple != NULL) { *data = tuple_data_range(tuple, size); @@ -524,33 +536,46 @@ hash_snapshot_iterator_next(struct snapshot_iterator *iterator, return 0; } -/** - * Create an ALL iterator with personal read view so further - * index modifications will not affect the iteration results. - * Must be destroyed by iterator->free after usage. - */ -static struct snapshot_iterator * -memtx_hash_index_create_snapshot_iterator(struct index *base) +/** Implementation of create_iterator index_read_view callback. */ +static struct index_read_view_iterator * +hash_read_view_create_iterator(struct index_read_view *base, + enum iterator_type type, + const char *key, uint32_t part_count) { - struct memtx_hash_index *index = (struct memtx_hash_index *)base; - struct hash_snapshot_iterator *it = (struct hash_snapshot_iterator *) - calloc(1, sizeof(*it)); - if (it == NULL) { - diag_set(OutOfMemory, sizeof(struct hash_snapshot_iterator), - "memtx_hash_index", "iterator"); - return NULL; - } + assert(type == ITER_ALL); + assert(key == NULL); + assert(part_count == 0); + (void)type; + (void)key; + (void)part_count; + struct hash_read_view *rv = (struct hash_read_view *)base; + struct hash_read_view_iterator *it = + (struct hash_read_view_iterator *)xmalloc(sizeof(*it)); + it->base.next_raw = hash_read_view_iterator_next_raw; + it->base.free = hash_read_view_iterator_free; + it->rv = rv; + light_index_view_iterator_begin(&rv->view, &it->iterator); + return (struct index_read_view_iterator *)it; +} +/** Implementation of create_read_view index callback. */ +static struct index_read_view * +memtx_hash_index_create_read_view(struct index *base) +{ + static const struct index_read_view_vtab vtab = { + .free = hash_read_view_free, + .create_iterator = hash_read_view_create_iterator, + }; + struct memtx_hash_index *index = (struct memtx_hash_index *)base; + struct hash_read_view *rv = + (struct hash_read_view *)xmalloc(sizeof(*rv)); struct space *space = space_cache_find(base->def->space_id); - memtx_tx_snapshot_cleaner_create(&it->cleaner, space); - - it->base.next = hash_snapshot_iterator_next; - it->base.free = hash_snapshot_iterator_free; - it->index = index; + memtx_tx_snapshot_cleaner_create(&rv->cleaner, space); + rv->base.vtab = &vtab; + rv->index = index; index_ref(base); - light_index_view_create(&it->view, &index->hash_table); - light_index_view_iterator_begin(&it->view, &it->iterator); - return (struct snapshot_iterator *) it; + light_index_view_create(&rv->view, &index->hash_table); + return (struct index_read_view *)rv; } static const struct index_vtab memtx_hash_index_vtab = { @@ -573,8 +598,7 @@ static const struct index_vtab memtx_hash_index_vtab = { /* .get = */ memtx_index_get, /* .replace = */ memtx_hash_index_replace, /* .create_iterator = */ memtx_hash_index_create_iterator, - /* .create_snapshot_iterator = */ - memtx_hash_index_create_snapshot_iterator, + /* .create_read_view = */ memtx_hash_index_create_read_view, /* .stat = */ generic_index_stat, /* .compact = */ generic_index_compact, /* .reset_stat = */ generic_index_reset_stat, diff --git a/src/box/memtx_rtree.cc b/src/box/memtx_rtree.cc index 77308aaec558ca63f8b36e5e2f6a6ee38dd9db63..1b52952306f06b5573d43c4d3a1046e0329d2e01 100644 --- a/src/box/memtx_rtree.cc +++ b/src/box/memtx_rtree.cc @@ -386,8 +386,7 @@ static const struct index_vtab memtx_rtree_index_vtab = { /* .get = */ memtx_index_get, /* .replace = */ memtx_rtree_index_replace, /* .create_iterator = */ memtx_rtree_index_create_iterator, - /* .create_snapshot_iterator = */ - generic_index_create_snapshot_iterator, + /* .create_read_view = */ generic_index_create_read_view, /* .stat = */ generic_index_stat, /* .compact = */ generic_index_compact, /* .reset_stat = */ generic_index_reset_stat, diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c index c329d5ace4134a6a039dfa04a17d0f70ae27d589..858b74defdbaddf3466d8a387792dfd18f1ff509 100644 --- a/src/box/memtx_space.c +++ b/src/box/memtx_space.c @@ -835,13 +835,6 @@ memtx_space_check_index_def(struct space *space, struct index_def *index_def) return 0; } -static struct snapshot_iterator * -sequence_data_index_create_snapshot_iterator(struct index *index) -{ - (void)index; - return sequence_data_iterator_create(); -} - static struct index * sequence_data_index_new(struct memtx_engine *memtx, struct index_def *def) { @@ -853,8 +846,7 @@ sequence_data_index_new(struct memtx_engine *memtx, struct index_def *def) static bool vtab_initialized; if (!vtab_initialized) { vtab = *index->vtab; - vtab.create_snapshot_iterator = - sequence_data_index_create_snapshot_iterator; + vtab.create_read_view = sequence_data_read_view_create; vtab_initialized = true; } diff --git a/src/box/memtx_tree.cc b/src/box/memtx_tree.cc index fcca15158366c46895f75e73f5890fdfef813e46..b66e7c340bb658f4340312139dc53b2b4b7f0523 100644 --- a/src/box/memtx_tree.cc +++ b/src/box/memtx_tree.cc @@ -1668,40 +1668,65 @@ memtx_tree_index_end_build(struct index *base) index->build_array_alloc_size = 0; } +/** Read view implementation. */ template <bool USE_HINT> -struct tree_snapshot_iterator { - struct snapshot_iterator base; +struct tree_read_view { + /** Base class. */ + struct index_read_view base; + /** Read view index. Ref counter incremented. */ struct memtx_tree_index<USE_HINT> *index; + /** BPS tree read view. */ memtx_tree_view_t<USE_HINT> tree_view; - memtx_tree_iterator_t<USE_HINT> tree_iterator; + /** Used for clarifying read view tuples. */ struct memtx_tx_snapshot_cleaner cleaner; }; +/** Read view iterator implementation. */ +template <bool USE_HINT> +struct tree_read_view_iterator { + /** Base class. */ + struct index_read_view_iterator base; + /** Read view. */ + struct tree_read_view<USE_HINT> *rv; + /** BPS tree iterator. */ + memtx_tree_iterator_t<USE_HINT> tree_iterator; +}; + +template <bool USE_HINT> +static void +tree_read_view_free(struct index_read_view *base) +{ + struct tree_read_view<USE_HINT> *rv = + (struct tree_read_view<USE_HINT> *)base; + memtx_tree_view_destroy(&rv->tree_view); + index_unref(&rv->index->base); + memtx_tx_snapshot_cleaner_destroy(&rv->cleaner); + TRASH(rv); + free(rv); +} + template <bool USE_HINT> static void -tree_snapshot_iterator_free(struct snapshot_iterator *iterator) +tree_read_view_iterator_free(struct index_read_view_iterator *iterator) { - assert(iterator->free == &tree_snapshot_iterator_free<USE_HINT>); - struct tree_snapshot_iterator<USE_HINT> *it = - (struct tree_snapshot_iterator<USE_HINT> *)iterator; - memtx_tree_view_destroy(&it->tree_view); - index_unref(&it->index->base); - memtx_tx_snapshot_cleaner_destroy(&it->cleaner); + assert(iterator->free == &tree_read_view_iterator_free<USE_HINT>); + TRASH(iterator); free(iterator); } +/** Implementation of next_raw index_read_view_iterator callback. */ template <bool USE_HINT> static int -tree_snapshot_iterator_next(struct snapshot_iterator *iterator, - const char **data, uint32_t *size) +tree_read_view_iterator_next_raw(struct index_read_view_iterator *iterator, + const char **data, uint32_t *size) { - assert(iterator->free == &tree_snapshot_iterator_free<USE_HINT>); - struct tree_snapshot_iterator<USE_HINT> *it = - (struct tree_snapshot_iterator<USE_HINT> *)iterator; + assert(iterator->free == &tree_read_view_iterator_free<USE_HINT>); + struct tree_read_view_iterator<USE_HINT> *it = + (struct tree_read_view_iterator<USE_HINT> *)iterator; while (true) { struct memtx_tree_data<USE_HINT> *res = - memtx_tree_view_iterator_get_elem(&it->tree_view, + memtx_tree_view_iterator_get_elem(&it->rv->tree_view, &it->tree_iterator); if (res == NULL) { @@ -1709,11 +1734,11 @@ tree_snapshot_iterator_next(struct snapshot_iterator *iterator, return 0; } - memtx_tree_view_iterator_next(&it->tree_view, + memtx_tree_view_iterator_next(&it->rv->tree_view, &it->tree_iterator); struct tuple *tuple = res->tuple; - tuple = memtx_tx_snapshot_clarify(&it->cleaner, tuple); + tuple = memtx_tx_snapshot_clarify(&it->rv->cleaner, tuple); if (tuple != NULL) { *data = tuple_data_range(tuple, size); @@ -1726,37 +1751,51 @@ tree_snapshot_iterator_next(struct snapshot_iterator *iterator, return 0; } -/** - * Create an ALL iterator with personal read view so further - * index modifications will not affect the iteration results. - * Must be destroyed by iterator->free after usage. - */ +/** Implementation of create_iterator index_read_view callback. */ template <bool USE_HINT> -static struct snapshot_iterator * -memtx_tree_index_create_snapshot_iterator(struct index *base) +static struct index_read_view_iterator * +tree_read_view_create_iterator(struct index_read_view *base, + enum iterator_type type, + const char *key, uint32_t part_count) { + assert(type == ITER_ALL); + assert(key == NULL); + assert(part_count == 0); + (void)type; + (void)key; + (void)part_count; + struct tree_read_view<USE_HINT> *rv = + (struct tree_read_view<USE_HINT> *)base; + struct tree_read_view_iterator<USE_HINT> *it = + (struct tree_read_view_iterator<USE_HINT> *) + xmalloc(sizeof(*it)); + it->base.free = tree_read_view_iterator_free<USE_HINT>; + it->base.next_raw = tree_read_view_iterator_next_raw<USE_HINT>; + it->rv = rv; + it->tree_iterator = memtx_tree_view_first(&rv->tree_view); + return (struct index_read_view_iterator *)it; +} + +/** Implementation of create_read_view index callback. */ +template <bool USE_HINT> +static struct index_read_view * +memtx_tree_index_create_read_view(struct index *base) +{ + static const struct index_read_view_vtab vtab = { + .free = tree_read_view_free<USE_HINT>, + .create_iterator = tree_read_view_create_iterator<USE_HINT>, + }; struct memtx_tree_index<USE_HINT> *index = (struct memtx_tree_index<USE_HINT> *)base; - struct tree_snapshot_iterator<USE_HINT> *it = - (struct tree_snapshot_iterator<USE_HINT> *) - calloc(1, sizeof(*it)); - if (it == NULL) { - diag_set(OutOfMemory, - sizeof(struct tree_snapshot_iterator<USE_HINT>), - "memtx_tree_index", "create_snapshot_iterator"); - return NULL; - } - + struct tree_read_view<USE_HINT> *rv = + (struct tree_read_view<USE_HINT> *)xmalloc(sizeof(*rv)); struct space *space = space_cache_find(base->def->space_id); - memtx_tx_snapshot_cleaner_create(&it->cleaner, space); - - it->base.free = tree_snapshot_iterator_free<USE_HINT>; - it->base.next = tree_snapshot_iterator_next<USE_HINT>; - it->index = index; + memtx_tx_snapshot_cleaner_create(&rv->cleaner, space); + rv->base.vtab = &vtab; + rv->index = index; index_ref(base); - memtx_tree_view_create(&it->tree_view, &index->tree); - it->tree_iterator = memtx_tree_view_first(&it->tree_view); - return (struct snapshot_iterator *) it; + memtx_tree_view_create(&rv->tree_view, &index->tree); + return (struct index_read_view *)rv; } /** @@ -1785,8 +1824,7 @@ static const struct index_vtab memtx_tree_disabled_index_vtab = { /* .get = */ generic_index_get, /* .replace = */ disabled_index_replace, /* .create_iterator = */ generic_index_create_iterator, - /* .create_snapshot_iterator = */ - generic_index_create_snapshot_iterator, + /* .create_read_view = */ generic_index_create_read_view, /* .stat = */ generic_index_stat, /* .compact = */ generic_index_compact, /* .reset_stat = */ generic_index_reset_stat, @@ -1849,8 +1887,8 @@ get_memtx_tree_index_vtab(void) memtx_tree_index_replace<USE_HINT>, /* .create_iterator = */ memtx_tree_index_create_iterator<USE_HINT>, - /* .create_snapshot_iterator = */ - memtx_tree_index_create_snapshot_iterator<USE_HINT>, + /* .create_read_view = */ + memtx_tree_index_create_read_view<USE_HINT>, /* .stat = */ generic_index_stat, /* .compact = */ generic_index_compact, /* .reset_stat = */ generic_index_reset_stat, diff --git a/src/box/sequence.c b/src/box/sequence.c index 1cd68980dcbb68fddcc2c7fde4c2fe5e35f379f5..f6eefd4bc1bafc571fc2bad412e0fd4e49d7b5f7 100644 --- a/src/box/sequence.c +++ b/src/box/sequence.c @@ -300,23 +300,34 @@ access_check_sequence(struct sequence *seq) return 0; } -struct sequence_data_iterator { - struct snapshot_iterator base; +/** Read view implementation. */ +struct sequence_data_read_view { + /** Base class. */ + struct index_read_view base; /** Frozen view of the data index. */ struct light_sequence_view view; +}; + +/** Read view iterator implementation. */ +struct sequence_data_iterator { + /** Base class. */ + struct index_read_view_iterator base; + /** Read view. */ + struct sequence_data_read_view *rv; /** Iterator over the data index. */ struct light_sequence_iterator iter; }; +/** Implementation of next_raw index_read_view_iterator callback. */ static int -sequence_data_iterator_next(struct snapshot_iterator *base, - const char **data, uint32_t *size) +sequence_data_iterator_next_raw(struct index_read_view_iterator *base, + const char **data, uint32_t *size) { struct sequence_data_iterator *iter = (struct sequence_data_iterator *)base; struct sequence_data *sd = light_sequence_view_iterator_get_and_next( - &iter->view, &iter->iter); + &iter->rv->view, &iter->iter); if (sd == NULL) { *data = NULL; return 0; @@ -338,26 +349,56 @@ sequence_data_iterator_next(struct snapshot_iterator *base, } static void -sequence_data_iterator_free(struct snapshot_iterator *base) +sequence_data_iterator_free(struct index_read_view_iterator *iter) { - struct sequence_data_iterator *iter = - (struct sequence_data_iterator *)base; - light_sequence_view_destroy(&iter->view); TRASH(iter); free(iter); } -struct snapshot_iterator * -sequence_data_iterator_create(void) +/** Implementation of create_iterator index_read_view callback. */ +static struct index_read_view_iterator * +sequence_data_iterator_create(struct index_read_view *base, + enum iterator_type type, + const char *key, uint32_t part_count) { - struct sequence_data_iterator *iter = xcalloc(1, sizeof(*iter)); - + assert(type == ITER_ALL); + assert(key == NULL); + assert(part_count == 0); + (void)type; + (void)key; + (void)part_count; + struct sequence_data_read_view *rv = + (struct sequence_data_read_view *)base; + struct sequence_data_iterator *iter = xmalloc(sizeof(*iter)); + iter->base.next_raw = sequence_data_iterator_next_raw; iter->base.free = sequence_data_iterator_free; - iter->base.next = sequence_data_iterator_next; + iter->rv = rv; + light_sequence_view_iterator_begin(&rv->view, &iter->iter); + return (struct index_read_view_iterator *)iter; +} + +static void +sequence_data_read_view_free(struct index_read_view *base) +{ + struct sequence_data_read_view *rv = + (struct sequence_data_read_view *)base; + light_sequence_view_destroy(&rv->view); + TRASH(rv); + free(rv); +} - light_sequence_view_create(&iter->view, &sequence_data_index); - light_sequence_view_iterator_begin(&iter->view, &iter->iter); - return &iter->base; +struct index_read_view * +sequence_data_read_view_create(struct index *index) +{ + (void)index; + static const struct index_read_view_vtab vtab = { + .free = sequence_data_read_view_free, + .create_iterator = sequence_data_iterator_create, + }; + struct sequence_data_read_view *rv = xmalloc(sizeof(*rv)); + rv->base.vtab = &vtab; + light_sequence_view_create(&rv->view, &sequence_data_index); + return (struct index_read_view *)rv; } int diff --git a/src/box/sequence.h b/src/box/sequence.h index 400bdc6f994828c5b28bef5fd8faa4538baeb200..e4968557ae52908ecef6477fa7907f8e0aaf844f 100644 --- a/src/box/sequence.h +++ b/src/box/sequence.h @@ -43,8 +43,8 @@ extern "C" { #endif /* defined(__cplusplus) */ -struct iterator; -struct Vdbe; +struct index; +struct index_read_view; /** Sequence metadata. */ struct sequence_def { @@ -158,14 +158,14 @@ int access_check_sequence(struct sequence *seq); /** - * Create an iterator over sequence data. + * Create a read view of sequence data. * - * The iterator creates a snapshot of sequence data and walks - * over it, i.e. updates done after the iterator was open are - * invisible. Used to make a snapshot of _sequence_data space. + * This function creates a snapshot of sequence data such that updates done + * after the read view was created are invisible. Used to make a snapshot of + * _sequence_data space. */ -struct snapshot_iterator * -sequence_data_iterator_create(void); +struct index_read_view * +sequence_data_read_view_create(struct index *index); /** * Get last element of given sequence. diff --git a/src/box/session_settings.c b/src/box/session_settings.c index c3233c95d80da5bbe6ef3f5f650343d0c0621d5a..aa79dbcec539cd356570e19966ef4c011d15ebfd 100644 --- a/src/box/session_settings.c +++ b/src/box/session_settings.c @@ -275,8 +275,7 @@ static const struct index_vtab session_settings_index_vtab = { /* .get = */ session_settings_index_get, /* .replace = */ generic_index_replace, /* .create_iterator = */ session_settings_index_create_iterator, - /* .create_snapshot_iterator = */ - generic_index_create_snapshot_iterator, + /* .create_read_view = */ generic_index_create_read_view, /* .stat = */ generic_index_stat, /* .compact = */ generic_index_compact, /* .reset_stat = */ generic_index_reset_stat, diff --git a/src/box/sysview.c b/src/box/sysview.c index 6f37e5fa968458361e8349219d568f34de0c49bf..6b04c45e579dd8ec226a888892b88661288cbaee 100644 --- a/src/box/sysview.c +++ b/src/box/sysview.c @@ -196,8 +196,7 @@ static const struct index_vtab sysview_index_vtab = { /* .get = */ sysview_index_get, /* .replace = */ generic_index_replace, /* .create_iterator = */ sysview_index_create_iterator, - /* .create_snapshot_iterator = */ - generic_index_create_snapshot_iterator, + /* .create_read_view = */ generic_index_create_read_view, /* .stat = */ generic_index_stat, /* .compact = */ generic_index_compact, /* .reset_stat = */ generic_index_reset_stat, diff --git a/src/box/vinyl.c b/src/box/vinyl.c index 403b7c49d0025d4f2a5adb98c3f0ed7633b369f4..89168a32d6c9303d954583e45dec0a04809476a9 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -4589,8 +4589,7 @@ static const struct index_vtab vinyl_index_vtab = { /* .get = */ vinyl_index_get, /* .replace = */ generic_index_replace, /* .create_iterator = */ vinyl_index_create_iterator, - /* .create_snapshot_iterator = */ - generic_index_create_snapshot_iterator, + /* .create_read_view = */ generic_index_create_read_view, /* .stat = */ vinyl_index_stat, /* .compact = */ vinyl_index_compact, /* .reset_stat = */ vinyl_index_reset_stat,