The Event Service provides asynchronous communications between cooperating, remote objects. It's most similar in nature to the message-passing and event-based messaging we saw in Chapter 6, "Message-Passing Systems".
The CORBA Event Service is based on a model involving suppliers and consumers of events, connected by event channels that carry events back and forth between the two. An event channel can support multiple event suppliers and multiple event consumers. The Event Service also supports two event propagation styles for both consumers and suppliers of events: push style and pull style. A push-style consumer has events pushed to it by its event suppliers, while a pull-style consumer explicitly pulls events from its suppliers. On the other end of the event channel, a push-style supplier pushes events to its consumers, while a pull-style supplier waits for its consumers to pull events from it. Figure B-2 shows the relationship between event suppliers, consumers, and channels. In the figure, arrows indicate flow of events, and the location of the head of the arrow indicates which entity drives the event transfer.
Although the event channel provides a physical connection between consumers and suppliers in the Event Service model, logically each consumer attaches itself to one or more suppliers, and each supplier attaches itself to one or more consumers. Each consumer and supplier attaches itself to an event channel by attaching itself to a proxy supplier or consumer that the event channel exports. An event channel can be thought of as supporting both the supplier and consumer interfaces, simultaneously.
So here's the typical execution plan that an agent follows when using the CORBA Event Service:
A reference to an event channel object is obtained, either using the Naming Service to look up a remote event channel object reference, or by invoking an operation on an existing remote object reference that dynamically opens an event channel.
If the agent has any event suppliers, they register themselves with the event channel by attaching themselves to proxy consumers obtained from the channel. Pull-style suppliers attach themselves to proxy pull consumers created from the channel, and push-style suppliers attach themselves to proxy push consumers created from the channel.
If the agent has any event consumers, they register themselves with the event channel in a similar way. Pull-style consumers attach themselves to proxy pull suppliers and push-style consumers attach themselves to proxy push suppliers.
When suppliers on the agent's side of the channel generate events, the events are carried through the event channel to any consumers attached remotely to the channel. Push suppliers push their events through the channel by calling push() methods on the proxy consumers obtained from the channel. Pull suppliers wait for their proxy consumers to pull events from them through the channel.
Consumers on the agent's side of the channel receive events from remote suppliers attached to the channel. Pull-style consumers pull events through the channel from their proxy suppliers by calling pull() methods on them. Push-style consumers wait for their proxy suppliers to give them events received through the channel.
The consumers and suppliers attached to a channel don't know or care about the type or implementation details of their counterparts on the other end of the event channel. A push consumer might attach itself to a channel with only a pull supplier on the other end; the event channel is responsible for ensuring that events are pulled from the supplier and pushed to the consumer, so that the flow of events is maintained. The same is the case when a pull consumer is attached to a push supplier--the event channel accepts the events pushed to it by the supplier, and buffers them until the consumer pulls them. Regardless of the types of suppliers and consumers attached to an event channel at any given time, you should assume that event delivery by the channel is asynchronous.
The Event Service specification provides both generic and typed event communication. In the generic case, the type of the event data is not specified in the interfaces for the suppliers, consumers, or channels. Event data is represented using the CORBA any data type, and suppliers and consumers call generic push() and pull() methods on each other to propagate events through the distributed system. In typed event communication, the interfaces for the suppliers, consumers, and channels can include type-specific event propagation methods and type-specific event representations. In this appendix we'll only discuss the generic event communication aspects of the Event Service.
Any given implementation of the event channel interface can support a particular quality of service. Some implementations may guarantee delivery of every event to every consumer attached to the channel, while others may just guarantee to make a best effort to deliver the events generated by its suppliers. The Event Service specification leaves the implementation open to these different levels of service to allow for different application requirements. The trade-offs here are similar to those found at a lower level, in choosing between TCP and UDP packet delivery over IP network connections. Guaranteed event delivery typically means reduced net throughput. Best-effort event delivery can potentially provide higher event throughput, but at the cost of potentially undelivered events, or events delivered to only some of the consumers attached to the channel.
The Event Service includes several modules that provide IDL interfaces for suppliers, consumers, and event channels. In this appendix we'll briefly review the highlights of the interfaces for generic event communication. If you're interested, see the CORBA Services specification document.
CORBA Services Specification, OMG Technical Document formal/97-07-04, July 1997.
The CosEventComm module contains interface definitions for push and pull consumers and suppliers of events:
The PushSupplier interface has only one method, disconnect_push_supplier() , which releases the supplier from its event communication link. There's no exported method for getting events from the supplier, since it's responsible for pushing events to its attached consumer(s).
The PushConsumer has a push() method, which accepts a single input argument of type any that represents the event data. The any type is an IDL language feature used to mark data that can be of any type. The receiver of the event is responsible for determining the actual data type. The PushConsumer also has a disconnect_push_consumer() method for releasing it from the event communication channel.
This interface has two methods for pulling event data from the supplier: pull() and try_pull(). A consumer can choose to do a blocking event pull by calling pull(), or it can do a nonblocking polling of the event supplier by calling try_pull(). There is also a disconnect_pull_supplier() method.
The PullConsumer just has a disconnect_pull_consumer() method, since it's responsible for internally pulling events from its suppliers.
The CosEventChannelAdmin module contains interfaces for event channels and their proxy consumers and suppliers:
This interface has three methods: for_consumers() , for_suppliers() , and destroy() . The for_consumers() method returns a reference to a ConsumerAdmin object, which can be used by consumers to get references to proxy suppliers. Likewise, the for_suppliers() method returns a SupplierAdmin object, which can be used by suppliers to get references to proxy consumers. The destroy() method destroys the channel and any communication resources it had been using.
This interface allows consumers to get references to proxy suppliers from an event channel. The obtain_push_supplier() method returns a reference to a ProxyPushSupplier object, and the obtain_pull_supplier() method returns a reference to a ProxyPullSupplier object.
The SupplierAdmin interface allows suppliers to get references to proxy consumers from the channel. The obtain_push_consumer() method returns a ProxyPushConsumer reference, and obtain_pull_consumer() returns a ProxyPullConsumer reference.
This interface derives from the PushSupplier interface in the CosEventComm module. It adds a method, connect_push_consumer(), which allows a local PushConsumer to attach itself to the supplier. The method takes a single argument: a reference to a PushConsumer. Attaching a consumer to the proxy supplier sets up a path for events to flow from the remote suppliers attached to the channel, through the channel, to the local proxy supplier, and finally to the local consumer.
This derives from PullSupplier and adds a connect_pull_consumer() method, which accepts a PullConsumer reference.
This derives from PushConsumer and adds a connect_push_supplier() method, which accepts a PushSupplier reference. Attaching a supplier to a proxy consumer sets up a path for events to flow from the local suppliers attached to the channel to the local proxy consumer, through the channel, and finally to remote consumers attached to the channel.
This derives from PullConsumer and adds a connect_pull_supplier() method, which accepts a PullSupplier reference.
As we discussed in Chapter 6, "Message-Passing Systems", the core Java API provides a basic framework for event-based communication between agents, remote or otherwise. The only full implementation of this framework present in the Java API is found in the AWT package, which uses the event delegation model to define the flow of user events from user interface elements to application objects that process the events, update the system state, and provide visual feedback to the user through changes to the user interface.
We showed in Chapter 6, "Message-Passing Systems" how the delegation event model in Java could be used to build a remote messaging system. But the Java API didn't provide us much "out-of-the-box." There is no generic event-handling interface provided as an extension of the placeholder EventListener interface. We had to fill this gap ourselves by creating the EventHandler interface with its generic handleEvent() abtract method. And there is no interface supplied at all for event sources. This significantly limits the usefulness of the Java API as a broad framework for distributed event-passing systems, especially when it comes to interfacing with other event-based systems.
Copyright © 2001 O'Reilly & Associates. All rights reserved.