. Tree Navigator performance improvement

- explicit txns around multiple nodeservice calls and internal (permission check free) nodeservice to retrieve node names
 - 25% improvement to retrieving node lists
. Permission code hotspot tuning and nodeservice methods ACL configuration tuning

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@4960 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2007-01-29 18:42:30 +00:00
parent 200ff43d6e
commit c68cf150b4
3 changed files with 148 additions and 80 deletions

View File

@@ -8,6 +8,7 @@ import java.util.Map;
import javax.faces.context.FacesContext; import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter; import javax.faces.context.ResponseWriter;
import javax.transaction.UserTransaction;
import org.alfresco.model.ApplicationModel; import org.alfresco.model.ApplicationModel;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
@@ -47,6 +48,7 @@ public class NavigatorPluginBean implements IContextListener
protected NodeRef previouslySelectedNode; protected NodeRef previouslySelectedNode;
private NodeService nodeService; private NodeService nodeService;
private NodeService internalNodeService;
private DictionaryService dictionaryService; private DictionaryService dictionaryService;
private static final Log logger = LogFactory.getLog(NavigatorPluginBean.class); private static final Log logger = LogFactory.getLog(NavigatorPluginBean.class);
@@ -69,54 +71,68 @@ public class NavigatorPluginBean implements IContextListener
FacesContext context = FacesContext.getCurrentInstance(); FacesContext context = FacesContext.getCurrentInstance();
ResponseWriter out = context.getResponseWriter(); ResponseWriter out = context.getResponseWriter();
Map params = context.getExternalContext().getRequestParameterMap(); UserTransaction tx = null;
String nodeRefStr = (String)params.get("nodeRef"); try
String area = (String)params.get("area");
if (logger.isDebugEnabled())
logger.debug("retrieveChildren: area = " + area + ", nodeRef = " + nodeRefStr);
// work out which list to cache the nodes in
Map<String, TreeNode> currentNodes = getNodesMapForArea(area);
if (nodeRefStr != null && currentNodes != null)
{ {
// get the given node's details tx = Repository.getUserTransaction(context, true);
NodeRef parentNodeRef = new NodeRef(nodeRefStr); tx.begin();
TreeNode parentNode = currentNodes.get(parentNodeRef.toString());
parentNode.setExpanded(true); Map params = context.getExternalContext().getRequestParameterMap();
String nodeRefStr = (String)params.get("nodeRef");
String area = (String)params.get("area");
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("retrieving children for noderef: " + parentNodeRef); logger.debug("retrieveChildren: area = " + area + ", nodeRef = " + nodeRefStr);
// remove any existing children as the latest ones will be added below // work out which list to cache the nodes in
parentNode.removeChildren(); Map<String, TreeNode> currentNodes = getNodesMapForArea(area);
// get all the child folder objects for the parent if (nodeRefStr != null && currentNodes != null)
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(parentNodeRef,
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
StringBuilder xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><nodes>");
for (ChildAssociationRef ref: childRefs)
{ {
NodeRef nodeRef = ref.getChildRef(); // get the given node's details
NodeRef parentNodeRef = new NodeRef(nodeRefStr);
TreeNode parentNode = currentNodes.get(parentNodeRef.toString());
parentNode.setExpanded(true);
if (isAddableChild(nodeRef)) if (logger.isDebugEnabled())
logger.debug("retrieving children for noderef: " + parentNodeRef);
// remove any existing children as the latest ones will be added below
parentNode.removeChildren();
// get all the child folder objects for the parent
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(parentNodeRef,
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
StringBuilder xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?><nodes>");
for (ChildAssociationRef ref: childRefs)
{ {
// build the XML representation of the child node NodeRef nodeRef = ref.getChildRef();
TreeNode childNode = createTreeNode(nodeRef);
parentNode.addChild(childNode); if (isAddableChild(nodeRef))
currentNodes.put(childNode.getNodeRef(), childNode); {
xml.append(childNode.toXML()); // build the XML representation of the child node
TreeNode childNode = createTreeNode(nodeRef);
parentNode.addChild(childNode);
currentNodes.put(childNode.getNodeRef(), childNode);
xml.append(childNode.toXML());
}
} }
xml.append("</nodes>");
// send the generated XML back to the tree
out.write(xml.toString());
if (logger.isDebugEnabled())
logger.debug("returning XML: " + xml.toString());
} }
xml.append("</nodes>");
// send the generated XML back to the tree // commit the transaction
out.write(xml.toString()); tx.commit();
}
if (logger.isDebugEnabled()) catch (Throwable err)
logger.debug("returning XML: " + xml.toString()); {
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
} }
} }
@@ -263,22 +279,35 @@ public class NavigatorPluginBean implements IContextListener
this.companyHomeRootNodes = new ArrayList<TreeNode>(); this.companyHomeRootNodes = new ArrayList<TreeNode>();
this.companyHomeNodes = new HashMap<String, TreeNode>(); this.companyHomeNodes = new HashMap<String, TreeNode>();
// query for the child nodes of company home UserTransaction tx = null;
NodeRef root = new NodeRef(Repository.getStoreRef(), try
Application.getCompanyRootId());
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(root,
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
for (ChildAssociationRef ref: childRefs)
{ {
NodeRef child = ref.getChildRef(); tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
tx.begin();
if (isAddableChild(child)) // query for the child nodes of company home
NodeRef root = new NodeRef(Repository.getStoreRef(),
Application.getCompanyRootId());
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(root,
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
for (ChildAssociationRef ref: childRefs)
{ {
TreeNode node = createTreeNode(child); NodeRef child = ref.getChildRef();
this.companyHomeRootNodes.add(node);
this.companyHomeNodes.put(node.getNodeRef(), node); if (isAddableChild(child))
{
TreeNode node = createTreeNode(child);
this.companyHomeRootNodes.add(node);
this.companyHomeNodes.put(node.getNodeRef(), node);
}
} }
tx.commit();
}
catch (Throwable err)
{
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
} }
} }
@@ -301,22 +330,35 @@ public class NavigatorPluginBean implements IContextListener
this.myHomeRootNodes = new ArrayList<TreeNode>(); this.myHomeRootNodes = new ArrayList<TreeNode>();
this.myHomeNodes = new HashMap<String, TreeNode>(); this.myHomeNodes = new HashMap<String, TreeNode>();
// query for the child nodes of the user's home UserTransaction tx = null;
NodeRef root = new NodeRef(Repository.getStoreRef(), try
Application.getCurrentUser(FacesContext.getCurrentInstance()).getHomeSpaceId());
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(root,
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
for (ChildAssociationRef ref: childRefs)
{ {
NodeRef child = ref.getChildRef(); tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
tx.begin();
if (isAddableChild(child)) // query for the child nodes of the user's home
NodeRef root = new NodeRef(Repository.getStoreRef(),
Application.getCurrentUser(FacesContext.getCurrentInstance()).getHomeSpaceId());
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(root,
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
for (ChildAssociationRef ref: childRefs)
{ {
TreeNode node = createTreeNode(child); NodeRef child = ref.getChildRef();
this.myHomeRootNodes.add(node);
this.myHomeNodes.put(node.getNodeRef(), node); if (isAddableChild(child))
{
TreeNode node = createTreeNode(child);
this.myHomeRootNodes.add(node);
this.myHomeNodes.put(node.getNodeRef(), node);
}
} }
tx.commit();
}
catch (Throwable err)
{
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
} }
} }
@@ -339,25 +381,38 @@ public class NavigatorPluginBean implements IContextListener
this.guestHomeRootNodes = new ArrayList<TreeNode>(); this.guestHomeRootNodes = new ArrayList<TreeNode>();
this.guestHomeNodes = new HashMap<String, TreeNode>(); this.guestHomeNodes = new HashMap<String, TreeNode>();
// query for the child nodes of the guest home space UserTransaction tx = null;
NavigationBean navBean = getNavigationBean(); try
if (navBean != null)
{ {
NodeRef root = navBean.getGuestHomeNode().getNodeRef(); tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(root, tx.begin();
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
for (ChildAssociationRef ref: childRefs) // query for the child nodes of the guest home space
NavigationBean navBean = getNavigationBean();
if (navBean != null)
{ {
NodeRef child = ref.getChildRef(); NodeRef root = navBean.getGuestHomeNode().getNodeRef();
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(root,
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
if (isAddableChild(child)) for (ChildAssociationRef ref: childRefs)
{ {
TreeNode node = createTreeNode(child); NodeRef child = ref.getChildRef();
this.guestHomeRootNodes.add(node);
this.guestHomeNodes.put(node.getNodeRef(), node); if (isAddableChild(child))
{
TreeNode node = createTreeNode(child);
this.guestHomeRootNodes.add(node);
this.guestHomeNodes.put(node.getNodeRef(), node);
}
} }
} }
tx.commit();
}
catch (Throwable err)
{
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
} }
} }
@@ -372,6 +427,14 @@ public class NavigatorPluginBean implements IContextListener
this.nodeService = nodeService; this.nodeService = nodeService;
} }
/**
* @param internalNodeService The internalNodeService to set.
*/
public void setInternalNodeService(NodeService internalNodeService)
{
this.internalNodeService = internalNodeService;
}
/** /**
* @param dictionaryService The DictionaryService to set. * @param dictionaryService The DictionaryService to set.
*/ */
@@ -554,8 +617,8 @@ public class NavigatorPluginBean implements IContextListener
protected TreeNode createTreeNode(NodeRef nodeRef) protected TreeNode createTreeNode(NodeRef nodeRef)
{ {
TreeNode node = new TreeNode(nodeRef.toString(), TreeNode node = new TreeNode(nodeRef.toString(),
Repository.getNameForNode(this.nodeService, nodeRef), Repository.getNameForNode(this.internalNodeService, nodeRef),
(String)this.nodeService.getProperty(nodeRef, ApplicationModel.PROP_ICON)); (String)this.internalNodeService.getProperty(nodeRef, ApplicationModel.PROP_ICON));
return node; return node;
} }
@@ -568,7 +631,7 @@ public class NavigatorPluginBean implements IContextListener
protected NavigationBean getNavigationBean() protected NavigationBean getNavigationBean()
{ {
return (NavigationBean)FacesHelper.getManagedBean( return (NavigationBean)FacesHelper.getManagedBean(
FacesContext.getCurrentInstance(), "NavigationBean"); FacesContext.getCurrentInstance(), NavigationBean.BEAN_NAME);
} }
/** /**
@@ -579,7 +642,7 @@ public class NavigatorPluginBean implements IContextListener
protected BrowseBean getBrowseBean() protected BrowseBean getBrowseBean()
{ {
return (BrowseBean)FacesHelper.getManagedBean( return (BrowseBean)FacesHelper.getManagedBean(
FacesContext.getCurrentInstance(), "BrowseBean"); FacesContext.getCurrentInstance(), BrowseBean.BEAN_NAME);
} }
/** /**

View File

@@ -3129,6 +3129,10 @@
<property-name>nodeService</property-name> <property-name>nodeService</property-name>
<value>#{NodeService}</value> <value>#{NodeService}</value>
</managed-property> </managed-property>
<managed-property>
<property-name>internalNodeService</property-name>
<value>#{nodeService}</value>
</managed-property>
<managed-property> <managed-property>
<property-name>dictionaryService</property-name> <property-name>dictionaryService</property-name>
<value>#{DictionaryService}</value> <value>#{DictionaryService}</value>

View File

@@ -435,12 +435,13 @@ a.topToolbarLinkHighlight, a.topToolbarLinkHighlight:link, a.topToolbarLinkHighl
.pager .pager
{ {
padding: 5px 3px 4px 3px; padding: 4px 2px 3px 2px;
border: 1px dotted #cccccc; border: 1px dotted #cccccc;
} }
.pager img .pager img
{ {
margin-top:2px;
vertical-align: -20%; vertical-align: -20%;
} }