From: Serge Petrenko <sergepetrenko@tarantool.org> To: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>, tarantool-patches@dev.tarantool.org, gorcunov@gmail.com Subject: Re: [Tarantool-patches] [PATCH 2/4] raft: initialize raft completely at runtime Date: Mon, 9 Nov 2020 15:50:13 +0300 [thread overview] Message-ID: <98eee088-598e-6437-1f21-fb28d4ca0581@tarantool.org> (raw) In-Reply-To: <5226a32c8783879dbf1b3714730b87147767466f.1604858551.git.v.shpilevoy@tarantool.org> 08.11.2020 21:03, Vladislav Shpilevoy пишет: > Global raft object was created mostly at compile time with > constant values assigned to all raft fields. But it won't work > soon because raft will be moved to a separate library, and it > will provide methods for raft creation and destruction. > > This patch makes raft not rely on compile time initialization, > and moves it entirely to raft_init(). Also there are added some > validations via new raft_validate() function, which should ensure > raft is not used before creation. > > This may be hard to support, since raft is used by recovery and > replication, even before instance has an ID. The validation should > help to catch bugs related to the initialization order of these > subsystems. > > Part of #5303 Hi! Thanks for the patch! LGTM. > --- > src/box/raft.c | 37 ++++++++++++++++++++++--------------- > src/box/raft.h | 14 ++++++++++++++ > 2 files changed, 36 insertions(+), 15 deletions(-) > > diff --git a/src/box/raft.c b/src/box/raft.c > index 8f8b59ba6..a6a893373 100644 > --- a/src/box/raft.c > +++ b/src/box/raft.c > @@ -46,21 +46,11 @@ > > /** Raft state of this instance. */ > struct raft raft = { > - .leader = 0, > - .state = RAFT_STATE_FOLLOWER, > - .volatile_term = 1, > - .volatile_vote = 0, > - .is_enabled = false, > - .is_candidate = false, > - .is_cfg_candidate = false, > - .is_write_in_progress = false, > - .is_broadcast_scheduled = false, > - .term = 1, > - .vote = 0, > - .vote_mask = 0, > - .vote_count = 0, > - .worker = NULL, > - .election_timeout = 5, > + /* > + * Set an invalid state to validate in all raft functions they are not > + * used before raft initialization. > + */ > + .state = 0, > }; > > /** > @@ -325,6 +315,7 @@ raft_request_to_string(const struct raft_request *req) > void > raft_process_recovery(const struct raft_request *req) > { > + raft_validate(); > say_verbose("RAFT: recover %s", raft_request_to_string(req)); > if (req->term != 0) { > raft.term = req->term; > @@ -353,6 +344,7 @@ raft_process_recovery(const struct raft_request *req) > int > raft_process_msg(const struct raft_request *req, uint32_t source) > { > + raft_validate(); > say_info("RAFT: message %s from %u", raft_request_to_string(req), > source); > assert(source > 0); > @@ -496,6 +488,7 @@ raft_process_msg(const struct raft_request *req, uint32_t source) > void > raft_process_heartbeat(uint32_t source) > { > + raft_validate(); > /* > * Raft handles heartbeats from all instances, including anon instances > * which don't participate in Raft. > @@ -905,6 +898,7 @@ raft_sm_stop(void) > void > raft_serialize_for_network(struct raft_request *req, struct vclock *vclock) > { > + raft_validate(); > memset(req, 0, sizeof(*req)); > /* > * Volatile state is never used for any communications. > @@ -926,6 +920,7 @@ raft_serialize_for_network(struct raft_request *req, struct vclock *vclock) > void > raft_serialize_for_disk(struct raft_request *req) > { > + raft_validate(); > memset(req, 0, sizeof(*req)); > req->term = raft.term; > req->vote = raft.vote; > @@ -934,12 +929,14 @@ raft_serialize_for_disk(struct raft_request *req) > void > raft_on_update(struct trigger *trigger) > { > + raft_validate(); > trigger_add(&raft.on_update, trigger); > } > > void > raft_cfg_is_enabled(bool is_enabled) > { > + raft_validate(); > if (is_enabled == raft.is_enabled) > return; > > @@ -952,6 +949,7 @@ raft_cfg_is_enabled(bool is_enabled) > void > raft_cfg_is_candidate(bool is_candidate) > { > + raft_validate(); > bool old_is_candidate = raft.is_candidate; > raft.is_cfg_candidate = is_candidate; > raft.is_candidate = is_candidate && raft.is_enabled; > @@ -991,6 +989,7 @@ raft_cfg_is_candidate(bool is_candidate) > void > raft_cfg_election_timeout(double timeout) > { > + raft_validate(); > if (timeout == raft.election_timeout) > return; > > @@ -1008,6 +1007,7 @@ raft_cfg_election_timeout(double timeout) > void > raft_cfg_election_quorum(void) > { > + raft_validate(); > if (raft.state != RAFT_STATE_CANDIDATE || > raft.state == RAFT_STATE_LEADER) > return; > @@ -1019,6 +1019,7 @@ raft_cfg_election_quorum(void) > void > raft_cfg_death_timeout(void) > { > + raft_validate(); > if (raft.state == RAFT_STATE_FOLLOWER && raft.is_candidate && > raft.leader != 0) { > assert(ev_is_active(&raft.timer)); > @@ -1034,6 +1035,7 @@ raft_cfg_death_timeout(void) > void > raft_new_term(void) > { > + raft_validate(); > if (raft.is_enabled) > raft_sm_schedule_new_term(raft.volatile_term + 1); > } > @@ -1079,6 +1081,11 @@ raft_schedule_broadcast(void) > void > raft_init(void) > { > + memset(&raft, 0, sizeof(raft)); > + raft.state = RAFT_STATE_FOLLOWER; > + raft.volatile_term = 1; > + raft.term = 1; > + raft.election_timeout = 5; > ev_timer_init(&raft.timer, raft_sm_schedule_new_election_cb, 0, 0); > rlist_create(&raft.on_update); > } > diff --git a/src/box/raft.h b/src/box/raft.h > index 8293d7410..0c60eccdf 100644 > --- a/src/box/raft.h > +++ b/src/box/raft.h > @@ -31,6 +31,7 @@ > */ > #include <stdint.h> > #include <stdbool.h> > +#include <assert.h> > #include "tarantool_ev.h" > #include "trigger.h" > > @@ -164,6 +165,16 @@ struct raft { > > extern struct raft raft; > > +/** > + * Ensure the raft node can be used. I.e. that it is properly initialized. > + * Entirely for debug purposes. > + */ > +static inline void > +raft_validate(void) > +{ > + assert(raft.state != 0); > +} > + > /** > * A flag whether the instance is read-only according to Raft. Even if Raft > * allows writes though, it does not mean the instance is writable. It can be > @@ -172,6 +183,7 @@ extern struct raft raft; > static inline bool > raft_is_ro(void) > { > + raft_validate(); > return raft.is_enabled && raft.state != RAFT_STATE_LEADER; > } > > @@ -179,6 +191,7 @@ raft_is_ro(void) > static inline bool > raft_is_source_allowed(uint32_t source_id) > { > + raft_validate(); > return !raft.is_enabled || raft.leader == source_id; > } > > @@ -186,6 +199,7 @@ raft_is_source_allowed(uint32_t source_id) > static inline bool > raft_is_enabled(void) > { > + raft_validate(); > return raft.is_enabled; > } > -- Serge Petrenko
next prev parent reply other threads:[~2020-11-09 12:50 UTC|newest] Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-11-08 18:03 [Tarantool-patches] [PATCH 0/4] Raft module, part 1 - explicit argument Vladislav Shpilevoy 2020-11-08 18:03 ` [Tarantool-patches] [PATCH 1/4] fiber: introduce fiber.arg Vladislav Shpilevoy 2020-11-09 12:49 ` Serge Petrenko 2020-11-09 14:27 ` Cyrill Gorcunov 2020-11-09 23:59 ` Vladislav Shpilevoy 2020-11-08 18:03 ` [Tarantool-patches] [PATCH 2/4] raft: initialize raft completely at runtime Vladislav Shpilevoy 2020-11-09 12:50 ` Serge Petrenko [this message] 2020-11-09 14:59 ` Cyrill Gorcunov 2020-11-09 23:59 ` Vladislav Shpilevoy 2020-11-08 18:03 ` [Tarantool-patches] [PATCH 3/4] raft: add explicit raft argument to all functions Vladislav Shpilevoy 2020-11-09 13:46 ` Serge Petrenko 2020-11-10 0:00 ` Vladislav Shpilevoy 2020-11-08 18:03 ` [Tarantool-patches] [PATCH 4/4] vclock: move to src/lib Vladislav Shpilevoy 2020-11-09 14:12 ` Serge Petrenko 2020-11-09 15:01 ` Cyrill Gorcunov 2020-11-10 21:06 ` [Tarantool-patches] [PATCH 0/4] Raft module, part 1 - explicit argument Alexander V. Tikhonov
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=98eee088-598e-6437-1f21-fb28d4ca0581@tarantool.org \ --to=sergepetrenko@tarantool.org \ --cc=gorcunov@gmail.com \ --cc=tarantool-patches@dev.tarantool.org \ --cc=v.shpilevoy@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH 2/4] raft: initialize raft completely at runtime' \ /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