📄 dataprocessor.java
字号:
/* ============================================================
* JRobin : Pure java implementation of RRDTool's functionality
* ============================================================
*
* Project Info: http://www.jrobin.org
* Project Lead: Sasa Markovic (saxon@jrobin.org);
*
* (C) Copyright 2003-2005, by Sasa Markovic.
*
* Developers: Sasa Markovic (saxon@jrobin.org)
*
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
package org.jrobin.data;
import org.jrobin.core.*;
import java.io.IOException;
import java.util.*;
/**
* Class which should be used for all calculations based on the data fetched from RRD files. This class
* supports ordinary DEF datasources (defined in RRD files), CDEF datasources (RPN expressions evaluation),
* SDEF (static datasources - extension of JRobin) and PDEF (plottables, see
* {@link Plottable Plottable} for more information.<p>
* <p/>
* Typical class usage:<p>
* <pre>
* final long t1 = ...
* final long t2 = ...
* DataProcessor dp = new DataProcessor(t1, t2);
* // DEF datasource
* dp.addDatasource("x", "demo.rrd", "some_source", "AVERAGE");
* // DEF datasource
* dp.addDatasource("y", "demo.rrd", "some_other_source", "AVERAGE");
* // CDEF datasource, z = (x + y) / 2
* dp.addDatasource("z", "x,y,+,2,/");
* // ACTION!
* dp.processData();
* // Dump calculated values
* System.out.println(dp.dump());
* </pre>
*/
public class DataProcessor implements ConsolFuns {
/**
* Constant representing the default number of pixels on a JRobin graph (will be used if
* no other value is specified with {@link #setStep(long) setStep()} method.
*/
public static final int DEFAULT_PIXEL_COUNT = 600;
private static final double DEFAULT_PERCENTILE = 95.0; // %
private int pixelCount = DEFAULT_PIXEL_COUNT;
/**
* Constant that defines the default {@link RrdDbPool} usage policy. Defaults to <code>false</code>
* (i.e. the pool will not be used to fetch data from RRD files)
*/
public static final boolean DEFAULT_POOL_USAGE_POLICY = false;
private boolean poolUsed = DEFAULT_POOL_USAGE_POLICY;
private final long tStart;
private long tEnd, timestamps[];
private long lastRrdArchiveUpdateTime = 0;
// this will be adjusted later
private long step = 0;
// resolution to be used for RRD fetch operation
private long fetchRequestResolution = 1;
// the order is important, ordinary HashMap is unordered
private Map<String, Source> sources = new LinkedHashMap<String, Source>();
private Def[] defSources;
/**
* Creates new DataProcessor object for the given time span. Ending timestamp may be set to zero.
* In that case, the class will try to find the optimal ending timestamp based on the last update time of
* RRD files processed with the {@link #processData()} method.
*
* @param t1 Starting timestamp in seconds without milliseconds
* @param t2 Ending timestamp in seconds without milliseconds
* @throws RrdException Thrown if invalid timestamps are supplied
*/
public DataProcessor(long t1, long t2) throws RrdException {
if ((t1 < t2 && t1 > 0 && t2 > 0) || (t1 > 0 && t2 == 0)) {
this.tStart = t1;
this.tEnd = t2;
}
else {
throw new RrdException("Invalid timestamps specified: " + t1 + ", " + t2);
}
}
/**
* Creates new DataProcessor object for the given time span. Ending date may be set to null.
* In that case, the class will try to find optimal ending date based on the last update time of
* RRD files processed with the {@link #processData()} method.
*
* @param d1 Starting date
* @param d2 Ending date
* @throws RrdException Thrown if invalid timestamps are supplied
*/
public DataProcessor(Date d1, Date d2) throws RrdException {
this(Util.getTimestamp(d1), d2 != null ? Util.getTimestamp(d2) : 0);
}
/**
* Creates new DataProcessor object for the given time span. Ending date may be set to null.
* In that case, the class will try to find optimal ending date based on the last update time of
* RRD files processed with the {@link #processData()} method.
*
* @param gc1 Starting Calendar date
* @param gc2 Ending Calendar date
* @throws RrdException Thrown if invalid timestamps are supplied
*/
public DataProcessor(Calendar gc1, Calendar gc2) throws RrdException {
this(Util.getTimestamp(gc1), gc2 != null ? Util.getTimestamp(gc2) : 0);
}
/**
* Returns boolean value representing {@link org.jrobin.core.RrdDbPool RrdDbPool} usage policy.
*
* @return true, if the pool will be used internally to fetch data from RRD files, false otherwise.
*/
public boolean isPoolUsed() {
return poolUsed;
}
/**
* Sets the {@link org.jrobin.core.RrdDbPool RrdDbPool} usage policy.
*
* @param poolUsed true, if the pool should be used to fetch data from RRD files, false otherwise.
*/
public void setPoolUsed(boolean poolUsed) {
this.poolUsed = poolUsed;
}
/**
* Sets the number of pixels (target graph width). This number is used only to calculate pixel coordinates
* for JRobin graphs (methods {@link #getValuesPerPixel(String)} and {@link #getTimestampsPerPixel()}),
* but has influence neither on datasource values calculated with the
* {@link #processData()} method nor on aggregated values returned from {@link #getAggregates(String)}
* and similar methods. In other words, aggregated values will not change once you decide to change
* the dimension of your graph.<p>
* <p/>
* The default number of pixels is defined by constant {@link #DEFAULT_PIXEL_COUNT}
* and can be changed with a {@link #setPixelCount(int)} method.
*
* @param pixelCount The number of pixels. If you process RRD data in order to display it on the graph,
* this should be the width of your graph.
*/
public void setPixelCount(int pixelCount) {
this.pixelCount = pixelCount;
}
/**
* Returns the number of pixels (target graph width). See {@link #setPixelCount(int)} for more information.
*
* @return Target graph width
*/
public int getPixelCount() {
return pixelCount;
}
/**
* Roughly corresponds to the --step option in RRDTool's graph/xport commands. Here is an explanation borrowed
* from RRDTool:<p>
* <p/>
* <i>"By default rrdgraph calculates the width of one pixel in the time
* domain and tries to get data at that resolution from the RRD. With
* this switch you can override this behavior. If you want rrdgraph to
* get data at 1 hour resolution from the RRD, then you can set the
* step to 3600 seconds. Note, that a step smaller than 1 pixel will
* be silently ignored."</i><p>
* <p/>
* I think this option is not that useful, but it's here just for compatibility.<p>
*
* @param step Time step at which data should be fetched from RRD files. If this method is not used,
* the step will be equal to the smallest RRD step of all processed RRD files. If no RRD file is processed,
* the step will be roughly equal to the with of one graph pixel (in seconds).
*/
public void setStep(long step) {
this.step = step;
}
/**
* Returns the time step used for data processing. Initially, this method returns zero.
* Once {@link #processData()} is finished, the method will return the real value used for
* all internal computations. Roughly corresponds to the --step option in RRDTool's graph/xport commands.
*
* @return Step used for data processing.
*/
public long getStep() {
return step;
}
/**
* Returns desired RRD archive step (reslution) in seconds to be used while fetching data
* from RRD files. In other words, this value will used as the last parameter of
* {@link RrdDb#createFetchRequest(String, long, long, long) RrdDb.createFetchRequest()} method
* when this method is called internally by this DataProcessor.
*
* @return Desired archive step (fetch resolution) in seconds.
*/
public long getFetchRequestResolution() {
return fetchRequestResolution;
}
/**
* Sets desired RRD archive step in seconds to be used internally while fetching data
* from RRD files. In other words, this value will used as the last parameter of
* {@link RrdDb#createFetchRequest(String, long, long, long) RrdDb.createFetchRequest()} method
* when this method is called internally by this DataProcessor. If this method is never called, fetch
* request resolution defaults to 1 (smallest possible archive step will be chosen automatically).
*
* @param fetchRequestResolution Desired archive step (fetch resoltuion) in seconds.
*/
public void setFetchRequestResolution(long fetchRequestResolution) {
this.fetchRequestResolution = fetchRequestResolution;
}
/**
* Returns ending timestamp. Basically, this value is equal to the ending timestamp
* specified in the constructor. However, if the ending timestamps was zero, it
* will be replaced with the real timestamp when the {@link #processData()} method returns. The real
* value will be calculated from the last update times of processed RRD files.
*
* @return Ending timestamp in seconds
*/
public long getEndingTimestamp() {
return tEnd;
}
/**
* Returns consolidated timestamps created with the {@link #processData()} method.
*
* @return array of timestamps in seconds
* @throws RrdException thrown if timestamps are not calculated yet
*/
public long[] getTimestamps() throws RrdException {
if (timestamps == null) {
throw new RrdException("Timestamps not calculated yet");
}
else {
return timestamps;
}
}
/**
* Returns calculated values for a single datasource. Corresponding timestamps can be obtained from
* the {@link #getTimestamps()} method.
*
* @param sourceName Datasource name
* @return an array of datasource values
* @throws RrdException Thrown if invalid datasource name is specified,
* or if datasource values are not yet calculated (method {@link #processData()}
* was not called)
*/
public double[] getValues(String sourceName) throws RrdException {
Source source = getSource(sourceName);
double[] values = source.getValues();
if (values == null) {
throw new RrdException("Values not available for source [" + sourceName + "]");
}
return values;
}
/**
* Returns single aggregated value for a single datasource.
*
* @param sourceName Datasource name
* @param consolFun Consolidation function to be applied to fetched datasource values.
* Valid consolidation functions are MIN, MAX, LAST, FIRST, AVERAGE and TOTAL
* (these string constants are conveniently defined in the {@link ConsolFuns} class)
* @return MIN, MAX, LAST, FIRST, AVERAGE or TOTAL value calculated from the data
* for the given datasource name
* @throws RrdException Thrown if invalid datasource name is specified,
* or if datasource values are not yet calculated (method {@link #processData()}
* was not called)
*/
public double getAggregate(String sourceName, String consolFun) throws RrdException {
Source source = getSource(sourceName);
return source.getAggregates(tStart, tEnd).getAggregate(consolFun);
}
/**
* Returns all (MIN, MAX, LAST, FIRST, AVERAGE and TOTAL) aggregated values for a single datasource.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -