From 07b7062b4891151de09673aca21ba58c64fbf777 Mon Sep 17 00:00:00 2001 From: Aleksandr Lyapunov <alyapunov@tarantool.org> Date: Tue, 13 Apr 2021 13:44:58 +0300 Subject: [PATCH] box: add successor argument in replace function Add an argument which will receive successor of the inserted tuple. Part of #5628 --- src/box/index.cc | 8 +++++--- src/box/index.h | 22 +++++++++++++++++----- src/box/memtx_bitset.c | 5 ++++- src/box/memtx_engine.c | 2 +- src/box/memtx_hash.c | 5 ++++- src/box/memtx_rtree.c | 6 +++++- src/box/memtx_space.c | 17 +++++++++++------ src/box/memtx_tree.cc | 14 +++++++++++--- src/box/memtx_tx.c | 17 ++++++++++------- 9 files changed, 68 insertions(+), 28 deletions(-) diff --git a/src/box/index.cc b/src/box/index.cc index e0139f699b..1c25490909 100644 --- a/src/box/index.cc +++ b/src/box/index.cc @@ -695,12 +695,13 @@ generic_index_get(struct index *index, const char *key, int generic_index_replace(struct index *index, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result) + struct tuple **result, struct tuple **successor) { (void)old_tuple; (void)new_tuple; (void)mode; (void)result; + (void)successor; diag_set(UnsupportedIndexFeature, index->def, "replace()"); return -1; } @@ -764,7 +765,7 @@ generic_index_build_next(struct index *index, struct tuple *tuple) */ if (index_reserve(index, 0) != 0) return -1; - return index_replace(index, NULL, tuple, DUP_INSERT, &unused); + return index_replace(index, NULL, tuple, DUP_INSERT, &unused, &unused); } void @@ -782,11 +783,12 @@ disabled_index_build_next(struct index *index, struct tuple *tuple) int disabled_index_replace(struct index *index, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result) + struct tuple **result, struct tuple **successor) { (void) old_tuple; (void) new_tuple; (void) mode; (void) index; *result = NULL; + *successor = NULL; return 0; } diff --git a/src/box/index.h b/src/box/index.h index 2395654b29..146c911dad 100644 --- a/src/box/index.h +++ b/src/box/index.h @@ -413,9 +413,19 @@ struct index_vtab { const char *key, uint32_t part_count); int (*get)(struct index *index, const char *key, uint32_t part_count, struct tuple **result); + /** + * Main entrance point for changing data in index. Once built and + * before deletion this is the only way to insert, replace and delete + * data from the index. + * @param mode - @sa dup_replace_mode description + * @param result - here the replaced or deleted tuple is placed. + * @param successor - if the index supports ordering, then in case of + * insert (!) here the successor tuple is returned. In other words, + * here will be stored the tuple, before which new tuple is inserted. + */ int (*replace)(struct index *index, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result); + struct tuple **result, struct tuple **successor); /** Create an index iterator. */ struct iterator *(*create_iterator)(struct index *index, enum iterator_type type, @@ -646,7 +656,7 @@ index_filter_tuple(struct index *index, struct tuple *tuple) { static inline int index_replace(struct index *index, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result) + struct tuple **result, struct tuple **successor) { old_tuple = index_filter_tuple(index, old_tuple); new_tuple = index_filter_tuple(index, new_tuple); @@ -654,7 +664,8 @@ index_replace(struct index *index, struct tuple *old_tuple, *result = NULL; return 0; } - return index->vtab->replace(index, old_tuple, new_tuple, mode, result); + return index->vtab->replace(index, old_tuple, new_tuple, mode, + result, successor); } static inline struct iterator * @@ -732,7 +743,8 @@ ssize_t generic_index_count(struct index *, enum iterator_type, const char *, uint32_t); 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 **); + enum dup_replace_mode, + struct tuple **, struct tuple **); struct snapshot_iterator *generic_index_create_snapshot_iterator(struct index *); void generic_index_stat(struct index *, struct info_handler *); void generic_index_compact(struct index *); @@ -749,7 +761,7 @@ disabled_index_build_next(struct index *index, struct tuple *tuple); int disabled_index_replace(struct index *index, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result); + struct tuple **result, struct tuple **successor); #if defined(__cplusplus) } /* extern "C" */ diff --git a/src/box/memtx_bitset.c b/src/box/memtx_bitset.c index da79e36def..40fa456692 100644 --- a/src/box/memtx_bitset.c +++ b/src/box/memtx_bitset.c @@ -288,10 +288,13 @@ make_key(const char *field, uint32_t *key_len) static int memtx_bitset_index_replace(struct index *base, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result) + struct tuple **result, struct tuple **successor) { struct memtx_bitset_index *index = (struct memtx_bitset_index *)base; + /* BITSET index doesn't support ordering. */ + *successor = NULL; + assert(!base->def->opts.is_unique); assert(!base->def->key_def->is_multikey); assert(old_tuple != NULL || new_tuple != NULL); diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c index 8e0622f122..e076cd71d5 100644 --- a/src/box/memtx_engine.c +++ b/src/box/memtx_engine.c @@ -431,7 +431,7 @@ memtx_engine_rollback_statement(struct engine *engine, struct txn *txn, struct index *index = space->index[i]; /* Rollback must not fail. */ if (index_replace(index, stmt->new_tuple, stmt->old_tuple, - DUP_INSERT, &unused) != 0) { + DUP_INSERT, &unused, &unused) != 0) { diag_log(); unreachable(); panic("failed to rollback change"); diff --git a/src/box/memtx_hash.c b/src/box/memtx_hash.c index f424cda03e..b531fd1801 100644 --- a/src/box/memtx_hash.c +++ b/src/box/memtx_hash.c @@ -339,11 +339,14 @@ memtx_hash_index_get(struct index *base, const char *key, static int memtx_hash_index_replace(struct index *base, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result) + struct tuple **result, struct tuple **successor) { struct memtx_hash_index *index = (struct memtx_hash_index *)base; struct light_index_core *hash_table = &index->hash_table; + /* HASH index doesn't support ordering. */ + *successor = NULL; + if (new_tuple) { uint32_t h = tuple_hash(new_tuple, base->def->key_def); struct tuple *dup_tuple = NULL; diff --git a/src/box/memtx_rtree.c b/src/box/memtx_rtree.c index 83b9d3f2db..62a8d53dc7 100644 --- a/src/box/memtx_rtree.c +++ b/src/box/memtx_rtree.c @@ -254,10 +254,14 @@ memtx_rtree_index_get(struct index *base, const char *key, static int memtx_rtree_index_replace(struct index *base, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result) + struct tuple **result, struct tuple **successor) { (void)mode; struct memtx_rtree_index *index = (struct memtx_rtree_index *)base; + + /* RTREE index doesn't support ordering. */ + *successor = NULL; + struct rtree_rect rect; if (new_tuple) { if (extract_rectangle(&rect, new_tuple, base->def) != 0) diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c index be672282a9..22ba82b455 100644 --- a/src/box/memtx_space.c +++ b/src/box/memtx_space.c @@ -145,8 +145,9 @@ memtx_space_replace_primary_key(struct space *space, struct tuple *old_tuple, enum dup_replace_mode mode, struct tuple **result) { + struct tuple *successor; if (index_replace(space->index[0], old_tuple, - new_tuple, mode, &old_tuple) != 0) + new_tuple, mode, &old_tuple, &successor) != 0) return -1; memtx_space_update_bsize(space, old_tuple, new_tuple); if (new_tuple != NULL) @@ -285,7 +286,9 @@ memtx_space_replace_all_keys(struct space *space, struct tuple *old_tuple, * If old_tuple is not NULL, the index has to * find and delete it, or return an error. */ - if (index_replace(pk, old_tuple, new_tuple, mode, &old_tuple) != 0) + struct tuple *successor; + if (index_replace(pk, old_tuple, new_tuple, mode, + &old_tuple, &successor) != 0) return -1; assert(old_tuple || new_tuple); @@ -294,7 +297,7 @@ memtx_space_replace_all_keys(struct space *space, struct tuple *old_tuple, struct tuple *unused; struct index *index = space->index[i]; if (index_replace(index, old_tuple, new_tuple, - DUP_INSERT, &unused) != 0) + DUP_INSERT, &unused, &unused) != 0) goto rollback; } @@ -310,7 +313,7 @@ memtx_space_replace_all_keys(struct space *space, struct tuple *old_tuple, struct index *index = space->index[i - 1]; /* Rollback must not fail. */ if (index_replace(index, new_tuple, old_tuple, - DUP_INSERT, &unused) != 0) { + DUP_INSERT, &unused, &unused) != 0) { diag_log(); unreachable(); panic("failed to rollback change"); @@ -1015,8 +1018,9 @@ memtx_build_on_replace(struct trigger *trigger, void *event) enum dup_replace_mode mode = state->index->def->opts.is_unique ? DUP_INSERT : DUP_REPLACE_OR_INSERT; + struct tuple *successor; state->rc = index_replace(state->index, stmt->old_tuple, - stmt->new_tuple, mode, &delete); + stmt->new_tuple, mode, &delete, &successor); if (state->rc != 0) { diag_move(diag_get(), &state->diag); return 0; @@ -1106,8 +1110,9 @@ memtx_space_build_index(struct space *src_space, struct index *new_index, * @todo: better message if there is a duplicate. */ struct tuple *old_tuple; + struct tuple *successor; rc = index_replace(new_index, NULL, tuple, - DUP_INSERT, &old_tuple); + DUP_INSERT, &old_tuple, &successor); if (rc != 0) break; assert(old_tuple == NULL); /* Guaranteed by DUP_INSERT. */ diff --git a/src/box/memtx_tree.cc b/src/box/memtx_tree.cc index 514f36808b..4e9aefbbba 100644 --- a/src/box/memtx_tree.cc +++ b/src/box/memtx_tree.cc @@ -762,7 +762,7 @@ template <bool USE_HINT> static int memtx_tree_index_replace(struct index *base, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result) + struct tuple **result, struct tuple **successor) { struct memtx_tree_index<USE_HINT> *index = (struct memtx_tree_index<USE_HINT> *)base; @@ -806,6 +806,7 @@ memtx_tree_index_replace(struct index *base, struct tuple *old_tuple, } return -1; } + *successor = suc_data.tuple; if (dup_data.tuple != NULL) { *result = dup_data.tuple; return 0; @@ -966,10 +967,14 @@ memtx_tree_index_replace_multikey_rollback(struct memtx_tree_index<true> *index, static int memtx_tree_index_replace_multikey(struct index *base, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result) + struct tuple **result, struct tuple **successor) { struct memtx_tree_index<true> *index = (struct memtx_tree_index<true> *)base; + + /* MUTLIKEY doesn't support successor for now. */ + *successor = NULL; + struct key_def *cmp_def = memtx_tree_cmp_def(&index->tree); *result = NULL; if (new_tuple != NULL) { @@ -1088,8 +1093,11 @@ memtx_tree_func_index_replace_rollback(struct memtx_tree_index<true> *index, static int memtx_tree_func_index_replace(struct index *base, struct tuple *old_tuple, struct tuple *new_tuple, enum dup_replace_mode mode, - struct tuple **result) + struct tuple **result, struct tuple **successor) { + /* FUNC doesn't support successor for now. */ + *successor = NULL; + struct memtx_tree_index<true> *index = (struct memtx_tree_index<true> *)base; struct index_def *index_def = index->base.def; diff --git a/src/box/memtx_tx.c b/src/box/memtx_tx.c index 75d39c729b..68e173ca64 100644 --- a/src/box/memtx_tx.c +++ b/src/box/memtx_tx.c @@ -490,14 +490,15 @@ memtx_tx_story_full_unlink(struct memtx_story *story) */ if (story->del_psn > 0 && story->space != NULL) { struct index *index = story->space->index[i]; - struct tuple *unused; + struct tuple *removed, *unused; if (index_replace(index, story->tuple, NULL, - DUP_INSERT, &unused) != 0) { + DUP_INSERT, + &removed, &unused) != 0) { diag_log(); unreachable(); panic("failed to rollback change"); } - assert(story->tuple == unused); + assert(story->tuple == removed); /* * All tuples in pk are referenced. * Once removed it must be unreferenced. @@ -988,9 +989,10 @@ memtx_tx_history_add_stmt(struct txn_stmt *stmt, struct tuple *old_tuple, for (uint32_t i = 0; i < space->index_count; i++) { struct index *index = space->index[i]; struct tuple **replaced = &directly_replaced[i]; + struct tuple *successor; if (index_replace(index, NULL, new_tuple, DUP_REPLACE_OR_INSERT, - replaced) != 0) + replaced, &successor) != 0) { directly_replaced_count = i; goto fail; @@ -1101,7 +1103,7 @@ memtx_tx_history_add_stmt(struct txn_stmt *stmt, struct tuple *old_tuple, struct index *index = space->index[i]; struct tuple *unused; if (index_replace(index, new_tuple, directly_replaced[i], - DUP_INSERT, &unused) != 0) { + DUP_INSERT, &unused, &unused) != 0) { diag_log(); unreachable(); panic("failed to rollback change"); @@ -1131,7 +1133,8 @@ memtx_tx_history_rollback_stmt(struct txn_stmt *stmt) struct tuple *was = link->older_story == NULL ? NULL : link->older_story->tuple; if (index_replace(index, story->tuple, was, - DUP_INSERT, &unused) != 0) { + DUP_INSERT, + &unused, &unused) != 0) { diag_log(); unreachable(); panic("failed to rollback change"); @@ -1243,7 +1246,7 @@ memtx_tx_history_prepare_stmt(struct txn_stmt *stmt) struct tuple *unused; struct index *index = stmt->space->index[i]; if (index_replace(index, story->tuple, old_story->tuple, - DUP_INSERT, &unused) != 0) { + DUP_INSERT, &unused, &unused) != 0) { diag_log(); panic("failed to rollback change"); } -- GitLab