question

Upvotes
Accepted
13 3 4 7

Is there a way to get a specific field entry from the field list without having to go through the entire fieldList that is received?

When receiving market price data as a consumer, I am wanting to first find the context id of the symbol being requested without having to decode each entry individually. Is there a way to do this?My initial though process was to us RsslMap instead RsslFieldList but that does not look like a viable option. Also, I was thinking of making a set that would contain just CONTEXT_ID in order to ensure that is decoded first and then decode the rest of the entries in a separate list. Am I on the right track by doing this?

elektronrefinitiv-realtimeelektron-sdkrrteta-apielektron-transport-apirssl
icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Upvotes
Accepted
4.4k 10 6 9

Hi @manning0218

With the way OMM/RWF data work, it is not possible to find a specific field without iterating through the list.

However, you can iterate through the list without having to decode the content of each entry. Which means you could simply do something like this:

do {
	retCode = rsslDecodeFieldEntry( &_decodeIter, &_rsslFieldEntry );
	if ( retCode == RSSL_RET_END_OF_CONTAINER )
	{
		return false;
	}
}
while (	_rsslFieldEntry.fieldId != fieldId );

But remember that you have to reset the iterator when you decide to decode the rest of the entries.

rsslClearDecodeIterator( &_decodeIter );

RsslRet retCode = rsslSetDecodeIteratorBuffer( &_decodeIter, &_rsslFieldListBuffer );
if ( RSSL_RET_SUCCESS != retCode )
{
	// Error
	return;
}

retCode = rsslSetDecodeIteratorRWFVersion( &_decodeIter, _rsslMajVer, _rsslMinVer );
if ( RSSL_RET_SUCCESS != retCode )
{
	// Error
	return;
}

retCode = rsslDecodeFieldList( &_decodeIter, &_rsslFieldList, _rsslLocalFLSetDefDb );

Also, I would like to point out that you cannot cast OMM/RWF container of one type into another. So using RsslMap instead RsslFieldList is definitely not a viable option.

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Upvotes
24 5 3 14

I would like to reopen this query to find out if there is any other efficient way using API where I can extract context id with out having to reset and decode the message again.

Just to reiterate: my use case is to extract the context id before iterating through the field list to apply our field mapping rules.

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Upvotes
12.1k 59 39 61

Hi @RAJ,

There is a way to process the message buffer that only requires you to iterate once. Because the Context ID lives within the body of the message, you will have to iterate through to pull out this data. However, the mechanism to optimize processing is to store a reference of the data to a hash table for each fid as you iterate.

For example, the algorithm is basically:

  • Iterate through the buffer
  • For each entry you encounter, add the element, keyed by the fid to a hash table.
    • It's important to note, you are not copying the data to a hash table, but instead a pointer to the data is added to the hash table
  • As you iterate through, you could optionally look for Context ID at this point. Or you could pull out the Context ID from the hash once you complete iteration.
    • Note: if you extract the context ID while iterating, you could possibly determine which FIDs you need to process for the remaining of the iteration — this optimizes processing
  • Once iteration completes, you simply pull out the fids of choice based on the context ID from your hash map.

For example, I took one of the tutorials (ETA C - Tutorial 4) and updated the basicMsgHandler.c file. When you look at my changes below, I basically iterate through the message and capture each fid within a hash table. Once iteration was complete, I simply display specific FIDs to demonstrate.

/* decode each field entry in list */
while ((ret = rsslDecodeFieldEntry(dIter, &fEntry)) != RSSL_RET_END_OF_CONTAINER) {
    if (ret == RSSL_RET_SUCCESS)
	fieldTable.insert(Fid_Map_Pair(fEntry.fieldId, 
                          Fid_Data_Pair(fEntry.encData.length, 
                          fEntry.encData.data)));
}
if (ret == RSSL_RET_END_OF_CONTAINER) {
    displayData(fieldTable, 3, dictionary);
    displayData(fieldTable, 6, dictionary);

    return RSSL_RET_SUCCESS;
}

The code to display the specific FID is:

void displayData(FID_MAP& fieldTable, RsslFieldId fid, RsslDataDictionary *dictionary)
{
    // Based of the FID, retrieve the data and decode 
    RwfBuffer encData;
    if (retrieveData(fieldTable, fid, encData))
    {
	RsslDecodeIterator dIter;
	rsslClearDecodeIterator(&dIter);
	rsslSetDecodeIteratorBuffer(&dIter, &encData);

	decodeFieldEntry(dictionary, fid, &dIter);
    }
}

The code to retrieve the data from the hash:

bool retrieveData(FID_MAP& table, RsslFieldId fid, RwfBuffer& encData)
{
    FID_MAP::iterator itr = table.find(fid);
    if (itr != table.end()) {
	encData.length = itr->second.first;
	encData.data = itr->second.second;
    }
    return(itr != table.end());
}

It's worth noting that iterating over the payload is a fairly quick and light weight operation. The overhead to skip fields is essentially a byte swap and an add to a pointer.

Hope this helps,

icon clock
10 |1500

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.