Class POAManagerImpl

  • All Implemented Interfaces:
    java.io.Serializable, Object, IDLEntity, POAManager, POAManagerOperations

    @ManagedObject
    @Description("A POAManager which controls invocations of its POAs")
    public class POAManagerImpl
    extends LocalObject
    implements POAManager
    POAManagerImpl is the implementation of the POAManager interface. Its public methods are activate(), hold_requests(), discard_requests() and deactivate().
    See Also:
    Serialized Form
    • Field Detail

      • pihandler

        private final PIHandler pihandler
      • myId

        private final int myId
      • stateLock

        private final java.util.concurrent.locks.ReentrantReadWriteLock stateLock
      • stateCV

        private final java.util.concurrent.locks.Condition stateCV
      • state

        private State state
      • poas

        private java.util.Set<POAImpl> poas
      • nInvocations

        private java.util.concurrent.atomic.AtomicInteger nInvocations
      • nWaiters

        private java.util.concurrent.atomic.AtomicInteger nWaiters
      • explicitStateChange

        private volatile boolean explicitStateChange
      • activeManagers

        private static java.lang.ThreadLocal<org.glassfish.pfl.basic.contain.MultiSet<POAManagerImpl>> activeManagers
        activeManagers is the set of POAManagerImpls for which a thread has called enter without exit 1 or more times. Once a thread has entered a POAManager, it must be able to re-enter the POAManager, even if the manager is HOLDING, because state transitions can be deferred until all threads have completed execution and called exit(). Without this change, one thread can be blocked on the state change method, and another thread that has entered the POAManager once can be blocked from re-entry on a nested co-located call. This leads to a permanent deadlock between the two threads. See Bug 6586417. To avoid this, we create a set of active managers, and record which managers a particular thread is using. A thread may re-enter any manager in HOLDING state once it has entered it for the first time. Note that POAManagerImpl uses the default equals and hashCode methods inherited from Object. This is fine, because two distinct POAManagerImpl instances always represent distinct POAManagerImpls. This is only a partial solution to the problem, but it should be sufficient for the app server, because all EJBs in the app server share the same POAManager. The problem in general is that state changes between multiple POAManager and invocation threads that make co-located calls to different POAManagers can still deadlock. This problem requires a different solution, because the hold_requests method may have already returned when the active thread needs to enter the holding POAManager, so we can't just let the thread in. I think in this case we need to reject the request because it may cause a deadlock. So, checkState needs to throw a TRANSIENT exception if it finds that the thread is already active in one or more POAManagers, AND it tries to enter a new POAManager. Such exceptions should be re-tried by the client, and will succeed after the holding POAManagers have been resumed. Another possible route to fix the app server bug (more globally) is to have the RFM suspend method use discard instead of hold. This may be better in some ways, but early tests with that approach led to some problems (which I can't recall right now). I suspect the issues may have been related to problems with the client-side retry logic, but those problems have now been fixed. In any case, we need to fix the POAManager issues.
    • Method Detail

      • stateToString

        private java.lang.String stateToString​(State state)
      • hashCode

        public int hashCode()
        Overrides:
        hashCode in class java.lang.Object
      • equals

        public boolean equals​(java.lang.Object obj)
        Overrides:
        equals in class java.lang.Object
      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object
      • getManagedPOAs

        @ManagedAttribute
        @Description("The set of POAs managed by this POAManager")
        java.util.Set<POAImpl> getManagedPOAs()
      • numberOfInvocations

        @ManagedAttribute
        @Description("Number of active invocations executing in this POAManager")
        public int numberOfInvocations()
      • numberOfWaiters

        @ManagedAttribute
        @Description("Number of threads waiting for invocations to complete in this POAManager")
        public int numberOfWaiters()
      • displayState

        @ManagedAttribute
        @Description("The current state of this POAManager")
        public java.lang.String displayState()
      • getFactory

        @ManagedAttribute
        @Description("The POAFactory that manages this POAManager")
        POAFactory getFactory()
      • numWaitersStart

        @InfoMethod
        private void numWaitersStart​(int value)
      • numWaitersEnd

        @InfoMethod
        private void numWaitersEnd​(int value)
      • countedWait

        private void countedWait()
      • nWaiters

        @InfoMethod
        private void nWaiters​(int value)
      • notifyWaiters

        private void notifyWaiters()
      • getManagerId

        @ManagedAttribute
        @NameValue
        @Description("The ID of this POAManager")
        public int getManagerId()
      • addPOA

        void addPOA​(POAImpl poa)
      • removePOA

        void removePOA​(POAImpl poa)
      • getORTState

        @ManagedAttribute
        @Description("The ObjectReferenceTemplate state of this POAManager")
        public short getORTState()
      • activate

        @ManagedOperation
        @Description("Make this POAManager active, so it can handle new requests")
        public void activate()
                      throws AdapterInactive
        activate Spec: pages 3-14 thru 3-18
        Specified by:
        activate in interface POAManagerOperations
        Throws:
        AdapterInactive - is raised if the operation is invoked on the POAManager in inactive state.
      • hold_requests

        @ManagedOperation
        @Description("Hold all requests to this POAManager")
        public void hold_requests​(boolean wait_for_completion)
                           throws AdapterInactive
        hold_requests Spec: pages 3-14 thru 3-18
        Specified by:
        hold_requests in interface POAManagerOperations
        Parameters:
        wait_for_completion - if FALSE, the operation returns immediately after changing state. If TRUE, it waits for all active requests to complete.
        Throws:
        AdapterInactive - is raised if the operation is invoked on the POAManager in inactive state.
      • discard_requests

        @ManagedOperation
        @ParameterNames("waitForCompletion")
        @Description("Make this POAManager discard all incoming requests")
        public void discard_requests​(boolean wait_for_completion)
                              throws AdapterInactive
        discard_requests Spec: pages 3-14 thru 3-18
        Specified by:
        discard_requests in interface POAManagerOperations
        Parameters:
        wait_for_completion - if FALSE, the operation returns immediately after changing state. If TRUE, it waits for all active requests to complete.
        Throws:
        AdapterInactive - is raised if the operation is invoked on the POAManager in inactive state.
      • deactivate

        public void deactivate​(boolean etherealize_objects,
                               boolean wait_for_completion)
                        throws AdapterInactive
        deactivate Spec: pages 3-14 thru 3-18 Note: INACTIVE is a permanent state.
        Specified by:
        deactivate in interface POAManagerOperations
        Parameters:
        etherealize_objects - a flag to indicate whether to invoke the etherealize operation of the associated servant manager for all active objects.
        wait_for_completion - if FALSE, the operation returns immediately after changing state. If TRUE, it waits for all active requests to complete.
        Throws:
        AdapterInactive - is raised if the operation is invoked on the POAManager in inactive state.
      • get_state

        public State get_state()
        Added according to the spec CORBA V2.3; this returns the state of the POAManager
        Specified by:
        get_state in interface POAManagerOperations
        Returns:
        the state of the manager
      • activeManagers

        @InfoMethod
        private void activeManagers​(org.glassfish.pfl.basic.contain.MultiSet<POAManagerImpl> am)
        The following methods are used on the invocation path.
      • alreadyActive

        @InfoMethod
        private void alreadyActive​(POAManagerImpl pm)
      • activeInDifferentPoaManager

        @InfoMethod
        private void activeInDifferentPoaManager()
      • checkState

        private void checkState()
      • addingThreadToActiveManagers

        @InfoMethod
        private void addingThreadToActiveManagers​(POAManagerImpl pmi)
      • removingThreadFromActiveManagers

        @InfoMethod
        private void removingThreadFromActiveManagers​(POAManagerImpl pmi)
      • enter

        void enter()
      • exit

        void exit()
      • implicitActivation

        public void implicitActivation()
        Activate the POAManager if no explicit state change has ever been previously invoked.