[infinispan-dev] fixing eviction with transactions (critical for Hibernate Search)

Mircea Markus mircea.markus at jboss.com
Tue Jun 7 08:41:01 EDT 2011


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. 
> 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. 
> 
> Cheers,
> Sanne
> _______________________________________________
> infinispan-dev mailing list
> infinispan-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/infinispan-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/infinispan-dev/attachments/20110607/21883033/attachment-0001.html 


More information about the infinispan-dev mailing list