static void MAMACALLTYPE msgCB (mamaSubscription subscription, mamaMsg msg, void* closure, void* itemClosure) { mama_u16_t command_id = 0; mamaCmResponderImpl *impl = (mamaCmResponderImpl*)closure; mamaCommand* command = (mamaCommand*)list_allocate_element(impl->mPendingCommands); /* Get the transport index in use by the supplied subscription. */ int transportIndex = 0; /* * The command ID field tells us what command to execute. * * Add new values for new commands. */ mamaMsg_getU16 (msg, NULL, MAMA_CM_COMMAND_ID, &command_id); /* TODO: We can convert this into a command lookup for various Client * management/wadmin type commands. */ switch (command_id) { case MAMA_COMMAND_SYNC: { mama_log (MAMA_LOG_LEVEL_FINE, "mamaCmResponder::msgCb(): " "CM SYNC Received" ); mamaSubscription_getTransportIndex(subscription, &transportIndex); mamaSyncCommand_create (command, msg, impl->mTransport, transportIndex, impl->publishers[transportIndex], endCB, impl); list_push_back(impl->mPendingCommands, command); mamaSyncCommand_run (command); } break; default: list_free_element (impl->mPendingCommands, command); mama_log (MAMA_LOG_LEVEL_FINE, "mamaCmResponder::msgCB(): " "Bad CM command: %d", command); } }
mama_status dqStrategy_checkSeqNum (dqStrategy strategy, mamaMsg msg, int msgType, mamaDqContext* ctx) { mama_seqnum_t seqNum = 0; mama_seqnum_t ctxSeqNum = ctx->mSeqNum; mama_u64_t senderId = 0; mama_u64_t ctxSenderId = ctx->mSenderId; dqState ctxDqState = ctx->mDQState; mamaSubscription subscription = self->mSubscription; mama_u16_t conflateCnt = 1; wombat_subscriptionGapCB onGap = NULL; mamaTransport transport; mamaStatsCollector transportStatsCollector = NULL; wombat_subscriptionQualityCB onQuality = NULL; mamaMsgStatus msgStatus = MAMA_MSG_STATUS_UNKNOWN; mamaTransport tport = NULL; mamaSubscription_getTransport (self->mSubscription, &tport); mamaMsg_getSeqNum (msg, &seqNum); ctx->mDoNotForward = 0; if (mamaMsg_getU64 (msg, MamaFieldSenderId.mName, MamaFieldSenderId.mFid, &senderId) != MAMA_STATUS_OK) { /* We just ignore it as we might be running against an older FH */ senderId = 0; } /*Special case for dealing with a fault tolerant takeover*/ if (ctxSenderId != 0 && senderId != 0 && ctxSenderId != senderId) { /* Only record FT Takeovers per transport and globally */ if (gGenerateTransportStats) { mamaSubscription_getTransport (subscription, &transport); transportStatsCollector = mamaTransport_getStatsCollector (transport); mamaStatsCollector_incrementStat (transportStatsCollector, MamaStatFtTakeovers.mFid); } if (mamaInternal_getGlobalStatsCollector() != NULL) { mamaStatsCollector_incrementStat (mamaInternal_getGlobalStatsCollector(), MamaStatFtTakeovers.mFid); } if (DQ_FT_WAIT_FOR_RECAP==mamaTransportImpl_getFtStrategyScheme(tport)) { ctx->mDoNotForward = 1; handleFTTakeover (strategy, msg, msgType, ctx, seqNum, senderId, 1); } else { return handleFTTakeover (strategy, msg, msgType, ctx, seqNum, senderId, 0); } } if (gMamaLogLevel >= MAMA_LOG_LEVEL_FINEST) { const char* symbol = NULL; mamaSubscription_getSymbol (subscription, &symbol); symbol = symbol == NULL ? "" : symbol; mama_log (MAMA_LOG_LEVEL_FINEST, "dqStrategy_checkSeqNum(): %s : seq# %ld", symbol, seqNum); } switch (msgType) { case MAMA_MSG_TYPE_QUOTE: case MAMA_MSG_TYPE_TRADE: case MAMA_MSG_TYPE_UPDATE: default: if (MAMA_STATUS_OK != mamaMsg_getU16 (msg, MamaFieldConflateCount.mName, MamaFieldConflateCount.mFid, &conflateCnt)) { /*Need to set conflateCnt=1 as mamaMsg_getU16 sets conflateCnt=0 if not found */ conflateCnt = 1; } /* Deliberate fallthrough. Only the types above can be conflated, so only try to extract the conflate count field for those types. */ case MAMA_MSG_TYPE_SEC_STATUS: case MAMA_MSG_TYPE_BOOK_UPDATE: if (((ctxDqState == DQ_STATE_NOT_ESTABLISHED) || (seqNum == 0) || (seqNum == (ctxSeqNum + conflateCnt))) && ((ctxDqState != DQ_STATE_WAITING_FOR_RECAP) || (ctxDqState != DQ_STATE_WAITING_FOR_RECAP_AFTER_FT))) { /* No gap */ if (self->mTryToFillGap) { self->mTryToFillGap = 0; dqContext_clearCache (ctx, 0); } /* It is no longer the case that all subscriptions are possibly stale. */ mamaSubscription_unsetAllPossiblyStale (subscription); /* If the sequence numbers for a message are correct then the subscription is OK. */ msgStatus = mamaMsgStatus_statusForMsg (msg); /* Check the status of the message. If it is stale, do not request a recap and do not set status OK. */ if (msgStatus == MAMA_MSG_STATUS_OK) { resetDqState (strategy, ctx); ctx->mSeqNum = seqNum; return MAMA_STATUS_OK; } } /* For late joins or middlewares that support a publish cache, it is possible that you will get old updates in this case take no action */ if (DQ_SCHEME_INGORE_DUPS == mamaTransportImpl_getDqStrategyScheme(tport)) { if ((seqNum <= ctxSeqNum) && ((ctx->mDQState != DQ_STATE_WAITING_FOR_RECAP) && (ctx->mDQState != DQ_STATE_WAITING_FOR_RECAP_AFTER_FT))) { ctx->mDoNotForward = 1; return MAMA_STATUS_OK; } } if ((seqNum == ctxSeqNum) && (ctxDqState != DQ_STATE_WAITING_FOR_RECAP_AFTER_FT)) { /* Duplicate data - set DQQuality to DUPLICATE, invoke quality callback */ ctx->mDQState = DQ_STATE_DUPLICATE; if ((onQuality = (mamaSubscription_getUserCallbacks (subscription))->onQuality)) { void* closure = NULL; const char* symbol = NULL; short cause; const void* platformInfo = NULL; mamaSubscription_getClosure (subscription, &closure); mamaSubscription_getSymbol (subscription, &symbol); mamaSubscription_getAdvisoryCauseAndPlatformInfo ( subscription, &cause, &platformInfo); onQuality (subscription, MAMA_QUALITY_DUPLICATE, symbol, cause, platformInfo, closure); } msgUtils_setStatus (msg, MAMA_MSG_STATUS_DUPLICATE); return MAMA_STATUS_OK; } if (ctxDqState == DQ_STATE_WAITING_FOR_RECAP_AFTER_FT) { ctx->mDoNotForward = 1; return MAMA_STATUS_OK; } else { /* If we get here, we missed a sequence number. */ if ((PRE_INITIAL_SCHEME_ON_GAP==mamaTransportImpl_getPreInitialScheme(tport)) &&(self->mTryToFillGap)) { self->mTryToFillGap = 0; if (dqContext_fillGap (ctx, seqNum, subscription)) { /* we filled it */ dqContext_clearCache (ctx, 0); ctx->mSeqNum = seqNum; return MAMA_STATUS_OK; } dqContext_clearCache (ctx, 0); } if (gMamaLogLevel >= MAMA_LOG_LEVEL_FINE) { const char* symbol = NULL; mamaSubscription_getSymbol (subscription, &symbol); symbol = symbol == NULL ? "" : symbol; mama_log (MAMA_LOG_LEVEL_FINE, "%s : SeqNum gap (%ld-%ld)", symbol, ctxSeqNum+1, seqNum-1); } if ((onGap = (mamaSubscription_getUserCallbacks (subscription)->onGap))) { void* closure = NULL; mamaSubscription_getClosure (subscription, &closure); onGap (subscription, closure); } handleStaleData (self, msg, ctx); } break; case MAMA_MSG_TYPE_INITIAL : case MAMA_MSG_TYPE_BOOK_INITIAL : msgStatus = MAMA_MSG_STATUS_UNKNOWN; self->mTryToFillGap = 1; msgStatus = mamaMsgStatus_statusForMsg (msg); /* Check the status of the message. If it is stale, do not request a recap and do not set status OK. */ if ((msgStatus == MAMA_MSG_STATUS_POSSIBLY_STALE) || (msgStatus == MAMA_MSG_STATUS_STALE)) { ctx->mDQState = DQ_STATE_STALE_NO_RECAP; dqStrategyImpl_resetDqContext (ctx, seqNum, senderId); return MAMA_STATUS_OK; } case MAMA_MSG_TYPE_RECAP : case MAMA_MSG_TYPE_BOOK_RECAP : /* For late joins or middlewares that support a publish cache, it is possible that you will get old updates in this case take no action */ if (DQ_SCHEME_INGORE_DUPS == mamaTransportImpl_getDqStrategyScheme(tport)) { if (MAMA_MSG_TYPE_RECAP == msgType) { /* Feed-handlers maintain sequence number for a Record FT Recap. */ if ((seqNum <= ctxSeqNum) && ((ctx->mDQState != DQ_STATE_WAITING_FOR_RECAP) && (ctx->mDQState != DQ_STATE_WAITING_FOR_RECAP_AFTER_FT))) { ctx->mDoNotForward = 1; return MAMA_STATUS_OK; } } else if (MAMA_MSG_TYPE_BOOK_RECAP == msgType) { if (0 == seqNum && ctxSeqNum > 0) { /* Special case of an FT Order Book Recap where a SeqNum of 0 is used. */ if (ctx->mDQState != DQ_STATE_WAITING_FOR_RECAP_AFTER_FT) { ctx->mDoNotForward = 1; return MAMA_STATUS_OK; } } /* Solicited Recap from Feed-Handler or * solicited / unsolicited Recap from mid-tier. */ else if ((seqNum <= ctxSeqNum) && ((ctx->mDQState != DQ_STATE_WAITING_FOR_RECAP) && (ctx->mDQState != DQ_STATE_WAITING_FOR_RECAP_AFTER_FT))) { ctx->mDoNotForward = 1; return MAMA_STATUS_OK; } } } if (mamaTransportImpl_preRecapCacheEnabled (tport)) { self->mTryToFillGap = 1; } mamaSubscription_unsetAllPossiblyStale (subscription); resetDqState (strategy, ctx); dqStrategyImpl_resetDqContext (ctx, seqNum, senderId); ctx->mDoNotForward = 0; return MAMA_STATUS_OK; case MAMA_MSG_TYPE_DDICT_SNAPSHOT : /*No DQ checking for Datadictionary*/ return MAMA_STATUS_OK; } return MAMA_STATUS_OK; }