From: Vladislav Shpilevoy via Tarantool-patches <tarantool-patches@dev.tarantool.org> To: tarantool-patches@dev.tarantool.org, sergepetrenko@tarantool.org Subject: [Tarantool-patches] [PATCH v2 12/11] error: introduce box.info.ro_reason Date: Sat, 13 Nov 2021 00:25:43 +0100 [thread overview] Message-ID: <0e293f9e-1014-1f94-cfe9-efd36f313049@tarantool.org> (raw) In-Reply-To: <cover.1636674803.git.v.shpilevoy@tarantool.org> 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,
next prev parent reply other threads:[~2021-11-12 23:25 UTC|newest] Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-11-11 23:54 [Tarantool-patches] [PATCH v2 00/11] ER_READONLY reason Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 01/11] diag: return created error from diag_set() Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 10/11] box: enrich ER_READONLY with new details Vladislav Shpilevoy via Tarantool-patches 2021-11-12 7:30 ` Serge Petrenko via Tarantool-patches 2021-11-12 23:24 ` Vladislav Shpilevoy via Tarantool-patches 2021-11-15 6:51 ` Serge Petrenko via Tarantool-patches 2021-11-15 21:56 ` Vladislav Shpilevoy via Tarantool-patches 2021-11-16 9:53 ` Serge Petrenko via Tarantool-patches 2021-11-16 22:08 ` Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 11/11] error: report ER_READONLY reason in message Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 02/11] uuid: move into libcore Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 03/11] error: introduce error_payload Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 04/11] error: move code to struct error from ClientError Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 05/11] error: use error_payload to store optional members Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 06/11] error: use error_payload in MessagePack codecs Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 07/11] error: use error_payload in Lua Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 08/11] luatest: copy config in cluster:build_server() Vladislav Shpilevoy via Tarantool-patches 2021-11-11 23:54 ` [Tarantool-patches] [PATCH v2 09/11] luatest: add new helpers for 'server' object Vladislav Shpilevoy via Tarantool-patches 2021-11-12 23:25 ` Vladislav Shpilevoy via Tarantool-patches [this message] 2021-11-15 6:53 ` [Tarantool-patches] [PATCH v2 12/11] error: introduce box.info.ro_reason Serge Petrenko via Tarantool-patches 2021-11-16 22:08 ` [Tarantool-patches] [PATCH v2 00/11] ER_READONLY reason Vladislav Shpilevoy via Tarantool-patches
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=0e293f9e-1014-1f94-cfe9-efd36f313049@tarantool.org \ --to=tarantool-patches@dev.tarantool.org \ --cc=sergepetrenko@tarantool.org \ --cc=v.shpilevoy@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v2 12/11] error: introduce box.info.ro_reason' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox