From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lf1-f46.google.com (mail-lf1-f46.google.com [209.85.167.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 4BD1E4696F5 for ; Thu, 19 Nov 2020 22:41:41 +0300 (MSK) Received: by mail-lf1-f46.google.com with SMTP id d17so9952156lfq.10 for ; Thu, 19 Nov 2020 11:41:41 -0800 (PST) From: Cyrill Gorcunov Date: Thu, 19 Nov 2020 22:40:59 +0300 Message-Id: <20201119194100.840495-4-gorcunov@gmail.com> In-Reply-To: <20201119194100.840495-1-gorcunov@gmail.com> References: <20201119194100.840495-1-gorcunov@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Tarantool-patches] [RFC 3/4] cfg: prepare symbolic evaluation of replication_synchro_quorum List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: tml Cc: Vladislav Shpilevoy Prepare scaffolds to evaluate replication_synchro_quorum, since we don't yet update the undeneath engines we accept and verify the formulas but refuse to proceed. In next patch we will support dynamic evaluation of the quorum number. Part-of #5446 Signed-off-by: Cyrill Gorcunov --- src/box/box.cc | 82 +++++++++++++++++++++++++++++++++++++++- src/box/box.h | 1 + src/box/lua/load_cfg.lua | 3 +- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/box/box.cc b/src/box/box.cc index 5fcf28cb3..5f7ddfa99 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -562,10 +562,90 @@ box_check_replication_sync_lag(void) return lag; } +/** + * Evaluate replicaion syncro quorum number from a formula. + */ +int +eval_replication_synchro_quorum(int nr_replicas) +{ + const char fmt[] = + "local f, err = loadstring(\"return (%s)\")\n" + "if not f then return 'failed to load \"%s\"' end\n" + "setfenv(f, { n = %d })\n" + "local ok, res = pcall(f)\n" + "if not ok then return res end\n" + "return math.floor(res)\n"; + char buf[512]; + int value = -1; + + errno = 0; + + const char *expr = cfg_gets("replication_synchro_quorum"); + size_t ret = snprintf(buf, sizeof(buf), fmt, expr, + expr, nr_replicas); + if (ret >= sizeof(buf)) { + errno = EINVAL; + diag_set(ClientError, ER_CFG, + "replication_synchro_quorum", + "the expression is too big"); + return -1; + } + + luaL_loadstring(tarantool_L, buf); + lua_call(tarantool_L, 0, 1); + + if (lua_isnumber(tarantool_L, -1)) { + value = (int)lua_tonumber(tarantool_L, -1); + } else { + assert(lua_isstring(tarantool_L, -1)); + errno = EINVAL; + diag_set(ClientError, ER_CFG, + "replication_synchro_quorum", + lua_tostring(tarantool_L, -1)); + } + lua_pop(tarantool_L, 1); + return value; +} + static int box_check_replication_synchro_quorum(void) { - int quorum = cfg_geti("replication_synchro_quorum"); + int quorum = 0; + + if (!cfg_isnumber("replication_synchro_quorum")) { + /* + * When validating a formula it must return a + * positive value for a single node and maximum + * possible replicas because the quorum will be + * evaluated on each new replica registration, + * starting from a single node. + */ + int v[] = {1, VCLOCK_MAX-1}; + for (size_t i = 0; i < lengthof(v); i++) { + quorum = eval_replication_synchro_quorum(v[i]); + if (quorum < 0 && errno == EINVAL) + return -1; + } + + /* + * Once syntax is valid we should pass the real + * default value from replication module itself + * to evaluate the actual value to use. + */ + int value = replication_synchro_quorum; + quorum = eval_replication_synchro_quorum(value); + /* + * FIXME: Until we get full support. + */ + diag_set(ClientError, ER_CFG, + "replication_synchro_quorum", + "symbolic evaluation is not yet supported"); + diag_log(); + quorum = -1; + } else { + quorum = cfg_geti("replication_synchro_quorum"); + } + if (quorum <= 0 || quorum >= VCLOCK_MAX) { diag_set(ClientError, ER_CFG, "replication_synchro_quorum", "the value must be greater than zero and less than " diff --git a/src/box/box.h b/src/box/box.h index b47a220b7..8f438faab 100644 --- a/src/box/box.h +++ b/src/box/box.h @@ -252,6 +252,7 @@ void box_set_replication_connect_timeout(void); void box_set_replication_connect_quorum(void); void box_set_replication_sync_lag(void); int box_set_replication_synchro_quorum(void); +int eval_replication_synchro_quorum(int nr_replicas); int box_set_replication_synchro_timeout(void); void box_set_replication_sync_timeout(void); void box_set_replication_skip_conflict(void); diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua index 76e2e92c2..26725e08d 100644 --- a/src/box/lua/load_cfg.lua +++ b/src/box/lua/load_cfg.lua @@ -172,7 +172,7 @@ local template_cfg = { replication_timeout = 'number', replication_sync_lag = 'number', replication_sync_timeout = 'number', - replication_synchro_quorum = 'number', + replication_synchro_quorum = 'string, number', replication_synchro_timeout = 'number', replication_connect_timeout = 'number', replication_connect_quorum = 'number', @@ -368,7 +368,6 @@ local dynamic_cfg_skip_at_load = { replication_connect_quorum = true, replication_sync_lag = true, replication_sync_timeout = true, - replication_synchro_quorum = true, replication_synchro_timeout = true, replication_skip_conflict = true, replication_anon = true, -- 2.26.2