[tarantool-patches] [PATCH 1/1] box: update listen and replication in a strict order

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Sat Sep 28 21:14:42 MSK 2019


box.cfg, being called with a table with several options, may
apply them in an arbitrary order because of how Lua stores
tables.

But sometimes the order matters. For example, when in one box.cfg
both listen and replication are updated. If replication includes
self, then it just won't work before listen.

The patch makes listen be applied always before replication. This
is done via introduction of a generic way to specify an order of
all box.cfg options at reconfiguration.

Closes #4433
---
Branch: https://github.com/tarantool/tarantool/tree/gerold103/gh-4433-replication-cfg-order
Issue: https://github.com/tarantool/tarantool/issues/4433

Note, there is no a test. Appeared, that order of keys in a Lua
table is too unstable. The same table is being iterated
differently in an interactive console, and in a test file. In
particular, these two cfgs:

    box.cfg{replication = {...}, listen = ...}
    box.cfg{listen = ..., replication = {...}}

Both update listen before replication even before my patch, by a
coincidence. But in an interactive console the first test hangs.

 src/box/lua/load_cfg.lua | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua
index 79bde4d23..8ae72767d 100644
--- a/src/box/lua/load_cfg.lua
+++ b/src/box/lua/load_cfg.lua
@@ -254,6 +254,32 @@ local dynamic_cfg = {
     net_msg_max             = private.cfg_set_net_msg_max,
 }
 
+--
+-- For some options it is important in which order they are set.
+-- For example, setting 'replication', including self, before
+-- 'listen' makes no sense:
+--
+--     box.cfg{replication = {'localhost:3301'}, listen = 3301}
+--
+-- Replication won't be able to connect to a not being listened
+-- port. In the table below for each option can be set a number.
+-- An option is set before all other options having a bigger
+-- number. Options without a number are installed after others in
+-- an undefined order. The table works for reconfiguration only.
+-- Order of first configuration is hardcoded in C and can't be
+-- changed.
+--
+local dynamic_cfg_order = {
+    listen                  = 100,
+    replication             = 200,
+}
+
+local function sort_cfg_cb(l, r)
+    l = dynamic_cfg_order[l] or math.huge
+    r = dynamic_cfg_order[r] or math.huge
+    return l < r
+end
+
 local dynamic_cfg_skip_at_load = {
     listen                  = true,
     memtx_memory            = true,
@@ -428,13 +454,16 @@ end
 local function reload_cfg(oldcfg, cfg)
     cfg = upgrade_cfg(cfg, translate_cfg)
     local newcfg = prepare_cfg(cfg, default_cfg, template_cfg, modify_cfg)
+    local ordered_cfg = {}
     -- iterate over original table because prepare_cfg() may store NILs
     for key, val in pairs(cfg) do
         if dynamic_cfg[key] == nil and oldcfg[key] ~= val then
             box.error(box.error.RELOAD_CFG, key);
         end
+        table.insert(ordered_cfg, key)
     end
-    for key in pairs(cfg) do
+    table.sort(ordered_cfg, sort_cfg_cb)
+    for _, key in pairs(ordered_cfg) do
         local val = newcfg[key]
         local oldval = oldcfg[key]
         if not compare_cfg(val, oldval) then
-- 
2.21.0 (Apple Git-122)





More information about the Tarantool-patches mailing list