[Tarantool-patches] [PATCH 2/4] tuple: use getters and setters

Ilya Kosarev i.kosarev at tarantool.org
Tue Jan 19 02:50:31 MSK 2021


This patch introduces getters and setters for tuple fields bsize,
data_offset and is_dirty. They now will be used instead of direct
field access. It allows struct tuple reassembling to make it's size
variable.

Prerequisites #5385
---
 perf/tuple.cc                |  8 +++---
 src/box/lua/merger.c         |  2 +-
 src/box/memtx_engine.c       | 11 ++++---
 src/box/memtx_tx.c           | 22 +++++++-------
 src/box/memtx_tx.h           |  2 +-
 src/box/sql.c                |  2 +-
 src/box/tuple.c              | 10 +++----
 src/box/tuple.h              | 56 ++++++++++++++++++++++++++++++++----
 src/box/tuple_compare.cc     |  2 +-
 src/box/tuple_extract_key.cc |  4 +--
 src/box/tuple_format.c       |  2 +-
 src/box/vy_stmt.c            | 22 ++++++++------
 src/box/vy_stmt.h            |  2 +-
 13 files changed, 96 insertions(+), 49 deletions(-)

diff --git a/perf/tuple.cc b/perf/tuple.cc
index 4d50a49b6..da45ec23d 100644
--- a/perf/tuple.cc
+++ b/perf/tuple.cc
@@ -34,9 +34,9 @@ access_fields(struct tuple *tuple)
 	int sum = 0;
 	sum += tuple->refs;
 	sum += tuple->format_id;
-	sum += tuple->bsize;
-	sum += tuple->data_offset;
-	sum += tuple->is_dirty;
+	sum += tuple_bsize(tuple);
+	sum += tuple_data_offset(tuple);
+	sum += tuple_is_dirty(tuple);
 	return sum;
 }
 
@@ -162,7 +162,7 @@ int main(int argc, char **argv)
 	for (size_t i = 0; i < amount; i++) {
 		struct tuple *tuple = tuple_new(format, start[i], end[i]);
 		tuple_ref(tuple);
-		if (tuple->bsize <= UINT8_MAX)
+		if (tuple_bsize(tuple) <= UINT8_MAX)
 			tiny_tuples.push_back(tuple);
 		else
 			big_tuples.push_back(tuple);
diff --git a/src/box/lua/merger.c b/src/box/lua/merger.c
index 89bdfffa6..91a77b2ae 100644
--- a/src/box/lua/merger.c
+++ b/src/box/lua/merger.c
@@ -1115,7 +1115,7 @@ encode_result_buffer(struct lua_State *L, struct merge_source *source,
 	while (result_len < limit && (rc =
 	       merge_source_next(source, NULL, &tuple)) == 0 &&
 	       tuple != NULL) {
-		uint32_t bsize = tuple->bsize;
+		uint32_t bsize = tuple_bsize(tuple);
 		ibuf_reserve(output_buffer, bsize);
 		memcpy(output_buffer->wpos, tuple_data(tuple), bsize);
 		output_buffer->wpos += bsize;
diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c
index f79f14b4f..c37b35586 100644
--- a/src/box/memtx_engine.c
+++ b/src/box/memtx_engine.c
@@ -1230,7 +1230,7 @@ memtx_tuple_new(struct tuple_format *format, const char *data, const char *end)
 	 */
 	uint32_t data_offset = sizeof(struct tuple) + field_map_size;
 	if (data_offset > INT16_MAX) {
-		/** tuple->data_offset is 15 bits */
+		/** tuple data_offset can't be more than 15 bits */
 		diag_set(ClientError, ER_TUPLE_METADATA_IS_TOO_BIG,
 			 data_offset);
 		goto end;
@@ -1263,13 +1263,12 @@ memtx_tuple_new(struct tuple_format *format, const char *data, const char *end)
 	tuple = &memtx_tuple->base;
 	tuple->refs = 0;
 	memtx_tuple->version = memtx->snapshot_version;
-	assert(tuple_len <= UINT32_MAX); /* bsize is UINT32_MAX */
-	tuple->bsize = tuple_len;
+	tuple_set_bsize(tuple, tuple_len);
 	tuple->format_id = tuple_format_id(format);
 	tuple_format_ref(format);
-	tuple->data_offset = data_offset;
-	tuple->is_dirty = false;
-	char *raw = (char *) tuple + tuple->data_offset;
+	tuple_set_data_offset(tuple, data_offset);
+	tuple_set_dirty_bit(tuple, false);
+	char *raw = (char *) tuple + data_offset;
 	field_map_build(&builder, raw - field_map_size);
 	memcpy(raw, data, tuple_len);
 	say_debug("%s(%zu) = %p", __func__, tuple_len, memtx_tuple);
diff --git a/src/box/memtx_tx.c b/src/box/memtx_tx.c
index 412099b94..1ef96dc96 100644
--- a/src/box/memtx_tx.c
+++ b/src/box/memtx_tx.c
@@ -194,7 +194,7 @@ memtx_tx_story_new(struct space *space, struct tuple *tuple)
 	/* Free some memory. */
 	for (size_t i = 0; i < TX_MANAGER_GC_STEPS_SIZE; i++)
 		memtx_tx_story_gc_step();
-	assert(!tuple->is_dirty);
+	assert(!tuple_is_dirty(tuple));
 	uint32_t index_count = space->index_count;
 	assert(index_count < BOX_INDEX_MAX);
 	struct mempool *pool = &txm.memtx_tx_story_pool[index_count];
@@ -218,7 +218,7 @@ memtx_tx_story_new(struct space *space, struct tuple *tuple)
 			 "mh_history_node");
 		return NULL;
 	}
-	tuple->is_dirty = true;
+	tuple_set_dirty_bit(tuple, true);
 	tuple_ref(tuple);
 
 	story->space = space;
@@ -298,7 +298,7 @@ memtx_tx_story_delete_del_stmt(struct memtx_story *story)
 static struct memtx_story *
 memtx_tx_story_get(struct tuple *tuple)
 {
-	assert(tuple->is_dirty);
+	assert(tuple_is_dirty(tuple));
 
 	mh_int_t pos = mh_history_find(txm.history, tuple, 0);
 	assert(pos != mh_end(txm.history));
@@ -348,7 +348,7 @@ memtx_tx_story_link_tuple(struct memtx_story *story,
 	assert(link->older.tuple == NULL);
 	if (older_tuple == NULL)
 		return;
-	if (older_tuple->is_dirty) {
+	if (tuple_is_dirty(older_tuple)) {
 		memtx_tx_story_link_story(story,
 					  memtx_tx_story_get(older_tuple),
 					  index);
@@ -586,7 +586,7 @@ memtx_tx_story_find_visible_tuple(struct memtx_story *story,
 			/* The tuple is so old that we don't know its story. */
 			*visible_replaced = story->link[index].older.tuple;
 			assert(*visible_replaced == NULL ||
-			       !(*visible_replaced)->is_dirty);
+			       !tuple_is_dirty(*visible_replaced));
 			break;
 		}
 		story = story->link[index].older.story;
@@ -704,7 +704,7 @@ memtx_tx_history_add_stmt(struct txn_stmt *stmt, struct tuple *old_tuple,
 		del_tuple = old_tuple;
 	}
 	if (del_tuple != NULL && del_story == NULL) {
-		if (del_tuple->is_dirty) {
+		if (tuple_is_dirty(del_tuple)) {
 			del_story = memtx_tx_story_get(del_tuple);
 		} else {
 			del_story = memtx_tx_story_new_del_stmt(del_tuple,
@@ -1030,14 +1030,14 @@ memtx_tx_history_commit_stmt(struct txn_stmt *stmt)
 	size_t res = 0;
 	if (stmt->add_story != NULL) {
 		assert(stmt->add_story->add_stmt == stmt);
-		res += stmt->add_story->tuple->bsize;
+		res += tuple_bsize(stmt->add_story->tuple);
 		stmt->add_story->add_stmt = NULL;
 		stmt->add_story = NULL;
 	}
 	if (stmt->del_story != NULL) {
 		assert(stmt->del_story->del_stmt == stmt);
 		assert(stmt->next_in_del_list == NULL);
-		res -= stmt->del_story->tuple->bsize;
+		res -= tuple_bsize(stmt->del_story->tuple);
 		stmt->del_story->del_stmt = NULL;
 		stmt->del_story = NULL;
 	}
@@ -1049,7 +1049,7 @@ memtx_tx_tuple_clarify_slow(struct txn *txn, struct space *space,
 			    struct tuple *tuple, uint32_t index,
 			    uint32_t mk_index, bool is_prepared_ok)
 {
-	assert(tuple->is_dirty);
+	assert(tuple_is_dirty(tuple));
 	struct memtx_story *story = memtx_tx_story_get(tuple);
 	bool own_change = false;
 	struct tuple *result = NULL;
@@ -1104,7 +1104,7 @@ memtx_tx_story_delete(struct memtx_story *story)
 	assert(pos != mh_end(txm.history));
 	mh_history_del(txm.history, pos, 0);
 
-	story->tuple->is_dirty = false;
+	tuple_set_dirty_bit(story->tuple, false);
 	tuple_unref(story->tuple);
 
 #ifndef NDEBUG
@@ -1133,7 +1133,7 @@ memtx_tx_track_read(struct txn *txn, struct space *space, struct tuple *tuple)
 	struct memtx_story *story;
 	struct tx_read_tracker *tracker = NULL;
 
-	if (!tuple->is_dirty) {
+	if (!tuple_is_dirty(tuple)) {
 		story = memtx_tx_story_new(space, tuple);
 		if (story == NULL)
 			return -1;
diff --git a/src/box/memtx_tx.h b/src/box/memtx_tx.h
index 25a203880..ae41d4501 100644
--- a/src/box/memtx_tx.h
+++ b/src/box/memtx_tx.h
@@ -302,7 +302,7 @@ memtx_tx_tuple_clarify(struct txn *txn, struct space *space,
 {
 	if (!memtx_tx_manager_use_mvcc_engine)
 		return tuple;
-	if (!tuple->is_dirty) {
+	if (!tuple_is_dirty(tuple)) {
 		memtx_tx_track_read(txn, space, tuple);
 		return tuple;
 	}
diff --git a/src/box/sql.c b/src/box/sql.c
index 3d968e56a..59e1e88fc 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1312,5 +1312,5 @@ vdbe_field_ref_prepare_tuple(struct vdbe_field_ref *field_ref,
 			     struct tuple *tuple)
 {
 	vdbe_field_ref_create(field_ref, tuple, tuple_data(tuple),
-			      tuple->bsize);
+			      tuple_bsize(tuple));
 }
diff --git a/src/box/tuple.c b/src/box/tuple.c
index c2023e4e8..c73ad4566 100644
--- a/src/box/tuple.c
+++ b/src/box/tuple.c
@@ -85,7 +85,7 @@ runtime_tuple_new(struct tuple_format *format, const char *data, const char *end
 	uint32_t field_map_size = field_map_build_size(&builder);
 	uint32_t data_offset = sizeof(struct tuple) + field_map_size;
 	if (data_offset > INT16_MAX) {
-		/** tuple->data_offset is 15 bits */
+		/** tuple data_offset can't be more than 15 bits */
 		diag_set(ClientError, ER_TUPLE_METADATA_IS_TOO_BIG,
 			 data_offset);
 		goto end;
@@ -101,11 +101,11 @@ runtime_tuple_new(struct tuple_format *format, const char *data, const char *end
 	}
 
 	tuple->refs = 0;
-	tuple->bsize = data_len;
+	tuple_set_bsize(tuple, data_len);
 	tuple->format_id = tuple_format_id(format);
 	tuple_format_ref(format);
-	tuple->data_offset = data_offset;
-	tuple->is_dirty = false;
+	tuple_set_data_offset(tuple, data_offset);
+	tuple_set_dirty_bit(tuple, false);
 	char *raw = (char *) tuple + data_offset;
 	field_map_build(&builder, raw - field_map_size);
 	memcpy(raw, data, data_len);
@@ -611,7 +611,7 @@ size_t
 box_tuple_bsize(box_tuple_t *tuple)
 {
 	assert(tuple != NULL);
-	return tuple->bsize;
+	return tuple_bsize(tuple);
 }
 
 ssize_t
diff --git a/src/box/tuple.h b/src/box/tuple.h
index e4267a4ec..aac054787 100644
--- a/src/box/tuple.h
+++ b/src/box/tuple.h
@@ -344,12 +344,55 @@ struct PACKED tuple
 	 */
 };
 
+static inline void
+tuple_set_dirty_bit(struct tuple *tuple, bool is_dirty)
+{
+	assert(tuple != NULL);
+	tuple->is_dirty = is_dirty;
+}
+
+static inline bool
+tuple_is_dirty(struct tuple *tuple)
+{
+	assert(tuple != NULL);
+	return tuple->is_dirty;
+}
+
+static inline void
+tuple_set_bsize(struct tuple *tuple, uint32_t bsize)
+{
+	assert(tuple != NULL);
+	assert(bsize <= UINT32_MAX); /* bsize is UINT32_MAX */
+	tuple->bsize = bsize;
+}
+
+static inline uint32_t
+tuple_bsize(struct tuple *tuple)
+{
+	assert(tuple != NULL);
+	return tuple->bsize;
+}
+
+static inline void
+tuple_set_data_offset(struct tuple *tuple, uint16_t data_offset)
+{
+	assert(tuple != NULL);
+	tuple->data_offset = data_offset;
+}
+
+static inline uint16_t
+tuple_data_offset(struct tuple *tuple)
+{
+	assert(tuple != NULL);
+	return tuple->data_offset;
+}
+
 /** Size of the tuple including size of struct tuple. */
 static inline size_t
 tuple_size(struct tuple *tuple)
 {
 	/* data_offset includes sizeof(struct tuple). */
-	return tuple->data_offset + tuple->bsize;
+	return tuple_data_offset(tuple) + tuple_bsize(tuple);
 }
 
 /**
@@ -360,7 +403,7 @@ tuple_size(struct tuple *tuple)
 static inline const char *
 tuple_data(struct tuple *tuple)
 {
-	return (const char *) tuple + tuple->data_offset;
+	return (const char *)tuple + tuple_data_offset(tuple);
 }
 
 /**
@@ -381,8 +424,8 @@ tuple_data_or_null(struct tuple *tuple)
 static inline const char *
 tuple_data_range(struct tuple *tuple, uint32_t *p_size)
 {
-	*p_size = tuple->bsize;
-	return (const char *) tuple + tuple->data_offset;
+	*p_size = tuple_bsize(tuple);
+	return (const char *)tuple + tuple_data_offset(tuple);
 }
 
 /**
@@ -535,7 +578,8 @@ tuple_validate(struct tuple_format *format, struct tuple *tuple)
 static inline const uint32_t *
 tuple_field_map(struct tuple *tuple)
 {
-	return (const uint32_t *) ((const char *) tuple + tuple->data_offset);
+	return (const uint32_t *) ((const char *) tuple +
+				   tuple_data_offset(tuple));
 }
 
 /**
@@ -1144,7 +1188,7 @@ tuple_unref(struct tuple *tuple)
 	if (unlikely(tuple->is_bigref))
 		tuple_unref_slow(tuple);
 	else if (--tuple->refs == 0) {
-		assert(!tuple->is_dirty);
+		assert(!tuple_is_dirty(tuple));
 		tuple_delete(tuple);
 	}
 }
diff --git a/src/box/tuple_compare.cc b/src/box/tuple_compare.cc
index 0946d77f8..eb148c2f5 100644
--- a/src/box/tuple_compare.cc
+++ b/src/box/tuple_compare.cc
@@ -874,7 +874,7 @@ tuple_compare_with_key_sequential(struct tuple *tuple, hint_t tuple_hint,
 		 * Key's and tuple's first field_count fields are
 		 * equal, and their bsize too.
 		 */
-		key += tuple->bsize - mp_sizeof_array(field_count);
+		key += tuple_bsize(tuple) - mp_sizeof_array(field_count);
 		for (uint32_t i = field_count; i < part_count;
 		     ++i, mp_next(&key)) {
 			if (mp_typeof(*key) != MP_NIL)
diff --git a/src/box/tuple_extract_key.cc b/src/box/tuple_extract_key.cc
index c1ad3929e..795dc6559 100644
--- a/src/box/tuple_extract_key.cc
+++ b/src/box/tuple_extract_key.cc
@@ -95,7 +95,7 @@ tuple_extract_key_sequential(struct tuple *tuple, struct key_def *key_def,
 	assert(!has_optional_parts || key_def->is_nullable);
 	assert(has_optional_parts == key_def->has_optional_parts);
 	const char *data = tuple_data(tuple);
-	const char *data_end = data + tuple->bsize;
+	const char *data_end = data + tuple_bsize(tuple);
 	return tuple_extract_key_sequential_raw<has_optional_parts>(data,
 								    data_end,
 								    key_def,
@@ -127,7 +127,7 @@ tuple_extract_key_slowpath(struct tuple *tuple, struct key_def *key_def,
 	uint32_t bsize = mp_sizeof_array(part_count);
 	struct tuple_format *format = tuple_format(tuple);
 	const uint32_t *field_map = tuple_field_map(tuple);
-	const char *tuple_end = data + tuple->bsize;
+	const char *tuple_end = data + tuple_bsize(tuple);
 
 	/* Calculate the key size. */
 	for (uint32_t i = 0; i < part_count; ++i) {
diff --git a/src/box/tuple_format.c b/src/box/tuple_format.c
index 5f5e833b4..dca0fbddc 100644
--- a/src/box/tuple_format.c
+++ b/src/box/tuple_format.c
@@ -482,7 +482,7 @@ tuple_format_create(struct tuple_format *format, struct key_def * const *keys,
 	       || json_token_is_multikey(&tuple_format_field(format, 0)->token));
 	size_t field_map_size = -current_slot * sizeof(uint32_t);
 	if (field_map_size > INT16_MAX) {
-		/** tuple->data_offset is 15 bits */
+		/** tuple data_offset can't be more than 15 bits */
 		diag_set(ClientError, ER_INDEX_FIELD_COUNT_LIMIT,
 			 -current_slot);
 		return -1;
diff --git a/src/box/vy_stmt.c b/src/box/vy_stmt.c
index 92e0aa1c5..accafc654 100644
--- a/src/box/vy_stmt.c
+++ b/src/box/vy_stmt.c
@@ -161,7 +161,7 @@ vy_stmt_alloc(struct tuple_format *format, uint32_t data_offset, uint32_t bsize)
 	assert(data_offset >= sizeof(struct vy_stmt) + format->field_map_size);
 
 	if (data_offset > INT16_MAX) {
-		/** tuple->data_offset is 15 bits */
+		/** tuple data_offset can't be more than 15 bits */
 		diag_set(ClientError, ER_TUPLE_METADATA_IS_TOO_BIG,
 			 data_offset);
 		return NULL;
@@ -196,9 +196,9 @@ vy_stmt_alloc(struct tuple_format *format, uint32_t data_offset, uint32_t bsize)
 	tuple->format_id = tuple_format_id(format);
 	if (cord_is_main())
 		tuple_format_ref(format);
-	tuple->bsize = bsize;
-	tuple->data_offset = data_offset;
-	tuple->is_dirty = false;
+	tuple_set_bsize(tuple, bsize);
+	tuple_set_data_offset(tuple, data_offset);
+	tuple_set_dirty_bit(tuple, false);
 	vy_stmt_set_lsn(tuple, 0);
 	vy_stmt_set_type(tuple, 0);
 	vy_stmt_set_flags(tuple, 0);
@@ -214,11 +214,12 @@ vy_stmt_dup(struct tuple *stmt)
 	 * the original tuple.
 	 */
 	struct tuple *res = vy_stmt_alloc(tuple_format(stmt),
-					  stmt->data_offset, stmt->bsize);
+					  tuple_data_offset(stmt),
+					  tuple_bsize(stmt));
 	if (res == NULL)
 		return NULL;
 	assert(tuple_size(res) == tuple_size(stmt));
-	assert(res->data_offset == stmt->data_offset);
+	assert(tuple_data_offset(res) == tuple_data_offset(stmt));
 	memcpy(res, stmt, tuple_size(stmt));
 	res->refs = 1;
 	return res;
@@ -411,17 +412,20 @@ vy_stmt_replace_from_upsert(struct tuple *upsert)
 	/* Get statement size without UPSERT operations */
 	uint32_t bsize;
 	vy_upsert_data_range(upsert, &bsize);
-	assert(bsize <= upsert->bsize);
+	assert(bsize <= tuple_bsize(upsert));
 
 	/* Copy statement data excluding UPSERT operations */
 	struct tuple_format *format = tuple_format(upsert);
-	struct tuple *replace = vy_stmt_alloc(format, upsert->data_offset, bsize);
+	struct tuple *replace = vy_stmt_alloc(format,
+					      tuple_data_offset(upsert),
+					      bsize);
 	if (replace == NULL)
 		return NULL;
 	/* Copy both data and field_map. */
 	char *dst = (char *)replace + sizeof(struct vy_stmt);
 	char *src = (char *)upsert + sizeof(struct vy_stmt);
-	memcpy(dst, src, upsert->data_offset + bsize - sizeof(struct vy_stmt));
+	memcpy(dst, src, tuple_data_offset(upsert) +
+			 bsize - sizeof(struct vy_stmt));
 	vy_stmt_set_type(replace, IPROTO_REPLACE);
 	vy_stmt_set_lsn(replace, vy_stmt_lsn(upsert));
 	return replace;
diff --git a/src/box/vy_stmt.h b/src/box/vy_stmt.h
index 24c7eaad7..69f46d67c 100644
--- a/src/box/vy_stmt.h
+++ b/src/box/vy_stmt.h
@@ -583,7 +583,7 @@ vy_stmt_upsert_ops(struct tuple *tuple, uint32_t *mp_size)
 	assert(vy_stmt_type(tuple) == IPROTO_UPSERT);
 	const char *mp = tuple_data(tuple);
 	mp_next(&mp);
-	*mp_size = tuple_data(tuple) + tuple->bsize - mp;
+	*mp_size = tuple_data(tuple) + tuple_bsize(tuple) - mp;
 	return mp;
 }
 
-- 
2.17.1



More information about the Tarantool-patches mailing list