-
Bug
-
Resolution: Done
-
Major
-
9.3.0.Final
-
None
-
Sprint 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:
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}}}
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().