From: Sergey Petrenko <sergepetrenko@tarantool.org> To: Konstantin Osipov <kostja@tarantool.org> Cc: tarantool-patches@freelists.org Subject: [tarantool-patches] Re: [PATCH] Do not update schema_version on space:truncate(). Date: Fri, 6 Jul 2018 18:15:17 +0300 [thread overview] Message-ID: <fa2c590c-ea9d-0c54-1194-5447f877baed@tarantool.org> (raw) In-Reply-To: <20180706142906.GA10648@chai> 06.07.2018 17:29, Konstantin Osipov пишет: > * Sergey Petrenko <sergepetrenko@tarantool.org> [18/07/06 17:27]: >> Will fix. I thought it'd be a good idea to only increment when we already >> know >> we won't be returning to the old state. >> So I should increase schema_version in UpdateSchemaVersion::alter() and >> decrease it in >> UpdateSchemaVersion::rollback() ? > Never decrement. Reloading a schema extra time won't break > anything. > > And what about creation/drop of a space? >> Move >> schema_version increment to on_replace_dd_space() > OK. > > > Fixed. See the new diff below: diff --git a/src/box/alter.cc b/src/box/alter.cc index 5dec2519d..ec3b91bff 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -1305,6 +1305,27 @@ RebuildIndex::~RebuildIndex() index_def_delete(new_index_def); } + +/** + * UpdateSchemaVersion - increment schema_version. Used on + * in alter_space_do(), i.e. when creating or dropping + * an index, altering a space. + */ +class UpdateSchemaVersion: public AlterSpaceOp +{ +public: + UpdateSchemaVersion(struct alter_space * alter) + :AlterSpaceOp(alter) {} + virtual void alter(struct alter_space *alter); +}; + +void +UpdateSchemaVersion::alter(struct alter_space *alter) +{ + (void)alter; + ++schema_version; +} + /* }}} */ /** @@ -1508,6 +1529,13 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event) * execution on a replica. */ (void) space_cache_replace(space); + /* + * Do not forget to update schema_version right after + * inserting the space to the space_cache, since no + * AlterSpaceOps are registered in case of space + * create. + */ + ++schema_version; /* * So may happen that until the DDL change record * is written to the WAL, the space is used for @@ -1552,6 +1580,12 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event) * execution on a replica. */ struct space *space = space_cache_delete(space_id(old_space)); + /* + * Do not forget to update schema_version right after + * deleting the space from the space_cache, since no + * AlterSpaceOps are registered in case of space drop. + */ + ++schema_version; struct trigger *on_commit = txn_alter_trigger_new(on_drop_space_commit, space); txn_on_commit(txn, on_commit); @@ -1603,6 +1637,8 @@ on_replace_dd_space(struct trigger * /* trigger */, void *event) def_guard.is_active = false; /* Create MoveIndex ops for all space indexes. */ alter_space_move_indexes(alter, 0, old_space->index_id_max + 1); + /* Remember to update schema_version. */ + (void) new UpdateSchemaVersion(alter); alter_space_do(txn, alter); alter_guard.is_active = false; } @@ -1800,6 +1836,8 @@ on_replace_dd_index(struct trigger * /* trigger */, void *event) * old space. */ alter_space_move_indexes(alter, iid + 1, old_space->index_id_max + 1); + /* Add an op to update schema_version on commit. */ + (void) new UpdateSchemaVersion(alter); alter_space_do(txn, alter); scoped_guard.is_active = false; } diff --git a/src/box/index.cc b/src/box/index.cc index 69fc76116..30cc0a684 100644 --- a/src/box/index.cc +++ b/src/box/index.cc @@ -433,7 +433,7 @@ iterator_create(struct iterator *it, struct index *index) { it->next = NULL; it->free = NULL; - it->schema_version = schema_version; + it->schema_state = schema_state; it->space_id = index->def->space_id; it->index_id = index->def->iid; it->index = index; @@ -443,15 +443,15 @@ int iterator_next(struct iterator *it, struct tuple **ret) { assert(it->next != NULL); - if (unlikely(it->schema_version != schema_version)) { + if (unlikely(it->schema_state != schema_state)) { struct space *space = space_by_id(it->space_id); if (space == NULL) goto invalidate; struct index *index = space_index(space, it->index_id); if (index != it->index || - index->schema_version > it->schema_version) + index->schema_state > it->schema_state) goto invalidate; - it->schema_version = schema_version; + it->schema_state = schema_state; } return it->next(it, ret); @@ -478,7 +478,7 @@ index_create(struct index *index, struct engine *engine, index->vtab = vtab; index->engine = engine; index->def = def; - index->schema_version = schema_version; + index->schema_state = schema_state; return 0; } diff --git a/src/box/index.h b/src/box/index.h index 3c478c6d6..cc9de57a5 100644 --- a/src/box/index.h +++ b/src/box/index.h @@ -233,8 +233,8 @@ struct iterator { int (*next)(struct iterator *it, struct tuple **ret); /** Destroy the iterator. */ void (*free)(struct iterator *); - /** Schema version at the time of the last index lookup. */ - uint32_t schema_version; + /** Schema state at the time of the last index lookup. */ + uint32_t schema_state; /** ID of the space the iterator is for. */ uint32_t space_id; /** ID of the index the iterator is for. */ @@ -242,7 +242,7 @@ struct iterator { /** * Pointer to the index the iterator is for. * Guaranteed to be valid only if the schema - * version has not changed since the last lookup. + * state has not changed since the last lookup. */ struct index *index; }; @@ -408,8 +408,8 @@ struct index { struct engine *engine; /* Description of a possibly multipart key. */ struct index_def *def; - /* Schema version at the time of construction. */ - uint32_t schema_version; + /* Schema state at the time of construction. */ + uint32_t schema_state; }; /** diff --git a/src/box/schema.cc b/src/box/schema.cc index 1b96f978c..02b4f54ee 100644 --- a/src/box/schema.cc +++ b/src/box/schema.cc @@ -58,7 +58,15 @@ static struct mh_i32ptr_t *spaces; static struct mh_i32ptr_t *funcs; static struct mh_strnptr_t *funcs_by_name; static struct mh_i32ptr_t *sequences; +/** Public change counter. On its update clients need to fetch + * new space data from the instance. */ uint32_t schema_version = 0; +/** + * Internal change counter. Grows faster, than the public one, + * because we need to remember when to update pointers to already + * non-existent space objects on space:truncate() operation. + */ +uint32_t schema_state = 0; uint32_t dd_version_id = version_id(1, 6, 4); struct rlist on_alter_space = RLIST_HEAD_INITIALIZER(on_alter_space); @@ -157,7 +165,7 @@ space_cache_delete(uint32_t id) assert(k != mh_end(spaces)); struct space *space = (struct space *)mh_i32ptr_node(spaces, k)->val; mh_i32ptr_del(spaces, k, NULL); - schema_version++; + schema_state++; return space; } @@ -175,7 +183,7 @@ space_cache_replace(struct space *space) panic_syserror("Out of memory for the data " "dictionary cache."); } - schema_version++; + schema_state++; return p_old ? (struct space *) p_old->val : NULL; } diff --git a/src/box/schema.h b/src/box/schema.h index 56f39b3fe..dcc764aef 100644 --- a/src/box/schema.h +++ b/src/box/schema.h @@ -42,6 +42,7 @@ extern "C" { #endif /* defined(__cplusplus) */ extern uint32_t schema_version; +extern uint32_t schema_state; /** * Persistent version of the schema, stored in _schema["version"]. @@ -68,14 +69,14 @@ box_schema_version(); static inline struct space * space_cache_find(uint32_t id) { - static uint32_t prev_schema_version = 0; + static uint32_t prev_schema_state = 0; static struct space *space = NULL; - if (prev_schema_version != schema_version) + if (prev_schema_state != schema_state) space = NULL; if (space && space->def->id == id) return space; if ((space = space_by_id(id))) { - prev_schema_version = schema_version; + prev_schema_state = schema_state; return space; } diag_set(ClientError, ER_NO_SUCH_SPACE, int2str(id)); diff --git a/src/box/sysview_index.c b/src/box/sysview_index.c index 0bec30282..6a2667db2 100644 --- a/src/box/sysview_index.c +++ b/src/box/sysview_index.c @@ -66,7 +66,7 @@ sysview_iterator_next(struct iterator *iterator, struct tuple **ret) assert(iterator->free == sysview_iterator_free); struct sysview_iterator *it = sysview_iterator(iterator); *ret = NULL; - if (it->source->schema_version != schema_version) + if (it->source->schema_state != schema_state) return 0; /* invalidate iterator */ struct sysview_index *index = (struct sysview_index *)iterator->index; int rc; diff --git a/src/box/vy_index.c b/src/box/vy_index.c index d9160041b..1d92bebd3 100644 --- a/src/box/vy_index.c +++ b/src/box/vy_index.c @@ -217,7 +217,7 @@ vy_index_new(struct vy_index_env *index_env, struct vy_cache_env *cache_env, index->mem = vy_mem_new(mem_env, *index->env->p_generation, cmp_def, format, index->mem_format_with_colmask, - index->upsert_format, schema_version); + index->upsert_format, schema_state); if (index->mem == NULL) goto fail_mem; @@ -764,7 +764,7 @@ vy_index_rotate_mem(struct vy_index *index) mem = vy_mem_new(index->mem->env, *index->env->p_generation, index->cmp_def, index->mem_format, index->mem_format_with_colmask, - index->upsert_format, schema_version); + index->upsert_format, schema_state); if (mem == NULL) return -1; diff --git a/src/box/vy_mem.c b/src/box/vy_mem.c index 629634bbf..d7f62fbba 100644 --- a/src/box/vy_mem.c +++ b/src/box/vy_mem.c @@ -98,7 +98,7 @@ struct vy_mem * vy_mem_new(struct vy_mem_env *env, int64_t generation, const struct key_def *cmp_def, struct tuple_format *format, struct tuple_format *format_with_colmask, - struct tuple_format *upsert_format, uint32_t schema_version) + struct tuple_format *upsert_format, uint32_t schema_state) { struct vy_mem *index = calloc(1, sizeof(*index)); if (!index) { @@ -111,7 +111,7 @@ vy_mem_new(struct vy_mem_env *env, int64_t generation, index->max_lsn = -1; index->cmp_def = cmp_def; index->generation = generation; - index->schema_version = schema_version; + index->schema_state = schema_state; index->format = format; tuple_format_ref(format); index->format_with_colmask = format_with_colmask; diff --git a/src/box/vy_mem.h b/src/box/vy_mem.h index d60032219..6f4af3c8d 100644 --- a/src/box/vy_mem.h +++ b/src/box/vy_mem.h @@ -174,8 +174,8 @@ struct vy_mem { const struct key_def *cmp_def; /** version is initially 0 and is incremented on every write */ uint32_t version; - /** Schema version at the time of creation. */ - uint32_t schema_version; + /** Schema state at the time of creation. */ + uint32_t schema_state; /** * Generation of statements stored in the tree. * Used as lsregion allocator identifier. @@ -250,7 +250,7 @@ vy_mem_wait_pinned(struct vy_mem *mem) * @param format_with_colmask Format for tuples, which have * column mask. * @param upsert_format Format for UPSERT tuples. - * @param schema_version Schema version. + * @param schema_state Schema state. * @retval new vy_mem instance on success. * @retval NULL on error, check diag. */ @@ -258,7 +258,7 @@ struct vy_mem * vy_mem_new(struct vy_mem_env *env, int64_t generation, const struct key_def *cmp_def, struct tuple_format *format, struct tuple_format *format_with_colmask, - struct tuple_format *upsert_format, uint32_t schema_version); + struct tuple_format *upsert_format, uint32_t schema_state); /** * Delete in-memory level. diff --git a/src/box/vy_tx.c b/src/box/vy_tx.c index 01130020b..019320ca4 100644 --- a/src/box/vy_tx.c +++ b/src/box/vy_tx.c @@ -45,7 +45,7 @@ #include "iproto_constants.h" #include "iterator_type.h" #include "salad/stailq.h" -#include "schema.h" /* schema_version */ +#include "schema.h" /* schema_state */ #include "trigger.h" #include "trivia/util.h" #include "tuple.h" @@ -414,11 +414,11 @@ vy_tx_write_prepare(struct txv *v) * In this case we need to dump the tree as is in order to * guarantee dump consistency. * - * - Schema version has increased after the tree was created. + * - Schema state has increased after the tree was created. * We have to seal the tree, because we don't support mixing * statements of different formats in the same tree. */ - if (unlikely(index->mem->schema_version != schema_version || + if (unlikely(index->mem->schema_state != schema_state || index->mem->generation != *index->env->p_generation)) { if (vy_index_rotate_mem(index) != 0) return -1; diff --git a/test/engine/ddl.result b/test/engine/ddl.result index c3cb1efc2..b6b6faf5b 100644 --- a/test/engine/ddl.result +++ b/test/engine/ddl.result @@ -388,6 +388,63 @@ s:drop() --- ... -- +-- gh-3414: do not increase schema_version on space:truncate() +-- +-- update schema_version on space.create() +sch_ver = box.internal.schema_version +--- +... +v = sch_ver() +--- +... +s = box.schema.create_space('test') +--- +... +v + 1 == sch_ver() +--- +- true +... +-- update schema_version on space:create_index() +prim = s:create_index("primary") +--- +... +v + 2 == sch_ver() +--- +- true +... +-- do not change schema_version on space.truncate() +s:truncate() +--- +... +v + 2 == sch_ver() +--- +- true +... +-- update schema_version on index.alter() +prim:alter{name="new_primary"} +--- +... +v + 3 == sch_ver() +--- +- true +... +-- update schema_version on index.drop() +box.schema.index.drop(s.id, 0) +--- +... +v + 4 == sch_ver() +--- +- true +... +-- update schema_version on space.drop() +s:drop() +--- +... +v + 5 == sch_ver() +--- +- true +... +-- -- gh-3229: update optionality if a space format is changed too, -- not only when indexes are updated. -- diff --git a/test/engine/ddl.test.lua b/test/engine/ddl.test.lua index 25381a3c8..e73c7dbb0 100644 --- a/test/engine/ddl.test.lua +++ b/test/engine/ddl.test.lua @@ -137,6 +137,30 @@ pk = s:create_index('pk') pk.parts[1].type s:drop() +-- +-- gh-3414: do not increase schema_version on space:truncate() +-- +-- update schema_version on space.create() +sch_ver = box.internal.schema_version +v = sch_ver() +s = box.schema.create_space('test') +v + 1 == sch_ver() +-- update schema_version on space:create_index() +prim = s:create_index("primary") +v + 2 == sch_ver() +-- do not change schema_version on space.truncate() +s:truncate() +v + 2 == sch_ver() +-- update schema_version on index.alter() +prim:alter{name="new_primary"} +v + 3 == sch_ver() +-- update schema_version on index.drop() +box.schema.index.drop(s.id, 0) +v + 4 == sch_ver() +-- update schema_version on space.drop() +s:drop() +v + 5 == sch_ver() + -- -- gh-3229: update optionality if a space format is changed too, -- not only when indexes are updated. diff --git a/test/unit/vy_point_lookup.c b/test/unit/vy_point_lookup.c index 963329c9f..914833e02 100644 --- a/test/unit/vy_point_lookup.c +++ b/test/unit/vy_point_lookup.c @@ -12,6 +12,7 @@ #include "identifier.h" uint32_t schema_version; +uint32_t schema_state; static int write_run(struct vy_run *run, const char *dir_name, -- 2.15.2 (Apple Git-101.1)
prev parent reply other threads:[~2018-07-06 15:15 UTC|newest] Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-07-06 11:46 [tarantool-patches] " Serge Petrenko 2018-07-06 14:07 ` [tarantool-patches] " Konstantin Osipov 2018-07-06 14:24 ` Sergey Petrenko 2018-07-06 14:29 ` Konstantin Osipov 2018-07-06 15:15 ` Sergey Petrenko [this message]
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=fa2c590c-ea9d-0c54-1194-5447f877baed@tarantool.org \ --to=sergepetrenko@tarantool.org \ --cc=kostja@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='[tarantool-patches] Re: [PATCH] Do not update schema_version on space:truncate().' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox