From: "Fabio M. Di Nitto" <fdinitto@xxxxxxxxxx> this commit has no functional changes or bugfixes. Simply reorganize the code in more logical way and change function names to be more consistent. Signed-off-by: Fabio M. Di Nitto <fdinitto@xxxxxxxxxx> --- :100644 100644 96ca5b4... 2e7b8f1... M services/votequorum.c services/votequorum.c | 1426 +++++++++++++++++++++++++------------------------ 1 files changed, 736 insertions(+), 690 deletions(-) diff --git a/services/votequorum.c b/services/votequorum.c index 96ca5b4..2e7b8f1 100644 --- a/services/votequorum.c +++ b/services/votequorum.c @@ -50,9 +50,17 @@ #include <corosync/icmap.h> #include <corosync/ipc_votequorum.h> -#define VOTEQUORUM_MAJOR_VERSION 7 -#define VOTEQUORUM_MINOR_VERSION 0 -#define VOTEQUORUM_PATCH_VERSION 0 +LOGSYS_DECLARE_SUBSYS ("VOTEQ"); + +/* + * interface with corosync + */ + +static struct corosync_api_v1 *corosync_api; + +/* + * votequorum global config vars + */ /* * Silly default to prevent accidents! @@ -60,14 +68,73 @@ #define DEFAULT_EXPECTED 1024 #define DEFAULT_QDEV_POLL 10000 #define DEFAULT_LEAVE_TMO 10000 + +static unsigned int quorumdev_poll = DEFAULT_QDEV_POLL; +static char quorum_device_name[VOTEQUORUM_MAX_QDISK_NAME_LEN]; + +static uint8_t two_node = 0; + +static uint8_t wait_for_all = 0; +static uint8_t wait_for_all_status = 0; + +static uint8_t auto_tie_breaker = 0; +static int lowest_node_id = -1; + #define DEFAULT_LMS_WIN 10000 +static uint8_t last_man_standing = 0; +static uint32_t last_man_standing_window = DEFAULT_LMS_WIN; -LOGSYS_DECLARE_SUBSYS ("VOTEQ"); +/* + * votequorum_exec defines/structs/forward definitions + */ -enum quorum_message_req_types { - MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO = 0, - MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE = 1, -}; +struct req_exec_quorum_nodeinfo { + struct qb_ipc_request_header header __attribute__((aligned(8))); + unsigned int first_trans; + unsigned int votes; + unsigned int expected_votes; + unsigned int major_version; /* Not backwards compatible */ + unsigned int minor_version; /* Backwards compatible */ + unsigned int patch_version; /* Backwards/forwards compatible */ + unsigned int config_version; + unsigned int flags; + unsigned int wait_for_all_status; + unsigned int quorate; +} __attribute__((packed)); + +struct req_exec_quorum_reconfigure { + struct qb_ipc_request_header header __attribute__((aligned(8))); + unsigned int param; + unsigned int nodeid; + unsigned int value; +} __attribute__((packed)); + +/* + * votequorum_exec onwire version (via totem) + */ + +#define VOTEQUORUM_MAJOR_VERSION 7 +#define VOTEQUORUM_MINOR_VERSION 0 +#define VOTEQUORUM_PATCH_VERSION 0 + +/* + * votequorum_exec onwire messages (via totem) + */ + +#define MESSAGE_REQ_EXEC_VOTEQUORUM_NODEINFO 0 +#define MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE 1 + +static void votequorum_exec_send_expectedvotes_notification(void); +static int votequorum_exec_send_quorum_notification(void *conn, uint64_t context); + +#define VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES 1 +#define VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES 2 + +static int votequorum_exec_send_reconfigure(int param, int nodeid, int value); + +/* + * votequorum internal node status/view + */ #define NODE_FLAGS_BEENDOWN 1 #define NODE_FLAGS_QDISK 8 @@ -95,39 +162,28 @@ struct cluster_node { struct list_head list; }; +/* + * votequorum internal quorum status + */ + static int quorum; static int cluster_is_quorate; static int first_trans = 1; -static unsigned int quorumdev_poll = DEFAULT_QDEV_POLL; -static uint8_t two_node = 0; -static uint8_t wait_for_all = 0; -static uint8_t wait_for_all_status = 0; -static uint8_t auto_tie_breaker = 0; -static int lowest_node_id = -1; -static uint8_t last_man_standing = 0; -static uint32_t last_man_standing_window = DEFAULT_LMS_WIN; -static int last_man_standing_timer_set = 0; -static corosync_timer_handle_t last_man_standing_timer; +/* + * votequorum membership data + */ static struct cluster_node *us; static struct cluster_node *quorum_device = NULL; -static char quorum_device_name[VOTEQUORUM_MAX_QDISK_NAME_LEN]; -static corosync_timer_handle_t quorum_device_timer; static struct list_head cluster_members_list; -static struct corosync_api_v1 *corosync_api; -static struct list_head trackers_list; static unsigned int quorum_members[PROCESSOR_COUNT_MAX+1]; static int quorum_members_entries = 0; static struct memb_ring_id quorum_ringid; -#define max(a,b) (((a) > (b)) ? (a) : (b)) -static struct cluster_node *find_node_by_nodeid(int nodeid); -static struct cluster_node *allocate_node(int nodeid); - -#define list_iterate(v, head) \ - for (v = (head)->next; v != head; v = v->next) - +/* + * votequorum tracking + */ struct quorum_pd { unsigned char track_flags; int tracking_enabled; @@ -136,33 +192,67 @@ struct quorum_pd { void *conn; }; +static struct list_head trackers_list; + +/* + * votequorum timers + */ + +static corosync_timer_handle_t quorum_device_timer; +static corosync_timer_handle_t last_man_standing_timer; +static int last_man_standing_timer_set = 0; + /* * Service Interfaces required by service_message_handler struct */ static void votequorum_init(struct corosync_api_v1 *api, - quorum_set_quorate_fn_t report); + quorum_set_quorate_fn_t q_set_quorate_fn); -static void quorum_confchg_fn ( +static void votequorum_confchg_fn ( enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, const unsigned int *joined_list, size_t joined_list_entries, const struct memb_ring_id *ring_id); -static int votequorum_exec_init_fn (struct corosync_api_v1 *api); +static quorum_set_quorate_fn_t quorum_callback; -static int quorum_lib_init_fn (void *conn); +/* + * votequorum_exec handler and definitions + */ -static int quorum_lib_exit_fn (void *conn); +static int votequorum_exec_init_fn (struct corosync_api_v1 *api); static void message_handler_req_exec_votequorum_nodeinfo ( const void *message, unsigned int nodeid); +static void exec_votequorum_nodeinfo_endian_convert (void *message); static void message_handler_req_exec_votequorum_reconfigure ( const void *message, unsigned int nodeid); +static void exec_votequorum_reconfigure_endian_convert (void *message); + +static struct corosync_exec_handler votequorum_exec_engine[] = +{ + { /* 0 */ + .exec_handler_fn = message_handler_req_exec_votequorum_nodeinfo, + .exec_endian_convert_fn = exec_votequorum_nodeinfo_endian_convert + }, + { /* 1 */ + .exec_handler_fn = message_handler_req_exec_votequorum_reconfigure, + .exec_endian_convert_fn = exec_votequorum_reconfigure_endian_convert + }, +}; + +/* + * Library Handler and Functions Definitions + */ + +static int quorum_lib_init_fn (void *conn); + +static int quorum_lib_exit_fn (void *conn); static void message_handler_req_lib_votequorum_getinfo (void *conn, const void *message); @@ -190,19 +280,6 @@ static void message_handler_req_lib_votequorum_trackstart (void *conn, static void message_handler_req_lib_votequorum_trackstop (void *conn, const void *message); -static int quorum_exec_send_nodeinfo(void); -static int quorum_exec_send_reconfigure(int param, int nodeid, int value); - -static void exec_votequorum_nodeinfo_endian_convert (void *message); -static void exec_votequorum_reconfigure_endian_convert (void *message); - -static void add_votequorum_config_notification(void); - -static void recalculate_quorum(int allow_decrease, int by_current_nodes); - -/* - * Library Handler Definition - */ static struct corosync_lib_handler quorum_lib_service[] = { { /* 0 */ @@ -243,48 +320,35 @@ static struct corosync_lib_handler quorum_lib_service[] = } }; -static struct corosync_exec_handler votequorum_exec_engine[] = -{ - { /* 0 */ - .exec_handler_fn = message_handler_req_exec_votequorum_nodeinfo, - .exec_endian_convert_fn = exec_votequorum_nodeinfo_endian_convert - }, - { /* 1 */ - .exec_handler_fn = message_handler_req_exec_votequorum_reconfigure, - .exec_endian_convert_fn = exec_votequorum_reconfigure_endian_convert - }, -}; - -static quorum_set_quorate_fn_t set_quorum; - /* - * lcrso object definition + * Dynamic loader/lcrso object definition */ + static struct quorum_services_api_ver1 votequorum_iface_ver0 = { .init = votequorum_init }; static struct corosync_service_engine quorum_service_handler = { - .name = "corosync votes quorum service v0.91", - .id = VOTEQUORUM_SERVICE, - .private_data_size = sizeof (struct quorum_pd), - .allow_inquorate = CS_LIB_ALLOW_INQUORATE, - .flow_control = COROSYNC_LIB_FLOW_CONTROL_REQUIRED, - .lib_init_fn = quorum_lib_init_fn, - .lib_exit_fn = quorum_lib_exit_fn, - .lib_engine = quorum_lib_service, - .lib_engine_count = sizeof (quorum_lib_service) / sizeof (struct corosync_lib_handler), - .exec_init_fn = votequorum_exec_init_fn, - .exec_engine = votequorum_exec_engine, - .exec_engine_count = sizeof (votequorum_exec_engine) / sizeof (struct corosync_exec_handler), - .confchg_fn = quorum_confchg_fn, - .sync_mode = CS_SYNC_V1 + .name = "corosync votes quorum service v0.91", + .id = VOTEQUORUM_SERVICE, + .private_data_size = sizeof (struct quorum_pd), + .allow_inquorate = CS_LIB_ALLOW_INQUORATE, + .flow_control = COROSYNC_LIB_FLOW_CONTROL_REQUIRED, + .lib_init_fn = quorum_lib_init_fn, + .lib_exit_fn = quorum_lib_exit_fn, + .lib_engine = quorum_lib_service, + .lib_engine_count = sizeof (quorum_lib_service) / sizeof (struct corosync_lib_handler), + .exec_init_fn = votequorum_exec_init_fn, + .exec_engine = votequorum_exec_engine, + .exec_engine_count = sizeof (votequorum_exec_engine) / sizeof (struct corosync_exec_handler), + .confchg_fn = votequorum_confchg_fn, + .sync_mode = CS_SYNC_V1 }; -/* - * Dynamic loader definition - */ -static struct corosync_service_engine *quorum_get_service_handler_ver0 (void); +static struct corosync_service_engine *quorum_get_service_handler_ver0 (void) +{ + return (&quorum_service_handler); +} static struct corosync_service_engine_iface_ver0 quorum_service_handler_iface = { .corosync_get_service_engine_ver0 = quorum_get_service_handler_ver0 @@ -320,12 +384,6 @@ static struct lcr_comp quorum_comp_ver0 = { .ifaces = corosync_quorum_ver0 }; - -static struct corosync_service_engine *quorum_get_service_handler_ver0 (void) -{ - return (&quorum_service_handler); -} - #ifdef COROSYNC_SOLARIS void corosync_lcr_component_register (void); void corosync_lcr_component_register (void) { @@ -337,252 +395,89 @@ __attribute__ ((constructor)) static void corosync_lcr_component_register (void) lcr_component_register (&quorum_comp_ver0); } -static void votequorum_init(struct corosync_api_v1 *api, - quorum_set_quorate_fn_t report) -{ - ENTER(); +/* + * common/utility macros/functions + */ - set_quorum = report; +#define max(a,b) (((a) > (b)) ? (a) : (b)) - icmap_get_uint8("quorum.wait_for_all", &wait_for_all); - icmap_get_uint8("quorum.auto_tie_breaker", &auto_tie_breaker); - icmap_get_uint8("quorum.last_man_standing", &last_man_standing); - icmap_get_uint32("quorum.last_man_standing_window", &last_man_standing_window); +#define list_iterate(v, head) \ + for (v = (head)->next; v != head; v = v->next) - /* - * TODO: we need to know the lowest node-id in the cluster - * current lack of node list with node-id's requires us to see all nodes - * to determine which is the lowest. - */ - if (auto_tie_breaker) { - wait_for_all = 1; - } +static void node_add_ordered(struct cluster_node *newnode) +{ + struct cluster_node *node = NULL; + struct list_head *tmp; + struct list_head *newlist = &newnode->list; - if (wait_for_all) { - wait_for_all_status = 1; + ENTER(); + + list_iterate(tmp, &cluster_members_list) { + node = list_entry(tmp, struct cluster_node, list); + if (newnode->node_id < node->node_id) { + break; + } } - /* Load the library-servicing part of this module */ - api->service_link_and_init(api, "corosync_votequorum_iface", 0); + if (!node) { + list_add(&newnode->list, &cluster_members_list); + } else { + newlist->prev = tmp->prev; + newlist->next = tmp; + tmp->prev->next = newlist; + tmp->prev = newlist; + } LEAVE(); } -struct req_exec_quorum_nodeinfo { - struct qb_ipc_request_header header __attribute__((aligned(8))); - unsigned int first_trans; - unsigned int votes; - unsigned int expected_votes; - unsigned int major_version; /* Not backwards compatible */ - unsigned int minor_version; /* Backwards compatible */ - unsigned int patch_version; /* Backwards/forwards compatible */ - unsigned int config_version; - unsigned int flags; - unsigned int wait_for_all_status; - unsigned int quorate; -} __attribute__((packed)); +static struct cluster_node *allocate_node(int nodeid) +{ + struct cluster_node *cl; -/* - * Parameters for RECONFIG command - */ -#define RECONFIG_PARAM_EXPECTED_VOTES 1 -#define RECONFIG_PARAM_NODE_VOTES 2 + ENTER(); -struct req_exec_quorum_reconfigure { - struct qb_ipc_request_header header __attribute__((aligned(8))); - unsigned int param; - unsigned int nodeid; - unsigned int value; -} __attribute__((packed)); + cl = malloc(sizeof(struct cluster_node)); + if (cl) { + memset(cl, 0, sizeof(struct cluster_node)); + cl->node_id = nodeid; + if (nodeid) { + node_add_ordered(cl); + } + } -static void read_quorum_config(void) + LEAVE(); + + return cl; +} + +static struct cluster_node *find_node_by_nodeid(int nodeid) { - int cluster_members = 0; + struct cluster_node *node; struct list_head *tmp; ENTER(); - log_printf(LOGSYS_LEVEL_DEBUG, "Reading configuration\n"); - - if (icmap_get_uint32("quorum.expected_votes", &us->expected_votes) != CS_OK) { - us->expected_votes = DEFAULT_EXPECTED; + if (nodeid == NODEID_US) { + LEAVE(); + return us; } - if (icmap_get_uint32("quorum.votes", &us->votes) != CS_OK) { - us->votes = 1; - } - - if (icmap_get_uint32("quorum.quorumdev_poll", &quorumdev_poll) != CS_OK) { - quorumdev_poll = DEFAULT_QDEV_POLL; - } - - icmap_get_uint8("quorum.two_node", &two_node); - - /* - * two_node mode is invalid if there are more than 2 nodes in the cluster! - */ - list_iterate(tmp, &cluster_members_list) { - cluster_members++; - } - - if (two_node && cluster_members > 2) { - log_printf(LOGSYS_LEVEL_WARNING, "quorum.two_node was set but there are more than 2 nodes in the cluster. It will be ignored.\n"); - two_node = 0; - } - - LEAVE(); -} - -static int votequorum_exec_init_fn (struct corosync_api_v1 *api) -{ -#ifdef COROSYNC_SOLARIS - logsys_subsys_init(); -#endif - - ENTER(); - - corosync_api = api; - - list_init(&cluster_members_list); - list_init(&trackers_list); - - /* - * Allocate a cluster_node for us - */ - us = allocate_node(corosync_api->totem_nodeid_get()); - if (!us) { - LEAVE(); - return (1); - } - - us->flags |= NODE_FLAGS_US; - us->state = NODESTATE_MEMBER; - us->expected_votes = DEFAULT_EXPECTED; - us->votes = 1; - time(&us->join_time); - - read_quorum_config(); - recalculate_quorum(0, 0); - - /* - * Listen for changes - */ - add_votequorum_config_notification(); - - /* - * Start us off with one node - */ - quorum_exec_send_nodeinfo(); - - LEAVE(); - - return (0); -} - -static int quorum_lib_exit_fn (void *conn) -{ - struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn); - - ENTER(); - - if (quorum_pd->tracking_enabled) { - list_del (&quorum_pd->list); - list_init (&quorum_pd->list); - } - - LEAVE(); - - return (0); -} - - -static int send_quorum_notification(void *conn, uint64_t context) -{ - struct res_lib_votequorum_notification *res_lib_votequorum_notification; - struct list_head *tmp; - struct cluster_node *node; - int cluster_members = 0; - int i = 0; - int size; - char *buf; - - ENTER(); - - list_iterate(tmp, &cluster_members_list) { - node = list_entry(tmp, struct cluster_node, list); - cluster_members++; - } - if (quorum_device) { - cluster_members++; - } - - size = sizeof(struct res_lib_votequorum_notification) + sizeof(struct votequorum_node) * cluster_members; - buf = alloca(size); - if (!buf) { + if (nodeid == NODEID_QDEVICE) { LEAVE(); - return -1; + return quorum_device; } - res_lib_votequorum_notification = (struct res_lib_votequorum_notification *)buf; - res_lib_votequorum_notification->quorate = cluster_is_quorate; - res_lib_votequorum_notification->node_list_entries = cluster_members; - res_lib_votequorum_notification->context = context; list_iterate(tmp, &cluster_members_list) { node = list_entry(tmp, struct cluster_node, list); - res_lib_votequorum_notification->node_list[i].nodeid = node->node_id; - res_lib_votequorum_notification->node_list[i++].state = node->state; - } - if (quorum_device) { - res_lib_votequorum_notification->node_list[i].nodeid = 0; - res_lib_votequorum_notification->node_list[i++].state = quorum_device->state | 0x80; - } - res_lib_votequorum_notification->header.id = MESSAGE_RES_VOTEQUORUM_NOTIFICATION; - res_lib_votequorum_notification->header.size = size; - res_lib_votequorum_notification->header.error = CS_OK; - - /* Send it to all interested parties */ - if (conn) { - int ret = corosync_api->ipc_dispatch_send(conn, buf, size); - LEAVE(); - return ret; - } else { - struct quorum_pd *qpd; - - list_iterate(tmp, &trackers_list) { - qpd = list_entry(tmp, struct quorum_pd, list); - res_lib_votequorum_notification->context = qpd->tracking_context; - corosync_api->ipc_dispatch_send(qpd->conn, buf, size); + if (node->node_id == nodeid) { + LEAVE(); + return node; } } LEAVE(); - - return 0; -} - -static void send_expectedvotes_notification(void) -{ - struct res_lib_votequorum_expectedvotes_notification res_lib_votequorum_expectedvotes_notification; - struct quorum_pd *qpd; - struct list_head *tmp; - - ENTER(); - - log_printf(LOGSYS_LEVEL_DEBUG, "Sending expected votes callback\n"); - - res_lib_votequorum_expectedvotes_notification.header.id = MESSAGE_RES_VOTEQUORUM_EXPECTEDVOTES_NOTIFICATION; - res_lib_votequorum_expectedvotes_notification.header.size = sizeof(res_lib_votequorum_expectedvotes_notification); - res_lib_votequorum_expectedvotes_notification.header.error = CS_OK; - res_lib_votequorum_expectedvotes_notification.expected_votes = us->expected_votes; - - list_iterate(tmp, &trackers_list) { - qpd = list_entry(tmp, struct quorum_pd, list); - res_lib_votequorum_expectedvotes_notification.context = qpd->tracking_context; - corosync_api->ipc_dispatch_send(qpd->conn, &res_lib_votequorum_expectedvotes_notification, - sizeof(struct res_lib_votequorum_expectedvotes_notification)); - } - - LEAVE(); + return NULL; } static void get_lowest_node_id(void) @@ -626,68 +521,9 @@ static int check_low_node_id_partition(void) return found; } -static void set_quorate(int total_votes) -{ - int quorate; - int quorum_change = 0; - - ENTER(); - - /* - * wait for all nodes to show up before granting quorum - */ - - if ((wait_for_all) && (wait_for_all_status)) { - if (total_votes != us->expected_votes) { - log_printf(LOGSYS_LEVEL_NOTICE, - "Waiting for all cluster members. " - "Current votes: %d expected_votes: %d\n", - total_votes, us->expected_votes); - cluster_is_quorate = 0; - return; - } - wait_for_all_status = 0; - get_lowest_node_id(); - } - - if (quorum > total_votes) { - quorate = 0; - } else { - quorate = 1; - } - - if ((auto_tie_breaker) && - (total_votes == (us->expected_votes / 2)) && - (check_low_node_id_partition() == 1)) { - quorate = 1; - } - - if (cluster_is_quorate && !quorate) { - quorum_change = 1; - log_printf(LOGSYS_LEVEL_DEBUG, "quorum lost, blocking activity\n"); - } - if (!cluster_is_quorate && quorate) { - quorum_change = 1; - log_printf(LOGSYS_LEVEL_DEBUG, "quorum regained, resuming activity\n"); - } - - cluster_is_quorate = quorate; - - if (wait_for_all) { - if (quorate) { - wait_for_all_status = 0; - } else { - wait_for_all_status = 1; - } - } - - if (quorum_change) { - set_quorum(quorum_members, quorum_members_entries, - cluster_is_quorate, &quorum_ringid); - } - - LEAVE(); -} +/* + * quorum calculation core bits + */ static int calculate_quorum(int allow_decrease, int max_expected, unsigned int *ret_total_votes) { @@ -760,121 +596,259 @@ static int calculate_quorum(int allow_decrease, int max_expected, unsigned int * return newquorum; } -/* Recalculate cluster quorum, set quorate and notify changes */ -static void recalculate_quorum(int allow_decrease, int by_current_nodes) +static void are_we_quorate(int total_votes) { - unsigned int total_votes = 0; - int cluster_members = 0; - struct list_head *nodelist; - struct cluster_node *node; + int quorate; + int quorum_change = 0; ENTER(); - list_iterate(nodelist, &cluster_members_list) { - node = list_entry(nodelist, struct cluster_node, list); - if (node->state == NODESTATE_MEMBER) { - if (by_current_nodes) { - cluster_members++; - } - total_votes += node->votes; - } - } - /* - * Keep expected_votes at the highest number of votes in the cluster + * wait for all nodes to show up before granting quorum */ - log_printf(LOGSYS_LEVEL_DEBUG, "total_votes=%d, expected_votes=%d\n", total_votes, us->expected_votes); - if (total_votes > us->expected_votes) { - us->expected_votes = total_votes; - send_expectedvotes_notification(); - } - - quorum = calculate_quorum(allow_decrease, cluster_members, &total_votes); - set_quorate(total_votes); - - send_quorum_notification(NULL, 0L); - LEAVE(); -} + if ((wait_for_all) && (wait_for_all_status)) { + if (total_votes != us->expected_votes) { + log_printf(LOGSYS_LEVEL_NOTICE, + "Waiting for all cluster members. " + "Current votes: %d expected_votes: %d\n", + total_votes, us->expected_votes); + cluster_is_quorate = 0; + return; + } + wait_for_all_status = 0; + get_lowest_node_id(); + } -static void node_add_ordered(struct cluster_node *newnode) -{ - struct cluster_node *node = NULL; - struct list_head *tmp; - struct list_head *newlist = &newnode->list; + if (quorum > total_votes) { + quorate = 0; + } else { + quorate = 1; + } - ENTER(); + if ((auto_tie_breaker) && + (total_votes == (us->expected_votes / 2)) && + (check_low_node_id_partition() == 1)) { + quorate = 1; + } - list_iterate(tmp, &cluster_members_list) { - node = list_entry(tmp, struct cluster_node, list); - if (newnode->node_id < node->node_id) { - break; + if (cluster_is_quorate && !quorate) { + quorum_change = 1; + log_printf(LOGSYS_LEVEL_DEBUG, "quorum lost, blocking activity\n"); + } + if (!cluster_is_quorate && quorate) { + quorum_change = 1; + log_printf(LOGSYS_LEVEL_DEBUG, "quorum regained, resuming activity\n"); + } + + cluster_is_quorate = quorate; + + if (wait_for_all) { + if (quorate) { + wait_for_all_status = 0; + } else { + wait_for_all_status = 1; } } - if (!node) { - list_add(&newnode->list, &cluster_members_list); - } else { - newlist->prev = tmp->prev; - newlist->next = tmp; - tmp->prev->next = newlist; - tmp->prev = newlist; + if (quorum_change) { + quorum_callback(quorum_members, quorum_members_entries, + cluster_is_quorate, &quorum_ringid); } LEAVE(); } -static struct cluster_node *allocate_node(int nodeid) +/* Recalculate cluster quorum, set quorate and notify changes */ +static void recalculate_quorum(int allow_decrease, int by_current_nodes) { - struct cluster_node *cl; + unsigned int total_votes = 0; + int cluster_members = 0; + struct list_head *nodelist; + struct cluster_node *node; ENTER(); - cl = malloc(sizeof(struct cluster_node)); - if (cl) { - memset(cl, 0, sizeof(struct cluster_node)); - cl->node_id = nodeid; - if (nodeid) { - node_add_ordered(cl); + list_iterate(nodelist, &cluster_members_list) { + node = list_entry(nodelist, struct cluster_node, list); + if (node->state == NODESTATE_MEMBER) { + if (by_current_nodes) { + cluster_members++; + } + total_votes += node->votes; } } + /* + * Keep expected_votes at the highest number of votes in the cluster + */ + log_printf(LOGSYS_LEVEL_DEBUG, "total_votes=%d, expected_votes=%d\n", total_votes, us->expected_votes); + if (total_votes > us->expected_votes) { + us->expected_votes = total_votes; + votequorum_exec_send_expectedvotes_notification(); + } + + quorum = calculate_quorum(allow_decrease, cluster_members, &total_votes); + are_we_quorate(total_votes); + + votequorum_exec_send_quorum_notification(NULL, 0L); + LEAVE(); +} - return cl; +/* + * configuration bits and pieces + */ + +/* + * votequorum_readconfig_static is executed before + * votequorum_readconfig_dynamic + */ + +static void votequorum_readconfig_static(void) +{ + icmap_get_uint8("quorum.wait_for_all", &wait_for_all); + icmap_get_uint8("quorum.auto_tie_breaker", &auto_tie_breaker); + icmap_get_uint8("quorum.last_man_standing", &last_man_standing); + icmap_get_uint32("quorum.last_man_standing_window", &last_man_standing_window); + + /* + * TODO: we need to know the lowest node-id in the cluster + * current lack of node list with node-id's requires us to see all nodes + * to determine which is the lowest. + */ + if (auto_tie_breaker) { + wait_for_all = 1; + } + + if (wait_for_all) { + wait_for_all_status = 1; + } } -static struct cluster_node *find_node_by_nodeid(int nodeid) +static void votequorum_readconfig_dynamic(void) { - struct cluster_node *node; + int cluster_members = 0; struct list_head *tmp; ENTER(); - if (nodeid == NODEID_US) { - LEAVE(); - return us; + log_printf(LOGSYS_LEVEL_DEBUG, "Reading configuration\n"); + + /* + * TODO: add votequorum_parse_nodelist(); + */ + + if (icmap_get_uint32("quorum.expected_votes", &us->expected_votes) != CS_OK) { + us->expected_votes = DEFAULT_EXPECTED; } - if (nodeid == NODEID_QDEVICE) { - LEAVE(); - return quorum_device; + if (icmap_get_uint32("quorum.votes", &us->votes) != CS_OK) { + us->votes = 1; } + if (icmap_get_uint32("quorum.quorumdev_poll", &quorumdev_poll) != CS_OK) { + quorumdev_poll = DEFAULT_QDEV_POLL; + } + + icmap_get_uint8("quorum.two_node", &two_node); + + /* + * two_node mode is invalid if there are more than 2 nodes in the cluster! + */ list_iterate(tmp, &cluster_members_list) { - node = list_entry(tmp, struct cluster_node, list); - if (node->node_id == nodeid) { - LEAVE(); - return node; - } + cluster_members++; + } + + if (two_node && cluster_members > 2) { + log_printf(LOGSYS_LEVEL_WARNING, "quorum.two_node was set but there are more than 2 nodes in the cluster. It will be ignored.\n"); + two_node = 0; } LEAVE(); - return NULL; } +static void votequorum_refresh_config( + int32_t event, + const char *key_name, + struct icmap_notify_value new_val, + struct icmap_notify_value old_val, + void *user_data) +{ + unsigned int old_votes; + unsigned int old_expected; + + ENTER(); + + old_votes = us->votes; + old_expected = us->expected_votes; + + /* + * Reload the configuration + */ + votequorum_readconfig_dynamic(); -static int quorum_exec_send_nodeinfo() + /* + * Check for fundamental changes that we need to propogate + */ + if (old_votes != us->votes) { + votequorum_exec_send_reconfigure(VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES, us->node_id, us->votes); + } + if (old_expected != us->expected_votes) { + votequorum_exec_send_reconfigure(VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES, us->node_id, us->expected_votes); + } + + LEAVE(); +} + +static void votequorum_exec_add_config_notification(void) +{ + icmap_track_t icmap_track; + + ENTER(); + + /* + * TODO: add track for nodeslist + */ + + icmap_track_add("quorum.", + ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX, + votequorum_refresh_config, + NULL, + &icmap_track); + + LEAVE(); +} + +/* + * votequorum_exec core + */ + +static int votequorum_exec_send_reconfigure(int param, int nodeid, int value) +{ + struct req_exec_quorum_reconfigure req_exec_quorum_reconfigure; + struct iovec iov[1]; + int ret; + + ENTER(); + + req_exec_quorum_reconfigure.param = param; + req_exec_quorum_reconfigure.nodeid = nodeid; + req_exec_quorum_reconfigure.value = value; + + req_exec_quorum_reconfigure.header.id = SERVICE_ID_MAKE(VOTEQUORUM_SERVICE, MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE); + req_exec_quorum_reconfigure.header.size = sizeof(req_exec_quorum_reconfigure); + + iov[0].iov_base = (void *)&req_exec_quorum_reconfigure; + iov[0].iov_len = sizeof(req_exec_quorum_reconfigure); + + ret = corosync_api->totem_mcast (iov, 1, TOTEM_AGREED); + + LEAVE(); + return ret; +} + +static int votequorum_exec_send_nodeinfo(void) { struct req_exec_quorum_nodeinfo req_exec_quorum_nodeinfo; struct iovec iov[1]; @@ -904,32 +878,293 @@ static int quorum_exec_send_nodeinfo() return ret; } +static int votequorum_exec_send_quorum_notification(void *conn, uint64_t context) +{ + struct res_lib_votequorum_notification *res_lib_votequorum_notification; + struct list_head *tmp; + struct cluster_node *node; + int cluster_members = 0; + int i = 0; + int size; + char *buf; + + ENTER(); + + list_iterate(tmp, &cluster_members_list) { + node = list_entry(tmp, struct cluster_node, list); + cluster_members++; + } + if (quorum_device) { + cluster_members++; + } + + size = sizeof(struct res_lib_votequorum_notification) + sizeof(struct votequorum_node) * cluster_members; + buf = alloca(size); + if (!buf) { + LEAVE(); + return -1; + } + + res_lib_votequorum_notification = (struct res_lib_votequorum_notification *)buf; + res_lib_votequorum_notification->quorate = cluster_is_quorate; + res_lib_votequorum_notification->node_list_entries = cluster_members; + res_lib_votequorum_notification->context = context; + list_iterate(tmp, &cluster_members_list) { + node = list_entry(tmp, struct cluster_node, list); + res_lib_votequorum_notification->node_list[i].nodeid = node->node_id; + res_lib_votequorum_notification->node_list[i++].state = node->state; + } + if (quorum_device) { + res_lib_votequorum_notification->node_list[i].nodeid = 0; + res_lib_votequorum_notification->node_list[i++].state = quorum_device->state | 0x80; + } + res_lib_votequorum_notification->header.id = MESSAGE_RES_VOTEQUORUM_NOTIFICATION; + res_lib_votequorum_notification->header.size = size; + res_lib_votequorum_notification->header.error = CS_OK; + + /* Send it to all interested parties */ + if (conn) { + int ret = corosync_api->ipc_dispatch_send(conn, buf, size); + LEAVE(); + return ret; + } else { + struct quorum_pd *qpd; + + list_iterate(tmp, &trackers_list) { + qpd = list_entry(tmp, struct quorum_pd, list); + res_lib_votequorum_notification->context = qpd->tracking_context; + corosync_api->ipc_dispatch_send(qpd->conn, buf, size); + } + } + + LEAVE(); + + return 0; +} + +static void votequorum_exec_send_expectedvotes_notification(void) +{ + struct res_lib_votequorum_expectedvotes_notification res_lib_votequorum_expectedvotes_notification; + struct quorum_pd *qpd; + struct list_head *tmp; + + ENTER(); + + log_printf(LOGSYS_LEVEL_DEBUG, "Sending expected votes callback\n"); + + res_lib_votequorum_expectedvotes_notification.header.id = MESSAGE_RES_VOTEQUORUM_EXPECTEDVOTES_NOTIFICATION; + res_lib_votequorum_expectedvotes_notification.header.size = sizeof(res_lib_votequorum_expectedvotes_notification); + res_lib_votequorum_expectedvotes_notification.header.error = CS_OK; + res_lib_votequorum_expectedvotes_notification.expected_votes = us->expected_votes; + + list_iterate(tmp, &trackers_list) { + qpd = list_entry(tmp, struct quorum_pd, list); + res_lib_votequorum_expectedvotes_notification.context = qpd->tracking_context; + corosync_api->ipc_dispatch_send(qpd->conn, &res_lib_votequorum_expectedvotes_notification, + sizeof(struct res_lib_votequorum_expectedvotes_notification)); + } + + LEAVE(); +} + +static void exec_votequorum_nodeinfo_endian_convert (void *message) +{ + struct req_exec_quorum_nodeinfo *nodeinfo = message; + + ENTER(); + + nodeinfo->votes = swab32(nodeinfo->votes); + nodeinfo->expected_votes = swab32(nodeinfo->expected_votes); + nodeinfo->major_version = swab32(nodeinfo->major_version); + nodeinfo->minor_version = swab32(nodeinfo->minor_version); + nodeinfo->patch_version = swab32(nodeinfo->patch_version); + nodeinfo->config_version = swab32(nodeinfo->config_version); + nodeinfo->flags = swab32(nodeinfo->flags); + nodeinfo->wait_for_all_status = swab32(nodeinfo->wait_for_all_status); + nodeinfo->quorate = swab32(nodeinfo->quorate); -static int quorum_exec_send_reconfigure(int param, int nodeid, int value) + LEAVE(); +} + +static void message_handler_req_exec_votequorum_nodeinfo ( + const void *message, + unsigned int nodeid) { - struct req_exec_quorum_reconfigure req_exec_quorum_reconfigure; - struct iovec iov[1]; - int ret; + const struct req_exec_quorum_nodeinfo *req_exec_quorum_nodeinfo = message; + struct cluster_node *node; + int old_votes; + int old_expected; + nodestate_t old_state; + int new_node = 0; ENTER(); - req_exec_quorum_reconfigure.param = param; - req_exec_quorum_reconfigure.nodeid = nodeid; - req_exec_quorum_reconfigure.value = value; + log_printf(LOGSYS_LEVEL_DEBUG, "got nodeinfo message from cluster node %d\n", nodeid); - req_exec_quorum_reconfigure.header.id = SERVICE_ID_MAKE(VOTEQUORUM_SERVICE, MESSAGE_REQ_EXEC_VOTEQUORUM_RECONFIGURE); - req_exec_quorum_reconfigure.header.size = sizeof(req_exec_quorum_reconfigure); + node = find_node_by_nodeid(nodeid); + if (!node) { + node = allocate_node(nodeid); + new_node = 1; + } + if (!node) { + corosync_api->error_memory_failure(); + LEAVE(); + return; + } - iov[0].iov_base = (void *)&req_exec_quorum_reconfigure; - iov[0].iov_len = sizeof(req_exec_quorum_reconfigure); + old_votes = node->votes; + old_expected = node->expected_votes; + old_state = node->state; - ret = corosync_api->totem_mcast (iov, 1, TOTEM_AGREED); + /* Update node state */ + node->votes = req_exec_quorum_nodeinfo->votes; + node->expected_votes = req_exec_quorum_nodeinfo->expected_votes; + node->state = NODESTATE_MEMBER; + + log_printf(LOGSYS_LEVEL_DEBUG, "nodeinfo message: votes: %d, expected: %d wfa: %d quorate: %d\n", + req_exec_quorum_nodeinfo->votes, + req_exec_quorum_nodeinfo->expected_votes, + req_exec_quorum_nodeinfo->wait_for_all_status, + req_exec_quorum_nodeinfo->quorate); + + if ((last_man_standing) && (req_exec_quorum_nodeinfo->votes > 1)) { + log_printf(LOGSYS_LEVEL_WARNING, "Last Man Standing feature is supported only when all" + "cluster nodes votes are set to 1. Disabling LMS."); + last_man_standing = 0; + if (last_man_standing_timer_set) { + corosync_api->timer_delete(last_man_standing_timer); + last_man_standing_timer_set = 0; + } + } + + node->flags &= ~NODE_FLAGS_BEENDOWN; + + if (new_node || + req_exec_quorum_nodeinfo->first_trans || + old_votes != node->votes || + old_expected != node->expected_votes || + old_state != node->state) { + recalculate_quorum(0, 0); + } + + if (!nodeid) { + free(node); + } + + if ((wait_for_all) && + (!req_exec_quorum_nodeinfo->wait_for_all_status) && + (req_exec_quorum_nodeinfo->quorate)) { + wait_for_all_status = 0; + } + + LEAVE(); +} + +static void exec_votequorum_reconfigure_endian_convert (void *message) +{ + struct req_exec_quorum_reconfigure *reconfigure = message; + + ENTER(); + + reconfigure->nodeid = swab32(reconfigure->nodeid); + reconfigure->value = swab32(reconfigure->value); + + LEAVE(); +} + +static void message_handler_req_exec_votequorum_reconfigure ( + const void *message, + unsigned int nodeid) +{ + const struct req_exec_quorum_reconfigure *req_exec_quorum_reconfigure = message; + struct cluster_node *node; + struct list_head *nodelist; + + ENTER(); + + log_printf(LOGSYS_LEVEL_DEBUG, "got reconfigure message from cluster node %d\n", nodeid); + + node = find_node_by_nodeid(req_exec_quorum_reconfigure->nodeid); + if (!node) { + LEAVE(); + return; + } + + switch(req_exec_quorum_reconfigure->param) + { + case VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES: + list_iterate(nodelist, &cluster_members_list) { + node = list_entry(nodelist, struct cluster_node, list); + if (node->state == NODESTATE_MEMBER && + node->expected_votes > req_exec_quorum_reconfigure->value) { + node->expected_votes = req_exec_quorum_reconfigure->value; + } + } + votequorum_exec_send_expectedvotes_notification(); + recalculate_quorum(1, 0); /* Allow decrease */ + break; + + case VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES: + node->votes = req_exec_quorum_reconfigure->value; + recalculate_quorum(1, 0); /* Allow decrease */ + break; + + } + + LEAVE(); +} + +static int votequorum_exec_init_fn (struct corosync_api_v1 *api) +{ +#ifdef COROSYNC_SOLARIS + logsys_subsys_init(); +#endif + + ENTER(); + + corosync_api = api; + + list_init(&cluster_members_list); + list_init(&trackers_list); + + /* + * Allocate a cluster_node for us + */ + us = allocate_node(corosync_api->totem_nodeid_get()); + if (!us) { + LEAVE(); + return (1); + } + + us->flags |= NODE_FLAGS_US; + us->state = NODESTATE_MEMBER; + us->expected_votes = DEFAULT_EXPECTED; + us->votes = 1; + time(&us->join_time); + + votequorum_readconfig_dynamic(); + recalculate_quorum(0, 0); + + /* + * Listen for changes + */ + votequorum_exec_add_config_notification(); + + /* + * Start us off with one node + */ + votequorum_exec_send_nodeinfo(); LEAVE(); - return ret; + + return (0); } -static void lms_timer_fn(void *arg) +/* + * votequorum service core + */ + +static void votequorum_last_man_standing_timer_fn(void *arg) { ENTER(); @@ -941,7 +1176,7 @@ static void lms_timer_fn(void *arg) LEAVE(); } -static void quorum_confchg_fn ( +static void votequorum_confchg_fn ( enum totem_configuration_type configuration_type, const unsigned int *member_list, size_t member_list_entries, const unsigned int *left_list, size_t left_list_entries, @@ -978,7 +1213,9 @@ static void quorum_confchg_fn ( corosync_api->timer_delete(last_man_standing_timer); last_man_standing_timer_set = 0; } - corosync_api->timer_add_duration((unsigned long long)last_man_standing_window*1000000, NULL, lms_timer_fn, &last_man_standing_timer); + corosync_api->timer_add_duration((unsigned long long)last_man_standing_window*1000000, + NULL, votequorum_last_man_standing_timer_fn, + &last_man_standing_timer); last_man_standing_timer_set = 1; } } @@ -989,7 +1226,7 @@ static void quorum_confchg_fn ( if (quorum_device) { quorum_members[quorum_members_entries++] = 0; } - quorum_exec_send_nodeinfo(); + votequorum_exec_send_nodeinfo(); } if (left_list_entries) { @@ -999,176 +1236,91 @@ static void quorum_confchg_fn ( memcpy(&quorum_ringid, ring_id, sizeof(*ring_id)); if (configuration_type == TOTEM_CONFIGURATION_REGULAR) { - set_quorum(quorum_members, quorum_members_entries, - cluster_is_quorate, &quorum_ringid); + quorum_callback(quorum_members, quorum_members_entries, + cluster_is_quorate, &quorum_ringid); } LEAVE(); } -static void exec_votequorum_nodeinfo_endian_convert (void *message) +static void votequorum_init(struct corosync_api_v1 *api, + quorum_set_quorate_fn_t q_set_quorate_fn) { - struct req_exec_quorum_nodeinfo *nodeinfo = message; - ENTER(); - nodeinfo->votes = swab32(nodeinfo->votes); - nodeinfo->expected_votes = swab32(nodeinfo->expected_votes); - nodeinfo->major_version = swab32(nodeinfo->major_version); - nodeinfo->minor_version = swab32(nodeinfo->minor_version); - nodeinfo->patch_version = swab32(nodeinfo->patch_version); - nodeinfo->config_version = swab32(nodeinfo->config_version); - nodeinfo->flags = swab32(nodeinfo->flags); - nodeinfo->wait_for_all_status = swab32(nodeinfo->wait_for_all_status); - nodeinfo->quorate = swab32(nodeinfo->quorate); + quorum_callback = q_set_quorate_fn; + + votequorum_readconfig_static(); + + /* Load the library-servicing part of this module */ + api->service_link_and_init(api, "corosync_votequorum_iface", 0); LEAVE(); } -static void exec_votequorum_reconfigure_endian_convert (void *message) +/* + * Library Handler init/fini + */ + +static int quorum_lib_init_fn (void *conn) { - struct req_exec_quorum_reconfigure *reconfigure = message; + struct quorum_pd *pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn); ENTER(); - reconfigure->nodeid = swab32(reconfigure->nodeid); - reconfigure->value = swab32(reconfigure->value); + list_init (&pd->list); + pd->conn = conn; LEAVE(); + return (0); } -static void message_handler_req_exec_votequorum_nodeinfo ( - const void *message, - unsigned int nodeid) +static int quorum_lib_exit_fn (void *conn) { - const struct req_exec_quorum_nodeinfo *req_exec_quorum_nodeinfo = message; - struct cluster_node *node; - int old_votes; - int old_expected; - nodestate_t old_state; - int new_node = 0; + struct quorum_pd *quorum_pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn); ENTER(); - log_printf(LOGSYS_LEVEL_DEBUG, "got nodeinfo message from cluster node %d\n", nodeid); - - node = find_node_by_nodeid(nodeid); - if (!node) { - node = allocate_node(nodeid); - new_node = 1; - } - if (!node) { - corosync_api->error_memory_failure(); - LEAVE(); - return; - } - - old_votes = node->votes; - old_expected = node->expected_votes; - old_state = node->state; - - /* Update node state */ - node->votes = req_exec_quorum_nodeinfo->votes; - node->expected_votes = req_exec_quorum_nodeinfo->expected_votes; - node->state = NODESTATE_MEMBER; - - log_printf(LOGSYS_LEVEL_DEBUG, "nodeinfo message: votes: %d, expected: %d wfa: %d quorate: %d\n", - req_exec_quorum_nodeinfo->votes, - req_exec_quorum_nodeinfo->expected_votes, - req_exec_quorum_nodeinfo->wait_for_all_status, - req_exec_quorum_nodeinfo->quorate); - - if ((last_man_standing) && (req_exec_quorum_nodeinfo->votes > 1)) { - log_printf(LOGSYS_LEVEL_WARNING, "Last Man Standing feature is supported only when all" - "cluster nodes votes are set to 1. Disabling LMS."); - last_man_standing = 0; - if (last_man_standing_timer_set) { - corosync_api->timer_delete(last_man_standing_timer); - last_man_standing_timer_set = 0; - } - } - - node->flags &= ~NODE_FLAGS_BEENDOWN; - - if (new_node || - req_exec_quorum_nodeinfo->first_trans || - old_votes != node->votes || - old_expected != node->expected_votes || - old_state != node->state) { - recalculate_quorum(0, 0); - } - - if (!nodeid) { - free(node); - } - - if ((wait_for_all) && - (!req_exec_quorum_nodeinfo->wait_for_all_status) && - (req_exec_quorum_nodeinfo->quorate)) { - wait_for_all_status = 0; + if (quorum_pd->tracking_enabled) { + list_del (&quorum_pd->list); + list_init (&quorum_pd->list); } LEAVE(); + + return (0); } -static void message_handler_req_exec_votequorum_reconfigure ( - const void *message, - unsigned int nodeid) -{ - const struct req_exec_quorum_reconfigure *req_exec_quorum_reconfigure = message; - struct cluster_node *node; - struct list_head *nodelist; +/* + * library internal functions + */ +static void quorum_device_timer_fn(void *arg) +{ ENTER(); - log_printf(LOGSYS_LEVEL_DEBUG, "got reconfigure message from cluster node %d\n", nodeid); - - node = find_node_by_nodeid(req_exec_quorum_reconfigure->nodeid); - if (!node) { + if (!quorum_device || quorum_device->state == NODESTATE_DEAD) { LEAVE(); return; } - switch(req_exec_quorum_reconfigure->param) - { - case RECONFIG_PARAM_EXPECTED_VOTES: - list_iterate(nodelist, &cluster_members_list) { - node = list_entry(nodelist, struct cluster_node, list); - if (node->state == NODESTATE_MEMBER && - node->expected_votes > req_exec_quorum_reconfigure->value) { - node->expected_votes = req_exec_quorum_reconfigure->value; - } - } - send_expectedvotes_notification(); - recalculate_quorum(1, 0); /* Allow decrease */ - break; - - case RECONFIG_PARAM_NODE_VOTES: - node->votes = req_exec_quorum_reconfigure->value; - recalculate_quorum(1, 0); /* Allow decrease */ - break; - + if ((quorum_device->last_hello / QB_TIME_NS_IN_SEC) + quorumdev_poll/1000 < + (qb_util_nano_current_get () / QB_TIME_NS_IN_SEC)) { + quorum_device->state = NODESTATE_DEAD; + log_printf(LOGSYS_LEVEL_INFO, "lost contact with quorum device\n"); + recalculate_quorum(0, 0); + } else { + corosync_api->timer_add_duration((unsigned long long)quorumdev_poll*1000000, quorum_device, + quorum_device_timer_fn, &quorum_device_timer); } LEAVE(); } -static int quorum_lib_init_fn (void *conn) -{ - struct quorum_pd *pd = (struct quorum_pd *)corosync_api->ipc_private_data_get (conn); - - ENTER(); - - list_init (&pd->list); - pd->conn = conn; - - LEAVE(); - return (0); -} - /* - * Message from the library + * Library Handler Functions */ + static void message_handler_req_lib_votequorum_getinfo (void *conn, const void *message) { const struct req_lib_votequorum_getinfo *req_lib_votequorum_getinfo = message; @@ -1238,9 +1390,6 @@ static void message_handler_req_lib_votequorum_getinfo (void *conn, const void * LEAVE(); } -/* - * Message from the library - */ static void message_handler_req_lib_votequorum_setexpected (void *conn, const void *message) { const struct req_lib_votequorum_setexpected *req_lib_votequorum_setexpected = message; @@ -1261,12 +1410,9 @@ static void message_handler_req_lib_votequorum_setexpected (void *conn, const vo goto error_exit; } - quorum_exec_send_reconfigure(RECONFIG_PARAM_EXPECTED_VOTES, us->node_id, - req_lib_votequorum_setexpected->expected_votes); + votequorum_exec_send_reconfigure(VOTEQUORUM_RECONFIG_PARAM_EXPECTED_VOTES, us->node_id, + req_lib_votequorum_setexpected->expected_votes); - /* - * send status - */ error_exit: res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; @@ -1276,9 +1422,6 @@ error_exit: LEAVE(); } -/* - * Message from the library - */ static void message_handler_req_lib_votequorum_setvotes (void *conn, const void *message) { const struct req_lib_votequorum_setvotes *req_lib_votequorum_setvotes = message; @@ -1318,12 +1461,9 @@ static void message_handler_req_lib_votequorum_setvotes (void *conn, const void nodeid = corosync_api->totem_nodeid_get(); } - quorum_exec_send_reconfigure(RECONFIG_PARAM_NODE_VOTES, nodeid, - req_lib_votequorum_setvotes->votes); + votequorum_exec_send_reconfigure(VOTEQUORUM_RECONFIG_PARAM_NODE_VOTES, nodeid, + req_lib_votequorum_setvotes->votes); - /* - * send status - */ error_exit: res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; @@ -1333,28 +1473,6 @@ error_exit: LEAVE(); } -static void quorum_device_timer_fn(void *arg) -{ - ENTER(); - - if (!quorum_device || quorum_device->state == NODESTATE_DEAD) { - LEAVE(); - return; - } - - if ((quorum_device->last_hello / QB_TIME_NS_IN_SEC) + quorumdev_poll/1000 < - (qb_util_nano_current_get () / QB_TIME_NS_IN_SEC)) { - quorum_device->state = NODESTATE_DEAD; - log_printf(LOGSYS_LEVEL_INFO, "lost contact with quorum device\n"); - recalculate_quorum(0, 0); - } else { - corosync_api->timer_add_duration((unsigned long long)quorumdev_poll*1000000, quorum_device, - quorum_device_timer_fn, &quorum_device_timer); - } - - LEAVE(); -} - static void message_handler_req_lib_votequorum_qdisk_register (void *conn, const void *message) { @@ -1374,9 +1492,6 @@ static void message_handler_req_lib_votequorum_qdisk_register (void *conn, list_add(&quorum_device->list, &cluster_members_list); } - /* - * send status - */ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; res_lib_votequorum_status.header.error = error; @@ -1404,9 +1519,6 @@ static void message_handler_req_lib_votequorum_qdisk_unregister (void *conn, error = CS_ERR_NOT_EXIST; } - /* - * send status - */ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; res_lib_votequorum_status.header.error = error; @@ -1477,9 +1589,6 @@ static void message_handler_req_lib_votequorum_qdisk_getinfo (void *conn, error = CS_ERR_NOT_EXIST; } - /* - * send status - */ res_lib_votequorum_qdisk_getinfo.header.size = sizeof(res_lib_votequorum_qdisk_getinfo); res_lib_votequorum_qdisk_getinfo.header.id = MESSAGE_RES_VOTEQUORUM_GETINFO; res_lib_votequorum_qdisk_getinfo.header.error = error; @@ -1503,7 +1612,7 @@ static void message_handler_req_lib_votequorum_trackstart (void *conn, if (req_lib_votequorum_trackstart->track_flags & CS_TRACK_CURRENT || req_lib_votequorum_trackstart->track_flags & CS_TRACK_CHANGES) { log_printf(LOGSYS_LEVEL_DEBUG, "sending initial status to %p\n", conn); - send_quorum_notification(conn, req_lib_votequorum_trackstart->context); + votequorum_exec_send_quorum_notification(conn, req_lib_votequorum_trackstart->context); } /* @@ -1519,9 +1628,6 @@ static void message_handler_req_lib_votequorum_trackstart (void *conn, list_add (&quorum_pd->list, &trackers_list); } - /* - * Send status - */ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; res_lib_votequorum_status.header.error = CS_OK; @@ -1548,9 +1654,6 @@ static void message_handler_req_lib_votequorum_trackstop (void *conn, error = CS_ERR_NOT_EXIST; } - /* - * send status - */ res_lib_votequorum_status.header.size = sizeof(res_lib_votequorum_status); res_lib_votequorum_status.header.id = MESSAGE_RES_VOTEQUORUM_STATUS; res_lib_votequorum_status.header.error = error; @@ -1558,60 +1661,3 @@ static void message_handler_req_lib_votequorum_trackstop (void *conn, LEAVE(); } - -static void reread_config(void) -{ - unsigned int old_votes; - unsigned int old_expected; - - ENTER(); - - old_votes = us->votes; - old_expected = us->expected_votes; - - /* - * Reload the configuration - */ - read_quorum_config(); - - /* - * Check for fundamental changes that we need to propogate - */ - if (old_votes != us->votes) { - quorum_exec_send_reconfigure(RECONFIG_PARAM_NODE_VOTES, us->node_id, us->votes); - } - if (old_expected != us->expected_votes) { - quorum_exec_send_reconfigure(RECONFIG_PARAM_EXPECTED_VOTES, us->node_id, us->expected_votes); - } - - LEAVE(); -} - -static void key_change_quorum( - int32_t event, - const char *key_name, - struct icmap_notify_value new_val, - struct icmap_notify_value old_val, - void *user_data) -{ - ENTER(); - - reread_config(); - - LEAVE(); -} - -static void add_votequorum_config_notification(void) -{ - icmap_track_t icmap_track; - - ENTER(); - - icmap_track_add("quorum.", - ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX, - key_change_quorum, - NULL, - &icmap_track); - - LEAVE(); -} -- 1.7.7.5 _______________________________________________ discuss mailing list discuss@xxxxxxxxxxxx http://lists.corosync.org/mailman/listinfo/discuss