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:
Derek Hulley
2006-05-03 23:06:59 +00:00
parent cf4e177ead
commit 56e9002855
2 changed files with 175 additions and 25 deletions

View File

@@ -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,8 +75,26 @@ public class ChildAssocImpl implements ChildAssoc
this.getChild().getParentAssocs().remove(this);
}
public synchronized ChildAssociationRef getChildAssocRef()
public ChildAssociationRef getChildAssocRef()
{
// 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(
@@ -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();
}
}
}

View File

@@ -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()
{
// first check if it is available
refReadLock.lock();
try
{
if (nodeAssocRef != null)
{
return nodeAssocRef;
}
}
finally
{
refReadLock.unlock();
}
// get write lock
refWriteLock.lock();
try
{
// double check
if (nodeAssocRef == null )
{
nodeAssocRef = new AssociationRef(getSource().getNodeRef(),
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();
}
}
}