From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id DE3B5718B1; Tue, 19 Jan 2021 02:51:40 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org DE3B5718B1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1611013900; bh=3EGnx8iFb8NE6gOqHqmcwJOm1IIPLktEkQW/IZkYnUU=; h=To:Date:In-Reply-To:References:In-Reply-To:References:Subject: List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help: List-Subscribe:From:Reply-To:Cc:From; b=J7kX7gf5eB1F97Hsyzpa7xzrcCEhwP8KIrfxv03J9eEkcwAR39PJ7JvuOQ3/Awzql oa8LFNvUY1v2ThL2ss11lVnK3lSDew5TElbDOfu7gdFKKWZr5MQTVMKk0bwr3a6Lx3 su7D8JOClVdxxxEzmXmf8ZGlXAZ7H1EAsk6mTFsw= Received: from smtp43.i.mail.ru (smtp43.i.mail.ru [94.100.177.103]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 43996645E6 for ; Tue, 19 Jan 2021 02:50:41 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 43996645E6 Received: by smtp43.i.mail.ru with esmtpa (envelope-from ) id 1l1eIC-000553-5G; Tue, 19 Jan 2021 02:50:40 +0300 To: v.shpilevoy@tarantool.org, alyapunov@tarantool.org Date: Tue, 19 Jan 2021 02:50:31 +0300 Message-Id: <9d45518e4962ce6ce0261e6766efb45e39241564.1611013688.git.i.kosarev@tarantool.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD9D0E79FBC973162CD3008320BFA2F4C653BABCE9B72A1DEA600894C459B0CD1B9FEA1F86B8B2DD8613497E155678C94105BDEB18AB7251EEF6AE5DE23F762A4BF X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE73A9F268E9C335DB5EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F790063762FE880BD25272B08638F802B75D45FF5571747095F342E8C7A0BC55FA0FE5FC76BE4C15C5329EC4DD0210E1CAD071D40CC7C88D29033E14389733CBF5DBD5E913377AFFFEAFD269176DF2183F8FC7C0D9442B0B5983000E8941B15DA834481FCF19DD082D7633A0EF3E4896CB9E6436389733CBF5DBD5E9D5E8D9A59859A8B6D082881546D93491CC7F00164DA146DA6F5DAA56C3B73B237318B6A418E8EAB8D32BA5DBAC0009BE9E8FC8737B5C2249D4106471554010DE76E601842F6C81A12EF20D2F80756B5F7E9C4E3C761E06A776E601842F6C81A127C277FBC8AE2E8B465C13E723E230573AA81AA40904B5D9DBF02ECDB25306B2B25CBF701D1BE8734AD6D5ED66289B5278DA827A17800CE797E1AC076310AD6267F23339F89546C5A8DF7F3B2552694A6FED454B719173D6725E5C173C3A84C3FD340EA919DED65B35872C767BF85DA2F004C906525384306FED454B719173D6462275124DF8B9C9DF33B08B2BB81206574AF45C6390F7469DAA53EE0834AAEE X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975C8F59B88ADF80E5C00C049BDB3DFECCDB72A5A2CA60CB639F9C2B6934AE262D3EE7EAB7254005DCED7532B743992DF240BDC6A1CF3F042BAD6DF99611D93F60EF6EA1BA7CA28B4A74699F904B3F4130E343918A1A30D5E7FCCB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D3430FC2BC1B917F0189BAAD7D158973D520853A4F8C9EA099BC789D2DB54019CDBBF8F74782377723E1D7E09C32AA3244C96BF82DC86C7AD02791FF627123D400330363D8B7DA7DD44927AC6DF5659F194 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojbL9S8ysBdXjuG74y4HcDPYgHPlNgwGhs X-Mailru-Sender: 06752BE58DD8CE37E6C4CE7F78F2F1FB675A15EBB4E9AB6467C888AB417DD5655AB84C596710711040CFBDB3DDA0AC31AAFFD2005305549D2F0B9811F39295BF38C65A79EEA694937402F9BA4338D657ED14614B50AE0675 X-Mras: Ok Subject: [Tarantool-patches] [PATCH 2/4] tuple: use getters and setters X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Ilya Kosarev via Tarantool-patches Reply-To: Ilya Kosarev Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" 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(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