Previous Table of Contents Next


22.14.3 Routing Protocol


   Processing of a time-independent invocation involves a series of roles played by various components of the distributed system. These roles include:

   Not all of these distinct roles are necessarily involved in every invocation, and more than one role can be played by the same component of the distributed system. A router implementation is likely to be able to serve any of the router roles, and may even serve multiple roles for the same invocation, such as when the initial request router also serves as the target router with no intermediate request routers involved.

   Routers can be collocated with client or server ORBs, or can be separate processes. Either way, routers must maintain persistent state with transactional semantics.

   22.14.3.1 Invoking Client

   The client application makes an asynchronous invocation either by specifying a ReplyHandler object or by using the polling API.

   Depending on QoS requirements, the client ORB may try to synchronously invoke the operation on the target object, using IIOP or some other synchronous protocol. This attempt will not be made if the client is part of an active transaction and the target has a TransactionPolicy of Requires_unshared.

   If the target is unreachable via a synchronous protocol, the client ORB tries to find an initial router to use. If the target IOR has a TAG_MESSAGE_ROUTERS component, its list of routers may be tried, starting from the one closest to the target, which is the last in the list. If none of these are reachable, or there is no TAG_MESSAGE_ROUTERS component, then the client ORB’s default router closest to the target may be chosen. The order in which the client ORB attempts to contact an initial router is not mandated by this specification. The client ORB may choose to send the request to any Router (such as its own closest Router in all cases) according to implementation-specific configuration. If the client application used the polling interface and a quality of service requiring the request to be persistent, the client ORB attempts to narrow the initial request router to a PersistentRequestRouter, and if this fails, a different router must be selected. If no router can be found meeting the required quality of service, the system exception CORBA::INV_POLICY is raised.

   Once an initial request router is identified, the client ORB delivers the request to it by invoking send_request if a ReplyHandler was specified, or create_persistent_request if the polling API and persistent QoS was used. The client application’s active transaction context, if any, is used for this invocation. Only service context information that is meaningful to the target in a time-independent invocation, such as CodeSets (but not TransactionContext), is included in the RequestMessage argument to send_request. Future ORB service specifications must state whether their service contexts are to be considered end-to-end (and therefore included within the RequestMessage) or are only for a single hop (and therefore used by the ORB when invoking the initial router but not included with the RequestMessage).

   An empty sequence is passed by the client ORB as the visited parameter. The list of routers from the target IOR’s TAG_MESSAGE_ROUTERS component is used as the to_visit parameter. This list may have additional routers added to it by the client ORB depending on administration of the network of routers. If the callback model is being used, the type-specific ReplyHandler is passed as the reply_destination. If the request was originated using create_persistent_request, the untyped ReplyHandler is passed as the reply_destination. For the reply to be able to be delivered asynchronously, these ReplyHandler IORs must contain enough routing information (e.g., TAG_MESSAGE_ROUTERS component).

   22.14.3.2 Initial Request Router

   The initial request router’s role depends on whether the ReplyHandler or polling API was used by the client.

   If the client ORB passed the request message, along with a ReplyHandler reference, to the initial router using the send_request operation, the initial request router saves the request message to stable storage within the client application’s transaction context, and then processes the request using the request routing algorithm described below.

   If create_persistent_request was called, the initial request router must instantiate a PersistentRequest object and return its reference to the client ORB, which will return it to the client application. Until the response for the request is delivered to the client, or the request times out, such an initial request router must keep an association between the identity of this PersistentRequest object and the state of the request. When routing the request (as described below), this first router passes a reply_destination, which is an UntypedReplyHandler implemented by the first router itself. This UntypedReplyHandler may be created either before or after the PersistentRequest and request state is committed to stable storage. After returning the PersistentRequest object and committing the request state to stable storage, all within the transaction context of the client application, the initial router processes the request using the routing algorithm described below. The routing process does not continue until the client’s initial transaction has been committed.

   22.14.3.3 Request Routing Algorithm

   Any router that has received a request message and committed it to stable storage processes it in the same way. If it can invoke the operation directly on the target object, the router serves as the target router for the invocation, as described below. If not, it tries to deliver the request to another router closer to the target object. If it can’t do either of these, it queues the request and tries again later, either after some period of time has elapsed, or in response to an announcement of availability from another router closer to the target as described in Section 22.15, “Router Administration,? on page 22-58.

   A router typically picks another router closer to the target by selecting from the list of routers passed to it as the to_visit parameter to either send_request or create_persistent_request. Routers later in the list are given preference as being closer to synchronous connection with the target. The next router can also be selected from some set of known Routers based on an implementation-specific configuration. If QoS attributes of the request message require persistence of requests, a transaction is first initiated. Then send_request is called on the selected router. The to_visit parameter is formed by removing the callee from the to_visit list received with the original request. Any routers further from the target than the callee (earlier in the to_visit list) are also removed. The target, reply_destination, selected_qos, and message parameters are copied from the received request. After invoking send_request, the router removes the request message from its stable storage, and commits the transaction if it initiated one.

   A router must ensure that exactly-once semantics are preserved. If delivering a request message results in an exception with a CompletionStatus of COMPLETED_NO, or in a transaction being aborted, it can retry. Since any invocation can raise a system exception, all exception replies with a completion status other than COMPLETED_NO must be reported back to the client via the reply message.

   22.14.3.4 Intermediate Request Router

   An intermediate router is simply a router that accepts a request message via send_request from one router and then, eventually, delivers it to another router, again using send_request. The send_multiple_requests operation may also be used to allow batching of requests between Routers. The intermediate routers may take a request’s QueueOrderPolicy (if present) into account when prioritizing the delivery of requests to destination routers, but is not required to do so.

   22.14.3.5 Target Router

   The target router for an invocation is a router that accepts a request message, delivers it to the target object, and, if a response is expected, routes the target’s reply back to the client. The target router may have to queue the request message before the invocation and/or may have to queue the response message after the invocation.

   The target router may be collocated with the target, or may deliver the request to the target via a synchronous GIOP-based protocol. The target router is responsible for processing any LOCATION_FORWARD replies that may be generated in making the invocation on the target, so only NO_EXCEPTION, USER_EXCEPTION, or SYSTEM_EXCEPTION replies are routed back to the client. When making the synchronous GIOP request on the target, the TargetRouter must marshal its request with the same byte order with which the original message body was marshaled. This byte order is recorded in the MessageBody structure. No Router is expected to remarshal the request body with a new byte order.

   If persistence of requests is required, the target router ensures that the request message is removed from stable storage and the reply message is committed to stable storage within the scope of a single transaction. If the target object’s IOR indicates that it supports time-independent transactions (through a TransactionPolicy of Allows_unshared, Allows_either, Requires_unshared, or Requires_either), then that same transaction context is propagated to the server application. Otherwise no transaction context is propagated to the target when the request is invoked.

   When guaranteed delivery is required, there may be one, two, or three distinct transactions involved in the target router’s processing of the invocation. The target router receives the request message within the context of a transaction initiated by a previous router or possibly the client ORB. If the target is accessible at that time, the operation can be invoked on the target and the reply message either stored or sent back toward the reply destination using the transaction context within which the request was received. If the target is not accessible, the request message is committed to stable storage and queued for later delivery to the target under a second transaction. When the target operation is invoked and its reply is received, the target router may deliver the reply to another router, or possibly to the client ORB. The router may deliver the reply in the same transaction as it invoked the operation, or the router may commit the reply to stable storage and later deliver it in yet another transaction. The completion of the transaction in which the TargetRouter actually delivers the request to the target is governed by the following cases:

   If the request has a QueueOrderPolicy associated with it, the target router is responsible for making invocations in the proper order. Depending on the Ordering requested (e.g., PRIORITY, TEMPORAL), the appropriate request is selected for delivery. Note that end-to-end ordering guarantees cannot be made when client and target are decoupled, so this ordering is really only a guideline. If multiple threads are used in the router for request delivery, it is certainly possible for delivery of requests to be out of order. The specification of QueueOrderPolicy does not require a router or server ORB to limit its use of threads in delivering requests.

   Regardless of how many transactions, if any, are used, the target router must route the reply back to the reply destination if and only if the response_expected flag was set to a non-zero value in the RequestMessage. The reply can take one of two forms depending on whether the reply_destination is a type-specific ReplyHandler (the client uses the Callback model) or if the reply_destination is an UntypedReplyHandler (a PersistentRequest was created such as when the client used the Polling model).

   Note – The type-specific reply handlers and the UntypedReplyHandler are both derived from the common base ReplyHandler interface, but there is no other inheritance relationship between the UntypedReplyHandler and the type-specific reply handlers.

   Regardless of destination, the new reply must be marshaled with the same byte order used by the target when the reply was originally marshaled. The Target Router is not expected to remarshal the reply body.

   22.14.3.6 Replying to a Type-specific ReplyHandler

   If the client originally supplied a type-specific ReplyHandler, the reply must be converted into a typed request invocation on the ReplyHandler. The Target Router determines this by verifying that the handler_type disposition of the reply_destination argument has the value TYPED. The format of the generated request depends on the reply_status:

   A reply with status LOCATION_FORWARD is handled as described below.

   22.14.3.7 Replying to an UntypedReplyHandler

   If the client originally created a PersistentRequest (such as by using the Polling model), the reply must be converted into the generic request operation supported by the UntypedReplyHandler interface. The Target Router determines this by verifying that the handler_type disposition of the reply_destination argument has the value UNTYPED. The generated reply operation has the name “reply? and takes as arguments the original operation name, the reply_status (NO_EXCEPTION, SYSTEM_EXCEPTION or USER_EXCEPTION) and a sequence of octet containing the reply data. The length is set to the size of the marshaled ReplyBody and the data is the marshaled body itself.

   22.14.3.8 Handling of Service Contexts

   When a TargetRouter receives a Reply, it generates a request on some ReplyTarget as described previously in this section. If the Reply contains service contexts, the TargetRouter must decide whether or not these contexts are to be used in its request on the ReplyTarget. End-to-end service contexts, such as the CodeSets context, are propagated to the ReplyTarget. Single-hop service contexts, such as the TransactionService context, are consumed by the TargetRouter. Unknown service contexts are propagated from the reply to the generated request on the ReplyTarget.

   22.14.3.9 Handling LOCATION_FORWARD Replies

   When a TargetRouter receives a Reply with status LOCATION_FORWARD, it must either use the returned reference as the new target for the request, or must return the new reference to the ReplyTarget. The Messaging protocol requires that the TargetRouter continue processing the request by either directly invoking the new target or routing the request toward the new target as has been described thus far.

   22.14.3.10 Routing of Replies

   As described above, the GIOP reply is turned into a request message targeted to the original reply_destination. Since this reply is now a request, it may be sent to its destination using the message routing protocol described in this section. For example, if the ReplyHandler’s reference contains Routing information, the TargetRouter may invoke the new request using some Router’s send_request operation. In this case, the specified routing protocol should be followed for this new request, with the response_expected flags all set to 0 and the reply_destination set to nil.

   22.14.3.11 UntypedReplyHandler

   When an UntypedReplyHandler’s reply operation is invoked, several things may happen. The specific correlation of a Router’s UntypedReplyHandler with the PersistentRequests it supports is not visible to this interoperability layer, but at a high level one of the following occurs: