Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@dev.tarantool.org, kostja.osipov@gmail.com,
	imun@tarantool.org, korablev@tarantool.org
Subject: [Tarantool-patches] [PATCH v2 3/4] tuple: allow xrow_update sizeof reserve more memory
Date: Tue,  4 Feb 2020 23:53:46 +0100	[thread overview]
Message-ID: <c3b87990d01b59991834dca160e201851d3a3084.1580856722.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1580856721.git.v.shpilevoy@tarantool.org>

Currently xrow_update sizeof + store are used to calculate the
result tuple's size, preallocate it as a monolithic memory block,
and save the update tree into it.

Sizeof was expected to return the exact memory size needed for the
tuple. But this is not useful when result size of a field depends
on its format type, and therefore on its position in the tuple.
Because in that case sizeof would need to care about tuple format,
and walk format tree just like store does now. Or it would be
needed to save the found json tree nodes into struct
xrow_update_op during sizeof calculation. All of this would make
sizeof code more complex.

The patch makes it possible for sizeof to return the maximal
needed size. So, for example, a floating point field size now
returns size needed for encoding of a double. And then store can
either encode double or float.

Follow-up #4701
---
 src/box/xrow_update.c       |  2 +-
 src/box/xrow_update_bar.c   |  5 ++---
 src/box/xrow_update_field.c | 37 ++++++++++++++++++++++---------------
 src/box/xrow_update_field.h |  4 ++--
 4 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/src/box/xrow_update.c b/src/box/xrow_update.c
index ac8c9d303..63f7bc3da 100644
--- a/src/box/xrow_update.c
+++ b/src/box/xrow_update.c
@@ -357,7 +357,7 @@ xrow_update_finish(struct xrow_update *update, struct tuple_format *format,
 	*p_tuple_len = xrow_update_array_store(&update->root, &format->fields,
 					       &format->fields.root, buffer,
 					       buffer + tuple_len);
-	assert(*p_tuple_len == tuple_len);
+	assert(*p_tuple_len <= tuple_len);
 	return buffer;
 }
 
diff --git a/src/box/xrow_update_bar.c b/src/box/xrow_update_bar.c
index b4a98978a..0033f0044 100644
--- a/src/box/xrow_update_bar.c
+++ b/src/box/xrow_update_bar.c
@@ -446,9 +446,8 @@ xrow_update_bar_store(struct xrow_update_field *field,
 
 		memcpy(out, field->data, before_point);
 		out += before_point;
-		op->meta->store(op, format_tree, this_node, field->bar.point,
-				out);
-		out += op->new_field_len;
+		out += op->meta->store(op, format_tree, this_node,
+				       field->bar.point, out);
 		memcpy(out, point_end, after_point);
 		return out + after_point - out_saved;
 	}
diff --git a/src/box/xrow_update_field.c b/src/box/xrow_update_field.c
index 42a3ba50a..d431c22f8 100644
--- a/src/box/xrow_update_field.c
+++ b/src/box/xrow_update_field.c
@@ -132,7 +132,6 @@ xrow_update_field_store(struct xrow_update_field *field,
 			struct json_token *this_node, char *out, char *out_end)
 {
 	struct xrow_update_op *op;
-	uint32_t size;
 	switch(field->type) {
 	case XUPDATE_NOP:
 		assert(out_end - out >= field->size);
@@ -140,10 +139,9 @@ xrow_update_field_store(struct xrow_update_field *field,
 		return field->size;
 	case XUPDATE_SCALAR:
 		op = field->scalar.op;
-		size = op->new_field_len;
-		assert(out_end - out >= size);
-		op->meta->store(op, format_tree, this_node, field->data, out);
-		return size;
+		assert(out_end - out >= op->new_field_len);
+		return op->meta->store(op, format_tree, this_node, field->data,
+				       out);
 	case XUPDATE_ARRAY:
 		return xrow_update_array_store(field, format_tree, this_node,
 					       out, out_end);
@@ -516,7 +514,7 @@ xrow_update_op_do_splice(struct xrow_update_op *op, const char *old)
 
 /* {{{ store_op */
 
-static void
+static uint32_t
 xrow_update_op_store_set(struct xrow_update_op *op,
 			 struct json_tree *format_tree,
 			 struct json_token *this_node, const char *in,
@@ -526,9 +524,10 @@ xrow_update_op_store_set(struct xrow_update_op *op,
 	(void) this_node;
 	(void) in;
 	memcpy(out, op->arg.set.value, op->arg.set.length);
+	return op->arg.set.length;
 }
 
-void
+uint32_t
 xrow_update_op_store_arith(struct xrow_update_op *op,
 			   struct json_tree *format_tree,
 			   struct json_token *this_node, const char *in,
@@ -537,30 +536,34 @@ xrow_update_op_store_arith(struct xrow_update_op *op,
 	(void) format_tree;
 	(void) this_node;
 	(void) in;
+	char *begin = out;
 	struct xrow_update_arg_arith *arg = &op->arg.arith;
 	switch (arg->type) {
 	case XUPDATE_TYPE_INT:
 		if (int96_is_uint64(&arg->int96)) {
-			mp_encode_uint(out, int96_extract_uint64(&arg->int96));
+			out = mp_encode_uint(
+				out, int96_extract_uint64(&arg->int96));
 		} else {
 			assert(int96_is_neg_int64(&arg->int96));
-			mp_encode_int(out, int96_extract_neg_int64(&arg->int96));
+			out = mp_encode_int(
+				out, int96_extract_neg_int64( &arg->int96));
 		}
 		break;
 	case XUPDATE_TYPE_DOUBLE:
-		mp_encode_double(out, arg->dbl);
+		out = mp_encode_double(out, arg->dbl);
 		break;
 	case XUPDATE_TYPE_FLOAT:
-		mp_encode_float(out, arg->flt);
+		out = mp_encode_float(out, arg->flt);
 		break;
 	default:
 		assert(arg->type == XUPDATE_TYPE_DECIMAL);
-		mp_encode_decimal(out, &arg->dec);
+		out = mp_encode_decimal(out, &arg->dec);
 		break;
 	}
+	return out - begin;
 }
 
-static void
+static uint32_t
 xrow_update_op_store_bit(struct xrow_update_op *op,
 			 struct json_tree *format_tree,
 			 struct json_token *this_node, const char *in,
@@ -569,10 +572,11 @@ xrow_update_op_store_bit(struct xrow_update_op *op,
 	(void) format_tree;
 	(void) this_node;
 	(void) in;
-	mp_encode_uint(out, op->arg.bit.val);
+	char *end = mp_encode_uint(out, op->arg.bit.val);
+	return end - out;
 }
 
-static void
+static uint32_t
 xrow_update_op_store_splice(struct xrow_update_op *op,
 			    struct json_tree *format_tree,
 			    struct json_token *this_node, const char *in,
@@ -583,6 +587,7 @@ xrow_update_op_store_splice(struct xrow_update_op *op,
 	struct xrow_update_arg_splice *arg = &op->arg.splice;
 	uint32_t new_str_len = arg->offset + arg->paste_length +
 			       arg->tail_length;
+	char *begin = out;
 	(void) mp_decode_strl(&in);
 	out = mp_encode_strl(out, new_str_len);
 	/* Copy field head. */
@@ -593,6 +598,8 @@ xrow_update_op_store_splice(struct xrow_update_op *op,
 	out = out + arg->paste_length;
 	/* Copy tail. */
 	memcpy(out, in + arg->tail_offset, arg->tail_length);
+	out = out + arg->tail_length;
+	return out - begin;
 }
 
 /* }}} store_op */
diff --git a/src/box/xrow_update_field.h b/src/box/xrow_update_field.h
index 782cb5d3f..5a8a79881 100644
--- a/src/box/xrow_update_field.h
+++ b/src/box/xrow_update_field.h
@@ -151,7 +151,7 @@ typedef int
 (*xrow_update_op_do_f)(struct xrow_update_op *op,
 		       struct xrow_update_field *field);
 
-typedef void
+typedef uint32_t
 (*xrow_update_op_store_f)(struct xrow_update_op *op,
 			  struct json_tree *format_tree,
 			  struct json_token *this_node, const char *in,
@@ -711,7 +711,7 @@ xrow_update_arith_make(struct xrow_update_op *op,
 		       struct xrow_update_arg_arith arg,
 		       struct xrow_update_arg_arith *ret);
 
-void
+uint32_t
 xrow_update_op_store_arith(struct xrow_update_op *op,
 			   struct json_tree *format_tree,
 			   struct json_token *this_node, const char *in,
-- 
2.21.1 (Apple Git-122.3)

  parent reply	other threads:[~2020-02-04 22:53 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-04 22:53 [Tarantool-patches] [PATCH v2 0/4] Don't truncate float in update Vladislav Shpilevoy
2020-02-04 22:53 ` [Tarantool-patches] [PATCH v2 1/4] tuple: don't truncate float in :update() Vladislav Shpilevoy
2020-02-10 14:41   ` Nikita Pettik
2020-02-10 21:18     ` Vladislav Shpilevoy
2020-02-19 21:36       ` Nikita Pettik
2020-02-04 22:53 ` [Tarantool-patches] [PATCH v2 2/4] tuple: pass tuple format to xrow_update_*_store() Vladislav Shpilevoy
2020-02-10 16:51   ` Nikita Pettik
2020-02-10 21:18     ` Vladislav Shpilevoy
2020-02-04 22:53 ` Vladislav Shpilevoy [this message]
2020-02-10 16:05   ` [Tarantool-patches] [PATCH v2 3/4] tuple: allow xrow_update sizeof reserve more memory Nikita Pettik
2020-02-04 22:53 ` [Tarantool-patches] [PATCH v2 4/4] tuple: use field type in update of a float/double Vladislav Shpilevoy
2020-02-10 16:16   ` Nikita Pettik
2020-02-10 21:18     ` Vladislav Shpilevoy
2020-02-05 11:09 ` [Tarantool-patches] [PATCH v2 0/4] Don't truncate float in update Konstantin Osipov
2020-02-05 22:11   ` Vladislav Shpilevoy
2020-02-20  6:15 ` Kirill Yukhin
2020-02-20 13:27   ` Nikita Pettik
2020-02-20 20:30   ` Vladislav Shpilevoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c3b87990d01b59991834dca160e201851d3a3084.1580856722.git.v.shpilevoy@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=imun@tarantool.org \
    --cc=korablev@tarantool.org \
    --cc=kostja.osipov@gmail.com \
    --cc=tarantool-patches@dev.tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH v2 3/4] tuple: allow xrow_update sizeof reserve more memory' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox