[PATCH] hot_standby: reflect amount of recovered rows in box.info

Serge Petrenko sergepetrenko at tarantool.org
Tue Oct 23 18:15:40 MSK 2018


To be able to switch to hot_standby instance with minimal downtime, we
need to know how far is it behind the primary instance, i.e. up to what
vclock we have recovered. Previously this was impossible because
box.info.vclock always referenced replicaset.vclock, which isn't updated
during hot_standby.
Introduce a pointer to relevant vclock: either recovery vclock (during
local recovery) or replicaset.vclock (at all other times) and use it in
box.info.vclock, box.info.lsn and box.info.signature.

Closes #3002
---
https://github.com/tarantool/tarantool/issues/3002
https://github.com/tarantool/tarantool/tree/sp/gh-3002-hot-standby-vclock

 src/box/box.cc                        | 12 +++++++++++-
 src/box/box.h                         |  7 +++++++
 src/box/lua/info.c                    |  6 +++---
 test/replication/hot_standby.result   | 26 ++++++++++++++++++++++++++
 test/replication/hot_standby.test.lua | 10 ++++++++++
 5 files changed, 57 insertions(+), 4 deletions(-)

diff --git a/src/box/box.cc b/src/box/box.cc
index c32f731b0..448fe3dcc 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -138,6 +138,8 @@ static struct fiber_pool tx_fiber_pool;
  */
 static struct cbus_endpoint tx_prio_endpoint;
 
+struct vclock *last_row_vclock = &replicaset.vclock;
+
 static int
 box_check_writable(void)
 {
@@ -1903,7 +1905,15 @@ local_recovery(const struct tt_uuid *instance_uuid,
 	recovery = recovery_new(cfg_gets("wal_dir"),
 				cfg_geti("force_recovery"),
 				checkpoint_vclock);
-	auto guard = make_scoped_guard([=]{ recovery_delete(recovery); });
+	/*
+	 * Update last_row_vclock to show in box.info.vclock
+	 * during recovery.
+	 */
+	last_row_vclock = &recovery->vclock;
+	auto guard = make_scoped_guard([&]{
+		last_row_vclock = &replicaset.vclock;
+		recovery_delete(recovery);
+	});
 
 	/*
 	 * Initialize the replica set vclock from recovery.
diff --git a/src/box/box.h b/src/box/box.h
index e46adb89b..539693695 100644
--- a/src/box/box.h
+++ b/src/box/box.h
@@ -51,6 +51,7 @@ struct obuf;
 struct ev_io;
 struct auth_request;
 struct space;
+struct vclock;
 
 /*
  * Initialize box library
@@ -117,6 +118,12 @@ extern bool box_checkpoint_is_in_progress;
 /** Incremented with each next snapshot. */
 extern uint32_t snapshot_version;
 
+/**
+ * A pointer to either recovery vclock (during recovery) or
+ * replicaset.vclock.
+ */
+extern struct vclock *last_row_vclock;
+
 /**
  * Iterate over all spaces and save them to the
  * snapshot file.
diff --git a/src/box/lua/info.c b/src/box/lua/info.c
index 655768ec4..59322e504 100644
--- a/src/box/lua/info.c
+++ b/src/box/lua/info.c
@@ -229,7 +229,7 @@ lbox_info_lsn(struct lua_State *L)
 	/* See comments in lbox_info_id */
 	struct replica *self = replica_by_uuid(&INSTANCE_UUID);
 	if (self != NULL && self->id != REPLICA_ID_NIL) {
-		luaL_pushint64(L, vclock_get(&replicaset.vclock, self->id));
+		luaL_pushint64(L, vclock_get(last_row_vclock, self->id));
 	} else {
 		luaL_pushint64(L, -1);
 	}
@@ -239,7 +239,7 @@ lbox_info_lsn(struct lua_State *L)
 static int
 lbox_info_signature(struct lua_State *L)
 {
-	luaL_pushint64(L, vclock_sum(&replicaset.vclock));
+	luaL_pushint64(L, vclock_sum(last_row_vclock));
 	return 1;
 }
 
@@ -275,7 +275,7 @@ lbox_info_server(struct lua_State *L)
 static int
 lbox_info_vclock(struct lua_State *L)
 {
-	lbox_pushvclock(L, &replicaset.vclock);
+	lbox_pushvclock(L, last_row_vclock);
 	return 1;
 }
 
diff --git a/test/replication/hot_standby.result b/test/replication/hot_standby.result
index 24be0a94f..e72254f91 100644
--- a/test/replication/hot_standby.result
+++ b/test/replication/hot_standby.result
@@ -151,6 +151,24 @@ a:call('_set_pri_lsn', {box.info.id, box.info.lsn})
 a:close()
 ---
 ...
+test_run:cmd("switch hot_standby")
+---
+- true
+...
+test_run:wait_lsn("hot_standby", "default")
+---
+...
+_set_pri_lsn(box.info.id, box.info.lsn)
+---
+...
+_print_lsn()
+---
+- 1
+...
+test_run:cmd("switch default")
+---
+- true
+...
 _insert(1, 10)
 ---
 - - [1, 'the tuple 1']
@@ -177,6 +195,14 @@ _select(1, 10)
   - [9, 'the tuple 9']
   - [10, 'the tuple 10']
 ...
+-- Check box.info.vclock is updated during hot standby.
+test_run:cmd("switch hot_standby")
+---
+- true
+...
+_wait_lsn(10)
+---
+...
 test_run:cmd("switch replica")
 ---
 - true
diff --git a/test/replication/hot_standby.test.lua b/test/replication/hot_standby.test.lua
index adb3fb6fa..1842ff39a 100644
--- a/test/replication/hot_standby.test.lua
+++ b/test/replication/hot_standby.test.lua
@@ -80,9 +80,19 @@ a = (require 'net.box').connect(REPLICA.host, REPLICA.service)
 a:call('_set_pri_lsn', {box.info.id, box.info.lsn})
 a:close()
 
+test_run:cmd("switch hot_standby")
+test_run:wait_lsn("hot_standby", "default")
+_set_pri_lsn(box.info.id, box.info.lsn)
+_print_lsn()
+
+test_run:cmd("switch default")
 _insert(1, 10)
 _select(1, 10)
 
+-- Check box.info.vclock is updated during hot standby.
+test_run:cmd("switch hot_standby")
+_wait_lsn(10)
+
 test_run:cmd("switch replica")
 _wait_lsn(10)
 _select(1, 10)
-- 
2.17.1 (Apple Git-112)




More information about the Tarantool-patches mailing list