From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Kirill Shcherbatov Subject: [PATCH v3 3/4] box: introduce tuple_extra infrastructure Date: Wed, 17 Jul 2019 04:20:44 +0300 Message-Id: <3474f2b5e217e1dcd5ab405b72f574b283b132f0.1563326037.git.kshcherbatov@tarantool.org> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit To: tarantool-patches@freelists.org, vdavydov.dev@gmail.com Cc: kostja@tarantool.org, Kirill Shcherbatov List-ID: Introduced a new object tuple_extra: a memory allocation is associated with given tuple and chunk_id. Extended tuple_format's vtab with few new methods to manage tuple_extras lifecycle. Supported tuple_extra for memtx engine: a memory chunks are allocated with memtx's smalloc allocator. Needed for #1260 --- src/box/memtx_engine.c | 29 +++++++++++++++++++++++++++++ src/box/tuple.c | 8 ++++++++ src/box/tuple.h | 39 +++++++++++++++++++++++++++++++++++++++ src/box/tuple_format.h | 15 +++++++++++++++ src/box/vy_stmt.c | 2 ++ 5 files changed, 93 insertions(+) diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c index 428491c2d..49efcc192 100644 --- a/src/box/memtx_engine.c +++ b/src/box/memtx_engine.c @@ -1126,9 +1126,38 @@ memtx_tuple_delete(struct tuple_format *format, struct tuple *tuple) smfree_delayed(&memtx->alloc, memtx_tuple, total); } +void +metmx_tuple_extra_delete(struct tuple_format *format, + struct tuple_extra *tuple_extra) +{ + struct memtx_engine *memtx = (struct memtx_engine *)format->engine; + uint32_t sz = tuple_extra_sz(tuple_extra->data_sz); + smfree(&memtx->alloc, tuple_extra, sz); +} + +struct tuple_extra * +memtx_tuple_extra_new(struct tuple_format *format, struct tuple *tuple, + uint32_t chunk_id, uint32_t data_sz) +{ + struct memtx_engine *memtx = (struct memtx_engine *)format->engine; + uint32_t sz = tuple_extra_sz(data_sz); + struct tuple_extra *tuple_extra = + (struct tuple_extra *) smalloc(&memtx->alloc, sz); + if (tuple == NULL) { + diag_set(OutOfMemory, sz, "smalloc", "tuple"); + return NULL; + } + tuple_extra->tuple = tuple; + tuple_extra->chunk_id = chunk_id; + tuple_extra->data_sz = data_sz; + return tuple_extra; +} + struct tuple_format_vtab memtx_tuple_format_vtab = { memtx_tuple_delete, memtx_tuple_new, + metmx_tuple_extra_delete, + memtx_tuple_extra_new, }; /** diff --git a/src/box/tuple.c b/src/box/tuple.c index c0e94d55b..ca0e5230a 100644 --- a/src/box/tuple.c +++ b/src/box/tuple.c @@ -67,6 +67,8 @@ runtime_tuple_new(struct tuple_format *format, const char *data, const char *end static struct tuple_format_vtab tuple_format_runtime_vtab = { runtime_tuple_delete, runtime_tuple_new, + NULL, + NULL, }; static struct tuple * @@ -785,3 +787,9 @@ mp_str(const char *data) return ""; return buf; } + +uint32_t +tuple_extra_sz(uint32_t data_sz) +{ + return sizeof(struct tuple_extra) + data_sz; +} diff --git a/src/box/tuple.h b/src/box/tuple.h index 99dfeb82d..70119292e 100644 --- a/src/box/tuple.h +++ b/src/box/tuple.h @@ -447,6 +447,45 @@ tuple_delete(struct tuple *tuple) format->vtab.tuple_delete(format, tuple); } +/** Tuple metadata hashtable entry. */ +struct tuple_extra { + /** Tuple pointer is used as a hash key. */ + struct tuple *tuple; + /** An extention identifier. */ + uint32_t chunk_id; + /** The payload size. Needed to perform memory release.*/ + uint32_t data_sz; + /** Metadata object payload. */ + char data[0]; +}; + +/** Calculate the size of tuple_extra object by given data_sz. */ +uint32_t +tuple_extra_sz(uint32_t data_sz); + +/** + * Allocate a new extra allocation for given tuple and + * unique chunk_id identifier. + */ +static inline struct tuple_extra * +tuple_extra_new(struct tuple *tuple, uint32_t chunk_id, uint32_t data_sz) +{ + struct tuple_format *format = tuple_format(tuple); + return format->vtab.tuple_extra_new(format, tuple, chunk_id, data_sz); +} + +/** + * Free allocated tuple extra for given tuple and unique + * chunk_id identifier. + */ +static inline void +tuple_extra_delete(struct tuple_extra *tuple_extra) +{ + struct tuple_format *format = + tuple_format(tuple_extra->tuple); + format->vtab.tuple_extra_delete(format, tuple_extra); +} + /** * Check tuple data correspondence to space format. * Actually, checks everything that is checked by diff --git a/src/box/tuple_format.h b/src/box/tuple_format.h index e4f5f0018..ac4f8a702 100644 --- a/src/box/tuple_format.h +++ b/src/box/tuple_format.h @@ -64,6 +64,7 @@ enum { TUPLE_INDEX_BASE = 1 }; enum { TUPLE_OFFSET_SLOT_NIL = INT32_MAX }; struct tuple; +struct tuple_extra; struct tuple_format; struct coll; @@ -82,6 +83,20 @@ struct tuple_format_vtab { struct tuple* (*tuple_new)(struct tuple_format *format, const char *data, const char *end); + /** + * Free allocated tuple extra for given tuple and unique + * chunk_id identifier. + */ + void + (*tuple_extra_delete)(struct tuple_format *format, + struct tuple_extra *tuple_extra); + /** + * Allocate a new extra allocation for given tuple and + * unique chunk_id identifier. + */ + struct tuple_extra * + (*tuple_extra_new)(struct tuple_format *format, struct tuple *tuple, + uint32_t chunk_id, uint32_t data_sz); }; /** Tuple field meta information for tuple_format. */ diff --git a/src/box/vy_stmt.c b/src/box/vy_stmt.c index f936cd61f..6b09e5e53 100644 --- a/src/box/vy_stmt.c +++ b/src/box/vy_stmt.c @@ -118,6 +118,8 @@ vy_stmt_env_create(struct vy_stmt_env *env) { env->tuple_format_vtab.tuple_new = vy_tuple_new; env->tuple_format_vtab.tuple_delete = vy_tuple_delete; + env->tuple_format_vtab.tuple_extra_new = NULL; + env->tuple_format_vtab.tuple_extra_delete = NULL; env->max_tuple_size = 1024 * 1024; env->key_format = vy_stmt_format_new(env, NULL, 0, NULL, 0, 0, NULL); if (env->key_format == NULL) -- 2.22.0