[Tarantool-patches] [DRAFT v2] replication: track information about replica

Cyrill Gorcunov gorcunov at gmail.com
Mon Jul 6 17:26:54 MSK 2020


On Thu, Jul 02, 2020 at 11:21:41PM +0300, Sergey Kaplun wrote:
> This is a draft for the patch.
> The patch allows to track information about changing relay state. At
> every change of relay state timestamp, vclock, new state (and error
> message if exists) will be saved at _cluster space.
> 
> The patch adds trigger list at relay, that is invoked when relay changes
> its state.  The trigger that updates _cluster space is setted when a
> replica is registered.
> ---
> 
> This is a draft for the patch. Nevertheless I would like to hear as much
> criticism as possible. Also it's important for me to hear @kostja's
> opinion here.
> 
> Originaly the task splits into the parts [1]:
> 
> 1) Pass extra info from downstreams (box.info.listen) to be saved on
> master. Persist it on master.
> 2) Persist last status change with its timestamp and vclock on master
> for each downstream.
> 
> This patch is the second part.
> 
> As we've discussed with Alexander Turenko, there are several ways how
> the first part can be implemented:
> 
> 1) Use additional bytes inside greeting to transport information to
> master. The bad thing is that greeting is about authorization, not the
> additional information.
> 
> 2) Add a new type of the request (eg IPROTO_INFO). An instance receiving
> such a request should provide information about itself. So far, this is
> only one field yet. Is it reasonable to add new protocol fields for one
> feature?
> 
> Thoughts?
> 
> [1]: https://github.com/tarantool/tarantool/issues/3363#issuecomment-622382549
> 
> Branch: https://github.com/tarantool/tarantool/tree/skaplun/gh-3363-track-replica-status-change
> Issue: https://github.com/tarantool/tarantool/issues/3363

Sergey, here is some update on top of this patch I would make.
Look I'm still thinking about the code architecture in general
so please give me some more time. Still just to share early
(completely untested of course :)
---
 src/box/alter.cc     |   51 +++++++++++++++++++++++++++++++--------------------
 src/box/box.cc       |    6 +++---
 src/box/relay.cc     |   17 +++++++----------
 src/box/schema_def.h |    5 +++++
 4 files changed, 46 insertions(+), 33 deletions(-)

Index: tarantool.git/src/box/alter.cc
===================================================================
--- tarantool.git.orig/src/box/alter.cc
+++ tarantool.git/src/box/alter.cc
@@ -4172,51 +4172,62 @@ relay_on_state_change(struct trigger *tr
 {
 	struct relay *relay = (struct relay *)event;
 	(void)trigger;
+
 	if (relay_get_state(relay) == RELAY_OFF)
 		return 0;
+
 	struct replica *replica = relay_replica(relay);
 	const struct tt_uuid *uuid = &replica->uuid;
+
 	assert(replica_by_uuid(uuid) != NULL);
 	assert(replica->id != REPLICA_ID_NIL);
+
 	struct credentials *orig_credentials = effective_user();
 	fiber_set_user(fiber(), &admin_credentials);
-	int rc;
-	if ((rc = boxk(IPROTO_UPDATE, BOX_CLUSTER_ID, "[%u]["
-		 "[%s%u%lf]" /* last row time */
-		 "[%s%u%s]" /* vclock */
-		 "[%s%u%s]" /* relay state */
-		 "]",
-		 (unsigned) replica->id,
-		 "=", 3, relay_last_row_time(relay),
-		 "=", 4, vclock_to_string(relay_vclock(relay)),
-		 "=", 5, relay_get_state_str(relay)
-		)) != 0) {
+
+	const char *vclock_str = vclock_to_string(relay_vclock(relay));
+	const char *state_str = relay_get_state_str(relay);
+	double timestamp = relay_last_row_time(relay);
+
+	int rc = boxk(IPROTO_UPDATE, BOX_CLUSTER_ID, "[%u]["
+		      "[%s%u%lf]"
+		      "[%s%u%s]"
+		      "[%s%u%s]"
+		      "]",
+		      (unsigned) replica->id,
+		      "=", BOX_CLUSTER_FIELD_LAST_ROW_TIME, timestamp,
+		      "=", BOX_CLUSTER_FIELD_VCLOCK, vclock_str,
+		      "=", BOX_CLUSTER_FIELD_RELAY_STATE, state_str);
+	if (rc != 0)
 		goto restore_cred;
-	}
+
+
 	switch (relay_get_state(relay)) {
 	case RELAY_STOPPED: {
-		struct error *e =
-			diag_last_error(relay_get_diag(relay));
-		if (e != NULL)
+		struct *diag = relay_get_diag(relay);
+		struct error *e = diag_last_error(diag);
+		if (e != NULL) {
 			rc = boxk(IPROTO_UPDATE, BOX_CLUSTER_ID,
 				 "[%u][[%s%u%s]]",
 				 (unsigned) replica->id,
-				 "=", 6, e->errmsg);
+				 "=", BOX_CLUSTER_FIELD_RELAY_ERR,
+				 e->errmsg);
+		}
 		break;
 	}
 	case RELAY_FOLLOW:
 		rc = boxk(IPROTO_UPDATE, BOX_CLUSTER_ID,
 			 "[%u][[%s%uNIL]]",
-			 (unsigned) replica->id, "=", 6);
+			 (unsigned) replica->id,
+			 "=", BOX_CLUSTER_FIELD_RELAY_ERR);
 		break;
 	default:
 		unreachable();
 	}
+
 restore_cred:
 	fiber_set_user(fiber(), orig_credentials);
-	if (rc != 0)
-		return -1;
-	return 0;
+	return rc;
 }
 
 static inline void
Index: tarantool.git/src/box/box.cc
===================================================================
--- tarantool.git.orig/src/box/box.cc
+++ tarantool.git/src/box/box.cc
@@ -1476,8 +1476,8 @@ box_session_push(const char *data, const
 	return rc;
 }
 
-static inline void
-box_register_replica(uint32_t id, const struct tt_uuid *uuid)
+static void
+box_register_replica_xc(uint32_t id, const struct tt_uuid *uuid)
 {
 	if (boxk(IPROTO_INSERT, BOX_CLUSTER_ID, "["
 		 "%u" /* replica id */
@@ -1524,7 +1524,7 @@ box_on_join(const tt_uuid *instance_uuid
 			break;
 		replica_id++;
 	}
-	box_register_replica(replica_id, instance_uuid);
+	box_register_replica_xc(replica_id, instance_uuid);
 }
 
 void
Index: tarantool.git/src/box/relay.cc
===================================================================
--- tarantool.git.orig/src/box/relay.cc
+++ tarantool.git/src/box/relay.cc
@@ -153,16 +153,13 @@ struct relay {
 const char *
 relay_get_state_str(const struct relay *relay)
 {
-	switch(relay->state) {
-	case RELAY_OFF:
-		return "off";
-	case RELAY_FOLLOW:
-		return "follow";
-	case RELAY_STOPPED:
-		return "stopped";
-	default:
-		return "<unknown relay state>";
-	}
+	static const char *st[] = {
+		[RELAY_OFF]	= "off",
+		[RELAY_FOLLOW]	= "follow",
+		[RELAY_STOPPED]	= "stopped",
+	};
+	return relay->state < lengthof(st) ?
+		st[relay->state] : "unknown";
 }
 
 static inline void
Index: tarantool.git/src/box/schema_def.h
===================================================================
--- tarantool.git.orig/src/box/schema_def.h
+++ tarantool.git/src/box/schema_def.h
@@ -206,6 +206,11 @@ enum {
 enum {
 	BOX_CLUSTER_FIELD_ID = 0,
 	BOX_CLUSTER_FIELD_UUID = 1,
+	BOX_CLUSTER_FIELD_HOST_PORT = 2,
+	BOX_CLUSTER_FIELD_RELAY_TIMESTAMP = 3,
+	BOX_CLUSTER_FIELD_RELAY_VCLOCK = 4,
+	BOX_CLUSTER_FIELD_RELAY_STATE = 5,
+	BOX_CLUSTER_FIELD_RELAY_ERR = 6,
 };
 
 /** _truncate fields. */


More information about the Tarantool-patches mailing list