📄 ccm.c
字号:
||(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 + -