[tarantool-patches] Re: [PATCH] Do not update schema_version on space:truncate().
Sergey Petrenko
sergepetrenko at tarantool.org
Fri Jul 6 18:15:17 MSK 2018
06.07.2018 17:29, Konstantin Osipov пишет:
> * Sergey Petrenko <sergepetrenko at 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)
More information about the Tarantool-patches
mailing list