[tarantool-patches] [PATCH 01/13] tuple: remove alloc and alloc_ctx args from update()
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Tue Aug 13 02:05:07 MSK 2019
They are always region_aligned_alloc and region pointer. Lets use
them always inside tuple_update.c, with no necessity to pass
explicitly.
The patch is motivated by forthcoming updates by JSON path, which
will strongly complicate and perhaps slow down the tuple_update.c
code. The present patch as well as some next ones should smooth
these problems.
---
src/box/lua/tuple.c | 9 +++--
src/box/memtx_space.c | 18 ++++------
src/box/space.c | 23 ++++++-------
src/box/tuple.c | 6 ++--
src/box/tuple_update.c | 74 +++++++++++++++++++++--------------------
src/box/tuple_update.h | 14 +++-----
src/box/vinyl.c | 10 ++----
src/box/vy_upsert.c | 29 ++++------------
test/unit/column_mask.c | 30 +++++++----------
9 files changed, 88 insertions(+), 125 deletions(-)
diff --git a/src/box/lua/tuple.c b/src/box/lua/tuple.c
index 183c3901d..2fbfb1473 100644
--- a/src/box/lua/tuple.c
+++ b/src/box/lua/tuple.c
@@ -447,11 +447,10 @@ lbox_tuple_transform(struct lua_State *L)
* to use the default one with no restrictions on field
* count or types.
*/
- const char *new_data = tuple_update_execute(region_aligned_alloc_cb,
- region, buf->buf,
- buf->buf + ibuf_used(buf),
- old_data, old_data + bsize,
- &new_size, 1, NULL);
+ const char *new_data =
+ tuple_update_execute(buf->buf, buf->buf + ibuf_used(buf),
+ old_data, old_data + bsize, &new_size, 1,
+ NULL);
if (new_data != NULL)
new_tuple = tuple_new(box_tuple_format_default(),
new_data, new_data + new_size);
diff --git a/src/box/memtx_space.c b/src/box/memtx_space.c
index cf29cf328..d63e8a5ca 100644
--- a/src/box/memtx_space.c
+++ b/src/box/memtx_space.c
@@ -419,8 +419,7 @@ memtx_space_execute_update(struct space *space, struct txn *txn,
uint32_t new_size = 0, bsize;
const char *old_data = tuple_data_range(old_tuple, &bsize);
const char *new_data =
- tuple_update_execute(region_aligned_alloc_cb, &fiber()->gc,
- request->tuple, request->tuple_end,
+ tuple_update_execute(request->tuple, request->tuple_end,
old_data, old_data + bsize,
&new_size, request->index_base, NULL);
if (new_data == NULL)
@@ -489,9 +488,8 @@ memtx_space_execute_upsert(struct space *space, struct txn *txn,
* we get it here, it's also OK to throw it
* @sa https://github.com/tarantool/tarantool/issues/1156
*/
- if (tuple_update_check_ops(region_aligned_alloc_cb, &fiber()->gc,
- request->ops, request->ops_end,
- request->index_base)) {
+ if (tuple_update_check_ops(request->ops, request->ops_end,
+ request->index_base) != 0) {
return -1;
}
stmt->new_tuple = memtx_tuple_new(space->format,
@@ -511,12 +509,10 @@ memtx_space_execute_upsert(struct space *space, struct txn *txn,
*/
uint64_t column_mask = COLUMN_MASK_FULL;
const char *new_data =
- tuple_upsert_execute(region_aligned_alloc_cb,
- &fiber()->gc, request->ops,
- request->ops_end, old_data,
- old_data + bsize, &new_size,
- request->index_base, false,
- &column_mask);
+ tuple_upsert_execute(request->ops, request->ops_end,
+ old_data, old_data + bsize,
+ &new_size, request->index_base,
+ false, &column_mask);
if (new_data == NULL)
return -1;
diff --git a/src/box/space.c b/src/box/space.c
index b4d48fcc3..fffe03c41 100644
--- a/src/box/space.c
+++ b/src/box/space.c
@@ -330,7 +330,6 @@ static int
space_before_replace(struct space *space, struct txn *txn,
struct request *request)
{
- struct region *gc = &fiber()->gc;
enum iproto_type type = request->type;
struct index *pk = space_index(space, 0);
@@ -396,10 +395,10 @@ space_before_replace(struct space *space, struct txn *txn,
}
old_data = tuple_data_range(old_tuple, &old_size);
old_data_end = old_data + old_size;
- new_data = tuple_update_execute(region_aligned_alloc_cb, gc,
- request->tuple, request->tuple_end,
- old_data, old_data_end, &new_size,
- request->index_base, NULL);
+ new_data = tuple_update_execute(request->tuple,
+ request->tuple_end, old_data,
+ old_data_end, &new_size,
+ request->index_base, NULL);
if (new_data == NULL)
return -1;
new_data_end = new_data + new_size;
@@ -419,18 +418,18 @@ space_before_replace(struct space *space, struct txn *txn,
*/
new_data = request->tuple;
new_data_end = request->tuple_end;
- if (tuple_update_check_ops(region_aligned_alloc_cb, gc,
- request->ops, request->ops_end,
- request->index_base) != 0)
+ if (tuple_update_check_ops(request->ops,
+ request->ops_end,
+ request->index_base) != 0)
return -1;
break;
}
old_data = tuple_data_range(old_tuple, &old_size);
old_data_end = old_data + old_size;
- new_data = tuple_upsert_execute(region_aligned_alloc_cb, gc,
- request->ops, request->ops_end,
- old_data, old_data_end, &new_size,
- request->index_base, false, NULL);
+ new_data = tuple_upsert_execute(request->ops, request->ops_end,
+ old_data, old_data_end,
+ &new_size, request->index_base,
+ false, NULL);
new_data_end = new_data + new_size;
break;
default:
diff --git a/src/box/tuple.c b/src/box/tuple.c
index a01646c68..beb290a9f 100644
--- a/src/box/tuple.c
+++ b/src/box/tuple.c
@@ -708,8 +708,7 @@ box_tuple_update(box_tuple_t *tuple, const char *expr, const char *expr_end)
struct region *region = &fiber()->gc;
size_t used = region_used(region);
const char *new_data =
- tuple_update_execute(region_aligned_alloc_cb, region, expr,
- expr_end, old_data, old_data + bsize,
+ tuple_update_execute(expr, expr_end, old_data, old_data + bsize,
&new_size, 1, NULL);
if (new_data == NULL) {
region_truncate(region, used);
@@ -731,8 +730,7 @@ box_tuple_upsert(box_tuple_t *tuple, const char *expr, const char *expr_end)
struct region *region = &fiber()->gc;
size_t used = region_used(region);
const char *new_data =
- tuple_upsert_execute(region_aligned_alloc_cb, region, expr,
- expr_end, old_data, old_data + bsize,
+ tuple_upsert_execute(expr, expr_end, old_data, old_data + bsize,
&new_size, 1, false, NULL);
if (new_data == NULL) {
region_truncate(region, used);
diff --git a/src/box/tuple_update.c b/src/box/tuple_update.c
index 7a203ced8..599952189 100644
--- a/src/box/tuple_update.c
+++ b/src/box/tuple_update.c
@@ -43,7 +43,7 @@
#include <bit/int96.h>
#include <salad/rope.h>
#include "column_mask.h"
-
+#include "fiber.h"
/** UPDATE request implementation.
* UPDATE request is represented by a sequence of operations, each
@@ -96,10 +96,27 @@
* deleted one.
*/
+static inline void *
+update_alloc(void *ctx, size_t size)
+{
+ void *ptr = region_aligned_alloc((struct region *) ctx, size,
+ alignof(uint64_t));
+ if (ptr == NULL)
+ diag_set(OutOfMemory, size, "region_aligned_alloc",
+ "update internals");
+ return ptr;
+}
+
+static void
+update_free(void *ctx, void *mem)
+{
+ (void) ctx;
+ (void) mem;
+}
+
/** Update internal state */
struct tuple_update
{
- tuple_update_alloc_func alloc;
void *alloc_ctx;
struct rope *rope;
struct update_op *ops;
@@ -508,7 +525,7 @@ do_op_insert(struct tuple_update *update, struct update_op *op)
if (op_adjust_field_no(update, op, rope_size(update->rope) + 1))
return -1;
struct update_field *field = (struct update_field *)
- update->alloc(update->alloc_ctx, sizeof(*field));
+ update_alloc(update->alloc_ctx, sizeof(*field));
if (field == NULL)
return -1;
update_field_init(field, op->arg.set.value, op->arg.set.length, 0);
@@ -778,7 +795,7 @@ update_field_split(void *split_ctx, void *data, size_t size, size_t offset)
struct update_field *prev = (struct update_field *) data;
struct update_field *next = (struct update_field *)
- update->alloc(update->alloc_ctx, sizeof(*next));
+ update_alloc(update->alloc_ctx, sizeof(*next));
if (next == NULL)
return NULL;
assert(offset > 0 && prev->tail_len > 0);
@@ -799,14 +816,6 @@ update_field_split(void *split_ctx, void *data, size_t size, size_t offset)
return next;
}
-/** Free rope node - do nothing, since we use a pool allocator. */
-static void
-region_alloc_free_stub(void *ctx, void *mem)
-{
- (void) ctx;
- (void) mem;
-}
-
/**
* We found a tuple to do the update on. Prepare a rope
* to perform operations on.
@@ -822,14 +831,14 @@ int
update_create_rope(struct tuple_update *update, const char *tuple_data,
const char *tuple_data_end, uint32_t field_count)
{
- update->rope = rope_new(update_field_split, update, update->alloc,
- region_alloc_free_stub, update->alloc_ctx);
+ update->rope = rope_new(update_field_split, update, update_alloc,
+ update_free, update->alloc_ctx);
if (update->rope == NULL)
return -1;
/* Initialize the rope with the old tuple. */
struct update_field *first = (struct update_field *)
- update->alloc(update->alloc_ctx, sizeof(*first));
+ update_alloc(update->alloc_ctx, sizeof(*first));
if (first == NULL)
return -1;
const char *field = tuple_data;
@@ -970,7 +979,7 @@ update_read_ops(struct tuple_update *update, const char *expr,
}
/* Read update operations. */
- update->ops = (struct update_op *) update->alloc(update->alloc_ctx,
+ update->ops = (struct update_op *) update_alloc(update->alloc_ctx,
update->op_count * sizeof(struct update_op));
if (update->ops == NULL)
return -1;
@@ -1160,13 +1169,10 @@ upsert_do_ops(struct tuple_update *update, const char *old_data,
}
static void
-update_init(struct tuple_update *update,
- tuple_update_alloc_func alloc, void *alloc_ctx,
- int index_base)
+update_init(struct tuple_update *update, int index_base)
{
memset(update, 0, sizeof(*update));
- update->alloc = alloc;
- update->alloc_ctx = alloc_ctx;
+ update->alloc_ctx = &fiber()->gc;
/*
* Base field offset, e.g. 0 for C and 1 for Lua. Used only for
* error messages. All fields numbers must be zero-based!
@@ -1178,7 +1184,7 @@ const char *
update_finish(struct tuple_update *update, uint32_t *p_tuple_len)
{
uint32_t tuple_len = update_calc_tuple_length(update);
- char *buffer = (char *) update->alloc(update->alloc_ctx, tuple_len);
+ char *buffer = (char *) update_alloc(update->alloc_ctx, tuple_len);
if (buffer == NULL)
return NULL;
*p_tuple_len = update_write_tuple(update, buffer, buffer + tuple_len);
@@ -1186,23 +1192,21 @@ update_finish(struct tuple_update *update, uint32_t *p_tuple_len)
}
int
-tuple_update_check_ops(tuple_update_alloc_func alloc, void *alloc_ctx,
- const char *expr, const char *expr_end, int index_base)
+tuple_update_check_ops(const char *expr, const char *expr_end, int index_base)
{
struct tuple_update update;
- update_init(&update, alloc, alloc_ctx, index_base);
+ update_init(&update, index_base);
return update_read_ops(&update, expr, expr_end, 0);
}
const char *
-tuple_update_execute(tuple_update_alloc_func alloc, void *alloc_ctx,
- const char *expr,const char *expr_end,
+tuple_update_execute(const char *expr,const char *expr_end,
const char *old_data, const char *old_data_end,
uint32_t *p_tuple_len, int index_base,
uint64_t *column_mask)
{
struct tuple_update update;
- update_init(&update, alloc, alloc_ctx, index_base);
+ update_init(&update, index_base);
uint32_t field_count = mp_decode_array(&old_data);
if (update_read_ops(&update, expr, expr_end, field_count) != 0)
@@ -1216,14 +1220,13 @@ tuple_update_execute(tuple_update_alloc_func alloc, void *alloc_ctx,
}
const char *
-tuple_upsert_execute(tuple_update_alloc_func alloc, void *alloc_ctx,
- const char *expr,const char *expr_end,
+tuple_upsert_execute(const char *expr,const char *expr_end,
const char *old_data, const char *old_data_end,
uint32_t *p_tuple_len, int index_base, bool suppress_error,
uint64_t *column_mask)
{
struct tuple_update update;
- update_init(&update, alloc, alloc_ctx, index_base);
+ update_init(&update, index_base);
uint32_t field_count = mp_decode_array(&old_data);
if (update_read_ops(&update, expr, expr_end, field_count) != 0)
@@ -1238,8 +1241,7 @@ tuple_upsert_execute(tuple_update_alloc_func alloc, void *alloc_ctx,
}
const char *
-tuple_upsert_squash(tuple_update_alloc_func alloc, void *alloc_ctx,
- const char *expr1, const char *expr1_end,
+tuple_upsert_squash(const char *expr1, const char *expr1_end,
const char *expr2, const char *expr2_end,
size_t *result_size, int index_base)
{
@@ -1247,7 +1249,7 @@ tuple_upsert_squash(tuple_update_alloc_func alloc, void *alloc_ctx,
const char *expr_end[2] = {expr1_end, expr2_end};
struct tuple_update update[2];
for (int j = 0; j < 2; j++) {
- update_init(&update[j], alloc, alloc_ctx, index_base);
+ update_init(&update[j], index_base);
if (update_read_ops(&update[j], expr[j], expr_end[j], 0))
return NULL;
mp_decode_array(&expr[j]);
@@ -1264,8 +1266,8 @@ tuple_upsert_squash(tuple_update_alloc_func alloc, void *alloc_ctx,
}
size_t possible_size = expr1_end - expr1 + expr2_end - expr2;
const uint32_t space_for_arr_tag = 5;
- char *buf = (char *)alloc(alloc_ctx,
- possible_size + space_for_arr_tag);
+ char *buf = (char *) update_alloc(&fiber()->gc,
+ possible_size + space_for_arr_tag);
if (buf == NULL)
return NULL;
/* reserve some space for mp array header */
diff --git a/src/box/tuple_update.h b/src/box/tuple_update.h
index 706edd55a..37faa1918 100644
--- a/src/box/tuple_update.h
+++ b/src/box/tuple_update.h
@@ -44,22 +44,17 @@ enum {
BOX_UPDATE_OP_CNT_MAX = 4000,
};
-typedef void *(*tuple_update_alloc_func)(void *, size_t);
-
int
-tuple_update_check_ops(tuple_update_alloc_func alloc, void *alloc_ctx,
- const char *expr, const char *expr_end, int index_base);
+tuple_update_check_ops(const char *expr, const char *expr_end, int index_base);
const char *
-tuple_update_execute(tuple_update_alloc_func alloc, void *alloc_ctx,
- const char *expr,const char *expr_end,
+tuple_update_execute(const char *expr,const char *expr_end,
const char *old_data, const char *old_data_end,
uint32_t *p_new_size, int index_base,
uint64_t *column_mask);
const char *
-tuple_upsert_execute(tuple_update_alloc_func alloc, void *alloc_ctx,
- const char *expr, const char *expr_end,
+tuple_upsert_execute(const char *expr, const char *expr_end,
const char *old_data, const char *old_data_end,
uint32_t *p_new_size, int index_base, bool suppress_error,
uint64_t *column_mask);
@@ -75,8 +70,7 @@ tuple_upsert_execute(tuple_update_alloc_func alloc, void *alloc_ctx,
* If it isn't possible to merge expressions NULL is returned.
*/
const char *
-tuple_upsert_squash(tuple_update_alloc_func alloc, void *alloc_ctx,
- const char *expr1, const char *expr1_end,
+tuple_upsert_squash(const char *expr1, const char *expr1_end,
const char *expr2, const char *expr2_end,
size_t *result_size, int index_base);
diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index cd009c1c2..4c5c08852 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -1942,8 +1942,7 @@ vy_update(struct vy_env *env, struct vy_tx *tx, struct txn_stmt *stmt,
uint32_t new_size, old_size;
const char *old_tuple = tuple_data_range(stmt->old_tuple, &old_size);
const char *old_tuple_end = old_tuple + old_size;
- new_tuple = tuple_update_execute(region_aligned_alloc_cb, &fiber()->gc,
- request->tuple, request->tuple_end,
+ new_tuple = tuple_update_execute(request->tuple, request->tuple_end,
old_tuple, old_tuple_end, &new_size,
request->index_base, &column_mask);
if (new_tuple == NULL)
@@ -2122,8 +2121,7 @@ vy_upsert(struct vy_env *env, struct vy_tx *tx, struct txn_stmt *stmt,
if (vy_is_committed(env, pk))
return 0;
/* Check update operations. */
- if (tuple_update_check_ops(region_aligned_alloc_cb, &fiber()->gc,
- request->ops, request->ops_end,
+ if (tuple_update_check_ops(request->ops, request->ops_end,
request->index_base)) {
return -1;
}
@@ -2181,9 +2179,7 @@ vy_upsert(struct vy_env *env, struct vy_tx *tx, struct txn_stmt *stmt,
old_tuple_end = old_tuple + old_size;
/* Apply upsert operations to the old tuple. */
- new_tuple = tuple_upsert_execute(region_aligned_alloc_cb,
- &fiber()->gc, ops, ops_end,
- old_tuple, old_tuple_end,
+ new_tuple = tuple_upsert_execute(ops, ops_end, old_tuple, old_tuple_end,
&new_size, 0, false, &column_mask);
if (new_tuple == NULL)
return -1;
diff --git a/src/box/vy_upsert.c b/src/box/vy_upsert.c
index e5e53be79..1c55f86c2 100644
--- a/src/box/vy_upsert.c
+++ b/src/box/vy_upsert.c
@@ -38,17 +38,6 @@
#include "fiber.h"
#include "column_mask.h"
-static void *
-vy_update_alloc(void *arg, size_t size)
-{
- /* TODO: rewrite tuple_upsert_execute() without exceptions */
- struct region *region = (struct region *) arg;
- void *data = region_aligned_alloc(region, size, sizeof(uint64_t));
- if (data == NULL)
- diag_set(OutOfMemory, size, "region", "upsert");
- return data;
-}
-
/**
* Try to squash two upsert series (msgspacked index_base + ops)
* Try to create a tuple with squahed operations
@@ -58,7 +47,7 @@ vy_update_alloc(void *arg, size_t size)
* @retval -1 - memory error
*/
static int
-vy_upsert_try_to_squash(struct tuple_format *format, struct region *region,
+vy_upsert_try_to_squash(struct tuple_format *format,
const char *key_mp, const char *key_mp_end,
const char *old_serie, const char *old_serie_end,
const char *new_serie, const char *new_serie_end,
@@ -68,8 +57,7 @@ vy_upsert_try_to_squash(struct tuple_format *format, struct region *region,
size_t squashed_size;
const char *squashed =
- tuple_upsert_squash(vy_update_alloc, region,
- old_serie, old_serie_end,
+ tuple_upsert_squash(old_serie, old_serie_end,
new_serie, new_serie_end,
&squashed_size, 0);
if (squashed == NULL)
@@ -130,10 +118,9 @@ vy_apply_upsert(struct tuple *new_stmt, struct tuple *old_stmt,
size_t region_svp = region_used(region);
uint8_t old_type = vy_stmt_type(old_stmt);
uint64_t column_mask = COLUMN_MASK_FULL;
- result_mp = tuple_upsert_execute(vy_update_alloc, region, new_ops,
- new_ops_end, result_mp, result_mp_end,
- &mp_size, 0, suppress_error,
- &column_mask);
+ result_mp = tuple_upsert_execute(new_ops, new_ops_end, result_mp,
+ result_mp_end, &mp_size, 0,
+ suppress_error, &column_mask);
result_mp_end = result_mp + mp_size;
if (old_type != IPROTO_UPSERT) {
assert(old_type == IPROTO_INSERT ||
@@ -163,10 +150,8 @@ vy_apply_upsert(struct tuple *new_stmt, struct tuple *old_stmt,
* UPSERT + UPSERT case: combine operations
*/
assert(old_ops_end - old_ops > 0);
- if (vy_upsert_try_to_squash(format, region,
- result_mp, result_mp_end,
- old_ops, old_ops_end,
- new_ops, new_ops_end,
+ if (vy_upsert_try_to_squash(format, result_mp, result_mp_end,
+ old_ops, old_ops_end, new_ops, new_ops_end,
&result_stmt) != 0) {
region_truncate(region, region_svp);
return NULL;
diff --git a/test/unit/column_mask.c b/test/unit/column_mask.c
index 7859626f8..3ffd351ac 100644
--- a/test/unit/column_mask.c
+++ b/test/unit/column_mask.c
@@ -3,6 +3,9 @@
#include "unit.h"
#include "msgpuck.h"
#include "trivia/util.h"
+#include "fiber.h"
+#include "memory.h"
+#include "tuple.h"
#define MAX_OPS 20
#define MAX_FIELDS 100
@@ -102,20 +105,6 @@ tuple_new_update(const struct tuple_update_template *update, char **end)
return ret;
}
-static char buffer[2048];
-static size_t pos = 0;
-
-/** Allocator for the tuple_update function. */
-static void *
-tuple_update_alloc_f(void *unused, size_t size)
-{
- (void) unused;
- fail_if(pos + size > sizeof(buffer));
- char *ret = &buffer[pos];
- pos += size;
- return ret;
-}
-
/**
* Execute an update operation from the template and compare it
* with the expected tuple and expected column_mask.
@@ -138,20 +127,19 @@ check_update_result(const struct tuple_template *original,
uint32_t actual_len;
uint64_t column_mask;
+ struct region *region = &fiber()->gc;
const char *actual =
- tuple_update_execute(tuple_update_alloc_f, NULL, ops, ops_end,
- old, old_end, &actual_len, 1,
+ tuple_update_execute(ops, ops_end, old, old_end, &actual_len, 1,
&column_mask);
fail_if(actual == NULL);
is((int32_t)actual_len, new_end - new, "check result length");
is(memcmp(actual, new, actual_len), 0, "tuple update is correct");
is(column_mask, expected_mask, "column_mask is correct");
+ fiber_gc();
free(old);
free(new);
free(ops);
- /* reset the global buffer. */
- pos = 0;
}
static inline void
@@ -239,6 +227,9 @@ basic_test()
int
main()
{
+ memory_init();
+ fiber_init(fiber_c_invoke);
+ tuple_init(NULL);
header();
plan(27);
@@ -246,4 +237,7 @@ main()
footer();
check_plan();
+ tuple_free();
+ fiber_free();
+ memory_free();
}
--
2.20.1 (Apple Git-117)
More information about the Tarantool-patches
mailing list