mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged BRANCHES/DEV/HEAD-BUG-FIX to HEAD:
54579: ALF-19785: Deadlock during build git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@54739 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -30,6 +30,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractLockStore<T extends ConcurrentMap<NodeRef, LockState>> implements LockStore
|
public abstract class AbstractLockStore<T extends ConcurrentMap<NodeRef, LockState>> implements LockStore
|
||||||
{
|
{
|
||||||
|
protected long maxTryLockMillis = 100;
|
||||||
protected T map;
|
protected T map;
|
||||||
|
|
||||||
public AbstractLockStore(T map)
|
public AbstractLockStore(T map)
|
||||||
@@ -37,6 +38,20 @@ public abstract class AbstractLockStore<T extends ConcurrentMap<NodeRef, LockSta
|
|||||||
this.map = map;
|
this.map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum time a lock store should wait while trying to acquire a concurrency lock.
|
||||||
|
*
|
||||||
|
* @see #acquireConcurrencyLock(NodeRef)
|
||||||
|
* @param maxTryLockMillis
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setMaxTryLockMillis(long maxTryLockMillis)
|
||||||
|
{
|
||||||
|
this.maxTryLockMillis = maxTryLockMillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LockState get(NodeRef nodeRef)
|
public LockState get(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
|
@@ -18,10 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.lock.mem;
|
package org.alfresco.repo.lock.mem;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.service.cmr.lock.LockType;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,5 +56,6 @@ public interface LockStore
|
|||||||
void clear();
|
void clear();
|
||||||
void acquireConcurrencyLock(NodeRef nodeRef);
|
void acquireConcurrencyLock(NodeRef nodeRef);
|
||||||
void releaseConcurrencyLock(NodeRef nodeRef);
|
void releaseConcurrencyLock(NodeRef nodeRef);
|
||||||
|
void setMaxTryLockMillis(long maxTryLockMillis);
|
||||||
public Set<NodeRef> getNodes();
|
public Set<NodeRef> getNodes();
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
|||||||
|
|
||||||
import org.alfresco.repo.lock.LockServiceImpl;
|
import org.alfresco.repo.lock.LockServiceImpl;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.util.LockHelper;
|
||||||
|
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.collect.MapMaker;
|
||||||
|
|
||||||
@@ -80,8 +81,9 @@ public class LockStoreImpl extends AbstractLockStore<ConcurrentMap<NodeRef, Lock
|
|||||||
public void acquireConcurrencyLock(NodeRef nodeRef)
|
public void acquireConcurrencyLock(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
WriteLock writeLock = getWriteLock(nodeRef);
|
WriteLock writeLock = getWriteLock(nodeRef);
|
||||||
// Block until available
|
// Block for a short time, if we can't acquire the lock, then throw
|
||||||
writeLock.lock();
|
// an exception that the will allow transaction retry behaviour.
|
||||||
|
LockHelper.tryLock(writeLock, maxTryLockMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -39,6 +39,7 @@ import org.alfresco.error.ExceptionStackUtil;
|
|||||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
|
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.alfresco.util.LockHelper.LockTryException;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.ibatis.exceptions.TooManyResultsException;
|
import org.apache.ibatis.exceptions.TooManyResultsException;
|
||||||
@@ -105,7 +106,8 @@ public class RetryingTransactionHelper
|
|||||||
TooManyResultsException.class, // Expected one result but found multiple (bad key alert)
|
TooManyResultsException.class, // Expected one result but found multiple (bad key alert)
|
||||||
ObjectNotFoundException.class,
|
ObjectNotFoundException.class,
|
||||||
CacheException.class, // Usually a cache replication issue
|
CacheException.class, // Usually a cache replication issue
|
||||||
SQLGrammarException.class // Actually specific to MS SQL Server 2005 - we check for this
|
SQLGrammarException.class, // Actually specific to MS SQL Server 2005 - we check for this
|
||||||
|
LockTryException.class
|
||||||
};
|
};
|
||||||
|
|
||||||
List<Class<?>> retryExceptions = new ArrayList<Class<?>>();
|
List<Class<?>> retryExceptions = new ArrayList<Class<?>>();
|
||||||
|
@@ -21,6 +21,7 @@ package org.alfresco.repo.lock.mem;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -29,6 +30,7 @@ import java.util.TreeSet;
|
|||||||
|
|
||||||
import org.alfresco.service.cmr.lock.LockType;
|
import org.alfresco.service.cmr.lock.LockType;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.util.LockHelper.LockTryException;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -156,4 +158,46 @@ public abstract class AbstractLockStoreTestBase<T extends LockStore>
|
|||||||
assertEquals(nodeRef3, it.next());
|
assertEquals(nodeRef3, it.next());
|
||||||
assertEquals(nodeRef4, it.next());
|
assertEquals(nodeRef4, it.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test()
|
||||||
|
public void whenTryLockFailsTransactionWillRetry() throws InterruptedException
|
||||||
|
{
|
||||||
|
final NodeRef nodeRef = new NodeRef("workspace://SpacesStore/whenTryLockFailsTransactionWillRetry");
|
||||||
|
|
||||||
|
// The "other" thread, that got there first and took the lock.
|
||||||
|
Thread thread = new Thread(getClass().getSimpleName()+"-testTryLock")
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Deliberately NOT releasing this lock, so we can check for tryLock failure.
|
||||||
|
lockStore.acquireConcurrencyLock(nodeRef);
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
// This shouldn't happen the first time.
|
||||||
|
fail("Failed to a acquire lock");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
thread.start();
|
||||||
|
|
||||||
|
|
||||||
|
// Wait for the other thread to perform the lock.
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
// Second attempt will fail (already locked above), expected exception
|
||||||
|
// must be thrown for retrying behaviour to work correctly.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lockStore.acquireConcurrencyLock(nodeRef);
|
||||||
|
fail("Exception was not thrown when unable to acquire lock.");
|
||||||
|
}
|
||||||
|
catch (LockTryException e)
|
||||||
|
{
|
||||||
|
// Good, we got the correct exception.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user