[tarantool-patches] [PATCH vshard 4/7] storage: wrap bucket status checks into functions

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Wed Mar 28 00:24:11 MSK 2018


It is hard to update all places, where statuses are used, when
a new status is added.
---
 vshard/storage/init.lua | 79 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 55 insertions(+), 24 deletions(-)

diff --git a/vshard/storage/init.lua b/vshard/storage/init.lua
index 471d26a..fe8a40f 100644
--- a/vshard/storage/init.lua
+++ b/vshard/storage/init.lua
@@ -100,6 +100,29 @@ local function is_this_replicaset_locked()
     return M.this_replicaset and M.this_replicaset.lock
 end
 
+--
+-- Check if @a bucket can accept 'write' requests. Writable
+-- buckets can accept 'read' too.
+--
+local function bucket_is_writable(bucket)
+    return bucket.status == consts.BUCKET.ACTIVE
+end
+
+--
+-- Check if @a bucket can accept 'read' requests.
+--
+local function bucket_is_readable(bucket)
+    return bucket_is_writable(bucket) or bucket.status == consts.BUCKET.SENDING
+end
+
+--
+-- Check if a bucket is sending or receiving.
+--
+local function bucket_is_transfer_in_progress(bucket)
+    return bucket.status == consts.BUCKET.SENDING or
+           bucket.status == consts.BUCKET.RECEIVING
+end
+
 --
 -- Check if @a bucket is garbage. It is true for
 -- * sent buckets;
@@ -192,7 +215,7 @@ end
 -- Check if a local bucket can be deleted.
 --
 local function recovery_local_bucket_is_garbage(local_bucket, remote_bucket)
-    return remote_bucket and remote_bucket.status == consts.BUCKET.ACTIVE
+    return remote_bucket and bucket_is_writable(remote_bucket)
 end
 
 --
@@ -242,8 +265,7 @@ local function recovery_step()
         end
         is_empty = false
         local bucket = _bucket:get{bucket_id}
-        if not bucket or (bucket.status ~= consts.BUCKET.SENDING and
-                          bucket.status ~= consts.BUCKET.RECEIVING) then
+        if not bucket or not bucket_is_transfer_in_progress(bucket) then
             -- Possibly, a bucket was deleted or recovered by
             -- an admin. Or recovery_f started not after
             -- bootstrap, but after master change - in such a case
@@ -399,24 +421,32 @@ local function bucket_check_state(bucket_id, mode)
     assert(mode == 'read' or mode == 'write')
     local bucket = box.space._bucket:get({bucket_id})
     local errcode = nil
-    if bucket == nil or bucket_is_garbage(bucket) or
-       bucket.status == consts.BUCKET.RECEIVING then
+    if not bucket then
         errcode = lerror.code.WRONG_BUCKET
-    elseif (bucket.status == consts.BUCKET.SENDING and mode ~= 'read') then
-        errcode = lerror.code.TRANSFER_IS_IN_PROGRESS
-    elseif bucket.status == consts.BUCKET.ACTIVE and mode ~= 'read' and
-           M.this_replicaset.master ~= M.this_replica then
+        goto finish
+    elseif mode == 'read' then
+        if not bucket_is_readable(bucket) then
+            errcode = lerror.code.WRONG_BUCKET
+            goto finish
+        end
+    elseif not bucket_is_writable(bucket) then
+        if bucket_is_transfer_in_progress(bucket) then
+            errcode = lerror.code.TRANSFER_IS_IN_PROGRESS
+        else
+            errcode = lerror.code.WRONG_BUCKET
+        end
+        goto finish
+    elseif M.this_replicaset.master ~= M.this_replica then
         errcode = lerror.code.NON_MASTER
-    end
-    if errcode ~= nil then
-        local dest = bucket and bucket.destination or nil
-        return bucket, lerror.vshard(errcode, {bucket_id = bucket_id,
-                                               destination = dest})
-    end
-
-    assert(bucket.status == consts.BUCKET.ACTIVE or
-           bucket.status == consts.BUCKET.SENDING and mode == 'read')
-    return bucket, nil
+        goto finish
+    end
+    assert(not errcode)
+    assert(mode == 'read' and bucket_is_readable(bucket) or
+           mode == 'write' and bucket_is_writable(bucket))
+::finish::
+    return bucket, errcode and
+           lerror.vshard(errcode, {bucket_id = bucket_id,
+                                   destination = bucket and bucket.destination})
 end
 
 --
@@ -1598,11 +1628,12 @@ local function storage_info()
     if is_this_replicaset_locked() then
         state.bucket.lock = true
     end
-    state.bucket.total = box.space._bucket.index.pk:count()
-    state.bucket.active = box.space._bucket.index.status:count({consts.BUCKET.ACTIVE})
-    state.bucket.garbage = box.space._bucket.index.status:count({consts.BUCKET.SENT})
-    state.bucket.receiving = box.space._bucket.index.status:count({consts.BUCKET.RECEIVING})
-    state.bucket.sending = box.space._bucket.index.status:count({consts.BUCKET.SENDING})
+    local status = box.space._bucket.index.status
+    state.bucket.total = box.space._bucket:count()
+    state.bucket.active = status:count({consts.BUCKET.ACTIVE})
+    state.bucket.garbage = status:count({consts.BUCKET.SENT})
+    state.bucket.receiving = status:count({consts.BUCKET.RECEIVING})
+    state.bucket.sending = status:count({consts.BUCKET.SENDING})
     if state.bucket.receiving ~= 0 and state.bucket.sending ~= 0 then
         --
         --Some buckets are receiving and some buckets are sending at same time,
-- 
2.14.3 (Apple Git-98)





More information about the Tarantool-patches mailing list