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;
}
}
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;
}
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;
}
Aggregations