mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Node cache changes (step): aspects are cached using the node's ID-VERSION key
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@31178 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -153,11 +153,11 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
private EntityLookupCache<Long, Node, NodeRef> nodesCache;
|
private EntityLookupCache<Long, Node, NodeRef> nodesCache;
|
||||||
/**
|
/**
|
||||||
* Cache for the QName values:<br/>
|
* Cache for the QName values:<br/>
|
||||||
* KEY: ID<br/>
|
* KEY: NodeVersionKey<br/>
|
||||||
* VALUE: Set<QName><br/>
|
* VALUE: Set<QName><br/>
|
||||||
* VALUE KEY: None<br/>
|
* VALUE KEY: None<br/>
|
||||||
*/
|
*/
|
||||||
private EntityLookupCache<Long, Set<QName>, Serializable> aspectsCache;
|
private EntityLookupCache<NodeVersionKey, Set<QName>, Serializable> aspectsCache;
|
||||||
/**
|
/**
|
||||||
* Cache for the Node properties:<br/>
|
* Cache for the Node properties:<br/>
|
||||||
* KEY: NodeVersionKey<br/>
|
* KEY: NodeVersionKey<br/>
|
||||||
@@ -184,7 +184,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
// Caches
|
// Caches
|
||||||
rootNodesCache = new EntityLookupCache<StoreRef, Node, Serializable>(new RootNodesCacheCallbackDAO());
|
rootNodesCache = new EntityLookupCache<StoreRef, Node, Serializable>(new RootNodesCacheCallbackDAO());
|
||||||
nodesCache = new EntityLookupCache<Long, Node, NodeRef>(new NodesCacheCallbackDAO());
|
nodesCache = new EntityLookupCache<Long, Node, NodeRef>(new NodesCacheCallbackDAO());
|
||||||
aspectsCache = new EntityLookupCache<Long, Set<QName>, Serializable>(new AspectsCallbackDAO());
|
aspectsCache = new EntityLookupCache<NodeVersionKey, Set<QName>, Serializable>(new AspectsCallbackDAO());
|
||||||
propertiesCache = new EntityLookupCache<NodeVersionKey, Map<QName, Serializable>, Serializable>(new PropertiesCallbackDAO());
|
propertiesCache = new EntityLookupCache<NodeVersionKey, Map<QName, Serializable>, Serializable>(new PropertiesCallbackDAO());
|
||||||
parentAssocsCache = new EntityLookupCache<Long, ParentAssocsInfo, ChildByNameKey>(new ParentAssocsCallbackDAO());
|
parentAssocsCache = new EntityLookupCache<Long, ParentAssocsInfo, ChildByNameKey>(new ParentAssocsCallbackDAO());
|
||||||
}
|
}
|
||||||
@@ -312,9 +312,9 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
*
|
*
|
||||||
* @param aspectsCache the cache
|
* @param aspectsCache the cache
|
||||||
*/
|
*/
|
||||||
public void setAspectsCache(SimpleCache<Long, Set<QName>> aspectsCache)
|
public void setAspectsCache(SimpleCache<NodeVersionKey, Set<QName>> aspectsCache)
|
||||||
{
|
{
|
||||||
this.aspectsCache = new EntityLookupCache<Long, Set<QName>, Serializable>(
|
this.aspectsCache = new EntityLookupCache<NodeVersionKey, Set<QName>, Serializable>(
|
||||||
aspectsCache,
|
aspectsCache,
|
||||||
CACHE_REGION_ASPECTS,
|
CACHE_REGION_ASPECTS,
|
||||||
new AspectsCallbackDAO());
|
new AspectsCallbackDAO());
|
||||||
@@ -325,7 +325,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
*
|
*
|
||||||
* @param propertiesCache the cache
|
* @param propertiesCache the cache
|
||||||
*/
|
*/
|
||||||
public void setPropertiesCache(SimpleCache<Long, Map<QName, Serializable>> propertiesCache)
|
public void setPropertiesCache(SimpleCache<NodeVersionKey, Map<QName, Serializable>> propertiesCache)
|
||||||
{
|
{
|
||||||
this.propertiesCache = new EntityLookupCache<NodeVersionKey, Map<QName, Serializable>, Serializable>(
|
this.propertiesCache = new EntityLookupCache<NodeVersionKey, Map<QName, Serializable>, Serializable>(
|
||||||
propertiesCache,
|
propertiesCache,
|
||||||
@@ -535,10 +535,11 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
// Properties
|
// Properties
|
||||||
propertiesCache.removeByKey(nodeVersionKey);
|
propertiesCache.removeByKey(nodeVersionKey);
|
||||||
// Aspects
|
// Aspects
|
||||||
aspectsCache.removeByKey(nodeId);
|
aspectsCache.removeByKey(nodeVersionKey);
|
||||||
// Parent Assocs
|
// Parent Assocs
|
||||||
parentAssocsCache.removeByKey(nodeId);
|
parentAssocsCache.removeByKey(nodeId);
|
||||||
}
|
}
|
||||||
|
invalidateCachesByNodeId(nodeId, null, parentAssocsCache);
|
||||||
// Finally remove the node reference
|
// Finally remove the node reference
|
||||||
nodesCache.removeByKey(nodeId);
|
nodesCache.removeByKey(nodeId);
|
||||||
}
|
}
|
||||||
@@ -893,6 +894,8 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
return nodeTxnId.equals(currentTxnId);
|
return nodeTxnId.equals(currentTxnId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Restore to simple version
|
||||||
|
// TODO: Add read-through option for caches
|
||||||
public Status getNodeRefStatus(NodeRef nodeRef)
|
public Status getNodeRefStatus(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
Node node = null;
|
Node node = null;
|
||||||
@@ -971,7 +974,23 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
Pair<Long, Node> pair = nodesCache.getByKey(nodeId);
|
Pair<Long, Node> pair = nodesCache.getByKey(nodeId);
|
||||||
if (pair == null || pair.getSecond().getDeleted())
|
if (pair == null || pair.getSecond().getDeleted())
|
||||||
{
|
{
|
||||||
throw new ConcurrencyFailureException("No live node exists for ID " + nodeId);
|
// Go back to the database and get what is there
|
||||||
|
NodeEntity dbNode = selectNodeById(nodeId, null);
|
||||||
|
if (pair == null)
|
||||||
|
{
|
||||||
|
throw new ConcurrencyFailureException(
|
||||||
|
"No node exists: \n" +
|
||||||
|
" ID: " + nodeId + "\n" +
|
||||||
|
" DB row: " + dbNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ConcurrencyFailureException(
|
||||||
|
"No live node exists: \n" +
|
||||||
|
" ID: " + nodeId + "\n" +
|
||||||
|
" Cache row: " + pair.getSecond() + "\n" +
|
||||||
|
" DB row: " + dbNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2111,6 +2130,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
Pair<NodeVersionKey, Map<QName, Serializable>> cacheEntry = propertiesCache.getByKey(nodeVersionKey);
|
Pair<NodeVersionKey, Map<QName, Serializable>> cacheEntry = propertiesCache.getByKey(nodeVersionKey);
|
||||||
if (cacheEntry == null)
|
if (cacheEntry == null)
|
||||||
{
|
{
|
||||||
|
invalidateNodeCaches(nodeId);
|
||||||
throw new DataIntegrityViolationException("Invalid node ID: " + nodeId);
|
throw new DataIntegrityViolationException("Invalid node ID: " + nodeId);
|
||||||
}
|
}
|
||||||
Map<QName, Serializable> cachedProperties = cacheEntry.getSecond();
|
Map<QName, Serializable> cachedProperties = cacheEntry.getSecond();
|
||||||
@@ -2258,7 +2278,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
catch (RuntimeException e)
|
catch (RuntimeException e)
|
||||||
{
|
{
|
||||||
// This could be because the cache is out of date
|
// This could be because the cache is out of date
|
||||||
aspectsCache.removeByKey(nodeId);
|
invalidateNodeCaches(nodeId);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -2297,12 +2317,12 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
|
|
||||||
// Just delete all the node's aspects
|
// Just delete all the node's aspects
|
||||||
int deleteCount = deleteNodeAspects(nodeId, null);
|
int deleteCount = deleteNodeAspects(nodeId, null);
|
||||||
// Manually update the cache
|
|
||||||
aspectsCache.setValue(nodeId, Collections.<QName>emptySet());
|
|
||||||
|
|
||||||
// Touch to bring into current txn
|
// Touch to bring into current txn
|
||||||
touchNodeImpl(nodeId);
|
touchNodeImpl(nodeId);
|
||||||
|
|
||||||
|
// Manually update the cache
|
||||||
|
setNodeAspectsCached(nodeId, Collections.<QName>emptySet());
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
return deleteCount > 0;
|
return deleteCount > 0;
|
||||||
}
|
}
|
||||||
@@ -2315,11 +2335,6 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
Set<Long> aspectQNameIdsToRemove = qnameDAO.convertQNamesToIds(aspectQNames, false);
|
Set<Long> aspectQNameIdsToRemove = qnameDAO.convertQNamesToIds(aspectQNames, false);
|
||||||
int deleteCount = deleteNodeAspects(nodeId, aspectQNameIdsToRemove);
|
int deleteCount = deleteNodeAspects(nodeId, aspectQNameIdsToRemove);
|
||||||
|
|
||||||
// Manually update the cache
|
|
||||||
Set<QName> newAspectQNames = new HashSet<QName>(existingAspectQNames);
|
|
||||||
newAspectQNames.removeAll(aspectQNames);
|
|
||||||
aspectsCache.setValue(nodeId, newAspectQNames);
|
|
||||||
|
|
||||||
// If we are removing the sys:aspect_root, then the parent assocs cache is unreliable
|
// If we are removing the sys:aspect_root, then the parent assocs cache is unreliable
|
||||||
if (aspectQNames.contains(ContentModel.ASPECT_ROOT))
|
if (aspectQNames.contains(ContentModel.ASPECT_ROOT))
|
||||||
{
|
{
|
||||||
@@ -2331,6 +2346,11 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
// Touch to bring into current txn
|
// Touch to bring into current txn
|
||||||
touchNodeImpl(nodeId);
|
touchNodeImpl(nodeId);
|
||||||
|
|
||||||
|
// Manually update the cache
|
||||||
|
Set<QName> newAspectQNames = new HashSet<QName>(existingAspectQNames);
|
||||||
|
newAspectQNames.removeAll(aspectQNames);
|
||||||
|
setNodeAspectsCached(nodeId, newAspectQNames);
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
return deleteCount > 0;
|
return deleteCount > 0;
|
||||||
}
|
}
|
||||||
@@ -2355,9 +2375,11 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
*/
|
*/
|
||||||
private Set<QName> getNodeAspectsCached(Long nodeId)
|
private Set<QName> getNodeAspectsCached(Long nodeId)
|
||||||
{
|
{
|
||||||
Pair<Long, Set<QName>> cacheEntry = aspectsCache.getByKey(nodeId);
|
NodeVersionKey nodeVersionKey = getNodeNotNull(nodeId).getNodeVersionKey();
|
||||||
|
Pair<NodeVersionKey, Set<QName>> cacheEntry = aspectsCache.getByKey(nodeVersionKey);
|
||||||
if (cacheEntry == null)
|
if (cacheEntry == null)
|
||||||
{
|
{
|
||||||
|
invalidateNodeCaches(nodeId);
|
||||||
throw new DataIntegrityViolationException("Invalid node ID: " + nodeId);
|
throw new DataIntegrityViolationException("Invalid node ID: " + nodeId);
|
||||||
}
|
}
|
||||||
return new HashSet<QName>(cacheEntry.getSecond());
|
return new HashSet<QName>(cacheEntry.getSecond());
|
||||||
@@ -2368,7 +2390,8 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
*/
|
*/
|
||||||
private void setNodeAspectsCached(Long nodeId, Set<QName> aspects)
|
private void setNodeAspectsCached(Long nodeId, Set<QName> aspects)
|
||||||
{
|
{
|
||||||
aspectsCache.setValue(nodeId, Collections.unmodifiableSet(aspects));
|
NodeVersionKey nodeVersionKey = getNodeNotNull(nodeId).getNodeVersionKey();
|
||||||
|
aspectsCache.setValue(nodeVersionKey, Collections.unmodifiableSet(aspects));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2377,16 +2400,16 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
* @author Derek Hulley
|
* @author Derek Hulley
|
||||||
* @since 3.4
|
* @since 3.4
|
||||||
*/
|
*/
|
||||||
private class AspectsCallbackDAO extends EntityLookupCallbackDAOAdaptor<Long, Set<QName>, Serializable>
|
private class AspectsCallbackDAO extends EntityLookupCallbackDAOAdaptor<NodeVersionKey, Set<QName>, Serializable>
|
||||||
{
|
{
|
||||||
public Pair<Long, Set<QName>> createValue(Set<QName> value)
|
public Pair<NodeVersionKey, Set<QName>> createValue(Set<QName> value)
|
||||||
{
|
{
|
||||||
throw new UnsupportedOperationException("A node always has a 'set' of aspects.");
|
throw new UnsupportedOperationException("A node always has a 'set' of aspects.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<Long, Set<QName>> findByKey(Long nodeId)
|
public Pair<NodeVersionKey, Set<QName>> findByKey(NodeVersionKey nodeVersionKey)
|
||||||
{
|
{
|
||||||
NodeVersionKey nodeVersionKey = getNodeNotNull(nodeId).getNodeVersionKey();
|
Long nodeId = nodeVersionKey.getNodeId();
|
||||||
Set<Long> nodeIds = Collections.singleton(nodeId);
|
Set<Long> nodeIds = Collections.singleton(nodeId);
|
||||||
Map<NodeVersionKey, Set<QName>> nodeAspectQNameIdsByVersionKey = selectNodeAspects(nodeIds);
|
Map<NodeVersionKey, Set<QName>> nodeAspectQNameIdsByVersionKey = selectNodeAspects(nodeIds);
|
||||||
Set<QName> nodeAspectQNames = nodeAspectQNameIdsByVersionKey.get(nodeVersionKey);
|
Set<QName> nodeAspectQNames = nodeAspectQNameIdsByVersionKey.get(nodeVersionKey);
|
||||||
@@ -2408,7 +2431,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Done
|
// Done
|
||||||
return new Pair<Long, Set<QName>>(nodeId, Collections.unmodifiableSet(nodeAspectQNames));
|
return new Pair<NodeVersionKey, Set<QName>>(nodeVersionKey, Collections.unmodifiableSet(nodeAspectQNames));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3682,7 +3705,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
{
|
{
|
||||||
propertiesNodeIds.add(nodeId);
|
propertiesNodeIds.add(nodeId);
|
||||||
}
|
}
|
||||||
if (aspectsCache.getValue(nodeId) == null)
|
if (aspectsCache.getValue(nodeVersionKey) == null)
|
||||||
{
|
{
|
||||||
aspectNodeIds.add(nodeId);
|
aspectNodeIds.add(nodeId);
|
||||||
}
|
}
|
||||||
@@ -3707,7 +3730,7 @@ public abstract class AbstractNodeDAOImpl implements NodeDAO, BatchingDAO
|
|||||||
// Cache the absence of aspects too!
|
// Cache the absence of aspects too!
|
||||||
for (Long nodeId: aspectNodeIds)
|
for (Long nodeId: aspectNodeIds)
|
||||||
{
|
{
|
||||||
aspectsCache.setValue(nodeId, Collections.<QName>emptySet());
|
setNodeAspectsCached(nodeId, Collections.<QName>emptySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<NodeVersionKey, Map<NodePropertyKey, NodePropertyValue>> propsByNodeId = selectNodeProperties(propertiesNodeIds);
|
Map<NodeVersionKey, Map<NodePropertyKey, NodePropertyValue>> propsByNodeId = selectNodeProperties(propertiesNodeIds);
|
||||||
|
@@ -85,7 +85,8 @@ public class NodeEntity implements Node, PermissionCheckValue
|
|||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder(512);
|
StringBuilder sb = new StringBuilder(512);
|
||||||
sb.append("NodeEntity")
|
sb.append("NodeEntity")
|
||||||
.append("[ ID=").append(id);
|
.append("[ ID=").append(id)
|
||||||
|
.append(", version=").append(version);
|
||||||
if (store != null)
|
if (store != null)
|
||||||
{
|
{
|
||||||
sb.append(", store=").append(store.getProtocol()).append("://").append(store.getIdentifier());
|
sb.append(", store=").append(store.getProtocol()).append("://").append(store.getIdentifier());
|
||||||
|
@@ -2326,6 +2326,9 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
|
|||||||
}
|
}
|
||||||
ChildAssociationRef oldParentAssocRef = oldParentAssocPair.getSecond();
|
ChildAssociationRef oldParentAssocRef = oldParentAssocPair.getSecond();
|
||||||
|
|
||||||
|
// Get the aspects for later use
|
||||||
|
Set<QName> nodeToMoveAspectQNames = nodeDAO.getNodeAspects(nodeToMoveId);
|
||||||
|
|
||||||
boolean movingStore = !oldStoreRef.equals(newStoreRef);
|
boolean movingStore = !oldStoreRef.equals(newStoreRef);
|
||||||
|
|
||||||
// Invoke "Before"policy behaviour
|
// Invoke "Before"policy behaviour
|
||||||
@@ -2375,7 +2378,6 @@ public class DbNodeServiceImpl extends AbstractNodeServiceImpl
|
|||||||
propagateTimeStamps(oldParentAssocRef);
|
propagateTimeStamps(oldParentAssocRef);
|
||||||
propagateTimeStamps(newParentAssocRef);
|
propagateTimeStamps(newParentAssocRef);
|
||||||
|
|
||||||
Set<QName> nodeToMoveAspectQNames = nodeDAO.getNodeAspects(nodeToMoveId);
|
|
||||||
// The Node changes NodeRefs, so this is really the deletion of the old node and creation
|
// The Node changes NodeRefs, so this is really the deletion of the old node and creation
|
||||||
// of a node in a new store as far as the clients are concerned.
|
// of a node in a new store as far as the clients are concerned.
|
||||||
invokeOnDeleteNode(oldParentAssocRef, nodeToMoveTypeQName, nodeToMoveAspectQNames, true);
|
invokeOnDeleteNode(oldParentAssocRef, nodeToMoveTypeQName, nodeToMoveAspectQNames, true);
|
||||||
|
Reference in New Issue
Block a user