⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 election.c

📁 在LINUX下实现HA的源代码
💻 C
字号:
/*  * 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 <crm/crm.h>#include <crmd_fsa.h>#include <libxml/tree.h>#include <crm/msg_xml.h>#include <crm/common/xmlutils.h>#include <crm/common/ipcutils.h>#include <crm/common/msgutils.h>#include <crm/cib.h>#include <string.h>#include <crmd_messages.h>#include <crm/dmalloc_wrapper.h>GHashTable *joined_nodes = NULL;/*	A_ELECTION_VOTE	*/enum crmd_fsa_inputdo_election_vote(long long action,		 enum crmd_fsa_cause cause,		 enum crmd_fsa_state cur_state,		 enum crmd_fsa_input current_input,		 void *data){	enum crmd_fsa_input election_result = I_NULL;	FNIN();	/* dont vote if we're in one of these states or wanting to shut down */	switch(cur_state) {		case S_RECOVERY:		case S_RECOVERY_DC:		case S_STOPPING:		case S_RELEASE_DC:		case S_TERMINATE:			FNRET(I_NULL);			/*  log warning */			break;		default:			if(is_set(fsa_input_register, R_SHUTDOWN)) {				FNRET(I_NULL);				/*  log warning */			}			break;	}		send_request(NULL, NULL, CRM_OPERATION_VOTE, NULL, CRM_SYSTEM_CRMD);		FNRET(election_result);}gbooleantimer_popped(gpointer data){	fsa_timer_t *timer = (fsa_timer_t *)data;	cl_log(LOG_INFO, "#!!#!!# Timer %s just popped!",	       fsa_input2string(timer->fsa_input));		stopTimer(timer); /*  dont make it go off again */	s_crmd_fsa(C_TIMER_POPPED, timer->fsa_input, NULL);		return TRUE;}gbooleando_dc_heartbeat(gpointer data){	fsa_timer_t *timer = (fsa_timer_t *)data;/* 	cl_log(LOG_DEBUG, "#!!#!!# Heartbeat timer just popped!"); */		gboolean was_sent = send_request(NULL, NULL, CRM_OPERATION_HBEAT, 					 NULL, CRM_SYSTEM_CRMD);	if(was_sent == FALSE) {		/*  this is bad */		stopTimer(timer); /*  dont make it go off again */		s_crmd_fsa(C_HEARTBEAT_FAILED, I_SHUTDOWN, NULL);	}		return TRUE;}/*	A_ELECTION_COUNT	*/enum crmd_fsa_inputdo_election_count_vote(long long action,		       enum crmd_fsa_cause cause,		       enum crmd_fsa_state cur_state,		       enum crmd_fsa_input current_input,		       void *data){	gboolean we_loose = FALSE;	xmlNodePtr vote = (xmlNodePtr)data;	unsigned int my_born = -1, your_born = -1;	int lpc = 0, my_index = -1, your_index = -1;	enum crmd_fsa_input election_result = I_NULL;	const char *vote_from = xmlGetProp(vote, XML_ATTR_HOSTFROM);	const char *lowest_uname = NULL;	int lowest_bornon = 0;		FNIN();	if(vote_from == NULL || strcmp(vote_from, fsa_our_uname) == 0) {		/*  dont count our own vote */		FNRET(election_result);	}	if(fsa_membership_copy->members_size < 1) {		/*  if even we are not in the cluster then we should not vote */		FNRET(I_FAIL);			}		lowest_uname = fsa_membership_copy->members[0].node_uname;	lowest_bornon = fsa_membership_copy->members[0].node_born_on;		for(; lpc < fsa_membership_copy->members_size; lpc++) {				const char *node_uname =			fsa_membership_copy->members[lpc].node_uname;		int this_born_on =			fsa_membership_copy->members[lpc].node_born_on;				if(node_uname == NULL) {			continue;		}				if(strcmp(vote_from, node_uname) == 0) {			your_born = this_born_on;			your_index = lpc;		} else if (strcmp(fsa_our_uname, node_uname) == 0) {			my_born = this_born_on;			my_index = lpc;		}				if(lowest_bornon > this_born_on) {			lowest_uname = node_uname;			lowest_bornon = this_born_on;					} else if(lowest_bornon == this_born_on			  && strcmp(lowest_uname, node_uname) > 0) {			lowest_uname = node_uname;			lowest_bornon = this_born_on;		}	}#if 0	cl_log(LOG_DEBUG, "%s (bornon=%d), our bornon (%d)",		   vote_from, your_born, my_born);	cl_log(LOG_DEBUG, "%s %s %s",	       fsa_our_uname,	       strcmp(fsa_our_uname, vote_from) < 0?"<":">=",	       vote_from);#endif	cl_log(LOG_DEBUG, "Election winner should be %s (born_on=%d)",	       lowest_uname, lowest_bornon);			if(lowest_uname != NULL && strcmp(lowest_uname, fsa_our_uname) == 0){		cl_log(LOG_DEBUG, "Election win: lowest born_on and uname");		election_result = I_ELECTION_DC;	} else if(your_born < my_born) {		cl_log(LOG_DEBUG, "Election fail: born_on");		we_loose = TRUE;	} else if(your_born == my_born		  && strcmp(fsa_our_uname, vote_from) > 0) {		cl_log(LOG_DEBUG, "Election fail: uname");		we_loose = TRUE;	} else {		CRM_DEBUG("We might win... we should vote (possibly again)");		election_result = I_DC_TIMEOUT;	}	if(we_loose) {		if(fsa_input_register & R_THE_DC) {			cl_log(LOG_DEBUG, "Give up the DC");			election_result = I_RELEASE_DC;		} else {			cl_log(LOG_DEBUG, "We werent the DC anyway");			election_result = I_NOT_DC;		}	}	if(we_loose || election_result == I_ELECTION_DC) {		/*  cancel timer, its been decided */		stopTimer(election_timeout);	}		FNRET(election_result);}/*	A_ELECT_TIMER_START, A_ELECTION_TIMEOUT 	*//*  we won */enum crmd_fsa_inputdo_election_timer_ctrl(long long action,		    enum crmd_fsa_cause cause,		    enum crmd_fsa_state cur_state,		    enum crmd_fsa_input current_input,		    void *data){	FNIN();	if(action & A_ELECT_TIMER_START) {		CRM_DEBUG("Starting the election timer...");		startTimer(election_timeout);			} else if(action & A_ELECT_TIMER_STOP || action & A_ELECTION_TIMEOUT) {		CRM_DEBUG("Stopping the election timer...");		stopTimer(election_timeout);			} else {		cl_log(LOG_ERR, "unexpected action %s",		       fsa_action2string(action));	}	if(action & A_ELECTION_TIMEOUT) {		CRM_DEBUG("The election timer went off, we win!");			FNRET(I_ELECTION_DC);			}		FNRET(I_NULL);}/*	A_DC_TIMER_STOP, A_DC_TIMER_START	*/enum crmd_fsa_inputdo_dc_timer_control(long long action,		   enum crmd_fsa_cause cause,		   enum crmd_fsa_state cur_state,		   enum crmd_fsa_input current_input,		   void *data){	gboolean timer_op_ok = TRUE;	FNIN();	if(action & A_DC_TIMER_STOP) {		timer_op_ok = stopTimer(election_trigger);	}	/* dont start a timer that wasnt already running */	if(action & A_DC_TIMER_START && timer_op_ok) {		startTimer(election_trigger);	}		FNRET(I_NULL);}/*	 A_DC_TAKEOVER	*/enum crmd_fsa_inputdo_dc_takeover(long long action,	       enum crmd_fsa_cause cause,	       enum crmd_fsa_state cur_state,	       enum crmd_fsa_input current_input,	       void *data){	FNIN();	CRM_DEBUG("################## Taking over the DC ##################");	set_bit_inplace(&fsa_input_register, R_THE_DC);	CRM_DEBUG2("Am I the DC? %s", AM_I_DC?"yes":"no");		set_bit_inplace(&fsa_input_register, R_JOIN_OK);	set_bit_inplace(&fsa_input_register, R_INVOKE_PE);		clear_bit_inplace(&fsa_input_register, R_CIB_DONE);	clear_bit_inplace(&fsa_input_register, R_HAVE_CIB);	startTimer(dc_heartbeat);		FNRET(I_NULL);}/*	 A_DC_RELEASE	*/enum crmd_fsa_inputdo_dc_release(long long action,	      enum crmd_fsa_cause cause,	      enum crmd_fsa_state cur_state,	      enum crmd_fsa_input current_input,	      void *data){	enum crmd_fsa_input result = I_NULL;	FNIN();	CRM_DEBUG("################## Releasing the DC ##################");	stopTimer(dc_heartbeat);	if(action & A_DC_RELEASE) {		clear_bit_inplace(&fsa_input_register, R_THE_DC);				/* get a new CIB from the new DC */		clear_bit_inplace(&fsa_input_register, R_HAVE_CIB);	} else if (action & A_DC_RELEASED) {		if(cur_state == S_STOPPING) {			result = I_SHUTDOWN; /*  necessary? */			result = I_RELEASE_SUCCESS;		}#if 0		else if( are there errors ) {			/*  we cant stay up if not healthy */			/*  or perhaps I_ERROR and go to S_RECOVER? */			result = I_SHUTDOWN;		}#endif		else			result = I_RELEASE_SUCCESS;	} else {		cl_log(LOG_ERR, "Warning, do_dc_release invoked for action %s",		       fsa_action2string(action));	}	CRM_DEBUG2("Am I still the DC? %s", AM_I_DC?"yes":"no");	FNRET(result);}/*	 A_JOIN_WELCOME, A_JOIN_WELCOME_ALL	*/enum crmd_fsa_inputdo_send_welcome(long long action,		enum crmd_fsa_cause cause,		enum crmd_fsa_state cur_state,		enum crmd_fsa_input current_input,		void *data){	int lpc = 0, size = 0, num_sent = 0;	oc_node_t *members;	gboolean was_sent = TRUE;	FNIN();	if(action & A_JOIN_WELCOME && data == NULL) {		cl_log(LOG_ERR,		       "Attempt to send welcome message "		       "without a message to reply to!");		FNRET(I_NULL);			} else if(action & A_JOIN_WELCOME) {		xmlNodePtr welcome = (xmlNodePtr)data;		const char *join_to = xmlGetProp(welcome, XML_ATTR_HOSTFROM);		if(join_to != NULL) {			send_request(NULL, NULL, CRM_OPERATION_WELCOME,				     join_to, CRM_SYSTEM_CRMD);		}				FNRET(I_NULL);	}/*  welcome everyone... */	/* Give everyone a chance to join before invoking the PolicyEngine */	stopTimer(integration_timer);	startTimer(integration_timer);		members = fsa_membership_copy->members;	size = fsa_membership_copy->members_size;		if(joined_nodes != NULL) {		g_hash_table_destroy(joined_nodes);		joined_nodes = g_hash_table_new(&g_str_hash, &g_str_equal);			}		for(; members != NULL && lpc < size; lpc++) {		const char *new_node = members[lpc].node_uname;		if(strcmp(fsa_our_uname, new_node) == 0) {			/*  dont send one to ourselves */			continue;		}		CRM_DEBUG3("Sending welcome message to %s (%d)",			   new_node, was_sent);		num_sent++;		was_sent = was_sent			&& send_request(NULL, NULL, CRM_OPERATION_WELCOME,					new_node, CRM_SYSTEM_CRMD);		CRM_DEBUG3("Sent welcome message to %s (%d)",			   new_node, was_sent);	}	if(was_sent == FALSE)		FNRET(I_FAIL);/* No point hanging around in S_INTEGRATION if we're the only ones here! */	if(num_sent == 0) {		/*  that was the last outstanding join ack) */		cl_log(LOG_INFO,"That was the last outstanding join ack");		FNRET(I_SUCCESS);	} else {		cl_log(LOG_DEBUG,		       "Still waiting on %d outstanding join acks",		       num_sent);		/* dont waste time by invoking the pe yet; */	}		FNRET(I_NULL);}/*	 A_JOIN_ACK	*/enum crmd_fsa_inputdo_ack_welcome(long long action,	    enum crmd_fsa_cause cause,	    enum crmd_fsa_state cur_state,	    enum crmd_fsa_input current_input,	    void *data){	xmlNodePtr cib_copy = NULL;	xmlNodePtr tmp1 = NULL;	xmlNodePtr tmp2 = NULL;	xmlNodePtr welcome = (xmlNodePtr)data;	FNIN();	#if 0	if(we are sick) {		log error ;		FNRET(I_NULL);	} #endif	cib_copy = get_cib_copy();	tmp1 = get_object_root(XML_CIB_TAG_STATUS, cib_copy);	tmp2 = create_cib_fragment(tmp1, NULL);		send_ha_reply(fsa_cluster_conn, welcome, tmp2);	free_xml(tmp2);	free_xml(cib_copy);		FNRET(I_NULL);}/*	 A_ANNOUNCE	*/enum crmd_fsa_inputdo_announce(long long action,	    enum crmd_fsa_cause cause,	    enum crmd_fsa_state cur_state,	    enum crmd_fsa_input current_input,	    void *data){	FNIN();		/* Once we hear from the DC, we can stop the timer	 *	 * This timer was started either on startup or when a node	 * left the CCM list	 */	/* dont announce if we're in one of these states */	switch(cur_state) {		case S_RECOVERY:		case S_RECOVERY_DC:		case S_RELEASE_DC:		case S_TERMINATE:			FNRET(I_NULL);			/*  log warning */			break;		default:			break;	}	if(AM_I_OPERATIONAL) {		send_request(NULL, NULL, CRM_OPERATION_ANNOUNCE,			     NULL, CRM_SYSTEM_DC);	} else {		/* Delay announce until we have finished local startup */		FNRET(I_NULL);	}		FNRET(I_NULL);}/*	 A_JOIN_PROCESS_ACK	*/enum crmd_fsa_inputdo_process_welcome_ack(long long action,		    enum crmd_fsa_cause cause,		    enum crmd_fsa_state cur_state,		    enum crmd_fsa_input current_input,		    void *data){	int lpc = 0, size = 0;	oc_node_t *members;	gboolean is_a_member = FALSE;	xmlNodePtr join_ack = (xmlNodePtr)data;	const char *join_from = xmlGetProp(join_ack, XML_ATTR_HOSTFROM);	xmlNodePtr cib_fragment = NULL;	xmlNodePtr tmp1 = NULL;		FNIN();	members = fsa_membership_copy->members;	size = fsa_membership_copy->members_size;		for(; lpc < size; lpc++) {		const char *new_node = members[lpc].node_uname;		if(strcmp(join_from, new_node) == 0) {			is_a_member = TRUE;		}	}		cib_fragment = find_xml_node(join_ack, XML_TAG_FRAGMENT);	if(is_a_member == FALSE) {		cl_log(LOG_ERR, "Node %s is not known to us", join_from);		/* make sure any information from this node is discarded,		 * it is invalid		 */		free_xml(cib_fragment);		FNRET(I_FAIL);	}	cl_log(LOG_DEBUG, "Welcoming node %s after ACK", join_from);		/*  add them to our list of "active" nodes */	g_hash_table_insert(joined_nodes, strdup(join_from),strdup(join_from));	if(cib_fragment == NULL) {		cl_log(LOG_ERR,		       "No status information was part of the"		       " Welcome ACK from %s",		       join_from);		FNRET(I_NULL);	}		/* TODO: check the fragment is only for the status section	const char *section = get_xml_attr(cib_fragment, NULL,					   XML_ATTR_FILTER_TYPE, TRUE);	*/		/* Make changes so that state=active for this node when the update	 *  is processed by A_CIB_INVOKE	 */	tmp1 = find_xml_node(cib_fragment, XML_TAG_CIB);	tmp1 = get_object_root(XML_CIB_TAG_STATUS, tmp1);	tmp1 = find_entity(tmp1, XML_CIB_TAG_STATE, join_from, FALSE);	set_xml_property_copy(tmp1, "state", "active");		if(g_hash_table_size(joined_nodes)	   == fsa_membership_copy->members_size) {		/*  that was the last outstanding join ack) */		cl_log(LOG_INFO,"That was the last outstanding join ack");		FNRET(I_SUCCESS);	} else {		cl_log(LOG_DEBUG,		       "Still waiting on %d outstanding join acks",		       size);		/* dont waste time by invoking the pe yet; */	}	FNRET(I_CIB_OP);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -