-
Bug
-
Resolution: Won't Do
-
Major
-
None
-
6.0.2.Final
-
None
Using InfiniSpan as it's shipped with Jboss WildFly 8.1.0.Final as distributed cache for Hibernate, it appears that the ClearCommand does not work in a cluster when pessimistic locking is used. Pessimistic locking seems to be the default in WildFly, even when theoretically it shouldn't be.
This will result in the following exception:
java.lang.ClassCastException: org.infinispan.context.impl.NonTxInvocationContext cannot be cast to org.infinispan.context.impl.TxInvocationContext at org.infinispan.interceptors.locking.PessimisticLockingInterceptor.visitClearCommand(PessimisticLockingInterceptor.java:194) at org.infinispan.commands.write.ClearCommand.acceptVisitor(ClearCommand.java:38) at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:98) at org.infinispan.interceptors.base.CommandInterceptor.handleDefault(CommandInterceptor.java:112) at org.infinispan.commands.AbstractVisitor.visitClearCommand(AbstractVisitor.java:47) at org.infinispan.commands.write.ClearCommand.acceptVisitor(ClearCommand.java:38) at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:98) at org.infinispan.interceptors.TxInterceptor.enlistWriteAndInvokeNext(TxInterceptor.java:255) at org.infinispan.interceptors.TxInterceptor.visitClearCommand(TxInterceptor.java:206) at org.infinispan.commands.write.ClearCommand.acceptVisitor(ClearCommand.java:38) at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:98) at org.infinispan.interceptors.base.CommandInterceptor.handleDefault(CommandInterceptor.java:112) at org.infinispan.commands.AbstractVisitor.visitClearCommand(AbstractVisitor.java:47) at org.infinispan.commands.write.ClearCommand.acceptVisitor(ClearCommand.java:38) at org.infinispan.interceptors.base.CommandInterceptor.invokeNextInterceptor(CommandInterceptor.java:98) at org.infinispan.interceptors.InvocationContextInterceptor.handleAll(InvocationContextInterceptor.java:110) at org.infinispan.interceptors.InvocationContextInterceptor.handleDefault(InvocationContextInterceptor.java:73) at org.infinispan.commands.AbstractVisitor.visitClearCommand(AbstractVisitor.java:47) at org.infinispan.commands.write.ClearCommand.acceptVisitor(ClearCommand.java:38) at org.infinispan.interceptors.InterceptorChain.invoke(InterceptorChain.java:333) at org.infinispan.commands.remote.BaseRpcInvokingCommand.processVisitableCommand(BaseRpcInvokingCommand.java:39) at org.infinispan.commands.remote.SingleRpcCommand.perform(SingleRpcCommand.java:48) at org.infinispan.remoting.InboundInvocationHandlerImpl.handleInternal(InboundInvocationHandlerImpl.java:95) at org.infinispan.remoting.InboundInvocationHandlerImpl.access$000(InboundInvocationHandlerImpl.java:50) at org.infinispan.remoting.InboundInvocationHandlerImpl$2.run(InboundInvocationHandlerImpl.java:172) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
The incoming command looks as follows:
CacheRpcCommand cmd: command: ClearCommand{flags=null} icf: org.infinispan.context.TransactionalInvocationContextFactory@3ef1861e Interceptor chain: >> org.infinispan.interceptors.InvocationContextInterceptor -- checks if stopping, otherwise continues >> org.infinispan.interceptors.CacheMgmtInterceptor -- does nothing >> org.infinispan.interceptors.TxInterceptor -- checks "shouldEnlist", if false does nothing >> org.infinispan.interceptors.NotificationInterceptor -- does nothing >> org.infinispan.interceptors.locking.PessimisticLockingInterceptor -- Throws exception if something in cache >> org.infinispan.interceptors.EntryWrappingInterceptor >> org.infinispan.interceptors.InvalidationInterceptor >> org.infinispan.interceptors.CallInterceptor
The problem seems to be that org.infinispan.commands.remote.BaseRpcInvokingCommand.processVisitableCommand always creates a NonTxInvocationContext. As per the following line of code:
final InvocationContext ctx = icf.createRemoteInvocationContextForCommand(vc, getOrigin());
When handling the ClearCommand, the PessimisticLockInterceptor always casts this to a TxInvocationContext whenever dataContainer is not empty, e.g. when there is cached data on the node where the clear command arrives. This happens in the following code:
public Object visitClearCommand(InvocationContext ctx, ClearCommand command) throws Throwable { try { boolean skipLocking = hasSkipLocking(command); long lockTimeout = getLockAcquisitionTimeout(command, skipLocking); for (InternalCacheEntry entry : dataContainer.entrySet()) lockAndRegisterBackupLock((TxInvocationContext) ctx, entry.getKey(), lockTimeout, skipLocking); return invokeNextInterceptor(ctx, command); } catch (Throwable te) { releaseLocksOnFailureBeforePrepare(ctx); throw te; } }
So seemingly this can't ever work.
Either the PessimisticLockingInterceptor can't be in a the interceptor chain when handling commands from a remote destination, or something has to be done about about the InvocationContext when handling remote commands?
- is related to
-
ISPN-5370 Make clear() non-transactional and lock free
- Closed