This source file includes following definitions.
- attrd_election_cb
- attrd_election_init
- attrd_election_fini
- attrd_start_election_if_needed
- attrd_election_won
- attrd_handle_election_op
- attrd_check_for_new_writer
- attrd_declare_winner
- attrd_remove_voter
- attrd_xml_add_writer
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11 #include <crm/msg_xml.h>
12 #include <crm/cluster.h>
13 #include <crm/cluster/election_internal.h>
14
15 #include "pacemaker-attrd.h"
16
17 static char *peer_writer = NULL;
18 static election_t *writer = NULL;
19
20 static gboolean
21 attrd_election_cb(gpointer user_data)
22 {
23 attrd_declare_winner();
24
25
26 attrd_peer_sync(NULL, NULL);
27
28
29 attrd_write_attributes(true, false);
30 return FALSE;
31 }
32
33 void
34 attrd_election_init(void)
35 {
36 writer = election_init(T_ATTRD, attrd_cluster->uname, 120000,
37 attrd_election_cb);
38 }
39
40 void
41 attrd_election_fini(void)
42 {
43 election_fini(writer);
44 }
45
46 void
47 attrd_start_election_if_needed(void)
48 {
49 if ((peer_writer == NULL)
50 && (election_state(writer) != election_in_progress)
51 && !attrd_shutting_down()) {
52
53 crm_info("Starting an election to determine the writer");
54 election_vote(writer);
55 }
56 }
57
58 bool
59 attrd_election_won(void)
60 {
61 return (election_state(writer) == election_won);
62 }
63
64 void
65 attrd_handle_election_op(const crm_node_t *peer, xmlNode *xml)
66 {
67 enum election_result rc = 0;
68 enum election_result previous = election_state(writer);
69
70 crm_xml_add(xml, F_CRM_HOST_FROM, peer->uname);
71
72
73 rc = election_count_vote(writer, xml, !attrd_shutting_down());
74
75 switch(rc) {
76 case election_start:
77 crm_debug("Unsetting writer (was %s) and starting new election",
78 peer_writer? peer_writer : "unset");
79 free(peer_writer);
80 peer_writer = NULL;
81 election_vote(writer);
82 break;
83
84 case election_lost:
85
86
87
88
89
90
91
92
93
94
95
96 if ((peer_writer == NULL) || (previous != election_lost)) {
97 pcmk__str_update(&peer_writer, peer->uname);
98 crm_debug("Election lost, presuming %s is writer for now",
99 peer_writer);
100 }
101 break;
102
103 case election_in_progress:
104 election_check(writer);
105 break;
106
107 default:
108 crm_info("Ignoring election op from %s due to error", peer->uname);
109 break;
110 }
111 }
112
113 bool
114 attrd_check_for_new_writer(const crm_node_t *peer, const xmlNode *xml)
115 {
116 int peer_state = 0;
117
118 crm_element_value_int(xml, PCMK__XA_ATTR_WRITER, &peer_state);
119 if (peer_state == election_won) {
120 if ((election_state(writer) == election_won)
121 && !pcmk__str_eq(peer->uname, attrd_cluster->uname, pcmk__str_casei)) {
122 crm_notice("Detected another attribute writer (%s), starting new election",
123 peer->uname);
124 election_vote(writer);
125
126 } else if (!pcmk__str_eq(peer->uname, peer_writer, pcmk__str_casei)) {
127 crm_notice("Recorded new attribute writer: %s (was %s)",
128 peer->uname, (peer_writer? peer_writer : "unset"));
129 pcmk__str_update(&peer_writer, peer->uname);
130 }
131 }
132 return (peer_state == election_won);
133 }
134
135 void
136 attrd_declare_winner(void)
137 {
138 crm_notice("Recorded local node as attribute writer (was %s)",
139 (peer_writer? peer_writer : "unset"));
140 pcmk__str_update(&peer_writer, attrd_cluster->uname);
141 }
142
143 void
144 attrd_remove_voter(const crm_node_t *peer)
145 {
146 election_remove(writer, peer->uname);
147 if (peer_writer && pcmk__str_eq(peer->uname, peer_writer, pcmk__str_casei)) {
148 free(peer_writer);
149 peer_writer = NULL;
150 crm_notice("Lost attribute writer %s", peer->uname);
151
152
153
154
155 election_clear_dampening(writer);
156
157
158
159
160
161
162
163 attrd_start_election_if_needed();
164
165
166
167
168
169 } else if (election_state(writer) == election_in_progress) {
170 crm_debug("Checking election status upon loss of voter %s", peer->uname);
171 election_check(writer);
172 }
173 }
174
175 void
176 attrd_xml_add_writer(xmlNode *xml)
177 {
178 crm_xml_add_int(xml, PCMK__XA_ATTR_WRITER, election_state(writer));
179 }