[tarantool-patches] [PATCH] vshard: added prohibition of multiple router/storage configuration from different fibers

Евгений Заикин dmarc-noreply at freelists.org
Mon Aug 13 12:41:20 MSK 2018


Adds prohibition of multiple router/storage configuration from different fibers
Fixes: #140
---
 Ticket:https://github.com/tarantool/vshard/issues/140
 Branch:rave4life/gh-140-prohibit-multiple-cfg
 
 test/misc/vshard_multi_fiber_cfg.result   | 53 +++++++++++++++++++++++
 test/misc/vshard_multi_fiber_cfg.test.lua | 21 +++++++++
 vshard/router/init.lua                    | 20 +++++++--
 vshard/storage/init.lua                   | 18 +++++++-
 4 files changed, 107 insertions(+), 5 deletions(-)
 create mode 100644 test/misc/vshard_multi_fiber_cfg.result
 create mode 100644 test/misc/vshard_multi_fiber_cfg.test.lua

diff --git a/test/misc/vshard_multi_fiber_cfg.result b/test/misc/vshard_multi_fiber_cfg.result
new file mode 100644
index 0000000..21121eb
--- /dev/null
+++ b/test/misc/vshard_multi_fiber_cfg.result
@@ -0,0 +1,53 @@
+test_run = require('test_run').new()
+---
+...
+cfg.weights = nil
+---
+...
+sample_replica_id = '9519e546-e39b-4db8-a3bb-66a59fdea9fc'
+---
+...
+vshard = require('vshard')
+---
+...
+-- gh-140 - Prohibit vshard.router/storage.cfg from multiple fibers
+fiber = require('fiber')
+---
+...
+c = fiber.channel(2)
+---
+...
+sf = function() fiber.create(function() pcall(vshard.storage.cfg, cfg, sample_replica_id, false) c:put(true) end) end
+---
+...
+sf()
+---
+...
+sf()
+---
+...
+c:get()
+---
+- true
+...
+c:get()
+---
+- true
+...
+rf = function() fiber.create(function() pcall(vshard.router.cfg, cfg) c:put(true) end) end
+---
+...
+rf()
+---
+...
+rf()
+---
+...
+c:get()
+---
+- true
+...
+c:get()
+---
+- true
+...
diff --git a/test/misc/vshard_multi_fiber_cfg.test.lua b/test/misc/vshard_multi_fiber_cfg.test.lua
new file mode 100644
index 0000000..fd1aeda
--- /dev/null
+++ b/test/misc/vshard_multi_fiber_cfg.test.lua
@@ -0,0 +1,21 @@
+test_run = require('test_run').new()
+
+cfg.weights = nil
+
+sample_replica_id = '9519e546-e39b-4db8-a3bb-66a59fdea9fc'
+
+vshard = require('vshard')
+
+-- gh-140 - Prohibit vshard.router/storage.cfg from multiple fibers
+fiber = require('fiber')
+c = fiber.channel(2)
+sf = function() fiber.create(function() pcall(vshard.storage.cfg, cfg, sample_replica_id, false) c:put(true) end) end
+sf()
+sf()
+c:get()
+c:get()
+rf = function() fiber.create(function() pcall(vshard.router.cfg, cfg) c:put(true) end) end
+rf()
+rf()
+c:get()
+c:get()
diff --git a/vshard/router/init.lua b/vshard/router/init.lua
index 971d830..de0a143 100644
--- a/vshard/router/init.lua
+++ b/vshard/router/init.lua
@@ -2,6 +2,20 @@ local log = require('log')
 local lfiber = require('fiber')
 local table_new = require('table.new')
 
+-- Function decorator that is used to prevent router.cfg() from
+-- being called concurrently by different fibers.
+local lock = lfiber.channel(1)
+local function locked(f)
+    return function(...)
+        lock:put(true)
+        local status, err = pcall(f, ...)
+        lock:get()
+        if not status then
+            error(err)
+        end
+    end
+end
+
 local MODULE_INTERNALS = '__module_vshard_router'
 -- Reload requirements, in case this module is reloaded manually.
 if rawget(_G, MODULE_INTERNALS) then
@@ -856,7 +870,7 @@ end
 
 local router_mt = {
     __index = {
-        cfg = function(router, cfg) return router_cfg(router, cfg, false) end,
+        cfg = function(router, cfg) return locked(router_cfg)(router, cfg, false) end,
         info = router_info;
         buckets_info = router_buckets_info;
         call = router_call;
@@ -930,7 +944,7 @@ end
 local function legacy_cfg(cfg)
     if M.static_router then
         -- Reconfigure.
-        router_cfg(M.static_router, cfg, false)
+        locked(router_cfg)(M.static_router, cfg, false)
     else
         -- Create new static instance.
         local router, err = router_new(STATIC_ROUTER_NAME, cfg)
@@ -955,7 +969,7 @@ if not rawget(_G, MODULE_INTERNALS) then
     rawset(_G, MODULE_INTERNALS, M)
 else
     for _, router in pairs(M.routers) do
-        router_cfg(router, router.current_cfg, true)
+        locked(router_cfg)(router, router.current_cfg, true)
         setmetatable(router, router_mt)
     end
     if M.static_router then
diff --git a/vshard/storage/init.lua b/vshard/storage/init.lua
index b1ecb7b..d848145 100644
--- a/vshard/storage/init.lua
+++ b/vshard/storage/init.lua
@@ -4,6 +4,20 @@ local lfiber = require('fiber')
 local netbox = require('net.box') -- for net.box:self()
 local trigger = require('internal.trigger')
 
+-- Function decorator that is used to prevent storage.cfg() from
+-- being called concurrently by different fibers.
+local lock = lfiber.channel(1)
+local function locked(f)
+    return function(...)
+        lock:put(true)
+        local status, err = pcall(f, ...)
+        lock:get()
+        if not status then
+            error(err)
+        end
+    end
+end
+
 local MODULE_INTERNALS = '__module_vshard_storage'
 -- Reload requirements, in case this module is reloaded manually.
 if rawget(_G, MODULE_INTERNALS) then
@@ -1866,7 +1880,7 @@ if not rawget(_G, MODULE_INTERNALS) then
     rawset(_G, MODULE_INTERNALS, M)
 else
     reload_evolution.upgrade(M)
-    storage_cfg(M.current_cfg, M.this_replica.uuid, true)
+    locked(storage_cfg)(M.current_cfg, M.this_replica.uuid, true)
     M.module_version = M.module_version + 1
 end
 
@@ -1905,7 +1919,7 @@ return {
     rebalancing_is_in_progress = rebalancing_is_in_progress,
     recovery_wakeup = recovery_wakeup,
     call = storage_call,
-    cfg = function(cfg, uuid) return storage_cfg(cfg, uuid, false) end,
+    cfg = function(cfg, uuid) return locked(storage_cfg)(cfg, uuid, false) end,
     info = storage_info,
     buckets_info = storage_buckets_info,
     buckets_count = storage_buckets_count,
-- 
2.17.1.windows.1



More information about the Tarantool-patches mailing list