From d6547bba8cfb857ff79939447c72318714bc1f90 Mon Sep 17 00:00:00 2001 From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> Date: Tue, 28 Feb 2023 23:15:04 +0100 Subject: [PATCH] replication: fix outdated ballot on deanon failure If attempt to set `box.cfg{replication_anon = false}` failed, the instance's ballot event had is_anon = false nonetheless. This was because on reconfig failure the option's scope guard did revert the option itself in C++ code, but didn't update the ballot. NO_DOC=bugfix --- .../unreleased/anon-on-failure-ballot.md | 4 ++ src/box/box.cc | 1 + test/replication-luatest/anon_test.lua | 61 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 changelogs/unreleased/anon-on-failure-ballot.md create mode 100644 test/replication-luatest/anon_test.lua diff --git a/changelogs/unreleased/anon-on-failure-ballot.md b/changelogs/unreleased/anon-on-failure-ballot.md new file mode 100644 index 0000000000..f01ee0eead --- /dev/null +++ b/changelogs/unreleased/anon-on-failure-ballot.md @@ -0,0 +1,4 @@ +## bugfix/replication + +* Fixed a bug when new instances could try to register via an anon instance + which previously failed to apply `box.cfg{replication_anon = false}`. diff --git a/src/box/box.cc b/src/box/box.cc index 28ab980232..a489dd5614 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -1970,6 +1970,7 @@ box_set_replication_anon(void) if (!anon) { auto guard = make_scoped_guard([&]{ replication_anon = !anon; + box_broadcast_ballot(); }); /* Turn anonymous instance into a normal one. */ replication_anon = anon; diff --git a/test/replication-luatest/anon_test.lua b/test/replication-luatest/anon_test.lua new file mode 100644 index 0000000000..750bf4003f --- /dev/null +++ b/test/replication-luatest/anon_test.lua @@ -0,0 +1,61 @@ +local server = require('luatest.server') +local t = require('luatest') +local g = t.group() + +g.before_all = function(lg) + lg.master = server:new({alias = 'master'}) + lg.master:start() +end + +g.after_all = function(lg) + lg.master:drop() +end + +-- +-- When an instance failed to apply cfg{replication_anon = false}, it used to +-- report itself as non-anon in the ballot anyway. Shouldn't be so. +-- +g.test_ballot_on_deanon_fail = function(lg) + local box_cfg = { + replication_anon = true, + read_only = true, + replication = { + lg.master.net_box_uri, + }, + } + local replica = server:new({ + alias = 'replica', + box_cfg = box_cfg, + }) + replica:start() + replica:exec(function() + t.assert_equals(box.info.id, 0) + end) + lg.master:exec(function() + rawset(_G, 'test_trigger', function() + error('Reject _cluster update') + end) + box.space._cluster:on_replace(_G.test_trigger) + end) + replica:exec(function() + local fiber = require('fiber') + local iproto = box.iproto + local is_anon = nil + local w = box.watch('internal.ballot', function(_, value) + is_anon = value[iproto.key.BALLOT][iproto.ballot_key.IS_ANON] + end) + fiber.yield() + t.assert(is_anon) + is_anon = nil + t.assert_error_msg_contains('Reject _cluster update', box.cfg, + {replication_anon = false}) + fiber.yield() + t.assert(is_anon) + w:unregister() + end) + replica:drop() + lg.master:exec(function() + box.space._cluster:on_replace(nil, _G.test_trigger) + _G.test_trigger = nil + end) +end -- GitLab