38 #include <sys/types.h> 44 #include <qb/qbipc_common.h> 75 static uint8_t qdevice_can_operate = 1;
76 static void *qdevice_reg_conn = NULL;
77 static uint8_t qdevice_master_wins = 0;
79 static uint8_t two_node = 0;
81 static uint8_t wait_for_all = 0;
82 static uint8_t wait_for_all_status = 0;
85 static int lowest_node_id = -1;
86 static int highest_node_id = -1;
88 #define DEFAULT_LMS_WIN 10000 89 static uint8_t last_man_standing = 0;
92 static uint8_t allow_downscale = 0;
93 static uint32_t ev_barrier = 0;
95 static uint8_t ev_tracking = 0;
96 static uint32_t ev_tracking_barrier = 0;
97 static int ev_tracking_fd = -1;
112 struct qb_ipc_request_header header __attribute__((aligned(8)));
122 struct qb_ipc_request_header header __attribute__((aligned(8)));
128 struct qb_ipc_request_header header __attribute__((aligned(8)));
143 #define MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO 0 144 #define MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE 1 145 #define MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_REG 2 146 #define MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_RECONFIGURE 3 148 static void votequorum_exec_send_expectedvotes_notification(
void);
149 static int votequorum_exec_send_quorum_notification(
void *conn, uint64_t context);
150 static int votequorum_exec_send_nodelist_notification(
void *conn, uint64_t context);
152 #define VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES 1 153 #define VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES 2 154 #define VOTEQUORUM_RECONFIG_PARAM_CANCEL_WFA 3 156 static int votequorum_exec_send_reconfigure(uint8_t
param,
unsigned int nodeid, uint32_t
value);
161 #define VOTEQUORUM_QDEVICE_OPERATION_UNREGISTER 0 162 #define VOTEQUORUM_QDEVICE_OPERATION_REGISTER 1 168 #define NODE_FLAGS_QUORATE 1 169 #define NODE_FLAGS_LEAVING 2 170 #define NODE_FLAGS_WFASTATUS 4 171 #define NODE_FLAGS_FIRST 8 172 #define NODE_FLAGS_QDEVICE_REGISTERED 16 173 #define NODE_FLAGS_QDEVICE_ALIVE 32 174 #define NODE_FLAGS_QDEVICE_CAST_VOTE 64 175 #define NODE_FLAGS_QDEVICE_MASTER_WINS 128 196 static uint8_t quorum;
197 static uint8_t cluster_is_quorate;
204 static struct list_head cluster_members_list;
208 static int quorum_members_entries = 0;
209 static int previous_quorum_members_entries = 0;
210 static int atb_nodelist_entries = 0;
217 static int cluster_nodes_entries = 0;
237 static int qdevice_timer_set = 0;
239 static int last_man_standing_timer_set = 0;
240 static int sync_nodeinfo_sent = 0;
241 static int sync_wait_for_poll_or_timeout = 0;
247 static int sync_in_progress = 0;
249 static void votequorum_sync_init (
250 const unsigned int *trans_list,
251 size_t trans_list_entries,
252 const unsigned int *member_list,
253 size_t member_list_entries,
256 static int votequorum_sync_process (
void);
257 static void votequorum_sync_activate (
void);
258 static void votequorum_sync_abort (
void);
267 static int votequorum_exec_exit_fn (
void);
268 static int votequorum_exec_send_nodeinfo(uint32_t
nodeid);
270 static void message_handler_req_exec_votequorum_nodeinfo (
273 static void exec_votequorum_nodeinfo_endian_convert (
void *message);
275 static void message_handler_req_exec_votequorum_reconfigure (
278 static void exec_votequorum_reconfigure_endian_convert (
void *message);
280 static void message_handler_req_exec_votequorum_qdevice_reg (
283 static void exec_votequorum_qdevice_reg_endian_convert (
void *message);
285 static void message_handler_req_exec_votequorum_qdevice_reconfigure (
288 static void exec_votequorum_qdevice_reconfigure_endian_convert (
void *message);
294 .exec_endian_convert_fn = exec_votequorum_nodeinfo_endian_convert
297 .exec_handler_fn = message_handler_req_exec_votequorum_reconfigure,
298 .exec_endian_convert_fn = exec_votequorum_reconfigure_endian_convert
301 .exec_handler_fn = message_handler_req_exec_votequorum_qdevice_reg,
302 .exec_endian_convert_fn = exec_votequorum_qdevice_reg_endian_convert
305 .exec_handler_fn = message_handler_req_exec_votequorum_qdevice_reconfigure,
306 .exec_endian_convert_fn = exec_votequorum_qdevice_reconfigure_endian_convert
314 static int quorum_lib_init_fn (
void *conn);
316 static int quorum_lib_exit_fn (
void *conn);
318 static void qdevice_timer_fn(
void *arg);
320 static void message_handler_req_lib_votequorum_getinfo (
void *conn,
321 const void *message);
323 static void message_handler_req_lib_votequorum_setexpected (
void *conn,
324 const void *message);
326 static void message_handler_req_lib_votequorum_setvotes (
void *conn,
327 const void *message);
329 static void message_handler_req_lib_votequorum_trackstart (
void *conn,
330 const void *message);
332 static void message_handler_req_lib_votequorum_trackstop (
void *conn,
333 const void *message);
335 static void message_handler_req_lib_votequorum_qdevice_register (
void *conn,
336 const void *message);
338 static void message_handler_req_lib_votequorum_qdevice_unregister (
void *conn,
339 const void *message);
341 static void message_handler_req_lib_votequorum_qdevice_update (
void *conn,
342 const void *message);
344 static void message_handler_req_lib_votequorum_qdevice_poll (
void *conn,
345 const void *message);
347 static void message_handler_req_lib_votequorum_qdevice_master_wins (
void *conn,
348 const void *message);
357 .lib_handler_fn = message_handler_req_lib_votequorum_setexpected,
361 .lib_handler_fn = message_handler_req_lib_votequorum_setvotes,
365 .lib_handler_fn = message_handler_req_lib_votequorum_trackstart,
369 .lib_handler_fn = message_handler_req_lib_votequorum_trackstop,
373 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_register,
377 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_unregister,
381 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_update,
385 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_poll,
389 .lib_handler_fn = message_handler_req_lib_votequorum_qdevice_master_wins,
395 .
name =
"corosync vote quorum service v1.0",
398 .private_data_size =
sizeof (
struct quorum_pd),
401 .lib_init_fn = quorum_lib_init_fn,
402 .lib_exit_fn = quorum_lib_exit_fn,
403 .lib_engine = quorum_lib_service,
405 .exec_init_fn = votequorum_exec_init_fn,
406 .exec_exit_fn = votequorum_exec_exit_fn,
407 .exec_engine = votequorum_exec_engine,
409 .sync_init = votequorum_sync_init,
410 .sync_process = votequorum_sync_process,
411 .sync_activate = votequorum_sync_activate,
412 .sync_abort = votequorum_sync_abort
417 return (&votequorum_service_engine);
422 .
name =
"corosync_votequorum",
432 #define max(a,b) (((a) > (b)) ? (a) : (b)) 434 #define list_iterate(v, head) \ 435 for (v = (head)->next; v != head; v = v->next) 437 static void node_add_ordered(
struct cluster_node *newnode)
453 list_add(&newnode->
list, &cluster_members_list);
472 cl = (
struct cluster_node *)&cluster_nodes[cluster_nodes_entries];
473 cluster_nodes_entries++;
494 node_add_ordered(cl);
503 static struct cluster_node *find_node_by_nodeid(
unsigned int nodeid)
532 static void get_lowest_node_id(
void)
544 (node->
node_id < lowest_node_id)) {
545 lowest_node_id = node->
node_id;
554 static void get_highest_node_id(
void)
566 (node->
node_id > highest_node_id)) {
567 highest_node_id = node->
node_id;
576 static int check_low_node_id_partition(
void)
587 (node->
node_id == lowest_node_id)) {
596 static int check_high_node_id_partition(
void)
607 (node->
node_id == highest_node_id)) {
616 static int is_in_nodelist(
int nodeid,
unsigned int *members,
int entries)
621 for (i=0; i<entries; i++) {
622 if (nodeid == members[i]) {
644 static int check_auto_tie_breaker(
void)
651 res = check_low_node_id_partition();
657 res = check_high_node_id_partition();
664 for (i=0; i < atb_nodelist_entries; i++) {
665 if (is_in_nodelist(atb_nodelist[i], quorum_members, quorum_members_entries)) {
672 for (j=0; j<i; j++) {
673 if (is_in_nodelist(atb_nodelist[j], previous_quorum_members, previous_quorum_members_entries)) {
700 static void parse_atb_string(
char *atb_string)
708 if (!strcmp(atb_string,
"lowest"))
711 if (!strcmp(atb_string,
"highest"))
714 if (atoi(atb_string)) {
716 atb_nodelist_entries = 0;
719 num = strtol(ptr, &ptr, 10);
722 atb_nodelist[atb_nodelist_entries++] = num;
726 if (atb_nodelist_entries) {
735 log_printf(
LOGSYS_LEVEL_WARNING,
"auto_tie_breaker_nodes is not valid. It must be 'lowest', 'highest' or a space-separated list of node IDs. auto_tie_breaker is disabled");
741 static int check_qdevice_master(
void)
762 static void decode_flags(uint32_t
flags)
767 "flags: quorate: %s Leaving: %s WFA Status: %s First: %s Qdevice: %s QdeviceAlive: %s QdeviceCastVote: %s QdeviceMasterWins: %s",
783 static int load_ev_tracking_barrier(
void)
786 char filename[PATH_MAX];
790 snprintf(filename,
sizeof(filename) - 1,
"%s/ev_tracking",
get_run_dir());
792 ev_tracking_fd = open(filename, O_RDWR, 0700);
793 if (ev_tracking_fd != -1) {
794 res = read (ev_tracking_fd, &ev_tracking_barrier,
sizeof(uint32_t));
795 close(ev_tracking_fd);
796 if (res ==
sizeof (uint32_t)) {
802 ev_tracking_barrier = 0;
804 ev_tracking_fd = open (filename, O_CREAT|O_RDWR, 0700);
805 if (ev_tracking_fd != -1) {
806 res = write (ev_tracking_fd, &ev_tracking_barrier,
sizeof (uint32_t));
807 if ((res == -1) || (res !=
sizeof (uint32_t))) {
809 "Unable to write to %s", filename);
811 close(ev_tracking_fd);
816 "Unable to create %s file", filename);
823 static void update_wait_for_all_status(uint8_t wfa_status)
827 wait_for_all_status = wfa_status;
828 if (wait_for_all_status) {
834 wait_for_all_status);
839 static void update_two_node(
void)
858 static void update_qdevice_can_operate(uint8_t status)
862 qdevice_can_operate = status;
863 icmap_set_uint8(
"runtime.votequorum.qdevice_can_operate", qdevice_can_operate);
868 static void update_qdevice_master_wins(uint8_t allow)
872 qdevice_master_wins = allow;
873 icmap_set_uint8(
"runtime.votequorum.qdevice_master_wins", qdevice_master_wins);
878 static void update_ev_tracking_barrier(uint32_t ev_t_barrier)
884 ev_tracking_barrier = ev_t_barrier;
885 icmap_set_uint32(
"runtime.votequorum.ev_tracking_barrier", ev_tracking_barrier);
887 if (lseek (ev_tracking_fd, 0, SEEK_SET) != 0) {
889 "Unable to update ev_tracking_barrier on disk data!!!");
894 res = write (ev_tracking_fd, &ev_tracking_barrier,
sizeof (uint32_t));
895 if (res !=
sizeof (uint32_t)) {
897 "Unable to update ev_tracking_barrier on disk data!!!");
899 #ifdef HAVE_FDATASYNC 900 fdatasync(ev_tracking_fd);
902 fsync(ev_tracking_fd);
912 static int calculate_quorum(
int allow_decrease,
unsigned int max_expected,
unsigned int *ret_total_votes)
916 unsigned int total_votes = 0;
917 unsigned int highest_expected = 0;
918 unsigned int newquorum, q1, q2;
919 unsigned int total_nodes = 0;
923 if ((allow_downscale) && (allow_decrease) && (max_expected)) {
924 max_expected =
max(ev_barrier, max_expected);
935 total_votes += node->
votes;
942 total_votes += qdevice->
votes;
946 if (max_expected > 0) {
947 highest_expected = max_expected;
954 q1 = (highest_expected + 2) / 2;
955 q2 = (total_votes + 2) / 2;
956 newquorum =
max(q1, q2);
962 if (!allow_decrease) {
963 newquorum =
max(quorum, newquorum);
973 if (two_node && total_nodes <= 2) {
977 if (ret_total_votes) {
978 *ret_total_votes = total_votes;
985 static void update_node_expected_votes(
int new_expected_votes)
990 if (new_expected_votes) {
1001 static void are_we_quorate(
unsigned int total_votes)
1004 int quorum_change = 0;
1012 if ((wait_for_all) && (wait_for_all_status)) {
1015 "Waiting for all cluster members. " 1016 "Current votes: %d expected_votes: %d",
1018 cluster_is_quorate = 0;
1021 update_wait_for_all_status(0);
1024 if (quorum > total_votes) {
1028 get_lowest_node_id();
1029 get_highest_node_id();
1032 if ((auto_tie_breaker !=
ATB_NONE) &&
1036 (previous_quorum_members_entries - quorum_members_entries < quorum) &&
1037 (check_auto_tie_breaker() == 1)) {
1041 if ((qdevice_master_wins) &&
1043 (check_qdevice_master() == 1)) {
1048 if (cluster_is_quorate && !quorate) {
1052 if (!cluster_is_quorate && quorate) {
1058 if (cluster_is_quorate) {
1066 update_wait_for_all_status(0);
1068 update_wait_for_all_status(1);
1072 if ((quorum_change) &&
1073 (sync_in_progress == 0)) {
1074 quorum_callback(quorum_members, quorum_members_entries,
1075 cluster_is_quorate, &quorum_ringid);
1076 votequorum_exec_send_quorum_notification(NULL, 0L);
1082 static void get_total_votes(
unsigned int *totalvotes,
unsigned int *current_members)
1084 unsigned int total_votes = 0;
1085 unsigned int cluster_members = 0;
1095 total_votes += node->
votes;
1099 if (qdevice->
votes) {
1100 total_votes += qdevice->
votes;
1104 *totalvotes = total_votes;
1105 *current_members = cluster_members;
1113 static void recalculate_quorum(
int allow_decrease,
int by_current_nodes)
1115 unsigned int total_votes = 0;
1116 unsigned int cluster_members = 0;
1120 get_total_votes(&total_votes, &cluster_members);
1122 if (!by_current_nodes) {
1123 cluster_members = 0;
1132 votequorum_exec_send_expectedvotes_notification();
1135 if ((ev_tracking) &&
1140 quorum = calculate_quorum(allow_decrease, cluster_members, &total_votes);
1141 update_node_expected_votes(cluster_members);
1143 are_we_quorate(total_votes);
1152 static int votequorum_read_nodelist_configuration(uint32_t *
votes,
1154 uint32_t *expected_votes)
1157 const char *iter_key;
1159 uint32_t our_pos, node_pos;
1160 uint32_t nodecount = 0;
1161 uint32_t nodelist_expected_votes = 0;
1162 uint32_t node_votes = 0;
1169 "No nodelist defined or our node is not in the nodelist");
1177 res = sscanf(iter_key,
"nodelist.node.%u.%s", &node_pos, tmp_key);
1182 if (strcmp(tmp_key,
"ring0_addr") != 0) {
1193 nodelist_expected_votes = nodelist_expected_votes + node_votes;
1195 if (node_pos == our_pos) {
1196 *votes = node_votes;
1200 *expected_votes = nodelist_expected_votes;
1210 static int votequorum_qdevice_is_configured(uint32_t *qdevice_votes)
1212 char *qdevice_model = NULL;
1218 if (strlen(qdevice_model)) {
1220 *qdevice_votes = -1;
1228 update_qdevice_can_operate(1);
1232 free(qdevice_model);
1240 #define VOTEQUORUM_READCONFIG_STARTUP 0 1241 #define VOTEQUORUM_READCONFIG_RUNTIME 1 1243 static char *votequorum_readconfig(
int runtime)
1245 uint32_t node_votes = 0, qdevice_votes = 0;
1246 uint32_t node_expected_votes = 0, expected_votes = 0;
1247 uint32_t node_count = 0;
1249 int have_nodelist, have_qdevice;
1250 char *atb_string = NULL;
1268 auto_tie_breaker = initial_auto_tie_breaker;
1276 have_nodelist = votequorum_read_nodelist_configuration(&node_votes, &node_count, &node_expected_votes);
1277 have_qdevice = votequorum_qdevice_is_configured(&qdevice_votes);
1284 if ((!have_nodelist) && (!expected_votes)) {
1286 error = (
char *)
"configuration error: nodelist or quorum.expected_votes must be configured!";
1299 if ((two_node) && (have_qdevice)) {
1301 error = (
char *)
"configuration error: two_node and quorum device cannot be configured at the same time!";
1310 update_qdevice_can_operate(0);
1326 icmap_get_uint32(
"quorum.last_man_standing_window", &last_man_standing_window);
1340 "auto_tie_breaker_node: is meaningless if auto_tie_breaker is set to 0");
1344 if (atb && atb_string) {
1345 parse_atb_string(atb_string);
1348 initial_auto_tie_breaker = auto_tie_breaker;
1351 if (allow_downscale) {
1356 if (load_ev_tracking_barrier() < 0) {
1358 return ((
char *)
"Unable to load ev_tracking file!");
1360 update_ev_tracking_barrier(ev_tracking_barrier);
1368 if (two_node && auto_tie_breaker !=
ATB_NONE) {
1378 if ((auto_tie_breaker !=
ATB_NONE) && (node_expected_votes % 2) &&
1380 if (last_man_standing) {
1389 error = (
char *)
"configuration error: auto_tie_breaker & last_man_standing not available in odd sized cluster";
1408 if ((have_qdevice) && (last_man_standing)) {
1410 error = (
char *)
"configuration error: quorum.device is not compatible with last_man_standing";
1415 update_qdevice_can_operate(0);
1419 if ((have_qdevice) && (auto_tie_breaker !=
ATB_NONE)) {
1421 error = (
char *)
"configuration error: quorum.device is not compatible with auto_tie_breaker";
1426 update_qdevice_can_operate(0);
1430 if ((have_qdevice) && (allow_downscale)) {
1432 error = (
char *)
"configuration error: quorum.device is not compatible with allow_downscale";
1437 update_qdevice_can_operate(0);
1446 if ((expected_votes) && (have_qdevice) && (qdevice_votes == -1)) {
1448 error = (
char *)
"configuration error: quorum.device.votes must be specified when quorum.expected_votes is set";
1453 update_qdevice_can_operate(0);
1462 if ((have_qdevice) &&
1463 (qdevice_votes == -1) &&
1465 (node_count != node_expected_votes)) {
1467 error = (
char *)
"configuration error: quorum.device.votes must be specified when not all nodes votes 1";
1472 update_qdevice_can_operate(0);
1480 if ((qdevice_votes > 0) && (expected_votes)) {
1481 int delta = expected_votes - qdevice_votes;
1484 error = (
char *)
"configuration error: quorum.device.votes is too high or expected_votes is too low";
1489 update_qdevice_can_operate(0);
1498 if ((have_qdevice) &&
1499 (qdevice_votes == -1) &&
1500 (!expected_votes) &&
1502 (node_count == node_expected_votes)) {
1503 qdevice_votes = node_expected_votes - 1;
1504 node_expected_votes = node_expected_votes + qdevice_votes;
1510 log_printf(
LOGSYS_LEVEL_DEBUG,
"ev_tracking=%d, ev_tracking_barrier = %d: expected_votes = %d\n", ev_tracking, ev_tracking_barrier, expected_votes);
1513 expected_votes = ev_tracking_barrier;
1516 if (have_nodelist) {
1517 us->
votes = node_votes;
1524 if (expected_votes) {
1532 if (!have_qdevice) {
1536 if (qdevice_votes != -1) {
1537 qdevice->
votes = qdevice_votes;
1543 update_wait_for_all_status(1);
1551 static void votequorum_refresh_config(
1553 const char *key_name,
1558 int old_votes, old_expected_votes;
1568 if (
icmap_get_uint8(
"config.totemconfig_reload_in_progress", &reloading) ==
CS_OK && reloading) {
1573 if (strcmp(key_name,
"quorum.cancel_wait_for_all") == 0 &&
1581 old_votes = us->
votes;
1592 votequorum_exec_send_nodeinfo(us->
node_id);
1594 if (us->
votes != old_votes) {
1606 static void votequorum_exec_add_config_notification(
void)
1616 votequorum_refresh_config,
1618 &icmap_track_nodelist);
1622 votequorum_refresh_config,
1624 &icmap_track_quorum);
1628 votequorum_refresh_config,
1630 &icmap_track_reload);
1639 static int votequorum_exec_send_reconfigure(uint8_t
param,
unsigned int nodeid, uint32_t
value)
1642 struct iovec iov[1];
1650 req_exec_quorum_reconfigure.
_pad0 = 0;
1651 req_exec_quorum_reconfigure.
_pad1 = 0;
1652 req_exec_quorum_reconfigure.
_pad2 = 0;
1655 req_exec_quorum_reconfigure.header.size =
sizeof(req_exec_quorum_reconfigure);
1657 iov[0].iov_base = (
void *)&req_exec_quorum_reconfigure;
1658 iov[0].iov_len =
sizeof(req_exec_quorum_reconfigure);
1666 static int votequorum_exec_send_nodeinfo(uint32_t nodeid)
1669 struct iovec iov[1];
1675 node = find_node_by_nodeid(nodeid);
1681 req_exec_quorum_nodeinfo.
votes = node->
votes;
1683 req_exec_quorum_nodeinfo.
flags = node->
flags;
1685 decode_flags(node->
flags);
1689 req_exec_quorum_nodeinfo.header.size =
sizeof(req_exec_quorum_nodeinfo);
1691 iov[0].iov_base = (
void *)&req_exec_quorum_nodeinfo;
1692 iov[0].iov_len =
sizeof(req_exec_quorum_nodeinfo);
1700 static int votequorum_exec_send_qdevice_reconfigure(
const char *
oldname,
const char *
newname)
1703 struct iovec iov[1];
1709 req_exec_quorum_qdevice_reconfigure.header.size =
sizeof(req_exec_quorum_qdevice_reconfigure);
1710 strcpy(req_exec_quorum_qdevice_reconfigure.
oldname, oldname);
1711 strcpy(req_exec_quorum_qdevice_reconfigure.
newname, newname);
1713 iov[0].iov_base = (
void *)&req_exec_quorum_qdevice_reconfigure;
1714 iov[0].iov_len =
sizeof(req_exec_quorum_qdevice_reconfigure);
1722 static int votequorum_exec_send_qdevice_reg(uint32_t
operation,
const char *qdevice_name_req)
1725 struct iovec iov[1];
1731 req_exec_quorum_qdevice_reg.header.size =
sizeof(req_exec_quorum_qdevice_reg);
1733 strcpy(req_exec_quorum_qdevice_reg.
qdevice_name, qdevice_name_req);
1735 iov[0].iov_base = (
void *)&req_exec_quorum_qdevice_reg;
1736 iov[0].iov_len =
sizeof(req_exec_quorum_qdevice_reg);
1744 static int votequorum_exec_send_quorum_notification(
void *conn, uint64_t context)
1750 int cluster_members = 0;
1769 res_lib_votequorum_notification->quorate = cluster_is_quorate;
1770 res_lib_votequorum_notification->context = context;
1771 res_lib_votequorum_notification->node_list_entries = cluster_members;
1773 res_lib_votequorum_notification->header.size = size;
1774 res_lib_votequorum_notification->header.error =
CS_OK;
1779 res_lib_votequorum_notification->node_list[i].nodeid = node->
node_id;
1780 res_lib_votequorum_notification->node_list[i++].state = node->
state;
1784 res_lib_votequorum_notification->node_list[i++].state = qdevice->
state;
1807 static int votequorum_exec_send_nodelist_notification(
void *conn, uint64_t context)
1822 res_lib_votequorum_notification->node_list_entries = quorum_members_entries;
1823 res_lib_votequorum_notification->ring_id.nodeid = quorum_ringid.
rep.
nodeid;
1824 res_lib_votequorum_notification->ring_id.seq = quorum_ringid.
seq;
1825 res_lib_votequorum_notification->context = context;
1827 for (i=0; i<quorum_members_entries; i++) {
1828 res_lib_votequorum_notification->node_list[i] = quorum_members[i];
1832 res_lib_votequorum_notification->header.size = size;
1833 res_lib_votequorum_notification->header.error =
CS_OK;
1855 static void votequorum_exec_send_expectedvotes_notification(
void)
1866 res_lib_votequorum_expectedvotes_notification.header.size =
sizeof(res_lib_votequorum_expectedvotes_notification);
1867 res_lib_votequorum_expectedvotes_notification.header.error =
CS_OK;
1868 res_lib_votequorum_expectedvotes_notification.expected_votes = us->
expected_votes;
1872 res_lib_votequorum_expectedvotes_notification.context = qpd->
tracking_context;
1874 sizeof(
struct res_lib_votequorum_expectedvotes_notification));
1880 static void exec_votequorum_qdevice_reconfigure_endian_convert (
void *message)
1887 static void message_handler_req_exec_votequorum_qdevice_reconfigure (
1888 const void *message,
1889 unsigned int nodeid)
1897 req_exec_quorum_qdevice_reconfigure->
oldname,
1898 req_exec_quorum_qdevice_reconfigure->
newname);
1900 if (!strcmp(req_exec_quorum_qdevice_reconfigure->
oldname, qdevice_name)) {
1903 strcpy(qdevice_name, req_exec_quorum_qdevice_reconfigure->
newname);
1914 static void exec_votequorum_qdevice_reg_endian_convert (
void *message)
1925 static void message_handler_req_exec_votequorum_qdevice_reg (
1926 const void *message,
1927 unsigned int nodeid)
1931 int wipe_qdevice_name = 1;
1942 switch(req_exec_quorum_qdevice_reg->
operation)
1946 if (!strlen(qdevice_name)) {
1948 strcpy(qdevice_name, req_exec_quorum_qdevice_reg->
qdevice_name);
1967 if (!qdevice_reg_conn) {
1976 if (!strlen(qdevice_name)) {
1977 strcpy(qdevice_name, req_exec_quorum_qdevice_reg->
qdevice_name);
1983 if ((!strncmp(req_exec_quorum_qdevice_reg->
qdevice_name,
1987 votequorum_exec_send_nodeinfo(us->
node_id);
1990 "A new qdevice with different name (new: %s old: %s) is trying to register!",
1991 req_exec_quorum_qdevice_reg->
qdevice_name, qdevice_name);
1995 res_lib_votequorum_status.header.size =
sizeof(res_lib_votequorum_status);
1997 res_lib_votequorum_status.header.error = error;
1998 corosync_api->
ipc_response_send(qdevice_reg_conn, &res_lib_votequorum_status,
sizeof(res_lib_votequorum_status));
1999 qdevice_reg_conn = NULL;
2006 wipe_qdevice_name = 0;
2010 if (wipe_qdevice_name) {
2019 static void exec_votequorum_nodeinfo_endian_convert (
void *message)
2033 static void message_handler_req_exec_votequorum_nodeinfo (
2034 const void *message,
2035 unsigned int sender_nodeid)
2042 nodestate_t old_state;
2044 int allow_downgrade = 0;
2046 unsigned int nodeid = req_exec_quorum_nodeinfo->
nodeid;
2053 req_exec_quorum_nodeinfo->
votes,
2055 req_exec_quorum_nodeinfo->
flags);
2058 decode_flags(req_exec_quorum_nodeinfo->
flags);
2061 node = find_node_by_nodeid(nodeid);
2063 node = allocate_node(nodeid);
2078 old_votes = node->
votes;
2080 old_state = node->
state;
2081 old_flags = node->
flags;
2085 struct cluster_node *sender_node = find_node_by_nodeid(sender_nodeid);
2087 assert(sender_node != NULL);
2089 if ((!cluster_is_quorate) &&
2091 node->
votes = req_exec_quorum_nodeinfo->
votes;
2099 node->
flags = req_exec_quorum_nodeinfo->
flags;
2100 node->
votes = req_exec_quorum_nodeinfo->
votes;
2105 allow_downgrade = 1;
2109 if ((!cluster_is_quorate) &&
2111 allow_downgrade = 1;
2121 if ((last_man_standing) && (node->
votes > 1)) {
2123 "cluster nodes votes are set to 1. Disabling LMS.");
2124 last_man_standing = 0;
2125 if (last_man_standing_timer_set) {
2127 last_man_standing_timer_set = 0;
2135 (old_votes != node->
votes) ||
2137 (old_flags != node->
flags) ||
2138 (old_state != node->
state)) {
2139 recalculate_quorum(allow_downgrade, by_node);
2142 if ((wait_for_all) &&
2145 update_wait_for_all_status(0);
2151 static void exec_votequorum_reconfigure_endian_convert (
void *message)
2163 static void message_handler_req_exec_votequorum_reconfigure (
2164 const void *message,
2165 unsigned int nodeid)
2173 nodeid, req_exec_quorum_reconfigure->
nodeid);
2175 switch(req_exec_quorum_reconfigure->
param)
2178 update_node_expected_votes(req_exec_quorum_reconfigure->
value);
2180 votequorum_exec_send_expectedvotes_notification();
2181 update_ev_barrier(req_exec_quorum_reconfigure->
value);
2185 recalculate_quorum(1, 0);
2189 node = find_node_by_nodeid(req_exec_quorum_reconfigure->
nodeid);
2194 node->
votes = req_exec_quorum_reconfigure->
value;
2195 recalculate_quorum(1, 0);
2199 update_wait_for_all_status(0);
2201 req_exec_quorum_reconfigure->
nodeid);
2202 recalculate_quorum(0, 0);
2211 static int votequorum_exec_exit_fn (
void)
2221 if (allow_downscale) {
2223 ret = votequorum_exec_send_nodeinfo(us->
node_id);
2226 if ((ev_tracking) && (ev_tracking_fd != -1)) {
2227 close(ev_tracking_fd);
2235 static void votequorum_set_icmap_ro_keys(
void)
2255 list_init(&cluster_members_list);
2256 list_init(&trackers_list);
2259 memset(cluster_nodes, 0,
sizeof(cluster_nodes));
2267 return ((
char *)
"Could not allocate node.");
2278 return ((
char *)
"Could not allocate node.");
2291 recalculate_quorum(0, 0);
2296 votequorum_set_icmap_ro_keys();
2301 votequorum_exec_add_config_notification();
2306 votequorum_exec_send_nodeinfo(us->
node_id);
2317 static void votequorum_last_man_standing_timer_fn(
void *arg)
2321 last_man_standing_timer_set = 0;
2322 if (cluster_is_quorate) {
2323 recalculate_quorum(1,1);
2329 static void votequorum_sync_init (
2330 const unsigned int *trans_list,
size_t trans_list_entries,
2331 const unsigned int *member_list,
size_t member_list_entries,
2341 sync_in_progress = 1;
2342 sync_nodeinfo_sent = 0;
2343 sync_wait_for_poll_or_timeout = 0;
2345 if (member_list_entries > 1) {
2355 for (i = 0; i < quorum_members_entries; i++) {
2357 for (j = 0; j < member_list_entries; j++) {
2358 if (quorum_members[i] == member_list[j]) {
2365 node = find_node_by_nodeid(quorum_members[i]);
2372 if (last_man_standing) {
2373 if (((member_list_entries >= quorum) && (left_nodes)) ||
2374 ((member_list_entries <= quorum) && (auto_tie_breaker !=
ATB_NONE) && (check_low_node_id_partition() == 1))) {
2375 if (last_man_standing_timer_set) {
2377 last_man_standing_timer_set = 0;
2379 corosync_api->
timer_add_duration((
unsigned long long)last_man_standing_window*1000000,
2380 NULL, votequorum_last_man_standing_timer_fn,
2381 &last_man_standing_timer);
2382 last_man_standing_timer_set = 1;
2386 memcpy(previous_quorum_members, quorum_members,
sizeof(
unsigned int) * quorum_members_entries);
2387 previous_quorum_members_entries = quorum_members_entries;
2389 memcpy(quorum_members, member_list,
sizeof(
unsigned int) * member_list_entries);
2390 quorum_members_entries = member_list_entries;
2391 memcpy(&quorum_ringid, ring_id,
sizeof(*ring_id));
2397 if (qdevice_timer_set) {
2400 corosync_api->
timer_add_duration((
unsigned long long)qdevice_sync_timeout*1000000, qdevice,
2401 qdevice_timer_fn, &qdevice_timer);
2402 qdevice_timer_set = 1;
2403 sync_wait_for_poll_or_timeout = 1;
2406 qdevice_name, qdevice_sync_timeout);
2412 static int votequorum_sync_process (
void)
2414 if (!sync_nodeinfo_sent) {
2415 votequorum_exec_send_nodeinfo(us->
node_id);
2417 if (strlen(qdevice_name)) {
2421 votequorum_exec_send_nodelist_notification(NULL, 0LL);
2422 sync_nodeinfo_sent = 1;
2436 static void votequorum_sync_activate (
void)
2438 recalculate_quorum(0, 0);
2439 quorum_callback(quorum_members, quorum_members_entries,
2440 cluster_is_quorate, &quorum_ringid);
2441 votequorum_exec_send_quorum_notification(NULL, 0L);
2443 sync_in_progress = 0;
2446 static void votequorum_sync_abort (
void)
2458 if (q_set_quorate_fn == NULL) {
2459 return ((
char *)
"Quorate function not set");
2463 quorum_callback = q_set_quorate_fn;
2466 &votequorum_service[0]);
2480 static int quorum_lib_init_fn (
void *conn)
2486 list_init (&pd->
list);
2493 static int quorum_lib_exit_fn (
void *conn)
2500 list_del (&quorum_pd->
list);
2501 list_init (&quorum_pd->
list);
2513 static void qdevice_timer_fn(
void *arg)
2518 (!qdevice_timer_set)) {
2526 votequorum_exec_send_nodeinfo(us->
node_id);
2528 qdevice_timer_set = 0;
2529 sync_wait_for_poll_or_timeout = 0;
2538 static void message_handler_req_lib_votequorum_getinfo (
void *conn,
const void *message)
2543 unsigned int highest_expected = 0;
2544 unsigned int total_votes = 0;
2546 uint32_t nodeid = req_lib_votequorum_getinfo->
nodeid;
2556 node = find_node_by_nodeid(nodeid);
2567 total_votes += iternode->
votes;
2572 total_votes += qdevice->
votes;
2575 switch(node->
state) {
2586 res_lib_votequorum_getinfo.
state = node->
state;
2589 res_lib_votequorum_getinfo.
state = node->
state;
2590 res_lib_votequorum_getinfo.
votes = node->
votes;
2594 res_lib_votequorum_getinfo.
quorum = quorum;
2595 res_lib_votequorum_getinfo.
total_votes = total_votes;
2596 res_lib_votequorum_getinfo.
flags = 0;
2602 if (cluster_is_quorate) {
2608 if (last_man_standing) {
2611 if (auto_tie_breaker !=
ATB_NONE) {
2614 if (allow_downscale) {
2619 strcpy(res_lib_votequorum_getinfo.
qdevice_name, qdevice_name);
2638 res_lib_votequorum_getinfo.header.size =
sizeof(res_lib_votequorum_getinfo);
2640 res_lib_votequorum_getinfo.header.error = error;
2641 corosync_api->
ipc_response_send(conn, &res_lib_votequorum_getinfo,
sizeof(res_lib_votequorum_getinfo));
2647 static void message_handler_req_lib_votequorum_setexpected (
void *conn,
const void *message)
2652 unsigned int newquorum;
2653 unsigned int total_votes;
2654 uint8_t allow_downscale_status = 0;
2658 allow_downscale_status = allow_downscale;
2659 allow_downscale = 0;
2664 newquorum = calculate_quorum(1, req_lib_votequorum_setexpected->
expected_votes, &total_votes);
2665 allow_downscale = allow_downscale_status;
2666 if (newquorum < total_votes / 2 ||
2667 newquorum > total_votes) {
2671 update_node_expected_votes(req_lib_votequorum_setexpected->
expected_votes);
2677 res_lib_votequorum_status.header.size =
sizeof(res_lib_votequorum_status);
2679 res_lib_votequorum_status.header.error = error;
2680 corosync_api->
ipc_response_send(conn, &res_lib_votequorum_status,
sizeof(res_lib_votequorum_status));
2685 static void message_handler_req_lib_votequorum_setvotes (
void *conn,
const void *message)
2690 unsigned int newquorum;
2691 unsigned int total_votes;
2692 unsigned int saved_votes;
2698 nodeid = req_lib_votequorum_setvotes->
nodeid;
2699 node = find_node_by_nodeid(nodeid);
2708 saved_votes = node->
votes;
2709 node->
votes = req_lib_votequorum_setvotes->
votes;
2711 newquorum = calculate_quorum(1, 0, &total_votes);
2713 if (newquorum < total_votes / 2 ||
2714 newquorum > total_votes) {
2715 node->
votes = saved_votes;
2721 req_lib_votequorum_setvotes->
votes);
2724 res_lib_votequorum_status.header.size =
sizeof(res_lib_votequorum_status);
2726 res_lib_votequorum_status.header.error = error;
2727 corosync_api->
ipc_response_send(conn, &res_lib_votequorum_status,
sizeof(res_lib_votequorum_status));
2732 static void message_handler_req_lib_votequorum_trackstart (
void *conn,
2733 const void *message)
2749 votequorum_exec_send_nodelist_notification(conn, req_lib_votequorum_trackstart->
context);
2750 votequorum_exec_send_quorum_notification(conn, req_lib_votequorum_trackstart->
context);
2768 list_add (&quorum_pd->
list, &trackers_list);
2772 res_lib_votequorum_status.header.size =
sizeof(res_lib_votequorum_status);
2774 res_lib_votequorum_status.header.error = error;
2775 corosync_api->
ipc_response_send(conn, &res_lib_votequorum_status,
sizeof(res_lib_votequorum_status));
2780 static void message_handler_req_lib_votequorum_trackstop (
void *conn,
2781 const void *message)
2792 list_del (&quorum_pd->
list);
2793 list_init (&quorum_pd->
list);
2798 res_lib_votequorum_status.header.size =
sizeof(res_lib_votequorum_status);
2800 res_lib_votequorum_status.header.error = error;
2801 corosync_api->
ipc_response_send(conn, &res_lib_votequorum_status,
sizeof(res_lib_votequorum_status));
2806 static void message_handler_req_lib_votequorum_qdevice_register (
void *conn,
2807 const void *message)
2815 if (!qdevice_can_operate) {
2816 log_printf(
LOGSYS_LEVEL_INFO,
"Registration of quorum device is disabled by incorrect corosync.conf. See logs for more information");
2822 if ((!strncmp(req_lib_votequorum_qdevice_register->
name,
2827 "A new qdevice with different name (new: %s old: %s) is trying to re-register!",
2828 req_lib_votequorum_qdevice_register->
name, qdevice_name);
2833 if (qdevice_reg_conn != NULL) {
2835 "Registration request already in progress");
2839 qdevice_reg_conn = conn;
2841 req_lib_votequorum_qdevice_register->
name) != 0) {
2843 "Unable to send qdevice registration request to cluster");
2845 qdevice_reg_conn = NULL;
2854 res_lib_votequorum_status.header.size =
sizeof(res_lib_votequorum_status);
2856 res_lib_votequorum_status.header.error = error;
2857 corosync_api->
ipc_response_send(conn, &res_lib_votequorum_status,
sizeof(res_lib_votequorum_status));
2862 static void message_handler_req_lib_votequorum_qdevice_unregister (
void *conn,
2863 const void *message)
2876 if (qdevice_timer_set) {
2878 qdevice_timer_set = 0;
2879 sync_wait_for_poll_or_timeout = 0;
2885 votequorum_exec_send_nodeinfo(us->
node_id);
2887 req_lib_votequorum_qdevice_unregister->
name);
2893 res_lib_votequorum_status.header.size =
sizeof(res_lib_votequorum_status);
2895 res_lib_votequorum_status.header.error = error;
2896 corosync_api->
ipc_response_send(conn, &res_lib_votequorum_status,
sizeof(res_lib_votequorum_status));
2901 static void message_handler_req_lib_votequorum_qdevice_update (
void *conn,
2902 const void *message)
2915 votequorum_exec_send_qdevice_reconfigure(req_lib_votequorum_qdevice_update->
oldname,
2916 req_lib_votequorum_qdevice_update->
newname);
2922 res_lib_votequorum_status.header.size =
sizeof(res_lib_votequorum_status);
2924 res_lib_votequorum_status.header.error = error;
2925 corosync_api->
ipc_response_send(conn, &res_lib_votequorum_status,
sizeof(res_lib_votequorum_status));
2930 static void message_handler_req_lib_votequorum_qdevice_poll (
void *conn,
2931 const void *message)
2940 if (!qdevice_can_operate) {
2946 if (!(req_lib_votequorum_qdevice_poll->ring_id.nodeid == quorum_ringid.
rep.
nodeid &&
2947 req_lib_votequorum_qdevice_poll->ring_id.seq == quorum_ringid.
seq)) {
2949 "ring id (%u.%"PRIu64
"). Ignoring poll call.",
2950 req_lib_votequorum_qdevice_poll->ring_id.nodeid, req_lib_votequorum_qdevice_poll->ring_id.seq,
2960 if (qdevice_timer_set) {
2962 qdevice_timer_set = 0;
2965 oldflags = us->
flags;
2969 if (req_lib_votequorum_qdevice_poll->
cast_vote) {
2975 if (us->
flags != oldflags) {
2976 votequorum_exec_send_nodeinfo(us->
node_id);
2979 corosync_api->
timer_add_duration((
unsigned long long)qdevice_timeout*1000000, qdevice,
2980 qdevice_timer_fn, &qdevice_timer);
2981 qdevice_timer_set = 1;
2982 sync_wait_for_poll_or_timeout = 0;
2988 res_lib_votequorum_status.header.size =
sizeof(res_lib_votequorum_status);
2990 res_lib_votequorum_status.header.error = error;
2991 corosync_api->
ipc_response_send(conn, &res_lib_votequorum_status,
sizeof(res_lib_votequorum_status));
2996 static void message_handler_req_lib_votequorum_qdevice_master_wins (
void *conn,
2997 const void *message)
3002 uint32_t oldflags = us->
flags;
3006 if (!qdevice_can_operate) {
3017 if (req_lib_votequorum_qdevice_master_wins->
allow) {
3023 if (us->
flags != oldflags) {
3024 votequorum_exec_send_nodeinfo(us->
node_id);
3027 update_qdevice_master_wins(req_lib_votequorum_qdevice_master_wins->
allow);
3033 res_lib_votequorum_status.header.size =
sizeof(res_lib_votequorum_status);
3035 res_lib_votequorum_status.header.error = error;
3036 corosync_api->
ipc_response_send(conn, &res_lib_votequorum_status,
sizeof(res_lib_votequorum_status));
char name[VOTEQUORUM_QDEVICE_MAX_NAME_LEN]
char newname[VOTEQUORUM_QDEVICE_MAX_NAME_LEN]
void *(* ipc_private_data_get)(void *conn)
#define VOTEQUORUM_INFO_QUORATE
char oldname[VOTEQUORUM_QDEVICE_MAX_NAME_LEN]
#define VOTEQUORUM_READCONFIG_STARTUP
const char * get_run_dir(void)
void(* timer_delete)(corosync_timer_handle_t timer_handle)
int(* timer_add_duration)(unsigned long long nanoseconds_in_future, void *data, void(*timer_nf)(void *data), corosync_timer_handle_t *handle)
const char * icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
Return next item in iterator iter.
#define NODE_FLAGS_WFASTATUS
#define LOGSYS_LEVEL_INFO
#define NODE_FLAGS_QUORATE
#define VOTEQUORUM_QDEVICE_DEFAULT_SYNC_TIMEOUT
The corosync_service_engine struct.
void icmap_iter_finalize(icmap_iter_t iter)
Finalize iterator.
The req_lib_votequorum_qdevice_master_wins struct.
#define VOTEQUORUM_QDEVICE_OPERATION_UNREGISTER
#define MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE
int(* ipc_response_send)(void *conn, const void *msg, size_t mlen)
#define list_iterate(v, head)
char * votequorum_init(struct corosync_api_v1 *api, quorum_set_quorate_fn_t q_set_quorate_fn)
#define VOTEQUORUM_RECONFIG_PARAM_CANCEL_WFA
char name[VOTEQUORUM_QDEVICE_MAX_NAME_LEN]
char qdevice_name[VOTEQUORUM_QDEVICE_MAX_NAME_LEN]
The req_lib_votequorum_qdevice_unregister struct.
#define NODE_FLAGS_QDEVICE_MASTER_WINS
The res_lib_votequorum_quorum_notification struct.
The corosync_lib_handler struct.
unsigned int highest_expected
#define VOTEQUORUM_INFO_LAST_MAN_STANDING
struct message_header header
#define VOTEQUORUM_INFO_WAIT_FOR_ALL
#define NODE_FLAGS_QDEVICE_CAST_VOTE
The res_lib_votequorum_status struct.
char name[VOTEQUORUM_QDEVICE_MAX_NAME_LEN]
#define MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_RECONFIGURE
The corosync_exec_handler struct.
#define VOTEQUORUM_INFO_TWONODE
int(* totem_mcast)(const struct iovec *iovec, unsigned int iov_len, unsigned int guarantee)
char qdevice_name[VOTEQUORUM_QDEVICE_MAX_NAME_LEN]
#define VOTEQUORUM_INFO_QDEVICE_REGISTERED
#define log_printf(level, format, args...)
unsigned int expected_votes
void(* exec_handler_fn)(const void *msg, unsigned int nodeid)
#define VOTEQUORUM_QDEVICE_NODEID
#define VOTEQUORUM_INFO_QDEVICE_MASTER_WINS
#define VOTEQUORUM_NODESTATE_MEMBER
#define SERVICE_ID_MAKE(a, b)
#define ICMAP_TRACK_DELETE
#define ICMAP_KEYNAME_MAXLEN
Maximum length of key in icmap.
void(* quorum_set_quorate_fn_t)(const unsigned int *view_list, size_t view_list_entries, int quorate, struct memb_ring_id *)
#define VOTEQUORUM_QDEVICE_OPERATION_REGISTER
cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8)
void(* error_memory_failure)(void) __attribute__((noreturn))
#define VOTEQUORUM_INFO_ALLOW_DOWNSCALE
#define LOGSYS_LEVEL_WARNING
#define ICMAP_TRACK_MODIFY
#define VOTEQUORUM_INFO_QDEVICE_ALIVE
cs_error_t icmap_set_uint32(const char *key_name, uint32_t value)
unsigned int(* totem_nodeid_get)(void)
#define CS_TRACK_CHANGES_ONLY
The req_lib_votequorum_getinfo struct.
char name[VOTEQUORUM_QDEVICE_MAX_NAME_LEN]
struct totem_ip_address rep
#define COROSYNC_LIB_FLOW_CONTROL_NOT_REQUIRED
The req_lib_votequorum_qdevice_update struct.
cs_error_t
The cs_error_t enum.
unsigned char track_flags
#define LOGSYS_LEVEL_DEBUG
LOGSYS_DECLARE_SUBSYS("VOTEQ")
The req_lib_votequorum_setvotes struct.
The corosync_api_v1 struct.
cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32)
The req_lib_votequorum_setexpected struct.
#define swab32(x)
The swab32 macro.
#define VOTEQUORUM_INFO_AUTO_TIE_BREAKER
struct corosync_service_engine * votequorum_get_service_engine_ver0(void)
The res_lib_votequorum_expectedvotes_notification struct.
The req_lib_votequorum_qdevice_register struct.
char * corosync_service_link_and_init(struct corosync_api_v1 *corosync_api, struct default_service *service)
Link and initialize a service.
char newname[VOTEQUORUM_QDEVICE_MAX_NAME_LEN]
#define VOTEQUORUM_NODESTATE_LEAVING
#define PROCESSOR_COUNT_MAX
unsigned int qdevice_votes
#define MESSAGE_REQ_EXEC_VOTEQUORUM_QDEVICE_REG
#define VOTEQUORUM_READCONFIG_RUNTIME
#define MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO
The req_lib_votequorum_trackstart struct.
#define VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES
#define VOTEQUORUM_QDEVICE_MAX_NAME_LEN
qb_loop_timer_handle corosync_timer_handle_t
corosync_timer_handle_t
The req_lib_votequorum_qdevice_poll struct.
cs_error_t icmap_get_string(const char *key_name, char **str)
Shortcut for icmap_get for string type.
#define LOGSYS_LEVEL_CRIT
char oldname[VOTEQUORUM_QDEVICE_MAX_NAME_LEN]
#define NODE_FLAGS_LEAVING
#define list_entry(ptr, type, member)
#define COROSYNC_LIB_FLOW_CONTROL_REQUIRED
#define LOGSYS_LEVEL_NOTICE
cs_error_t icmap_set_uint8(const char *key_name, uint8_t value)
void(* lib_handler_fn)(void *conn, const void *msg)
The res_lib_votequorum_getinfo struct.
#define VOTEQUORUM_NODESTATE_DEAD
cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access)
Set read-only access for given key (key_name) or prefix, If prefix is set.
#define VOTEQUORUM_INFO_QDEVICE_CAST_VOTE
int(* ipc_dispatch_send)(void *conn, const void *msg, size_t mlen)
#define VOTEQUORUM_QDEVICE_DEFAULT_TIMEOUT
icmap_iter_t icmap_iter_init(const char *prefix)
Initialize iterator with given prefix.
struct memb_ring_id ring_id
uint64_t tracking_context
#define VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES
#define NODE_FLAGS_QDEVICE_ALIVE
qb_map_iter_t * icmap_iter_t
Itterator type.
Structure passed as new_value and old_value in change callback.
#define NODE_FLAGS_QDEVICE_REGISTERED
cs_error_t icmap_track_add(const char *key_name, int32_t track_type, icmap_notify_fn_t notify_fn, void *user_data, icmap_track_t *icmap_track)
Add tracking function for given key_name.
struct qb_ipc_request_header header __attribute__((aligned(8)))
#define ICMAP_TRACK_PREFIX
Whole prefix is tracked, instead of key only (so "totem." tracking means that "totem.nodeid", "totem.version", ...
unsigned int expected_votes