mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Performance tweaks for AVM Indexing.
Removed calls to getXXXPaths(). Changed mappings of properties and aspects on AVM Nodes to favor get all calls. Added getAspects() and getNodeProperties() which take AVMNodeDescriptors. Used these in AVM Indexing to reduce the number of redundant full lookups. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6121 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -232,6 +232,14 @@ public class AVMLockingAwareService implements AVMService, ApplicationContextAwa
|
||||
return fService.getAspects(version, path);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.avm.AVMService#getAspects(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
|
||||
*/
|
||||
public Set<QName> getAspects(AVMNodeDescriptor desc)
|
||||
{
|
||||
return fService.getAspects(desc);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.avm.AVMService#getCommonAncestor(org.alfresco.service.cmr.avm.AVMNodeDescriptor, org.alfresco.service.cmr.avm.AVMNodeDescriptor)
|
||||
*/
|
||||
@@ -249,6 +257,14 @@ public class AVMLockingAwareService implements AVMService, ApplicationContextAwa
|
||||
return fService.getContentDataForRead(version, path);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.avm.AVMService#getContentDataForRead(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
|
||||
*/
|
||||
public ContentData getContentDataForRead(AVMNodeDescriptor desc)
|
||||
{
|
||||
return fService.getContentDataForRead(desc);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.avm.AVMService#getContentDataForWrite(java.lang.String)
|
||||
*/
|
||||
@@ -445,6 +461,14 @@ public class AVMLockingAwareService implements AVMService, ApplicationContextAwa
|
||||
return fService.getNodeProperties(version, path);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.avm.AVMService#getNodeProperties(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
|
||||
*/
|
||||
public Map<QName, PropertyValue> getNodeProperties(AVMNodeDescriptor desc)
|
||||
{
|
||||
return fService.getNodeProperties(desc);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.avm.AVMService#getNodeProperty(int, java.lang.String, org.alfresco.service.namespace.QName)
|
||||
*/
|
||||
|
@@ -235,4 +235,10 @@ public interface AVMNode
|
||||
* @return A Set of Aspects names.
|
||||
*/
|
||||
public Set<QName> getAspects();
|
||||
|
||||
/**
|
||||
* Add properties to those that already exist.
|
||||
* @param properties The properties to add.
|
||||
*/
|
||||
public void addProperties(Map<QName, PropertyValue> properties);
|
||||
}
|
||||
|
@@ -90,12 +90,15 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
|
||||
*/
|
||||
private Set<QName> fAspects;
|
||||
|
||||
private Map<QName, PropertyValue> fProperties;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
protected AVMNodeImpl()
|
||||
{
|
||||
fAspects = new HashSet<QName>();
|
||||
fProperties = new HashMap<QName, PropertyValue>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,6 +110,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
|
||||
AVMStore store)
|
||||
{
|
||||
fAspects = new HashSet<QName>();
|
||||
fProperties = new HashMap<QName, PropertyValue>();
|
||||
fID = id;
|
||||
fVersionID = -1;
|
||||
fIsRoot = false;
|
||||
@@ -343,14 +347,10 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
|
||||
*/
|
||||
protected void copyProperties(AVMNode other)
|
||||
{
|
||||
Map<QName, PropertyValue> properties = other.getProperties();
|
||||
for (QName name : properties.keySet())
|
||||
fProperties = new HashMap<QName, PropertyValue>();
|
||||
for (Map.Entry<QName, PropertyValue> entry : other.getProperties().entrySet())
|
||||
{
|
||||
AVMNodeProperty newProp = new AVMNodePropertyImpl();
|
||||
newProp.setNode(this);
|
||||
newProp.setName(name);
|
||||
newProp.setValue(properties.get(name));
|
||||
AVMDAOs.Instance().fAVMNodePropertyDAO.save(newProp);
|
||||
fProperties.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,18 +394,15 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
|
||||
{
|
||||
checkReadOnly();
|
||||
}
|
||||
AVMNodeProperty prop = AVMDAOs.Instance().fAVMNodePropertyDAO.get(this, name);
|
||||
if (prop != null)
|
||||
fProperties.put(name, value);
|
||||
}
|
||||
|
||||
public void addProperties(Map<QName, PropertyValue> properties)
|
||||
{
|
||||
for (Map.Entry<QName, PropertyValue> entry : properties.entrySet())
|
||||
{
|
||||
prop.setValue(value);
|
||||
AVMDAOs.Instance().fAVMNodePropertyDAO.update(prop);
|
||||
return;
|
||||
fProperties.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
prop = new AVMNodePropertyImpl();
|
||||
prop.setNode(this);
|
||||
prop.setName(name);
|
||||
prop.setValue(value);
|
||||
AVMDAOs.Instance().fAVMNodePropertyDAO.save(prop);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,14 +411,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
|
||||
*/
|
||||
public void setProperties(Map<QName, PropertyValue> properties)
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
checkReadOnly();
|
||||
}
|
||||
for (QName name : properties.keySet())
|
||||
{
|
||||
setProperty(name, properties.get(name));
|
||||
}
|
||||
fProperties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,12 +421,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
|
||||
*/
|
||||
public PropertyValue getProperty(QName name)
|
||||
{
|
||||
AVMNodeProperty prop = AVMDAOs.Instance().fAVMNodePropertyDAO.get(this, name);
|
||||
if (prop == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return prop.getValue();
|
||||
return fProperties.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -445,13 +430,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
|
||||
*/
|
||||
public Map<QName, PropertyValue> getProperties()
|
||||
{
|
||||
Map<QName, PropertyValue> retVal = new HashMap<QName, PropertyValue>();
|
||||
List<AVMNodeProperty> props = AVMDAOs.Instance().fAVMNodePropertyDAO.get(this);
|
||||
for (AVMNodeProperty prop : props)
|
||||
{
|
||||
retVal.put(prop.getName(), prop.getValue());
|
||||
}
|
||||
return retVal;
|
||||
return fProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -464,7 +443,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
|
||||
{
|
||||
checkReadOnly();
|
||||
}
|
||||
AVMDAOs.Instance().fAVMNodePropertyDAO.delete(this, name);
|
||||
fProperties.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -472,11 +451,7 @@ public abstract class AVMNodeImpl implements AVMNode, Serializable
|
||||
*/
|
||||
public void deleteProperties()
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
checkReadOnly();
|
||||
}
|
||||
AVMDAOs.Instance().fAVMNodePropertyDAO.deleteAll(this);
|
||||
fProperties.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -23,6 +23,7 @@
|
||||
|
||||
package org.alfresco.repo.avm;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.service.namespace.QName;
|
||||
@@ -72,4 +73,10 @@ public interface AVMNodePropertyDAO
|
||||
* @param name The name of the property to delete.
|
||||
*/
|
||||
public void delete(AVMNode node, QName name);
|
||||
|
||||
/**
|
||||
* Get an iterator over all properties.
|
||||
* @return
|
||||
*/
|
||||
public Iterator<AVMNodeProperty> iterate();
|
||||
}
|
||||
|
@@ -106,7 +106,7 @@ public class AVMRepository
|
||||
private AVMStorePropertyDAO fAVMStorePropertyDAO;
|
||||
|
||||
private ChildEntryDAO fChildEntryDAO;
|
||||
|
||||
|
||||
// A bunch of TransactionListeners that do work for this.
|
||||
|
||||
/**
|
||||
@@ -2677,4 +2677,39 @@ public class AVMRepository
|
||||
components.remove(components.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<QName, PropertyValue> getNodeProperties(AVMNodeDescriptor desc)
|
||||
{
|
||||
AVMNode node = fAVMNodeDAO.getByID(desc.getId());
|
||||
if (node == null)
|
||||
{
|
||||
throw new AVMNotFoundException("Node not found: " + desc);
|
||||
}
|
||||
return node.getProperties();
|
||||
}
|
||||
|
||||
public ContentData getContentDataForRead(AVMNodeDescriptor desc)
|
||||
{
|
||||
AVMNode node = fAVMNodeDAO.getByID(desc.getId());
|
||||
if (node == null)
|
||||
{
|
||||
throw new AVMNotFoundException("Node not found: " + desc);
|
||||
}
|
||||
if (node.getType() == AVMNodeType.PLAIN_FILE)
|
||||
{
|
||||
PlainFileNode file = (PlainFileNode)node;
|
||||
return file.getContentData();
|
||||
}
|
||||
throw new AVMWrongTypeException("Not a Plain File: " + desc);
|
||||
}
|
||||
|
||||
public Set<QName> getAspects(AVMNodeDescriptor desc)
|
||||
{
|
||||
AVMNode node = fAVMNodeDAO.getByID(desc.getId());
|
||||
if (node == null)
|
||||
{
|
||||
throw new AVMNotFoundException("Node not found: " + desc);
|
||||
}
|
||||
return node.getAspects();
|
||||
}
|
||||
}
|
||||
|
@@ -1068,6 +1068,18 @@ public class AVMServiceImpl implements AVMService
|
||||
return fAVMRepository.getNodeProperties(version, path);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.avm.AVMService#getNodeProperties(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
|
||||
*/
|
||||
public Map<QName, PropertyValue> getNodeProperties(AVMNodeDescriptor desc)
|
||||
{
|
||||
if (desc == null)
|
||||
{
|
||||
throw new AVMBadArgumentException("Null descriptor.");
|
||||
}
|
||||
return fAVMRepository.getNodeProperties(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a property.
|
||||
* @param path The path to the node.
|
||||
@@ -1215,6 +1227,18 @@ public class AVMServiceImpl implements AVMService
|
||||
return fAVMRepository.getContentDataForRead(version, path);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.avm.AVMService#getContentDataForRead(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
|
||||
*/
|
||||
public ContentData getContentDataForRead(AVMNodeDescriptor desc)
|
||||
{
|
||||
if (desc == null)
|
||||
{
|
||||
throw new AVMBadArgumentException("Null descriptor.");
|
||||
}
|
||||
return fAVMRepository.getContentDataForRead(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Content data for writing.
|
||||
* @param path The path to the node.
|
||||
@@ -1295,6 +1319,18 @@ public class AVMServiceImpl implements AVMService
|
||||
return fAVMRepository.getAspects(version, path);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.avm.AVMService#getAspects(org.alfresco.service.cmr.avm.AVMNodeDescriptor)
|
||||
*/
|
||||
public Set<QName> getAspects(AVMNodeDescriptor desc)
|
||||
{
|
||||
if (desc == null)
|
||||
{
|
||||
throw new AVMBadArgumentException("Null descriptor: " + desc);
|
||||
}
|
||||
return fAVMRepository.getAspects(desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an aspect and its properties from a node.
|
||||
* @param path The path to the node.
|
||||
|
@@ -101,6 +101,37 @@ import org.alfresco.util.Pair;
|
||||
*/
|
||||
public class AVMServiceTest extends AVMServiceTestBase
|
||||
{
|
||||
/**
|
||||
* Test version by date lookup.
|
||||
*/
|
||||
public void testVersionByDate()
|
||||
{
|
||||
try
|
||||
{
|
||||
ArrayList<Long> times = new ArrayList<Long>();
|
||||
BulkLoader loader = new BulkLoader();
|
||||
loader.setAvmService(fService);
|
||||
loader.recursiveLoad("source/java/org/alfresco/repo/avm", "main:/");
|
||||
times.add(System.currentTimeMillis());
|
||||
assertEquals(1, fService.createSnapshot("main", null, null).get("main").intValue());
|
||||
loader.recursiveLoad("source/java/org/alfresco/repo/action", "main:/");
|
||||
times.add(System.currentTimeMillis());
|
||||
assertEquals(2, fService.createSnapshot("main", null, null).get("main").intValue());
|
||||
loader.recursiveLoad("source/java/org/alfresco/repo/audit", "main:/");
|
||||
times.add(System.currentTimeMillis());
|
||||
assertEquals(3, fService.createSnapshot("main", null, null).get("main").intValue());
|
||||
assertEquals(1, fService.getStoreVersions("main", null, new Date(times.get(0))).size());
|
||||
assertEquals(3, fService.getStoreVersions("main", new Date(times.get(0)), null).size());
|
||||
assertEquals(2, fService.getStoreVersions("main", new Date(times.get(1)),
|
||||
new Date(System.currentTimeMillis())).size());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test properties.
|
||||
*/
|
||||
@@ -4992,36 +5023,6 @@ public class AVMServiceTest extends AVMServiceTestBase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test version by date lookup.
|
||||
*/
|
||||
public void testVersionByDate()
|
||||
{
|
||||
try
|
||||
{
|
||||
ArrayList<Long> times = new ArrayList<Long>();
|
||||
BulkLoader loader = new BulkLoader();
|
||||
loader.setAvmService(fService);
|
||||
loader.recursiveLoad("source/java/org/alfresco/repo/avm", "main:/");
|
||||
times.add(System.currentTimeMillis());
|
||||
assertEquals(1, fService.createSnapshot("main", null, null).get("main").intValue());
|
||||
loader.recursiveLoad("source/java/org/alfresco/repo/action", "main:/");
|
||||
times.add(System.currentTimeMillis());
|
||||
assertEquals(2, fService.createSnapshot("main", null, null).get("main").intValue());
|
||||
loader.recursiveLoad("source/java/org/alfresco/repo/audit", "main:/");
|
||||
times.add(System.currentTimeMillis());
|
||||
assertEquals(3, fService.createSnapshot("main", null, null).get("main").intValue());
|
||||
assertEquals(1, fService.getStoreVersions("main", null, new Date(times.get(0))).size());
|
||||
assertEquals(3, fService.getStoreVersions("main", new Date(times.get(0)), null).size());
|
||||
assertEquals(2, fService.getStoreVersions("main", new Date(times.get(1)),
|
||||
new Date(System.currentTimeMillis())).size());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace(System.err);
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test AVMStore functions.
|
||||
|
@@ -1058,7 +1058,7 @@ public class AVMStoreImpl implements AVMStore, Serializable
|
||||
throw new AVMNotFoundException("Path " + path + " not found.");
|
||||
}
|
||||
AVMNode node = lPath.getCurrentNode();
|
||||
node.setProperties(properties);
|
||||
node.addProperties(properties);
|
||||
node.setGuid(GUID.generate());
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package org.alfresco.repo.avm;
|
||||
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
|
||||
/**
|
||||
* Interface for Plain file nodes.
|
||||
* @author britt
|
||||
@@ -17,4 +19,10 @@ interface PlainFileNode extends FileNode
|
||||
* @param mimeType
|
||||
*/
|
||||
public void setMimeType(String mimeType);
|
||||
|
||||
/**
|
||||
* Special case.
|
||||
* @return
|
||||
*/
|
||||
public ContentData getContentData();
|
||||
}
|
||||
|
@@ -129,7 +129,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode
|
||||
setVersionID(versionID + 1);
|
||||
AVMDAOs.Instance().fAVMNodeDAO.save(this);
|
||||
AVMDAOs.Instance().fAVMNodeDAO.flush();
|
||||
setProperties(props);
|
||||
addProperties(props);
|
||||
setAspects(new HashSet<QName>(aspects));
|
||||
if (acl != null)
|
||||
{
|
||||
@@ -376,6 +376,14 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode
|
||||
* @return The ContentData object for this file.
|
||||
*/
|
||||
public ContentData getContentData(Lookup lPath)
|
||||
{
|
||||
return getContentData();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.avm.PlainFileNode#getContentData()
|
||||
*/
|
||||
public ContentData getContentData()
|
||||
{
|
||||
return new ContentData(fContentURL, fMimeType, fLength, fEncoding);
|
||||
}
|
||||
|
@@ -51,6 +51,22 @@
|
||||
<key column="id"/>
|
||||
<element type="QName" not-null="true" column="name" length="200"/>
|
||||
</set>
|
||||
<map name="properties" fetch="join" lazy="false" table="avm_node_properties_new" cascade="all" optimistic-lock="true">
|
||||
<cache usage="read-write"/>
|
||||
<key column="node_id" not-null="true"/>
|
||||
<map-key type="QName" length="200" column="qname"/>
|
||||
<composite-element class="org.alfresco.repo.domain.PropertyValue">
|
||||
<property name="actualType" column="actual_type" type="string" length="15" not-null="true" />
|
||||
<property name="multiValued" column="multi_valued" type="boolean" not-null="true" />
|
||||
<property name="persistedType" column="persisted_type" type="string" length="15" not-null="true" />
|
||||
<property name="booleanValue" column="boolean_value" type="boolean" />
|
||||
<property name="longValue" column="long_value" type="long" />
|
||||
<property name="floatValue" column="float_value" type="float" />
|
||||
<property name="doubleValue" column="double_value" type="double" />
|
||||
<property name="stringValue" column="string_value" type="string" length="1024"/>
|
||||
<property name="serializableValue" column="serializable_value" type="serializable" length="16384"/>
|
||||
</composite-element>
|
||||
</map>
|
||||
<!-- Deleted nodes -->
|
||||
<subclass name="DeletedNodeImpl"
|
||||
proxy="DeletedNode"
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package org.alfresco.repo.avm.hibernate;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.avm.AVMNode;
|
||||
@@ -91,4 +92,15 @@ class AVMNodePropertyDAOHibernate extends HibernateDaoSupport
|
||||
delete.setParameter("name", name);
|
||||
delete.executeUpdate();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.avm.AVMNodePropertyDAO#iterate()
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator<AVMNodeProperty> iterate()
|
||||
{
|
||||
Query query =
|
||||
getSession().createQuery("from AVMNodePropertyImpl anp");
|
||||
return (Iterator<AVMNodeProperty>)query.iterate();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user