From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id A81C12BCCD for ; Tue, 27 Mar 2018 17:24:20 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OP9tR7q238al for ; Tue, 27 Mar 2018 17:24:20 -0400 (EDT) Received: from smtp43.i.mail.ru (smtp43.i.mail.ru [94.100.177.103]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 6187C2B747 for ; Tue, 27 Mar 2018 17:24:20 -0400 (EDT) From: Vladislav Shpilevoy Subject: [tarantool-patches] [PATCH vshard 4/7] storage: wrap bucket status checks into functions Date: Wed, 28 Mar 2018 00:24:11 +0300 Message-Id: <3c09922e0e31ae4d19570c09a8d9df38f1712b17.1522185711.git.v.shpilevoy@tarantool.org> In-Reply-To: References: In-Reply-To: References: Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org Cc: georgy@tarantool.org, Vladislav Shpilevoy 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)