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 68A636ECE3; Thu, 20 Jan 2022 03:44:50 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 68A636ECE3 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1642639490; bh=jFuCeJEMLXzWBjdqQ0WVCbWM6joOGJ1+SD0gOcRiXMI=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=s5B4iFbm5djNYfhG8UEn6qHA5glzz1axjcOF4jocV6z6/UQ3tJ6uU1p+QpBXWb6Do atytIgoiPVg0Pj7ADeGYvMSMEhAV66uWqGLYjZfTUWVAkG2eQrjpOqjbFMYHNtJGAI C8xYr/Xgqrc7gMOUlIEwLHnIHhCR4qIcIsKi5Hmk= Received: from smtpng3.i.mail.ru (smtpng3.i.mail.ru [94.100.177.149]) (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 7F2406ECEB for ; Thu, 20 Jan 2022 03:43:50 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 7F2406ECEB Received: by smtpng3.m.smailru.net with esmtpa (envelope-from ) id 1nALYL-0006wT-Lb; Thu, 20 Jan 2022 03:43:50 +0300 To: tarantool-patches@dev.tarantool.org, sergepetrenko@tarantool.org Date: Thu, 20 Jan 2022 01:43:44 +0100 Message-Id: <01cd76a0f455e58365dc7fa389ca37f1f007ecad.1642639079.git.v.shpilevoy@tarantool.org> 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: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD98A33503A0B8627DBA78465C0ED1D0F3062AE718BAE98551D182A05F5380850407618CC20A8AA2C51235EC551FFDFA46F5BBD1C576B4D92C76081552EBD148BDC X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE79A02CFBD12041B85C2099A533E45F2D0395957E7521B51C2CFCAF695D4D8E9FCEA1F7E6F0F101C6778DA827A17800CE7D3E352D4AD7EBF54EA1F7E6F0F101C6723150C8DA25C47586E58E00D9D99D84E1BDDB23E98D2D38BEBC5CAB6D411FFA657CBD4C879E892E5FB2EDF30238C7BEFCC7F00164DA146DAFE8445B8C89999728AA50765F79006375FFD5C25497261569FA2833FD35BB23D2EF20D2F80756B5F868A13BD56FB6657A471835C12D1D977725E5C173C3A84C351672B98BD86E645117882F4460429728AD0CFFFB425014E868A13BD56FB6657E2021AF6380DFAD1A18204E546F3947CB11811A4A51E3B096D1867E19FE1407959CC434672EE6371089D37D7C0E48F6C8AA50765F79006373BC478629CBEC79DEFF80C71ABB335746BA297DBC24807EABDAD6C7F3747799A X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975C0410BD8E874E3D5C1C2CD84C6D971E0257AAE164120584459C2B6934AE262D3EE7EAB7254005DCED114C52B35DBB74F4E7EAB7254005DCEDA5DF9383870C0FED1E0A4E2319210D9B64D260DF9561598F01A9E91200F654B08D63A13FB2B5C60D8E8E86DC7131B365E7726E8460B7C23C X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D3430FC2BC1B917F018CAE4F2EB038AFD34A2DAF9395A742C6F765C759A97CF046540E541DC3DC0D1F31D7E09C32AA3244C12F55800D7A7D6719F10C3AA2CD6ADF75A1673A01BA68E40729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojPeoZbWa28mxDlER8vhf5NA== X-Mailru-Sender: 689FA8AB762F739339CABD9B3CA9A7D601CCF990E3CD23D4483944160067AA1E3841015FED1DE5223CC9A89AB576DD93FB559BB5D741EB963CF37A108A312F5C27E8A8C3839CE0E25FEEDEB644C299C0ED14614B50AE0675 X-Mras: Ok Subject: [Tarantool-patches] [PATCH v2 2/5] raft: fix ev_timer.at incorrect usage 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" ev_timer.at was used as timeout. But after ev_timer_start() it turns into the deadline - totally different value. The patch makes sure ev_timer.at is not used in raft at all. To test that the fakeev subsystem is patched to start its time not from 0. Otherwise ev_timer.at often really matched the timeout even for an active timer. --- src/lib/fakesys/fakeev.c | 10 +++++-- src/lib/raft/raft.c | 59 ++++++++++++++++++++++------------------ src/lib/raft/raft.h | 2 +- 3 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/lib/fakesys/fakeev.c b/src/lib/fakesys/fakeev.c index 5c3469486..333c1646f 100644 --- a/src/lib/fakesys/fakeev.c +++ b/src/lib/fakesys/fakeev.c @@ -37,8 +37,11 @@ #include "say.h" #include +/** Start not from 0 to catch bugs like incorrect usage of ev_timer members. */ +#define FAKEEV_START_TIME 10000 + /** Global watch, propagated by new events. */ -static double watch = 0; +static double watch = FAKEEV_START_TIME; /** * Increasing event identifiers are used to preserve order of @@ -278,6 +281,7 @@ fakeev_timer_start(struct ev_loop *loop, struct ev_timer *base) return; /* Create the periodic watcher and one event. */ fakeev_timer_event_new((struct ev_watcher *)base, base->at); + base->at += watch; } double @@ -287,6 +291,7 @@ fakeev_timer_remaining(struct ev_loop *loop, struct ev_timer *base) struct fakeev_event *e = fakeev_event_by_ev((struct ev_watcher *)base); if (e == NULL) return base->at; + assert(e->deadline == base->at); return e->deadline - fakeev_time(); } @@ -298,6 +303,7 @@ fakeev_timer_again(struct ev_loop *loop, struct ev_timer *base) return; /* Create the periodic watcher and one event. */ fakeev_timer_event_new((struct ev_watcher *)base, base->repeat); + base->at = watch + base->repeat; } /** Time stop cancels the event if the timer is active. */ @@ -339,7 +345,7 @@ fakeev_reset(void) fakeev_event_delete(e); assert(mh_size(events_hash) == 0); event_id = 0; - watch = 0; + watch = FAKEEV_START_TIME; } void diff --git a/src/lib/raft/raft.c b/src/lib/raft/raft.c index 1ae8fe87f..d6a849503 100644 --- a/src/lib/raft/raft.c +++ b/src/lib/raft/raft.c @@ -931,22 +931,23 @@ raft_restore(struct raft *raft) void raft_cfg_election_timeout(struct raft *raft, double timeout) { - if (timeout == raft->election_timeout) + double old_timeout = raft->election_timeout; + if (timeout == old_timeout) return; raft->election_timeout = timeout; - if (raft->vote != 0 && raft->leader == 0 && raft->is_candidate && - !raft->is_write_in_progress) { - assert(raft_ev_is_active(&raft->timer)); - struct ev_loop *loop = raft_loop(); - double timeout = raft_ev_timer_remaining(loop, &raft->timer) - - raft->timer.at + raft->election_timeout; - if (timeout < 0) - timeout = 0; - raft_ev_timer_stop(loop, &raft->timer); - raft_ev_timer_set(&raft->timer, timeout, timeout); - raft_ev_timer_start(loop, &raft->timer); - } + if (raft->vote == 0 || raft->leader != 0 || !raft->is_candidate || + raft->is_write_in_progress) + return; + + assert(raft_ev_is_active(&raft->timer)); + struct ev_loop *loop = raft_loop(); + timeout += raft_ev_timer_remaining(loop, &raft->timer) - old_timeout; + if (timeout < 0) + timeout = 0; + raft_ev_timer_stop(loop, &raft->timer); + raft_ev_timer_set(&raft->timer, timeout, raft->election_timeout); + raft_ev_timer_start(loop, &raft->timer); } void @@ -961,21 +962,25 @@ raft_cfg_election_quorum(struct raft *raft, int election_quorum) } void -raft_cfg_death_timeout(struct raft *raft, double death_timeout) +raft_cfg_death_timeout(struct raft *raft, double timeout) { - raft->death_timeout = death_timeout; - if (raft->state == RAFT_STATE_FOLLOWER && raft->is_candidate && - raft->leader != 0) { - assert(raft_ev_is_active(&raft->timer)); - struct ev_loop *loop = raft_loop(); - double timeout = raft_ev_timer_remaining(loop, &raft->timer) - - raft->timer.at + raft->death_timeout; - if (timeout < 0) - timeout = 0; - raft_ev_timer_stop(loop, &raft->timer); - raft_ev_timer_set(&raft->timer, timeout, timeout); - raft_ev_timer_start(loop, &raft->timer); - } + double old_timeout = raft->death_timeout; + if (timeout == old_timeout) + return; + + raft->death_timeout = timeout; + if (raft->state != RAFT_STATE_FOLLOWER || !raft->is_candidate || + raft->leader == 0) + return; + + assert(raft_ev_is_active(&raft->timer)); + struct ev_loop *loop = raft_loop(); + timeout += raft_ev_timer_remaining(loop, &raft->timer) - old_timeout; + if (timeout < 0) + timeout = 0; + raft_ev_timer_stop(loop, &raft->timer); + raft_ev_timer_set(&raft->timer, timeout, raft->death_timeout); + raft_ev_timer_start(loop, &raft->timer); } void diff --git a/src/lib/raft/raft.h b/src/lib/raft/raft.h index 53e2c58a8..e844c2d07 100644 --- a/src/lib/raft/raft.h +++ b/src/lib/raft/raft.h @@ -307,7 +307,7 @@ raft_cfg_election_quorum(struct raft *raft, int election_quorum); * heartbeats from the leader to consider it dead. */ void -raft_cfg_death_timeout(struct raft *raft, double death_timeout); +raft_cfg_death_timeout(struct raft *raft, double timeout); /** * Configure ID of the given Raft instance. The ID can't be changed after it is -- 2.24.3 (Apple Git-128)