Defining the transport function table
The EventTransport.h header file provides a definition for an AP_EventTransport_Functions structure. This defines a function table whose elements must be set to point to the implementations of the above functions. Its definition is as follows:
/**
* AP_EventTransport_Functions
*
* Table of client visible functions exported by a transport library
* instance. These functions declare the only operations that may be
* performed by users of a transport.
*
* Note that all of these functions take an initial AP_EventTransport*
* argument; this is analogous to the (hidden) 'this' pointer passed to
* a C++ object when a member function is invoked on it.
*/
struct AP_EventTransport_Functions {
/**
* updateProperties
*
* Update the configuration of the transport. The transport may assume
* that stop(), flushUpstream() and flushDownstream() have all been called
* before this function is invoked. The recommended procedure for
* updating properties is to first compare the new property set with the
* existing stored properties -- if there are no changes, no action should
* be taken. Any pointer to the old property set becomes invalid as soon
* as this function returns; any such pointers should therefore be
* discarded in favour of the supplied new properties.
*
* @param transport The event transport instance
* @param properties The new transport property set derived from the IAF
* configuration file
* @param timestampConfig Timestamp recording/logging settings
* @return Event transport error code. If this is not
* AP_EventTransport_OK, the getLastError() function should be called to
* get a more detailed description of what went wrong.
*/
AP_EventTransportError (*updateProperties)(
struct AP_EventTransport* transport,
AP_EventTransportProperties* properties,
IAF_TimestampConfig* timestampConfig);
/**
* sendTransportEvent
*
* Called by an event encoder to send a message to the external transport.
* It is assumed that the encoder and transport share the same definition
* of the content of the event, so that the transport can effectively
* interpret the event and free any dynamically-allocated memory.
*
* @param transport The event transport instance
* @param event The event to be sent on the external transport. Ownership
* is transferred to the callee.
* @param timeStamp Timestamps associated with this event. Ownership is
* transferred to the callee.
* @return Event transport error code. If this is not
* AP_EventTransport_OK, the getLastError() function should be called to
* get a more detailed description of what went wrong.
*/
AP_EventTransportError (*sendTransportEvent)(
struct AP_EventTransport* transport,
AP_TransportEvent event,
AP_TimestampSet* timeStamp);
/**
* addEventDecoder
*
* Add a named event decoder to the set of decoders known to the
* transport. If the named decoder already exists, it should be
* replaced.
*
* @param transport The event transport instance
* @param name The name of the decoder to be added
* @param decoder The decoder object itself
*/
void (*addEventDecoder)(struct AP_EventTransport* transport,
const AP_char8* name, struct AP_EventDecoder* decoder);
/**
* removeEventDecoder
*
* Remove a named event decoder from the set of decoders known to the
* transport. If the named decoder does not exist, the function should do
* nothing.
*
* @param transport The event transport instance
* @param name The decoder to be removed
*/
void (*removeEventDecoder)(struct AP_EventTransport* transport,
const AP_char8* name);
/**
* flushUpstream
*
* Flush any pending normalized events onto the external transport. The
* transport may assume that the stop() function has been called before
* this function, so in many cases no action will be required to complete
* the flushing operation.
*
* @param transport The event transport instance
* @return Event transport error code. If this is not
* AP_EventTransport_OK, the getLastError() function should be called to
* get a more detailed description of what went wrong.
*/
AP_EventTransportError (*flushUpstream)(
struct AP_EventTransport* transport);
/**
* flushDownstream
*
* Flush any pending transport events into the decoder. The transport may
* assume that the stop() function has been called before this function,
* so in many cases no action will be required to complete the flushing
* operation. Under no circumstances should any events be sent to the
* Correlator after flushDownstream() has returned.
*
* @param transport The event transport instance
* @return Event transport error code. If this is not
* AP_EventTransport_OK, the getLastError() function should be called to
* get a more detailed description of what went wrong
*/
AP_EventTransportError (*flushDownstream)(
struct AP_EventTransport* transport);
/**
* start
*
* Establish a connection and start processing incoming data from the
* external transport.
*
* An adapter should send events to the correlator only after its start()
* method is called and before the stop() method returns. Therefore we
* strongly recommend that a transport should not change to a state where
* it is possible to receive events from any external transport until the
* start() method has been called. In many cases, adapters will also need
* to communicate with service monitors in the correlator to ensure that
* the required monitors and event definitions are injected before they
* begin to process messages from the external system. This is necessary in
* order to avoid events from the adapter being lost if the correlator is
* not yet ready to parse and process them.
*
* @param transport The event transport instance
* @return Event transport error code. If this is not
* AP_EventTransport_OK, the getLastError() function should be called to
* get a more detailed description of what went wrong.
*/
AP_EventTransportError (*start)(struct AP_EventTransport* transport);
/**
* stop
*
* Stop processing incoming data from the external transport, typically
* by pausing or closing down connections.
*
* Adapter authors must ensure that no events are sent to the Correlator
* after stop() has returned (the only exception being rare cases where the
* transport sends buffered events in the Correlator in the
* flushDownstream() method, which is called by the IAF after stop()).
* If necessary any messages that are unavoidably received from the
* transport after stop() has returned should be blocked, queued or simply
* dropped.
*
* @param transport The event transport instance
* @return Event transport error code. If this is not
* AP_EventTransport_OK, the getLastError() function should be called to
* get a more detailed description of what went wrong.
*/
AP_EventTransportError (*stop)(struct AP_EventTransport* transport);
/**
* getLastError
*
* Return the transport's stored error message, if any. The message
* string is owned by the transport so should not be modified or freed by
* the caller.
*
* @param transport The event transport instance
* @return The last error message generated by the transport
*/
const AP_char8* (*getLastError)(struct AP_EventTransport* transport);
/**
* getStatus
*
* Fill in the supplied AP_EventTransportStatus structure with up-to-date
* status information for the transport. Note that any data pointed to by
* the returned structure (such as strings) remains owned by the
* transport. The caller must copy this data if it wishes to modify it.
*
* @param codec The event transport instance
* @param status The status structure to be filled in
*/
void (*getStatus)(struct AP_EventTransport* transport,
AP_EventTransportStatus* status);
};
Note that the order of the function pointers within the function table is critical to the reliable operation of the IAF. However, the order that the function definitions appear within the plug-in source code, and indeed the names of the functions, are not important. Apama recommends that the functions be declared static, so that they are not globally visible and can only be accessed via the function table.
It is therefore not obligatory to implement the functions documented above with the same names as per the definitions, as long as the mapping is performed correctly in an instantiation of AP_EventTransport_Functions. A definition in an event transport implementation would look as follows:
/**
* Function table for the AP_EventTransport interface. The address of this
* structure must be placed in the 'functions' field of the AP_EventTransport
* object.
*/
static struct AP_EventTransport_Functions EventTransport_Functions
= {
updateProperties,
sendTransportEvent,
addEventDecoder,
removeEventDecoder,
flushUpstream,
flushDownstream,
start,
stop,
getLastError,
getStatus
};
The function table created above needs to be placed in an AP_EventTransport object. The definition of this structure is as follows:
/**
* External (client-visible) interface to an IAF TIL plugin library. The
* AP_EventTransport struct contains a table of function pointers, declared in
* the AP_EventTransport_Functions struct above. The implementation of these
* functions is private. Users of the transport library should invoke
* functions on it as in the following example (transport is of type
* AP_EventTransport*):
*
* i = transport->functions->sendTransportEvent(mapper, event, timestamp);
*/
struct AP_EventTransport {
void* reserved;
struct AP_EventTransport_Functions* functions;
};
and one such object needs to be created for every plug-in within its constructor function. Its first element, reserved, is a placeholder for any private data that the transport layer requires.