[tarantool-patches] Re: [PATCH 1/4] Fix races related to object outdating

  • From: Vladislav Shpilevoy <v.shpilevoy@xxxxxxxxxxxxx>
  • To: tarantool-patches@xxxxxxxxxxxxx, AKhatskevich <avkhatskevich@xxxxxxxxxxxxx>
  • Date: Mon, 30 Jul 2018 14:55:31 +0300

Hi! Thanks for the patch! See 1 comment below and fixes on
the branch in a separate commit. Please, look and squash.

On 30/07/2018 11:56, AKhatskevich wrote:

Reload/reconfigure may replace many of M fields during any yield.
Old objects should not be accessed after they are outdated.

This commit handles such cases within `vshard.router`.
---
  vshard/replicaset.lua   | 30 ++++++++++++++-----------
  vshard/router/init.lua  | 58 +++++++++++++++++++++++++++++--------------------
  vshard/storage/init.lua |  1 +
  3 files changed, 52 insertions(+), 37 deletions(-)

diff --git a/vshard/router/init.lua b/vshard/router/init.lua
index 142ddb6..1a0ed2f 100644
--- a/vshard/router/init.lua
+++ b/vshard/router/init.lua
@@ -88,15 +94,18 @@ local function bucket_discovery(bucket_id)
      log.verbose("Discovering bucket %d", bucket_id)
      local last_err = nil
      local unreachable_uuid = nil
-    for uuid, replicaset in pairs(M.replicasets) do
-        local _, err =
-            replicaset:callrw('vshard.storage.bucket_stat', {bucket_id})
-        if err == nil then
-            bucket_set(bucket_id, replicaset)
-            return replicaset
-        elseif err.code ~= lerror.code.WRONG_BUCKET then
-            last_err = err
-            unreachable_uuid = uuid
+    for uuid, _ in pairs(M.replicasets) do
+        -- Handle reload/reconfigure.
+        replicaset = M.replicasets[uuid]
+        if replicaset then
+            local _, err =
+                replicaset:callrw('vshard.storage.bucket_stat', {bucket_id})
+            if err == nil then
+                return bucket_set(bucket_id, replicaset.uuid)

Do not return error immediately. You can continue iteration in the hope
of finding the bucket out on one of next replicasets. So here you
do 'if bucket_set ~= nil then return result end'. Else continue.

+            elseif err.code ~= lerror.code.WRONG_BUCKET then
+                last_err = err
+                unreachable_uuid = uuid
+            end
          end
      end
      local err = nil

Other related posts: