The Handler exposes the following major events: Exchange message received, Order Book Changed, Handler (Feed) state changed, and Error occurred.
The Exchange message received event is fired by the Handler when a subscription is started. The Handler calls the associated listener (event handler) for each message it receives. Invocation of the event handler is not guaranteed to occur on a single thread: product-definition messages retrieved during security-definition recovery are delivered from an internal security-definition thread, while messages received over multicast are delivered from the Feed Engine worker thread(s). See the Threading Model topic for details. The product-definition messages retrieved during security-definition recovery (over TCP) stop once that recovery finishes. Option, strategy, and expiry definitions that arrive over multicast, along with all other market-data messages, keep being delivered on the subscribed markets for as long as the subscription remains active.
The Order Book changed event is raised by the Handler in response to notifications from the Multicast Price Feed about added or modified orders, changes in price levels, executed trades, and other events. Events of this type occur only when the subscription is active. The associated listener will never be called before Handler::start succeeds, and after the subscription is stopped using the Handler::stop member. These callbacks are delivered on the Feed Engine worker thread(s); see the Threading Model topic for the synchronization guarantees when more than one worker thread is used.
The Handler (Feed) state changed event is raised by the Handler when the handler's or feed's state changes.
The Error occurred event is fired by the Handler when an error condition is met. This could be a generic error, such as an inability to write to a log file, or a failure scenario, such as receiving a message from the Multicast Price Feed with an invalid sequence number. This event is raised by the Handler only when a subscription is active.
For each of these events, Handler provides an interface (C++ class with virtual members) like ErrorListener, which has to be implemented to handle the event and a member like Handler::registerErrorListener, which allows an instance of the event handler to be associated with an appropriate event in the scope of a particular ICE iMpact Handler.
The table below depicts the correspondence between events and listeners interface:
To register a particular listener there are corresponding registerListener() member of the Handler class:
The exchange groups market data messages into multicast message blocks. Every block starts with a header reporting the feed session number, the sequence number, the number of messages in the block, and the time the exchange sent the block.
When a feed has no market data to publish, the exchange keeps sending blocks that consist of a header only. Such blocks are called empty blocks, or heartbeats. They carry no messages, but their headers still report the exchange send time, so they remain a source of feed timing information for markets that trade rarely.
By default, the Handler does not report empty blocks: FeedListener::onMulticastMessageBlockBegin and FeedListener::onMulticastMessageBlockEnd are raised only for blocks that contain at least one message.
Set HandlerSettings::notifyOnEmptyMulticastMessageBlocks to true before constructing the Handler to have both events raised for empty blocks as well. In that case:
An empty block does not advance the sequence number the feed expects, so consecutive empty blocks all carry the same sequence number. While a feed is delivering normally the Handler reports each of them, including copies of the same block received over more than one network interface. Use MessageInfo::rawSentTime to tell them apart; do not treat the number of events as a count of what the exchange sent.
The option applies to live, snapshot and replayed feeds alike. Enabling it increases the number of event invocations on the Feed Engine worker threads, because every feed keeps sending empty blocks while it is idle.
A feed is not always delivering normally, and an empty block carries nothing the Handler can recover from, so it is dropped rather than deferred whenever the feed has something more pressing in hand:
So on a feed that is delivering normally, every empty block it receives is reported, and the send time each one carries is the exchange's own timestamp for a block that has only just arrived. That is the property the option exists to provide. It does not extend to a queued feed, whose one buffered block is reported when the queue is replayed and carries a send time as old as the recovery.
The following sample demonstrates how to receive notifications about errors that occur in the Handler: