Tarantool development patches archive
 help / color / mirror / Atom feed
* [tarantool-patches] [box.ctl 0/3] Introduce box.ctl.on_ctl_event trigger
@ 2018-06-14 15:04 Ilya Markov
  2018-06-14 15:04 ` [tarantool-patches] [box.ctl 1/3] box.ctl: Introduce stab box.ctl.on_ctl_event Ilya Markov
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Ilya Markov @ 2018-06-14 15:04 UTC (permalink / raw)
  To: georgy; +Cc: tarantool-patches



Ilya Markov (3):
  box.ctl: Introduce stab box.ctl.on_ctl_event
  box.ctl: Add on_ctl_event trigger calls
  box.ctl: Add replica error event

branch: gh-3159-box-on-ctl-event 

 src/box/CMakeLists.txt             |   1 +
 src/box/alter.cc                   |   1 +
 src/box/box.cc                     |  53 +++++++-
 src/box/box.h                      |   1 +
 src/box/ctl.c                      |  63 +++++++++
 src/box/ctl.h                      |  82 ++++++++++++
 src/box/engine.c                   |  14 ++
 src/box/lua/cfg.cc                 |  12 ++
 src/box/lua/ctl.c                  |  55 ++++++++
 src/box/lua/ctl.h                  |   2 +
 src/box/lua/load_cfg.lua           |  10 +-
 src/box/memtx_engine.c             |   2 +-
 src/box/relay.cc                   |   7 +
 src/box/replication.cc             |  14 ++
 src/cfg.c                          |  37 ++++++
 src/cfg.h                          |   4 +
 test/replication/master_onctl.lua  |  37 ++++++
 test/replication/onctl.result      | 262 +++++++++++++++++++++++++++++++++++++
 test/replication/onctl.test.lua    | 108 +++++++++++++++
 test/replication/replica_onctl.lua |  34 +++++
 test/replication/suite.cfg         |   1 +
 21 files changed, 796 insertions(+), 4 deletions(-)
 create mode 100644 src/box/ctl.c
 create mode 100644 src/box/ctl.h
 create mode 100644 test/replication/master_onctl.lua
 create mode 100644 test/replication/onctl.result
 create mode 100644 test/replication/onctl.test.lua
 create mode 100644 test/replication/replica_onctl.lua

-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] [box.ctl 1/3] box.ctl: Introduce stab box.ctl.on_ctl_event
  2018-06-14 15:04 [tarantool-patches] [box.ctl 0/3] Introduce box.ctl.on_ctl_event trigger Ilya Markov
@ 2018-06-14 15:04 ` Ilya Markov
  2018-07-31 11:40   ` [tarantool-patches] " Konstantin Belyavskiy
  2018-06-14 15:04 ` [tarantool-patches] [box.ctl 2/3] box.ctl: Add on_ctl_event trigger calls Ilya Markov
  2018-06-14 15:04 ` [tarantool-patches] [box.ctl 3/3] box.ctl: Add replica error event Ilya Markov
  2 siblings, 1 reply; 7+ messages in thread
From: Ilya Markov @ 2018-06-14 15:04 UTC (permalink / raw)
  To: georgy; +Cc: tarantool-patches

Add required for trigger on_ctl_event
structures and lua bindings.

Prerequisite #3259
---
 src/box/CMakeLists.txt   |  1 +
 src/box/box.cc           |  9 ++++++
 src/box/box.h            |  1 +
 src/box/ctl.c            | 63 +++++++++++++++++++++++++++++++++++++
 src/box/ctl.h            | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/box/lua/cfg.cc       | 12 +++++++
 src/box/lua/ctl.c        | 51 ++++++++++++++++++++++++++++++
 src/box/lua/ctl.h        |  2 ++
 src/box/lua/load_cfg.lua | 10 +++++-
 src/cfg.c                | 37 ++++++++++++++++++++++
 src/cfg.h                |  4 +++
 11 files changed, 270 insertions(+), 1 deletion(-)
 create mode 100644 src/box/ctl.c
 create mode 100644 src/box/ctl.h

diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 6b1ae3e..74f6b54 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -112,6 +112,7 @@ add_library(box STATIC
     journal.c
     wal.c
     call.c
+    ctl.c
     ${lua_sources}
     lua/init.c
     lua/call.c
diff --git a/src/box/box.cc b/src/box/box.cc
index 61bfa11..26277e7 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -72,6 +72,7 @@
 #include "call.h"
 #include "func.h"
 #include "sequence.h"
+#include "ctl.h"
 
 static char status[64] = "unknown";
 
@@ -823,6 +824,13 @@ box_set_net_msg_max(void)
 				IPROTO_FIBER_POOL_SIZE_FACTOR);
 }
 
+void
+box_set_on_ctl_event(void)
+{
+	if (cfg_reset_on_ctl_event() < 0)
+		diag_raise();
+}
+
 /* }}} configuration bindings */
 
 /**
@@ -1808,6 +1816,7 @@ box_cfg_xc(void)
 	box_set_replication_connect_timeout();
 	box_set_replication_connect_quorum();
 	box_set_replication_skip_conflict();
+	box_set_on_ctl_event();
 	replication_sync_lag = box_check_replication_sync_lag();
 	xstream_create(&join_stream, apply_initial_join_row);
 	xstream_create(&subscribe_stream, apply_row);
diff --git a/src/box/box.h b/src/box/box.h
index d396789..0325527 100644
--- a/src/box/box.h
+++ b/src/box/box.h
@@ -191,6 +191,7 @@ void box_set_replication_connect_timeout(void);
 void box_set_replication_connect_quorum(void);
 void box_set_replication_skip_conflict(void);
 void box_set_net_msg_max(void);
+void box_set_on_ctl_event(void);
 
 extern "C" {
 #endif /* defined(__cplusplus) */
diff --git a/src/box/ctl.c b/src/box/ctl.c
new file mode 100644
index 0000000..fc3ae37
--- /dev/null
+++ b/src/box/ctl.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010-2018, Tarantool AUTHORS, please see AUTHORS file.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <lib/small/small/rlist.h>
+#include <trigger.h>
+#include <box/ctl.h>
+#include "errcode.h"
+#include "error.h"
+#include <exception.h>
+
+RLIST_HEAD(on_ctl_event);
+
+int
+run_on_ctl_event_triggers(const struct on_ctl_event_ctx *result) {
+	return trigger_run(&on_ctl_event, (void *) result);
+}
+
+int
+run_on_ctl_event_trigger_type(enum ctl_event_type type)
+{
+	struct on_ctl_event_ctx ctx = {};
+	ctx.type = type;
+	return run_on_ctl_event_triggers(&ctx);
+}
+
+int
+cfg_reset_on_ctl_event()
+{
+	if (cfg_reset_trigger("on_ctl_event", &on_ctl_event,
+		lbox_push_on_ctl_event, NULL) < 0) {
+		diag_set(ClientError, ER_CFG, "on_ctl_event",
+			 "expected function or table");
+		return -1;
+	}
+	return 0;
+}
\ No newline at end of file
diff --git a/src/box/ctl.h b/src/box/ctl.h
new file mode 100644
index 0000000..1dbb6be
--- /dev/null
+++ b/src/box/ctl.h
@@ -0,0 +1,81 @@
+#ifndef INCLUDES_TARANTOOL_CTL_H
+#define INCLUDES_TARANTOOL_CTL_H
+
+/*
+ * Copyright 2010-2018, Tarantool AUTHORS, please see AUTHORS file.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the
+ *    following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <cfg.h>
+#include <box/lua/ctl.h>
+#include "errcode.h"
+#include "error.h"
+#include <exception.h>
+
+/** Global on-ctl_event triggers. */
+extern struct rlist on_ctl_event;
+
+enum ctl_event_type {
+	CTL_EVENT_SYSTEM_SPACE_RECOVERY,
+	CTL_EVENT_LOCAL_RECOVERY,
+	CTL_EVENT_READ_ONLY,
+	CTL_EVENT_READ_WRITE,
+	CTL_EVENT_SHUTDOWN,
+	CTL_EVENT_REPLICASET_ADD,
+	CTL_EVENT_REPLICASET_REMOVE,
+};
+
+struct on_ctl_event_ctx {
+	enum ctl_event_type type;
+	uint32_t replica_id;
+};
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+/**
+ * Runs on_ctl_event triggers with specified context.
+ */
+int
+run_on_ctl_event_triggers(const struct on_ctl_event_ctx *result);
+
+/**
+ * Runs on_ctl_event triggers with specified type.
+ */
+int
+run_on_ctl_event_trigger_type(enum ctl_event_type type);
+
+int
+cfg_reset_on_ctl_event();
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+#endif /* INCLUDES_TARANTOOL_LUA_CTL_H */
diff --git a/src/box/lua/cfg.cc b/src/box/lua/cfg.cc
index 5afebc9..c92478f 100644
--- a/src/box/lua/cfg.cc
+++ b/src/box/lua/cfg.cc
@@ -254,6 +254,17 @@ lbox_cfg_set_net_msg_max(struct lua_State *L)
 }
 
 static int
+lbox_cfg_set_on_ctl_event(struct lua_State *L)
+{
+	try {
+		box_set_on_ctl_event();
+	} catch (Exception *) {
+		luaT_error(L);
+	}
+	return 0;
+}
+
+static int
 lbox_cfg_set_worker_pool_threads(struct lua_State *L)
 {
 	(void) L;
@@ -331,6 +342,7 @@ box_lua_cfg_init(struct lua_State *L)
 		{"cfg_set_replication_skip_conflict", lbox_cfg_set_replication_skip_conflict},
 		{"cfg_set_replication_connect_timeout", lbox_cfg_set_replication_connect_timeout},
 		{"cfg_set_net_msg_max", lbox_cfg_set_net_msg_max},
+		{"cfg_set_on_ctl_event", lbox_cfg_set_on_ctl_event},
 		{NULL, NULL}
 	};
 
diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
index 9a105ed..52f320a 100644
--- a/src/box/lua/ctl.c
+++ b/src/box/lua/ctl.c
@@ -35,6 +35,8 @@
 #include <lua.h>
 #include <lauxlib.h>
 #include <lualib.h>
+#include <lua/trigger.h>
+#include <box/ctl.h>
 
 #include "lua/utils.h"
 
@@ -64,9 +66,37 @@ lbox_ctl_wait_rw(struct lua_State *L)
 	return 0;
 }
 
+
+int
+lbox_push_on_ctl_event(struct lua_State *L, void *event)
+{
+	struct on_ctl_event_ctx *ctx = (struct on_ctl_event_ctx *) event;
+	lua_newtable(L);
+	lua_pushstring(L, "type");
+	lua_pushinteger(L, ctx->type);
+	lua_settable(L, -3);
+
+	if (ctx->type == CTL_EVENT_REPLICASET_ADD ||
+		ctx->type == CTL_EVENT_REPLICASET_REMOVE) {
+		lua_pushstring(L, "replica_id");
+		luaL_pushuint64(L, ctx->replica_id);
+		lua_settable(L, -3);
+	}
+	return 1;
+}
+
+static int
+lbox_on_ctl_event(struct lua_State *L)
+{
+	return lbox_trigger_reset(L, 2, &on_ctl_event,
+				  lbox_push_on_ctl_event, NULL);
+}
+
+
 static const struct luaL_Reg lbox_ctl_lib[] = {
 	{"wait_ro", lbox_ctl_wait_ro},
 	{"wait_rw", lbox_ctl_wait_rw},
+	{"on_ctl_event", lbox_on_ctl_event},
 	{NULL, NULL}
 };
 
@@ -75,4 +105,25 @@ box_lua_ctl_init(struct lua_State *L)
 {
 	luaL_register_module(L, "box.ctl", lbox_ctl_lib);
 	lua_pop(L, 1);
+
+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.ctl", 1);
+	lua_newtable(L);
+	lua_setfield(L, -2, "event");
+	lua_getfield(L, -1, "event");
+
+	lua_pushnumber(L, CTL_EVENT_SYSTEM_SPACE_RECOVERY);
+	lua_setfield(L, -2, "SYSTEM_SPACE_RECOVERY");
+	lua_pushnumber(L, CTL_EVENT_LOCAL_RECOVERY);
+	lua_setfield(L, -2, "LOCAL_RECOVERY");
+	lua_pushnumber(L, CTL_EVENT_READ_ONLY);
+	lua_setfield(L, -2, "READ_ONLY");
+	lua_pushnumber(L, CTL_EVENT_READ_WRITE);
+	lua_setfield(L, -2, "READ_WRITE");
+	lua_pushnumber(L, CTL_EVENT_SHUTDOWN);
+	lua_setfield(L, -2, "SHUTDOWN");
+	lua_pushnumber(L, CTL_EVENT_REPLICASET_ADD);
+	lua_setfield(L, -2, "CTL_EVENT_REPLICASET_ADD");
+	lua_pushnumber(L, CTL_EVENT_REPLICASET_REMOVE);
+	lua_setfield(L, -2, "CTL_EVENT_REPLICASET_REMOVE");
+	lua_pop(L, 2); /* box, ctl */
 }
diff --git a/src/box/lua/ctl.h b/src/box/lua/ctl.h
index e7c2edd..ab63232 100644
--- a/src/box/lua/ctl.h
+++ b/src/box/lua/ctl.h
@@ -41,6 +41,8 @@ struct lua_State;
 void
 box_lua_ctl_init(struct lua_State *L);
 
+int
+lbox_push_on_ctl_event(struct lua_State *L, void *event);
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua
index 0b668cd..c4d1347 100644
--- a/src/box/lua/load_cfg.lua
+++ b/src/box/lua/load_cfg.lua
@@ -1,7 +1,11 @@
 -- load_cfg.lua - internal file
 
 local log = require('log')
-local json = require('json')
+local json = require("json").new()
+json.cfg{
+    encode_use_tostring    = true,
+}
+
 local private = require('box.internal')
 local urilib = require('uri')
 local math = require('math')
@@ -64,6 +68,7 @@ local default_cfg = {
     feedback_host         = "https://feedback.tarantool.io",
     feedback_interval     = 3600,
     net_msg_max           = 768,
+    on_ctl_event          = nil,
 }
 
 -- types of available options
@@ -125,6 +130,7 @@ local template_cfg = {
     feedback_host         = 'string',
     feedback_interval     = 'number',
     net_msg_max           = 'number',
+    on_ctl_event          = 'function, table',
 }
 
 local function normalize_uri(port)
@@ -216,6 +222,7 @@ local dynamic_cfg = {
     replicaset_uuid         = check_replicaset_uuid,
     replication_skip_conflict = private.cfg_set_replication_skip_conflict,
     net_msg_max             = private.cfg_set_net_msg_max,
+    on_ctl_event            = private.cfg_set_on_ctl_event,
 }
 
 local dynamic_cfg_skip_at_load = {
@@ -232,6 +239,7 @@ local dynamic_cfg_skip_at_load = {
     force_recovery          = true,
     instance_uuid           = true,
     replicaset_uuid         = true,
+    on_ctl_event            = true,
 }
 
 local function convert_gb(size)
diff --git a/src/cfg.c b/src/cfg.c
index 7c7d6e7..b07c1f3 100644
--- a/src/cfg.c
+++ b/src/cfg.c
@@ -153,3 +153,40 @@ cfg_getarr_elem(const char *name, int i)
 	lua_pop(tarantool_L, 2);
 	return val;
 }
+
+int
+cfg_reset_trigger(const char *name, struct rlist *list,
+		  lbox_push_event_f push_event, lbox_pop_event_f pop_event)
+{
+	cfg_get(name);
+	struct lua_State *L = tarantool_L;
+	if (lua_isnil(L, -1))
+		return 0;
+	if (!lua_isfunction(L, -1) && !lua_istable(L, -1)) {
+		return -1;
+	}
+	if (lua_istable(L, -1)) {
+		lua_pushinteger(L, 1);
+		lua_gettable(L, -2);
+		if (!luaL_isnull(L, lua_gettop(L)) && !lua_isfunction(L, -1))
+			return -1;
+		bool is_nil = luaL_isnull(L, lua_gettop(L));
+		if (is_nil) {
+			lua_pop(L, 1);
+			lua_pushnil(L);
+		}
+		lua_pushinteger(L, 2);
+		lua_gettable(L, -3);
+		if (!lua_isfunction(L, -1) && !lua_isnil(L, -1))
+			return -1;
+		if (is_nil && lua_isnil(L, -1)) {
+			return 0;
+		}
+	} else {
+		lua_pushnil(L);
+	}
+	int rc = lbox_trigger_reset(L, lua_gettop(L), list,
+				  push_event, pop_event);
+	lua_pop(L, 1);
+	return rc;
+}
\ No newline at end of file
diff --git a/src/cfg.h b/src/cfg.h
index 8499388..d36465c 100644
--- a/src/cfg.h
+++ b/src/cfg.h
@@ -32,6 +32,7 @@
  */
 
 #include <stdint.h>
+#include <lua/trigger.h>
 
 #if defined(__cplusplus)
 extern "C" {
@@ -61,6 +62,9 @@ cfg_getarr_size(const char *name);
 const char *
 cfg_getarr_elem(const char *name, int i);
 
+int
+cfg_reset_trigger(const char *name, struct rlist *list,
+		  lbox_push_event_f push_event, lbox_pop_event_f pop_event);
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] [box.ctl 2/3] box.ctl: Add on_ctl_event trigger calls
  2018-06-14 15:04 [tarantool-patches] [box.ctl 0/3] Introduce box.ctl.on_ctl_event trigger Ilya Markov
  2018-06-14 15:04 ` [tarantool-patches] [box.ctl 1/3] box.ctl: Introduce stab box.ctl.on_ctl_event Ilya Markov
@ 2018-06-14 15:04 ` Ilya Markov
  2018-07-31 11:40   ` [tarantool-patches] " Konstantin Belyavskiy
  2018-06-14 15:04 ` [tarantool-patches] [box.ctl 3/3] box.ctl: Add replica error event Ilya Markov
  2 siblings, 1 reply; 7+ messages in thread
From: Ilya Markov @ 2018-06-14 15:04 UTC (permalink / raw)
  To: georgy; +Cc: tarantool-patches

Add following cases of triggers:
* System space recovery. Called on finish of bootstrap or finish of join or
snapshot recovery.
* Local recovery. Called on finish of bootstrap or finish of recovery.
* Read_only/read_write. Called on changes of read_only state of
instance.
* Shutdown. Called on controlled shutdown.
* Replicaset_add/replicaset_remove. Called on changes in space _cluster.

Errors inside triggers are logged and don't influence on instance
behaviour.

Continue #3159
---
 src/box/alter.cc                   |   1 +
 src/box/box.cc                     |  44 ++++++-
 src/box/engine.c                   |  14 +++
 src/box/lua/ctl.c                  |   4 +-
 src/box/memtx_engine.c             |   2 +-
 src/box/replication.cc             |  14 +++
 test/replication/master_onctl.lua  |  34 +++++
 test/replication/onctl.result      | 250 +++++++++++++++++++++++++++++++++++++
 test/replication/onctl.test.lua    | 105 ++++++++++++++++
 test/replication/replica_onctl.lua |  34 +++++
 test/replication/suite.cfg         |   1 +
 11 files changed, 498 insertions(+), 5 deletions(-)
 create mode 100644 test/replication/master_onctl.lua
 create mode 100644 test/replication/onctl.result
 create mode 100644 test/replication/onctl.test.lua
 create mode 100644 test/replication/replica_onctl.lua

diff --git a/src/box/alter.cc b/src/box/alter.cc
index 6f6fcb0..7ec548b 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -52,6 +52,7 @@
 #include "identifier.h"
 #include "version.h"
 #include "sequence.h"
+#include "ctl.h"
 
 /**
  * chap-sha1 of empty string, i.e.
diff --git a/src/box/box.cc b/src/box/box.cc
index 26277e7..1de37d2 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -113,6 +113,11 @@ static fiber_cond ro_cond;
  */
 static bool is_orphan = true;
 
+/**
+ * Fiber used for on_ctl_event trigger.
+ */
+static fiber *ro_checker;
+
 /* Use the shared instance of xstream for all appliers */
 static struct xstream join_stream;
 static struct xstream subscribe_stream;
@@ -1573,6 +1578,9 @@ box_set_replicaset_uuid(const struct tt_uuid *replicaset_uuid)
 void
 box_free(void)
 {
+	if (run_on_ctl_event_trigger_type(CTL_EVENT_SHUTDOWN) < 0)
+		say_error("ctl_trigger error in shutdown: %s",
+			  diag_last_error(diag_get())->errmsg);
 	/*
 	 * See gh-584 "box_free() is called even if box is not
 	 * initialized
@@ -1592,7 +1600,8 @@ box_free(void)
 		engine_shutdown();
 		wal_thread_stop();
 	}
-
+	if (!fiber_is_dead(ro_checker))
+		fiber_cancel(ro_checker);
 	fiber_cond_destroy(&ro_cond);
 }
 
@@ -1693,6 +1702,10 @@ bootstrap_from_master(struct replica *master)
 	engine_begin_initial_recovery_xc(NULL);
 	applier_resume_to_state(applier, APPLIER_FINAL_JOIN, TIMEOUT_INFINITY);
 
+	if (run_on_ctl_event_trigger_type(CTL_EVENT_SYSTEM_SPACE_RECOVERY) < 0)
+		say_error("ctl_trigger error in system space recovery: %s",
+			  diag_last_error(diag_get())->errmsg);
+
 	/*
 	 * Process final data (WALs).
 	 */
@@ -1755,11 +1768,35 @@ tx_prio_cb(struct ev_loop *loop, ev_watcher *watcher, int events)
 	cbus_process(endpoint);
 }
 
+static int
+check_ro_f(MAYBE_UNUSED va_list ap)
+{
+	double timeout = TIMEOUT_INFINITY;
+	struct on_ctl_event_ctx ctx;
+	memset(&ctx, 0, sizeof(ctx));
+	while (true) {
+		if (box_wait_ro(!box_is_ro(), timeout) != 0) {
+			if (fiber_is_cancelled())
+				break;
+			else
+				return -1;
+		}
+		if (run_on_ctl_event_trigger_type(
+			box_is_ro() ? CTL_EVENT_READ_ONLY:
+					      CTL_EVENT_READ_WRITE) < 0)
+			say_error("ctl_trigger error in %s: %s",
+				  box_is_ro() ? "read_only" :"read_write",
+				  diag_last_error(diag_get())->errmsg);
+	}
+	return 0;
+}
+
 void
 box_init(void)
 {
 	fiber_cond_create(&ro_cond);
-
+	ro_checker = fiber_new_xc("check_ro", check_ro_f);
+	fiber_start(ro_checker, NULL);
 	user_cache_init();
 	/*
 	 * The order is important: to initialize sessions,
@@ -1885,6 +1922,9 @@ box_cfg_xc(void)
 		 */
 		memtx_engine_recover_snapshot_xc(memtx,
 				&last_checkpoint_vclock);
+		if (run_on_ctl_event_trigger_type(CTL_EVENT_SYSTEM_SPACE_RECOVERY) < 0)
+			say_error("ctl_trigger error in system space recovery: %s",
+				  diag_last_error(diag_get())->errmsg);
 
 		engine_begin_final_recovery_xc();
 		recovery_follow_local(recovery, &wal_stream.base, "hot_standby",
diff --git a/src/box/engine.c b/src/box/engine.c
index 82293fd..fa78753 100644
--- a/src/box/engine.c
+++ b/src/box/engine.c
@@ -29,10 +29,12 @@
  * SUCH DAMAGE.
  */
 #include "engine.h"
+#include "ctl.h"
 
 #include <stdint.h>
 #include <string.h>
 #include <small/rlist.h>
+#include <fiber.h>
 
 RLIST_HEAD(engines);
 
@@ -73,6 +75,14 @@ engine_bootstrap(void)
 		if (engine->vtab->bootstrap(engine) != 0)
 			return -1;
 	}
+	if (run_on_ctl_event_trigger_type(CTL_EVENT_SYSTEM_SPACE_RECOVERY) < 0)
+		say_error("ctl_trigger error in system space recovery: %s",
+			  diag_last_error(diag_get())->errmsg);
+
+	if (run_on_ctl_event_trigger_type(CTL_EVENT_LOCAL_RECOVERY) < 0)
+		say_error("ctl_trigger error in local recovery: %s",
+			  diag_last_error(diag_get())->errmsg);
+
 	return 0;
 }
 
@@ -111,6 +121,10 @@ engine_end_recovery(void)
 		if (engine->vtab->end_recovery(engine) != 0)
 			return -1;
 	}
+	if (run_on_ctl_event_trigger_type(CTL_EVENT_LOCAL_RECOVERY) < 0)
+		say_error("ctl_trigger error in local recovery: %s",
+			  diag_last_error(diag_get())->errmsg);
+
 	return 0;
 }
 
diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
index 52f320a..5bd9be3 100644
--- a/src/box/lua/ctl.c
+++ b/src/box/lua/ctl.c
@@ -122,8 +122,8 @@ box_lua_ctl_init(struct lua_State *L)
 	lua_pushnumber(L, CTL_EVENT_SHUTDOWN);
 	lua_setfield(L, -2, "SHUTDOWN");
 	lua_pushnumber(L, CTL_EVENT_REPLICASET_ADD);
-	lua_setfield(L, -2, "CTL_EVENT_REPLICASET_ADD");
+	lua_setfield(L, -2, "REPLICASET_ADD");
 	lua_pushnumber(L, CTL_EVENT_REPLICASET_REMOVE);
-	lua_setfield(L, -2, "CTL_EVENT_REPLICASET_REMOVE");
+	lua_setfield(L, -2, "REPLICASET_REMOVE");
 	lua_pop(L, 2); /* box, ctl */
 }
diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c
index fac84ce..e737ea3 100644
--- a/src/box/memtx_engine.c
+++ b/src/box/memtx_engine.c
@@ -48,6 +48,7 @@
 #include "replication.h"
 #include "schema.h"
 #include "gc.h"
+#include "ctl.h"
 
 static void
 txn_on_yield_or_stop(struct trigger *trigger, void *event)
@@ -197,7 +198,6 @@ memtx_engine_recover_snapshot(struct memtx_engine *memtx,
 	 */
 	if (!xlog_cursor_is_eof(&cursor))
 		panic("snapshot `%s' has no EOF marker", filename);
-
 	return 0;
 }
 
diff --git a/src/box/replication.cc b/src/box/replication.cc
index c1e1769..75aecd0 100644
--- a/src/box/replication.cc
+++ b/src/box/replication.cc
@@ -41,6 +41,7 @@
 #include "error.h"
 #include "relay.h"
 #include "vclock.h" /* VCLOCK_MAX */
+#include "ctl.h"
 
 uint32_t instance_id = REPLICA_ID_NIL;
 struct tt_uuid INSTANCE_UUID;
@@ -172,6 +173,12 @@ replicaset_add(uint32_t replica_id, const struct tt_uuid *replica_uuid)
 	replica->uuid = *replica_uuid;
 	replica_hash_insert(&replicaset.hash, replica);
 	replica_set_id(replica, replica_id);
+	struct on_ctl_event_ctx on_ctl_ctx;
+	on_ctl_ctx.type = CTL_EVENT_REPLICASET_ADD;
+	on_ctl_ctx.replica_id = replica_id;
+	if (run_on_ctl_event_triggers(&on_ctl_ctx) < 0)
+		say_error("ctl_trigger error in replica add: %s",
+			  diag_last_error(diag_get())->errmsg);
 	return replica;
 }
 
@@ -203,12 +210,19 @@ replica_clear_id(struct replica *replica)
 	 * Some records may arrive later on due to asynchronous nature of
 	 * replication.
 	 */
+	struct on_ctl_event_ctx on_ctl_ctx;
+	on_ctl_ctx.type = CTL_EVENT_REPLICASET_REMOVE;
+	on_ctl_ctx.replica_id = replica->id;
+
 	replicaset.replica_by_id[replica->id] = NULL;
 	replica->id = REPLICA_ID_NIL;
 	if (replica_is_orphan(replica)) {
 		replica_hash_remove(&replicaset.hash, replica);
 		replica_delete(replica);
 	}
+	if (run_on_ctl_event_triggers(&on_ctl_ctx) < 0)
+		say_error("ctl_trigger error in replica remove: %s",
+			  diag_last_error(diag_get())->errmsg);
 }
 
 static void
diff --git a/test/replication/master_onctl.lua b/test/replication/master_onctl.lua
new file mode 100644
index 0000000..e0eb39a
--- /dev/null
+++ b/test/replication/master_onctl.lua
@@ -0,0 +1,34 @@
+#!/usr/bin/env tarantool
+os = require('os')
+
+SYSTEM_SPACE_RECOVERY = 0
+LOCAL_RECOVERY = 0
+READ_ONLY = 0
+READ_WRITE = 0
+REPLICASET_ADD = {}
+REPLICASET_REMOVE = {}
+
+local function onctl(ctx)
+    if ctx.type == box.ctl.event.SYSTEM_SPACE_RECOVERY then
+        SYSTEM_SPACE_RECOVERY = SYSTEM_SPACE_RECOVERY + 1
+    elseif ctx.type == box.ctl.event.LOCAL_RECOVERY then
+        LOCAL_RECOVERY = LOCAL_RECOVERY + 1
+    elseif ctx.type == box.ctl.event.READ_ONLY then
+        READ_ONLY = READ_ONLY + 1
+    elseif ctx.type == box.ctl.event.READ_WRITE then
+        READ_WRITE = READ_WRITE + 1
+    elseif ctx.type == box.ctl.event.REPLICASET_ADD then
+        table.insert(REPLICASET_ADD, ctx.replica_id)
+    elseif ctx.type == box.ctl.event.REPLICASET_REMOVE then
+        table.insert(REPLICASET_REMOVE, ctx.replica_id)
+    end
+end
+
+box.cfg({
+    listen              = os.getenv("LISTEN"),
+    memtx_memory        = 107374182,
+    replication_connect_timeout = 0.5,
+    on_ctl_event        = onctl,
+})
+
+require('console').listen(os.getenv('ADMIN'))
diff --git a/test/replication/onctl.result b/test/replication/onctl.result
new file mode 100644
index 0000000..19b3e67
--- /dev/null
+++ b/test/replication/onctl.result
@@ -0,0 +1,250 @@
+env = require('test_run')
+---
+...
+test_run = env.new()
+---
+...
+test_run:cmd("create server master with script='replication/master_onctl.lua'")
+---
+- true
+...
+test_run:cmd("create server replica with rpl_master=master, script='replication/replica_onctl.lua'")
+---
+- true
+...
+test_run:cmd("start server master")
+---
+- true
+...
+test_run:cmd("switch master")
+---
+- true
+...
+box.schema.user.grant('guest', 'replication')
+---
+...
+SYSTEM_SPACE_RECOVERY
+---
+- 1
+...
+LOCAL_RECOVERY
+---
+- 1
+...
+READ_ONLY
+---
+- 0
+...
+READ_WRITE
+---
+- 1
+...
+-- must be two entries. First from bootstrap.snap, second for current instance.
+REPLICASET_ADD
+---
+- - 1
+  - 1
+...
+-- must be one entry. Deletion of initial tuple in _cluster space.
+REPLICASET_REMOVE
+---
+- - 1
+...
+REPLICASET_ADD = {}
+---
+...
+REPLICASET_REMOVE = {}
+---
+...
+new_replica_id = 0
+---
+...
+deleted_replica_id = 0
+---
+...
+test_run:cmd("setopt delimiter ';'")
+---
+- true
+...
+function on_ctl_new(ctx)
+    if ctx.type == box.ctl.event.REPLICASET_ADD then
+        new_replica_id = ctx.replica_id
+    elseif ctx.type == box.ctl.event.REPLICASET_REMOVE then
+        deleted_replica_id = ctx.replica_id
+    end
+end;
+---
+...
+test_run:cmd("setopt delimiter ''");
+---
+- true
+...
+_ = box.ctl.on_ctl_event(on_ctl_new)
+---
+...
+test_run:cmd("start server replica")
+---
+- true
+...
+REPLICASET_ADD
+---
+- - 2
+...
+REPLICASET_REMOVE
+---
+- []
+...
+new_replica_id
+---
+- 2
+...
+deleted_replica_id
+---
+- 0
+...
+test_run:cmd("switch replica")
+---
+- true
+...
+test_run:cmd("setopt delimiter ';'")
+---
+- true
+...
+function on_ctl_shutdown(ctx)
+    if ctx.type == box.ctl.event.SHUTDOWN then
+        require("log").info("test replica shutdown")
+    end
+end;
+---
+...
+function on_ctl_error(ctx)
+    error("trigger error")
+end;
+---
+...
+test_run:cmd("setopt delimiter ''");
+---
+- true
+...
+SYSTEM_SPACE_RECOVERY
+---
+- 1
+...
+LOCAL_RECOVERY
+---
+- 1
+...
+READ_ONLY
+---
+- 0
+...
+READ_WRITE
+---
+- 1
+...
+REPLICASET_ADD
+---
+- - 2
+...
+REPLICASET_REMOVE
+---
+- []
+...
+box.cfg{read_only = true}
+---
+...
+fiber = require("fiber")
+---
+...
+while READ_ONLY == 0 do fiber.sleep(0.001) end
+---
+...
+READ_ONLY
+---
+- 1
+...
+box.cfg{on_ctl_event = on_ctl_error}
+---
+...
+box.cfg{read_only = false}
+---
+...
+test_run:grep_log('replica', 'ctl_trigger error')
+---
+- ctl_trigger error
+...
+box.cfg{on_ctl_event = {box.NULL, on_ctl_error}}
+---
+...
+box.cfg{on_ctl_event = on_ctl_shutdown}
+---
+...
+test_run:cmd("restart server replica")
+-- TODO: test SHUTDOWN, when it is possible to grep logs of killed replica.
+--test_run:grep_log('replica', 'test replica shutdown')
+test_run:cmd("switch master")
+---
+- true
+...
+box.schema.user.revoke('guest', 'replication')
+---
+...
+_ = box.space._cluster:delete{2}
+---
+...
+SYSTEM_SPACE_RECOVERY
+---
+- 1
+...
+LOCAL_RECOVERY
+---
+- 1
+...
+READ_ONLY
+---
+- 0
+...
+READ_WRITE
+---
+- 1
+...
+REPLICASET_ADD
+---
+- - 2
+...
+REPLICASET_REMOVE
+---
+- - 2
+...
+new_replica_id
+---
+- 2
+...
+deleted_replica_id
+---
+- 2
+...
+box.ctl.on_ctl_event(nil, on_ctl_new)
+---
+...
+-- cleanup
+test_run:cmd("switch default")
+---
+- true
+...
+test_run:cmd("stop server master")
+---
+- true
+...
+test_run:cmd("cleanup server master")
+---
+- true
+...
+test_run:cmd("stop server replica")
+---
+- true
+...
+test_run:cmd("cleanup server replica")
+---
+- true
+...
diff --git a/test/replication/onctl.test.lua b/test/replication/onctl.test.lua
new file mode 100644
index 0000000..ff6a898
--- /dev/null
+++ b/test/replication/onctl.test.lua
@@ -0,0 +1,105 @@
+env = require('test_run')
+test_run = env.new()
+
+test_run:cmd("create server master with script='replication/master_onctl.lua'")
+test_run:cmd("create server replica with rpl_master=master, script='replication/replica_onctl.lua'")
+
+test_run:cmd("start server master")
+test_run:cmd("switch master")
+box.schema.user.grant('guest', 'replication')
+
+SYSTEM_SPACE_RECOVERY
+LOCAL_RECOVERY
+READ_ONLY
+READ_WRITE
+-- must be two entries. First from bootstrap.snap, second for current instance.
+REPLICASET_ADD
+-- must be one entry. Deletion of initial tuple in _cluster space.
+REPLICASET_REMOVE
+
+REPLICASET_ADD = {}
+REPLICASET_REMOVE = {}
+
+new_replica_id = 0
+deleted_replica_id = 0
+
+test_run:cmd("setopt delimiter ';'")
+function on_ctl_new(ctx)
+    if ctx.type == box.ctl.event.REPLICASET_ADD then
+        new_replica_id = ctx.replica_id
+    elseif ctx.type == box.ctl.event.REPLICASET_REMOVE then
+        deleted_replica_id = ctx.replica_id
+    end
+end;
+test_run:cmd("setopt delimiter ''");
+
+_ = box.ctl.on_ctl_event(on_ctl_new)
+
+test_run:cmd("start server replica")
+
+REPLICASET_ADD
+REPLICASET_REMOVE
+
+new_replica_id
+deleted_replica_id
+
+test_run:cmd("switch replica")
+
+test_run:cmd("setopt delimiter ';'")
+function on_ctl_shutdown(ctx)
+    if ctx.type == box.ctl.event.SHUTDOWN then
+        require("log").info("test replica shutdown")
+    end
+end;
+
+function on_ctl_error(ctx)
+    error("trigger error")
+end;
+
+test_run:cmd("setopt delimiter ''");
+
+SYSTEM_SPACE_RECOVERY
+LOCAL_RECOVERY
+READ_ONLY
+READ_WRITE
+REPLICASET_ADD
+REPLICASET_REMOVE
+
+box.cfg{read_only = true}
+fiber = require("fiber")
+while READ_ONLY == 0 do fiber.sleep(0.001) end
+READ_ONLY
+
+box.cfg{on_ctl_event = on_ctl_error}
+box.cfg{read_only = false}
+test_run:grep_log('replica', 'ctl_trigger error')
+box.cfg{on_ctl_event = {box.NULL, on_ctl_error}}
+box.cfg{on_ctl_event = on_ctl_shutdown}
+
+test_run:cmd("restart server replica")
+-- TODO: test SHUTDOWN, when it is possible to grep logs of killed replica.
+--test_run:grep_log('replica', 'test replica shutdown')
+
+
+test_run:cmd("switch master")
+box.schema.user.revoke('guest', 'replication')
+_ = box.space._cluster:delete{2}
+
+SYSTEM_SPACE_RECOVERY
+LOCAL_RECOVERY
+READ_ONLY
+READ_WRITE
+REPLICASET_ADD
+REPLICASET_REMOVE
+
+new_replica_id
+deleted_replica_id
+
+box.ctl.on_ctl_event(nil, on_ctl_new)
+
+-- cleanup
+test_run:cmd("switch default")
+test_run:cmd("stop server master")
+test_run:cmd("cleanup server master")
+test_run:cmd("stop server replica")
+test_run:cmd("cleanup server replica")
diff --git a/test/replication/replica_onctl.lua b/test/replication/replica_onctl.lua
new file mode 100644
index 0000000..d6ce73c
--- /dev/null
+++ b/test/replication/replica_onctl.lua
@@ -0,0 +1,34 @@
+#!/usr/bin/env tarantool
+
+SYSTEM_SPACE_RECOVERY = 0
+LOCAL_RECOVERY = 0
+READ_ONLY = 0
+READ_WRITE = 0
+REPLICASET_ADD = {}
+REPLICASET_REMOVE = {}
+
+local function onctl(ctx)
+    if ctx.type == box.ctl.event.SYSTEM_SPACE_RECOVERY then
+        SYSTEM_SPACE_RECOVERY = SYSTEM_SPACE_RECOVERY + 1
+    elseif ctx.type == box.ctl.event.LOCAL_RECOVERY then
+        LOCAL_RECOVERY = LOCAL_RECOVERY + 1
+    elseif ctx.type == box.ctl.event.READ_ONLY then
+        READ_ONLY = READ_ONLY + 1
+    elseif ctx.type == box.ctl.event.READ_WRITE then
+        READ_WRITE = READ_WRITE + 1
+    elseif ctx.type == box.ctl.event.REPLICASET_ADD then
+        table.insert(REPLICASET_ADD, ctx.replica_id)
+    elseif ctx.type == box.ctl.event.REPLICASET_REMOVE then
+        table.insert(REPLICASET_REMOVE, ctx.replica_id)
+    end
+end
+
+box.cfg({
+    listen              = os.getenv("LISTEN"),
+    replication         = os.getenv("MASTER"),
+    memtx_memory        = 107374182,
+    replication_connect_timeout = 0.5,
+    on_ctl_event        = onctl,
+})
+
+require('console').listen(os.getenv('ADMIN'))
diff --git a/test/replication/suite.cfg b/test/replication/suite.cfg
index 95e94e5..365a825 100644
--- a/test/replication/suite.cfg
+++ b/test/replication/suite.cfg
@@ -6,6 +6,7 @@
     "wal_off.test.lua": {},
     "hot_standby.test.lua": {},
     "rebootstrap.test.lua": {},
+    "onctl.test.lua": {},
     "*": {
         "memtx": {"engine": "memtx"},
         "vinyl": {"engine": "vinyl"}
-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] [box.ctl 3/3] box.ctl: Add replica error event
  2018-06-14 15:04 [tarantool-patches] [box.ctl 0/3] Introduce box.ctl.on_ctl_event trigger Ilya Markov
  2018-06-14 15:04 ` [tarantool-patches] [box.ctl 1/3] box.ctl: Introduce stab box.ctl.on_ctl_event Ilya Markov
  2018-06-14 15:04 ` [tarantool-patches] [box.ctl 2/3] box.ctl: Add on_ctl_event trigger calls Ilya Markov
@ 2018-06-14 15:04 ` Ilya Markov
  2018-07-31 11:40   ` [tarantool-patches] " Konstantin Belyavskiy
  2 siblings, 1 reply; 7+ messages in thread
From: Ilya Markov @ 2018-06-14 15:04 UTC (permalink / raw)
  To: georgy; +Cc: tarantool-patches

Add event: replica fails with some error.

In scope of #3159
---
 src/box/ctl.h                     |  1 +
 src/box/lua/ctl.c                 |  6 +++++-
 src/box/relay.cc                  |  7 +++++++
 test/replication/master_onctl.lua |  3 +++
 test/replication/onctl.result     | 12 ++++++++++++
 test/replication/onctl.test.lua   |  5 ++++-
 6 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/src/box/ctl.h b/src/box/ctl.h
index 1dbb6be..db6f08a 100644
--- a/src/box/ctl.h
+++ b/src/box/ctl.h
@@ -49,6 +49,7 @@ enum ctl_event_type {
 	CTL_EVENT_SHUTDOWN,
 	CTL_EVENT_REPLICASET_ADD,
 	CTL_EVENT_REPLICASET_REMOVE,
+	CTL_EVENT_REPLICA_CONNECTION_ERROR,
 };
 
 struct on_ctl_event_ctx {
diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
index 5bd9be3..8a0dfc2 100644
--- a/src/box/lua/ctl.c
+++ b/src/box/lua/ctl.c
@@ -37,6 +37,7 @@
 #include <lualib.h>
 #include <lua/trigger.h>
 #include <box/ctl.h>
+#include <tt_uuid.h>
 
 #include "lua/utils.h"
 
@@ -77,7 +78,8 @@ lbox_push_on_ctl_event(struct lua_State *L, void *event)
 	lua_settable(L, -3);
 
 	if (ctx->type == CTL_EVENT_REPLICASET_ADD ||
-		ctx->type == CTL_EVENT_REPLICASET_REMOVE) {
+		ctx->type == CTL_EVENT_REPLICASET_REMOVE ||
+		ctx->type == CTL_EVENT_REPLICA_CONNECTION_ERROR) {
 		lua_pushstring(L, "replica_id");
 		luaL_pushuint64(L, ctx->replica_id);
 		lua_settable(L, -3);
@@ -125,5 +127,7 @@ box_lua_ctl_init(struct lua_State *L)
 	lua_setfield(L, -2, "REPLICASET_ADD");
 	lua_pushnumber(L, CTL_EVENT_REPLICASET_REMOVE);
 	lua_setfield(L, -2, "REPLICASET_REMOVE");
+	lua_pushnumber(L, CTL_EVENT_REPLICA_CONNECTION_ERROR);
+	lua_setfield(L, -2, "REPLICA_CONNECTION_ERROR");
 	lua_pop(L, 2); /* box, ctl */
 }
diff --git a/src/box/relay.cc b/src/box/relay.cc
index a25cc54..d535f83 100644
--- a/src/box/relay.cc
+++ b/src/box/relay.cc
@@ -52,6 +52,7 @@
 #include "xrow_io.h"
 #include "xstream.h"
 #include "wal.h"
+#include "ctl.h"
 
 /**
  * Cbus message to send status updates from relay to tx thread.
@@ -548,6 +549,12 @@ relay_subscribe_f(va_list ap)
 	if (!diag_is_empty(&relay->diag)) {
 		/* An error has occurred while reading ACKs of xlog. */
 		diag_move(&relay->diag, diag_get());
+		struct on_ctl_event_ctx ctx;
+		ctx.type = CTL_EVENT_REPLICA_CONNECTION_ERROR;
+		ctx.replica_id = relay->replica->id;
+		if (run_on_ctl_event_triggers(&ctx) < 0)
+			say_error("ctl_trigger error in replica error: %s",
+				  diag_last_error(diag_get())->errmsg);
 		/* Reference the diag in the status. */
 		diag_add_error(&relay->diag, diag_last_error(diag_get()));
 	}
diff --git a/test/replication/master_onctl.lua b/test/replication/master_onctl.lua
index e0eb39a..355e791 100644
--- a/test/replication/master_onctl.lua
+++ b/test/replication/master_onctl.lua
@@ -7,6 +7,7 @@ READ_ONLY = 0
 READ_WRITE = 0
 REPLICASET_ADD = {}
 REPLICASET_REMOVE = {}
+REPLICA_CONNECTION_ERROR = {}
 
 local function onctl(ctx)
     if ctx.type == box.ctl.event.SYSTEM_SPACE_RECOVERY then
@@ -21,6 +22,8 @@ local function onctl(ctx)
         table.insert(REPLICASET_ADD, ctx.replica_id)
     elseif ctx.type == box.ctl.event.REPLICASET_REMOVE then
         table.insert(REPLICASET_REMOVE, ctx.replica_id)
+    elseif ctx.type == box.ctl.event.REPLICA_CONNECTION_ERROR then
+        table.insert(REPLICA_CONNECTION_ERROR, ctx.replica_id)
     end
 end
 
diff --git a/test/replication/onctl.result b/test/replication/onctl.result
index 19b3e67..24a6683 100644
--- a/test/replication/onctl.result
+++ b/test/replication/onctl.result
@@ -50,6 +50,10 @@ REPLICASET_REMOVE
 ---
 - - 1
 ...
+REPLICA_CONNECTION_ERROR
+---
+- []
+...
 REPLICASET_ADD = {}
 ---
 ...
@@ -94,6 +98,10 @@ REPLICASET_REMOVE
 ---
 - []
 ...
+REPLICA_CONNECTION_ERROR
+---
+- []
+...
 new_replica_id
 ---
 - 2
@@ -186,6 +194,10 @@ test_run:cmd("switch master")
 ---
 - true
 ...
+REPLICA_CONNECTION_ERROR
+---
+- - 2
+...
 box.schema.user.revoke('guest', 'replication')
 ---
 ...
diff --git a/test/replication/onctl.test.lua b/test/replication/onctl.test.lua
index ff6a898..352b118 100644
--- a/test/replication/onctl.test.lua
+++ b/test/replication/onctl.test.lua
@@ -16,6 +16,7 @@ READ_WRITE
 REPLICASET_ADD
 -- must be one entry. Deletion of initial tuple in _cluster space.
 REPLICASET_REMOVE
+REPLICA_CONNECTION_ERROR
 
 REPLICASET_ADD = {}
 REPLICASET_REMOVE = {}
@@ -39,6 +40,7 @@ test_run:cmd("start server replica")
 
 REPLICASET_ADD
 REPLICASET_REMOVE
+REPLICA_CONNECTION_ERROR
 
 new_replica_id
 deleted_replica_id
@@ -80,8 +82,9 @@ test_run:cmd("restart server replica")
 -- TODO: test SHUTDOWN, when it is possible to grep logs of killed replica.
 --test_run:grep_log('replica', 'test replica shutdown')
 
-
 test_run:cmd("switch master")
+REPLICA_CONNECTION_ERROR
+
 box.schema.user.revoke('guest', 'replication')
 _ = box.space._cluster:delete{2}
 
-- 
2.7.4

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] Re: [tarantool-patches] [box.ctl 1/3] box.ctl: Introduce stab box.ctl.on_ctl_event
  2018-06-14 15:04 ` [tarantool-patches] [box.ctl 1/3] box.ctl: Introduce stab box.ctl.on_ctl_event Ilya Markov
@ 2018-07-31 11:40   ` Konstantin Belyavskiy
  0 siblings, 0 replies; 7+ messages in thread
From: Konstantin Belyavskiy @ 2018-07-31 11:40 UTC (permalink / raw)
  To: georgy,
	Илья
	Марков
  Cc: tarantool-patches

[-- Attachment #1: Type: text/plain, Size: 14645 bytes --]

Hi,
overall patch looks good with minor fixes (short summary, see explanation below):
- fix commit message
- change function name
- remove unused header

>Четверг, 14 июня 2018, 18:04 +03:00 от Ilya Markov <imarkov@tarantool.org>:
>
>Add required for trigger on_ctl_event
>structures and lua bindings.
>
>Prerequisite #3259 
#3159
>
>---
> src/box/CMakeLists.txt   |  1 +
> src/box/box.cc           |  9 ++++++
> src/box/box.h            |  1 +
> src/box/ctl.c            | 63 +++++++++++++++++++++++++++++++++++++
> src/box/ctl.h            | 81 ++++++++++++++++++++++++++++++++++++++++++++++++
> src/box/lua/cfg.cc       | 12 +++++++
> src/box/lua/ctl.c        | 51 ++++++++++++++++++++++++++++++
> src/box/lua/ctl.h        |  2 ++
> src/box/lua/load_cfg.lua | 10 +++++-
> src/cfg.c                | 37 ++++++++++++++++++++++
> src/cfg.h                |  4 +++
> 11 files changed, 270 insertions(+), 1 deletion(-)
> create mode 100644 src/box/ctl.c
> create mode 100644 src/box/ctl.h
>
>diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
>index 6b1ae3e..74f6b54 100644
>--- a/src/box/CMakeLists.txt
>+++ b/src/box/CMakeLists.txt
>@@ -112,6 +112,7 @@ add_library(box STATIC
>     journal.c
>     wal.c
>     call.c
>+    ctl.c
>     ${lua_sources}
>     lua/init.c
>     lua/call.c
>diff --git a/src/box/box.cc b/src/box/box.cc
>index 61bfa11..26277e7 100644
>--- a/src/box/box.cc
>+++ b/src/box/box.cc
>@@ -72,6 +72,7 @@
> #include "call.h"
> #include "func.h"
> #include "sequence.h"
>+#include "ctl.h"
>
> static char status[64] = "unknown";
>
>@@ -823,6 +824,13 @@ box_set_net_msg_max(void)
> 				IPROTO_FIBER_POOL_SIZE_FACTOR);
> }
>
>+void
>+box_set_on_ctl_event(void)
>+{
>+	if (cfg_reset_on_ctl_event() < 0)
>+		diag_raise();
>+} 
Please add _xc suffix, since function raise exception.
>
>+
> /* }}} configuration bindings */
>
> /**
>@@ -1808,6 +1816,7 @@ box_cfg_xc(void)
> 	box_set_replication_connect_timeout();
> 	box_set_replication_connect_quorum();
> 	box_set_replication_skip_conflict();
>+	box_set_on_ctl_event();
> 	replication_sync_lag = box_check_replication_sync_lag();
> 	xstream_create(&join_stream, apply_initial_join_row);
> 	xstream_create(&subscribe_stream, apply_row);
>diff --git a/src/box/box.h b/src/box/box.h
>index d396789..0325527 100644
>--- a/src/box/box.h
>+++ b/src/box/box.h
>@@ -191,6 +191,7 @@ void box_set_replication_connect_timeout(void);
> void box_set_replication_connect_quorum(void);
> void box_set_replication_skip_conflict(void);
> void box_set_net_msg_max(void);
>+void box_set_on_ctl_event(void);
>
> extern "C" {
> #endif /* defined(__cplusplus) */
>diff --git a/src/box/ctl.c b/src/box/ctl.c
>new file mode 100644
>index 0000000..fc3ae37
>--- /dev/null
>+++ b/src/box/ctl.c
>@@ -0,0 +1,63 @@
>+/*
>+ * Copyright 2010-2018, Tarantool AUTHORS, please see AUTHORS file.
>+ *
>+ * Redistribution and use in source and binary forms, with or
>+ * without modification, are permitted provided that the following
>+ * conditions are met:
>+ *
>+ * 1. Redistributions of source code must retain the above
>+ *    copyright notice, this list of conditions and the
>+ *    following disclaimer.
>+ *
>+ * 2. Redistributions in binary form must reproduce the above
>+ *    copyright notice, this list of conditions and the following
>+ *    disclaimer in the documentation and/or other materials
>+ *    provided with the distribution.
>+ *
>+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
>+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
>+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
>+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
>+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
>+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
>+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
>+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
>+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>+ * SUCH DAMAGE.
>+ */
>+#include <lib/small/small/rlist.h>
>+#include <trigger.h>
>+#include <box/ctl.h>
>+#include "errcode.h"
>+#include "error.h"
>+#include <exception.h>
>+
>+RLIST_HEAD(on_ctl_event);
>+
>+int
>+run_on_ctl_event_triggers(const struct on_ctl_event_ctx *result) {
>+	return trigger_run(&on_ctl_event, (void *) result);
>+}
>+
>+int
>+run_on_ctl_event_trigger_type(enum ctl_event_type type)
>+{
>+	struct on_ctl_event_ctx ctx = {};
>+	ctx.type = type;
>+	return run_on_ctl_event_triggers(&ctx);
>+}
>+
>+int
>+cfg_reset_on_ctl_event()
>+{
>+	if (cfg_reset_trigger("on_ctl_event", &on_ctl_event,
>+		lbox_push_on_ctl_event, NULL) < 0) {
>+		diag_set(ClientError, ER_CFG, "on_ctl_event",
>+			 "expected function or table");
>+		return -1;
>+	}
>+	return 0;
>+}
>\ No newline at end of file
>diff --git a/src/box/ctl.h b/src/box/ctl.h
>new file mode 100644
>index 0000000..1dbb6be
>--- /dev/null
>+++ b/src/box/ctl.h
>@@ -0,0 +1,81 @@
>+#ifndef INCLUDES_TARANTOOL_CTL_H
>+#define INCLUDES_TARANTOOL_CTL_H
>+
>+/*
>+ * Copyright 2010-2018, Tarantool AUTHORS, please see AUTHORS file.
>+ *
>+ * Redistribution and use in source and binary forms, with or
>+ * without modification, are permitted provided that the following
>+ * conditions are met:
>+ *
>+ * 1. Redistributions of source code must retain the above
>+ *    copyright notice, this list of conditions and the
>+ *    following disclaimer.
>+ *
>+ * 2. Redistributions in binary form must reproduce the above
>+ *    copyright notice, this list of conditions and the following
>+ *    disclaimer in the documentation and/or other materials
>+ *    provided with the distribution.
>+ *
>+ * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
>+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
>+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
>+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
>+ * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
>+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
>+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
>+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
>+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
>+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
>+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>+ * SUCH DAMAGE.
>+ */
>+
>+#include <cfg.h>
>+#include <box/lua/ctl.h>
>
>+#include "errcode.h"
>+#include "error.h"
>+#include <exception.h>
I think last three headers are useless here.
>
>+
>+/** Global on-ctl_event triggers. */
>+extern struct rlist on_ctl_event;
>+
>+enum ctl_event_type {
>+	CTL_EVENT_SYSTEM_SPACE_RECOVERY,
>+	CTL_EVENT_LOCAL_RECOVERY,
>+	CTL_EVENT_READ_ONLY,
>+	CTL_EVENT_READ_WRITE,
>+	CTL_EVENT_SHUTDOWN,
>+	CTL_EVENT_REPLICASET_ADD,
>+	CTL_EVENT_REPLICASET_REMOVE,
>+};
>+
>+struct on_ctl_event_ctx {
>+	enum ctl_event_type type;
>+	uint32_t replica_id;
>+};
>+
>+#if defined(__cplusplus)
>+extern "C" {
>+#endif /* defined(__cplusplus) */
>+
>+/**
>+ * Runs on_ctl_event triggers with specified context.
>+ */
>+int
>+run_on_ctl_event_triggers(const struct on_ctl_event_ctx *result);
>+
>+/**
>+ * Runs on_ctl_event triggers with specified type.
>+ */
>+int
>+run_on_ctl_event_trigger_type(enum ctl_event_type type);
>+
>+int
>+cfg_reset_on_ctl_event();
>+#if defined(__cplusplus)
>+} /* extern "C" */
>+#endif /* defined(__cplusplus) */
>+
>+#endif /* INCLUDES_TARANTOOL_LUA_CTL_H */
>diff --git a/src/box/lua/cfg.cc b/src/box/lua/cfg.cc
>index 5afebc9..c92478f 100644
>--- a/src/box/lua/cfg.cc
>+++ b/src/box/lua/cfg.cc
>@@ -254,6 +254,17 @@ lbox_cfg_set_net_msg_max(struct lua_State *L)
> }
>
> static int
>+lbox_cfg_set_on_ctl_event(struct lua_State *L)
>+{
>+	try {
>+		box_set_on_ctl_event();
>+	} catch (Exception *) {
>+		luaT_error(L);
>+	}
>+	return 0;
>+}
>+
>+static int
> lbox_cfg_set_worker_pool_threads(struct lua_State *L)
> {
> 	(void) L;
>@@ -331,6 +342,7 @@ box_lua_cfg_init(struct lua_State *L)
> 		{"cfg_set_replication_skip_conflict", lbox_cfg_set_replication_skip_conflict},
> 		{"cfg_set_replication_connect_timeout", lbox_cfg_set_replication_connect_timeout},
> 		{"cfg_set_net_msg_max", lbox_cfg_set_net_msg_max},
>+		{"cfg_set_on_ctl_event", lbox_cfg_set_on_ctl_event},
> 		{NULL, NULL}
> 	};
>
>diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
>index 9a105ed..52f320a 100644
>--- a/src/box/lua/ctl.c
>+++ b/src/box/lua/ctl.c
>@@ -35,6 +35,8 @@
> #include <lua.h>
> #include <lauxlib.h>
> #include <lualib.h>
>+#include <lua/trigger.h>
>+#include <box/ctl.h>
>
> #include "lua/utils.h"
>
>@@ -64,9 +66,37 @@ lbox_ctl_wait_rw(struct lua_State *L)
> 	return 0;
> }
>
>+
>+int
>+lbox_push_on_ctl_event(struct lua_State *L, void *event)
>+{
>+	struct on_ctl_event_ctx *ctx = (struct on_ctl_event_ctx *) event;
>+	lua_newtable(L);
>+	lua_pushstring(L, "type");
>+	lua_pushinteger(L, ctx->type);
>+	lua_settable(L, -3);
>+
>+	if (ctx->type == CTL_EVENT_REPLICASET_ADD ||
>+		ctx->type == CTL_EVENT_REPLICASET_REMOVE) {
>+		lua_pushstring(L, "replica_id");
>+		luaL_pushuint64(L, ctx->replica_id);
>+		lua_settable(L, -3);
>+	}
>+	return 1;
>+}
>+
>+static int
>+lbox_on_ctl_event(struct lua_State *L)
>+{
>+	return lbox_trigger_reset(L, 2, &on_ctl_event,
>+				  lbox_push_on_ctl_event, NULL);
>+}
>+
>+
> static const struct luaL_Reg lbox_ctl_lib[] = {
> 	{"wait_ro", lbox_ctl_wait_ro},
> 	{"wait_rw", lbox_ctl_wait_rw},
>+	{"on_ctl_event", lbox_on_ctl_event},
> 	{NULL, NULL}
> };
>
>@@ -75,4 +105,25 @@ box_lua_ctl_init(struct lua_State *L)
> {
> 	luaL_register_module(L, "box.ctl", lbox_ctl_lib);
> 	lua_pop(L, 1);
>+
>+	luaL_findtable(L, LUA_GLOBALSINDEX, "box.ctl", 1);
>+	lua_newtable(L);
>+	lua_setfield(L, -2, "event");
>+	lua_getfield(L, -1, "event");
>+
>+	lua_pushnumber(L, CTL_EVENT_SYSTEM_SPACE_RECOVERY);
>+	lua_setfield(L, -2, "SYSTEM_SPACE_RECOVERY");
>+	lua_pushnumber(L, CTL_EVENT_LOCAL_RECOVERY);
>+	lua_setfield(L, -2, "LOCAL_RECOVERY");
>+	lua_pushnumber(L, CTL_EVENT_READ_ONLY);
>+	lua_setfield(L, -2, "READ_ONLY");
>+	lua_pushnumber(L, CTL_EVENT_READ_WRITE);
>+	lua_setfield(L, -2, "READ_WRITE");
>+	lua_pushnumber(L, CTL_EVENT_SHUTDOWN);
>+	lua_setfield(L, -2, "SHUTDOWN");
>+	lua_pushnumber(L, CTL_EVENT_REPLICASET_ADD);
>+	lua_setfield(L, -2, "CTL_EVENT_REPLICASET_ADD");
>+	lua_pushnumber(L, CTL_EVENT_REPLICASET_REMOVE);
>+	lua_setfield(L, -2, "CTL_EVENT_REPLICASET_REMOVE");
>+	lua_pop(L, 2); /* box, ctl */
> }
>diff --git a/src/box/lua/ctl.h b/src/box/lua/ctl.h
>index e7c2edd..ab63232 100644
>--- a/src/box/lua/ctl.h
>+++ b/src/box/lua/ctl.h
>@@ -41,6 +41,8 @@ struct lua_State;
> void
> box_lua_ctl_init(struct lua_State *L);
>
>+int
>+lbox_push_on_ctl_event(struct lua_State *L, void *event);
> #if defined(__cplusplus)
> } /* extern "C" */
> #endif /* defined(__cplusplus) */
>diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua
>index 0b668cd..c4d1347 100644
>--- a/src/box/lua/load_cfg.lua
>+++ b/src/box/lua/load_cfg.lua
>@@ -1,7 +1,11 @@
> -- load_cfg.lua - internal file
>
> local log = require('log')
>-local json = require('json')
>+local json = require("json").new()
>+json.cfg{
>+    encode_use_tostring    = true,
>+}
>+
> local private = require('box.internal')
> local urilib = require('uri')
> local math = require('math')
>@@ -64,6 +68,7 @@ local default_cfg = {
>     feedback_host         = " https://feedback.tarantool.io ",
>     feedback_interval     = 3600,
>     net_msg_max           = 768,
>+    on_ctl_event          = nil,
> }
>
> -- types of available options
>@@ -125,6 +130,7 @@ local template_cfg = {
>     feedback_host         = 'string',
>     feedback_interval     = 'number',
>     net_msg_max           = 'number',
>+    on_ctl_event          = 'function, table',
> }
>
> local function normalize_uri(port)
>@@ -216,6 +222,7 @@ local dynamic_cfg = {
>     replicaset_uuid         = check_replicaset_uuid,
>     replication_skip_conflict = private.cfg_set_replication_skip_conflict,
>     net_msg_max             = private.cfg_set_net_msg_max,
>+    on_ctl_event            = private.cfg_set_on_ctl_event,
> }
>
> local dynamic_cfg_skip_at_load = {
>@@ -232,6 +239,7 @@ local dynamic_cfg_skip_at_load = {
>     force_recovery          = true,
>     instance_uuid           = true,
>     replicaset_uuid         = true,
>+    on_ctl_event            = true,
> }
>
> local function convert_gb(size)
>diff --git a/src/cfg.c b/src/cfg.c
>index 7c7d6e7..b07c1f3 100644
>--- a/src/cfg.c
>+++ b/src/cfg.c
>@@ -153,3 +153,40 @@ cfg_getarr_elem(const char *name, int i)
> 	lua_pop(tarantool_L, 2);
> 	return val;
> }
>+
>+int
>+cfg_reset_trigger(const char *name, struct rlist *list,
>+		  lbox_push_event_f push_event, lbox_pop_event_f pop_event)
>+{
>+	cfg_get(name);
>+	struct lua_State *L = tarantool_L;
>+	if (lua_isnil(L, -1))
>+		return 0;
>+	if (!lua_isfunction(L, -1) && !lua_istable(L, -1)) {
>+		return -1;
>+	}
>+	if (lua_istable(L, -1)) {
>+		lua_pushinteger(L, 1);
>+		lua_gettable(L, -2);
>+		if (!luaL_isnull(L, lua_gettop(L)) && !lua_isfunction(L, -1))
>+			return -1;
>+		bool is_nil = luaL_isnull(L, lua_gettop(L));
>+		if (is_nil) {
>+			lua_pop(L, 1);
>+			lua_pushnil(L);
>+		}
>+		lua_pushinteger(L, 2);
>+		lua_gettable(L, -3);
>+		if (!lua_isfunction(L, -1) && !lua_isnil(L, -1))
>+			return -1;
>+		if (is_nil && lua_isnil(L, -1)) {
>+			return 0;
>+		}
>+	} else {
>+		lua_pushnil(L);
>+	}
>+	int rc = lbox_trigger_reset(L, lua_gettop(L), list,
>+				  push_event, pop_event);
>+	lua_pop(L, 1);
>+	return rc;
>+}
>\ No newline at end of file
>diff --git a/src/cfg.h b/src/cfg.h
>index  8499388 ..d36465c 100644
>--- a/src/cfg.h
>+++ b/src/cfg.h
>@@ -32,6 +32,7 @@
>  */
>
> #include <stdint.h>
>+#include <lua/trigger.h>
>
> #if defined(__cplusplus)
> extern "C" {
>@@ -61,6 +62,9 @@ cfg_getarr_size(const char *name);
> const char *
> cfg_getarr_elem(const char *name, int i);
>
>+int
>+cfg_reset_trigger(const char *name, struct rlist *list,
>+		  lbox_push_event_f push_event, lbox_pop_event_f pop_event);
> #if defined(__cplusplus)
> } /* extern "C" */
> #endif /* defined(__cplusplus) */
>-- 
>2.7.4
>
>


Best regards,
Konstantin Belyavskiy
k.belyavskiy@tarantool.org

[-- Attachment #2: Type: text/html, Size: 18206 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] Re: [tarantool-patches] [box.ctl 2/3] box.ctl: Add on_ctl_event trigger calls
  2018-06-14 15:04 ` [tarantool-patches] [box.ctl 2/3] box.ctl: Add on_ctl_event trigger calls Ilya Markov
@ 2018-07-31 11:40   ` Konstantin Belyavskiy
  0 siblings, 0 replies; 7+ messages in thread
From: Konstantin Belyavskiy @ 2018-07-31 11:40 UTC (permalink / raw)
  To: georgy,
	Илья
	Марков
  Cc: tarantool-patches

[-- Attachment #1: Type: text/plain, Size: 18761 bytes --]

Hi,
overall patch looks good with minor conplains (summary)
- unused headers
- is it worth it to create a separate fiber to check if read-only condition was changed?
- test SHUTDOWN should be implemented



>Четверг, 14 июня 2018, 18:04 +03:00 от Ilya Markov <imarkov@tarantool.org>:
>
>Add following cases of triggers:
>* System space recovery. Called on finish of bootstrap or finish of join or
>snapshot recovery.
>* Local recovery. Called on finish of bootstrap or finish of recovery.
>* Read_only/read_write. Called on changes of read_only state of
>instance.
>* Shutdown. Called on controlled shutdown.
>* Replicaset_add/replicaset_remove. Called on changes in space _cluster.
>
>Errors inside triggers are logged and don't influence on instance
>behaviour.
>
>Continue #3159
>---
> src/box/alter.cc                   |   1 +
> src/box/box.cc                     |  44 ++++++-
> src/box/engine.c                   |  14 +++
> src/box/lua/ctl.c                  |   4 +-
> src/box/memtx_engine.c             |   2 +-
> src/box/replication.cc             |  14 +++
> test/replication/master_onctl.lua  |  34 +++++
> test/replication/onctl.result      | 250 +++++++++++++++++++++++++++++++++++++
> test/replication/onctl.test.lua    | 105 ++++++++++++++++
> test/replication/replica_onctl.lua |  34 +++++
> test/replication/suite.cfg         |   1 +
> 11 files changed, 498 insertions(+), 5 deletions(-)
> create mode 100644 test/replication/master_onctl.lua
> create mode 100644 test/replication/onctl.result
> create mode 100644 test/replication/onctl.test.lua
> create mode 100644 test/replication/replica_onctl.lua
>
>diff --git a/src/box/alter.cc b/src/box/alter.cc
>index 6f6fcb0..7ec548b 100644
>--- a/src/box/alter.cc
>+++ b/src/box/alter.cc
>@@ -52,6 +52,7 @@
> #include "identifier.h"
> #include "version.h"
> #include "sequence.h"
>
>+#include "ctl.h" 
Not used.
>
>
> /**
>  * chap-sha1 of empty string, i.e.
>diff --git a/src/box/box.cc b/src/box/box.cc
>index 26277e7..1de37d2 100644
>--- a/src/box/box.cc
>+++ b/src/box/box.cc
>@@ -113,6 +113,11 @@ static fiber_cond ro_cond;
>  */
> static bool is_orphan = true;
>
>+/**
>+ * Fiber used for on_ctl_event trigger.
>+ */
>+static fiber *ro_checker;
>+
> /* Use the shared instance of xstream for all appliers */
> static struct xstream join_stream;
> static struct xstream subscribe_stream;
>@@ -1573,6 +1578,9 @@ box_set_replicaset_uuid(const struct tt_uuid *replicaset_uuid)
> void
> box_free(void)
> {
>+	if (run_on_ctl_event_trigger_type(CTL_EVENT_SHUTDOWN) < 0)
>+		say_error("ctl_trigger error in shutdown: %s",
>+			  diag_last_error(diag_get())->errmsg);
> 	/*
> 	 * See gh-584 "box_free() is called even if box is not
> 	 * initialized
>@@ -1592,7 +1600,8 @@ box_free(void)
> 		engine_shutdown();
> 		wal_thread_stop();
> 	}
>-
>+	if (!fiber_is_dead(ro_checker))
>+		fiber_cancel(ro_checker);
> 	fiber_cond_destroy(&ro_cond);
> }
>
>@@ -1693,6 +1702,10 @@ bootstrap_from_master(struct replica *master)
> 	engine_begin_initial_recovery_xc(NULL);
> 	applier_resume_to_state(applier, APPLIER_FINAL_JOIN, TIMEOUT_INFINITY);
>
>+	if (run_on_ctl_event_trigger_type(CTL_EVENT_SYSTEM_SPACE_RECOVERY) < 0)
>+		say_error("ctl_trigger error in system space recovery: %s",
>+			  diag_last_error(diag_get())->errmsg);
>+
> 	/*
> 	 * Process final data (WALs).
> 	 */
>@@ -1755,11 +1768,35 @@ tx_prio_cb(struct ev_loop *loop, ev_watcher *watcher, int events)
> 	cbus_process(endpoint);
> }
>
>+static int
>+check_ro_f(MAYBE_UNUSED va_list ap)
>+{
>+	double timeout = TIMEOUT_INFINITY;
>+	struct on_ctl_event_ctx ctx;
>+	memset(&ctx, 0, sizeof(ctx));
>+	while (true) {
>+		if (box_wait_ro(!box_is_ro(), timeout) != 0) {
>+			if (fiber_is_cancelled())
>+				break;
>+			else
>+				return -1;
>+		}
>+		if (run_on_ctl_event_trigger_type(
>+			box_is_ro() ? CTL_EVENT_READ_ONLY:
>+					      CTL_EVENT_READ_WRITE) < 0)
>+			say_error("ctl_trigger error in %s: %s",
>+				  box_is_ro() ? "read_only" :"read_write",
>+				  diag_last_error(diag_get())->errmsg);
>+	}
>+	return 0;
>+}
>+ 
Is it worth it to create a separate fiber? May be check it near or inside fiber_cond_broadcast(&ro_cond)?

>
> void
> box_init(void)
> {
> 	fiber_cond_create(&ro_cond);
>-
>+	ro_checker = fiber_new_xc("check_ro", check_ro_f);
>+	fiber_start(ro_checker, NULL);
> 	user_cache_init();
> 	/*
> 	 * The order is important: to initialize sessions,
>@@ -1885,6 +1922,9 @@ box_cfg_xc(void)
> 		 */
> 		memtx_engine_recover_snapshot_xc(memtx,
> 				&last_checkpoint_vclock);
>+		if (run_on_ctl_event_trigger_type(CTL_EVENT_SYSTEM_SPACE_RECOVERY) < 0)
>+			say_error("ctl_trigger error in system space recovery: %s",
>+				  diag_last_error(diag_get())->errmsg);
>
> 		engine_begin_final_recovery_xc();
> 		recovery_follow_local(recovery, &wal_stream.base, "hot_standby",
>diff --git a/src/box/engine.c b/src/box/engine.c
>index 82293fd..fa78753 100644
>--- a/src/box/engine.c
>+++ b/src/box/engine.c
>@@ -29,10 +29,12 @@
>  * SUCH DAMAGE.
>  */
> #include "engine.h"
>+#include "ctl.h"
>
> #include <stdint.h>
> #include <string.h>
> #include <small/rlist.h>
>
>+#include <fiber.h>
Not used.
>
> RLIST_HEAD(engines);
>
>@@ -73,6 +75,14 @@ engine_bootstrap(void)
> 		if (engine->vtab->bootstrap(engine) != 0)
> 			return -1;
> 	}
>+	if (run_on_ctl_event_trigger_type(CTL_EVENT_SYSTEM_SPACE_RECOVERY) < 0)
>+		say_error("ctl_trigger error in system space recovery: %s",
>+			  diag_last_error(diag_get())->errmsg);
>+
>+	if (run_on_ctl_event_trigger_type(CTL_EVENT_LOCAL_RECOVERY) < 0)
>+		say_error("ctl_trigger error in local recovery: %s",
>+			  diag_last_error(diag_get())->errmsg);
>+
> 	return 0;
> }
>
>@@ -111,6 +121,10 @@ engine_end_recovery(void)
> 		if (engine->vtab->end_recovery(engine) != 0)
> 			return -1;
> 	}
>+	if (run_on_ctl_event_trigger_type(CTL_EVENT_LOCAL_RECOVERY) < 0)
>+		say_error("ctl_trigger error in local recovery: %s",
>+			  diag_last_error(diag_get())->errmsg);
>+
> 	return 0;
> }
>
>diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
>index 52f320a..5bd9be3 100644
>--- a/src/box/lua/ctl.c
>+++ b/src/box/lua/ctl.c
>@@ -122,8 +122,8 @@ box_lua_ctl_init(struct lua_State *L)
> 	lua_pushnumber(L, CTL_EVENT_SHUTDOWN);
> 	lua_setfield(L, -2, "SHUTDOWN");
> 	lua_pushnumber(L, CTL_EVENT_REPLICASET_ADD);
>-	lua_setfield(L, -2, "CTL_EVENT_REPLICASET_ADD");
>+	lua_setfield(L, -2, "REPLICASET_ADD");
> 	lua_pushnumber(L, CTL_EVENT_REPLICASET_REMOVE);
>-	lua_setfield(L, -2, "CTL_EVENT_REPLICASET_REMOVE");
>+	lua_setfield(L, -2, "REPLICASET_REMOVE");
> 	lua_pop(L, 2); /* box, ctl */
> }
>diff --git a/src/box/memtx_engine.c b/src/box/memtx_engine.c
>index fac84ce..e737ea3 100644
>--- a/src/box/memtx_engine.c
>+++ b/src/box/memtx_engine.c
>@@ -48,6 +48,7 @@
> #include "replication.h"
> #include "schema.h"
> #include "gc.h"
>
>+#include "ctl.h"
Also not used.
>
> static void
> txn_on_yield_or_stop(struct trigger *trigger, void *event)
>@@ -197,7 +198,6 @@ memtx_engine_recover_snapshot(struct memtx_engine *memtx,
> 	 */
> 	if (!xlog_cursor_is_eof(&cursor))
> 		panic("snapshot `%s' has no EOF marker", filename);
>-
> 	return 0;
> }
>
>diff --git a/src/box/replication.cc b/src/box/replication.cc
>index c1e1769..75aecd0 100644
>--- a/src/box/replication.cc
>+++ b/src/box/replication.cc
>@@ -41,6 +41,7 @@
> #include "error.h"
> #include "relay.h"
> #include "vclock.h" /* VCLOCK_MAX */
>+#include "ctl.h"
>
> uint32_t instance_id = REPLICA_ID_NIL;
> struct tt_uuid INSTANCE_UUID;
>@@ -172,6 +173,12 @@ replicaset_add(uint32_t replica_id, const struct tt_uuid *replica_uuid)
> 	replica->uuid = *replica_uuid;
> 	replica_hash_insert(&replicaset.hash, replica);
> 	replica_set_id(replica, replica_id);
>+	struct on_ctl_event_ctx on_ctl_ctx;
>+	on_ctl_ctx.type = CTL_EVENT_REPLICASET_ADD;
>+	on_ctl_ctx.replica_id = replica_id;
>+	if (run_on_ctl_event_triggers(&on_ctl_ctx) < 0)
>+		say_error("ctl_trigger error in replica add: %s",
>+			  diag_last_error(diag_get())->errmsg);
> 	return replica;
> }
>
>@@ -203,12 +210,19 @@ replica_clear_id(struct replica *replica)
> 	 * Some records may arrive later on due to asynchronous nature of
> 	 * replication.
> 	 */
>+	struct on_ctl_event_ctx on_ctl_ctx;
>+	on_ctl_ctx.type = CTL_EVENT_REPLICASET_REMOVE;
>+	on_ctl_ctx.replica_id = replica->id;
>+
> 	replicaset.replica_by_id[replica->id] = NULL;
> 	replica->id = REPLICA_ID_NIL;
> 	if (replica_is_orphan(replica)) {
> 		replica_hash_remove(&replicaset.hash, replica);
> 		replica_delete(replica);
> 	}
>+	if (run_on_ctl_event_triggers(&on_ctl_ctx) < 0)
>+		say_error("ctl_trigger error in replica remove: %s",
>+			  diag_last_error(diag_get())->errmsg);
> }
>
> static void
>diff --git a/test/replication/master_onctl.lua b/test/replication/master_onctl.lua
>new file mode 100644
>index 0000000..e0eb39a
>--- /dev/null
>+++ b/test/replication/master_onctl.lua
>@@ -0,0 +1,34 @@
>+#!/usr/bin/env tarantool
>+os = require('os')
>+
>+SYSTEM_SPACE_RECOVERY = 0
>+LOCAL_RECOVERY = 0
>+READ_ONLY = 0
>+READ_WRITE = 0
>+REPLICASET_ADD = {}
>+REPLICASET_REMOVE = {}
>+
>+local function onctl(ctx)
>+    if ctx.type == box.ctl.event.SYSTEM_SPACE_RECOVERY then
>+        SYSTEM_SPACE_RECOVERY = SYSTEM_SPACE_RECOVERY + 1
>+    elseif ctx.type == box.ctl.event.LOCAL_RECOVERY then
>+        LOCAL_RECOVERY = LOCAL_RECOVERY + 1
>+    elseif ctx.type == box.ctl.event.READ_ONLY then
>+        READ_ONLY = READ_ONLY + 1
>+    elseif ctx.type == box.ctl.event.READ_WRITE then
>+        READ_WRITE = READ_WRITE + 1
>+    elseif ctx.type == box.ctl.event.REPLICASET_ADD then
>+        table.insert(REPLICASET_ADD, ctx.replica_id)
>+    elseif ctx.type == box.ctl.event.REPLICASET_REMOVE then
>+        table.insert(REPLICASET_REMOVE, ctx.replica_id)
>+    end
>+end
>+
>+box.cfg({
>+    listen              = os.getenv("LISTEN"),
>+    memtx_memory        = 107374182,
>+    replication_connect_timeout = 0.5,
>+    on_ctl_event        = onctl,
>+})
>+
>+require('console').listen(os.getenv('ADMIN'))
>diff --git a/test/replication/onctl.result b/test/replication/onctl.result
>new file mode 100644
>index 0000000..19b3e67
>--- /dev/null
>+++ b/test/replication/onctl.result
>@@ -0,0 +1,250 @@
>+env = require('test_run')
>+---
>+...
>+test_run = env.new()
>+---
>+...
>+test_run:cmd("create server master with script='replication/master_onctl.lua'")
>+---
>+- true
>+...
>+test_run:cmd("create server replica with rpl_master=master, script='replication/replica_onctl.lua'")
>+---
>+- true
>+...
>+test_run:cmd("start server master")
>+---
>+- true
>+...
>+test_run:cmd("switch master")
>+---
>+- true
>+...
>+box.schema.user.grant('guest', 'replication')
>+---
>+...
>+SYSTEM_SPACE_RECOVERY
>+---
>+- 1
>+...
>+LOCAL_RECOVERY
>+---
>+- 1
>+...
>+READ_ONLY
>+---
>+- 0
>+...
>+READ_WRITE
>+---
>+- 1
>+...
>+-- must be two entries. First from bootstrap.snap, second for current instance.
>+REPLICASET_ADD
>+---
>+- - 1
>+  - 1
>+...
>+-- must be one entry. Deletion of initial tuple in _cluster space.
>+REPLICASET_REMOVE
>+---
>+- - 1
>+...
>+REPLICASET_ADD = {}
>+---
>+...
>+REPLICASET_REMOVE = {}
>+---
>+...
>+new_replica_id = 0
>+---
>+...
>+deleted_replica_id = 0
>+---
>+...
>+test_run:cmd("setopt delimiter ';'")
>+---
>+- true
>+...
>+function on_ctl_new(ctx)
>+    if ctx.type == box.ctl.event.REPLICASET_ADD then
>+        new_replica_id = ctx.replica_id
>+    elseif ctx.type == box.ctl.event.REPLICASET_REMOVE then
>+        deleted_replica_id = ctx.replica_id
>+    end
>+end;
>+---
>+...
>+test_run:cmd("setopt delimiter ''");
>+---
>+- true
>+...
>+_ = box.ctl.on_ctl_event(on_ctl_new)
>+---
>+...
>+test_run:cmd("start server replica")
>+---
>+- true
>+...
>+REPLICASET_ADD
>+---
>+- - 2
>+...
>+REPLICASET_REMOVE
>+---
>+- []
>+...
>+new_replica_id
>+---
>+- 2
>+...
>+deleted_replica_id
>+---
>+- 0
>+...
>+test_run:cmd("switch replica")
>+---
>+- true
>+...
>+test_run:cmd("setopt delimiter ';'")
>+---
>+- true
>+...
>+function on_ctl_shutdown(ctx)
>+    if ctx.type == box.ctl.event.SHUTDOWN then
>+        require("log").info("test replica shutdown")
>+    end
>+end;
>+---
>+...
>+function on_ctl_error(ctx)
>+    error("trigger error")
>+end;
>+---
>+...
>+test_run:cmd("setopt delimiter ''");
>+---
>+- true
>+...
>+SYSTEM_SPACE_RECOVERY
>+---
>+- 1
>+...
>+LOCAL_RECOVERY
>+---
>+- 1
>+...
>+READ_ONLY
>+---
>+- 0
>+...
>+READ_WRITE
>+---
>+- 1
>+...
>+REPLICASET_ADD
>+---
>+- - 2
>+...
>+REPLICASET_REMOVE
>+---
>+- []
>+...
>+box.cfg{read_only = true}
>+---
>+...
>+fiber = require("fiber")
>+---
>+...
>+while READ_ONLY == 0 do fiber.sleep(0.001) end
>+---
>+...
>+READ_ONLY
>+---
>+- 1
>+...
>+box.cfg{on_ctl_event = on_ctl_error}
>+---
>+...
>+box.cfg{read_only = false}
>+---
>+...
>+test_run:grep_log('replica', 'ctl_trigger error')
>+---
>+- ctl_trigger error
>+...
>+box.cfg{on_ctl_event = {box.NULL, on_ctl_error}}
>+---
>+...
>+box.cfg{on_ctl_event = on_ctl_shutdown}
>+---
>+...
>+test_run:cmd("restart server replica")
>+-- TODO: test SHUTDOWN, when it is possible to grep logs of killed replica.
>+--test_run:grep_log('replica', 'test replica shutdown')
>+test_run:cmd("switch master")
>+---
>+- true
>+...
>+box.schema.user.revoke('guest', 'replication')
>+---
>+...
>+_ = box.space._cluster:delete{2}
>+---
>+...
>+SYSTEM_SPACE_RECOVERY
>+---
>+- 1
>+...
>+LOCAL_RECOVERY
>+---
>+- 1
>+...
>+READ_ONLY
>+---
>+- 0
>+...
>+READ_WRITE
>+---
>+- 1
>+...
>+REPLICASET_ADD
>+---
>+- - 2
>+...
>+REPLICASET_REMOVE
>+---
>+- - 2
>+...
>+new_replica_id
>+---
>+- 2
>+...
>+deleted_replica_id
>+---
>+- 2
>+...
>+box.ctl.on_ctl_event(nil, on_ctl_new)
>+---
>+...
>+-- cleanup
>+test_run:cmd("switch default")
>+---
>+- true
>+...
>+test_run:cmd("stop server master")
>+---
>+- true
>+...
>+test_run:cmd("cleanup server master")
>+---
>+- true
>+...
>+test_run:cmd("stop server replica")
>+---
>+- true
>+...
>+test_run:cmd("cleanup server replica")
>+---
>+- true
>+...
>diff --git a/test/replication/onctl.test.lua b/test/replication/onctl.test.lua
>new file mode 100644
>index 0000000..ff6a898
>--- /dev/null
>+++ b/test/replication/onctl.test.lua
>@@ -0,0 +1,105 @@
>+env = require('test_run')
>+test_run = env.new()
>+
>+test_run:cmd("create server master with script='replication/master_onctl.lua'")
>+test_run:cmd("create server replica with rpl_master=master, script='replication/replica_onctl.lua'")
>+
>+test_run:cmd("start server master")
>+test_run:cmd("switch master")
>+box.schema.user.grant('guest', 'replication')
>+
>+SYSTEM_SPACE_RECOVERY
>+LOCAL_RECOVERY
>+READ_ONLY
>+READ_WRITE
>+-- must be two entries. First from bootstrap.snap, second for current instance.
>+REPLICASET_ADD
>+-- must be one entry. Deletion of initial tuple in _cluster space.
>+REPLICASET_REMOVE
>+
>+REPLICASET_ADD = {}
>+REPLICASET_REMOVE = {}
>+
>+new_replica_id = 0
>+deleted_replica_id = 0
>+
>+test_run:cmd("setopt delimiter ';'")
>+function on_ctl_new(ctx)
>+    if ctx.type == box.ctl.event.REPLICASET_ADD then
>+        new_replica_id = ctx.replica_id
>+    elseif ctx.type == box.ctl.event.REPLICASET_REMOVE then
>+        deleted_replica_id = ctx.replica_id
>+    end
>+end;
>+test_run:cmd("setopt delimiter ''");
>+
>+_ = box.ctl.on_ctl_event(on_ctl_new)
>+
>+test_run:cmd("start server replica")
>+
>+REPLICASET_ADD
>+REPLICASET_REMOVE
>+
>+new_replica_id
>+deleted_replica_id
>+
>+test_run:cmd("switch replica")
>+
>+test_run:cmd("setopt delimiter ';'")
>+function on_ctl_shutdown(ctx)
>+    if ctx.type == box.ctl.event.SHUTDOWN then
>+        require("log").info("test replica shutdown")
>+    end
>+end;
>+
>+function on_ctl_error(ctx)
>+    error("trigger error")
>+end;
>+
>+test_run:cmd("setopt delimiter ''");
>+
>+SYSTEM_SPACE_RECOVERY
>+LOCAL_RECOVERY
>+READ_ONLY
>+READ_WRITE
>+REPLICASET_ADD
>+REPLICASET_REMOVE
>+
>+box.cfg{read_only = true}
>+fiber = require("fiber")
>+while READ_ONLY == 0 do fiber.sleep(0.001) end
>+READ_ONLY
>+
>+box.cfg{on_ctl_event = on_ctl_error}
>+box.cfg{read_only = false}
>+test_run:grep_log('replica', 'ctl_trigger error')
>+box.cfg{on_ctl_event = {box.NULL, on_ctl_error}}
>+box.cfg{on_ctl_event = on_ctl_shutdown}
>+
>+test_run:cmd("restart server replica")
>+-- TODO: test SHUTDOWN, when it is possible to grep logs of killed replica.
>+--test_run:grep_log('replica', 'test replica shutdown') 
It should be done
>
>+
>+
>+test_run:cmd("switch master")
>+box.schema.user.revoke('guest', 'replication')
>+_ = box.space._cluster:delete{2}
>+
>+SYSTEM_SPACE_RECOVERY
>+LOCAL_RECOVERY
>+READ_ONLY
>+READ_WRITE
>+REPLICASET_ADD
>+REPLICASET_REMOVE
>+
>+new_replica_id
>+deleted_replica_id
>+
>+box.ctl.on_ctl_event(nil, on_ctl_new)
>+
>+-- cleanup
>+test_run:cmd("switch default")
>+test_run:cmd("stop server master")
>+test_run:cmd("cleanup server master")
>+test_run:cmd("stop server replica")
>+test_run:cmd("cleanup server replica")
>diff --git a/test/replication/replica_onctl.lua b/test/replication/replica_onctl.lua
>new file mode 100644
>index 0000000..d6ce73c
>--- /dev/null
>+++ b/test/replication/replica_onctl.lua
>@@ -0,0 +1,34 @@
>+#!/usr/bin/env tarantool
>+
>+SYSTEM_SPACE_RECOVERY = 0
>+LOCAL_RECOVERY = 0
>+READ_ONLY = 0
>+READ_WRITE = 0
>+REPLICASET_ADD = {}
>+REPLICASET_REMOVE = {}
>+
>+local function onctl(ctx)
>+    if ctx.type == box.ctl.event.SYSTEM_SPACE_RECOVERY then
>+        SYSTEM_SPACE_RECOVERY = SYSTEM_SPACE_RECOVERY + 1
>+    elseif ctx.type == box.ctl.event.LOCAL_RECOVERY then
>+        LOCAL_RECOVERY = LOCAL_RECOVERY + 1
>+    elseif ctx.type == box.ctl.event.READ_ONLY then
>+        READ_ONLY = READ_ONLY + 1
>+    elseif ctx.type == box.ctl.event.READ_WRITE then
>+        READ_WRITE = READ_WRITE + 1
>+    elseif ctx.type == box.ctl.event.REPLICASET_ADD then
>+        table.insert(REPLICASET_ADD, ctx.replica_id)
>+    elseif ctx.type == box.ctl.event.REPLICASET_REMOVE then
>+        table.insert(REPLICASET_REMOVE, ctx.replica_id)
>+    end
>+end
>+
>+box.cfg({
>+    listen              = os.getenv("LISTEN"),
>+    replication         = os.getenv("MASTER"),
>+    memtx_memory        = 107374182,
>+    replication_connect_timeout = 0.5,
>+    on_ctl_event        = onctl,
>+})
>+
>+require('console').listen(os.getenv('ADMIN'))
>diff --git a/test/replication/suite.cfg b/test/replication/suite.cfg
>index 95e94e5..365a825 100644
>--- a/test/replication/suite.cfg
>+++ b/test/replication/suite.cfg
>@@ -6,6 +6,7 @@
>     "wal_off.test.lua": {},
>     "hot_standby.test.lua": {},
>     "rebootstrap.test.lua": {},
>+    "onctl.test.lua": {},
>     "*": {
>         "memtx": {"engine": "memtx"},
>         "vinyl": {"engine": "vinyl"}
>-- 
>2.7.4
>
>


Best regards,
Konstantin Belyavskiy
k.belyavskiy@tarantool.org

[-- Attachment #2: Type: text/html, Size: 23719 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [tarantool-patches] Re: [tarantool-patches] [box.ctl 3/3] box.ctl: Add replica error event
  2018-06-14 15:04 ` [tarantool-patches] [box.ctl 3/3] box.ctl: Add replica error event Ilya Markov
@ 2018-07-31 11:40   ` Konstantin Belyavskiy
  0 siblings, 0 replies; 7+ messages in thread
From: Konstantin Belyavskiy @ 2018-07-31 11:40 UTC (permalink / raw)
  To: georgy,
	Илья
	Марков
  Cc: tarantool-patches

[-- Attachment #1: Type: text/plain, Size: 5355 bytes --]

Hi,
Overall patch looks good with minor complains:
- unused header.


>Четверг, 14 июня 2018, 18:04 +03:00 от Ilya Markov <imarkov@tarantool.org>:
>
>Add event: replica fails with some error.
>
>In scope of #3159
>---
> src/box/ctl.h                     |  1 +
> src/box/lua/ctl.c                 |  6 +++++-
> src/box/relay.cc                  |  7 +++++++
> test/replication/master_onctl.lua |  3 +++
> test/replication/onctl.result     | 12 ++++++++++++
> test/replication/onctl.test.lua   |  5 ++++-
> 6 files changed, 32 insertions(+), 2 deletions(-)
>
>diff --git a/src/box/ctl.h b/src/box/ctl.h
>index 1dbb6be..db6f08a 100644
>--- a/src/box/ctl.h
>+++ b/src/box/ctl.h
>@@ -49,6 +49,7 @@ enum ctl_event_type {
> 	CTL_EVENT_SHUTDOWN,
> 	CTL_EVENT_REPLICASET_ADD,
> 	CTL_EVENT_REPLICASET_REMOVE,
>+	CTL_EVENT_REPLICA_CONNECTION_ERROR,
> };
>
> struct on_ctl_event_ctx {
>diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
>index 5bd9be3..8a0dfc2 100644
>--- a/src/box/lua/ctl.c
>+++ b/src/box/lua/ctl.c
>@@ -37,6 +37,7 @@
> #include <lualib.h>
> #include <lua/trigger.h>
> #include <box/ctl.h>
>
>+#include <tt_uuid.h> 
Please remove it, since it's unused.
>
>
> #include "lua/utils.h"
>
>@@ -77,7 +78,8 @@ lbox_push_on_ctl_event(struct lua_State *L, void *event)
> 	lua_settable(L, -3);
>
> 	if (ctx->type == CTL_EVENT_REPLICASET_ADD ||
>-		ctx->type == CTL_EVENT_REPLICASET_REMOVE) {
>+		ctx->type == CTL_EVENT_REPLICASET_REMOVE ||
>+		ctx->type == CTL_EVENT_REPLICA_CONNECTION_ERROR) {
> 		lua_pushstring(L, "replica_id");
> 		luaL_pushuint64(L, ctx->replica_id);
> 		lua_settable(L, -3);
>@@ -125,5 +127,7 @@ box_lua_ctl_init(struct lua_State *L)
> 	lua_setfield(L, -2, "REPLICASET_ADD");
> 	lua_pushnumber(L, CTL_EVENT_REPLICASET_REMOVE);
> 	lua_setfield(L, -2, "REPLICASET_REMOVE");
>+	lua_pushnumber(L, CTL_EVENT_REPLICA_CONNECTION_ERROR);
>+	lua_setfield(L, -2, "REPLICA_CONNECTION_ERROR");
> 	lua_pop(L, 2); /* box, ctl */
> }
>diff --git a/src/box/relay.cc b/src/box/relay.cc
>index a25cc54..d535f83 100644
>--- a/src/box/relay.cc
>+++ b/src/box/relay.cc
>@@ -52,6 +52,7 @@
> #include "xrow_io.h"
> #include "xstream.h"
> #include "wal.h"
>+#include "ctl.h"
>
> /**
>  * Cbus message to send status updates from relay to tx thread.
>@@ -548,6 +549,12 @@ relay_subscribe_f(va_list ap)
> 	if (!diag_is_empty(&relay->diag)) {
> 		/* An error has occurred while reading ACKs of xlog. */
> 		diag_move(&relay->diag, diag_get());
>+		struct on_ctl_event_ctx ctx;
>+		ctx.type = CTL_EVENT_REPLICA_CONNECTION_ERROR;
>+		ctx.replica_id = relay->replica->id;
>+		if (run_on_ctl_event_triggers(&ctx) < 0)
>+			say_error("ctl_trigger error in replica error: %s",
>+				  diag_last_error(diag_get())->errmsg);
> 		/* Reference the diag in the status. */
> 		diag_add_error(&relay->diag, diag_last_error(diag_get()));
> 	}
>diff --git a/test/replication/master_onctl.lua b/test/replication/master_onctl.lua
>index e0eb39a..355e791 100644
>--- a/test/replication/master_onctl.lua
>+++ b/test/replication/master_onctl.lua
>@@ -7,6 +7,7 @@ READ_ONLY = 0
> READ_WRITE = 0
> REPLICASET_ADD = {}
> REPLICASET_REMOVE = {}
>+REPLICA_CONNECTION_ERROR = {}
>
> local function onctl(ctx)
>     if ctx.type == box.ctl.event.SYSTEM_SPACE_RECOVERY then
>@@ -21,6 +22,8 @@ local function onctl(ctx)
>         table.insert(REPLICASET_ADD, ctx.replica_id)
>     elseif ctx.type == box.ctl.event.REPLICASET_REMOVE then
>         table.insert(REPLICASET_REMOVE, ctx.replica_id)
>+    elseif ctx.type == box.ctl.event.REPLICA_CONNECTION_ERROR then
>+        table.insert(REPLICA_CONNECTION_ERROR, ctx.replica_id)
>     end
> end
>
>diff --git a/test/replication/onctl.result b/test/replication/onctl.result
>index 19b3e67..24a6683 100644
>--- a/test/replication/onctl.result
>+++ b/test/replication/onctl.result
>@@ -50,6 +50,10 @@ REPLICASET_REMOVE
> ---
> - - 1
> ...
>+REPLICA_CONNECTION_ERROR
>+---
>+- []
>+...
> REPLICASET_ADD = {}
> ---
> ...
>@@ -94,6 +98,10 @@ REPLICASET_REMOVE
> ---
> - []
> ...
>+REPLICA_CONNECTION_ERROR
>+---
>+- []
>+...
> new_replica_id
> ---
> - 2
>@@ -186,6 +194,10 @@ test_run:cmd("switch master")
> ---
> - true
> ...
>+REPLICA_CONNECTION_ERROR
>+---
>+- - 2
>+...
> box.schema.user.revoke('guest', 'replication')
> ---
> ...
>diff --git a/test/replication/onctl.test.lua b/test/replication/onctl.test.lua
>index ff6a898..352b118 100644
>--- a/test/replication/onctl.test.lua
>+++ b/test/replication/onctl.test.lua
>@@ -16,6 +16,7 @@ READ_WRITE
> REPLICASET_ADD
> -- must be one entry. Deletion of initial tuple in _cluster space.
> REPLICASET_REMOVE
>+REPLICA_CONNECTION_ERROR
>
> REPLICASET_ADD = {}
> REPLICASET_REMOVE = {}
>@@ -39,6 +40,7 @@ test_run:cmd("start server replica")
>
> REPLICASET_ADD
> REPLICASET_REMOVE
>+REPLICA_CONNECTION_ERROR
>
> new_replica_id
> deleted_replica_id
>@@ -80,8 +82,9 @@ test_run:cmd("restart server replica")
> -- TODO: test SHUTDOWN, when it is possible to grep logs of killed replica.
> --test_run:grep_log('replica', 'test replica shutdown')
>
>-
> test_run:cmd("switch master")
>+REPLICA_CONNECTION_ERROR
>+
> box.schema.user.revoke('guest', 'replication')
> _ = box.space._cluster:delete{2}
>
>-- 
>2.7.4
>
>


Best regards,
Konstantin Belyavskiy
k.belyavskiy@tarantool.org

[-- Attachment #2: Type: text/html, Size: 7087 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-07-31 11:40 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-14 15:04 [tarantool-patches] [box.ctl 0/3] Introduce box.ctl.on_ctl_event trigger Ilya Markov
2018-06-14 15:04 ` [tarantool-patches] [box.ctl 1/3] box.ctl: Introduce stab box.ctl.on_ctl_event Ilya Markov
2018-07-31 11:40   ` [tarantool-patches] " Konstantin Belyavskiy
2018-06-14 15:04 ` [tarantool-patches] [box.ctl 2/3] box.ctl: Add on_ctl_event trigger calls Ilya Markov
2018-07-31 11:40   ` [tarantool-patches] " Konstantin Belyavskiy
2018-06-14 15:04 ` [tarantool-patches] [box.ctl 3/3] box.ctl: Add replica error event Ilya Markov
2018-07-31 11:40   ` [tarantool-patches] " Konstantin Belyavskiy

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