]
Galder Zamarreño updated ISPN-9314:
-----------------------------------
Status: Resolved (was: Pull Request Sent)
Resolution: Done
AtomicKeySetImpl deserialization should not modify running
transaction
----------------------------------------------------------------------
Key: ISPN-9314
URL:
https://issues.jboss.org/browse/ISPN-9314
Project: Infinispan
Issue Type: Bug
Components: Core
Affects Versions: 9.3.0.CR1
Reporter: Dan Berindei
Assignee: Dan Berindei
Fix For: 9.3.0.Final
{{AtomicKeySetImpl.Externalizer.readObject()}} invokes a {{GetKeysInGroupCommand}} with a
new context, but if a transaction is already running on the same thread it will reuse the
transaction. Since tx contexts are just a wrapper over the {{CacheTransaction}}, looking
up entries for the {{GetKeysInGroupCommand}} modifies the parent invocation context as
well.
Every time an {{AtomicKeySetImpl}} is read in a transaction and then passivated before
commit, the externalizer thus adds the members of the group in the parent
transaction's context:
{noformat}
testng-test: Committing {AtomicKeySetImpl.Key{group=key1,
key=second}=VersionedRepeatableReadEntry(58cf8f94){key=AtomicKeySetImpl.Key{group=key1,
key=second}, value=second component of object with key=key1, isCreated=true,
isChanged=true, isRemoved=false, isExpired=false, skipLookup=true,
metadata=EmbeddedExpirableMetadata{lifespan=-1, maxIdle=-1,
version=NumericVersion{version=0}}}, key1=VersionedRepeatableReadEntry(66c38e51)
{key=key1, value=AtomicKeySetImpl{keys=[AtomicKeySetImpl.Key{group=key1, key=first},
first], added=[second], removed=null}, isCreated=false, isChanged=true, isRemoved=false,
isExpired=false, skipLookup=true,
metadata=MetaParamsInternalMetadata{params=MetaParams{length=1,
metas=[MetaEntryVersion=NumericVersion{version=2}]}}}}
Breakpoint reached
at
org.infinispan.transaction.impl.LocalTransaction.putLookedUpEntry(LocalTransaction.java:107)
at
org.infinispan.context.impl.AbstractTxInvocationContext.putLookedUpEntry(AbstractTxInvocationContext.java:105)
at
org.infinispan.container.impl.EntryFactoryImpl.wrapExternalEntry(EntryFactoryImpl.java:173)
at
org.infinispan.interceptors.impl.CacheLoaderInterceptor.lambda$visitGetKeysInGroupCommand$2(CacheLoaderInterceptor.java:208)
at
org.infinispan.interceptors.impl.CacheLoaderInterceptor$$Lambda$304.1315908533.accept(Unknown
Source:-1)
at io.reactivex.Flowable.blockingForEach(Flowable.java:5325)
at
org.infinispan.interceptors.impl.CacheLoaderInterceptor.visitGetKeysInGroupCommand(CacheLoaderInterceptor.java:208)
at
org.infinispan.commands.remote.GetKeysInGroupCommand.acceptVisitor(GetKeysInGroupCommand.java:91)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextThenAccept(BaseAsyncInterceptor.java:98)
at
org.infinispan.interceptors.impl.EntryWrappingInterceptor.visitGetKeysInGroupCommand(EntryWrappingInterceptor.java:427)
at
org.infinispan.commands.remote.GetKeysInGroupCommand.acceptVisitor(GetKeysInGroupCommand.java:91)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextAndFinally(BaseAsyncInterceptor.java:150)
at
org.infinispan.interceptors.impl.GroupingInterceptor.visitGetKeysInGroupCommand(GroupingInterceptor.java:50)
at
org.infinispan.commands.remote.GetKeysInGroupCommand.acceptVisitor(GetKeysInGroupCommand.java:91)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNext(BaseAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.handleDefault(DDAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.visitGetKeysInGroupCommand(DDAsyncInterceptor.java:177)
at
org.infinispan.commands.remote.GetKeysInGroupCommand.acceptVisitor(GetKeysInGroupCommand.java:91)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNext(BaseAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.handleDefault(DDAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.visitGetKeysInGroupCommand(DDAsyncInterceptor.java:177)
at
org.infinispan.commands.remote.GetKeysInGroupCommand.acceptVisitor(GetKeysInGroupCommand.java:91)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNext(BaseAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.handleDefault(DDAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.visitGetKeysInGroupCommand(DDAsyncInterceptor.java:177)
at
org.infinispan.commands.remote.GetKeysInGroupCommand.acceptVisitor(GetKeysInGroupCommand.java:91)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNext(BaseAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.handleDefault(DDAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.visitGetKeysInGroupCommand(DDAsyncInterceptor.java:177)
at
org.infinispan.commands.remote.GetKeysInGroupCommand.acceptVisitor(GetKeysInGroupCommand.java:91)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextAndExceptionally(BaseAsyncInterceptor.java:123)
at
org.infinispan.interceptors.impl.InvocationContextInterceptor.visitCommand(InvocationContextInterceptor.java:90)
at
org.infinispan.interceptors.impl.AsyncInterceptorChainImpl.invoke(AsyncInterceptorChainImpl.java:248)
at
org.infinispan.atomic.impl.AtomicKeySetImpl$Externalizer.readObject(AtomicKeySetImpl.java:498)
at
org.infinispan.atomic.impl.AtomicKeySetImpl$Externalizer.readObject(AtomicKeySetImpl.java:466)
at
org.infinispan.marshall.core.GlobalMarshaller.readWithExternalizer(GlobalMarshaller.java:708)
at
org.infinispan.marshall.core.GlobalMarshaller.readNonNullableObject(GlobalMarshaller.java:691)
at
org.infinispan.marshall.core.GlobalMarshaller.readNullableObject(GlobalMarshaller.java:361)
at org.infinispan.marshall.core.BytesObjectInput.readObject(BytesObjectInput.java:40)
at org.infinispan.util.KeyValuePair$Externalizer.readObject(KeyValuePair.java:49)
at org.infinispan.util.KeyValuePair$Externalizer.readObject(KeyValuePair.java:37)
at
org.infinispan.marshall.core.GlobalMarshaller.readWithExternalizer(GlobalMarshaller.java:708)
at
org.infinispan.marshall.core.GlobalMarshaller.readNonNullableObject(GlobalMarshaller.java:691)
at
org.infinispan.marshall.core.GlobalMarshaller.readNullableObject(GlobalMarshaller.java:361)
at
org.infinispan.marshall.core.GlobalMarshaller.objectFromObjectInput(GlobalMarshaller.java:194)
at
org.infinispan.marshall.core.GlobalMarshaller.objectFromByteBuffer(GlobalMarshaller.java:190)
at
org.infinispan.persistence.dummy.DummyInMemoryStore.deserialize(DummyInMemoryStore.java:363)
at
org.infinispan.persistence.dummy.DummyInMemoryStore.load(DummyInMemoryStore.java:160)
at
org.infinispan.persistence.manager.PersistenceManagerImpl.loadFromAllStores(PersistenceManagerImpl.java:551)
at
org.infinispan.persistence.PersistenceUtil.loadAndCheckExpiration(PersistenceUtil.java:219)
at
org.infinispan.persistence.PersistenceUtil.lambda$loadAndComputeInDataContainer$2(PersistenceUtil.java:196)
at org.infinispan.persistence.PersistenceUtil$$Lambda$295.869610006.compute(Unknown
Source:-1)
at
org.infinispan.container.impl.AbstractInternalDataContainer.lambda$compute$3(AbstractInternalDataContainer.java:231)
at
org.infinispan.container.impl.AbstractInternalDataContainer$$Lambda$274.1969969319.apply(Unknown
Source:-1)
at
com.github.benmanes.caffeine.cache.BoundedLocalCache.lambda$remap$16(BoundedLocalCache.java:2199)
at
com.github.benmanes.caffeine.cache.BoundedLocalCache$$Lambda$275.2081595126.apply(Unknown
Source:-1)
at java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1853)
at
com.github.benmanes.caffeine.cache.BoundedLocalCache.remap(BoundedLocalCache.java:2194)
at
com.github.benmanes.caffeine.cache.BoundedLocalCache.compute(BoundedLocalCache.java:2146)
at com.github.benmanes.caffeine.cache.LocalCache.compute(LocalCache.java:100)
at
org.infinispan.container.impl.AbstractInternalDataContainer.compute(AbstractInternalDataContainer.java:230)
at
org.infinispan.persistence.PersistenceUtil.loadAndComputeInDataContainer(PersistenceUtil.java:206)
at org.infinispan.statetransfer.CommitManager.commitEntry(CommitManager.java:129)
at org.infinispan.statetransfer.CommitManager.commit(CommitManager.java:97)
at
org.infinispan.interceptors.locking.ClusteringDependentLogic$LocalLogic.commitSingleEntry(ClusteringDependentLogic.java:352)
at
org.infinispan.interceptors.locking.ClusteringDependentLogic$AbstractClusteringDependentLogic.commitEntry(ClusteringDependentLogic.java:189)
at
org.infinispan.interceptors.impl.VersionedEntryWrappingInterceptor.commitContextEntry(VersionedEntryWrappingInterceptor.java:116)
at
org.infinispan.interceptors.impl.EntryWrappingInterceptor.commitEntryIfNeeded(EntryWrappingInterceptor.java:813)
at
org.infinispan.interceptors.impl.EntryWrappingInterceptor.lambda$commitContextEntries$7(EntryWrappingInterceptor.java:570)
at
org.infinispan.interceptors.impl.EntryWrappingInterceptor$$Lambda$293.268086000.accept(Unknown
Source:-1)
at java.util.HashMap.forEach(HashMap.java:1289)
at org.infinispan.context.EntryLookup.forEachEntry(EntryLookup.java:38)
at
org.infinispan.interceptors.impl.EntryWrappingInterceptor.commitContextEntries(EntryWrappingInterceptor.java:569)
at
org.infinispan.interceptors.impl.VersionedEntryWrappingInterceptor.doCommit(VersionedEntryWrappingInterceptor.java:95)
at
org.infinispan.interceptors.impl.VersionedEntryWrappingInterceptor.lambda$visitCommitCommand$1(VersionedEntryWrappingInterceptor.java:87)
at
org.infinispan.interceptors.impl.VersionedEntryWrappingInterceptor$$Lambda$288.836170750.accept(Unknown
Source:-1)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextAndFinally(BaseAsyncInterceptor.java:163)
at
org.infinispan.interceptors.impl.VersionedEntryWrappingInterceptor.visitCommitCommand(VersionedEntryWrappingInterceptor.java:86)
at org.infinispan.commands.tx.CommitCommand.acceptVisitor(CommitCommand.java:38)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNext(BaseAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.handleDefault(DDAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.visitCommitCommand(DDAsyncInterceptor.java:142)
at org.infinispan.commands.tx.CommitCommand.acceptVisitor(CommitCommand.java:38)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextThenAccept(BaseAsyncInterceptor.java:98)
at
org.infinispan.interceptors.impl.NotificationInterceptor.visitCommitCommand(NotificationInterceptor.java:46)
at org.infinispan.commands.tx.CommitCommand.acceptVisitor(CommitCommand.java:38)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextAndFinally(BaseAsyncInterceptor.java:150)
at
org.infinispan.interceptors.locking.AbstractTxLockingInterceptor.visitCommitCommand(AbstractTxLockingInterceptor.java:51)
at org.infinispan.commands.tx.CommitCommand.acceptVisitor(CommitCommand.java:38)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextThenAccept(BaseAsyncInterceptor.java:98)
at
org.infinispan.interceptors.impl.TxInterceptor.finishCommit(TxInterceptor.java:189)
at
org.infinispan.interceptors.impl.TxInterceptor.visitCommitCommand(TxInterceptor.java:183)
at org.infinispan.commands.tx.CommitCommand.acceptVisitor(CommitCommand.java:38)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNext(BaseAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.handleDefault(DDAsyncInterceptor.java:54)
at
org.infinispan.interceptors.DDAsyncInterceptor.visitCommitCommand(DDAsyncInterceptor.java:142)
at org.infinispan.commands.tx.CommitCommand.acceptVisitor(CommitCommand.java:38)
at
org.infinispan.interceptors.BaseAsyncInterceptor.invokeNextAndExceptionally(BaseAsyncInterceptor.java:123)
at
org.infinispan.interceptors.impl.InvocationContextInterceptor.visitCommand(InvocationContextInterceptor.java:90)
at
org.infinispan.interceptors.impl.AsyncInterceptorChainImpl.invoke(AsyncInterceptorChainImpl.java:248)
at org.infinispan.interceptors.InterceptorChain.invoke(InterceptorChain.java:137)
at
org.infinispan.transaction.impl.TransactionCoordinator.commitInternal(TransactionCoordinator.java:219)
at
org.infinispan.transaction.impl.TransactionCoordinator.commit(TransactionCoordinator.java:161)
at
org.infinispan.transaction.xa.XaTransactionTable.commit(XaTransactionTable.java:125)
at
org.infinispan.transaction.xa.TransactionXaAdapter.commit(TransactionXaAdapter.java:68)
at
com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord.topLevelOnePhaseCommit(XAResourceRecord.java:698)
at
com.arjuna.ats.arjuna.coordinator.BasicAction.onePhaseCommit(BasicAction.java:2364)
at com.arjuna.ats.arjuna.coordinator.BasicAction.End(BasicAction.java:1518)
at
com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:96)
at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162)
at
com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1200)
at
com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:126)
at org.infinispan.atomic.impl.TransactionHelper.run(TransactionHelper.java:75)
at
org.infinispan.atomic.impl.FineGrainedAtomicMapProxyImpl.put(FineGrainedAtomicMapProxyImpl.java:186)
at
org.infinispan.atomic.LocalDeltaAwareEvictionTest$5.createObject(LocalDeltaAwareEvictionTest.java:279)
at
org.infinispan.atomic.LocalDeltaAwareEvictionTest$5.createObject(LocalDeltaAwareEvictionTest.java:273)
at
org.infinispan.atomic.LocalDeltaAwareEvictionTest$1.call(LocalDeltaAwareEvictionTest.java:95)
at
org.infinispan.atomic.LocalDeltaAwareEvictionTest.withTx(LocalDeltaAwareEvictionTest.java:78)
at
org.infinispan.atomic.LocalDeltaAwareEvictionTest.test(LocalDeltaAwareEvictionTest.java:92)
at
org.infinispan.atomic.LocalDeltaAwareEvictionTest.testFineGrainedAtomicMap(LocalDeltaAwareEvictionTest.java:269)
testng-test: Adding entry AtomicKeySetImpl.Key{group=key1, key=first} :
VersionedRepeatableReadEntry(fabb651){key=AtomicKeySetImpl.Key{group=key1, key=first},
value=first component of object with key=key1, isCreated=false, isChanged=false,
isRemoved=false, isExpired=false, skipLookup=false,
metadata=EmbeddedExpirableMetadata{lifespan=-1, maxIdle=-1,
version=NumericVersion{version=2}}}
{noformat}
Interesting enough, the {{Iterator}}-based iteration in
{{EntryWrappingInterceptor.commitContextEntries}} doesn't throw a
{{ConcurrentModificationException}} after this modification (at least in
{{LocalDeltaAwareEvictionTest}}). It only started failing after I replaced the iterator
with {{HashMap.forEach()}}.