/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2006-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.netmgt.collectd;
import java.io.File;
import java.util.List;
import org.opennms.core.utils.ThreadCategory;
import org.opennms.netmgt.config.DataCollectionConfigFactory;
import org.opennms.netmgt.config.MibObject;
import org.opennms.netmgt.rrd.RrdException;
import org.opennms.netmgt.rrd.RrdUtils;
import org.opennms.netmgt.snmp.SnmpValue;
/**
* This class encapsulates an RRDTool data source. Data source information
* parsed from the DataCollection.xml file is stored in RRDDataSource objects.
*
* For additional information on RRD and RRDTool see:
* http://ee-staff.ethz.ch/~oetiker/webtools/rrdtool/
*
* @author <A HREF="mailto:mike@opennms.org">Mike </A>
* @author <A HREF="http://www.opennms.org/">OpenNMS </A>
* @author <A HREF="mailto:mike@opennms.org">Mike </A>
* @author <A HREF="http://www.opennms.org/">OpenNMS </A>
* @version 1.1.1.1
*/
public class JMXDataSource implements Cloneable {
private static final int MAX_DS_NAME_LENGTH = 19;
/** Constant <code>RRD_ERROR="RRD_ERROR"</code> */
public static final String RRD_ERROR = "RRD_ERROR";
/**
* Defines the list of supported (MIB) object types which may be mapped to
* one of the supported RRD data source types. Currently the only two
* supported RRD data source types are: COUNTER & GAUGE. A simple string
* comparison is performed against this list of supported types to determine
* if an object can be represented by an RRD data source. NOTE: String
* comparison uses String.startsWith() method so "counter32" & "counter64"
* values will match "counter" entry. Comparison is case sensitive.
*/
private static final String[] supportedObjectTypes = new String[] { "counter", "gauge", "timeticks", "integer", "octetstring" };
/**
* Index of data type in supportedObjectTypes string array.
*/
private static final int COUNTER_INDEX = 0;
private static final int GAUGE_INDEX = 1;
private static final int TIMETICKS_INDEX = 2;
private static final int INTEGER_INDEX = 3;
private static final int OCTETSTRING_INDEX = 4;
/**
* RRDTool defined Data Source Types NOTE: "DERIVE" and "ABSOLUTE" not
* currently supported.
*/
private static final String DST_GAUGE = "GAUGE";
private static final String DST_COUNTER = "COUNTER";
// private static final String DST_DERIVE = "DERIVE";
// private static final String DST_ABSOLUTE = "ABSOLUTE";
/**
* Data Source Type. This must be one of the available RRDTool data source
* type values: GAUGE, COUNTER, DERIVE, or ABSOLUTE
*/
private String m_type;
/**
* Data Source Heartbeat. This is the maximum number of seconds that may
* pass between updates of this data source before the value of the data
* source is assumed to be 'Unknown'.
*/
private int m_heartbeat;
/**
* Minimum Expected Range. Together with m_max defines the expected range of
* the data supplied by this data source. May be set to "U" for 'Unknown'.
*/
private String m_min;
/**
* Maximum Expected Range. Together with m_min defines the expected range of
* the data supplied by this data source. May be set to "U" for Unknown.
*/
private String m_max;
private String m_oid;
private String m_instance;
private String m_name;
private String m_collectionName;
/**
* <p>handlesType</p>
*
* @param objectType MIB object type being inquired about
* @return true if RRDDataSource can handle the given type, false if it can't
*/
public static boolean handlesType(String objectType) {
return (JMXDataSource.mapType(objectType)!=null);
}
/**
* Static method which takes a MIB object type (counter, counter32,
* octetstring, etc...) and returns the appropriate RRD data type. If the
* object type cannot be mapped to an RRD type, null is returned. RRD only
* supports integer data so MIB objects of type 'octetstring' are not
* supported.
*
* @param objectType -
* MIB object type to be mapped.
* @return RRD type string or NULL object type is not supported.
*/
public static String mapType(String objectType) {
String rrdType = null;
// For consistency lower case objecType parameter before comparison
objectType = objectType.toLowerCase();
int index;
for (index = 0; index < supportedObjectTypes.length; index++) {
if (objectType.startsWith(supportedObjectTypes[index]))
break;
}
switch (index) {
// counter maps to RRD data source type COUNTER.
case COUNTER_INDEX:
rrdType = DST_COUNTER;
break;
// gauge, timeticks, and integer types all map to RRD
// data source type GAUGE.
case OCTETSTRING_INDEX:
case TIMETICKS_INDEX:
case INTEGER_INDEX:
case GAUGE_INDEX:
rrdType = DST_GAUGE;
break;
// no match, object data type is NOT supported
default:
rrdType = null;
break;
}
return rrdType;
}
/**
* Constructor
*/
public JMXDataSource() {
super();
m_type = null;
m_heartbeat = 600; // 10 minutes
m_min = "U";
m_max = "U";
}
/**
* <p>Constructor for JMXDataSource.</p>
*
* @param obj a {@link org.opennms.netmgt.config.MibObject} object.
* @param collectionName a {@link java.lang.String} object.
*/
public JMXDataSource(MibObject obj, String collectionName) {
m_collectionName = collectionName;
ThreadCategory log = ThreadCategory.getInstance(getClass());
// Assign heartbeat using formula (2 * step) and hard code
// min & max values to "U" ("unknown").
this.setHeartbeat(
2
* DataCollectionConfigFactory.getInstance().getStep(
collectionName));
// Truncate MIB object name/alias if it exceeds the 19 char max for
// RRD data source names.
if (this.getName().length() > MAX_DS_NAME_LENGTH) {
if (log.isEnabledFor(ThreadCategory.Level.WARN))
log.warn(
"buildDataSourceList: Mib object name/alias '"
+ obj.getAlias()
+ "' exceeds 19 char maximum for RRD data source names, truncating.");
char[] temp = this.getName().toCharArray();
this.setName(String.copyValueOf(temp, 0, MAX_DS_NAME_LENGTH));
}
// Map MIB object data type to RRD data type
this.setType(JMXDataSource.mapType(obj.getType()));
this.m_min = "U";
this.m_max = "U";
// Assign the data source object identifier and instance
if (log.isDebugEnabled()) {
log.debug(
"buildDataSourceList: ds_name: "
+ this.getName()
+ " ds_oid: "
+ this.getOid()
+ "."
+ this.getInstance()
+ " ds_max: "
+ this.getMax()
+ " ds_min: "
+ this.getMin());
}
}
/**
* This method is used to assign the object's identifier.
*
* @param oid -
* object identifier in dotted decimal notation (e.g.,
* ".1.3.6.1.2.1.1.1")
*/
public void setOid(String oid) {
m_oid = oid;
}
/**
* This method is used to assign the object's instance id.
*
* @param instance -
* instance identifier (to be appended to oid)
*/
public void setInstance(String instance) {
m_instance = instance;
}
/**
* This method is used to assign the data source name.
*
* @param name a {@link java.lang.String} object.
*/
public void setName(String name) {
m_name = name;
}
/**
* Returns the object's identifier.
*
* @return The object's identifier string.
*/
public String getOid() {
return m_oid;
}
/**
* Returns the object's instance id.
*
* @return The object's instance id string.
*/
public String getInstance() {
return m_instance;
}
/**
* Returns the object's name.
*
* @return The object's name.
*/
public String getName() {
return m_name;
}
/**
* Class copy constructor. Constructs a new object that is an identical to
* the passed object, however no data is shared between the two objects. Any
* changes to one will not affect the other.
*
* @param second
* The object to make a duplicate of.
*/
public JMXDataSource(JMXDataSource second) {
m_oid = second.m_oid;
m_instance = second.m_instance;
m_name = second.m_name;
m_type = second.m_type;
m_heartbeat = second.m_heartbeat;
m_min = second.m_min;
m_max = second.m_max;
}
/**
* This method is used to assign the object's expected data type.
*
* @param type -
* object's data type
*/
public void setType(String type) {
m_type = type;
}
/**
* <p>setHeartbeat</p>
*
* @param heartbeat a int.
*/
public void setHeartbeat(int heartbeat) {
m_heartbeat = heartbeat;
}
/**
* <p>setMin</p>
*
* @param minimum a {@link java.lang.String} object.
*/
public void setMin(String minimum) {
m_min = minimum;
}
/**
* <p>setMax</p>
*
* @param maximum a {@link java.lang.String} object.
*/
public void setMax(String maximum) {
m_max = maximum;
}
/**
* Returns the object's data type.
*
* @return The object's data type
*/
public String getType() {
return m_type;
}
/**
* <p>getHeartbeat</p>
*
* @return a int.
*/
public int getHeartbeat() {
return m_heartbeat;
}
/**
* <p>getMin</p>
*
* @return a {@link java.lang.String} object.
*/
public String getMin() {
return m_min;
}
/**
* <p>getMax</p>
*
* @return a {@link java.lang.String} object.
*/
public String getMax() {
return m_max;
}
/**
* {@inheritDoc}
*
* Used to get a duplicate of self. The duplicate is identical to self but
* shares no common data.
*/
@Override
public Object clone() {
return new JMXDataSource(this);
}
/**
* This method is responsible for returning a String object which represents
* the content of this RRDDataSource object. Primarily used for debugging
* purposes.
*
* @return String which represents the content of this RRDDataSource object
*/
public String toString() {
StringBuffer buffer = new StringBuffer();
// Build the buffer
buffer.append("\n oid: ").append(m_oid);
buffer.append("\n name: ").append(m_name);
buffer.append("\n type: ").append(m_type);
buffer.append("\n heartbeat: ").append(m_heartbeat);
buffer.append("\n min: ").append(m_min);
buffer.append("\n max: ").append(m_max);
return buffer.toString();
}
/**
* <p>performUpdate</p>
*
* @param owner a {@link java.lang.String} object.
* @param repository a {@link java.io.File} object.
* @param value a {@link org.opennms.netmgt.snmp.SnmpValue} object.
* @return a boolean.
*/
public boolean performUpdate(
String owner,
File repository,
SnmpValue value) {
String val = getStorableValue(value);
String collectionName = m_collectionName;
int step = DataCollectionConfigFactory.getInstance().getStep(collectionName);
List<String> rraList = DataCollectionConfigFactory.getInstance().getRRAList(collectionName);
boolean result=false;
try {
RrdUtils.createRRD(owner, repository.getAbsolutePath(), getName(), step, getType(), getHeartbeat(), getMin(), getMax(), rraList);
RrdUtils.updateRRD(owner, repository.getAbsolutePath(), getName(), val);
} catch (RrdException e) {
result=true;
}
return result;
}
/**
* <p>getStorableValue</p>
*
* @param snmpVal a {@link org.opennms.netmgt.snmp.SnmpValue} object.
* @return a {@link java.lang.String} object.
*/
public String getStorableValue(SnmpValue snmpVal) {
return (snmpVal == null ? null : Long.toString(snmpVal.toLong()));
}
}