[infinispan-issues] [JBoss JIRA] (ISPN-2240) Per-key lock container leads to superfluous TimeoutExceptions on concurrent access to same key
Robert Stupp (JIRA)
jira-events at lists.jboss.org
Mon Sep 3 11:10:33 EDT 2012
[ https://issues.jboss.org/browse/ISPN-2240?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12715445#comment-12715445 ]
Robert Stupp commented on ISPN-2240:
------------------------------------
Above recommendation works. Would be nice to get some feedback from the developers.
Temporary change of
{noformat}
org.infinispan.interceptors.locking.NonTransactionalLockingInterceptor#visitPutKeyValueCommand
{noformat}
to
{noformat}
public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
assertNonTransactional(ctx);
if (dm!=null && rpcManager!=null && ctx.isOriginLocal()) {
Address primary = dm.getPrimaryLocation(command.getKey());
Address local = rpcManager.getAddress();
if (!local.equals(primary)) {
SingleRpcCommand rpcCommand = commandsFactory.buildSingleRpcCommand(command);
Map<Address, Response> response = rpcManager.invokeRemotely(Collections.singleton(primary), rpcCommand, ResponseMode.SYNCHRONOUS, 10000);
Response resp = response.get(primary);
if (resp==null) { // todo need to ignore L1 invalidation caused by current put
entryFactory.wrapEntryForPut(ctx, command.getKey(), null, !command.isPutIfAbsent());
MVCCEntry e = (MVCCEntry) ctx.lookupEntry(command.getKey());
e.setValue(command.getValue());
e.setLifespan(command.getLifespanMillis());
e.setMaxIdle(command.getMaxIdleTimeMillis());
return null;
}
if (resp instanceof SuccessfulResponse) {
SuccessfulResponse sr = (SuccessfulResponse) resp;
entryFactory.wrapEntryForPut(ctx, command.getKey(), null, !command.isPutIfAbsent());
MVCCEntry e = (MVCCEntry) ctx.lookupEntry(command.getKey());
e.setValue(command.getValue());
e.setLifespan(command.getLifespanMillis());
e.setMaxIdle(command.getMaxIdleTimeMillis());
return sr.getResponseValue();
}
if (resp instanceof ExceptionResponse) {
ExceptionResponse er = (ExceptionResponse)resp;
throw er.getException();
}
throw new Error("hmmm ... "+resp);
}
}
try {
lockKey(ctx, command.getKey());
return invokeNextInterceptor(ctx, command);
} catch (Throwable te) {
throw cleanLocksAndRethrow(ctx, te);
}
finally {
lockManager.unlockAll(ctx);
}
}
{noformat}
> Per-key lock container leads to superfluous TimeoutExceptions on concurrent access to same key
> ----------------------------------------------------------------------------------------------
>
> Key: ISPN-2240
> URL: https://issues.jboss.org/browse/ISPN-2240
> Project: Infinispan
> Issue Type: Bug
> Components: Locking and Concurrency
> Affects Versions: 5.1.6.FINAL, 5.1.x
> Reporter: Robert Stupp
> Assignee: Mircea Markus
> Attachments: ISPN-2240_fix_TimeoutExceptions.patch, somehow.zip
>
>
> Hi,
> I've encountered a lot of TimeoutExceptions just running a load test against an infinispan cluster.
> I tracked down the reason and found out, that the code in org.infinispan.util.concurrent.locks.containers.AbstractPerEntryLockContainer#releaseLock() causes these superfluous TimeoutExceptions.
> A small test case (which just prints out timeouts, too late timeouts and "paints" a lot of dots to the console - more dots/second on the console means better throughput ;-)
> In a short test I extended the class ReentrantPerEntryLockContainer and changed the implementation of releaseLock() as follows:
> {noformat}
> public void releaseLock(Object lockOwner, Object key) {
> ReentrantLock l = locks.get(key);
> if (l != null) {
> if (!l.isHeldByCurrentThread())
> throw new IllegalStateException("Lock for [" + key + "] not held by current thread " + Thread.currentThread());
> while (l.isHeldByCurrentThread())
> unlock(l, lockOwner);
> if (!l.hasQueuedThreads())
> locks.remove(key);
> }
> else
> throw new IllegalStateException("No lock for [" + key + ']');
> }
> {noformat}
> The main improvement is that locks are not removed from the concurrent map as long as other threads are waiting on that lock.
> If the lock is removed from the map while other threads are waiting for it, they may run into timeouts and force TimeoutExceptions to the client.
> The above methods "paints more dots per second" - means: it gives a better throughput for concurrent accesses to the same key.
> The re-implemented method should also fix some replication timeout exceptions.
> Please, please add this to 5.1.7, if possible.
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the infinispan-issues
mailing list