From 225374e5fd28d96f2bff6e68d7d028033af9b534 Mon Sep 17 00:00:00 2001
From: Roman Tsisyk <roman@tsisyk.com>
Date: Wed, 3 Sep 2014 18:34:34 +0400
Subject: [PATCH] Fix #484: JOIN doesn't save data to snapshot

1. snapshot_save calls snapshot_space
2. snapshot_space uses index->initIterator()
3. initIterator() doesn't work until endBuild() is called
4. index->endBuild() is called by space_end_recover_snapshot()
   *after* snapshot_save()
=> Replica doesn't save some tuples into snapshot on JOIN

This patch changes space_end_recover_snapshot() order.
---
 src/box/box.cc                        |  5 ++--
 test/replication/init_storage.result  | 33 ++++++++++++++++++++++++---
 test/replication/init_storage.test.py | 29 +++++++++++++++++++----
 3 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/src/box/box.cc b/src/box/box.cc
index 1a61f5cb6e..20d6dffcd8 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -405,20 +405,21 @@ box_init()
 	if (recovery_has_data(recovery)) {
 		/* Process existing snapshot */
 		recover_snap(recovery);
+		space_end_recover_snapshot();
 	} else if (recovery_has_remote(recovery)) {
 		/* Initialize a new replica */
 		replica_bootstrap(recovery);
+		space_end_recover_snapshot();
 		snapshot_save(recovery);
 	} else {
 		/* Initialize the first server of a new cluster */
 		recovery_bootstrap(recovery);
 		box_set_cluster_uuid();
 		box_set_server_uuid();
+		space_end_recover_snapshot();
 		snapshot_save(recovery);
 	}
 
-	space_end_recover_snapshot();
-
 	title("orphan", NULL);
 	recovery_follow_local(recovery,
 			      cfg_getd("wal_dir_rescan_delay"));
diff --git a/test/replication/init_storage.result b/test/replication/init_storage.result
index 4b4e01d1b8..1e57498026 100644
--- a/test/replication/init_storage.result
+++ b/test/replication/init_storage.result
@@ -4,7 +4,7 @@ box.schema.user.grant('guest', 'read,write,execute', 'universe')
 space = box.schema.create_space('test', {id =  42})
 ---
 ...
-space:create_index('primary', { type = 'hash'})
+space:create_index('primary', { type = 'tree'})
 ---
 ...
 for k = 1, 9 do space:insert{k, k*k} end
@@ -17,16 +17,43 @@ box.space.test
 ---
 - null
 ...
+-------------------------------------------------------------
+replica JOIN
+-------------------------------------------------------------
 box.snapshot()
 ---
 - ok
 ...
-for k = 10, 19 do box.space[42]:insert{k, k*k*k} end
----
+box.space.test:select()
+---
+- - [1, 1]
+  - [2, 4]
+  - [3, 9]
+  - [4, 16]
+  - [5, 25]
+  - [6, 36]
+  - [7, 49]
+  - [8, 64]
+  - [9, 81]
+...
+box.space.test:select()
+---
+- - [1, 1]
+  - [2, 4]
+  - [3, 9]
+  - [4, 16]
+  - [5, 25]
+  - [6, 36]
+  - [7, 49]
+  - [8, 64]
+  - [9, 81]
 ...
 -------------------------------------------------------------
 replica test 2 (must be ok)
 -------------------------------------------------------------
+for k = 10, 19 do box.space[42]:insert{k, k*k*k} end
+---
+...
 space = box.space.test
 ---
 ...
diff --git a/test/replication/init_storage.test.py b/test/replication/init_storage.test.py
index d623b5eb6f..e7049c89a2 100644
--- a/test/replication/init_storage.test.py
+++ b/test/replication/init_storage.test.py
@@ -4,10 +4,11 @@ from lib.tarantool_server import TarantoolServer
 
 # master server
 master = server
+master_id = master.get_param('server')['id']
 
 master.admin("box.schema.user.grant('guest', 'read,write,execute', 'universe')")
 master.admin("space = box.schema.create_space('test', {id =  42})")
-master.admin("space:create_index('primary', { type = 'hash'})")
+master.admin("space:create_index('primary', { type = 'tree'})")
 
 master.admin('for k = 1, 9 do space:insert{k, k*k} end')
 
@@ -29,15 +30,35 @@ replica.admin('box.space.test')
 replica.stop()
 replica.cleanup(True)
 
+print '-------------------------------------------------------------'
+print 'replica JOIN'
+print '-------------------------------------------------------------'
+
 master.admin('box.snapshot()')
 master.restart()
-master.admin('for k = 10, 19 do box.space[42]:insert{k, k*k*k} end')
-master_id = master.get_param('server')['id']
-lsn = master.get_lsn(master_id)
+
+replica.deploy()
+replica.wait_lsn(master_id, master.get_lsn(master_id))
+replica.admin('box.space.test:select()')
+
+#
+# gh-484: JOIN doesn't save data to snapshot with TREE index
+#
+
+replica.restart()
+
+replica.admin('box.space.test:select()')
+replica.stop()
+replica.cleanup(True)
+
 print '-------------------------------------------------------------'
 print 'replica test 2 (must be ok)'
 print '-------------------------------------------------------------'
 
+master.restart()
+master.admin('for k = 10, 19 do box.space[42]:insert{k, k*k*k} end')
+lsn = master.get_lsn(master_id)
+
 replica = TarantoolServer(server.ini)
 replica.script = 'replication/replica.lua'
 replica.vardir = os.path.join(server.vardir, 'replica')
-- 
GitLab