Events

Events are heavily leveraged by REDHAWK to provide system awareness and exchange both synchronous and asynchronous data. This chapter describes the mechanics of creating and consuming events as well as standard event types defined in REDHAWK and how they are used. The methodology used to exchange synchronous and asynchronous data, although reliant on events as the communications mechanism, is discussed in Messaging.

Event Definition

CORBA defines an interface for the transport of events as well as an interface for the creation of event channels that can support a publish/subscribe pattern; within REDHAWK, publishers are often described as producers, and subscribers are often described as consumers.

In REDHAWK, an event is defined as the payload sent on a single call to the push() function in the PushConsumer interface of the CosEventComm Interface Description Language (IDL) module.

The PushConsumer interface is as follows:

interface PushConsumer {
    void push (in any data) raises(Disconnected);
    void disconnect_push_consumer();
};

The description of the EventChannel interface and its use is complicated but luckily unnecessary for the use of events in REDHAWK. Channels provide a logical association between a plain text string (channel name) and an object that implements the interfaces necessary to interconnect producers and consumers. The channel name cannot contain periods or colons and may not be an empty string. CosEventChannelAdmin::EventChannel, the EventChannel interface allows a producer or consumer to register itself with the event channel. This registration process gives the producer a reference to a virtual consumer where events can be pushed (recall that at the end of the day, CORBA is just an RPC mechanism). The registration process allows the consumer to give a reference to itself to a virtual producer, so that when an event becomes available, the correct function is invoked in the consumer. It is the job of the implementer of the EventChannel interface, also known as an Event Service, to maintain the registration interface as well as the different virtual producers and consumers necessary to re-direct all events to their appropriate destinations. The program omniEvents implements the EventChannel interface and enables the publish/subscribe pattern as described above; REDHAWK uses omniEvents as its Event Service.

An interesting aspect of the EventChannel interface is that there is no reason why that interface is implemented on a single central event broker. It is possible to create a consumer that implements both a consumer interface and the EventChannel interface. This allows that consumer to consume events either directly from a producer or indirectly through an Event Service. While a central event broker like omniEvents allows for the fluid addition of producers and consumers into the domain, the inherent latency to the distribution of the event can be significant (a single call for the publishing of the event, an intermediate process queuing that event, and then one or more pushes for the distribution of the event to one or more consumers). On the other hand, a point-to-point connection between a producer and a consumer removes the intermediary broker and enables low-latency messaging between components. In REDHAWK, low-latency point-to-point events are used only on messages, which are described in Messaging.

Standard REDHAWK Events

REDHAWK has defined several standard event types that can be used to monitor the overall state of a domain or individual components. The system management events are sent over the domain management channels. Individual component events are associated with property changes.

REDHAWK defines an Outgoing Domain Management (ODM) channel as well as an Incoming Domain Management (IDM) channel. The ODM channel contains events that are generated by the Domain Manager which indicate the addition or removal of entities to and from the domain. The IDM channel contains events that are generated by devices which indicate changes in the state of a device.

ODM Channel

The ODM channel contains event types used to describe the addition or removal of objects from the domain:

struct DomainManagementObjectAddedEventType {
  string producerId;
  string sourceId;
  string sourceName;
  StandardEvent::SourceCategoryType sourceCategory;
  Object sourceIOR;
};
struct DomainManagementObjectRemovedEventType {
  string producerId;
  string sourceId;
  string sourceName;
  StandardEvent::SourceCategoryType sourceCategory;
};

Either event contains information as to who had something added/removed to/from it, the ID of the entity that was added/removed, the name of the entity that was added/removed, and the category of item that was added/removed. In the case of an added object, the Interoperable Object Reference (IOR) (stringified pointer to the object) is included in the event.

The category of item that was added or removed is of type SourceCategoryType, which is defined as:

enum SourceCategoryType {
  DEVICE_MANAGER,
  DEVICE,
  APPLICATION_FACTORY,
  APPLICATION,
  SERVICE
};

The ODM channel can also contain an event type used to describe the state change of a resource, like an application:

struct ResourceStateChangeEventType {
  string sourceId;
  string sourceName;
  ExtendedEvent::ResourceStateChangeType stateChangeFrom;
  ExtendedEvent::ResourceStateChangeType stateChangeTo;
}

where ExtendedEvent::ResourceStateChangeType is defined as:

enum ResourceStateChangeType {
  STOPPED,
  STARTED
}

IDM Channel

The IDM channel can contain a StateChangeEventType event or a AbnormalComponentTerminationEventType event. The StateChangeEventType event is defined as:

struct StateChangeEventType {
  string producerId;
  string sourceId;
  StandardEvent::StateChangeCategoryType stateChangeCategory;
  StandardEvent::StateChangeType stateChangeFrom;
  StandardEvent::StateChangeType stateChangeTo;
};

The producerId and sourceId of the event type are redundant; they are both the id of the device that is issuing the event.

The StateChangeCategoryType and StateChangeType are:

enum StateChangeCategoryType {
  ADMINISTRATIVE_STATE_EVENT,
  OPERATIONAL_STATE_EVENT,
  USAGE_STATE_EVENT
};
enum StateChangeType {
  LOCKED,
  UNLOCKED,
  SHUTTING_DOWN,
  ENABLED,
  DISABLED,
  IDLE,
  ACTIVE,
  BUSY
};

The two enumerated types are closely linked; an ADMINISTRATIVE_STATE_EVENT can only contain states LOCKED, UNLOCKED, and SHUTTING_DOWN, while an OPERATIONAL_STATE_EVENT can only contain states ENABLED and DISABLED, and a USAGE_STATE_EVENT can only contain states IDLE, ACTIVE, or BUSY.

The AbnormalComponentTerminationEventType event is defined as:

struct AbnormalComponentTerminationEventType {
  string deviceId;
  string componentId;
  string applicationId;
};

This event is triggered when a component abnormally terminates. The event contains the device ID that is producing the event, the component ID that terminated abnormally, and the application ID that hosts that component.

Property Change Events

Whenever a property changes on a component or device, either through the internal update of the component property or through an external configuration update, an event can be triggered. Any consumer can be registered onto any component or device to listen to any arbitrary set of properties that the component or device may have.

The event type is PropertyChangeEvent, which is defined as:

struct PropertyChangeEvent {
  string evt_id;
  string reg_id;
  string resource_id;
  CF::Properties properties;
};

Consuming Events

Event consumption is meant as a system-level monitoring process. Therefore, REDHAWK does not include component ports that allow the consumption of these events. To monitor events over a given channel, a simple API is available. The Domain Manager contains the function registerWithEventChannel() to register a consumer to a given channel and unregisterFromEventChannel() to unregister a consumer from an event channel.

A command-line tool is available that registers with event channels and displays the contents of the channel, eventviewer. The arguments to eventviewer are the name of the domain and the name of the channel.

An example of the use of eventviewer is described below:

  1. Start a Domain Manager:

    nodeBooter -D
  2. In a new terminal, attach the eventviewer to the domain's ODM channel:

    eventviewer REDHAWK_DEV ODM_Channel
    Receiving events. Press 'enter' key to exit
  3. In a new terminal, start a Device Manager:

    nodeBooter -d $SDRROOT/dev/nodes/DevMgr_localhost-localdomain/DeviceManager.dcd.xml
  4. On the Eventviewer terminal, the Device Manager and device registration are shown:

    eventviewer REDHAWK_DEV ODM_Channel
    Receiving events. Press 'enter' key to exit
    {'sourceId': 'DCE:83f3c741-19bf-4794-877f-0322cd62290a','sourceName': 'DevMgr_localhost-localdomain', 'sourceIOR': <ossie.cf.CF._objref_DeviceManager instance at 0x25160e0>, 'sourceCategory': DEVICE_MANAGER, 'producerId': 'DCE:516aa867-e262-4c70-8355-db415f4b0fc6'}
    {'sourceId': 'DCE:f5781785-9dd7-4873-8f30-99d7e2ca1a8f', 'sourceName': 'GPP_localhost_localdomain', 'sourceIOR': <ossie.cf.CF._objref_AggregateExecutableDevice instance at 0x2d46638>, 'sourceCategory': DEVICE, 'producerId': 'DCE:516aa867-e262-4c70-8355-db415f4b0fc6'}
  5. Shutdown the Device Manager (Ctrl+C on the Device Manager terminal)

  6. On the Eventviewer terminal, the device and Device Manager unregistration is displayed:

    eventviewer REDHAWK_DEV ODM_Channel
    Receiving events. Press 'enter' key to exit
    {'sourceId': 'DCE:83f3c741-19bf-4794-877f-0322cd62290a', 'sourceName': 'DevMgr_localhost-localdomain', 'sourceIOR': <ossie.cf.CF._objref_DeviceManager instance at 0x25160e0>, 'sourceCategory': DEVICE_MANAGER, 'producerId': 'DCE:516aa867-e262-4c70-8355-db415f4b0fc6'}
    {'sourceId': 'DCE:f5781785-9dd7-4873-8f30-99d7e2ca1a8f', 'sourceName': 'GPP_localhost_localdomain', 'sourceIOR': <ossie.cf.CF._objref_AggregateExecutableDevice instance at 0x2d46638>, 'sourceCategory': DEVICE, 'producerId': 'DCE:516aa867-e262-4c70-8355-db415f4b0fc6'}
    {'sourceId': 'DCE:f5781785-9dd7-4873-8f30-99d7e2ca1a8f', 'sourceName': 'GPP_localhost_localdomain', 'sourceCategory': DEVICE, 'producerId': 'DCE:516aa867-e262-4c70-8355-db415f4b0fc6'}
    {'sourceId': 'DCE:83f3c741-19bf-4794-877f-0322cd62290a','sourceName': 'DevMgr_localhost-localdomain', 'sourceCategory': DEVICE_MANAGER, 'producerId': 'DCE:516aa867-e262-4c70-8355-db415f4b0fc6'}

Writing Your Own Event Consumer

In CORBA's Event API, messages are passed as an CORBA::Any type, so when the event is consumed from an event channel, it arrives as a CORBA::Any type. The application eventviewer contains an example of how to create an event consumer.

The consumer object is an object that implements the PushConsumer interface.

In Python, the definition of such a class is:

class Consumer_i(CosEventComm__POA.PushConsumer):
  def __init__(self):
    pass

  def push(self, data):
    event = any.from_any(data)
    print event

  def disconnect_push_consumer (self):
    pass

In the above example, the call to any.from_any converts from a CORBA::Any type to a Python dictionary.

An object of the class Consumer_i needs to be instantiated and given to the Domain Manager. In Python, the easiest way to access a running domain is to use the REDHAWK runtime package (a thorough description of the REDHAWK runtime package is available in Runtime Environment / Inspection); in the case of a domain called REDHAWK_DEV, the process needed to associate this consumer with the event channel is:

from ossie.utils import redhawk

_consumer = Consumer_i()
channel_name = 'ODM_Channel'
registration_id = 'some random string'
dom = redhawk.attach('REDHAWK_DEV')
dom.registerWithEventChannel(_consumer._this(), registration_id, channel_name)

In the example shown above, the consumer is attached to the ODM_Channel on the domain REDHAWK_DEV. The registration id is some string that can be used to uniquely identify this registration.

Using this id, to unregister the code the following method is invoked:

dom.unregisterFromEventChannel(registration_id, channel_name)

Cleaning up the Event Service

Sometimes the system will fail in ways that the Event Service (omniEvents) will no longer be synchronized with the domain. When this happens, two utilities have been included with REDHAWK to help understand the state of the Event Service and clean it up if necessary.

The first tool is eventl, which lists all of the events that are currently being handled by the Event Service. The other tool is rmeventall, which cleans up all of the event channels that the Event Service is currently supporting.

The Event Channel Manager

The Event Channel Manager provides a single point for creation and inspection of event channels on the domain. It also provides an interface for users to register publishers or subscribers to any of the available event channels.