Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Advanced CORBA Programming wit C++ - M. Henning, S. Vinoski.pdf
Скачиваний:
65
Добавлен:
24.05.2014
Размер:
5 Mб
Скачать

IT-SC book: Advanced CORBA® Programming with C++

ObjectId-to-servant association in its Active Object Map, just as it always does if it has the RETAIN policy. If no association is found but the application has registered a ServantActivator, the POA invokes it in an attempt to obtain a suitable servant. In other words, after an object has been deactivated, the POA acts the same as if it had never been activated in the first place. Alternatively, if a request arrives or if the application attempts explicit activation while etherealize is still running, reactivation will be blocked until the ServantActivator has finished etherealizing the servant. After that, reactivation will occur as usual.

Because deactivate_object does not remove the object's entry from the Active Object Map until there are no more active requests for that object, a steady stream of incoming requests can actually keep the object from being deactivated. This is a side effect of allowing the servant to finish its normal processing before deactivation occurs. A servant performing such processing may invoke recursive method calls on the object it incarnates, and deactivation should not necessarily prevent those method invocations. Also, if a servant already has a method in progress when the application calls deactivate_object and if that method is blocked waiting for another long-running operation to complete, actual deactivation will be blocked until the method in progress finishes. You must be aware of these types of situations and be sure that your applications do not prematurely delete their servants out from under methods that are still in progress. As we recommend in Section 11.7.5, the best way to clean up your servants with a RETAIN POA is to use a ServantActivator.

The deactivate_object operation is an important part of the process of destroying a CORBA object. After an application deactivates an object, new requests for that object either cause reactivation or result in the CORBA::OBJECT_NOT_EXIST exception. After your application either raises the OBJECT_NOT_EXIST exception directly for a given object or fails to register a servant so that the POA raises it, you must be careful never to reincarnate the object. OBJECT_NOT_EXIST is essentially an object death certificate—it is intended as a definitive statement that the object is gone for good. Remember, because the POA has no persistent state, it is the application, and not the POA, that ultimately decides whether a given object still exists. If you raise OBJECT_NOT_EXIST for a given object and then later bring it back to life, you will not only break the CORBA object model but also cause confusion for your client applications and your administrative tools.

We discuss deactivate_object and object destruction issues further in Chapter 12 when we cover the OMG Life Cycle Service [21].

11.10 Request Flow Control

Our descriptions of servants and servant managers have shown how the POA provides applications with a great degree of flexibility in managing their own resources. For example, servant managers and default servants enable tight control over the amount of

440

IT-SC book: Advanced CORBA® Programming with C++

memory devoted to servant storage, allowing applications with many objects to scale gracefully.

Another aspect of resource management relates to the rate of requests that a server application can handle. As shown in Figure 9.1, each POA has an associated POAManager that essentially acts as a faucet or valve that allows you to control the flow of requests into the POA. Figure 11.9 illustrates the relationships among an application, an ORB, POAManager objects, and POAs.

Figure 11.9 Relationships among applications, ORBs, POAManagers, and POAs.

A single application may actually contain multiple ORB instances if it invokes CORBA::ORB_init multiple times with different arguments, but that is atypical and is therefore not shown here. In Figure 11.9, the application contains one ORB, and it in turn contains a single Root POA. The application has created a hierarchy of child POAs descending from the Root POA. It also has two POAManager objects: one for the Root POA and some of its descendants and the other for a different set of POAs descended from the Root POA. Although we do not show them, each POA typically also has one or more servants associated with it.

Applications use the POAManager interface to allow requests to pass into a POA unimpeded, to discard or hold requests, or to deactivate all request handling.

module PortableServer { interface POAManager {

exception AdapterInactive {};

441

IT-SC book: Advanced CORBA® Programming with C++

enum State { HOLDING, ACTIVE, DISCARDING, INACTIVE };

State

get_state();

 

void

activate() raises(AdapterInactive);

void

hold_requests(in boolean wait_for_completion)

 

raises(AdapterInactive);

void

discard_requests(in boolean wait_for_completion)

 

raises(AdapterInactive);

void

deactivate(

etherealize_objects,

 

in boolean

 

in boolean

wait_for_completion

) raises(AdapterInactive);

};

// ...

};

The four operations provided by the POAManager interface (other than the get_state operation) correspond to the four possible states of a POAManager object. You invoke the activate operation to cause the target POAManager to transition into the active state and let requests flow through to the POA or POAs under its control.

You call the hold_requests operation to change the target POAManager into the holding state. In this state, the POAManager queues all incoming requests for the POA or POAs under its control. The maximum number of requests that a POAManager can queue while in the holding state is implementation-dependent. If the POAManager reaches its queuing limits, it may discard each request by raising the standard CORBA:: TRANSIENT system exception, indicating that the client should retry the request. If the wait_for_completion argument to hold_requests is false, the operation returns immediately after changing the state of the POAManager. If wait_for_completion is true, first the POAManager state is changed to holding, and then the operation does not return either until any requests that were already in progress complete or the state of the POAManager is changed from the holding state to some other state by another thread.

You invoke the discard_requests operation to cause the target POAManager to change to the discarding state. This state causes the POAManager to throw each incoming request away without queuing it and without delivering it to the target POA; instead, it raises the CORBA::TRANSIENT exception back to the client. If the wait_for_completion argument to discard_requests is false, the operation returns immediately after changing the state of the POAManager. If wait_for_completion is true, first the POAManager state is changed to discarding, and then the operation does not return until any requests that were already in progress

442

IT-SC book: Advanced CORBA® Programming with C++

complete or the state of the POAManager is changed from the discarding state to some other state by another thread.

You invoke the deactivate operation to change the state of the target POAManager to the inactive state. A POAManager in this state is no longer capable of processing requests and cannot be reactivated. If new requests arrive for objects in the POA or POAs controlled by the inactive POAManager, they are rejected in an implementation-specific manner. Some ORBs might raise the standard CORBA::OBJ_ADAPTER system exception back to the client, and others might transparently redirect the client ORB to another object. Unlike the holding or discarding states, raising CORBA::TRANSIENT back to the client is not a good approach because it implies that a retried request might reach the target object. As long as the POAManager is in the inactive state, retries will not succeed because all requests destined for that POAManager will be rejected. Raising CORBA::OBJECT_NOT_EXIST is also unacceptable because the target object may very well still exist. The ORB cannot know for sure whether the object still exists because it is inaccessible, even to the ORB, because of the inactive state of its

POAManager.

The get_state operation returns the POAManager's current state. Figure 11.10 shows a state diagram that illustrates the legal state transitions that a POAManager can make.

443

IT-SC book: Advanced CORBA® Programming with C++

Figure 11.10 POAManager state transition diagram.

A POAManager is associated with a POA at creation time. As shown in Section 11.5, the POA::create_POA operation has a reference to a POAManager object as its second argument.

If you pass a non-nil reference to a POAManager for this argument, the creation operation associates the new POA with that POAManager. This allows you to control request flow for multiple POAs via a single POAManager. On the other hand, if this argument is a nil reference, the implementation creates a new POAManager along with the new POA. Note that if a child POA has a separate POAManager from its parent POA, any state changes you apply to the POAManager of the parent POA do not affect that of the child and vice versa.

The state diagram in Figure 11.10 shows that newly created POAs begin their lives in the holding state. From the holding state they can legally transition to the active, discarding, or inactive states. You can transition a POA freely between the holding, discarding, and active states. After the state of a POA has been changed to inactive, however, the only legal change of state is to destroy it by invoking POA::destroy. In any state, except the inactive state, you can transition back to the same state without error. The reason that the inactive state is not a temporary state like the others is that ORB implementations may use it to perform resource cleanup such as closing network

444