Source unavailable message always popup when starting program everytime.

Client is in TREP environment , everytime when client start the program to fetch items.

The program get "Source unavailable" messages several times after the "all is well received" message received.

image

Tagged:

Best Answer

  • @jessie.lin

    The "Source unavaiable" status generally is created by RFA to inform that the data's status is suspect because the requested service is down or unavailable and the item will be recovered when the service is up.

    This log should be from the scenario that application requests item before the connection is establised so the requested service was not avialable at that time. This commonly be found in the application such as "StarterConsumer" example that request item imediately after login request without verifying service status.

    With regard to the "received invalid item data from server." message, the message should not be received from API/feed. I understand that the message is the application's message. Is this correct?

Answers

  • Below is the snippet example code based on StarterConsumer to verify Service Status to solve this issue.


    Step 1: Send the Directory Request after received login success response.

    Handle* StarterConsumer::sendDirectoryRequest()
    {
    ReqMsg reqMsg;
    AttribInfo attribInfo;
    Handle* dirHandle;
    OMMItemIntSpec ommItemIntSpec;
    // To request a specific service directory, set the serviceName on the request as follows:
    // attribInfo.setServiceName( RFA_String( "XYZ_SERVICE", 0, false) );
    // Otherwise, the request by default will be for all available services.
    reqMsg.setMsgModelType(MMT_DIRECTORY);
    reqMsg.setInteractionType(ReqMsg::InitialImageFlag | ReqMsg::InterestAfterRefreshFlag);
    attribInfo.setServiceName(_cfgVars.serviceName);//Optional: Set the service name in request//
    attribInfo.setDataMask(rfa::rdm::SERVICE_INFO_FILTER | rfa::rdm::SERVICE_STATE_FILTER);
    reqMsg.setAttribInfo(attribInfo);
    ommItemIntSpec.setMsg(&reqMsg);

    AppUtil::log(__LINE__, AppUtil::TRACE, "Create Directory Request %s", _cfgVars.serviceName.c_str());
    dirHandle = _pOMMConsumer->registerClient(_pEventQueue, &ommItemIntSpec, *this, NULL);
    return dirHandle;
    }


    Step 2: Add the Directory response process, at this step we will send Item Request after we have received the Directory response.

    void StarterConsumer::processRespMsg(const rfa::sessionLayer::OMMItemEvent& event, const RespMsg& respMsg)
    {
    switch(respMsg.getMsgModelType())
    {
    case MMT_LOGIN:
    processLoginResponse(event, respMsg);
    break;
    case MMT_MARKET_PRICE:
    processMarketPriceResponse(event, respMsg);
    break;
    case MMT_DIRECTORY:
    processDirectoryResponse(event, respMsg);//Add the Directory Response handle
    break;
    default:
    AppUtil::log(__LINE__, AppUtil::WARN, "<- Received unhandled OMMItemEvent msgModelType: %u", (UInt32)respMsg.getMsgModelType());
    break;
    }
    }

    void StarterConsumer::processDirectoryResponse(const rfa::sessionLayer::OMMItemEvent& event, const RespMsg& respMsg)
    {
    RespStatus respStatus = respMsg.getRespStatus();
    // Check if we have refresh complete
    if (respMsg.getIndicationMask() & RespMsg::RefreshCompleteFlag)
    {
    // Check if the stream is open
    if (respMsg.getHintMask() & RespMsg::RespStatusFlag &&
    respStatus.getStreamState() == RespStatus::OpenEnum)
    {
    // Check if we have a usable payload
    if ((respMsg.getHintMask() & RespMsg::PayloadFlag) && !respMsg.getPayload().isBlank())
    {
    AppUtil::log(__LINE__, AppUtil::TRACE, "Received Directory Response");

    _pDecoder->decodeData(respMsg.getPayload());// TO-DO: Client can process the service status here//
    sendItemRequest(_cfgVars.itemName, _cfgVars.serviceName);
    }
    }
    }
    }

    This should have resolve the "Source unavailable" in case of service state on server side is actually up!


  • But for the completion, we can go further by checking that Service Status is actually up and ready for you to request items


    Step 3: Decode Directory Response and check the Service State before sending Item Request, (Optional, but actually is the right thing to do), we will replace the TO-DO code in the Step 2)

    //_pDecoder->decodeData(respMsg.getPayload());// TO-DO: Client can process the service status here//
    //sendItemRequest(_cfgVars.itemName, _cfgVars.serviceName);

    RFA_String testService = _cfgVars.serviceName;
    UInt serviceState = 0;
    UInt acceptingRequest = 0;
    RespStatus stateStatus;
    UInt stateStatusFlag = 0;
    bool result = false;
    stateStatus.clear();

    result = getDirectoryServiceState(respMsg.getPayload(), testService, &serviceState, &acceptingRequest, &stateStatus, &stateStatusFlag);
    if (result == true)
    {
    AppUtil::log(__LINE__, AppUtil::TRACE, "Service: %s, ServiceState: %d, AcceptingRequest: %d, stateStatus: %s, stateStatusFlag", testService.c_str(), serviceState, acceptingRequest, stateStatus.getStatusText().c_str(), stateStatusFlag);

    if(serviceState == 1 && acceptingRequest == 1)
    {
    sendItemRequest(_cfgVars.itemName, _cfgVars.serviceName);// Send item request//
    AppUtil::log(__LINE__, AppUtil::TRACE, "Send item request");
    }
    }
    else
    {
    AppUtil::log(__LINE__, AppUtil::TRACE, "Service: %s not found", testService.c_str());
    }


    This function is an example of how to decode and get the Service State and Accepting Request of the specified Service Name from Directory Response.

    Note that our code is just an example serves as a guideline, the errors are omitted.

    bool getDirectoryServiceState(const Data& inputData, const RFA_String service_name, UInt* _serviceState, UInt* _acceptingRequests, RespStatus* _stateStatus, UInt* _stateStatusFlag)
    {
    const Map& input = static_cast <const Map&>(inputData);
    int outputchecker = 0;
    bool result = false;
    MapReadIterator itMap;
    itMap.start(input);
    // decode entries
    while (!itMap.off())
    {
    const MapEntry& mapEntry = static_cast <const MapEntry&>(itMap.value());
    RFA_String _serviceName = static_cast<const DataBuffer&> (mapEntry.getKeyData()).getAsString();

    if (_serviceName == service_name)// found service name
    {
    if (mapEntry.getData().getDataType() != FilterListEnum)
    {
    //ERROR Expected data datatype of FilterList
    return result;
    }
    const FilterList& filterList = static_cast<const FilterList&>(mapEntry.getData());
    FilterListReadIterator flRI;
    flRI.start(filterList);
    while (!flRI.off())
    {
    const FilterEntry& filterEntry = flRI.value();
    if (filterEntry.getFilterID() == SERVICE_STATE_ID)
    {
    if (filterEntry.getData().getDataType() != ElementListEnum)
    {
    //ERROR Expected data datatype of ElementList
    return result;
    }
    const ElementList& elementList = static_cast<const ElementList&>(filterEntry.getData());
    ElementListReadIterator elReadIter;
    elReadIter.start(elementList);
    while (!elReadIter.off())
    {
    const ElementEntry& element = elReadIter.value();
    const RFA_String& elementName = element.getName();

    // get ServiceState - UInt
    if (elementName == ENAME_SVC_STATE)
    {
    *_serviceState = (static_cast<const DataBuffer&> (element.getData())).getUInt();
    outputchecker |= 1;
    }
    // get AcceptingRequests - UInt
    else if (elementName == ENAME_ACCEPTING_REQS)
    {
    *_acceptingRequests = (static_cast<const DataBuffer&> (element.getData())).getUInt();
    outputchecker |= 2;
    }
    // get AcceptingRequests - RespStatus
    else if (elementName == ENAME_STATUS)
    {
    *_stateStatus = (static_cast<const DataBuffer&> (element.getData())).getRespStatus();
    *_stateStatusFlag = true;
    outputchecker |= 4;
    }

    if (outputchecker == (1 | 2 | 4))
    {
    return true;
    }
    elReadIter.forth();
    }
    }
    flRI.forth();
    }
    }
    itMap.forth();
    }
    }


  • For more information about this please refer to

    RFA C++ Tutorial 9 (Directory message) and RFA C++ Tutorial 10 (Steps to request item after received Directory and Dictionary)