1 /* 2 * Copyright 2009-2022 the Pacemaker project contributors 3 * 4 * The version control history for this file may have further details. 5 * 6 * This source code is licensed under the GNU Lesser General Public License 7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. 8 */ 9 10 #ifndef CRM_COMMON_ELECTION__H 11 # define CRM_COMMON_ELECTION__H 12 13 #ifdef __cplusplus 14 extern "C" { 15 #endif 16 17 /** 18 * \file 19 * \brief Functions for conducting elections 20 * 21 * An election is useful for a daemon that runs on all nodes but needs any one 22 * instance to perform a special role. 23 * 24 * Elections are closely tied to the cluster peer cache. Peers in the cache that 25 * are active members are eligible to vote. Elections are named for logging 26 * purposes, but only one election may exist at any time, so typically an 27 * election would be created at daemon start-up and freed at shutdown. 28 * 29 * Pacemaker's election procedure has been heavily adapted from the 30 * Invitation Algorithm variant of the Garcia-Molina Bully Algorithm: 31 * 32 * https://en.wikipedia.org/wiki/Bully_algorithm 33 * 34 * Elections are conducted via cluster messages. There are two types of 35 * messages: a "vote" is a declaration of the voting node's candidacy, and is 36 * always broadcast; a "no-vote" is a concession by the responding node, and is 37 * always a reply to the preferred node's vote. (These correspond to "invite" 38 * and "accept" in the traditional algorithm.) 39 * 40 * A vote together with any no-vote replies to it is considered an election 41 * round. Rounds are numbered with a simple counter unique to each node 42 * (this would be the group number in the traditional algorithm). Concurrent 43 * election rounds are possible. 44 * 45 * An election round is started when any node broadcasts a vote. When a node 46 * receives another node's vote, it compares itself against the sending node 47 * according to certain metrics, and either starts a new round (if it prefers 48 * itself) or replies to the other node with a no-vote (if it prefers that 49 * node). 50 * 51 * If a node receives no-votes from all other active nodes, it declares itself 52 * the winner. The library API does not notify other nodes of this; callers 53 * must implement that if desired. 54 */ 55 56 typedef struct election_s election_t; 57 58 /*! Possible election states */ 59 enum election_result { 60 election_start = 0, /*! new election needed */ 61 election_in_progress, /*! election started but not all peers have voted */ 62 election_lost, /*! local node lost most recent election */ 63 election_won, /*! local node won most recent election */ 64 election_error, /*! election message or election object invalid */ 65 }; 66 67 void election_fini(election_t *e); 68 void election_reset(election_t *e); 69 election_t *election_init(const char *name, const char *uname, guint period_ms, GSourceFunc cb); 70 71 void election_timeout_set_period(election_t *e, guint period_ms); 72 void election_timeout_stop(election_t *e); 73 74 void election_vote(election_t *e); 75 bool election_check(election_t *e); 76 void election_remove(election_t *e, const char *uname); 77 enum election_result election_state(const election_t *e); 78 enum election_result election_count_vote(election_t *e, const xmlNode *message, 79 bool can_win); 80 void election_clear_dampening(election_t *e); 81 82 #ifdef __cplusplus 83 } 84 #endif 85 86 #endif