Page #115 (Resource Dispensers)

< BACK  NEXT >
[oR]

Just-in-Time (JIT) Activation

In an enterprise system, a user-driven client application often creates an object, makes a method call, and holds on to the object to use it later. The time between calls can vary from seconds to minutes or even hours. Meanwhile, on the server side, the object continues to stay alive, tying up resources. Imagine the resource-sharing problem that would arise if a hundred or more clients locked access to the resources that they weren t even using.

Just-in-time (JIT) activation is a mechanism provided by COM+ to manage the lifetime of an object more efficiently. The idea is very simple the actual object is activated just prior to the first call made on it and is deactivated immediately after finishing its work.

Here s how it works.

When the client creates an object that is marked for JIT activation, COM+ activates the actual object and returns a proxy to the client, as shown in Figure 11.1.

Figure 11.1. JIT activation: Client gets a proxy.
graphics/11fig01.gif

Once the object is created, the client makes method calls on it as usual. When the object is finished doing its work, COM+ deactivates the actual object. However, the proxy, the stub, and the ORPC channel connecting them are all still in place. The client continues to hold the reference to the object via its proxy, unaware that the underlying object has been deactivated. This is illustrated in Figure 11.2.

Figure 11.2. JIT activation: The actual object has been deactivated.
graphics/11fig02.gif

When a client makes a call on the proxy, the proxy informs the stub. At this point, COM+ activates a new instance of the object, as shown in Figure 11.3.

Figure 11.3. JIT activation of a new instance.
graphics/11fig03.gif

A component is marked for JIT activation from the Component Services snap-in, as shown in Figure 11.4.

Figure 11.4. Enabling a component for JIT activation.
graphics/11fig04.gif
Figure 11.4. Enabling a component for JIT activation.
graphics/11fig04.gif

Now comes the million dollar question how does COM+ know that it is safe to deactivate the object?

COM+ could perhaps wait for a predefined timeout period to check if the client makes any call. If no call comes in within this timeout period, then COM+ can deactivate the object. However, such a timeout-based deactivation mechanism may result in an unexpected behavior.

Consider, for example, a component that supports obtaining salary information for an employee. It implements the following interface:

 interface IMyJITDemo : IDispatch  {   HRESULT SetEmployee([in] BSTR bsEmployeeName);    HRESULT GetSalary([out, retval] long* pVal);  }; 

The idea is that the client first calls SetEmployee to specify the employee name, and then calls GetSalary to obtain the salary of the employee. Let s say the client doesn t call GetSalary within the timeout period. As a result, COM+ deactivates the object. Later, when GetSalary call comes in, a new instance is activated. However, the new instance has no idea who the employee is for which GetSalary is being called. In the best case, the call will return a failure condition. In the worst case, it will return an invalid value.

The real problem is that when the original object was being deactivated, it was in a state a state that contained the name of the employee. When the object got deactivated, this state got lost.

In order for JIT to work, the object should be deactivated when it is stateless, that is, it either contains no data, or contains data that is not important and may be discarded.

But the stub doesn t have the foggiest idea about the statelessness or the statefulness of an object. As far as it is concerned, the object is nothing but an implementation of a bunch of interfaces.

Unlike the stub, however, the object does know what state it is in. If only it can inform the stub that it is done with the work it is supposed to do. Then the stub can go ahead and deactivate the object.

In our example case, it is not okay to deactivate the object after calling SetEmployee, but it is perfectly fine to deactivate the object after the client calls the GetSalary method.

An object that is JIT-enabled contains a bit in its context called the done bit or, more precisely, the deactivate-on-return bit. COM+ checks this bit after its return from each method call. If the bit is turned on, COM+ will deactivate the object. By default, COM+ turns this bit off before entering a method. However, one can change this behavior at the interface method level from the Component Services snap-in.

The deactivate-on-return bit can also be set programmatically by using the method SetDeactivateOnReturn available on the interface IContextState. The following is its prototype:

 Interface IContextState : IUnknown  {   ...    HRESULT SetDeactivateOnReturn(VARIANT_BOOL bVal);  } 

Parameter bVal informs COM+ whether or not the object should be deactivated.

graphics/01icon02.gif

SetDeactivateOnReturn requires VARIANT_BOOL (and not BOOL) as the parameter type. Do not use TRUE or FALSE as the parameter. Use VARIANT_TRUE or VARIANT_FALSE instead.


Method CMyJITDemo::SetSalary can now be implemented as follows:

 STDMETHODIMP CMyJITDemo::GetSalary(long *pVal)  {   CComPtr<IContextState> spState;    HRESULT hr = ::CoGetObjectContext(__uuidof(IContextState),      (void**) &spState);    hr = spState->SetDeactivateOnReturn(VARIANT_TRUE);    ...    return S_OK;  } 

Note that the implementation of SetEmployee need not explicitly set the deactivate-on-return bit to VARIANT_FALSE. This is because, by default, COM+ automatically sets this bit to VARIANT_FALSE before calling a method.

When JIT activation is enabled on a component, COM+ enforces the Synchronization attribute to be set to Required. The reason for this is simple. If two clients were simultaneously calling a JIT-activated component, and a method call from one of them causes the object to be deactivated on return, the other method call would be left accessing invalid memory location or other such resources. This problem can be avoided by ensuring that only one method call gets serviced at a time, which is exactly what Synchronization=Required does (see Chapter 6).

Although JIT activation results in reclaiming the resource taken up by the object, it is often less than what you think. Even though the COM object that finished its work is deactivated, the channel and the stub still stay in place. Only when the object consumes considerably more memory than these infrastructural items does JIT activation provide some benefit. However, keep in mind that repeated activation/deactivation of the object results in some performance degradation. Before enabling JIT activation, you should consider if the benefit of saving resources outweighs performance degradation. JIT activation is more beneficial when deactivating an object recovers a scarce, expensive resource, such as a database connection.

The real benefit of JIT is that it enforces transactional correctness. Recall from Chapter 8 that a transaction is completed only after the root object of the transaction is deactivated. Forcing the client to release the root object and re-create it for each transaction not only requires some programming effort on the part of the client, but it is also inefficient, as the proxy, the stub, and the channel are torn down every time. Marking the root-object transactional component as JIT-activated and setting the deactivate-on-return bit within an appropriate method implementation deactivates the root object. Not only does this enforce transaction completion, it also leaves the setup (the proxy, the stub, and the ORPC channel) intact. In fact, JIT activation is so crucial for transactional correctness that, if a component is marked to participate in a transaction, COM+ enforces that the component gets enabled for JIT activation.

If JIT activation is enabled on a component, it implies that its objects are created and destroyed frequently. The primary intention of destroying an object is to force the object to release its resources. If somehow we can force the object to release its resources without actually destroying the object, we could reuse the object without having to create it, thus saving some CPU cycles. This is what object pooling, a COM+ provided mechanism and our next topic of discussion, tries to achieve. By pooling JIT-activated objects, you can greatly speed up object reactivation for the client.


< BACK  NEXT >


COM+ Programming. A Practical Guide Using Visual C++ and ATL
COM+ Programming. A Practical Guide Using Visual C++ and ATL
ISBN: 130886742
EAN: N/A
Year: 2000
Pages: 129

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net