Search in sources :

Example 1 with MethodLockInfo

use of com.sun.ejb.MethodLockInfo in project Payara by payara.

the class SafeProperties method setConcurrencyInvInfo.

private void setConcurrencyInvInfo(Method invInfoMethod, String methodIntf, InvocationInfo invInfo) {
    MethodLockInfo lockInfo = null;
    // Set READ/WRITE lock info.  Only applies to singleton beans.
    if (isSingleton) {
        EjbSessionDescriptor singletonDesc = (EjbSessionDescriptor) ejbDescriptor;
        List<MethodDescriptor> readLockMethods = singletonDesc.getReadLockMethods();
        List<MethodDescriptor> writeLockMethods = singletonDesc.getWriteLockMethods();
        DistributedLockType distLockType = singletonDesc.isClustered() ? singletonDesc.getClusteredLockType() : DistributedLockType.LOCK_NONE;
        for (MethodDescriptor readLockMethodDesc : readLockMethods) {
            Method readLockMethod = readLockMethodDesc.getMethod(singletonDesc);
            if (implMethodMatchesInvInfoMethod(invInfoMethod, methodIntf, readLockMethod)) {
                lockInfo = new MethodLockInfo();
                switch(distLockType) {
                    case INHERIT:
                        {
                            _logger.log(Level.WARNING, "Distributed Read Lock for Method {0} Upgraded to Read/Write", readLockMethod.getName());
                            lockInfo.setLockType(LockType.WRITE, true);
                            break;
                        }
                    case LOCK_NONE:
                        {
                            lockInfo.setLockType(LockType.READ, false);
                        }
                }
                break;
            }
        }
        if (lockInfo == null) {
            for (MethodDescriptor writeLockMethodDesc : writeLockMethods) {
                Method writeLockMethod = writeLockMethodDesc.getMethod(singletonDesc);
                if (implMethodMatchesInvInfoMethod(invInfoMethod, methodIntf, writeLockMethod)) {
                    lockInfo = new MethodLockInfo();
                    lockInfo.setLockType(LockType.WRITE, distLockType != DistributedLockType.LOCK_NONE);
                    break;
                }
            }
        }
    }
    // Set AccessTimeout info
    if (isSingleton || isStatefulSession) {
        EjbSessionDescriptor sessionDesc = (EjbSessionDescriptor) ejbDescriptor;
        List<EjbSessionDescriptor.AccessTimeoutHolder> accessTimeoutInfo = sessionDesc.getAccessTimeoutInfo();
        for (EjbSessionDescriptor.AccessTimeoutHolder accessTimeoutHolder : accessTimeoutInfo) {
            MethodDescriptor accessTimeoutMethodDesc = accessTimeoutHolder.method;
            Method accessTimeoutMethod = accessTimeoutMethodDesc.getMethod(sessionDesc);
            if (implMethodMatchesInvInfoMethod(invInfoMethod, methodIntf, accessTimeoutMethod)) {
                if (lockInfo == null) {
                    lockInfo = new MethodLockInfo();
                }
                lockInfo.setTimeout(accessTimeoutHolder.value, accessTimeoutHolder.unit);
                break;
            }
        }
    }
    if (lockInfo != null) {
        invInfo.methodLockInfo = lockInfo;
    }
}
Also used : DistributedLockType(fish.payara.cluster.DistributedLockType) Method(java.lang.reflect.Method) EjbSessionDescriptor(org.glassfish.ejb.deployment.descriptor.EjbSessionDescriptor) MethodDescriptor(com.sun.enterprise.deployment.MethodDescriptor) MethodLockInfo(com.sun.ejb.MethodLockInfo)

Example 2 with MethodLockInfo

use of com.sun.ejb.MethodLockInfo in project Payara by payara.

the class CMCSingletonContainer method _getContext.

/*
     * Findbugs complains that the lock acquired in this method is not
     *  unlocked on all paths in this method.
     *
     * Even though the method doesn't unlock the (possibly) acquired
     * lock, the lock is guaranteed to be unlocked in releaseContext()
     * even in the presence of (both checked and unchecked) exceptions.
     *
     * The general pattern used by various parts of the EJB container code is:
     *
     * try {
     *      container.preInvoke(inv);
     *      returnValue = container.intercept(inv);
     * } catch (Exception1 e1) {
     *      ...
     * } catch (Exception2 e2) {
     *      ...
     * } finally {
     *      container.postInvoke();
     * }
     *
     * Thus, it is clear that, BaseContainer.postInvoke() which in turn
     * calls releaseContext() will be called if container.preInvoke()
     * is called. This ensures that CMCSingletonContainer (this class)
     * releases the lock acquired by _getContext().
     *
     * Also, note that the above works even for loopback methods as
     * container.preInvoke() and container,postInvoke() will be called
     * before every bean method.
     *
     */
@Override
protected ComponentContext _getContext(EjbInvocation inv) {
    super._getContext(inv);
    InvocationInfo invInfo = inv.invocationInfo;
    MethodLockInfo lockInfo = (invInfo.methodLockInfo == null) ? defaultMethodLockInfo : invInfo.methodLockInfo;
    Lock theLock;
    if (lockInfo.isDistributed()) {
        if (_logger.isLoggable(Level.FINE)) {
            // log all lock operations
            theLock = (Lock) Proxy.newProxyInstance(loader, new Class<?>[] { Lock.class }, (proxy, method, args) -> {
                FencedLock fencedLock = clusteredLookup.getDistributedLock();
                _logger.log(Level.FINE, "DistributedLock, about to call {0}, Locked: {1}, Locked by Us: {2}, thread ID {3}", new Object[] { method.getName(), fencedLock.isLocked(), fencedLock.isLockedByCurrentThread(), Thread.currentThread().getId() });
                Object rv = method.invoke(fencedLock, args);
                _logger.log(Level.FINE, "DistributedLock, after to call {0}, Locked: {1}, Locked by Us: {2}, thread ID {3}", new Object[] { method.getName(), fencedLock.isLocked(), fencedLock.isLockedByCurrentThread(), Thread.currentThread().getId() });
                return rv;
            });
        } else {
            theLock = clusteredLookup.getDistributedLock();
        }
    } else {
        theLock = lockInfo.isReadLockedMethod() ? readLock : writeLock;
    }
    if ((rwLock.getReadHoldCount() > 0) && (!rwLock.isWriteLockedByCurrentThread())) {
        if (lockInfo.isWriteLockedMethod()) {
            throw new IllegalLoopbackException("Illegal Reentrant Access : Attempt to make " + "a loopback call on a Write Lock method '" + invInfo.targetMethod1 + "' while a Read lock is already held");
        }
    }
    /*
         * Please see comment at the beginning of the method.
         * Even though the method doesn't unlock the (possibly) acquired
         * lock, the lock is guaranteed to be unlocked in releaseContext()
         * even if exceptions were thrown in _getContext()
         */
    if (!lockInfo.hasTimeout() || ((lockInfo.hasTimeout() && (lockInfo.getTimeout() == BLOCK_INDEFINITELY)))) {
        theLock.lock();
    } else {
        try {
            boolean lockStatus = theLock.tryLock(lockInfo.getTimeout(), lockInfo.getTimeUnit());
            if (!lockStatus) {
                String msg = "Couldn't acquire a lock within " + lockInfo.getTimeout() + " " + lockInfo.getTimeUnit();
                if (lockInfo.getTimeout() == NO_BLOCKING) {
                    throw new ConcurrentAccessException(msg);
                } else {
                    throw new ConcurrentAccessTimeoutException(msg);
                }
            }
        } catch (InterruptedException inEx) {
            String msg = "Couldn't acquire a lock within " + lockInfo.getTimeout() + " " + lockInfo.getTimeUnit();
            ConcurrentAccessException cae = (lockInfo.getTimeout() == NO_BLOCKING) ? new ConcurrentAccessException(msg) : new ConcurrentAccessTimeoutException(msg);
            cae.initCause(inEx);
            throw cae;
        }
    }
    // Now that we have acquired the lock, remember it
    inv.setCMCLock(theLock);
    // Now that we have the lock return the singletonCtx
    return singletonCtx;
}
Also used : IllegalLoopbackException(javax.ejb.IllegalLoopbackException) InvocationInfo(com.sun.ejb.InvocationInfo) FencedLock(com.hazelcast.cp.lock.FencedLock) ConcurrentAccessException(javax.ejb.ConcurrentAccessException) ConcurrentAccessTimeoutException(javax.ejb.ConcurrentAccessTimeoutException) MethodLockInfo(com.sun.ejb.MethodLockInfo) FencedLock(com.hazelcast.cp.lock.FencedLock) ReentrantReadWriteLock(java.util.concurrent.locks.ReentrantReadWriteLock) Lock(java.util.concurrent.locks.Lock)

Example 3 with MethodLockInfo

use of com.sun.ejb.MethodLockInfo in project Payara by payara.

the class AsynchronousTask method _getContext.

/**
 * Called from preInvoke which is called from the EJBObject
 * for local and remote invocations.
 */
@Override
public ComponentContext _getContext(EjbInvocation ejbInvocation) {
    EJBLocalRemoteObject ejbObject = ejbInvocation.ejbObject;
    Serializable sessionKey = (Serializable) ejbObject.getKey();
    logTraceInfo(ejbInvocation, sessionKey, "Trying to get context");
    SessionContextImpl sessionContext = getSessionContext(ejbInvocation, ejbObject, sessionKey);
    MethodLockInfo lockInfo = ejbInvocation.invocationInfo.methodLockInfo;
    boolean allowSerializedAccess = isAllowSerializedAccess(lockInfo);
    if (allowSerializedAccess) {
        aquireStatefulLockOrThrow(ejbInvocation, sessionContext, lockInfo);
        // Explicitly set state to track that we're holding the lock for this invocation.
        // No matter what we need to ensure that the lock is released.   In some
        // cases releaseContext() isn't called so for safety we'll have more than one
        // place that can potentially release the lock.  The invocation state will ensure
        // we don't accidently unlock too many times.
        ejbInvocation.setHoldingSFSBSerializedLock(true);
    }
    SessionContextImpl context = null;
    try {
        synchronized (sessionContext) {
            SessionContextImpl newSessionContext = sessionContext;
            if (sessionContext.getState() == PASSIVATED) {
                // This is possible if the EJB was passivated after
                // the last lookupEJB. Try to activate it again.
                newSessionContext = (SessionContextImpl) sessionBeanCache.lookupEJB(sessionKey, this, ejbObject);
                if (newSessionContext == null) {
                    logTraceInfo(ejbInvocation, sessionKey, "Context does not exist");
                    // EJB2.0 section 7.6
                    throw new NoSuchObjectLocalException("The EJB does not exist. key: " + sessionKey);
                }
                // Swap any stateful lock that was set on the original sc
                newSessionContext.setStatefulWriteLock(sessionContext);
            }
            // Acquire the lock again, in case a new session context was returned.
            synchronized (newSessionContext) {
                // Check & set the state of the EJB
                if (newSessionContext.getState() == DESTROYED) {
                    logTraceInfo(ejbInvocation, sessionKey, "Got destroyed context");
                    throw new NoSuchObjectLocalException("The EJB does not exist. session-key: " + sessionKey);
                } else if (newSessionContext.getState() == INVOKING) {
                    handleConcurrentInvocation(allowSerializedAccess, ejbInvocation, newSessionContext, sessionKey);
                }
                if (newSessionContext.getState() == READY) {
                    decrementMethodReadyStat();
                }
                if (isHAEnabled) {
                    doVersionCheck(ejbInvocation, sessionKey, sessionContext);
                }
                newSessionContext.setState(INVOKING);
                context = newSessionContext;
            }
        }
        // Touch the context here so timestamp is set & timeout is prevented
        context.touch();
        if (context.existsInStore() && removalGracePeriodInSeconds > 0) {
            updateLastPersistedTime(context, sessionKey);
        }
        logTraceInfo(ejbInvocation, context, "Got Context!!");
    } catch (RuntimeException t) {
        // ReleaseContext isn't called if this method throws an exception,
        // so make sure to release any sfsb lock
        releaseSFSBSerializedLock(ejbInvocation, sessionContext);
        throw t;
    }
    return context;
}
Also used : NoSuchObjectLocalException(javax.ejb.NoSuchObjectLocalException) Serializable(java.io.Serializable) IndirectlySerializable(com.sun.enterprise.container.common.spi.util.IndirectlySerializable) MethodLockInfo(com.sun.ejb.MethodLockInfo)

Aggregations

MethodLockInfo (com.sun.ejb.MethodLockInfo)3 FencedLock (com.hazelcast.cp.lock.FencedLock)1 InvocationInfo (com.sun.ejb.InvocationInfo)1 IndirectlySerializable (com.sun.enterprise.container.common.spi.util.IndirectlySerializable)1 MethodDescriptor (com.sun.enterprise.deployment.MethodDescriptor)1 DistributedLockType (fish.payara.cluster.DistributedLockType)1 Serializable (java.io.Serializable)1 Method (java.lang.reflect.Method)1 Lock (java.util.concurrent.locks.Lock)1 ReentrantReadWriteLock (java.util.concurrent.locks.ReentrantReadWriteLock)1 ConcurrentAccessException (javax.ejb.ConcurrentAccessException)1 ConcurrentAccessTimeoutException (javax.ejb.ConcurrentAccessTimeoutException)1 IllegalLoopbackException (javax.ejb.IllegalLoopbackException)1 NoSuchObjectLocalException (javax.ejb.NoSuchObjectLocalException)1 EjbSessionDescriptor (org.glassfish.ejb.deployment.descriptor.EjbSessionDescriptor)1