From aee3723ff5aff93330e7caf6567714a4773e5a78 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja@tarantool.org> Date: Fri, 3 Apr 2015 16:43:55 +0300 Subject: [PATCH] memtx engine: move gradual index construction logic into memtx_engine.cc --- src/box/memtx_engine.cc | 165 +++++++++++++++++++++++++++++++++++++++ src/box/space.cc | 166 +--------------------------------------- src/box/space.h | 10 --- 3 files changed, 166 insertions(+), 175 deletions(-) diff --git a/src/box/memtx_engine.cc b/src/box/memtx_engine.cc index 7c13a9ef58..2147de5445 100644 --- a/src/box/memtx_engine.cc +++ b/src/box/memtx_engine.cc @@ -69,6 +69,171 @@ struct MemtxSpace: public Handler { } }; +/** + * A version of space_replace for a space which has + * no indexes (is not yet fully built). + */ +struct tuple * +space_replace_no_keys(struct space *space, struct tuple * /* old_tuple */, + struct tuple * /* new_tuple */, + enum dup_replace_mode /* mode */) +{ + Index *index = index_find(space, 0); + assert(index == NULL); /* not reached. */ + (void) index; + return NULL; /* replace found no old tuple */ +} + +/** + * A short-cut version of space_replace() used during bulk load + * from snapshot. + */ +struct tuple * +space_replace_build_next(struct space *space, struct tuple *old_tuple, + struct tuple *new_tuple, enum dup_replace_mode mode) +{ + assert(old_tuple == NULL && mode == DUP_INSERT); + (void) mode; + if (old_tuple) { + /* + * Called from txn_rollback() In practice + * is impossible: all possible checks for tuple + * validity are done before the space is changed, + * and WAL is off, so this part can't fail. + */ + panic("Failed to commit transaction when loading " + "from snapshot"); + } + space->index[0]->buildNext(new_tuple); + return NULL; /* replace found no old tuple */ +} + +/** + * A short-cut version of space_replace() used when loading + * data from XLOG files. + */ +struct tuple * +space_replace_primary_key(struct space *space, struct tuple *old_tuple, + struct tuple *new_tuple, enum dup_replace_mode mode) +{ + return space->index[0]->replace(old_tuple, new_tuple, mode); +} + +static struct tuple * +space_replace_all_keys(struct space *space, struct tuple *old_tuple, + struct tuple *new_tuple, enum dup_replace_mode mode) +{ + uint32_t i = 0; + try { + /* Update the primary key */ + Index *pk = index_find(space, 0); + assert(pk->key_def->is_unique); + /* + * If old_tuple is not NULL, the index + * has to find and delete it, or raise an + * error. + */ + old_tuple = pk->replace(old_tuple, new_tuple, mode); + + assert(old_tuple || new_tuple); + /* Update secondary keys. */ + for (i++; i < space->index_count; i++) { + Index *index = space->index[i]; + index->replace(old_tuple, new_tuple, DUP_INSERT); + } + return old_tuple; + } catch (Exception *e) { + /* Rollback all changes */ + for (; i > 0; i--) { + Index *index = space->index[i-1]; + index->replace(new_tuple, old_tuple, DUP_INSERT); + } + throw; + } + + assert(false); + return NULL; +} + +/** + * Secondary indexes are built in bulk after all data is + * recovered. This function enables secondary keys on a space. + * Data dictionary spaces are an exception, they are fully + * built right from the start. + */ +void +space_build_secondary_keys(struct space *space) +{ + if (space->index_id_max > 0) { + Index *pk = space->index[0]; + uint32_t n_tuples = pk->size(); + + if (n_tuples > 0) { + say_info("Building secondary indexes in space '%s'...", + space_name(space)); + } + + for (uint32_t j = 1; j < space->index_count; j++) + index_build(space->index[j], pk); + + if (n_tuples > 0) { + say_info("Space '%s': done", space_name(space)); + } + } + engine_recovery *r = &space->handler->recovery; + r->state = READY_ALL_KEYS; + r->recover = space_noop; /* mark the end of recover */ + r->replace = space_replace_all_keys; +} + +/** Build the primary key after loading data from a snapshot. */ +void +space_end_build_primary_key(struct space *space) +{ + space->index[0]->endBuild(); + engine_recovery *r = &space->handler->recovery; + r->state = READY_PRIMARY_KEY; + r->replace = space_replace_primary_key; + r->recover = space_build_secondary_keys; +} + +/** Prepare the primary key for bulk load (loading from + * a snapshot). + */ +void +space_begin_build_primary_key(struct space *space) +{ + space->index[0]->beginBuild(); + engine_recovery *r = &space->handler->recovery; + r->replace = space_replace_build_next; + r->recover = space_end_build_primary_key; +} + +/** + * Bring a space up to speed if its primary key is added during + * XLOG recovery. This is a recovery function called on + * spaces which had no primary key at the end of snapshot + * recovery, and got one only when reading an XLOG. + */ +void +space_build_primary_key(struct space *space) +{ + space_begin_build_primary_key(space); + space_end_build_primary_key(space); +} + +/** Bring a space up to speed once it's got a primary key. + * + * This is a recovery function used for all spaces added after the + * end of SNAP/XLOG recovery. + */ +void +space_build_all_keys(struct space *space) +{ + space_build_primary_key(space); + space_build_secondary_keys(space); +} + /** * This is a vtab with which a newly created space which has no * keys is primed. diff --git a/src/box/space.cc b/src/box/space.cc index ae197445b4..85777d1eb3 100644 --- a/src/box/space.cc +++ b/src/box/space.cc @@ -89,6 +89,7 @@ space_new(struct space_def *def, struct rlist *key_list) rlist_create(&space->on_replace); auto scoped_guard = make_scoped_guard([=] { + /** Ensure space_delete deletes all indexes. */ space_fill_index_map(space); space_delete(space); }); @@ -127,182 +128,17 @@ space_delete(struct space *space) free(space); } -/** - * A version of space_replace for a space which has - * no indexes (is not yet fully built). - */ -struct tuple * -space_replace_no_keys(struct space *space, struct tuple * /* old_tuple */, - struct tuple * /* new_tuple */, - enum dup_replace_mode /* mode */) -{ - Index *index = index_find(space, 0); - assert(index == NULL); /* not reached. */ - (void) index; - return NULL; /* replace found no old tuple */ -} - /** Do nothing if the space is already recovered. */ void space_noop(struct space * /* space */) {} -/** - * A short-cut version of space_replace() used during bulk load - * from snapshot. - */ -struct tuple * -space_replace_build_next(struct space *space, struct tuple *old_tuple, - struct tuple *new_tuple, enum dup_replace_mode mode) -{ - assert(old_tuple == NULL && mode == DUP_INSERT); - (void) mode; - if (old_tuple) { - /* - * Called from txn_rollback() In practice - * is impossible: all possible checks for tuple - * validity are done before the space is changed, - * and WAL is off, so this part can't fail. - */ - panic("Failed to commit transaction when loading " - "from snapshot"); - } - space->index[0]->buildNext(new_tuple); - return NULL; /* replace found no old tuple */ -} - -/** - * A short-cut version of space_replace() used when loading - * data from XLOG files. - */ -struct tuple * -space_replace_primary_key(struct space *space, struct tuple *old_tuple, - struct tuple *new_tuple, enum dup_replace_mode mode) -{ - return space->index[0]->replace(old_tuple, new_tuple, mode); -} - -static struct tuple * -space_replace_all_keys(struct space *space, struct tuple *old_tuple, - struct tuple *new_tuple, enum dup_replace_mode mode) -{ - uint32_t i = 0; - try { - /* Update the primary key */ - Index *pk = space->index[0]; - assert(pk->key_def->is_unique); - /* - * If old_tuple is not NULL, the index - * has to find and delete it, or raise an - * error. - */ - old_tuple = pk->replace(old_tuple, new_tuple, mode); - - assert(old_tuple || new_tuple); - /* Update secondary keys. */ - for (i++; i < space->index_count; i++) { - Index *index = space->index[i]; - index->replace(old_tuple, new_tuple, DUP_INSERT); - } - return old_tuple; - } catch (Exception *e) { - /* Rollback all changes */ - for (; i > 0; i--) { - Index *index = space->index[i-1]; - index->replace(new_tuple, old_tuple, DUP_INSERT); - } - throw; - } - - assert(false); - return NULL; -} - uint32_t space_size(struct space *space) { return space_index(space, 0)->size(); } -/** - * Secondary indexes are built in bulk after all data is - * recovered. This function enables secondary keys on a space. - * Data dictionary spaces are an exception, they are fully - * built right from the start. - */ -void -space_build_secondary_keys(struct space *space) -{ - if (space->index_id_max > 0) { - Index *pk = space->index[0]; - uint32_t n_tuples = pk->size(); - - if (n_tuples > 0) { - say_info("Building secondary indexes in space '%s'...", - space_name(space)); - } - - for (uint32_t j = 1; j < space->index_count; j++) - index_build(space->index[j], pk); - - if (n_tuples > 0) { - say_info("Space '%s': done", space_name(space)); - } - } - engine_recovery *r = &space->handler->recovery; - r->state = READY_ALL_KEYS; - r->recover = space_noop; /* mark the end of recover */ - r->replace = space_replace_all_keys; -} - -/** Build the primary key after loading data from a snapshot. */ -void -space_end_build_primary_key(struct space *space) -{ - space->index[0]->endBuild(); - engine_recovery *r = &space->handler->recovery; - r->state = READY_PRIMARY_KEY; - r->replace = space_replace_primary_key; - r->recover = space_build_secondary_keys; -} - -/** Prepare the primary key for bulk load (loading from - * a snapshot). - */ -void -space_begin_build_primary_key(struct space *space) -{ - space->index[0]->beginBuild(); - engine_recovery *r = &space->handler->recovery; - r->replace = space_replace_build_next; - r->recover = space_end_build_primary_key; -} - -/** - * Bring a space up to speed if its primary key is added during - * XLOG recovery. This is a recovery function called on - * spaces which had no primary key at the end of snapshot - * recovery, and got one only when reading an XLOG. - */ -void -space_build_primary_key(struct space *space) -{ - space_begin_build_primary_key(space); - space_end_build_primary_key(space); -} - -/** Bring a space up to speed once it's got a primary key. - * - * This is a recovery function used for all spaces added after the - * end of SNAP/XLOG recovery. - */ -void -space_build_all_keys(struct space *space) -{ - space_build_primary_key(space); - space_build_secondary_keys(space); -} - void space_validate_tuple(struct space *sp, struct tuple *new_tuple) { diff --git a/src/box/space.h b/src/box/space.h index 3d5190495c..dd513be625 100644 --- a/src/box/space.h +++ b/src/box/space.h @@ -195,16 +195,6 @@ space_replace(struct space *space, struct tuple *old_tuple, return space->handler->replace(space, old_tuple, new_tuple, mode); } -struct tuple * -space_replace_no_keys(struct space*, struct tuple*, struct tuple*, - enum dup_replace_mode); -struct tuple * -space_replace_primary_key(struct space*, struct tuple*, struct tuple*, - enum dup_replace_mode); - -void space_begin_build_primary_key(struct space *space); -void space_build_primary_key(struct space *space); -void space_build_all_keys(struct space *space); void space_noop(struct space *space); uint32_t -- GitLab