Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/crm/crmd/election.c b/crm/crmd/election.c
index 6d881d520f..be66a01f99 100644
--- a/crm/crmd/election.c
+++ b/crm/crmd/election.c
@@ -1,451 +1,451 @@
/*
* Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <portability.h>
#include <heartbeat.h>
#include <crm/cib.h>
#include <crm/msg_xml.h>
#include <crm/common/xml.h>
#include <crm/crm.h>
#include <crmd_fsa.h>
#include <crmd_messages.h>
#include <crmd_callbacks.h>
#include <clplumbing/Gmain_timeout.h>
#include <clplumbing/cl_uuid.h>
#include <crm/dmalloc_wrapper.h>
GHashTable *voted = NULL;
uint highest_born_on = -1;
static int current_election_id = 1;
/* A_ELECTION_VOTE */
enum crmd_fsa_input
do_election_vote(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
gboolean not_voting = FALSE;
HA_Message *vote = NULL;
/* don't vote if we're in one of these states or wanting to shut down */
switch(cur_state) {
case S_RECOVERY:
case S_STOPPING:
case S_TERMINATE:
crm_warn("Not voting in election, we're in state %s",
fsa_state2string(cur_state));
not_voting = TRUE;
break;
default:
break;
}
if(not_voting == FALSE) {
if(is_set(fsa_input_register, R_STARTING)) {
not_voting = TRUE;
}
}
if(not_voting) {
if(AM_I_DC) {
register_fsa_input(C_FSA_INTERNAL, I_RELEASE_DC, NULL);
} else {
register_fsa_input(C_FSA_INTERNAL, I_PENDING, NULL);
}
return I_NULL;
}
vote = create_request(
CRM_OP_VOTE, NULL, NULL,
CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL);
current_election_id++;
ha_msg_add(vote, F_CRM_ELECTION_OWNER, fsa_our_uuid);
ha_msg_add_int(vote, F_CRM_ELECTION_ID, current_election_id);
send_request(vote, NULL);
if(cur_state == S_ELECTION || cur_state == S_RELEASE_DC) {
crm_timer_start(election_timeout);
} else if(cur_state != S_INTEGRATION) {
crm_err("Broken? Voting in state %s",
fsa_state2string(cur_state));
}
return I_NULL;
}
char *dc_hb_msg = NULL;
int beat_num = 0;
gboolean
do_dc_heartbeat(gpointer data)
{
#if 0
fsa_timer_t *timer = (fsa_timer_t *)data;
crm_debug_3("Sending DC Heartbeat %d", beat_num);
HA_Message *msg = ha_msg_new(5);
ha_msg_add(msg, F_TYPE, T_CRM);
ha_msg_add(msg, F_SUBTYPE, XML_ATTR_REQUEST);
ha_msg_add(msg, F_CRM_SYS_TO, CRM_SYSTEM_CRMD);
ha_msg_add(msg, F_CRM_SYS_FROM, CRM_SYSTEM_DC);
ha_msg_add(msg, F_CRM_TASK, CRM_OP_HBEAT);
ha_msg_add_int(msg, "dc_beat_seq", beat_num);
beat_num++;
if(send_msg_via_ha(fsa_cluster_conn, msg) == FALSE) {
/* this is bad */
crm_timer_stop(timer); /* make it not go off again */
register_fsa_input(C_HEARTBEAT_FAILED, I_SHUTDOWN, NULL);
return FALSE;
}
#endif
return TRUE;
}
struct election_data_s
{
const char *winning_uname;
unsigned int winning_bornon;
};
static void
log_node(gpointer key, gpointer value, gpointer user_data)
{
crm_err("%s: %s", (char*)user_data, (char*)key);
}
enum crmd_fsa_input
do_election_check(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
int voted_size = g_hash_table_size(voted);
int num_members = g_hash_table_size(fsa_membership_copy->members);
/* in the case of #voted > #members, it is better to
* wait for the timeout and give the cluster time to
* stabilize
*/
if(fsa_state != S_ELECTION) {
crm_debug("Ignore election check: we not in an election");
} else if(voted_size >= num_members) {
/* we won and everyone has voted */
crm_timer_stop(election_timeout);
register_fsa_input(C_FSA_INTERNAL, I_ELECTION_DC, NULL);
if(voted_size > num_members) {
char *data = NULL;
data = crm_strdup("member");
g_hash_table_foreach(
fsa_membership_copy->members, log_node, data);
crm_free(data);
data = crm_strdup("voted");
g_hash_table_foreach(voted, log_node, data);
crm_free(data);
}
crm_debug("Destroying voted hash");
g_hash_table_destroy(voted);
voted = NULL;
} else {
crm_info("Still waiting on %d non-votes (%d total)",
num_members - voted_size, num_members);
}
return I_NULL;
}
/* A_ELECTION_COUNT */
enum crmd_fsa_input
do_election_count_vote(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
int election_id = -1;
gboolean we_loose = FALSE;
enum crmd_fsa_input election_result = I_NULL;
oc_node_t *our_node = NULL, *your_node = NULL;
ha_msg_input_t *vote = fsa_typed_data(fsa_dt_ha_msg);
const char *op = cl_get_string(vote->msg, F_CRM_TASK);
const char *vote_from = cl_get_string(vote->msg, F_CRM_HOST_FROM);
const char *your_version = cl_get_string(vote->msg, F_CRM_VERSION);
const char *election_owner= cl_get_string(vote->msg, F_CRM_ELECTION_OWNER);
/* if the membership copy is NULL we REALLY shouldnt be voting
* the question is how we managed to get here.
*/
CRM_CHECK(fsa_membership_copy != NULL, return I_NULL);
CRM_CHECK(fsa_membership_copy->members != NULL, return I_NULL);
CRM_CHECK(vote_from != NULL, vote_from = fsa_our_uname);
our_node = (oc_node_t*)g_hash_table_lookup(
fsa_membership_copy->members, fsa_our_uname);
your_node = (oc_node_t*)g_hash_table_lookup(
fsa_membership_copy->members, vote_from);
if(your_node == NULL) {
crm_debug("Election ignore: The other side doesn't exist in CCM.");
return I_NULL;
}
if(voted == NULL) {
crm_debug("Created voted hash");
voted = g_hash_table_new_full(
g_str_hash, g_str_equal,
g_hash_destroy_str, g_hash_destroy_str);
}
ha_msg_value_int(vote->msg, F_CRM_ELECTION_ID, &election_id);
crm_debug("Election %d, owner: %s", election_id, election_owner);
/* update the list of nodes that have voted */
- if(crm_str_eq(fsa_our_uuid, election_owner)) {
+ if(crm_str_eq(fsa_our_uuid, election_owner, TRUE)) {
if(election_id == current_election_id) {
char *uname_copy = NULL;
char *op_copy = crm_strdup(op);
uname_copy = crm_strdup(your_node->node_uname);
g_hash_table_replace(voted, uname_copy, op_copy);
crm_info("Updated voted hash for %s to %s",
your_node->node_uname, op);
} else {
crm_debug("Ignore old '%s' from %s: %d vs. %d",
op, your_node->node_uname,
election_id, current_election_id);
return I_NULL;
}
} else {
CRM_CHECK(crm_str_neq(op, CRM_OP_NOVOTE), return I_NULL);
}
- if(vote_from == NULL || crm_str_eq(vote_from, fsa_our_uname)) {
+ if(vote_from == NULL || crm_str_eq(vote_from, fsa_our_uname, TRUE)) {
/* don't count our own vote */
crm_info("Election ignore: our %s (%s)", op,crm_str(vote_from));
return I_NULL;
- } else if(crm_str_eq(op, CRM_OP_NOVOTE)) {
+ } else if(crm_str_eq(op, CRM_OP_NOVOTE, TRUE)) {
crm_info("Election ignore: no-vote from %s", vote_from);
return I_NULL;
}
crm_info("Election check: %s from %s", op, vote_from);
if(our_node == NULL
|| fsa_membership_copy->last_event == OC_EV_MS_EVICTED) {
crm_info("Election fail: we don't exist in CCM");
we_loose = TRUE;
} else if(compare_version(your_version, CRM_FEATURE_SET) < 0) {
crm_info("Election fail: version");
we_loose = TRUE;
} else if(compare_version(your_version, CRM_FEATURE_SET) > 0) {
crm_info("Election pass: version");
} else if(your_node->node_born_on < our_node->node_born_on) {
crm_debug("Election fail: born_on");
we_loose = TRUE;
} else if(your_node->node_born_on > our_node->node_born_on) {
crm_debug("Election pass: born_on");
} else if(strcasecmp(fsa_our_uname, vote_from) > 0) {
crm_debug("Election fail: uname");
we_loose = TRUE;
} else {
CRM_CHECK(strcasecmp(fsa_our_uname, vote_from) != 0, ;);
crm_debug("Them: %s (born=%d) Us: %s (born=%d)",
vote_from, your_node->node_born_on,
fsa_our_uname, our_node->node_born_on);
/* cant happen...
* } else if(strcasecmp(fsa_our_uname, vote_from) == 0) {
*
* default...
* } else { // strcasecmp(fsa_our_uname, vote_from) < 0
* we win
*/
}
if(we_loose) {
cl_uuid_t vote_uuid_s;
gboolean vote_sent = FALSE;
char vote_uuid[UU_UNPARSE_SIZEOF];
HA_Message *novote = create_request(
CRM_OP_NOVOTE, NULL, vote_from,
CRM_SYSTEM_CRMD, CRM_SYSTEM_CRMD, NULL);
update_dc(NULL, FALSE);
if(cl_get_uuid(vote->msg, F_ORIGUUID, &vote_uuid_s) == HA_OK) {
cl_uuid_unparse(&vote_uuid_s, vote_uuid);
} else {
cl_log_message(LOG_ERR, vote->msg);
}
crm_timer_stop(election_timeout);
crm_debug("Election lost to %s (%s/%d)",
vote_from, vote_uuid, election_id);
if(fsa_input_register & R_THE_DC) {
crm_debug_3("Give up the DC to %s", vote_from);
election_result = I_RELEASE_DC;
} else {
crm_debug_3("We werent the DC anyway");
election_result = I_PENDING;
}
ha_msg_add(novote, F_CRM_ELECTION_OWNER, vote_uuid);
ha_msg_add_int(novote, F_CRM_ELECTION_ID, election_id);
vote_sent = send_request(novote, NULL);
CRM_DEV_ASSERT(vote_sent);
fsa_cib_conn->cmds->set_slave(fsa_cib_conn, cib_scope_local);
} else {
if(cur_state == S_PENDING) {
crm_debug("Election ignore: We already lost the election");
return I_NULL;
} else {
crm_info("Election won over %s", vote_from);
election_result = I_ELECTION;
}
crm_debug("Destroying voted hash");
g_hash_table_destroy(voted);
voted = NULL;
}
register_fsa_input(C_FSA_INTERNAL, election_result, NULL);
return I_NULL;
}
/* A_ELECT_TIMER_START, A_ELECTION_TIMEOUT */
/* we won */
enum crmd_fsa_input
do_election_timer_ctrl(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
return I_NULL;
}
static void
feature_update_callback(const HA_Message *msg, int call_id, int rc,
crm_data_t *output, void *user_data)
{
if(rc != cib_ok) {
fsa_data_t *msg_data = NULL;
register_fsa_error(C_FSA_INTERNAL, I_ERROR, NULL);
}
}
/* A_DC_TAKEOVER */
enum crmd_fsa_input
do_dc_takeover(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
int rc = cib_ok;
crm_data_t *cib = NULL;
crm_info("Taking over DC status for this partition");
set_bit_inplace(fsa_input_register, R_THE_DC);
if(voted != NULL) {
crm_debug_2("Destroying voted hash");
g_hash_table_destroy(voted);
voted = NULL;
}
set_bit_inplace(fsa_input_register, R_JOIN_OK);
set_bit_inplace(fsa_input_register, R_INVOKE_PE);
fsa_cib_conn->cmds->set_slave_all(fsa_cib_conn, cib_none);
fsa_cib_conn->cmds->set_master(fsa_cib_conn, cib_none);
cib = createEmptyCib();
crm_xml_add(cib, XML_ATTR_CRM_VERSION, CRM_FEATURE_SET);
crm_xml_add(cib, XML_ATTR_CIB_REVISION, CIB_FEATURE_SET);
fsa_cib_update(XML_TAG_CIB, cib, cib_quorum_override, rc);
add_cib_op_callback(rc, FALSE, NULL, feature_update_callback);
free_xml(cib);
return I_NULL;
}
/* A_DC_RELEASE */
enum crmd_fsa_input
do_dc_release(long long action,
enum crmd_fsa_cause cause,
enum crmd_fsa_state cur_state,
enum crmd_fsa_input current_input,
fsa_data_t *msg_data)
{
enum crmd_fsa_input result = I_NULL;
if(action & A_DC_RELEASE) {
crm_debug("Releasing the role of DC");
clear_bit_inplace(fsa_input_register, R_THE_DC);
} else if (action & A_DC_RELEASED) {
crm_info("DC role released");
#if 0
if( are there errors ) {
/* we cant stay up if not healthy */
/* or perhaps I_ERROR and go to S_RECOVER? */
result = I_SHUTDOWN;
}
#endif
register_fsa_input(C_FSA_INTERNAL, I_RELEASE_SUCCESS, NULL);
} else {
crm_err("Unknown action %s", fsa_action2string(action));
}
crm_debug_2("Am I still the DC? %s", AM_I_DC?XML_BOOLEAN_YES:XML_BOOLEAN_NO);
return result;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Oct 16, 3:04 PM (15 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2536420
Default Alt Text
(12 KB)

Event Timeline