[rhq] modules/enterprise

Jay Shaughnessy jshaughn at fedoraproject.org
Thu Aug 16 16:47:52 UTC 2012


 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java                           |    3 
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java |   15 +-
 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java                       |   14 ++
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java                                  |   68 ++++++++++
 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java                                 |   18 ++
 5 files changed, 112 insertions(+), 6 deletions(-)

New commits:
commit 30a6818e7ae101dc8df7edc198c5ee9ac790683e
Author: Jay Shaughnessy <jshaughn at redhat.com>
Date:   Thu Aug 16 12:39:22 2012 -0400

    [Bug 784571 - Resource tree not complete when more than 200 children]
    We decided not to allow an unlimited number of child resources be returned
    when expanding a node in the tree.  But there are major problems with
    simply limiting the children to 200.  This is what we do today, and the
    results are unordered. Meaning you can lose any number of resources of
    any types and it is not possible to know what you are missing. And we don't
    indicate that the tree is incomplete. If we add ordering (alphabetical by
    resource name) you still lose any number of resources, but always the same
    ones.  In this way it is much easier to realize that you are missing
    child resources (and/or entire child types) because the resources returned
    obviously stop as some lexigraphical point.
    
    Still, we don't want to allow an unbounded fetch in the GUI.  The solution
    here is to move the unbounded fetch to the server side and to introduce
    SLSB support to prune the results and return the pruned child set.  In this
    way we can limit the max child resources while returning a much more
    reasonable resource set.
    
    The way it works is as follows: There are two variable in use:
    
    maxResources
    Will not return more than this number of resources.  If the original fetch
    exceeds maxResources then maxResourcesByType will be enforced.  If, after
    trimming by type, maxResources is still exceeded, then the tail
    resources (assuming a sorted set) will be removed to enforce the limit.
    If <=0 the default (currently set to 1000) will be used.
    
    maxResourcesByType
    If maxResources is exceeded by the initial result set then members of each
    type will be trimmed down to meet this limit.
    If <=0 the default (currently set to 200) will be used.
    
    The defaults may change after this check-in based on testing results. The
    GUI will not set these values in the fetch, so the defaults will be applied.
    
    The default values can be overriden (and applied to all fetches/sessions) by
    setting the following system properties (in rhq-server.properties and restarting):
    rhq.server.findResourcesByCriteriaBounded.maxResources
    rhq.server.findResourcesByCriteriaBounded.maxResourcesByType
    
    So, this allows us to:
    - Avoid an unbounded fetch.
    - Have any distribution of child resources of various types as long as the
      maxResources limit is not exceeded.
    - Apply an even and understandable pruning when necessary.
    
    It does not yet allow us to indicate in the tree which resource types have
    been pruned.  This will be a future enhancement and tracked as
    https://bugzilla.redhat.com/show_bug.cgi?id=848853.

diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java
index 59d96c6..1cdc64c 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/ResourceGWTService.java
@@ -70,6 +70,9 @@ public interface ResourceGWTService extends RemoteService {
 
     PageList<Resource> findResourcesByCriteria(ResourceCriteria criteria) throws RuntimeException;
 
+    List<Resource> findResourcesByCriteriaBounded(ResourceCriteria criteria, int maxResources, int maxResourcesByType)
+        throws RuntimeException;
+
     PageList<ResourceComposite> findResourceCompositesByCriteria(ResourceCriteria criteria) throws RuntimeException;
 
     List<ResourceError> findResourceErrors(int resourceId) throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
index 5c58a70..b6a5f5f 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeDatasource.java
@@ -44,8 +44,7 @@ import org.rhq.core.domain.criteria.ResourceCriteria;
 import org.rhq.core.domain.resource.Resource;
 import org.rhq.core.domain.resource.ResourceSubCategory;
 import org.rhq.core.domain.resource.ResourceType;
-import org.rhq.core.domain.util.PageControl;
-import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageOrdering;
 import org.rhq.enterprise.gui.coregui.client.CoreGUI;
 import org.rhq.enterprise.gui.coregui.client.Messages;
 import org.rhq.enterprise.gui.coregui.client.ViewChangedException;
@@ -159,12 +158,16 @@ public class ResourceTreeDatasource extends DataSource {
         } else {
             Log.debug("ResourceTreeDatasource: Loading Resource [" + parentResourceId + "]...");
 
+            // This fetch limits the number of resources that can be returned to protect against fetching a massive
+            // number of children for a parent. Doing so may cause an unacceptably slow tree rendering, too much vertical
+            // scroll, or perhaps even hang the gui if it consumed too many resources.  To see all children the
+            // user will need to visit the Inventory->Children view for the resource.
             ResourceCriteria criteria = new ResourceCriteria();
             criteria.addFilterParentResourceId(Integer.parseInt(parentResourceId));
-            // we don't need sorting since we get everything and the tree nodes are already sorted
-            criteria.setPageControl(PageControl.getUnlimitedInstance());
+            // we must sort the results to ensure that if cropped we at least show the same results each time
+            criteria.addSortName(PageOrdering.ASC);
 
-            resourceService.findResourcesByCriteria(criteria, new AsyncCallback<PageList<Resource>>() {
+            resourceService.findResourcesByCriteriaBounded(criteria, -1, -1, new AsyncCallback<List<Resource>>() {
                 public void onFailure(Throwable caught) {
                     CoreGUI.getErrorHandler().handleError(MSG.view_tree_common_loadFailed_children(), caught);
                     response.setStatus(RPCResponse.STATUS_FAILURE);
@@ -173,7 +176,7 @@ public class ResourceTreeDatasource extends DataSource {
                     loadingLabel.hide();
                 }
 
-                public void onSuccess(PageList<Resource> result) {
+                public void onSuccess(List<Resource> result) {
                     processIncomingData(result, response, requestId);
                 }
             });
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java
index 17ccd78..4ee821b 100644
--- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java
+++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/ResourceGWTServiceImpl.java
@@ -145,6 +145,20 @@ public class ResourceGWTServiceImpl extends AbstractGWTServiceImpl implements Re
         }
     }
 
+    public List<Resource> findResourcesByCriteriaBounded(ResourceCriteria criteria, int maxResources,
+        int maxResourcesByType) throws RuntimeException {
+        try {
+            List<Resource> result = resourceManager.findResourcesByCriteriaBounded(getSessionSubject(), criteria,
+                maxResources, maxResourcesByType);
+
+            ObjectFilter.filterFieldsInCollection(result, importantFieldsSet);
+
+            return SerialUtility.prepare(result, "ResourceService.findResourcesByCriteriaBounded");
+        } catch (Throwable t) {
+            throw getExceptionToThrowToClient(t);
+        }
+    }
+
     public PageList<ResourceComposite> findResourceCompositesByCriteria(ResourceCriteria criteria)
         throws RuntimeException {
         try {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
index dce2e23..0fe906a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java
@@ -24,6 +24,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -142,6 +143,9 @@ import org.rhq.enterprise.server.util.QueryUtility;
 public class ResourceManagerBean implements ResourceManagerLocal, ResourceManagerRemote {
     private final Log log = LogFactory.getLog(ResourceManagerBean.class);
 
+    private final static String BOUNDED_MAX_RESOURCES = "1000";
+    private final static String BOUNDED_MAX_RESOURCES_BY_TYPE = "200";
+
     @PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
     private EntityManager entityManager;
 
@@ -2472,6 +2476,70 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
         return results;
     }
 
+    @Override
+    public List<Resource> findResourcesByCriteriaBounded(Subject subject, ResourceCriteria criteria, int maxResources,
+        int maxResourcesByType) {
+
+        // find all of the requested resources but don't return them until they meet our bounded return requirements
+        // maintain any requested sorting
+        criteria.clearPaging();
+
+        // perform the requested criteria query
+        PageList<Resource> results = findResourcesByCriteria(subject, criteria);
+
+        // If not specified use the default maxResources
+        if (maxResources <= 0) {
+            try {
+                maxResources = Integer.parseInt(System.getProperty(
+                    "rhq.server.findResourcesByCriteriaBounded.maxResources", BOUNDED_MAX_RESOURCES));
+            } catch (NumberFormatException e) {
+            }
+            if (maxResources <= 0) {
+                maxResources = Integer.parseInt(BOUNDED_MAX_RESOURCES);
+            }
+        }
+
+        if (results.getTotalSize() <= maxResources) {
+            return results;
+        }
+
+        // If not specified use the default maxResourcesByType
+        if (maxResourcesByType <= 0) {
+            try {
+                maxResourcesByType = Integer.parseInt(System.getProperty(
+                    "rhq.server.findResourcesByCriteriaBounded.maxResourcesByType", BOUNDED_MAX_RESOURCES_BY_TYPE));
+            } catch (NumberFormatException e) {
+            }
+            if (maxResourcesByType <= 0) {
+                maxResourcesByType = Integer.parseInt(BOUNDED_MAX_RESOURCES_BY_TYPE);
+            }
+        }
+
+        // We need to trim the returned resources, enforce maxResourcesByType
+        Map<Integer, Integer> typeCounts = new HashMap<Integer, Integer>();
+
+        for (Iterator<Resource> i = results.iterator(); i.hasNext();) {
+            Resource r = i.next();
+            Integer typeId = r.getResourceType().getId();
+            Integer count = typeCounts.get(typeId);
+            if (null == count) {
+                count = 0;
+            }
+            typeCounts.put(typeId, ++count);
+            if (count > maxResourcesByType) {
+                i.remove();
+            }
+        }
+
+        // If after we've trimmed all types the results are still more than maxSize then we need to just chop
+        // keeping the most important (presumably the beginning of the list, if it's sorted)
+        while (maxResources < results.size()) {
+            results.remove(maxResources);
+        }
+
+        return results;
+    }
+
     public Resource getPlaformOfResource(Subject subject, int resourceId) {
         Resource resource = null;
         Resource parent = null;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
index fc075be..f555116 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java
@@ -446,6 +446,24 @@ public interface ResourceManagerLocal {
      */
     public void updateAncestry(Subject subject, int resourceId);
 
+    /**
+     * This method exists to support the GUI resource tree, by not returning an unlimited number of resources
+     * but instead bounding the returned size.  Note, this routine does not offer paging and any PageControl set in
+     * the Criteria is ignored. This is for use when paging is not required or possible, such as in a tree. 
+     *  
+     * @param subject
+     * @param criteria
+     * @param maxResources Will not return more than this number of resources.  If the original fetch exceeds maxResources
+     * then maxResourcesByType will be enforced.  If, after trimming by type, maxResources is still exceeded, then the least
+     * significant resources (the tail, assuming a sorted set) will be removed to enforce the limit. If <=0 the default
+     * will be used.     
+     * @param maxResourcesByType If maxResources is exceeded by the initial result set then members of each type will be
+     * trimmed down to meet this limit.  If <=0 the default will be used.
+     * @return The resulting resources, trimmed if necessary to meet the specify sizing bounds.
+     */
+    List<Resource> findResourcesByCriteriaBounded(Subject subject, ResourceCriteria criteria, int maxResources,
+        int maxResourcesByType);
+
     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     //
     // The following are shared with the Remote Interface




More information about the rhq-commits mailing list