From 5c28ac94b92d7d3b37a2e413798d16eb580ec6d8 Mon Sep 17 00:00:00 2001
From: Dmitry Simonenko <pmwkaa@gmail.com>
Date: Mon, 1 Jul 2013 18:32:07 +0400
Subject: [PATCH] tarantool-snap: fix tuple update corruption

---
 client/tarantool_snap/compat.c   |  8 ++---
 client/tarantool_snap/cursor.c   |  1 -
 client/tarantool_snap/indexate.c |  1 -
 client/tarantool_snap/main.c     |  3 --
 client/tarantool_snap/snapshot.c |  7 ++--
 client/tarantool_snap/space.c    |  1 +
 client/tarantool_snap/ts.h       |  1 -
 client/tarantool_snap/update.cc  | 58 ++++++++++++++++++--------------
 connector/c/tnt/tnt_request.c    |  8 ++---
 9 files changed, 44 insertions(+), 44 deletions(-)

diff --git a/client/tarantool_snap/compat.c b/client/tarantool_snap/compat.c
index b18df25fbb..f2c8c62641 100644
--- a/client/tarantool_snap/compat.c
+++ b/client/tarantool_snap/compat.c
@@ -62,10 +62,10 @@ void say_snap(int level, const char *filename, int line, const char *error,
 sayfunc_t _say = say_snap;
 
 void assert_fail(const char *assertion, const char *file, unsigned int line,
-                 const char *function) {
-	(void)assertion;
-	(void)file;
-	(void)line;
+                 const char *function)
+{
 	(void)function;
+	fflush(NULL);
+	printf("assert: %s:%d %s\n", file, line, assertion);
 	exit(1);
 }
diff --git a/client/tarantool_snap/cursor.c b/client/tarantool_snap/cursor.c
index 32e80e9723..39f2bf0e31 100644
--- a/client/tarantool_snap/cursor.c
+++ b/client/tarantool_snap/cursor.c
@@ -23,7 +23,6 @@
 #include "space.h"
 #include "sha1.h"
 #include "ref.h"
-#include "region.h"
 #include "ts.h"
 #include "cursor.h"
 
diff --git a/client/tarantool_snap/indexate.c b/client/tarantool_snap/indexate.c
index b3a125f44b..26a3b2590e 100644
--- a/client/tarantool_snap/indexate.c
+++ b/client/tarantool_snap/indexate.c
@@ -21,7 +21,6 @@
 #include "space.h"
 #include "sha1.h"
 #include "ref.h"
-#include "region.h"
 #include "ts.h"
 #include "indexate.h"
 #include "update.h"
diff --git a/client/tarantool_snap/main.c b/client/tarantool_snap/main.c
index 6951e7495c..688ece7149 100644
--- a/client/tarantool_snap/main.c
+++ b/client/tarantool_snap/main.c
@@ -46,7 +46,6 @@
 #include "config.h"
 #include "space.h"
 #include "ref.h"
-#include "region.h"
 #include "ts.h"
 #include "indexate.h"
 #include "snapshot.h"
@@ -63,7 +62,6 @@ ts_init(void)
 	memset(&tss.s, 0, sizeof(tss.s));
 	tss.last_snap_lsn = 0;
 	tss.last_xlog_lsn = 0;
-	ts_region_init(&tss.rup);
 	return 0;
 }
 
@@ -73,7 +71,6 @@ ts_free(void)
 	ts_options_free(&tss.opts);
 	ts_space_free(&tss.s);
 	ts_reftable_free(&tss.rt);
-	ts_region_free(&tss.rup);
 }
 
 int main(int argc, char *argv[])
diff --git a/client/tarantool_snap/snapshot.c b/client/tarantool_snap/snapshot.c
index 666ae92799..a79059b67b 100644
--- a/client/tarantool_snap/snapshot.c
+++ b/client/tarantool_snap/snapshot.c
@@ -23,7 +23,6 @@
 #include "space.h"
 #include "sha1.h"
 #include "ref.h"
-#include "region.h"
 #include "ts.h"
 #include "indexate.h"
 #include "snapshot.h"
@@ -55,7 +54,7 @@ ts_snapshot_write(FILE *snapshot, uint32_t space, uint64_t lsn, struct tnt_tuple
 			.cookie = 0,
 			.space = space,
 			.tuple_size = t->cardinality,
-			.data_size = t->size 
+			.data_size = t->size - sizeof(uint32_t)
 		}
 	};
 
@@ -173,14 +172,14 @@ int ts_snapshot_create(void)
 				struct ts_ref *r = ts_reftable_map(&tss.rt, k->file);
 
 				if (count % 10000 == 0) {
-					printf("(dump) %020llu.snap %.3fM processed\r",
+					printf("( >> ) %020llu.snap %.3fM processed\r",
 						   (unsigned long long) snap_lsn,
 						   (float)count / 1000000);
 					fflush(stdout);
 				}
 				count++;
 
-				/* first, check if key hash a data */
+				/* first, check if key has a data */
 				if (k->flags & TS_KEY_WITH_DATA) {
 					uint32_t size = *(uint32_t*)(k->key + space->key_size);
 
diff --git a/client/tarantool_snap/space.c b/client/tarantool_snap/space.c
index bc7435a3cb..3e9513010e 100644
--- a/client/tarantool_snap/space.c
+++ b/client/tarantool_snap/space.c
@@ -278,6 +278,7 @@ ts_space_keyalloc_sparse(struct ts_space *s, struct tnt_tuple *t, int fileid,
 	struct ts_key *k = malloc(size);
 	if (k == NULL)
 		return NULL;
+	memset(k, 0, size);
 	k->file = fileid;
 	k->offset = offset;
 	k->flags = 0;
diff --git a/client/tarantool_snap/ts.h b/client/tarantool_snap/ts.h
index 7e468e80a7..4ef3369cf3 100644
--- a/client/tarantool_snap/ts.h
+++ b/client/tarantool_snap/ts.h
@@ -5,7 +5,6 @@ struct ts {
 	struct ts_options opts;
 	struct ts_spaces s;
 	struct ts_reftable rt;
-	struct ts_region rup;
 	uint64_t last_snap_lsn;
 	uint64_t last_xlog_lsn;
 };
diff --git a/client/tarantool_snap/update.cc b/client/tarantool_snap/update.cc
index e61fca2ac2..a909cb1fe1 100644
--- a/client/tarantool_snap/update.cc
+++ b/client/tarantool_snap/update.cc
@@ -51,48 +51,54 @@ extern "C" {
 #include "space.h"
 #include "sha1.h"
 #include "ref.h"
-#include "region.h"
 #include "ts.h"
 #include "indexate.h"
 
 extern struct ts tss;
 
+static inline void*
+_alloc(void *arg, unsigned int size) {
+	(void)arg;
+	return malloc(size);
+}
+
 struct tnt_tuple*
 ts_update(struct tnt_request *r, struct tnt_tuple *old)
 {
+	void *buf = NULL;
 	uint32_t new_size = 0;
 	uint32_t new_count = 0;
+	try {
+		struct tuple_update *u =
+			tuple_update_prepare((region_alloc_func)_alloc, NULL,
+                                 (const char*)(r->r.update.ops),
+                                 (const char*)(r->r.update.ops + r->r.update.ops_size),
+                                 (const char*)(old->data + sizeof(uint32_t)),
+                                 (const char*)(old->data + sizeof(uint32_t) + old->size - sizeof(uint32_t)),
+                                 old->cardinality,
+                                 &new_size,
+                                 &new_count);
+		if (u == NULL)
+			return NULL;
 
-	char *data = old->data + sizeof(uint32_t);
-	struct tuple_update *u =
-		tuple_update_prepare((region_alloc_func)ts_region_alloc, &tss.rup,
-		                     (const char*)(r->r.update.ops),
-		                     (const char*)(r->r.update.ops + r->r.update.ops_size),
-		                     (const char*)(data),
-		                     (const char*)(data + old->size - sizeof(uint32_t)),
-		                     old->cardinality,
-		                     &new_size,
-		                     &new_count);
-	if (u == NULL)
-		return NULL;
-
-	new_size += sizeof(uint32_t);
-
-	void *buf = tnt_mem_alloc(new_size);
-	if (buf == NULL) {
-		ts_region_reset(&tss.rup);
-		return NULL;
-	}
+		buf = tnt_mem_alloc(new_size);
+		if (buf == NULL) {
+			/* reset pool */
+			return NULL;
+		}
+		memset(buf, 0, new_size);
 
-	try {
-		tuple_update_execute(u, (char*)buf + sizeof(uint32_t));
+		tuple_update_execute(u, (char*)buf);
 	} catch (const Exception&) {
-		free(buf);
-		ts_region_reset(&tss.rup);
+		if (buf)
+			free(buf);
+		/* reset pool */
+		fflush(NULL);
+		printf("update failed\n");
 		return NULL;
 	}
 
-	ts_region_reset(&tss.rup);
+	/* reset pool */
 	struct tnt_tuple *n = tnt_tuple_set_as(NULL, buf, new_size, new_count);
 	if (n == NULL) {
 		free(buf);
diff --git a/connector/c/tnt/tnt_request.c b/connector/c/tnt/tnt_request.c
index 59077f59c0..42e4a0f294 100644
--- a/connector/c/tnt/tnt_request.c
+++ b/connector/c/tnt/tnt_request.c
@@ -309,7 +309,7 @@ tnt_request_update(struct tnt_request *r, tnt_request_t rcv, void *ptr)
 	/* initializing tuple */
 	if (tnt_tuple_set(&r->r.update.t, buf, ks) == NULL)
 		goto error;
-	size -= ks - 4;
+	size -= ks /*- 4 */;
 
 	/* ops data */
 	r->r.update.opc = *(uint32_t*)(buf + ks);
@@ -320,14 +320,14 @@ tnt_request_update(struct tnt_request *r, tnt_request_t rcv, void *ptr)
 	memset(r->r.update.opv, 0, sizeof(opvsz));
 
 	/* allocating ops buffer */
-	r->r.update.ops_size = 0;
+	r->r.update.ops_size = 4;
 	r->r.update.ops = tnt_mem_alloc(size);
 	if (r->r.update.ops == NULL)
 		goto error;
-	memcpy(r->r.update.ops, buf + ks + 4, size);
+	memcpy(r->r.update.ops, buf + ks /*+ 4*/, size);
 
 	/* parsing operations */
-	char *p = r->r.update.ops;
+	char *p = r->r.update.ops + 4;
 	for (i = 0 ; i < r->r.update.opc ; i++) {
 		struct tnt_request_update_op *op = &r->r.update.opv[i];
 		/* field */
-- 
GitLab