I2JAV 1.2 NO IDEA Avatar
  1. OMG Issue

I2JAV12 — Colocated calls in Java

  • Key: I2JAV12-17
  • Legacy Issue Number: 4701
  • Status: closed  
  • Source: Oracle ( Ken Cavanaugh)
  • Summary:

    Note: this is NOT issue 3754, but it is related. A new issue is needed
    as described below:
    --------------------------------------------------------------------------
    Issue 3754 (colocated call optimization and portable interceptors) was
    raised some time ago by Harold Carr. This issue discusses the problems
    of supporting portable interceptors for RMI-IIOP calls when the colocated
    call optimization is used. The basic issue is that there is no way for the
    ORB to detect whether a local dispatch to a servant completed normally or
    completed by throwing an exception. This problem exists because the
    current is_local/servant_preinvoke/servant_postinvoke mechanism has no
    way to report normal or exceptional completion of a local dispatch.

    The same problem arises in the IDL stub case as well.
    Both Java mappings can share the same solution here, but a solution requires
    changing part of the portable stub API which is shared by both mappings.

    In the discussion of 3754, Simon Nash asked to reassign the issue from the
    Java to IDL RTF to the Java mapping RTF. We really need two separate issues
    here. I propose that we do the following:

    1. Move 3754 back to the Java to IDL RTF since Harold wrote the issue with the
    RMI-IIOP mapping in mind.

    2. Create a new Java mapping issue for the same problem. The bulk of this message
    should be the new issue.

    Both RTFs will need to consider the issues. The new Java mapping issue will need
    to propose extensions to the portable stub APIs and document the required changes
    in the IDL based stubs, while the resolution to 3754 will need to adopt the
    same new portable stub API and document the required changes in the RMI-IIOP stubs.

    To start a discussion, here is my initial proposal for solving this problem in
    the Java mapping RTF:

    We need to add methods to report the result of the local dispatch. I propose that
    we extend the portable definition of ServantObject as follows:

    abstract public class ServantObjectExt extends ServantObject

    { abstract public void normalCompletion() ; abstract public void exceptionalCompletion( Throwable thr ) ; }

    Another alternative is to extend the Delegate class instead. I prefer the
    ServantObject approach because the method signatures are simpler:
    adding these methods on the Delegate would require passing ServantObject
    as an argument, since multiple threads could be simultaneously invoking
    methods on the same object reference, which would share the same delegate.

    Making this change makes it necessary to consider what happens in
    mixed versions.

    Old stub, Old ServantObject:
    no change

    New stub, new ServantObject:
    stub always invokes either normalCompletion or
    exceptionalCompletion, so the ORB has enough information to correctly implement
    portable interceptor behavior. Note that a location forward (e.g. from a
    ServantManager) is not a problem today, since it happens inside of
    _servant_preinvoke,
    which allows the ORB to correctly handle that case.

    New stub, old ServantObject:
    If a new stub is written to do an instanceof check on
    the ServantObject it gets from _servant_preinvoke, it can correctly determine
    whether or not to call the new methods. There are a number of possibilities
    for the check:

    1. Just use (so instanceof ServantObjectExt) and rely on the ServantObjectExt
    class to be defined somewhere in the environment. New stubs that wanted to
    be compatible with old ORBs would need to be packaged somehow with this
    class in their classpath. The stubs would need the ServantObjectExt class
    both at compile time and at runtime.

    2. A stub could be written to entirely use reflection for the instanceof check
    and the method invocation. This would avoid the requirement to have
    ServantObjectExt in the classpath, but would require more code in the stubs,
    plus run a little slower (probably about 2X slower in JDK 1.4, but in
    earlier JDKs the penalty could easily be 10-20X).

    Old stub, new ServantObject:
    In this case, neither method is ever invoked, so the
    ORB can tell the difference between normal completion and an old stub.
    The PI implementation in this case is free to do anything. However, probably the
    best approach is to extend RequestInfo::reply_status with a new value
    PortableInterceptor::UNKNOWN. Then the local case would always use the
    interceptor points send_other and receive_other with a reply_status set to
    UNKNOWN. This extension requires a new core issue.

    It is worth noting here that the PI change makes it reasonable to consider simply
    changing PI, and avoid changing the ServantObject API and 2 language mappings.
    In this case, a user of PI cannot tell what is happening with colocated calls
    in a very basic sense: did the operation complete successfully or not?
    Many applications of PI (for example, transactions and security) often do not
    require the use of PI in the colocated case. However, one important application
    is best done this way: logging/tracing in a complex system. I believe this
    argues strongly for extending the mapping, since a log entry that cannot distinguish
    success from failure is of little use.

    With the instanceof check, the local code for the sample stub then becomes
    (from page 1-114 of ptc/01-06-04):

    org.omg.CORBA.portable.ServantObject _so =
    _servant_preinvoke( "length", _opsClass ) ;
    if (_so == null)
    continue ;

    Example.AnInterfaceOperations _self =
    (Example.AnInterfaceOperations)_so.servant ;

    try

    { int result = _self.length(s) ; if (so instanceof ServantObjectExt) ((ServantObjectExt)so).normalCompletion() ; return result ; }

    catch (Throwable thr)

    { if (so instanceof ServantObjectExt) ((ServantObjectExt)so).exceptionalCompletion( thr ) ; throw thr ; }

    finally

    { _servant_postinvoke( _so ) ; }

    Note that the instanceof checks are quite fast in modern JVMs,
    so I don't think this adds significantly to the overhead of the operation.
    A reflective solution is also possible, but I am not including that here.
    In any case, the precise code generation should be left to the implementation.
    All that the spec should require is:

    1. If the invocation on the servant completes without throwing an exception,
    then the stub code must call servant.normalCompletion after the invocation
    completes.

    2. If the invocation on the servant throws exception exc, then the stub code
    must call servant.exceptionalCompletion( exc ) after the invocation completes.

    In either case, the servant completion call must occur before the
    _servant_postinvoke call.

  • Reported: I2JAV 1.1 — Mon, 12 Nov 2001 05:00 GMT
  • Disposition: Resolved — I2JAV 1.2
  • Disposition Summary:

    Incorporate the revised text, make corresponding changes in the standard source files, close

  • Updated: Fri, 6 Mar 2015 20:58 GMT