From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 11A366F853; Sat, 13 Nov 2021 02:25:47 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 11A366F853 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1636759547; bh=MVsWfIXZJXrGjOPdL0OCuVqZjzEfoumMSE1Vs21qDEc=; h=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=ID5Qqi9nxRSyUS+IVhVDBxrCnaXm1jRnDcSm8KtrMYcP3oNAlz/9IuVMqUV9xctXp WqfZa0l0qs6OtxSPawtRqSRvrFlTuryQN1VWGn0is6AeE668gY6bjt8rUbtfRGKBrK Dar++KY3jpA/DMPmcM5GXf+je2ses3dhHn2sgiGw= Received: from smtpng1.i.mail.ru (smtpng1.i.mail.ru [94.100.181.251]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id D72FE6F853 for ; Sat, 13 Nov 2021 02:25:44 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org D72FE6F853 Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1mlfvT-000615-UY; Sat, 13 Nov 2021 02:25:44 +0300 Message-ID: <0e293f9e-1014-1f94-cfe9-efd36f313049@tarantool.org> Date: Sat, 13 Nov 2021 00:25:43 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:91.0) Gecko/20100101 Thunderbird/91.3.0 Content-Language: en-US To: tarantool-patches@dev.tarantool.org, sergepetrenko@tarantool.org References: In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-7564579A: 78E4E2B564C1792B X-77F55803: 4F1203BC0FB41BD9731B3922EC0639791BFBC8C450C80827E49496A0B58C59AD00894C459B0CD1B92D6304B5D1ADEAC23F519F0ED7BE4754FAD2CB537C7C45AAFEFE3136639EADCB X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE721B3E54BB37EA0B4EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F790063703E3935C5A8197E98638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D874F9AF9EF0E119FF15DB2A37B78779C4117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8BAA867293B0326636D2E47CDBA5A96583BA9C0B312567BB231DD303D21008E29813377AFFFEAFD269A417C69337E82CC2E827F84554CEF50127C277FBC8AE2E8BA83251EDC214901ED5E8D9A59859A8B6B1CFA6D474D4A6A4089D37D7C0E48F6C5571747095F342E88FB05168BE4CE3AF X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A213B5FB47DCBC3458834459D11680B50544ABBB58A88CF8DF2503AD2AA3768C2A X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C4C7A0BC55FA0FE5FC3DE189F34CB7C92FE24B084000BF5039F27B3C3F35BFC989B1881A6453793CE9C32612AADDFBE061C61BE10805914D3804EBA3D8E7E5B87ABF8C51168CD8EBDBE96A3A8AAADC8934DC48ACC2A39D04F89CDFB48F4795C241BDAD6C7F3747799A X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D346F8291983715AC665B199FD495285D7DED0FA0162143AE4C61DCADD807D6298DFBF11E5A453FAB5E1D7E09C32AA3244C41541789A369BC2EE6F8A75742DB52149CA7333006C390A0729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojLk+X/GdHsno/3NU71mms4w== X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5DAAF36B5D08D9C525D927081E182FCCDC3841015FED1DE5223CC9A89AB576DD93FB559BB5D741EB963CF37A108A312F5C27E8A8C3839CE0E267EA787935ED9F1B X-Mras: Ok Subject: [Tarantool-patches] [PATCH v2 12/11] error: introduce box.info.ro_reason X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Vladislav Shpilevoy via Tarantool-patches Reply-To: Vladislav Shpilevoy Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" Follow-up #5568 @TarantoolBot document Title: box.info.ro_reason The new `box.info` field - `ro_reason` - is `nil` on a writable instance. On a read-only instance `box.info.ro == true` it reports an error reason. Currently the list is - `'election'` - `box.cfg.election_mode` is not `'off'` and this instance is not a leader. See `box.info.election` for details. - `'synchro'` - the synchro queue is owned by some other instance. For details see `box.info.synchro`. - `'config'` - `box.cfg.read_only` is true; - `'orphan'` - the instance is in orphan state. --- diff --git a/changelogs/unreleased/gh-5568-readonly-reason.md b/changelogs/unreleased/gh-5568-readonly-reason.md index f3a2db986..d2985eede 100644 --- a/changelogs/unreleased/gh-5568-readonly-reason.md +++ b/changelogs/unreleased/gh-5568-readonly-reason.md @@ -1,4 +1,6 @@ ## feature/core * Error objects with the code `box.error.READONLY` now have additional fields - explaining why the error happened (gh-5568). + explaining why the error happened. + Also there is a new field `box.info.ro_reason`. It is `nil` on a writable + instance, but reports a reason when `box.info.ro` is true (gh-5568). diff --git a/src/box/box.cc b/src/box/box.cc index f776c82c1..c3bdff2f5 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -174,6 +174,20 @@ box_update_ro_summary(void) fiber_cond_broadcast(&ro_cond); } +const char * +box_ro_reason(void) +{ + if (raft_is_ro(box_raft())) + return "election"; + if (txn_limbo_is_ro(&txn_limbo)) + return "synchro"; + if (is_ro) + return "config"; + if (is_orphan) + return "orphan"; + assert(false); +} + static int box_check_writable(void) { diff --git a/src/box/box.h b/src/box/box.h index 14278a294..83fdba332 100644 --- a/src/box/box.h +++ b/src/box/box.h @@ -152,6 +152,13 @@ box_do_set_orphan(bool orphan); void box_update_ro_summary(void); +/** + * Get the reason why the instance is read only if it is. Can't be called on a + * writable instance. + */ +const char * +box_ro_reason(void); + /** * Iterate over all spaces and save them to the * snapshot file. diff --git a/src/box/lua/info.c b/src/box/lua/info.c index 6e13041b2..cc0790077 100644 --- a/src/box/lua/info.c +++ b/src/box/lua/info.c @@ -321,6 +321,16 @@ lbox_info_ro(struct lua_State *L) return 1; } +static int +lbox_info_ro_reason(struct lua_State *L) +{ + if (box_is_ro()) + lua_pushstring(L, box_ro_reason()); + else + lua_pushnil(L); + return 1; +} + /* * Tarantool 1.6.x compat */ @@ -635,6 +645,7 @@ static const struct luaL_Reg lbox_info_dynamic_meta[] = { {"signature", lbox_info_signature}, {"vclock", lbox_info_vclock}, {"ro", lbox_info_ro}, + {"ro_reason", lbox_info_ro_reason}, {"replication", lbox_info_replication}, {"replication_anon", lbox_info_replication_anon}, {"status", lbox_info_status}, diff --git a/test/replication-luatest/gh_5568_read_only_reason_test.lua b/test/replication-luatest/gh_5568_read_only_reason_test.lua index 5e67029c0..13682cbba 100644 --- a/test/replication-luatest/gh_5568_read_only_reason_test.lua +++ b/test/replication-luatest/gh_5568_read_only_reason_test.lua @@ -53,6 +53,10 @@ local read_only_msg = "Can't modify data on a read-only instance - " -- Read-only because of box.cfg{read_only = true}. -- g.test_read_only_reason_cfg = function(g) + t.assert_equals(g.master:exec(function() + return box.info.ro_reason + end), nil, "no ro reason"); + local ok, err = g.master:exec(function() box.cfg{read_only = true} local ok, err = pcall(box.schema.create_space, 'test') @@ -61,6 +65,9 @@ g.test_read_only_reason_cfg = function(g) t.assert(not ok, 'fail ddl') t.assert_str_contains(err.message, read_only_msg.. 'box.cfg.read_only is true') + t.assert_equals(g.master:exec(function() + return box.info.ro_reason + end), "config", "ro reason config"); t.assert_covers(err, { reason = 'state', state = 'read_only', @@ -93,6 +100,9 @@ g.test_read_only_reason_orphan = function(g) end, {fake_uri}) t.assert(not ok, 'fail ddl') t.assert_str_contains(err.message, read_only_msg..'it is an orphan') + t.assert_equals(g.master:exec(function() + return box.info.ro_reason + end), "orphan", "ro reason orphan"); t.assert_covers(err, { reason = 'state', state = 'orphan', @@ -124,6 +134,9 @@ g.test_read_only_reason_election_no_leader = function(g) t.assert(err.term, 'has term') t.assert_str_contains(err.message, read_only_msg..('state is election '.. '%s with term %s'):format(err.state, err.term)) + t.assert_equals(g.master:exec(function() + return box.info.ro_reason + end), "election", "ro reason election"); t.assert_covers(err, { reason = 'election', state = 'follower', @@ -158,6 +171,9 @@ g.test_read_only_reason_election_has_leader = function(g) t.assert_str_contains(err.message, read_only_msg..('state is election '.. '%s with term %s, leader is %s (%s)'):format( err.state, err.term, err.leader_id, err.leader_uuid)) + t.assert_equals(g.replica:exec(function() + return box.info.ro_reason + end), "election", "ro reason election"); t.assert_covers(err, { reason = 'election', state = 'follower', @@ -200,6 +216,9 @@ g.test_read_only_reason_synchro = function(g) t.assert_str_contains(err.message, read_only_msg..('synchro queue with '.. 'term %s belongs to %s (%s)'):format(err.term, err.queue_owner_id, err.queue_owner_uuid)) + t.assert_equals(g.replica:exec(function() + return box.info.ro_reason + end), "synchro", "ro reason synchro"); t.assert_covers(err, { reason = 'synchro', queue_owner_id = g.master:instance_id(), @@ -258,6 +277,9 @@ g.test_read_only_reason_election_has_leader_no_uuid = function(g) t.assert_str_contains(err.message, read_only_msg..('state is election %s '.. 'with term %s, leader is %s'):format(err.state, err.term, err.leader_id)) + t.assert_equals(g.replica:exec(function() + return box.info.ro_reason + end), "election", "ro reason election"); t.assert_covers(err, { reason = 'election', state = 'follower', @@ -295,6 +317,9 @@ g.test_read_only_reason_synchro_no_uuid = function(g) t.assert_str_contains(err.message, read_only_msg..('synchro queue with '.. 'term %s belongs to %s'):format(err.term, err.queue_owner_id)) + t.assert_equals(g.replica:exec(function() + return box.info.ro_reason + end), "synchro", "ro reason synchro"); t.assert_covers(err, { reason = 'synchro', queue_owner_id = leader_id,