📄 distgaplib.c
字号:
* lost a remote comparison, so forget about the old group * id and try a new one. */ case DIST_PKT_TYPE_GAP_REJECT: { DIST_PKT_GAP_REJECT *pDistPktGapReject; DIST_GRP_DB_NODE *pDistGrp; pDistPktGapReject = (DIST_PKT_GAP_REJECT *) &distPktGap; /* Convert rejectId (uint16) to host order */ pDistPktGapReject->rejectId = ntohs (pDistPktGapReject->rejectId); #ifdef DIST_GAP_REPORT printf ("distGapInput: received REJECT for `%s'/%d from node %ld\n", pDistPktGapReject->rejectName, pDistPktGapReject->rejectId, distNodeIdSrc);#endif msgQDistGrpDbLock(); pDistGrp = msgQDistGrpLclFindById (pDistPktGapReject->rejectId); if (pDistGrp == NULL || msgQDistGrpLclGetState (pDistGrp) == DIST_GRP_STATE_GLOBAL) { /* * This is a REJECT for an id, that * 1) does not exist anymore (due to earlier REJECTs): * This means, someone sent us a REJECT. As a * consequence of this, we destoyed the local entry * for this group and tried again with a new id. * 2) was confirmed by GAP earlier (group is in GLOBAL state). * * All responses to the old group id go here and will be ignored. */ msgQDistGrpDbUnlock(); break; } /* * Cleanup and reinitialize the GAP structure. */ distGapOutstandUnlink (pDistGrp->pGrpDbGapNode); distGapOutstandLink (pDistGrp->pGrpDbGapNode); pDistGrp->pGrpDbGapNode->gapTimeout = DIST_GAP_TRY_TIMO; pDistGrp->pGrpDbGapNode->gapRetries = 1; /* * Get a new id and reset state. */ msgQDistGrpLclSetId (pDistGrp, distGrpIdNext++); msgQDistGrpLclSetState (pDistGrp, DIST_GRP_STATE_LOCAL_TRY); msgQDistGrpDbUnlock(); /* * Have a different TRY. */ distGapTry (DIST_IF_BROADCAST_ADDR, pDistGrp); break; } /* * We received an ASK_WAIT. We have send a TRY before. Someone else * found a conflict, where it is trying to create the same group, but * with an alternate id. Since the other node has a higher node id * it asks us to wait for a SET. */ case DIST_PKT_TYPE_GAP_ASK_WAIT: { DIST_PKT_GAP_ASK_WAIT *pDistPktGapAskWait; DIST_GRP_DB_NODE *pDistGrp; pDistPktGapAskWait = (DIST_PKT_GAP_ASK_WAIT *) &distPktGap; /* Convert askWaitId (uint16) to host byte order */ pDistPktGapAskWait->askWaitId = ntohs (pDistPktGapAskWait->askWaitId);#ifdef DIST_GAP_REPORT printf ("distGapInput: received ASK_WAIT for `%s'/%d from node %ld\n", pDistPktGapAskWait->askWaitName, pDistPktGapAskWait->askWaitId, distNodeIdSrc);#endif msgQDistGrpDbLock(); pDistGrp = msgQDistGrpLclFindByName (pDistPktGapAskWait->askWaitName); if (pDistGrp == NULL || msgQDistGrpLclGetState (pDistGrp) == DIST_GRP_STATE_GLOBAL) { /* * This is an ASK_WAIT for an id, that * 1) does not exist anymore (due to earlier REJECTs): * This means, someone sent us a REJECT. As a * consequence of this, we destoyed the local entry * for this group and tried again with a new id. * 2) was confirmed by GAP earlier (group is in GLOBAL state). * * All responses to the old group id go here and will be ignored. */ msgQDistGrpDbUnlock(); break; } if (msgQDistGrpLclGetState (pDistGrp) != DIST_GRP_STATE_WAIT) { /* * Remove the list of outstanding responses. Do *NOT* * remove the GAP structure. */ distGapOutstandUnlink (pDistGrp->pGrpDbGapNode); msgQDistGrpLclSetState (pDistGrp, DIST_GRP_STATE_WAIT); pDistGrp->pGrpDbGapNode->gapTimeout = DIST_GAP_WAIT_TIMO; } msgQDistGrpDbUnlock(); break; } /* * We have received a SET. When receiving a SET, we already should * have received a TRY and responded to it with OK. */ case DIST_PKT_TYPE_GAP_SET: { DIST_PKT_GAP_SET *pDistPktGapSet; DIST_GRP_DB_NODE *pGrpFoundById; DIST_GRP_DB_NODE *pGrpFoundByName; DIST_GRP_DB_NODE *pDistGrp; pDistPktGapSet = (DIST_PKT_GAP_SET *) &distPktGap; /* Convert setId (uint16) to host byte order */ pDistPktGapSet->setId = ntohs (pDistPktGapSet->setId);#ifdef DIST_GAP_REPORT printf ("distGapInput: received SET for `%s'/%d from node %ld\n", pDistPktGapSet->setName, pDistPktGapSet->setId, distNodeIdSrc);#endif /* * Sanity check: Is this a SET from future? */ if (pDistPktGapSet->setId >= distGrpIdNext) { /* * There was no TRY for this SET! Just ignore this. */#ifdef DIST_DIAGNOSTIC distLog ("distGapInput/SET: no TRY for SET\n");#endif break; } msgQDistGrpDbLock(); pGrpFoundById = msgQDistGrpLclFindById (pDistPktGapSet->setId); pGrpFoundByName = msgQDistGrpLclFindByName (pDistPktGapSet->setName); if (pGrpFoundByName && (!pGrpFoundById || pGrpFoundById == pGrpFoundByName) && (msgQDistGrpLclGetState (pGrpFoundByName) != DIST_GRP_STATE_GLOBAL)) { /* * When do we get here? * We were waiting for this one. An earlier TRY asked us to * wait. Here is the SET we waited for. */#ifdef DIST_GAP_REPORT printf ("distGapInput/SET: got SET for existing nonglobal group");#endif msgQDistGrpLclSetId (pGrpFoundByName, pDistPktGapSet->setId); msgQDistGrpLclSetState (pGrpFoundByName, DIST_GRP_STATE_GLOBAL); msgQDistGrpLclSetCreator (pGrpFoundByName, distNodeIdSrc); if (pGrpFoundByName->pGrpDbGapNode) { distGapOutstandUnlink (pGrpFoundByName->pGrpDbGapNode); semFlush (&pGrpFoundByName->pGrpDbGapNode->gapWaitFor); } msgQDistGrpDbUnlock(); break; } if (pGrpFoundById != pGrpFoundByName) { /* * Id or name are already in database but do not point * to the same object. This can happen, if we receive * multiple SETs. */ msgQDistGrpDbUnlock();#ifdef DIST_GAP_REPORT printf ("distGapInput/SET: id or name already in database\n");#endif break; } if (pGrpFoundById && pGrpFoundById == pGrpFoundByName) { /* * An exact copy of this object is already in the database. * Ignore state. */#ifdef DIST_GAP_REPORT printf ("distGapInput/SET: `%s' (0x%lx) is already in database\n", pDistPktGapSet->setName, (u_long) pDistPktGapSet->setId);#endif msgQDistGrpLclSetState (pGrpFoundByName, DIST_GRP_STATE_GLOBAL); msgQDistGrpLclSetCreator (pGrpFoundByName, distNodeIdSrc); if (pGrpFoundByName->pGrpDbGapNode != NULL) semFlush (&pGrpFoundByName->pGrpDbGapNode->gapWaitFor); msgQDistGrpDbUnlock(); break; } /* * Neither id nor name are found in the database. * Create node in group database. */#ifdef DIST_GAP_REPORT printf ("distGapInput/SET: creating local db entry `%s' (0x%lx)\n", pDistPktGapSet->setName, (u_long) pDistPktGapSet->setId);#endif pDistGrp = msgQDistGrpLclCreate (pDistPktGapSet->setName, pDistPktGapSet->setId, DIST_GRP_STATE_GLOBAL); msgQDistGrpLclSetCreator (pDistGrp, distNodeLocalGetId ()); if (pDistGrp == NULL) { /* * We have a SET from remote and cannot create a new * node in the group database. This is a fatal error. */ distPanic ("distGapInput:SET: creation of new node failed\n"); } msgQDistGrpLclSetCreator (pDistGrp, distNodeIdSrc); msgQDistGrpDbUnlock(); break; } /* * This type of telegram is unknown. */ default: { /* * When we get here, the packet is already acknowledged. * But this makes no difference since an unknown type of * telegram is a fatal error. Let's panic! */#ifdef DIST_DIAGNOSTIC distPanic ("distGapInput: unknown type of telegram\n");#endif } } return (DIST_GAP_STATUS_OK); }#ifdef DIST_GAP_TASK/********************************************************************************* distGapTimerTask - Timeout management task*** NOMANUAL*/LOCAL void distGapTimerTask () { while (1) { distGapTimer (); taskDelay (DIST_GAP_MGR_WAKEUP_TICKS); } }/********************************************************************************* distGapTimer - Timeout management** The job of the distGapTimer() is to go through the list of active* GAPs to see if a GAP has timed out.** NOMANUAL*/LOCAL void distGapTimer () { DIST_GAP_NODE *pGapNode; distGapLock(); /* * Run through list of open GAPs. */ pGapNode = (DIST_GAP_NODE *) DLL_FIRST (&gapInProgress); while (pGapNode != NULL) { DIST_GAP_RESPONSE *pDistGapResponse = (DIST_GAP_RESPONSE *) SLL_FIRST (&pGapNode->gapOutstand); switch (msgQDistGrpLclGetState (pGapNode->pGapGrp)) { case DIST_GRP_STATE_LOCAL_TRY: /* try initiated by us */ case DIST_GRP_STATE_WAIT_TRY: /* retry after wait */ { /* * This GAP is open and we are still trying. */ if (pGapNode->gapTimeout == 0) { /* * GAP has timed out. Lookup the missing nodes. */ DIST_GAP_RESPONSE *pDistGapResponsePrev; while (pDistGapResponse != NULL) { if (distNodeGetState (pDistGapResponse->pGapResponseNode) == DIST_NODE_STATE_OPERATIONAL) { /* * According to our local database the node is OPERATIONAL. * Check the number of retries. */ DIST_NODE_ID distNodeIdMissing = pDistGapResponse->pGapResponseNode->nodeId; if (pGapNode->gapRetries++ > DIST_GAP_MAX_RETRIES) { /* * The number of retries is within the limit. * Send a unicast TRY with a higher timeout to the * missing node. */ pGapNode->gapTimeout = pGapNode->gapRetries * DIST_GAP_TRY_TIMO; distGapTry (distNodeIdMissing, pGapNode->pGapGrp); } else { /* * We have exceeded the limit of max retries. * The remote node seams to be dead. Tell the node * database about our assumption. */ (void) distNodeCrashed (distNodeIdMissing); distGapOutstandDel (pGapNode, pDistGapResponse, pDistGapResponsePrev); } } else { /* * Node has died, while we were waiting for a response. * Dying is something like agreeing. */ distGapOutstandDel (pGapNode, pDistGapResponse, pDistGapResponsePrev); } pDistGapResponsePrev = pDistGapResponse; pDistGapResponse = (DIST_GAP_RESPONSE *) SLL_NEXT (pDistGapResponse); } /* while (pDistGapResponse != NULL) */ } pGapNode->gapTimeout--; break; } case DIST_GRP_STATE_WAIT: { /* * Someone told us to wait. */ if (pGapNode->gapTimeout == 0) { /* * GAP timed out and we are still waiting for a SET. We will * return to try again, but we must not forget the WAITing * state we were in, since the missing SET might come in at * any time. */ DIST_GRP_DB_NODE *pDistGrp; /* * Reinitialize the GAP structure. Cleanup was done, * before entering WAITing state. */ distGapOutstandLink (pGapNode); pDistGrp->pGrpDbGapNode->gapTimeout = DIST_GAP_TRY_TIMO; pDistGrp->pGrpDbGapNode->gapRetries = 1; /* * Get a new id and reset state. */ pDistGrp = pGapNode->pGapGrp; msgQDistGrpLclSetId (pDistGrp, distGrpIdNext++); msgQDistGrpLclSetState (pDistGrp, DIST_GRP_STATE_WAIT_TRY); /* * Have another TRY with a different id. */ distGapTry (DIST_IF_BROADCAST_ADDR, pDistGrp); } pGapNode->gapTimeout--; break; } default: {#ifdef DIST_DIAGNOSTIC distLog ("distGapTimer: `%s' in unknown or unexpected state %d\n", &pGapNode->pGapGrp->grpDbName, pGapNode->pGapGrp->grpDbState);#endif } } /* switch (state) */ pGapNode = (DIST_GAP_NODE *) DLL_NEXT (pGapNode); } /* while (pGapNode != NULL) */ distGapUnlock(); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -