[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