[jboss-user] [JBoss Cache: Core Edition] - Re: is it possible for MVCCInvocationContext to have null mv

dukehoops do-not-reply at jboss.com
Mon Mar 9 14:54:27 EDT 2009


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



More information about the jboss-user mailing list