Beispiel #1
0
void MAMACALLTYPE
subscriptionOnMsg  (mamaSubscription subscription,
                    mamaMsg msg,
                    void *closure,
                    void *itemClosure)
{
    pubCache* cache = (pubCache*) closure;
    switch (mamaMsgType_typeForMsg (msg))
    {
    case MAMA_MSG_TYPE_DELETE:
    case MAMA_MSG_TYPE_EXPIRE:
        mamaSubscription_destroy (subscription);
        mamaSubscription_deallocate (subscription);
        if (cache->pub)
            mamaDQPublisher_send(cache->pub, msg);
        cache->sub = NULL;
        return;
    default:
        break;
    }

    switch (mamaMsgStatus_statusForMsg (msg))
    {
    case MAMA_MSG_STATUS_BAD_SYMBOL:
    case MAMA_MSG_STATUS_EXPIRED:
    case MAMA_MSG_STATUS_TIMEOUT:
        mamaSubscription_destroy (subscription);
        mamaSubscription_deallocate (subscription);
        if (cache->pub)
            mamaDQPublisher_send(cache->pub, msg);
        cache->sub = NULL;
        return;
    default:
        break;
    }

    mamaMsg_applyMsg(cache->cachedMsg, msg);

    if (cache->pub)
    {
        mamaDQPublisher_setStatus(cache->pub, mamaMsgStatus_statusForMsg (msg));
        mamaDQPublisher_send(cache->pub, msg);
    }

    fflush(stdout);
}
static void 
processMsg( mamaDictionary dictionary, const mamaMsg msg )
{
    mamaMsgStatus     msgStatus = -1;
    mamaMsgType       msgType = -1;

    msgStatus = mamaMsgStatus_statusForMsg( msg ); 
    msgType   = mamaMsgType_typeForMsg( msg );

    if( msgStatus == MAMA_MSG_STATUS_TIMEOUT )
    {
        self->mCallbackSet.onTimeout( dictionary, self->mClosure );
        return;
    }

    if( msgStatus != MAMA_MSG_STATUS_OK && 
        msgType   != MAMA_MSG_TYPE_DDICT_SNAPSHOT &&
        msgType   != MAMA_MSG_TYPE_UPDATE ) 
    {
        char errBuf[1024];

        snprintf( errBuf, 1023, "Error: mamaDictionary: unexpected "
                                    "MsgType/MsgStatus: %s/%s\n",
               mamaMsgType_stringForType(msgType),
               mamaMsgStatus_stringForStatus(msgStatus));

        self->mCallbackSet.onError( dictionary, errBuf, self->mClosure );
        return;
    }

    mamaDictionary_buildDictionaryFromMessage( dictionary, msg );

    mamaSubscription_destroy (self->mSubscription);
    mamaSubscription_deallocate (self->mSubscription);
    self->mSubscription = NULL;

    /* do this last in case the dictionary transport is destroyed
       in the callback */
    self->mCallbackSet.onComplete( dictionary, self->mClosure );
}
Beispiel #3
0
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;
}