[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