From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Serge Petrenko Subject: [PATCH] box: add on_schema_init trigger Date: Sat, 2 Mar 2019 15:31:49 +0300 Message-Id: <20190302123149.5115-1-sergepetrenko@tarantool.org> To: vdavydov.dev@gmail.com, kostja@tarantool.org Cc: tarantool-patches@freelists.org, Serge Petrenko List-ID: 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)