Merged HEAD-BUG-FIX to HEAD (changes required to support ALF-19785)

54568: Merged V4.1-BUG-FIX (4.1.7) to HEAD-BUG-FIX (4.2.0)
    54471: Fix MNT-9517: Deadlock when binding class behaviours during bootstrap AND starting subsystems
  54471: Fix MNT-9517: Deadlock when binding class behaviours during bootstrap AND starting subsystems


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@54747 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Matt Ward
2013-09-02 08:42:13 +00:00
parent 6ba121eb00
commit 2066ff0384
2 changed files with 64 additions and 79 deletions

View File

@@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.alfresco.util.LockHelper;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -91,43 +92,41 @@ import org.apache.commons.logging.LogFactory;
return super.create(binding); return super.create(binding);
} }
lock.readLock().lock(); LockHelper.tryLock(lock.readLock(), 100);
try try
{ {
P policyInterface = singleCache.get(binding); P policyInterface = singleCache.get(binding);
if (policyInterface == null) if (policyInterface != null)
{ {
// Upgrade read lock to write lock return policyInterface;
lock.readLock().unlock();
lock.writeLock().lock();
try
{
// Check again
policyInterface = singleCache.get(binding);
if (policyInterface == null)
{
policyInterface = super.create(binding);
singleCache.put(binding, policyInterface);
if (logger.isDebugEnabled())
logger.debug("Cached delegate interface " + policyInterface + " for " + binding + " and policy " + getPolicyClass());
}
}
finally
{
// Downgrade lock to read
lock.readLock().lock();
lock.writeLock().unlock();
}
} }
return policyInterface;
} }
finally finally
{ {
lock.readLock().unlock(); lock.readLock().unlock();
} }
// There wasn't one
LockHelper.tryLock(lock.writeLock(), 100);
try
{
P policyInterface = singleCache.get(binding);
if (policyInterface != null)
{
return policyInterface;
}
policyInterface = super.create(binding);
singleCache.put(binding, policyInterface);
if (logger.isDebugEnabled())
logger.debug("Cached delegate interface " + policyInterface + " for " + binding + " and policy " + getPolicyClass());
return policyInterface;
}
finally
{
lock.writeLock().unlock();
}
} }
@@ -140,45 +139,42 @@ import org.apache.commons.logging.LogFactory;
return super.createList(binding); return super.createList(binding);
} }
lock.readLock().lock(); LockHelper.tryLock(lock.readLock(), 100);
try try
{ {
Collection<P> policyInterfaces = listCache.get(binding); Collection<P> policyInterfaces = listCache.get(binding);
if (policyInterfaces == null) if (policyInterfaces != null)
{ {
// Upgrade read lock to write lock return policyInterfaces;
lock.readLock().unlock();
lock.writeLock().lock();
try
{
// Check again
policyInterfaces = listCache.get(binding);
if (policyInterfaces == null)
{
policyInterfaces = super.createList(binding);
listCache.put(binding, policyInterfaces);
if (logger.isDebugEnabled())
logger.debug("Cached delegate interface collection " + policyInterfaces + " for " + binding + " and policy " + getPolicyClass());
}
}
finally
{
// Downgrade lock to read
lock.readLock().lock();
lock.writeLock().unlock();
}
} }
return policyInterfaces; }
}
finally finally
{ {
lock.readLock().unlock(); lock.readLock().unlock();
} }
}
// There wasn't one
LockHelper.tryLock(lock.writeLock(), 100);
try
{
Collection<P> policyInterfaces = listCache.get(binding);
if (policyInterfaces != null)
{
return policyInterfaces;
}
policyInterfaces = super.createList(binding);
listCache.put(binding, policyInterfaces);
if (logger.isDebugEnabled())
logger.debug("Cached delegate interface collection " + policyInterfaces + " for " + binding + " and policy " + getPolicyClass());
return policyInterfaces;
}
finally
{
lock.writeLock().unlock();
}
}
/** /**
* Clear entries in the cache based on binding changes. * Clear entries in the cache based on binding changes.
@@ -191,8 +187,7 @@ import org.apache.commons.logging.LogFactory;
{ {
if (binding == null) if (binding == null)
{ {
lock.writeLock().lock(); LockHelper.tryLock(lock.writeLock(), 100);
try try
{ {
// A specific binding has not been provided, so clear all entries // A specific binding has not been provided, so clear all entries
@@ -230,8 +225,7 @@ import org.apache.commons.logging.LogFactory;
// Remove all invalid bindings // Remove all invalid bindings
if (invalidBindings.size() > 0) if (invalidBindings.size() > 0)
{ {
lock.writeLock().lock(); LockHelper.tryLock(lock.writeLock(), 100);
try try
{ {
for (B invalidBinding : invalidBindings) for (B invalidBinding : invalidBindings)
@@ -249,5 +243,4 @@ import org.apache.commons.logging.LogFactory;
} }
} }
} }
} }

View File

@@ -25,6 +25,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.util.LockHelper;
/** /**
@@ -88,13 +89,10 @@ import org.alfresco.service.namespace.QName;
} }
/* (non-Javadoc) @Override
* @see org.alfresco.repo.policy.BehaviourIndex#getAll()
*/
@SuppressWarnings("unchecked")
public Collection<BehaviourDefinition> getAll() public Collection<BehaviourDefinition> getAll()
{ {
lock.readLock().lock(); LockHelper.tryLock(lock.readLock(), 100);
try try
{ {
@@ -110,13 +108,11 @@ import org.alfresco.service.namespace.QName;
} }
/* (non-Javadoc) @Override
* @see org.alfresco.repo.policy.BehaviourIndex#find()
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Collection<BehaviourDefinition> find(B binding) public Collection<BehaviourDefinition> find(B binding)
{ {
lock.readLock().lock(); LockHelper.tryLock(lock.readLock(), 100);
try try
{ {
@@ -158,18 +154,14 @@ import org.alfresco.service.namespace.QName;
} }
/* (non-Javadoc) @Override
* @see org.alfresco.repo.policy.BehaviourIndex#find()
*/
public void addChangeObserver(BehaviourChangeObserver<B> observer) public void addChangeObserver(BehaviourChangeObserver<B> observer)
{ {
observers.add(observer); observers.add(observer);
} }
/* (non-Javadoc) @Override
* @see org.alfresco.repo.policy.BehaviourIndex#getFilter()
*/
public BehaviourFilter getFilter() public BehaviourFilter getFilter()
{ {
return filter; return filter;
@@ -183,7 +175,7 @@ import org.alfresco.service.namespace.QName;
*/ */
public void putClassBehaviour(BehaviourDefinition<B> behaviour) public void putClassBehaviour(BehaviourDefinition<B> behaviour)
{ {
lock.writeLock().lock(); LockHelper.tryLock(lock.writeLock(), 100);
try try
{ {
classMap.put(behaviour); classMap.put(behaviour);
@@ -202,7 +194,7 @@ import org.alfresco.service.namespace.QName;
*/ */
public void putServiceBehaviour(BehaviourDefinition<ServiceBehaviourBinding> behaviour) public void putServiceBehaviour(BehaviourDefinition<ServiceBehaviourBinding> behaviour)
{ {
lock.writeLock().lock(); LockHelper.tryLock(lock.writeLock(), 100);
try try
{ {
serviceMap.put(behaviour); serviceMap.put(behaviour);
@@ -220,7 +212,7 @@ import org.alfresco.service.namespace.QName;
*/ */
public void removeClassBehaviour(BehaviourDefinition<B> behaviour) public void removeClassBehaviour(BehaviourDefinition<B> behaviour)
{ {
lock.writeLock().lock(); LockHelper.tryLock(lock.writeLock(), 100);
try try
{ {
classMap.remove(behaviour); classMap.remove(behaviour);