Merge HEAD to BRANCHES/V2.1.0.x:

74932: RM-1461: CLONE - RM slower then standard repo/sites when rendering document details when folder contains 15k documents



git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.1.0.x@76597 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Roy Wetherall
2014-07-16 02:00:27 +00:00
parent 558399aa2b
commit ca26cf5715
7 changed files with 522 additions and 420 deletions

View File

@@ -272,6 +272,7 @@
<aspect>rma:recordComponentIdentifier</aspect>
<aspect>rma:commonRecordDetails</aspect>
<aspect>rma:filePlanComponent</aspect>
<aspect>rma:heldChildren</aspect>
</mandatory-aspects>
</type>
@@ -1213,6 +1214,20 @@
</properties>
</aspect>
<!-- Number of held children, used to improve evaluation performance -->
<!-- @since 2.2 -->
<aspect name="rma:heldChildren">
<title>Held children</title>
<properties>
<property name="rma:heldChildrenCount">
<type>d:int</type>
<protected>true</protected>
<mandatory>true</mandatory>
<default>0</default>
</property>
</properties>
</aspect>
<!-- Helper aspect that can be used to keep a count -->
<aspect name="rma:countable">
<title>Countable aspect</title>

View File

@@ -57,7 +57,6 @@ import org.alfresco.service.cmr.repository.Period;
import org.alfresco.service.cmr.security.OwnableService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.PropertyCheck;
import org.springframework.beans.factory.BeanNameAware;

View File

@@ -42,11 +42,13 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ParameterCheck;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
@@ -191,10 +193,10 @@ public class FreezeServiceImpl extends ServiceBaseImpl
for (ChildAssociationRef assoc : assocs)
{
// we only care about primary children
if (assoc.isPrimary() == true)
if (assoc.isPrimary())
{
NodeRef nodeRef = assoc.getChildRef();
if (isFrozen(nodeRef) == true)
if (isFrozen(nodeRef))
{
// never allowed to delete a node with a frozen child
throw new AccessDeniedException("Can not delete node, because it contains a frozen child node.");
@@ -531,21 +533,68 @@ public class FreezeServiceImpl extends ServiceBaseImpl
* @see org.alfresco.module.org_alfresco_module_rm.freeze.FreezeService#hasFrozenChildren(org.alfresco.service.cmr.repository.NodeRef)
*/
@Override
public boolean hasFrozenChildren(NodeRef nodeRef)
public boolean hasFrozenChildren(final NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
List<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS,
RegexQNamePattern.MATCH_ALL);
boolean result = false;
// check that we are dealing with a record folder
if (isRecordFolder(nodeRef))
{
int heldCount = 0;
if (nodeService.hasAspect(nodeRef, ASPECT_HELD_CHILDREN))
{
heldCount = (Integer)getInternalNodeService().getProperty(nodeRef, PROP_HELD_CHILDREN_COUNT);
}
else
{
final TransactionService transactionService = (TransactionService)applicationContext.getBean("transactionService");
heldCount = AuthenticationUtil.runAsSystem(new RunAsWork<Integer>()
{
@Override
public Integer doWork()
{
return transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Integer>()
{
public Integer execute() throws Throwable
{
int heldCount = 0;
// NOTE: this process remains to 'patch' older systems to improve performance next time around
List<ChildAssociationRef> childAssocs = getInternalNodeService().getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, null);
if (childAssocs != null && !childAssocs.isEmpty())
{
for (ChildAssociationRef childAssociationRef : childAssocs)
{
if (isFrozen(childAssociationRef.getChildRef())) { return true; }
NodeRef record = childAssociationRef.getChildRef();
if (childAssociationRef.isPrimary() && isRecord(record) && isFrozen(record))
{
heldCount ++;
}
}
}
return false;
// add aspect and set count
Map<QName, Serializable> props = new HashMap<QName, Serializable>(1);
props.put(PROP_HELD_CHILDREN_COUNT, heldCount);
getInternalNodeService().addAspect(nodeRef, ASPECT_HELD_CHILDREN, props);
return heldCount;
}
},
false, true);
}
});
}
// true if more than one child held
result = (heldCount > 0);
}
return result;
}
/**

View File

@@ -214,6 +214,23 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONC
}
}
/**
* @see org.alfresco.repo.jscript.app.JSONConversionComponent#permissionsToJSON(org.alfresco.service.cmr.repository.NodeRef)
*/
protected JSONObject permissionsToJSON(final NodeRef nodeRef)
{
JSONObject permissionsJSON = null;
if (!filePlanService.isFilePlanComponent(nodeRef))
{
permissionsJSON = super.permissionsToJSON(nodeRef);
}
else
{
permissionsJSON = new JSONObject();
}
return permissionsJSON;
}
/**
* Gets the rm 'type' used as a UI convenience and compatibility flag.
*/

View File

@@ -253,6 +253,11 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel
public static final QName PROP_RECORD_REJECTION_DATE = QName.createQName(RM_URI, "recordRejectionDate");
public static final QName PROP_RECORD_REJECTION_REASON = QName.createQName(RM_URI, "recordRejectionReason");
// Held children aspect
// @since 2.2
QName ASPECT_HELD_CHILDREN = QName.createQName(RM_URI, "heldChildren");
QName PROP_HELD_CHILDREN_COUNT = QName.createQName(RM_URI, "heldChildrenCount");
// Countable aspect
public static final QName ASPECT_COUNTABLE = QName.createQName(RM_URI, "countable");
public static final QName PROP_COUNT = QName.createQName(RM_URI, "count");

View File

@@ -18,6 +18,8 @@
*/
package org.alfresco.module.org_alfresco_module_rm.util;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind;
@@ -85,7 +87,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
* <p>
* Used for performance reasons.
*/
private NodeService getInternalNodeService()
protected NodeService getInternalNodeService()
{
if (internalNodeService == null)
{
@@ -270,6 +272,8 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
/**
* Indicates whether the given node reference is a hold or not.
* <p>
* Exposed publicly in the {@link HoldService}
*
* @param nodeRef node reference
* @return boolean true if rma:hold or sub-type, false otherwise
@@ -289,6 +293,8 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
/**
* Indicates whether the given node reference is a transfer or not.
*
* @see org.alfresco.module.org_alfresco_module_rm.transfer.TransferService#isTransfer(NodeRef)
*/
public boolean isTransfer(NodeRef nodeRef)
{
@@ -321,7 +327,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
if (nodeRef != null)
{
result = (NodeRef)getInternalNodeService().getProperty(nodeRef, PROP_ROOT_NODEREF);
if (result == null)
if (result == null || !instanceOf(result, TYPE_FILE_PLAN))
{
if (instanceOf(nodeRef, TYPE_FILE_PLAN))
{
@@ -355,6 +361,8 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
return instanceOf(className, ofClassName);
}
private static Map<String, Boolean> instanceOfCache = new HashMap<String, Boolean>();
/**
* Utility method to quickly determine whether one class is equal to or sub of another.
*
@@ -366,12 +374,25 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{
ParameterCheck.mandatory("className", className);
ParameterCheck.mandatory("ofClassName", ofClassName);
boolean result = false;
String key = className.toString() + "|" + ofClassName.toString();
if (instanceOfCache.containsKey(key))
{
result = instanceOfCache.get(key);
}
else
{
if (ofClassName.equals(className) ||
dictionaryService.isSubClass(className, ofClassName))
{
result = true;
}
instanceOfCache.put(key, result);
}
return result;
}

View File

@@ -62,7 +62,6 @@ public class FreezeServiceImplTest extends BaseRMTestCase
// Freeze a record
freezeService.freeze("FreezeReason", recordOne);
assertTrue(freezeService.hasFrozenChildren(rmFolder));
// Check the hold exists
Set<NodeRef> holdAssocs = freezeService.getHolds(filePlan);
@@ -192,7 +191,6 @@ public class FreezeServiceImplTest extends BaseRMTestCase
assertFalse(freezeService.isFrozen(recordTwo));
assertFalse(freezeService.isFrozen(recordThree));
assertFalse(freezeService.isFrozen(recordFour));
assertFalse(freezeService.hasFrozenChildren(rmFolder));
// Test freezing nodes, adding them to an existing hold
NodeRef hold = freezeService.freeze("AnotherFreezeReason", recordFour);
@@ -201,7 +199,6 @@ public class FreezeServiceImplTest extends BaseRMTestCase
nodes.add(recordTwo);
nodes.add(recordThree);
freezeService.freeze(hold, nodes);
assertTrue(freezeService.hasFrozenChildren(rmFolder));
// Check the hold
holdAssocs = freezeService.getHolds(filePlan);
@@ -216,7 +213,6 @@ public class FreezeServiceImplTest extends BaseRMTestCase
assertFalse(freezeService.isFrozen(recordTwo));
assertFalse(freezeService.isFrozen(recordThree));
assertFalse(freezeService.isFrozen(recordFour));
assertFalse(freezeService.hasFrozenChildren(rmFolder));
return null;
}