1 /*
2 * Copyright 2009-2019 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(election_t *e);
78 enum election_result election_count_vote(election_t *e, xmlNode *vote, bool can_win);
79 void election_clear_dampening(election_t *e);
80
81 #ifdef __cplusplus
82 }
83 #endif
84
85 #endif