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

📄 ccm.c

📁 在LINUX下实现HA的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		||(ha_msg_add(m, CCM_MAJORTRANS, majortrans) == HA_FAIL)		||(ha_msg_add(m, CCM_MINORTRANS, minortrans) == HA_FAIL)){			cl_log(LOG_ERR, "timeout_msg_create: Cannot "				"create timeout message");		return HA_FAIL;	}	timeout_msg = m;	return 0;}static struct ha_msg  *timeout_msg_mod(ccm_info_t *info){	char majortrans[15]; /* 10 is the maximum number of digits in 				UINT_MAX , adding a buffer of 5 */	char minortrans[15]; /*		ditto 	*/	char *cookie = CCM_GET_COOKIE(info);	int major  = CCM_GET_MAJORTRANS(info);	int minor  = CCM_GET_MINORTRANS(info);	struct ha_msg *m = timeout_msg;	assert(m);	snprintf(majortrans, sizeof(majortrans), "%d", major);	snprintf(minortrans, sizeof(minortrans), "%d", minor);	if((ha_msg_mod(m, CCM_COOKIE, cookie) == HA_FAIL)		||(ha_msg_mod(m, CCM_MAJORTRANS, majortrans) == HA_FAIL)		||(ha_msg_mod(m, CCM_MINORTRANS, minortrans) == HA_FAIL)){			cl_log(LOG_ERR, "timeout_msg_mod: Cannot "				"modify timeout message");		return NULL;	}	return m;}#ifdef TIMEOUT_MSG_FUNCTIONS_NEEDED/* *//* timeout_msg_done:  *//*   done with the processing of this message. */static voidtimeout_msg_done(void){	/* nothing to do. */	return;}/* *//* timeout_msg_del:  *//*   delete the given timeout message. *//*   nobody calls this function.  *//*   someday somebody will call it :) */static voidtimeout_msg_del(void){	ha_msg_del(timeout_msg);	timeout_msg = NULL;}#endif/* *//* These are the function that keep track of number of time a version *//* response message has been dropped. These function are consulted by *//* the CCM algorithm to determine if a version response message has *//* to be dropped or not. *//* */static int respdrop=0;#define MAXDROP 3static intresp_can_i_drop(void){	if (respdrop >= MAXDROP)		return FALSE;	return TRUE;}static voidresp_dropped(void){	respdrop++;}static voidresp_reset(void){	respdrop=0;}/* *//* End of response processing messages. *//* *//* *//* BEGIN OF functions that track the time since a connectivity reply has *//* been sent to the leader. *//* */static longclock_t finallist_time;static voidfinallist_init(void){	finallist_time = ccm_get_time();}static voidfinallist_reset(void){	finallist_time = 0;}static intfinallist_timeout(unsigned long timeout){	return(ccm_timeout(finallist_time, ccm_get_time(), timeout));}/* *//* END OF functions that track the time since a connectivity reply has *//* been sent to the leader. *//* *//* BEGINE of the functions that track asynchronous leave *//* *//* When ccm running on a  node leaves the cluster voluntarily it  *//* sends  a  leave  message  to  the  other nodes in the cluster.  *//* Similarly  whenever  ccm  running on some node of the cluster, *//* dies  the  local  heartbeat   delivers a leave message to ccm. *//* And  whenever  some node in the cluster dies, local heartbeat  *//* informs  the  death  through  a  callback.  *//* In all these cases, ccm is informed about the loss of the node, *//* asynchronously, in  some context where immidiate processing of  *//* the message is not possible.  *//* The  following  set of routines act as a cache that keep track  *//* of  message  leaves  and  facilitates  the  delivery  of these  *//* messages at a convinient time. *//*  *//* */static unsigned char *leave_bitmap=NULL;static voidleave_init(void){	int numBytes;	assert(!leave_bitmap);	numBytes = bitmap_create(&leave_bitmap, MAXNODE);	memset(leave_bitmap, 0, numBytes);}static voidleave_reset(void){	int numBytes = bitmap_size(MAXNODE);	if(!leave_bitmap) return;	memset(leave_bitmap, 0, numBytes);	return;}static voidleave_cache(int i){	assert(leave_bitmap);	bitmap_mark(i, leave_bitmap, MAXNODE);}static intleave_get_next(void){	int i;	assert(leave_bitmap);	for ( i = 0 ; i < MAXNODE; i++ ) {		if(bitmap_test(i,leave_bitmap,MAXNODE)) {			bitmap_clear(i,leave_bitmap,MAXNODE);			return i;		}	}	return -1;}static intleave_any(void){	if(bitmap_count(leave_bitmap,MAXNODE)) return TRUE;	return FALSE;}/* leave bitmap relate routines end *//* Reset all the datastructures. Go to a state which is equivalent *//* to a state when the node is just about to join a cluster. */static void ccm_reset(ccm_info_t *info){	if(ccm_already_joined(info)) client_evicted();	CCM_RESET_MEMBERSHIP(info);	ccm_memcomp_reset(info);	CCM_SET_ACTIVEPROTO(info, CCM_VER_NONE);	CCM_SET_COOKIE(info,"");	CCM_SET_MAJORTRANS(info,0);	CCM_SET_MINORTRANS(info,0);	CCM_SET_CL(info,-1);	CCM_SET_JOINED_TRANSITION(info, 0);	CCM_SET_STATE(info, CCM_STATE_NONE);	update_reset(CCM_GET_UPDATETABLE(info));	g_slist_free(CCM_GET_JOINERHEAD(info));	CCM_SET_JOINERHEAD(info, NULL);	version_reset(CCM_GET_VERSION(info));	finallist_reset();	leave_reset();	report_reset();}static void ccm_init(ccm_info_t *info){	update_init(CCM_GET_UPDATETABLE(info));	CCM_SET_JOINERHEAD(info, NULL);	CCM_INIT_MAXTRANS(info);        leave_init();        (void)timeout_msg_init(info);	ccm_reset(info);}/* * BEGIN OF ROUTINES THAT REPORT THE MEMBERSHIP TO CLIENTS. */static voidreport_reset(void){	return;}/* *//* print and report the cluster membership to clients. *//* */static voidreport_mbrs(ccm_info_t *info){	int i;	char *nodename;	static struct born_s  {		int index;		int bornon;	}  bornon[MAXNODE];/*avoid making it a 				stack variable*/		if(CCM_GET_MEMCOUNT(info)==1){		bornon[0].index  = CCM_GET_MEMINDEX(info,0);		bornon[0].bornon = CCM_GET_MAJORTRANS(info);	} else for(i=0; i < CCM_GET_MEMCOUNT(info); i++){		bornon[i].index = CCM_GET_MEMINDEX(info,i);		bornon[i].bornon = update_get_uptime(CCM_GET_UPDATETABLE(info), 				CCM_GET_LLM(info),				CCM_GET_MEMINDEX(info,i));		if(bornon[i].bornon==0) 			bornon[i].bornon=CCM_GET_MAJORTRANS(info);		assert(bornon[i].bornon!=-1);	}	if(global_verbose) {		cl_log(LOG_DEBUG,"\t\t the following are the members " 			"of the group of transition=%d",			CCM_GET_MAJORTRANS(info));		for (i=0 ;  i < CCM_GET_MEMCOUNT(info); i++) {			nodename = LLM_GET_NODEID(CCM_GET_LLM(info), 					CCM_GET_MEMINDEX(info,i));			cl_log(LOG_DEBUG,"\t\tnodename=%s bornon=%d", nodename, 					bornon[i].bornon);		}	}	/* 	 * report to clients, the new membership 	 */	client_new_mbrship(CCM_GET_MEMCOUNT(info), 		CCM_GET_MAJORTRANS(info),		CCM_GET_MEMTABLE(info), 		(CCM_GET_MEMCOUNT(info)==1 		&& llm_only_active_node(CCM_GET_LLM(info))),		bornon);	return;}/* * END OF ROUTINES THAT REPORT THE MEMBERSHIP TO CLIENTS. *//* *//* generate a random cookie. *//* NOTE: cookie  is  a  mechanism  of  seperating out the contexts *//* of  messages  of  partially  partitioned  clusters. *//* For example, consider  a  case  where   node  A  is  physically *//* in  the  partition  X  and  partition  Y,  and  but  has joined  *//* membership  in partition X. It will end up getting ccm protocol *//* messages  sent  by  members in both the partitions. In order to  *//* seperate  out  messages  belonging  to  individual partition, a  *//* random  string  is  used  as  a identifier by each partition to  *//* identify  its  messages.  In  the above case A will get message  *//* from  both  the  partitions  but  only listens to messages from  *//* partition X and drops messages from partition Y. *//* */static char *ccm_generate_random_cookie(void){	char *cookie;	int i;	struct timeval tmp;	cookie = g_malloc(COOKIESIZE*sizeof(char));	/* g_malloc never returns NULL: assert(cookie); */	/* seed the random with a random value */	gettimeofday(&tmp, NULL);	srandom((unsigned int)tmp.tv_usec); 	for ( i = 0 ; i < COOKIESIZE-1; i++ ) {		cookie[i] = random()%(127-'!')+'!';	}	cookie[i] = '\0';	return cookie;}static voidccm_free_random_cookie(char *cookie){	assert(cookie && *cookie);	g_free(cookie);}/* BEGIN OF FUNCTIONS that keep track of connectivity  information  *//* conveyed by individual members of the cluster. These  functions  *//* are used by only the cluster leader. Ultimately these connectivity *//* information is used by the cluster to extract out the members *//* of the cluster that have total connectivity. */static intccm_memcomp_cmpr(gconstpointer a, gconstpointer b){	return(*((const uint32_t *)a)-*((const uint32_t *)b));}static voidccm_memcomp_free(gpointer data, gpointer userdata){	if(data) g_free(data);	return;}static voidccm_memcomp_note(ccm_info_t *info, const char *orig, 		uint32_t maxtrans, const char *memlist){	int uuid, numbytes;	unsigned char *bitlist;	uint32_t *ptr;	memcomp_t *mem_comp = CCM_GET_MEMCOMP(info);	/* find the uuid of the originator */	uuid = llm_get_uuid(CCM_GET_LLM(info), orig);	/* convert the memlist into a bit map and feed it to the graph */	numbytes = ccm_str2bitmap(memlist, &bitlist);		graph_update_membership(MEMCOMP_GET_GRAPH(mem_comp), 			uuid, bitlist);	/*NOTE DO NOT DELETE bitlist, because it is 	 * being handled by graph*/	ptr = (uint32_t *)g_malloc(2*sizeof(uint32_t));	ptr[0] = maxtrans;	ptr[1] = uuid;	MEMCOMP_SET_MAXT(mem_comp, 		(g_slist_insert_sorted(MEMCOMP_GET_MAXT(mem_comp), 			ptr, ccm_memcomp_cmpr)));	return;}/* called by the cluster leader only  */static voidccm_memcomp_note_my_membership(ccm_info_t *info){	char *memlist;	int str_len;	/* find the uuid of the originator */	str_len = update_strcreate(CCM_GET_UPDATETABLE(info), 			&memlist, CCM_GET_LLM(info));	ccm_memcomp_note(info, ccm_get_my_hostname(info), 			CCM_GET_MAXTRANS(info), memlist);	update_strdelete(memlist);	return;}/* add a new member to the membership list */static voidccm_memcomp_add(ccm_info_t *info, const char *orig){	int uuid, myuuid;	memcomp_t *mem_comp = CCM_GET_MEMCOMP(info);	uuid = llm_get_uuid(CCM_GET_LLM(info), orig);	myuuid = llm_get_uuid(CCM_GET_LLM(info), 			ccm_get_my_hostname(info));	graph_add_uuid(MEMCOMP_GET_GRAPH(mem_comp), uuid);	graph_add_to_membership(MEMCOMP_GET_GRAPH(mem_comp), 			myuuid, uuid);	/* ccm_memcomp_note(info, orig, maxtrans, memlist); */	return;}static void ccm_memcomp_init(ccm_info_t *info){	int track=-1;	int uuid;		memcomp_t *mem_comp = CCM_GET_MEMCOMP(info);	MEMCOMP_SET_GRAPH(mem_comp, graph_init());	/* go through the update list and note down all the members who	 * had participated in the join messages. We should be expecting	 * reply memlist bitmaps atleast from these nodes.	 */	while((uuid = update_get_next_uuid(CCM_GET_UPDATETABLE(info), 				CCM_GET_LLM(info), &track)) != -1) {		graph_add_uuid(MEMCOMP_GET_GRAPH(mem_comp),uuid); 	}	MEMCOMP_SET_MAXT(mem_comp,  NULL);	MEMCOMP_SET_INITTIME(mem_comp, ccm_get_time());}static void ccm_memcomp_reset(ccm_info_t *info){	GSList *head;	memcomp_t *mem_comp = CCM_GET_MEMCOMP(info);	graph_free(MEMCOMP_GET_GRAPH(mem_comp));	MEMCOMP_SET_GRAPH(mem_comp,NULL);	head = MEMCOMP_GET_MAXT(mem_comp);	g_slist_foreach(MEMCOMP_GET_MAXT(mem_comp), 			ccm_memcomp_free, NULL);	g_slist_free(MEMCOMP_GET_MAXT(mem_comp));	MEMCOMP_SET_MAXT(mem_comp,  NULL);	return;}static intccm_memcomp_rcvd_all(ccm_info_t *info){	return 	graph_filled_all(MEMCOMP_GET_GRAPH(CCM_GET_MEMCOMP(info)));}static intccm_memcomp_timeout(ccm_info_t *info, long timeout){	memcomp_t *mem_comp = CCM_GET_MEMCOMP(info);	return(ccm_timeout(MEMCOMP_GET_INITTIME(mem_comp), 				ccm_get_time(), timeout));}

⌨️ 快捷键说明

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