/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2007-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.web.svclayer.support; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.opennms.netmgt.config.attrsummary.Attribute; import org.opennms.netmgt.config.attrsummary.Resource; import org.opennms.netmgt.config.attrsummary.Summary; import org.opennms.netmgt.dao.FilterDao; import org.opennms.netmgt.dao.ResourceDao; import org.opennms.netmgt.dao.RrdDao; import org.opennms.netmgt.dao.support.NodeSnmpResourceType; import org.opennms.netmgt.model.AbstractEntityVisitor; import org.opennms.netmgt.model.OnmsNode; import org.opennms.netmgt.model.OnmsResource; import org.opennms.netmgt.model.RrdGraphAttribute; import org.opennms.web.svclayer.RrdSummaryService; import org.opennms.web.svclayer.SummarySpecification; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; /** * <p>DefaultRrdSummaryService class.</p> * * @author <a href="mailto:brozow@opennms.org">Mathew Brozowski</a> * @version $Id: $ * @since 1.8.1 */ public class DefaultRrdSummaryService implements RrdSummaryService, InitializingBean { static class SummaryBuilder { private SummaryHolder m_root; private ResourceHolder m_currentResource; private Attribute m_currAttr; interface ResourceParent { public boolean isRoot(); public void addResource(Resource resource); public void commit(); } class SummaryHolder implements ResourceParent { Summary m_summary = new Summary(); public void addResource(Resource resource) { m_summary.addResource(resource); } public void commit() { } public Summary getSummary() { return m_summary; } public boolean isRoot() { return true; } public String toString() { return "[root]"; } } class ResourceHolder implements ResourceParent { ResourceParent m_parent; boolean m_commited = false; Resource m_resource; ResourceHolder(ResourceParent parent, String name) { Assert.notNull(parent, "parent must not be null"); m_parent = parent; m_resource = new Resource(); m_resource.setName(name); } public ResourceParent getParent() { return m_parent; } public boolean isCommited() { return m_commited; } public void commit() { if (isCommited()) return; if (m_parent != null) m_parent.commit(); addSelf(); m_commited = true; } public void addResource(Resource resource) { m_resource.addResource(resource); } protected Attribute addAttribute(String name) { Attribute attr = new Attribute(); attr.setName(name); m_resource.addAttribute(attr); commit(); return attr; } protected void addSelf() { if (getParent() == null) { m_root.addResource(m_resource); } else { getParent().addResource(m_resource); } } public String toString() { return (getParent() == null ? "[root]" : getParent().toString())+".["+m_resource.getName()+"]"; } public boolean isRoot() { return false; } } SummaryBuilder() { m_root = new SummaryHolder(); } Summary getSummary() { return m_root.getSummary(); } public void addAttribute(String name) { Assert.state(m_currentResource != null, "addResource must be called before calling addAttribute"); m_currAttr = m_currentResource.addAttribute(name); } public void setMin(double min){ checkForCurrAttr(); m_currAttr.setMin(min); } private void checkForCurrAttr() { Assert.state(m_currAttr != null, "addAttribute must be called before calling setMin,setMax or setAverage"); } public void setAverage(double avg) { checkForCurrAttr(); m_currAttr.setAverage(avg); } public void setMax(double max) { checkForCurrAttr(); m_currAttr.setMax(max); } public void pushResource(String label) { ResourceParent parent = (m_currentResource == null ? m_root : m_currentResource); m_currentResource = new ResourceHolder(parent, label); } public void popResource() { Assert.state(m_currentResource != null, "you must push a resource before you can pop one"); if (m_currentResource.getParent().isRoot()) { m_currentResource = null; } else { m_currentResource = (ResourceHolder)m_currentResource.getParent(); } } } public FilterDao m_filterDao; public ResourceDao m_resourceDao; public RrdDao m_rrdDao; public Stats m_stats = new Stats(); static class OpStats { private String m_name; private int m_count = 0; private long m_total = 0; private long m_lastStarted = -1; OpStats(String n) { m_name = n; } void begin() { m_count++; m_lastStarted = System.nanoTime(); } void end() { long ended = System.nanoTime(); Assert.state(m_lastStarted >= 0, "must call begin before calling end"); m_total += (ended - m_lastStarted); m_lastStarted = -1; } @Override public String toString() { double total = (double)m_total; return String.format("stats: %s: count=%d, totalTime=%f ms ( %f us/call )", m_name, m_count, total/1000000.0, total/(m_count*1000.0)); } } static class Stats { Map<String, OpStats> map = new LinkedHashMap<String, OpStats>(); public void begin(String operation) { if (!map.containsKey(operation)) { map.put(operation, new OpStats(operation)); } map.get(operation).begin(); } public void end(String operation) { map.get(operation).end(); } @Override public String toString() { StringBuilder bldr = new StringBuilder(map.size()*50); for (OpStats opStat : map.values()) { bldr.append(opStat); bldr.append('\n'); } return bldr.toString(); } } /** * <p>getSummary</p> * * @param filterRule a {@link java.lang.String} object. * @param startTime a long. * @param endTime a long. * @param attributeSieve a {@link java.lang.String} object. * @return a {@link org.opennms.netmgt.config.attrsummary.Summary} object. */ public Summary getSummary(String filterRule, final long startTime, final long endTime, final String attributeSieve) { m_stats.begin("getSummary"); try { final SummaryBuilder bldr = new SummaryBuilder(); m_filterDao.walkMatchingNodes(filterRule, new AbstractEntityVisitor() { public void visitNode(OnmsNode node) { OnmsResource nodeResource = getResourceForNode(node); bldr.pushResource(node.getLabel()); for(OnmsResource child : getChildResources1(nodeResource)) { if (child.getResourceType() instanceof NodeSnmpResourceType) { addAttributes(getResourceGraphAttributes(child)); } } for(OnmsResource child : getChildResources2(nodeResource)) { if (!(child.getResourceType() instanceof NodeSnmpResourceType)) { addResource(child); } } bldr.popResource(); } private Collection<RrdGraphAttribute> getResourceGraphAttributes(OnmsResource child) { String op = "getResourceGraphAttributes-"+child.getResourceType().getName(); m_stats.begin(op); try { return child.getRrdGraphAttributes().values(); } finally { m_stats.end(op); } } private List<OnmsResource> getChildResources1(OnmsResource nodeResource) { m_stats.begin("getChildResources1"); try { return nodeResource.getChildResources(); } finally { m_stats.end("getChildResources1"); } } private List<OnmsResource> getChildResources2(OnmsResource nodeResource) { m_stats.begin("getChildResources2"); try { return nodeResource.getChildResources(); } finally { m_stats.end("getChildResources2"); } } private OnmsResource getResourceForNode(OnmsNode node) { m_stats.begin("getResourceForNode"); try { return m_resourceDao.getResourceForNode(node); } finally { m_stats.end("getResourceForNode"); } } private void addResource(OnmsResource resource) { addResource(resource, resource.getLabel()); } private void addResource(OnmsResource resource, String label) { Collection<RrdGraphAttribute> attrs = getResourceGraphAttributes(resource); if (attrs.size() > 0) { bldr.pushResource(label); addAttributes(attrs); bldr.popResource(); } } private void addAttributes(Collection<RrdGraphAttribute> attrs) { m_stats.begin("addAttributes"); try { for(RrdGraphAttribute attr : attrs) { if (attr.getName().matches(attributeSieve)) { bldr.addAttribute(attr.getName()); double[] values = getValues(attr); bldr.setMin(values[0]); bldr.setAverage(values[1]); bldr.setMax(values[2]); } } } finally { m_stats.end("addAttributes"); } } private double[] getValues(RrdGraphAttribute attr) { m_stats.begin("getValues"); try { return m_rrdDao.getPrintValues(attr, "AVERAGE", startTime*1000, endTime*1000, "MIN", "AVERAGE", "MAX"); } finally { m_stats.end("getValues"); } } }); return bldr.getSummary(); } finally { m_stats.end("getSummary"); } } /** * <p>afterPropertiesSet</p> * * @throws java.lang.Exception if any. */ @Override public void afterPropertiesSet() throws Exception { Assert.state(m_filterDao != null, "filterDao property must be set"); Assert.state(m_resourceDao != null, "resourceDao property must be set"); Assert.state(m_rrdDao != null, "rrdDao property must be set"); } /** * <p>setFilterDao</p> * * @param filterDao a {@link org.opennms.netmgt.dao.FilterDao} object. */ public void setFilterDao(FilterDao filterDao) { m_filterDao = filterDao; } /** * <p>setResourceDao</p> * * @param resourceDao a {@link org.opennms.netmgt.dao.ResourceDao} object. */ public void setResourceDao(ResourceDao resourceDao) { m_resourceDao = resourceDao; } /** * <p>setRrdDao</p> * * @param rrdDao a {@link org.opennms.netmgt.dao.RrdDao} object. */ public void setRrdDao(RrdDao rrdDao) { m_rrdDao = rrdDao; } /** {@inheritDoc} */ public Summary getSummary(SummarySpecification spec) { return getSummary(spec.getFilterRule(), spec.getStartTime(), spec.getEndTime(), spec.getAttributeSieve()); } }