On 8 Jun 2011, at 11:44, Galder Zamarreño wrote: > > On Jun 7, 2011, at 2:41 PM, Mircea Markus wrote: > >> >> On 7 Jun 2011, at 13:13, Sanne Grinovero wrote: >> >>> Hello all, >>> in this scenario we have the Infinispan Lucene Directory using >>> batching (DummyTransaction), eviction and passivation to keep the >>> amount of memory being used for the index under control; I'm using >>> LIRS but experienced the same issue with all other strategies. >>> >>> As you can see from the following stacktrace, the batching ends by >>> sending a commit request, so the status of the transaction is 8 >>> (STATUS_COMMITTING) in this context. >>> The new data is stored in the DataContainer, then the >>> BoundedConcurrentHashMap notifies the EvictionManagerImpl as it has to >>> evict some values, and this one attempts to acquire a lock on the >>> to-be-evicted keys (which are obviously not the same I'm trying to >>> store). >>> Acquiring this lock is an invalid operation as the transaction is in >>> commit state, and so this operation fails with an exception. >>> >>> Thread [Hibernate Search: Directory writer-1] (Suspended (breakpoint >>> at line 92 in LockManagerImpl)) >>> LockManagerImpl.lockAndRecord(Object, InvocationContext) line: 92 >>> EvictionManagerImpl.acquireLock(InvocationContext, Object) line: 210 >>> EvictionManagerImpl.onEntryEviction(Object, InternalCacheEntry) line: >>> 170 >>> EvictionManagerImpl.onEntryEviction(Map<Object,InternalCacheEntry>) >>> line: 162 >>> >>> DefaultDataContainer$DefaultEvictionListener.onEntryEviction(Map<Object,InternalCacheEntry>) >>> line: 201 >>> >>> BoundedConcurrentHashMap$Segment<K,V>.notifyEvictionListener(Set<HashEntry<K,V>>) >>> line: 1176 >>> BoundedConcurrentHashMap$Segment<K,V>.put(K, int, V, boolean) line: >>> 1011 >>> BoundedConcurrentHashMap<K,V>.put(K, V) line: 1556 >>> DefaultDataContainer.put(Object, Object, long, long) line: 148 >>> ReadCommittedEntry.commit(DataContainer) line: 177 >>> LockingInterceptor.commitEntry(CacheEntry, boolean) line: 389 >>> LockingInterceptor.cleanupLocks(InvocationContext, boolean) line: 367 >>> LockingInterceptor.visitCommitCommand(TxInvocationContext, >>> CommitCommand) line: 98 >>> CommitCommand.acceptVisitor(InvocationContext, Visitor) line: 60 >>> >>> CacheStoreInterceptor(CommandInterceptor).invokeNextInterceptor(InvocationContext, >>> VisitableCommand) line: 119 >>> CacheStoreInterceptor.visitCommitCommand(TxInvocationContext, >>> CommitCommand) line: 148 >>> CommitCommand.acceptVisitor(InvocationContext, Visitor) line: 60 >>> >>> CacheLoaderInterceptor(CommandInterceptor).invokeNextInterceptor(InvocationContext, >>> VisitableCommand) line: 119 >>> >>> CacheLoaderInterceptor(CommandInterceptor).handleDefault(InvocationContext, >>> VisitableCommand) line: 133 >>> >>> CacheLoaderInterceptor(AbstractVisitor).visitCommitCommand(TxInvocationContext, >>> CommitCommand) line: 116 >>> CommitCommand.acceptVisitor(InvocationContext, Visitor) line: 60 >>> >>> NotificationInterceptor(CommandInterceptor).invokeNextInterceptor(InvocationContext, >>> VisitableCommand) line: 119 >>> NotificationInterceptor.visitCommitCommand(TxInvocationContext, >>> CommitCommand) line: 56 >>> CommitCommand.acceptVisitor(InvocationContext, Visitor) line: 60 >>> >>> TxInterceptor(CommandInterceptor).invokeNextInterceptor(InvocationContext, >>> VisitableCommand) line: 119 >>> TxInterceptor.visitCommitCommand(TxInvocationContext, CommitCommand) >>> line: 142 >>> CommitCommand.acceptVisitor(InvocationContext, Visitor) line: 60 >>> >>> CacheMgmtInterceptor(CommandInterceptor).invokeNextInterceptor(InvocationContext, >>> VisitableCommand) line: 119 >>> >>> CacheMgmtInterceptor(CommandInterceptor).handleDefault(InvocationContext, >>> VisitableCommand) line: 133 >>> >>> CacheMgmtInterceptor(AbstractVisitor).visitCommitCommand(TxInvocationContext, >>> CommitCommand) line: 116 >>> CommitCommand.acceptVisitor(InvocationContext, Visitor) line: 60 >>> >>> InvocationContextInterceptor(CommandInterceptor).invokeNextInterceptor(InvocationContext, >>> VisitableCommand) line: 119 >>> InvocationContextInterceptor.handleAll(InvocationContext, >>> VisitableCommand) line: 96 >>> InvocationContextInterceptor.handleDefault(InvocationContext, >>> VisitableCommand) line: 63 >>> >>> InvocationContextInterceptor(AbstractVisitor).visitCommitCommand(TxInvocationContext, >>> CommitCommand) line: 116 >>> CommitCommand.acceptVisitor(InvocationContext, Visitor) line: 60 >>> >>> BatchingInterceptor(CommandInterceptor).invokeNextInterceptor(InvocationContext, >>> VisitableCommand) line: 119 >>> BatchingInterceptor.handleDefault(InvocationContext, >>> VisitableCommand) line: 77 >>> >>> BatchingInterceptor(AbstractVisitor).visitCommitCommand(TxInvocationContext, >>> CommitCommand) line: 116 >>> CommitCommand.acceptVisitor(InvocationContext, Visitor) line: 60 >>> InterceptorChain.invoke(InvocationContext, VisitableCommand) line: 274 >>> TransactionCoordinator.commit(LocalTransaction, boolean) line: 136 >>> TransactionXaAdapter.commit(Xid, boolean) line: 124 >>> DummyTransaction.runCommitTx() line: 312 >>> DummyTransaction.commit() line: 99 >>> BatchModeTransactionManager(DummyBaseTransactionManager).commit() line: >>> 97 >>> BatchContainer.resolveTransaction(BatchContainer$BatchDetails, >>> boolean) line: 131 >>> BatchContainer.endBatch(boolean, boolean) line: 108 >>> BatchContainer.endBatch(boolean) line: 93 >>> CacheDelegate<K,V>.endBatch(boolean) line: 436 >>> InfinispanIndexOutput.close() line: 208 >>> IOUtils.closeSafely(Closeable...) line: 80 >>> FieldsWriter.close() line: 111 >>> StoredFieldsWriter.flush(SegmentWriteState) line: 52 >>> DocFieldProcessor.flush(Collection<DocConsumerPerThread>, >>> SegmentWriteState) line: 58 >>> >>> I would like to remove the lock operation from the eviction listener, >>> but I'm not understanding why this locking is needed there and would >>> appreciate some explanations or help with this. >> Looking at the code, my first thought was that it is needed for sync-ing >> cache store /passivator access on that key. >> But afaik the cache store takes care of key locking at its own level[1], so >> I think that should be remove entirely. >> >> [1] >> https://github.com/mmarkus/infinispan/blob/master/core/src/main/java/org/infinispan/loaders/LockSupportCacheStore.java >>> Shouldn't an evict operation be a "best effort" operation in all >>> cases, >> +1. Even if my statement above doesn't stand and there's a reason to keep >> the lock for consistency, it should be a best effort: try to lock with 0 >> timeout, if fails just ignore it and move on. > > Hmmm, if eviction was on its own, I can see the point of best effort. > > But, the point of passivation is that you evict from memory and you store in > the cache store. What harm does it cause that eviction could not work for a > passivated cache? You could potentially end up with entries both in cache and > store for at least a brief period of time, until the eviction thread tries to > evict it again. As per the stack trace, the lock acquisition fails within the scope of BoundedConcurrentHashMap$Segment.notifyEvictionListener: that means that entries were removed from memory for sure. So the only possible problematic outcome is to have entires removed from memory but not passivated. Still a problem though. > Now, what happens in a passivated cache if the entry, which is supposed to > have been passivated, is still in memory due to eviction not acquiring the > lock, that's not going to happen, the failing lock acquisition fails after element is evicted. I don't think this lock acquisition is needed though, and the fact that tests didn't fail after Sanne removed the locking code from EvictionManagerImpl.onEntryEviction back my assumption. > and suddenly it gets modified in memory. Will this changes propagate to the > passivated entry? > > I think this needs some thought... > > Btw, 2LC uses eviction but no passivation. > >>> or is the idea here that we want the evictable data to be >>> consistently evicted on multiple nodes, or maybe even rollback an >>> evict operation? >> We don't advertise cluster-wise eviction consistency, so I doubt that is the >> case. > > Indeed, eviction is a local only operation. > >>> >>> Cheers, >>> Sanne >>> _______________________________________________ >>> infinispan-dev mailing list >>> infinispan-dev@lists.jboss.org >>> https://lists.jboss.org/mailman/listinfo/infinispan-dev >> >> _______________________________________________ >> infinispan-dev mailing list >> infinispan-dev@lists.jboss.org >> https://lists.jboss.org/mailman/listinfo/infinispan-dev > > -- > Galder Zamarreño > Sr. Software Engineer > Infinispan, JBoss Cache > > > _______________________________________________ > infinispan-dev mailing list > infinispan-dev@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/infinispan-dev
_______________________________________________ infinispan-dev mailing list infinispan-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/infinispan-dev