📄 ccm.c
字号:
/* 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(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));}static intccm_memcomp_get_maxmembership(ccm_info_t *info, unsigned char **bitmap){ GSList *head; uint32_t *ptr; int uuid; memcomp_t *mem_comp = CCM_GET_MEMCOMP(info); (void)graph_get_maxclique(MEMCOMP_GET_GRAPH(mem_comp), bitmap); head = MEMCOMP_GET_MAXT(mem_comp); while (head) { ptr = (uint32_t *)g_slist_nth_data(head, 0); uuid = ptr[1]; if(bitmap_test(uuid, *bitmap, MAXNODE)) { return ptr[0]; } head = g_slist_next(head); } return 0;}/* *//* END OF the membership tracking functions. *//* */static int ccm_am_i_member(ccm_info_t *info, const char *memlist){ unsigned char *bitmap; int numBytes = ccm_str2bitmap(memlist, &bitmap); /* what is my node Uuid */ llm_info_t *llm = CCM_GET_LLM(info); int my_uuid = LLM_GET_MYUUID(llm); if (bitmap_test(my_uuid, bitmap, numBytes)){ bitmap_delete(bitmap); return TRUE; } bitmap_delete(bitmap); return FALSE;}/* *//* BEGIN OF FUNCTIONS that keep track of stablized membership list *//* *//* These function keep track of consensus membership once a instance *//* of the ccm algorithm terminates and decided on the final consensus *//* members of the cluster. *//* */static int ccm_memlist_changed(ccm_info_t *info, char *bitmap /* the bitmap string containing bits */){ int nodeCount, i; llm_info_t *llm; uint indx, uuid; /* go through the membership list */ nodeCount = CCM_GET_MEMCOUNT(info); llm = CCM_GET_LLM(info); for ( i = 0 ; i < nodeCount; i++ ) { indx = CCM_GET_MEMINDEX(info, i); assert(indx >=0 && indx < LLM_GET_NODECOUNT(llm)); uuid = LLM_GET_UUID(llm,indx); assert(uuid>=0 && uuid < MAXNODE); if (!bitmap_test(uuid, bitmap, MAXNODE)){ return TRUE; } } return FALSE;} static int ccm_fill_memlist(ccm_info_t *info, const unsigned char *bitmap){ llm_info_t *llm; uint i, uuid; llm = CCM_GET_LLM(info); CCM_RESET_MEMBERSHIP(info); for ( i = 0 ; i < LLM_GET_NODECOUNT(llm); i++ ) { uuid = LLM_GET_UUID(llm,i); if(bitmap_test(uuid, bitmap, MAXNODE)){ /*update the membership list with this member*/ CCM_ADD_MEMBERSHIP(info, i); } } return FALSE;}static int ccm_fill_memlist_from_str(ccm_info_t *info, const unsigned char *memlist){ unsigned char *bitmap; int ret; (void)ccm_str2bitmap(memlist, &bitmap); ret = ccm_fill_memlist(info, bitmap); bitmap_delete(bitmap); return ret;} static int ccm_fill_memlist_from_bitmap(ccm_info_t *info, const unsigned char *bitmap){ return ccm_fill_memlist(info, bitmap);}static intccm_get_membership_index(ccm_info_t *info, const char *node){ int i,indx;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -