mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
More robust concurrency handling of cached references
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2750 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -16,6 +16,10 @@
|
||||
*/
|
||||
package org.alfresco.repo.domain.hibernate;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
|
||||
import org.alfresco.repo.domain.ChildAssoc;
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
@@ -34,10 +38,17 @@ public class ChildAssocImpl implements ChildAssoc
|
||||
private QName qName;
|
||||
private boolean isPrimary;
|
||||
private int index;
|
||||
|
||||
private transient ReadLock refReadLock;
|
||||
private transient WriteLock refWriteLock;
|
||||
private transient ChildAssociationRef childAssocRef;
|
||||
|
||||
public ChildAssocImpl()
|
||||
{
|
||||
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
refReadLock = lock.readLock();
|
||||
refWriteLock = lock.writeLock();
|
||||
|
||||
setIndex(Integer.MAX_VALUE); // comes last
|
||||
}
|
||||
|
||||
@@ -64,9 +75,27 @@ public class ChildAssocImpl implements ChildAssoc
|
||||
this.getChild().getParentAssocs().remove(this);
|
||||
}
|
||||
|
||||
public synchronized ChildAssociationRef getChildAssocRef()
|
||||
public ChildAssociationRef getChildAssocRef()
|
||||
{
|
||||
if (childAssocRef == null)
|
||||
// first check if it is available
|
||||
refReadLock.lock();
|
||||
try
|
||||
{
|
||||
if (childAssocRef != null)
|
||||
{
|
||||
return childAssocRef;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
refReadLock.unlock();
|
||||
}
|
||||
// get write lock
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
// double check
|
||||
if (childAssocRef == null )
|
||||
{
|
||||
childAssocRef = new ChildAssociationRef(
|
||||
this.typeQName,
|
||||
@@ -78,6 +107,11 @@ public class ChildAssocImpl implements ChildAssoc
|
||||
}
|
||||
return childAssocRef;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
@@ -161,6 +195,7 @@ public class ChildAssocImpl implements ChildAssoc
|
||||
/**
|
||||
* For Hibernate use
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private void setId(Long id)
|
||||
{
|
||||
this.id = id;
|
||||
@@ -175,8 +210,17 @@ public class ChildAssocImpl implements ChildAssoc
|
||||
* For Hibernate use
|
||||
*/
|
||||
private void setParent(Node parentNode)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.parent = parentNode;
|
||||
this.childAssocRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Node getChild()
|
||||
@@ -188,8 +232,17 @@ public class ChildAssocImpl implements ChildAssoc
|
||||
* For Hibernate use
|
||||
*/
|
||||
private void setChild(Node node)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
child = node;
|
||||
this.childAssocRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public QName getTypeQName()
|
||||
@@ -198,8 +251,17 @@ public class ChildAssocImpl implements ChildAssoc
|
||||
}
|
||||
|
||||
public void setTypeQName(QName typeQName)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.typeQName = typeQName;
|
||||
this.childAssocRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public QName getQname()
|
||||
@@ -208,8 +270,17 @@ public class ChildAssocImpl implements ChildAssoc
|
||||
}
|
||||
|
||||
public void setQname(QName qname)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.qName = qname;
|
||||
this.childAssocRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getIsPrimary()
|
||||
@@ -218,8 +289,17 @@ public class ChildAssocImpl implements ChildAssoc
|
||||
}
|
||||
|
||||
public void setIsPrimary(boolean isPrimary)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.isPrimary = isPrimary;
|
||||
this.childAssocRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
@@ -228,7 +308,16 @@ public class ChildAssocImpl implements ChildAssoc
|
||||
}
|
||||
|
||||
public void setIndex(int index)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.index = index;
|
||||
this.childAssocRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,6 +16,10 @@
|
||||
*/
|
||||
package org.alfresco.repo.domain.hibernate;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||
|
||||
import org.alfresco.repo.domain.Node;
|
||||
import org.alfresco.repo.domain.NodeAssoc;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
@@ -33,10 +37,16 @@ public class NodeAssocImpl implements NodeAssoc
|
||||
private Node source;
|
||||
private Node target;
|
||||
private QName typeQName;
|
||||
|
||||
private transient ReadLock refReadLock;
|
||||
private transient WriteLock refWriteLock;
|
||||
private transient AssociationRef nodeAssocRef;
|
||||
|
||||
public NodeAssocImpl()
|
||||
{
|
||||
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
refReadLock = lock.readLock();
|
||||
refWriteLock = lock.writeLock();
|
||||
}
|
||||
|
||||
public void buildAssociation(Node sourceNode, Node targetNode)
|
||||
@@ -62,16 +72,40 @@ public class NodeAssocImpl implements NodeAssoc
|
||||
this.getTarget().getSourceNodeAssocs().remove(this);
|
||||
}
|
||||
|
||||
public synchronized AssociationRef getNodeAssocRef()
|
||||
public AssociationRef getNodeAssocRef()
|
||||
{
|
||||
if (nodeAssocRef == null)
|
||||
// first check if it is available
|
||||
refReadLock.lock();
|
||||
try
|
||||
{
|
||||
nodeAssocRef = new AssociationRef(getSource().getNodeRef(),
|
||||
if (nodeAssocRef != null)
|
||||
{
|
||||
return nodeAssocRef;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
refReadLock.unlock();
|
||||
}
|
||||
// get write lock
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
// double check
|
||||
if (nodeAssocRef == null )
|
||||
{
|
||||
nodeAssocRef = new AssociationRef(
|
||||
getSource().getNodeRef(),
|
||||
this.typeQName,
|
||||
getTarget().getNodeRef());
|
||||
}
|
||||
return nodeAssocRef;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
@@ -132,8 +166,17 @@ public class NodeAssocImpl implements NodeAssoc
|
||||
* For internal use
|
||||
*/
|
||||
private void setSource(Node source)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.source = source;
|
||||
this.nodeAssocRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public Node getTarget()
|
||||
@@ -145,8 +188,17 @@ public class NodeAssocImpl implements NodeAssoc
|
||||
* For internal use
|
||||
*/
|
||||
private void setTarget(Node target)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.target = target;
|
||||
this.nodeAssocRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public QName getTypeQName()
|
||||
@@ -155,7 +207,16 @@ public class NodeAssocImpl implements NodeAssoc
|
||||
}
|
||||
|
||||
public void setTypeQName(QName typeQName)
|
||||
{
|
||||
refWriteLock.lock();
|
||||
try
|
||||
{
|
||||
this.typeQName = typeQName;
|
||||
this.nodeAssocRef = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
refWriteLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user