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 612AC6FC8F; Fri, 16 Apr 2021 19:31:51 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 612AC6FC8F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1618590711; bh=/nLEiPuPSUZg8MW+BIIcDzspIxIrOIGL+8+AsXbeQds=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=YMASIJb4wHFHzsSnQ0ApfjqrjltuLoTBL2cE3cSiQDy6VAimWIXHTLxygerlWVFi0 6+OJDysMwMqcukH2cRIZdRktuJJr8/XBlCQBSY+Q0/ArDqSaIBbNhpJo19r5jEQxPt 18iJlJOBHfiyRHjJV+ddufyKs7va2Izz7cAIO+xg= Received: from smtp17.mail.ru (smtp17.mail.ru [94.100.176.154]) (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 47A9A74CDE for ; Fri, 16 Apr 2021 19:26:06 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 47A9A74CDE Received: by smtp17.mail.ru with esmtpa (envelope-from ) id 1lXRID-00008e-Ew; Fri, 16 Apr 2021 19:26:05 +0300 To: v.shpilevoy@tarantool.org, gorcunov@gmail.com Date: Fri, 16 Apr 2021 19:25:43 +0300 Message-Id: X-Mailer: git-send-email 2.24.3 (Apple Git-128) In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD92FFCB8E6708E74807BAE725B9AE625DE765B0E193B5B7687182A05F5380850400A61BE2332CA35AC8C997B7C265D9DCB2FEE343EDB24E4F8E106859297B329C1 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7612B7ED227D9C0F5EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F790063725FA9CD6081C82518638F802B75D45FF914D58D5BE9E6BC1A93B80C6DEB9DEE97C6FB206A91F05B226FA9AD9A2935C50C7D42B508C278128AD368CDB2FD0D9CCD2E47CDBA5A96583C09775C1D3CA48CFCA5A41EBD8A3A0199FA2833FD35BB23D2EF20D2F80756B5F868A13BD56FB6657A471835C12D1D977725E5C173C3A84C3CA5A41EBD8A3A0199FA2833FD35BB23DF004C90652538430302FCEF25BFAB3454AD6D5ED66289B5278DA827A17800CE75316DB96053AEAC1D32BA5DBAC0009BE395957E7521B51C20BC6067A898B09E4090A508E0FED6299176DF2183F8FC7C0FD77E3C7FBC4A742CD04E86FAF290E2D7E9C4E3C761E06A71DD303D21008E298D5E8D9A59859A8B6B372FE9A2E580EFC725E5C173C3A84C3CE9959E2676FD87735872C767BF85DA2F004C90652538430E4A6367B16DE6309 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975CBF1196BB3248DD4B3F8C8D595271AFB3FA0D329ED3C95E4D9C2B6934AE262D3EE7EAB7254005DCED7532B743992DF240BDC6A1CF3F042BAD6DF99611D93F60EF0417BEADF48D1460699F904B3F4130E343918A1A30D5E7FCCB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34A503FBFE8BE8FC490B5BCA32982821D727D85EF67D0FC7CF00E4B9C17C1E202ADEFA2A02F8211F2E1D7E09C32AA3244CB3C35479C53A2C8322FFD05326A7B7AAE8FBBEFAE1C4874C927AC6DF5659F194 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2bioj3S6P1v0GIqRTEey3WiaFxA== X-Mailru-Sender: 583F1D7ACE8F49BDD2846D59FC20E9F8DF49C5E8585DB5373400C56A7D56F84652C04C1A56F5DA8A424AE0EB1F3D1D21E2978F233C3FAE6EE63DB1732555E4A8EE80603BA4A5B0BC112434F685709FCF0DA7A0AF5A3A8387 X-Mras: Ok Subject: [Tarantool-patches] [PATCH v4 12/12] box.ctl: rename clear_synchro_queue to promote 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: Serge Petrenko via Tarantool-patches Reply-To: Serge Petrenko Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" New function name will be `box.ctl.promote()`. It's much shorter and closer to the function's now enriched functionality. Old name `box.ctl.clear_synchro_queue()` remains in Lua for the sake of backward compatibility. Follow-up #5445 Closes #3055 @TarantoolBot document Title: deprecate `box.ctl.clear_synchro_queue()` in favor of `box.ctl.promote()` Replace all the mentions of `box.ctl.clear_synchro_queue()` with `box.ctl.promote()` and add a note that `box.ctl.clear_synchro_queue()` is a deprecated alias to `box.ctl.promote()` --- changelogs/unreleased/box-ctl-promote.md | 8 ++ src/box/box.cc | 20 ++-- src/box/box.h | 2 +- src/box/lua/ctl.c | 8 +- src/box/raft.c | 4 +- .../gh-3055-election-promote.result | 105 ++++++++++++++++++ .../gh-3055-election-promote.test.lua | 43 +++++++ test/replication/suite.cfg | 1 + 8 files changed, 175 insertions(+), 16 deletions(-) create mode 100644 changelogs/unreleased/box-ctl-promote.md create mode 100644 test/replication/gh-3055-election-promote.result create mode 100644 test/replication/gh-3055-election-promote.test.lua diff --git a/changelogs/unreleased/box-ctl-promote.md b/changelogs/unreleased/box-ctl-promote.md new file mode 100644 index 000000000..15f6fb206 --- /dev/null +++ b/changelogs/unreleased/box-ctl-promote.md @@ -0,0 +1,8 @@ +## feature/replication + +* Introduce `box.ctl.promote()` and the concept of manual elections (enabled + with `election_mode='manual'`). Once the instance is in `manual` election + mode, it acts like a `voter` most of the time, but may trigger elections and + become a leader, once `box.ctl.promote()` is called. + When `election_mode ~= 'manual'`, `box.ctl.promote()` replaces + `box.ctl.clear_synchro_queue()`, which is now deprecated (gh-3055). diff --git a/src/box/box.cc b/src/box/box.cc index be7234302..70cb2bd53 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -1504,12 +1504,12 @@ box_wait_quorum(uint32_t lead_id, int64_t target_lsn, int quorum, } int -box_clear_synchro_queue(void) +box_promote(void) { /* A guard to block multiple simultaneous function invocations. */ - static bool in_clear_synchro_queue = false; - if (in_clear_synchro_queue) { - diag_set(ClientError, ER_UNSUPPORTED, "clear_synchro_queue", + static bool in_promote = false; + if (in_promote) { + diag_set(ClientError, ER_UNSUPPORTED, "box.ctl.promote", "simultaneous invocations"); return -1; } @@ -1558,7 +1558,7 @@ box_clear_synchro_queue(void) int64_t wait_lsn = txn_limbo.confirmed_lsn; int rc = 0; int quorum = replication_synchro_quorum; - in_clear_synchro_queue = true; + in_promote = true; if (run_elections) { /* @@ -1580,13 +1580,13 @@ box_clear_synchro_queue(void) raft_stop_candidate(box_raft(), false); if (!box_raft()->is_enabled) { diag_set(ClientError, ER_RAFT_DISABLED); - in_clear_synchro_queue = false; + in_promote = false; return -1; } if (box_raft()->state != RAFT_STATE_LEADER) { diag_set(ClientError, ER_INTERFERING_PROMOTE, box_raft()->leader); - in_clear_synchro_queue = false; + in_promote = false; return -1; } } @@ -1610,13 +1610,13 @@ box_clear_synchro_queue(void) if (former_leader_id != txn_limbo.owner_id) { diag_set(ClientError, ER_INTERFERING_PROMOTE, txn_limbo.owner_id); - in_clear_synchro_queue = false; + in_promote = false; return -1; } } /* - * clear_synchro_queue() is a no-op on the limbo owner, so all the rows + * promote() is a no-op on the limbo owner, so all the rows * in the limbo must've come through the applier meaning they already * have an lsn assigned, even if their WAL write hasn't finished yet. */ @@ -1651,7 +1651,7 @@ promote: assert(txn_limbo_is_empty(&txn_limbo)); } } - in_clear_synchro_queue = false; + in_promote = false; return rc; } diff --git a/src/box/box.h b/src/box/box.h index 90facd189..04bdd397d 100644 --- a/src/box/box.h +++ b/src/box/box.h @@ -274,7 +274,7 @@ extern "C" { typedef struct tuple box_tuple_t; int -box_clear_synchro_queue(void); +box_promote(void); /* box_select is private and used only by FFI */ API_EXPORT int diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c index 5b8d0d0e4..368b9ab60 100644 --- a/src/box/lua/ctl.c +++ b/src/box/lua/ctl.c @@ -82,9 +82,9 @@ lbox_ctl_on_schema_init(struct lua_State *L) } static int -lbox_ctl_clear_synchro_queue(struct lua_State *L) +lbox_ctl_promote(struct lua_State *L) { - if (box_clear_synchro_queue() != 0) + if (box_promote() != 0) return luaT_error(L); return 0; } @@ -124,7 +124,9 @@ static const struct luaL_Reg lbox_ctl_lib[] = { {"wait_rw", lbox_ctl_wait_rw}, {"on_shutdown", lbox_ctl_on_shutdown}, {"on_schema_init", lbox_ctl_on_schema_init}, - {"clear_synchro_queue", lbox_ctl_clear_synchro_queue}, + {"promote", lbox_ctl_promote}, + /* An old alias. */ + {"clear_synchro_queue", lbox_ctl_promote}, {"is_recovery_finished", lbox_ctl_is_recovery_finished}, {"set_on_shutdown_timeout", lbox_ctl_set_on_shutdown_timeout}, {NULL, NULL} diff --git a/src/box/raft.c b/src/box/raft.c index 9a67a7cb0..6e9770072 100644 --- a/src/box/raft.c +++ b/src/box/raft.c @@ -89,14 +89,14 @@ box_raft_update_synchro_queue(struct raft *raft) assert(raft == box_raft()); /* * In case these are manual elections, we are already in the middle of a - * `clear_synchro_queue` call. No need to call it once again. + * `promote` call. No need to call it once again. */ if (raft->state == RAFT_STATE_LEADER && box_election_mode != ELECTION_MODE_MANUAL) { int rc = 0; uint32_t errcode = 0; do { - rc = box_clear_synchro_queue(); + rc = box_promote(); if (rc != 0) { struct error *err = diag_last_error(diag_get()); errcode = box_error_code(err); diff --git a/test/replication/gh-3055-election-promote.result b/test/replication/gh-3055-election-promote.result new file mode 100644 index 000000000..6f5af13bc --- /dev/null +++ b/test/replication/gh-3055-election-promote.result @@ -0,0 +1,105 @@ +-- test-run result file version 2 +test_run = require('test_run').new() + | --- + | ... + +-- +-- gh-3055 box.ctl.promote(). Call on instance with election_mode='manual' +-- in order to promote it to leader. +SERVERS = {'election_replica1', 'election_replica2', 'election_replica3'} + | --- + | ... +-- Start in candidate state in order for bootstrap to work. +test_run:create_cluster(SERVERS, 'replication', {args='2 0.1 candidate'}) + | --- + | ... +test_run:wait_fullmesh(SERVERS) + | --- + | ... + +cfg_set_manual =\ + "box.cfg{election_mode='manual'} "..\ + "assert(box.info.election.state == 'follower') "..\ + "assert(box.info.ro)" + | --- + | ... + +for _, server in pairs(SERVERS) do\ + ok, res = test_run:eval(server, cfg_set_manual)\ + assert(ok)\ +end + | --- + | ... + +-- Promote without living leader. +test_run:switch('election_replica1') + | --- + | - true + | ... +assert(box.info.election.state == 'follower') + | --- + | - true + | ... +term = box.info.election.term + | --- + | ... +box.ctl.promote() + | --- + | ... +assert(box.info.election.state == 'leader') + | --- + | - true + | ... +assert(not box.info.ro) + | --- + | - true + | ... +assert(box.info.election.term > term) + | --- + | - true + | ... + +-- Test promote when there's a live leader. +test_run:switch('election_replica2') + | --- + | - true + | ... +term = box.info.election.term + | --- + | ... +assert(box.info.election.state == 'follower') + | --- + | - true + | ... +assert(box.info.ro) + | --- + | - true + | ... +assert(box.info.election.leader ~= 0) + | --- + | - true + | ... +box.ctl.promote() + | --- + | ... +assert(box.info.election.state == 'leader') + | --- + | - true + | ... +assert(not box.info.ro) + | --- + | - true + | ... +assert(box.info.election.term > term) + | --- + | - true + | ... + +-- Cleanup. +test_run:switch('default') + | --- + | - true + | ... +test_run:drop_cluster(SERVERS) + | --- + | ... diff --git a/test/replication/gh-3055-election-promote.test.lua b/test/replication/gh-3055-election-promote.test.lua new file mode 100644 index 000000000..cbc3ed206 --- /dev/null +++ b/test/replication/gh-3055-election-promote.test.lua @@ -0,0 +1,43 @@ +test_run = require('test_run').new() + +-- +-- gh-3055 box.ctl.promote(). Call on instance with election_mode='manual' +-- in order to promote it to leader. +SERVERS = {'election_replica1', 'election_replica2', 'election_replica3'} +-- Start in candidate state in order for bootstrap to work. +test_run:create_cluster(SERVERS, 'replication', {args='2 0.1 candidate'}) +test_run:wait_fullmesh(SERVERS) + +cfg_set_manual =\ + "box.cfg{election_mode='manual'} "..\ + "assert(box.info.election.state == 'follower') "..\ + "assert(box.info.ro)" + +for _, server in pairs(SERVERS) do\ + ok, res = test_run:eval(server, cfg_set_manual)\ + assert(ok)\ +end + +-- Promote without living leader. +test_run:switch('election_replica1') +assert(box.info.election.state == 'follower') +term = box.info.election.term +box.ctl.promote() +assert(box.info.election.state == 'leader') +assert(not box.info.ro) +assert(box.info.election.term > term) + +-- Test promote when there's a live leader. +test_run:switch('election_replica2') +term = box.info.election.term +assert(box.info.election.state == 'follower') +assert(box.info.ro) +assert(box.info.election.leader ~= 0) +box.ctl.promote() +assert(box.info.election.state == 'leader') +assert(not box.info.ro) +assert(box.info.election.term > term) + +-- Cleanup. +test_run:switch('default') +test_run:drop_cluster(SERVERS) diff --git a/test/replication/suite.cfg b/test/replication/suite.cfg index 8b185ce7e..dc39e2f74 100644 --- a/test/replication/suite.cfg +++ b/test/replication/suite.cfg @@ -2,6 +2,7 @@ "anon.test.lua": {}, "anon_register_gap.test.lua": {}, "gh-2991-misc-asserts-on-update.test.lua": {}, + "gh-3055-election-promote.test.lua": {}, "gh-3111-misc-rebootstrap-from-ro-master.test.lua": {}, "gh-3160-misc-heartbeats-on-master-changes.test.lua": {}, "gh-3247-misc-iproto-sequence-value-not-replicated.test.lua": {}, -- 2.24.3 (Apple Git-128)