[PATCH] box: add on_schema_init trigger

Serge Petrenko sergepetrenko at tarantool.org
Sat Mar 2 15:31:49 MSK 2019


This patch introduces an on_schema_init trigger. The trigger may be set
before box.cfg() is called and is called during box.cfg() right after
prototypes of system spaces, such as _space, are created. This allows to
set triggers on system spaces before any other non-system data is
recovered. For example, it is possible to set an on_replace trigger on
_space, which will work even during recovery.

Part of #3159

@TarantoolBot document
Title: document box.ctl.on_schema_init triggers
on_schema_init triggers are set before the first call to box.cfg() and
are fired during box.cfg() before user data recovery start.

To set the trigger, say
```
box.ctl.on_schema_init(new_trig, old_trig)
```
where `old_trig` may be omitted. This will replace `old_trig` with `new_trig`.
Such triggers let you, for example, set triggers on system spaces before
recovery of any data, so that the triggers are fired even during
recovery.
---
https://github.com/tarantool/tarantool/tree/sp/gh-3159-on-schema-init
https://github.com/tarantool/tarantool/issues/3159

The trigger name is open for discussion, I believe there are some other good
variants: box.ctl.on_bootstrap_start / box.ctl.on_recovery_start
I've put the tests in a new file because I intend to use it later for other
box.ctl. triggers.

 src/box/lua/ctl.c                        |  8 ++++++
 src/box/schema.cc                        |  9 +++++++
 src/box/schema.h                         |  1 +
 test/box-tap/ctl_on_schema_init.test.lua | 31 ++++++++++++++++++++++++
 4 files changed, 49 insertions(+)
 create mode 100755 test/box-tap/ctl_on_schema_init.test.lua

diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
index 7010be138..0767cf476 100644
--- a/src/box/lua/ctl.c
+++ b/src/box/lua/ctl.c
@@ -40,6 +40,7 @@
 #include "lua/trigger.h"
 
 #include "box/box.h"
+#include "box/schema.h"	/* on_schema_init triggers */
 
 static int
 lbox_ctl_wait_ro(struct lua_State *L)
@@ -71,10 +72,17 @@ lbox_ctl_on_shutdown(struct lua_State *L)
 	return lbox_trigger_reset(L, 2, &box_on_shutdown, NULL, NULL);
 }
 
+static int
+lbox_ctl_on_schema_init(struct lua_State *L)
+{
+	return lbox_trigger_reset(L, 2, &on_schema_init, NULL, NULL);
+}
+
 static const struct luaL_Reg lbox_ctl_lib[] = {
 	{"wait_ro", lbox_ctl_wait_ro},
 	{"wait_rw", lbox_ctl_wait_rw},
 	{"on_shutdown", lbox_ctl_on_shutdown},
+	{"on_schema_init", lbox_ctl_on_schema_init},
 	{NULL, NULL}
 };
 
diff --git a/src/box/schema.cc b/src/box/schema.cc
index 8625d92ea..b1c7c6059 100644
--- a/src/box/schema.cc
+++ b/src/box/schema.cc
@@ -69,6 +69,9 @@ uint32_t schema_version = 0;
  */
 uint32_t space_cache_version = 0;
 
+/** Triggers invoked after schema initialization. */
+struct rlist on_schema_init = RLIST_HEAD_INITIALIZER(on_schema_init);
+
 struct rlist on_alter_space = RLIST_HEAD_INITIALIZER(on_alter_space);
 struct rlist on_alter_sequence = RLIST_HEAD_INITIALIZER(on_alter_sequence);
 
@@ -500,6 +503,12 @@ schema_init()
 		init_system_space(space);
 		trigger_run_xc(&on_alter_space, space);
 	}
+
+	/*
+	 * Run the triggers right after creating all the system
+	 * space stubs.
+	 */
+	trigger_run(&on_schema_init, NULL);
 }
 
 void
diff --git a/src/box/schema.h b/src/box/schema.h
index f3df08b48..a2897cfab 100644
--- a/src/box/schema.h
+++ b/src/box/schema.h
@@ -43,6 +43,7 @@ extern "C" {
 
 extern uint32_t schema_version;
 extern uint32_t space_cache_version;
+extern struct rlist on_schema_init;
 
 /**
  * Lock of schema modification
diff --git a/test/box-tap/ctl_on_schema_init.test.lua b/test/box-tap/ctl_on_schema_init.test.lua
new file mode 100755
index 000000000..51b28ea08
--- /dev/null
+++ b/test/box-tap/ctl_on_schema_init.test.lua
@@ -0,0 +1,31 @@
+#!/usr/bin/env tarantool
+
+--
+-- gh-3159: test on_schema_init trigger
+--
+local tap = require('tap')
+local test = tap.test('on_schema_init')
+local str = ''
+test:plan(7)
+
+function testing_trig()
+    test:istable(box.space._space, 'system spaces are accessible')
+    test:is(type(box.space._space.before_replace), 'function', 'before_replace triggers')
+    test:is(type(box.space._space.on_replace), 'function', 'on_replace triggers')
+    test:is(type(box.space._space:on_replace(function() str = str.."_space:on_replace" end)),
+            'function', 'set on_replace trigger')
+    str = str..'on_schema_init'
+end
+
+trig = box.ctl.on_schema_init(testing_trig)
+test:is(type(trig), 'function', 'on_schema_init trigger set')
+
+box.cfg{log = 'tarantool.log'}
+test:like(str, 'on_schema_init', 'on_schema_init trigger works')
+str = ''
+box.schema.space.create("test")
+-- test that _space.on_replace trigger may be set in on_schema_init
+test:like(str, '_space:on_replace', 'can set on_replace')
+test:check()
+box.space.test:drop()
+os.exit(0)
-- 
2.17.2 (Apple Git-113)




More information about the Tarantool-patches mailing list