11 #include <sys/resource.h> 
   21 #define STORM_INTERVAL   2       
   36     crm_info(
"Election %s complete", e->name);
 
   46 static gboolean election_timer_cb(gpointer user_data)
 
   50     crm_info(
"Election %s %p timed out", e->name, e);
 
   67     static guint count = 0;
 
   78         e->uname = strdup(uname);
 
   88     if(e && uname && e->voted) {
 
   89         g_hash_table_remove(e->voted, uname);
 
   96     crm_trace(
"Resetting election %s", e->name);
 
  101         crm_trace(
"Destroying voted cache with %d members", g_hash_table_size(e->voted));
 
  102         g_hash_table_destroy(e->voted);
 
  142         crm_err(
"No election defined");
 
  147 crm_uptime(
struct timeval *output)
 
  149     static time_t expires = 0;
 
  150     static struct rusage info;
 
  152     time_t tm_now = time(NULL);
 
  154     if (expires < tm_now) {
 
  157         info.ru_utime.tv_sec = 0;
 
  158         info.ru_utime.tv_usec = 0;
 
  159         rc = getrusage(RUSAGE_SELF, &info);
 
  165             crm_perror(LOG_ERR, 
"Could not calculate the current uptime");
 
  170         crm_debug(
"Current CPU usage is: %lds, %ldus", (
long)info.ru_utime.tv_sec,
 
  171                   (
long)info.ru_utime.tv_usec);
 
  175     output->tv_sec = info.ru_utime.tv_sec;
 
  176     output->tv_usec = info.ru_utime.tv_usec;
 
  182 crm_compare_age(
struct timeval your_age)
 
  184     struct timeval our_age;
 
  186     crm_uptime(&our_age); 
 
  188     if (our_age.tv_sec > your_age.tv_sec) {
 
  189         crm_debug(
"Win: %ld vs %ld (seconds)", (
long)our_age.tv_sec, (
long)your_age.tv_sec);
 
  191     } 
else if (our_age.tv_sec < your_age.tv_sec) {
 
  192         crm_debug(
"Lose: %ld vs %ld (seconds)", (
long)our_age.tv_sec, (
long)your_age.tv_sec);
 
  194     } 
else if (our_age.tv_usec > your_age.tv_usec) {
 
  195         crm_debug(
"Win: %ld.%ld vs %ld.%ld (usec)",
 
  196                   (
long)our_age.tv_sec, (
long)our_age.tv_usec, (
long)your_age.tv_sec, (
long)your_age.tv_usec);
 
  198     } 
else if (our_age.tv_usec < your_age.tv_usec) {
 
  199         crm_debug(
"Lose: %ld.%ld vs %ld.%ld (usec)",
 
  200                   (
long)our_age.tv_sec, (
long)our_age.tv_usec, (
long)your_age.tv_sec, (
long)your_age.tv_usec);
 
  211     xmlNode *vote = NULL;
 
  215         crm_trace(
"Not voting in election: not initialized");
 
  221         crm_trace(
"Cannot vote yet: %p", our_node);
 
  239     crm_debug(
"Started election %d", e->count);
 
  241         g_hash_table_destroy(e->voted);
 
  245     election_timeout_start(e);
 
  261         voted_size = g_hash_table_size(e->voted);
 
  267     if (voted_size >= num_members) {
 
  270         if (voted_size > num_members) {
 
  276             while (g_hash_table_iter_next(&gIter, NULL, (gpointer *) & node)) {
 
  282             g_hash_table_iter_init(&gIter, e->voted);
 
  283             while (g_hash_table_iter_next(&gIter, (gpointer *) & key, NULL)) {
 
  289         election_complete(e);
 
  293         crm_debug(
"Still waiting on %d non-votes (%d total)",
 
  294                   num_members - voted_size, num_members);
 
  300 #define loss_dampen 2            
  307     int election_id = -1;
 
  308     int log_level = LOG_INFO;
 
  309     gboolean use_born_on = FALSE;
 
  310     gboolean done = FALSE;
 
  311     gboolean we_lose = FALSE;
 
  312     const char *op = NULL;
 
  313     const char *from = NULL;
 
  314     const char *reason = 
"unknown";
 
  315     const char *election_owner = NULL;
 
  316     crm_node_t *our_node = NULL, *your_node = NULL;
 
  318     static int election_wins = 0;
 
  320     xmlNode *novote = NULL;
 
  321     time_t tm_now = time(NULL);
 
  322     static time_t expires = 0;
 
  323     static time_t last_election_loss = 0;
 
  332         crm_info(
"Not voting in election: not initialized");
 
  336         crm_info(
"Not voting in election: no peer cache");
 
  348     if (e->voted == NULL) {
 
  350         e->voted = crm_str_table_new();
 
  359     if(can_win == FALSE) {
 
  360         reason = 
"Not eligible";
 
  364         reason = 
"We are not part of the cluster";
 
  368     } 
else if (election_id != e->count && 
crm_str_eq(our_node->
uuid, election_owner, TRUE)) {
 
  370         reason = 
"Superseded";
 
  375         reason = 
"Peer is not part of our cluster";
 
  376         log_level = LOG_WARNING;
 
  380         char *op_copy = strdup(op);
 
  381         char *uname_copy = strdup(from);
 
  386         g_hash_table_replace(e->voted, uname_copy, op_copy);
 
  391         struct timeval your_age;
 
  399         your_age.tv_sec = tv_sec;
 
  400         your_age.tv_usec = tv_usec;
 
  402         age = crm_compare_age(your_age);
 
  404             char *op_copy = strdup(op);
 
  405             char *uname_copy = strdup(from);
 
  410             g_hash_table_replace(e->voted, uname_copy, op_copy);
 
  421         } 
else if (age < 0) {
 
  425         } 
else if (age > 0) {
 
  429         } 
else if (use_born_on && your_node->born < our_node->
born) {
 
  433         } 
else if (use_born_on && your_node->born > our_node->
born) {
 
  436         } 
else if (e->uname == NULL) {
 
  437             reason = 
"Unknown host name";
 
  440         } 
else if (strcasecmp(e->uname, from) > 0) {
 
  441             reason = 
"Host name";
 
  445             reason = 
"Host name";
 
  454     if (expires < tm_now) {
 
  458     } 
else if (done == FALSE && we_lose == FALSE) {
 
  465         if (election_wins > (peers * peers)) {
 
  466             crm_warn(
"Election storm detected: %d elections in %d seconds", election_wins,
 
  475         do_crm_log(log_level + 1, 
"Election %d (current: %d, owner: %s): Processed %s from %s (%s)",
 
  476                    election_id, e->count, election_owner, op, from, reason);
 
  479     } 
else if (we_lose == FALSE) {
 
  480         do_crm_log(log_level, 
"Election %d (owner: %s) pass: %s from %s (%s)",
 
  481                    election_id, election_owner, op, from, reason);
 
  483         if (last_election_loss == 0
 
  484             || tm_now - last_election_loss > (time_t) 
loss_dampen) {
 
  486             last_election_loss = 0;
 
  494         crm_info(
"Election %d ignore: We already lost an election less than %ds ago (%s)",
 
  495                  election_id, loss_dampen, ctime(&last_election_loss));
 
  501     do_crm_log(log_level, 
"Election %d (owner: %s) lost: %s from %s (%s)",
 
  502                election_id, election_owner, op, from, reason);
 
  512     last_election_loss = tm_now;
 
bool election_check(election_t *e)
 
#define CRM_CHECK(expr, failure_action)
 
void crm_write_blackbox(int nsig, struct qb_log_callsite *callsite)
 
enum election_result election_count_vote(election_t *e, xmlNode *vote, bool can_win)
 
void mainloop_timer_start(mainloop_timer_t *t)
 
guint mainloop_timer_set_period(mainloop_timer_t *t, guint period_ms)
 
void mainloop_timer_del(mainloop_timer_t *t)
 
void election_remove(election_t *e, const char *uname)
 
gboolean is_heartbeat_cluster(void)
 
gboolean crm_is_peer_active(const crm_node_t *node)
 
void election_fini(election_t *e)
 
struct mainloop_timer_s mainloop_timer_t
 
crm_node_t * crm_get_peer(unsigned int id, const char *uname)
 
guint crm_active_peers(void)
 
void mainloop_timer_stop(mainloop_timer_t *t)
 
#define F_CRM_ELECTION_AGE_S
 
Wrappers for and extensions to glib mainloop. 
 
void election_vote(election_t *e)
 
struct election_s election_t
 
#define crm_warn(fmt, args...)
 
#define crm_debug(fmt, args...)
 
#define crm_trace(fmt, args...)
 
#define do_crm_log(level, fmt, args...)
Log a message. 
 
Wrappers for and extensions to libxml2. 
 
int crm_element_value_int(xmlNode *data, const char *name, int *dest)
 
const char * crm_element_value(xmlNode *data, const char *name)
 
void free_xml(xmlNode *child)
 
gboolean crm_str_eq(const char *a, const char *b, gboolean use_case)
 
enum election_result election_state(election_t *e)
 
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
 
election_t * election_init(const char *name, const char *uname, guint period_ms, GSourceFunc cb)
 
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
 
#define F_CRM_ELECTION_AGE_US
 
#define crm_perror(level, fmt, args...)
Log a system error message. 
 
#define crm_err(fmt, args...)
 
void election_timeout_stop(election_t *e)
 
void election_reset(election_t *e)
 
int compare_version(const char *version1, const char *version2)
 
mainloop_timer_t * mainloop_timer_add(const char *name, guint period_ms, bool repeat, GSourceFunc cb, void *userdata)
 
void election_timeout_set_period(election_t *e, guint period_ms)
 
#define F_CRM_ELECTION_ID
 
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
 
gboolean send_cluster_message(crm_node_t *node, enum crm_ais_msg_types service, xmlNode *data, gboolean ordered)
 
#define create_request(task, xml_data, host_to, sys_to, sys_from, uuid_from)
 
GHashTable * crm_peer_cache
 
#define crm_info(fmt, args...)
 
gboolean is_classic_ais_cluster(void)
 
Functions for conducting elections. 
 
#define F_CRM_ELECTION_OWNER