Well, it appears that the above *is* possible - but I wonder whether that is a 
bug. Basically, because of failSilently==true putForExternalRead ends up adding 
Node to MVCCInvocationContext.lookedUpNodes but subsequent evictNode() uses 
MVCCInvocationContext.mvccTCtx to look up the same node (and fails to find it)

Setup: Hibernate, JBC 3.0.3.GA; MVCC; JTA tm injected; REPEATABLE_READ iso

Consider the following scenario:
pre: cache is empty

tx.begin()
cache.putForExternalRead(fqnA, val);
cache.evictNode(fqnA) //expect eviction to succeed
tx.commit()

1. By the time invocationContextInteceptor invokes next interceptor, 
mvccInvocationContext.mvccTCtx is null!

Given failSilently=true in putForExternalRead:
         getInvocationContext().getOptionOverrides().setFailSilently(true);
  |          
getInvocationContext().getOptionOverrides().setForceAsynchronous(true);
  |          PutForExternalReadCommand command = 
commandsFactory.buildPutForExternalReadCommand(null, fqn, key, value);
  |          invoker.invoke(ctx, command);
... InvocationContextInterceptor sets transactionalContext twice in handleAll 
(at lines 150 and 164):

         if (txManager != null)
  |          {
  |             Transaction tx = getTransaction();
  |             GlobalTransaction realGtx = getGlobalTransaction(tx, gtx);
  |             if (tx == null && realGtx != null && realGtx.isRemote()) tx = 
txTable.getLocalTransaction(gtx);
  |             setTransactionalContext(tx, realGtx, null, ctx);
  |          }

..and


         if (optionOverride != null && optionOverride.isFailSilently())
  |          {
  |             log.debug("FAIL_SILENTLY Option is present - suspending any 
ongoing transaction.");
  |             suppressExceptions = true;
  |             if (ctx.getTransaction() != null)
  |             {
  |                suspendedTransaction = txManager.suspend();
  |                setTransactionalContext(null, null, null, ctx); 
  |                if (trace) log.trace("Suspending transaction " + 
suspendedTransaction);
  |                resumeSuspended = true;
  |             }

The first invocation of setTransactionalContext injects valid 
TransactionContext, Transaction into MVCCInvocationContext. but the second 
invocation clears them, such that invocationContext.getTransaction() will 
return null henceforth.

Subsequently other interceptors are invoked, including TxInterceptor, whose 
attachGtxAndPassUpChain does not attach anything because 
ctx.getTransaction()==null. For the remainder of this invocation 
MVCCInvocationContext.mvccTCtx remains null and ctx.lookedUpNodes is used.

2. Cache.evictNode fails to evict because ctx.lookUpNode looks in mvccTCtx and 
does not find Node.

Subsequent Cache.evictNode(fqn) does not use failSilently option, so 
setTransactionalContext in InvocationContextInterceptor is NOT called twice and 
valid transactionContext remains injected into invocationContext. So, when 
ctx.lookUpNode() is called from EvictCommand.perform, existing ctx.mvccTCtx is 
consulted (and NOT 'lookUpNodes'). And thus, the node is not found, and 
eviction is not performed. NOTE: seems like any command that uses 
ctx.lookUpNode and is NOT invoked with failSilently==true will fail to lookup 
this node for the same reason.

Also note that in NotifierImpl.resetInvocationContext lookedUpNodes are copied, 
so the above not-evicted-node would be copied as well.

Thoughts?

If the does seem like a bug, the obvious solution seems to be not to use 
failSilently option in Cache.putForExternalRead (and in other places?). What 
would be the implication?



View the original post : 
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4216349#4216349

Reply to the post : 
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4216349
_______________________________________________
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user

Reply via email to