[tarantool-patches] [PATCH] Add a way to know instance is being run or restarted by tarantoolctl.

Serge Petrenko sergepetrenko at tarantool.org
Mon Jul 2 00:40:48 MSK 2018


There are some hacks to know the instance was run by tarantoolctl,
none of them are too reliable, thoug. This patch adds a convenient
way to know whether instance is being run or restarted by tarantoolctl.
For this purpose, we intoduce 2 new fields to box.info table:
box.info.tarantoolctl and box.info.is_restart, set to true, respectively,
if the instance is being run by tarantoolctl, and if it is being restarted.

Closes: #3215
---
https://github.com/tarantool/tarantool/tree/sergepetrenko/gh-3215-tarantoolctl-detection
https://github.com/tarantool/tarantool/issues/3215

 extra/dist/tarantoolctl.in |  9 +++++++++
 src/box/lua/info.c         | 15 +++++++++++++++
 src/main.cc                | 37 +++++++++++++++++++++++++++++++++++++
 src/main.h                 | 12 ++++++++++++
 test/box/info.result       | 10 ++++++++++
 test/box/info.test.lua     |  2 ++
 6 files changed, 85 insertions(+)

diff --git a/extra/dist/tarantoolctl.in b/extra/dist/tarantoolctl.in
index b6b8e09c9..e3212c14a 100755
--- a/extra/dist/tarantoolctl.in
+++ b/extra/dist/tarantoolctl.in
@@ -22,6 +22,7 @@ int kill(int pid, int sig);
 int isatty(int fd);
 int getppid(void);
 int chdir(const char *path);
+int setenv(const char *name, const char *value, int overwrite);
 ]]
 
 local TIMEOUT_INFINITY = 100 * 365 * 86400
@@ -509,6 +510,11 @@ local function start()
         log.error("The daemon is already running: PID %s", pid)
         os.exit(1)
     end
+
+    -- Set an environment variable for tarantool
+    -- to know it's being run under tarantoolctl.
+    ffi.C.setenv('TARANTOOLCTL', 'true', 0)
+
     box.cfg = wrapper_cfg
     require('title').update{
         script_name = instance_path,
@@ -593,6 +599,9 @@ local function restart()
     end
     stop()
     fiber.sleep(1)
+    -- Set an environment variable for tarantool to
+    -- know it's being restarted by tarantoolctl.
+    ffi.C.setenv('TARANTOOL_RESTART', 'true', 0)
     start()
     return 0
 end
diff --git a/src/box/lua/info.c b/src/box/lua/info.c
index d6697df9c..9b29d1320 100644
--- a/src/box/lua/info.c
+++ b/src/box/lua/info.c
@@ -246,6 +246,19 @@ lbox_info_ro(struct lua_State *L)
 	return 1;
 }
 
+static int
+lbox_info_tarantoolctl(struct lua_State *L)
+{
+	lua_pushboolean(L, tarantool_under_tarantoolctl());
+	return 1;
+}
+
+static int
+lbox_info_is_restart(struct lua_State *L)
+{
+	lua_pushboolean(L, tarantool_is_restart());
+	return 1;
+}
 /*
  * Tarantool 1.6.x compat
  */
@@ -530,6 +543,8 @@ static const struct luaL_Reg lbox_info_dynamic_meta[] = {
 	{"signature", lbox_info_signature},
 	{"vclock", lbox_info_vclock},
 	{"ro", lbox_info_ro},
+	{"tarantoolctl", lbox_info_tarantoolctl},
+	{"is_restart", lbox_info_is_restart},
 	{"replication", lbox_info_replication},
 	{"status", lbox_info_status},
 	{"uptime", lbox_info_uptime},
diff --git a/src/main.cc b/src/main.cc
index a36a2b0d0..888926ec3 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -87,14 +87,41 @@ static int main_argc;
 static ev_signal ev_sigs[6];
 static const int ev_sig_count = sizeof(ev_sigs)/sizeof(*ev_sigs);
 
+static bool under_tarantoolctl;
+static bool is_restart;
+
 static double start_time;
 
+bool
+tarantool_under_tarantoolctl()
+{
+	return under_tarantoolctl;
+}
+
+bool
+tarantool_is_restart()
+{
+	return is_restart;
+}
+
 double
 tarantool_uptime(void)
 {
 	return ev_monotonic_now(loop()) - start_time;
 }
 
+/**
+ * Check if the instance is being run or restarted
+ * by tarantoolctl. In case it is, there will be
+ * TARANTOOLCTL (and maybe TARANTOOL_RESTART) environment
+ * variable set for us by tarantoolctl.
+ */
+void detect_tarantoolctl()
+{
+	under_tarantoolctl = getenv("TARANTOOLCTL") != NULL;
+	is_restart = getenv("TARANTOOL_RESTART") != NULL;
+}
+
 /**
 * Create a checkpoint from signal handler (SIGUSR1)
 */
@@ -523,6 +550,16 @@ load_cfg()
 	title_set_custom(cfg_gets("custom_proc_title"));
 	title_update();
 	box_cfg();
+
+	/*
+	 * tarantoolctl is a lua script executed by tarantool,
+	 * so the only valid place in tarantool to detect
+	 * tarantoolctl's presence is after the call to
+	 * tarantool_lua_run_script(), but before user code
+	 * execution. Doing it right after user calls
+	 * box.cfg{} seems to be the only way out.
+	 */
+	detect_tarantoolctl();
 }
 
 void
diff --git a/src/main.h b/src/main.h
index 221374144..c69b6a912 100644
--- a/src/main.h
+++ b/src/main.h
@@ -37,6 +37,18 @@
 extern "C" {
 #endif /* defined(__cplusplus) */
 
+/**
+ * Returns whether instance was run by tarantoolctl.
+ */
+bool
+tarantool_under_tarantoolctl();
+
+/**
+ * Returns whether the instance was restarted by tarantoolctl.
+ */
+bool
+tarantool_is_restart();
+
 double tarantool_uptime(void);
 
 void
diff --git a/test/box/info.result b/test/box/info.result
index 338463155..5b7a827bf 100644
--- a/test/box/info.result
+++ b/test/box/info.result
@@ -51,6 +51,14 @@ box.info.status
 ---
 - running
 ...
+box.info.tarantoolctl == true or box.info
+---
+- true
+...
+box.info.is_restart == false or box.info
+---
+- true
+...
 string.len(box.info.uptime) > 0
 ---
 - true
@@ -77,6 +85,7 @@ t
 - - cluster
   - gc
   - id
+  - is_restart
   - lsn
   - memory
   - pid
@@ -84,6 +93,7 @@ t
   - ro
   - signature
   - status
+  - tarantoolctl
   - uptime
   - uuid
   - vclock
diff --git a/test/box/info.test.lua b/test/box/info.test.lua
index 60ee3216d..828e21c56 100644
--- a/test/box/info.test.lua
+++ b/test/box/info.test.lua
@@ -14,6 +14,8 @@ box.info.signature >= 0
 box.info.ro == false
 box.info.replication[1].id
 box.info.status
+box.info.tarantoolctl == true or box.info
+box.info.is_restart == false or box.info
 string.len(box.info.uptime) > 0
 string.match(box.info.uptime, '^[1-9][0-9]*$') ~= nil
 box.info.cluster.uuid == box.space._schema:get{'cluster'}[2]
-- 
2.15.2 (Apple Git-101.1)





More information about the Tarantool-patches mailing list