[patches] [PATCH 3/4] key_def: add key_def reference counter
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Mon Mar 12 00:53:35 MSK 2018
Vinyl alter can change key comparators, while they are being used
in workers. So the workers must be able to reference an old
key_def and an old cmp_def, while in TX thread alter creates new
ones.
Needed for #3229
Signed-off-by: Vladislav Shpilevoy <v.shpilevoy at tarantool.org>
---
src/box/alter.cc | 3 ++-
src/box/index_def.c | 14 ++++----------
src/box/key_def.cc | 16 ++++++++++++++--
src/box/key_def.h | 11 +++++++++++
src/box/schema.cc | 4 ++--
src/box/vinyl.c | 4 ++--
src/box/vy_index.c | 8 ++++----
7 files changed, 39 insertions(+), 21 deletions(-)
diff --git a/src/box/alter.cc b/src/box/alter.cc
index 7eec4786b..98c8bcdaf 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -328,7 +328,8 @@ index_def_new_from_tuple(struct tuple *tuple, struct space *space)
}
auto key_def_guard = make_scoped_guard([&] {
free(part_def);
- free(key_def);
+ if (key_def != NULL)
+ key_def_unref(key_def);
});
if (is_166plus) {
/* 1.6.6+ */
diff --git a/src/box/index_def.c b/src/box/index_def.c
index c503c7879..36eded106 100644
--- a/src/box/index_def.c
+++ b/src/box/index_def.c
@@ -141,16 +141,10 @@ void
index_def_delete(struct index_def *index_def)
{
free(index_def->name);
-
- if (index_def->key_def) {
- TRASH(index_def->key_def);
- free(index_def->key_def);
- }
-
- if (index_def->cmp_def) {
- TRASH(index_def->cmp_def);
- free(index_def->cmp_def);
- }
+ if (index_def->key_def)
+ key_def_unref(index_def->key_def);
+ if (index_def->cmp_def)
+ key_def_unref(index_def->cmp_def);
TRASH(index_def);
free(index_def);
diff --git a/src/box/key_def.cc b/src/box/key_def.cc
index 955349cf3..fd0857ec1 100644
--- a/src/box/key_def.cc
+++ b/src/box/key_def.cc
@@ -103,9 +103,18 @@ key_def_dup(const struct key_def *src)
return NULL;
}
memcpy(res, src, sz);
+ res->refs = 1;
return res;
}
+void
+key_def_unref(struct key_def *key_def)
+{
+ assert(key_def->refs > 0);
+ if (--key_def->refs == 0)
+ free(key_def);
+}
+
static void
key_def_set_cmp(struct key_def *def)
{
@@ -125,6 +134,7 @@ key_def_new(uint32_t part_count)
diag_set(OutOfMemory, sz, "malloc", "struct key_def");
return NULL;
}
+ key_def->refs = 1;
key_def->part_count = part_count;
key_def->unique_part_count = part_count;
return key_def;
@@ -145,7 +155,7 @@ key_def_new_with_parts(struct key_part_def *parts, uint32_t part_count)
if (coll == NULL) {
diag_set(ClientError, ER_WRONG_INDEX_OPTIONS,
i + 1, "collation was not found by ID");
- free(def);
+ key_def_unref(def);
return NULL;
}
}
@@ -187,7 +197,8 @@ box_key_def_new(uint32_t *fields, uint32_t *types, uint32_t part_count)
void
box_key_def_delete(box_key_def_t *key_def)
{
- free(key_def);
+ assert(key_def->refs == 1);
+ key_def_unref(key_def);
}
int
@@ -546,6 +557,7 @@ key_def_merge(const struct key_def *first, const struct key_def *second)
"new_def");
return NULL;
}
+ new_def->refs = 1;
new_def->part_count = new_part_count;
new_def->unique_part_count = new_part_count;
new_def->is_nullable = first->is_nullable || second->is_nullable;
diff --git a/src/box/key_def.h b/src/box/key_def.h
index 4726c38a2..93b5d30ab 100644
--- a/src/box/key_def.h
+++ b/src/box/key_def.h
@@ -135,6 +135,8 @@ struct key_def {
uint64_t column_mask;
/** The size of the 'parts' array. */
uint32_t part_count;
+ /** Reference counter. */
+ int refs;
/** Description of parts of a multipart index. */
struct key_part parts[];
};
@@ -149,6 +151,15 @@ struct key_def {
struct key_def *
key_def_dup(const struct key_def *src);
+static inline void
+key_def_ref(struct key_def *key_def)
+{
+ ++key_def->refs;
+}
+
+void
+key_def_unref(struct key_def *key_def);
+
/** \cond public */
typedef struct key_def box_key_def_t;
diff --git a/src/box/schema.cc b/src/box/schema.cc
index 2e8533b94..e614efb92 100644
--- a/src/box/schema.cc
+++ b/src/box/schema.cc
@@ -278,7 +278,7 @@ schema_init()
struct key_def *key_def = key_def_new(1); /* part count */
if (key_def == NULL)
diag_raise();
- auto key_def_guard = make_scoped_guard([&] { box_key_def_delete(key_def); });
+ auto key_def_guard = make_scoped_guard([&] { key_def_unref(key_def); });
key_def_set_part(key_def, 0 /* part no */, 0 /* field no */,
FIELD_TYPE_STRING, false, NULL);
@@ -329,7 +329,7 @@ schema_init()
sc_space_new(BOX_CLUSTER_ID, "_cluster", key_def, &on_replace_cluster,
NULL);
- free(key_def);
+ key_def_unref(key_def);
key_def = key_def_new(2); /* part count */
if (key_def == NULL)
diag_raise();
diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index 3467281a7..ba0688259 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -3097,7 +3097,7 @@ vy_join_cb(const struct vy_log_record *record, void *arg)
ctx->space_id = record->space_id;
ctx->index_id = record->index_id;
if (ctx->key_def != NULL)
- free(ctx->key_def);
+ key_def_unref(ctx->key_def);
ctx->key_def = key_def_new_with_parts(record->key_parts,
record->key_part_count);
if (ctx->key_def == NULL)
@@ -3234,7 +3234,7 @@ vinyl_engine_join(struct engine *engine, struct vclock *vclock,
/* Cleanup. */
if (ctx->key_def != NULL)
- free(ctx->key_def);
+ key_def_unref(ctx->key_def);
if (ctx->format != NULL)
tuple_format_unref(ctx->format);
if (ctx->upsert_format != NULL)
diff --git a/src/box/vy_index.c b/src/box/vy_index.c
index 68fccab52..9cf80a74a 100644
--- a/src/box/vy_index.c
+++ b/src/box/vy_index.c
@@ -257,9 +257,9 @@ fail_mem_format_with_colmask:
fail_upsert_format:
tuple_format_unref(index->disk_format);
fail_format:
- free(cmp_def);
+ key_def_unref(cmp_def);
fail_cmp_def:
- free(key_def);
+ key_def_unref(key_def);
fail_key_def:
free(index->tree);
fail_tree:
@@ -308,8 +308,8 @@ vy_index_delete(struct vy_index *index)
tuple_format_unref(index->disk_format);
tuple_format_unref(index->mem_format_with_colmask);
tuple_format_unref(index->upsert_format);
- free(index->cmp_def);
- free(index->key_def);
+ key_def_unref(index->cmp_def);
+ key_def_unref(index->key_def);
histogram_delete(index->run_hist);
vy_index_stat_destroy(&index->stat);
vy_cache_destroy(&index->cache);
--
2.14.3 (Apple Git-98)
More information about the Tarantool-patches
mailing list