osaf/services/saf/immsv/immnd/ImmModel.cc | 86 +++++++++++++++++++++++++++++- osaf/services/saf/immsv/immnd/ImmModel.hh | 2 + osaf/services/saf/immsv/immnd/immnd_init.h | 4 + osaf/services/saf/immsv/immnd/immnd_proc.c | 43 +++++++++++--- 4 files changed, 123 insertions(+), 12 deletions(-)
When discarding a client, there are chances that IMMND fails to send impl/admo/ccb discard messages or IMMD can't receive those messages. In that case, we have to make sure that those messages are re-sent. If not, we will have admo/ccb resource leak or implementers marked as dying forever. DEFAULT_TIMEOUT_SEC (6sec) is used as retry interval. diff --git a/osaf/services/saf/immsv/immnd/ImmModel.cc b/osaf/services/saf/immsv/immnd/ImmModel.cc --- a/osaf/services/saf/immsv/immnd/ImmModel.cc +++ b/osaf/services/saf/immsv/immnd/ImmModel.cc @@ -534,6 +534,8 @@ static IdVector sImplsDeadDuring // but before it arrives over fevs. // This to avoid apparent implementor // re-create by finalizeSync (at non coord). +static ContinuationMap2 sDiscardingClientMap; /* Make sure that impl/ccb/admo associated with + the client are discarded successfully */ static DeferredObjUpdatesMap sDeferredObjUpdatesMap; @@ -1170,6 +1172,8 @@ immModel_cleanTheBasement(IMMND_CB *cb, SaUint32T* searchReqArrSize, SaUint32T** ccbIdArr, SaUint32T* ccbIdArrSize, + SaUint32T** clientIdArr, + SaUint32T* clientIdArrSize, SaUint32T** pbePrtoReqArr, SaUint32T* pbePrtoReqArrSize, SaBoolT iAmCoordNow) @@ -1178,6 +1182,7 @@ immModel_cleanTheBasement(IMMND_CB *cb, InvocVector searchReqs; InvocVector::iterator ix1; IdVector ccbs; + IdVector clients; IdVector pbePrtoReqs; IdVector::iterator ix2; unsigned int ix; @@ -1187,6 +1192,7 @@ immModel_cleanTheBasement(IMMND_CB *cb, admReqs, searchReqs, ccbs, + clients, pbePrtoReqs, iAmCoordNow); @@ -1226,6 +1232,16 @@ immModel_cleanTheBasement(IMMND_CB *cb, osafassert(ix==(*ccbIdArrSize)); } + *clientIdArrSize = (SaUint32T) clients.size(); + if (*clientIdArrSize) { + *clientIdArr = (SaUint32T *) malloc((*clientIdArrSize) * sizeof(SaUint32T)); + + for (ix2 = clients.begin(), ix = 0; ix2 != clients.end(); ++ix2, ++ix) { + (*clientIdArr)[ix] = (*ix2); + } + osafassert(ix == (*clientIdArrSize)); + } + *pbePrtoReqArrSize = (SaUint32T) pbePrtoReqs.size(); if(*pbePrtoReqArrSize) { *pbePrtoReqArr = (SaUint32T *) @@ -2146,6 +2162,11 @@ immModel_prepareForSync(IMMND_CB *cb, Sa ImmModel::instance(&cb->immModel)->prepareForSync(isJoining); } +void immModel_addDiscardingClient(IMMND_CB *cb, SaUint32T clientId) +{ + ImmModel::instance(&cb->immModel)->addDiscardingClient(clientId); +} + void immModel_discardContinuations(IMMND_CB *cb, SaUint32T deadConn) { @@ -13375,6 +13396,26 @@ ImmModel::discardImplementer(unsigned in } void +ImmModel::addDiscardingClient(SaUint32T clientId) +{ + TRACE_ENTER(); + + ContinuationMap2::iterator ci = sDiscardingClientMap.find(clientId); + if (ci == sDiscardingClientMap.end()) { + TRACE("Add discarding client %u", clientId); + sDiscardingClientMap[clientId] = ContinuationInfo2(0 /*Unused*/, DEFAULT_TIMEOUT_SEC); + } else { + /* Update the create-time */ + TRACE("Update time for discarding client %u", clientId); + osaf_clock_gettime_sec(CLOCK_MONOTONIC, &(ci->second.mCreateTime)); + osafassert(ci->second.mCreateTime >= ((time_t) 0)); + } + + TRACE_LEAVE(); + return; +} + +void ImmModel::discardContinuations(SaUint32T dead) { TRACE_ENTER(); @@ -13730,7 +13771,7 @@ ImmModel::purgeSyncRequest(SaUint32T cli SaUint32T ImmModel::cleanTheBasement(InvocVector& admReqs, - InvocVector& searchReqs, IdVector& ccbs, IdVector& pbePrtoReqs, + InvocVector& searchReqs, IdVector& ccbs, IdVector& clients, IdVector& pbePrtoReqs, bool iAmCoord) { time_t now; @@ -13875,6 +13916,49 @@ ImmModel::cleanTheBasement(InvocVector& delete (ccb); } + ci2 = sDiscardingClientMap.begin(); + while (ci2 != sDiscardingClientMap.end()) { + SaUint32T implId; + ConnVector cv; + + /* Check if there's still implementer associated with the client */ + implId = getImplementerId(ci2->first); + if (implId) { + TRACE("client %llu is not completely discarded", ci2->first); + if (now - ci2->second.mCreateTime >= (DEFAULT_TIMEOUT_SEC)) { + clients.push_back(ci2->first); + } + ++ci2; + continue; + } + + /* Check if there're still CCBs associated with the client */ + getCcbIdsForOrigCon(ci2->first, cv); + if (cv.size()) { + TRACE("client %llu is not completely discarded", ci2->first); + if (now - ci2->second.mCreateTime >= (DEFAULT_TIMEOUT_SEC)) { + clients.push_back(ci2->first); + } + ++ci2; + continue; + } + + /* Check if there're still admos associated with the client */ + cv.clear(); + getAdminOwnerIdsForCon(ci2->first, cv); + if (cv.size()) { + TRACE("client %llu is not completely discarded", ci2->first); + if (now - ci2->second.mCreateTime >= (DEFAULT_TIMEOUT_SEC)) { + clients.push_back(ci2->first); + } + ++ci2; + continue; + } + + TRACE("client %llu is completely discarded, remove it", ci2->first); + ci2 = sDiscardingClientMap.erase(ci2); /* C++11 */ + } + ci2=sPbeRtReqContinuationMap.begin(); while(ci2!=sPbeRtReqContinuationMap.end()) { //Timeout on PRT request continuation is hardwired but long. diff --git a/osaf/services/saf/immsv/immnd/ImmModel.hh b/osaf/services/saf/immsv/immnd/ImmModel.hh --- a/osaf/services/saf/immsv/immnd/ImmModel.hh +++ b/osaf/services/saf/immsv/immnd/ImmModel.hh @@ -557,6 +557,7 @@ public: bool reallyDiscard, IdVector& gv, bool isAtCoord); + void addDiscardingClient(SaUint32T clientId); void discardContinuations(SaUint32T dead); void discardNode(unsigned int nodeId, IdVector& cv, IdVector& gv, bool isAtCoord, bool scAbsence); void getCcbIdsForOrigCon(SaUint32T dead, IdVector& cv); @@ -572,6 +573,7 @@ public: InvocVector& admReqs, InvocVector& searchReqs, IdVector& ccbs, + IdVector& clients, IdVector& pbePrtoReqs, bool iAmCoord); diff --git a/osaf/services/saf/immsv/immnd/immnd_init.h b/osaf/services/saf/immsv/immnd/immnd_init.h --- a/osaf/services/saf/immsv/immnd/immnd_init.h +++ b/osaf/services/saf/immsv/immnd/immnd_init.h @@ -133,6 +133,8 @@ extern "C" { SaUint32T *searchReqArrSize, SaUint32T **ccbIdArr, SaUint32T *ccbIdArrSize, + SaUint32T **clientIdArr, + SaUint32T *clientIdArrSize, SaUint32T **pbePrtoReqIdArr, SaUint32T *pbePrtoReqArrSize, SaBoolT iAmCoordNow); @@ -379,6 +381,8 @@ extern "C" { SaUint32T ccbId, SaUint32T invocation, SaAisErrorT error, SaUint32T *reqConn); + void immModel_addDiscardingClient(IMMND_CB *cb, SaUint32T clientId); + void immModel_discardContinuations(IMMND_CB *cb, SaUint32T deadConn); SaBoolT immModel_immNotWritable(IMMND_CB *cb); diff --git a/osaf/services/saf/immsv/immnd/immnd_proc.c b/osaf/services/saf/immsv/immnd/immnd_proc.c --- a/osaf/services/saf/immsv/immnd/immnd_proc.c +++ b/osaf/services/saf/immsv/immnd/immnd_proc.c @@ -133,13 +133,13 @@ uint32_t immnd_proc_imma_discard_connect if (!scAbsence && immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD, cb->immd_mdest_id, &send_evt) != NCSCC_RC_SUCCESS) { if (immnd_is_immd_up(cb)) { - LOG_ER("Discard implementer failed for implId:%u " - "but IMMD is up !? - case not handled. Client will be orphanded", implId); + LOG_WA("Discard implementer failed for implId:%u " + "but IMMD is up !? will retry later ", implId); } else { LOG_WA("Discard implementer failed for implId:%u " "(immd_down)- will retry later", implId); + cl_node->mIsStale = true; } - cl_node->mIsStale = true; } /*Discard the local implementer directly and redundantly to avoid race conditions using this implementer (ccb's causing abort upcalls). @@ -171,14 +171,13 @@ uint32_t immnd_proc_imma_discard_connect if (immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD, cb->immd_mdest_id, &send_evt) != NCSCC_RC_SUCCESS) { if (immnd_is_immd_up(cb)) { - LOG_ER("Failure to broadcast discard Ccb for ccbId:%u " - "but IMMD is up !? - case not handled. Client will " - "be orphanded", implId); + LOG_WA("Failure to broadcast discard Ccb for ccbId:%u " + "but IMMD is up !? - will retry later", implId); } else { LOG_WA("Failure to broadcast discard Ccb for ccbId:%u " "(immd down)- will retry later", idArr[ix]); + cl_node->mIsStale = true; } - cl_node->mIsStale = true; } } free(idArr); @@ -216,14 +215,13 @@ uint32_t immnd_proc_imma_discard_connect if(immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD, cb->immd_mdest_id, &send_evt) != NCSCC_RC_SUCCESS) { if (immnd_is_immd_up(cb)) { - LOG_ER("Failure to broadcast discard admo0wner for ccbId:%u " - "but IMMD is up !? - case not handled. Client will " - "be orphanded", implId); + LOG_WA("Failure to broadcast discard admo0wner for ccbId:%u " + "but IMMD is up !? - will retry later", implId); } else { LOG_WA("Failure to broadcast discard admowner for id:%u " "(immd down)- will retry later", idArr[ix]); + cl_node->mIsStale = true; } - cl_node->mIsStale = true; } } } @@ -234,6 +232,12 @@ uint32_t immnd_proc_imma_discard_connect if (!cl_node->mIsStale) { TRACE_5("Discard connection id:%llx succeeded", cl_node->imm_app_hdl); + + /* Add the discarding client to continuation map */ + immModel_addDiscardingClient(cb, client_id); + + /* Don't add stale clients to the map. They will be discarded by + * immnd_proc_imma_discard_stales() when IMMD is up again. */ } TRACE_LEAVE(); @@ -986,6 +990,8 @@ static void immnd_cleanTheHouse(IMMND_CB SaUint32T searchReqArrSize = 0; SaUint32T *ccbIdArr = NULL; SaUint32T ccbIdArrSize = 0; + SaUint32T *clientIdArr = NULL; + SaUint32T clientIdArrSize = 0; SaUint32T *pbePrtoReqArr = NULL; SaUint32T pbePrtoReqArrSize = 0; @@ -1082,6 +1088,8 @@ static void immnd_cleanTheHouse(IMMND_CB &searchReqArrSize, &ccbIdArr, &ccbIdArrSize, + &clientIdArr, + &clientIdArrSize, &pbePrtoReqArr, &pbePrtoReqArrSize, iAmCoordNow); @@ -1261,6 +1269,19 @@ static void immnd_cleanTheHouse(IMMND_CB free(ccbIdArr); } + if (clientIdArrSize) { + for (ix = 0; ix < clientIdArrSize; ++ix) { + /* The client-node is deleted in the first attempt of discarding. + * Create a dummy client-node for the client-id */ + IMMND_IMM_CLIENT_NODE dummy_node; + memset(&dummy_node, 0, sizeof(IMMND_IMM_CLIENT_NODE)); + dummy_node.imm_app_hdl = m_IMMSV_PACK_HANDLE(clientIdArr[ix], cb->node_id); + + immnd_proc_imma_discard_connection(cb, &dummy_node, false); + } + free(clientIdArr); + } + if (pbePrtoReqArrSize) { IMMSV_EVT reply; memset(&reply, 0, sizeof(IMMSV_EVT)); ------------------------------------------------------------------------------ What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports. https://ad.doubleclick.net/ddm/clk/305295220;132659582;e _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel