[Up: Reference Implementation]
[Previous: MICO] [Next: Object Key Generation]

Design

Figure 5.3: Only the Root POA is registered with the MICO ORB
\includegraphics{pics/poa-arch.eps}

Of the many POA instances that can exist in a server, only the Root POA is registered with the ORB (see figure 5.3). It is made responsible for receiving requests for any POA, inspecting their target object reference and dispatching them to child POAs as necessary. Since MICO allows for many object adapters, another design would have been to register each POA instance directly with the ORB. However, that would pose a problem with non-existent adapters, as a non-existing POA instance does not mean that the request is undeliverable. Rather, if a POA does not exist, the request must be delivered to the parent POA, which can then invoke its adapter activator to recreate the missing POA. Only the Root POA is guaranteed to exist throughout the server's lifetime - it can be destroyed, but not be reactivated. By handing requests down from the Root POA along the line of descendants, adapter activators can be invoked at each step.

As a slight improvement in configurations with deeply nested child POA's, the Root POA keeps a map of all existing POAs. For an incoming request, the Root POA checks the request's object key, and dispatches the request directly if the responsible POA does exist. Only if the lookup in the global POA map fails does the Root POA need to dissect the POA name into its components in order to locate the most specific existing POA among the missing POA's ancestors.

Once the target POA is found, it proceeds as shown in figure 4.7 to find a servant. Some care was taken in designing the Active Object Map, so that many active objects can be handled efficiently. The Active Object Map is a C++ class of its own, actually consisting of two STL maps, one mapping Object Ids to object records, the other is a multimap mapping servants to object records.5.2 With STL's runtime complexity guarantees, entries can be found with a runtime of \( O(\log n) \) either by Object Id or by servant.

Beside the servant, an object record holds a full object reference, so that, when requested, this reference can be merely duplicated instead of recomposing it from scratch each time.

Figure 5.4: Class Diagram for the Portable Object Adapter Implementation
\includegraphics{pics/poa-impl-uml.eps}

Figure 5.4 shows an UML class diagram [42] of the classes used in the reference implementation. The four classes at the top of the diagram are provided by the ORB. POA is the IDL-generated base class, ObjectAdapter the abstract base class for MICO object adapters, ORB the ORB core class, and ORBRequest encapsulates an incoming request. At the bottom, Servant is the base class of all skeletons.

POA_impl
Implements the POA and the ObjectAdapter interfaces, though only the Root POA is actually registered with the ORB. Each POA keeps an ActiveObjectMap and a number of InvocationRecords, in case requests must be queued while the POA Manager is in the holding state. If the POA has the ``system id'' id assignment policy, it keeps a UniqueIdGenerator.
ActiveObjectMap
Maintains a list of ObjectRecords, indexed by ObjectId.
ObjectRecord
Associates a servant with an object reference; object references are encapsulated in a POAObjectReference value.
InvocationRecord
Associates an incoming request with an object reference.
POAObjectReference
Provides methods for the efficient composition and decomposition of an object reference (or rather the object key) into its components.
ObjectId
An efficient encapsulation of an Object Id, mainly to serve as the key in the Active Object Map.
POACurrent_impl
Implements the PortableServer::Current interface, whose purpose is to provide context information during a method invocation. Because more than one invocation may be in progress (nested method invocations), it keeps a stack of CurrentState objects. The inheritance from the IDL-generated base class is not shown.
CurrentState
The currently executing object reference, POA and (indirectly) servant must be available as context information.
For the most part, the implementation of the Portable Object Adapter did not hold any surprises. After deciding on the design and the class layout, putting the precise wording of the specification into code was for the most part straightforward.

More thinking had to go into the unspecified part of constructing the object key, and into realizing the missing control over persistent objects and their implementations. Both subjects are detailed in the following sections, as is the collocation optimization mechanism to reduce the overhead of method invocations if client and server are in the same process.

The IDL code generation for skeleton classes was taken almost unchanged from the BOA, with minor adjustments for the inheritance and naming convention: the format of requests and their dispatching is the same as before. Without much innovation, the POA skeletons use the same optimizations that already existed for BOA skeletons to use the Static Skeleton Interface.


[Previous: MICO] [Next: Object Key Generation]
[Up: Reference Implementation]

Frank Pilhofer
1999-06-23