You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(11) |
Oct
(60) |
Nov
(68) |
Dec
(10) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(10) |
Feb
(15) |
Mar
(30) |
Apr
(20) |
May
(32) |
Jun
(30) |
Jul
(61) |
Aug
(13) |
Sep
(14) |
Oct
(13) |
Nov
(28) |
Dec
(10) |
2005 |
Jan
(7) |
Feb
(5) |
Mar
|
Apr
(2) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(4) |
Oct
|
Nov
|
Dec
|
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(15) |
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(20) |
Aug
(35) |
Sep
(3) |
Oct
(2) |
Nov
|
Dec
|
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(14) |
Sep
(2) |
Oct
|
Nov
|
Dec
|
2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(3) |
2011 |
Jan
|
Feb
|
Mar
|
Apr
(5) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Sasa M. <sa...@us...> - 2004-12-08 14:02:49
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23351/org/jrobin/data Modified Files: DataProcessor.java Source.java Log Message: Implemented 95th percentile for datasource values (see get95Percentile method in the DataAnalyzer class). Minor changes in the core package. Index: Source.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/Source.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Source.java 25 Nov 2004 12:14:54 -0000 1.1 --- Source.java 8 Dec 2004 14:02:37 -0000 1.2 *************** *** 30,33 **** --- 30,35 ---- import org.jrobin.core.Util; + import java.util.Arrays; + abstract class Source implements ConsolFuns { final private String name; *************** *** 78,81 **** --- 80,118 ---- } + final double getPercentile(int percentile) throws RrdException { + if(values == null) { + throw new RrdException("Could not calculate 95th percentile for datasource [" + + name + "], datasource values are still not available"); + } + if(percentile > 100 || percentile <= 0) { + throw new RrdException("Invalid percentile specified: " + percentile); + } + return getPercentile(values, percentile); + } + + private static double getPercentile(double[] values, int percentile) { + int count = values.length; + double[] valuesCopy = new double[count]; + for(int i = 0; i < count; i++) { + valuesCopy[i] = values[i]; + } + Arrays.sort(valuesCopy); + // NaN values are at the end, eliminate them from consideration + while(count > 0 && Double.isNaN(valuesCopy[count - 1])) { + count--; + } + // skip top [percentile]% values + int skipCount = (int) Math.ceil(((100 - percentile) * count) / 100.0); + count -= skipCount; + // if we have anything left... + if(count > 0) { + return valuesCopy[count - 1]; + } + else { + // not enough data available + return Double.NaN; + } + } + private double getTotal(double secondsPerPixel) { double sum = 0; *************** *** 115,118 **** return min; } - } --- 152,154 ---- Index: DataProcessor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/DataProcessor.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** DataProcessor.java 26 Nov 2004 13:47:51 -0000 1.3 --- DataProcessor.java 8 Dec 2004 14:02:37 -0000 1.4 *************** *** 240,243 **** --- 240,263 ---- /** + * Used by ISPs which charge for bandwidth utilization on a "95th percentile" basis.<p> + * + * The 95th percentile is the highest source value left when the top 5% of a numerically sorted set + * of source data is discarded. It is used as a measure of the peak value used when one discounts + * a fair amount for transitory spikes. This makes it markedly different from the average.<p> + * + * Read more about this topic at + * <a href="http://www.red.net/support/resourcecentre/leasedline/percentile.php">Rednet</a> or + * <a href="http://www.bytemark.co.uk/support/tech/95thpercentile.html">Bytemark</a>. + * + * @param sourceName Datasource name + * @return 95th percentile of fetched source values + * @throws RrdException Thrown if invalid source name is supplied + */ + public double get95Percentile(String sourceName) throws RrdException { + Source source = getSource(sourceName); + return source.getPercentile(95); + } + + /** * Returns array of datasource names defined in this DataProcessor. * @return array of datasource names |
From: Sasa M. <sa...@us...> - 2004-12-08 14:02:45
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23351/org/jrobin/core Modified Files: RrdDb.java Log Message: Implemented 95th percentile for datasource values (see get95Percentile method in the DataAnalyzer class). Minor changes in the core package. Index: RrdDb.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDb.java,v retrieving revision 1.34 retrieving revision 1.35 diff -C2 -d -r1.34 -r1.35 *** RrdDb.java 19 Nov 2004 12:00:01 -0000 1.34 --- RrdDb.java 8 Dec 2004 14:02:36 -0000 1.35 *************** *** 556,572 **** } backend.beforeUpdate(); ! long newTime = sample.getTime(); ! long lastTime = header.getLastUpdateTime(); ! if(lastTime >= newTime) { ! throw new RrdException("Bad sample timestamp " + newTime + ! ". Last update time was " + lastTime + ", at least one second step is required"); } ! double[] newValues = sample.getValues(); ! for(int i = 0; i < datasources.length; i++) { ! double newValue = newValues[i]; ! datasources[i].process(newTime, newValue); } - header.setLastUpdateTime(newTime); - backend.afterUpdate(); } --- 556,576 ---- } backend.beforeUpdate(); ! try { ! long newTime = sample.getTime(); ! long lastTime = header.getLastUpdateTime(); ! if(lastTime >= newTime) { ! throw new RrdException("Bad sample timestamp " + newTime + ! ". Last update time was " + lastTime + ", at least one second step is required"); ! } ! double[] newValues = sample.getValues(); ! for(int i = 0; i < datasources.length; i++) { ! double newValue = newValues[i]; ! datasources[i].process(newTime, newValue); ! } ! header.setLastUpdateTime(newTime); } ! finally { ! backend.afterUpdate(); } } *************** *** 587,594 **** } backend.beforeFetch(); ! Archive archive = findMatchingArchive(request); ! FetchData fetchData = archive.fetchData(request); ! backend.afterFetch(); ! return fetchData; } --- 591,602 ---- } backend.beforeFetch(); ! try { ! Archive archive = findMatchingArchive(request); ! FetchData fetchData = archive.fetchData(request); ! return fetchData; ! } ! finally { ! backend.afterFetch(); ! } } |
From: Sasa M. <sa...@us...> - 2004-11-26 13:48:02
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18474/org/jrobin/data Modified Files: DataProcessor.java Def.java Log Message: Ending timestamp passed to the constructor can be equal to zero. It will be adjusted properly once data is fetched from RRD files. Index: DataProcessor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/DataProcessor.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** DataProcessor.java 25 Nov 2004 14:26:06 -0000 1.2 --- DataProcessor.java 26 Nov 2004 13:47:51 -0000 1.3 *************** *** 63,99 **** private int pixelCount = DEFAUL_PIXEL_COUNT; private int pixelsPerStep = 1; private boolean poolUsed = false; ! final private long tStart, tEnd; private double[] timestamps; private Map sources = new LinkedHashMap(); /** ! * Creates new DataProcessor object for the given time span. * @param t1 Starting timestamp in seconds without milliseconds * @param t2 Ending timestamp in seconds without milliseconds */ ! public DataProcessor(long t1, long t2) { ! assert t1 < t2: "Invalid time span while constructing DataAnalyzer"; ! this.tStart = t1; ! this.tEnd = t2; ! createTimestamps(); } /** ! * Creates new DataProcessor object for the given time span. * @param d1 Starting date * @param d2 Ending date */ ! public DataProcessor(Date d1, Date d2) { this(Util.getTimestamp(d1), Util.getTimestamp(d2)); } /** ! * Creates new DataProcessor object for the given time span. * @param gc1 Starting Gregorian calendar date * @param gc2 Ending Gregorian calendar date */ ! public DataProcessor(GregorianCalendar gc1, GregorianCalendar gc2) { this(Util.getTimestamp(gc1), Util.getTimestamp(gc2)); } --- 63,117 ---- private int pixelCount = DEFAUL_PIXEL_COUNT; private int pixelsPerStep = 1; + private long customStep = 0; private boolean poolUsed = false; ! final private long tStart; ! private long tEnd; private double[] timestamps; + // the order is important, ordinary HashMap is unordered private Map sources = new LinkedHashMap(); /** ! * 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 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 timestamp may be set to zero. ! * In that case, the class will try to find optimal ending timestamp 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), Util.getTimestamp(d2)); } /** ! * 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 optimal ending timestamp based on the last update time of ! * RRD files processed with the {@link #processData()} method. ! * * @param gc1 Starting Gregorian calendar date * @param gc2 Ending Gregorian calendar date + * @throws RrdException Thrown if invalid timestamps are supplied */ ! public DataProcessor(GregorianCalendar gc1, GregorianCalendar gc2) throws RrdException { this(Util.getTimestamp(gc1), Util.getTimestamp(gc2)); } *************** *** 103,114 **** ///////////////////////////////////////////////////////////////// - private void createTimestamps() { - timestamps = new double[pixelCount]; - final double span = tEnd - tStart; - for(int i = 0; i < pixelCount; i++) { - timestamps[i] = tStart + ((double) i / (double)(pixelCount - 1)) * span; - } - } - /** * Returns boolean value representing {@link org.jrobin.core.RrdDbPool RrdDbPool} usage policy. --- 121,124 ---- *************** *** 147,151 **** public void setPixelCount(int pixelCount) { this.pixelCount = pixelCount; - createTimestamps(); } --- 157,160 ---- *************** *** 166,175 **** */ public void setStep(long step) { ! double secondsPerPixel = getSecondsPerPixel(); ! pixelsPerStep = Math.max((int) Math.ceil(step / secondsPerPixel), 1); } ! private double getSecondsPerPixel() { ! return (double) (tEnd - tStart) / (double) (pixelCount - 1); } --- 175,190 ---- */ public void setStep(long step) { ! this.customStep = step; } ! /** ! * Returns ending timestamp. Basically, this value is equal to the ending timestamp ! * specified in the constructor. However, if it was set to zero in the constructor, 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; } *************** *** 180,185 **** * number of pixels. */ ! public double[] getTimestamps() { ! return timestamps; } --- 195,205 ---- * number of pixels. */ ! public double[] getTimestamps() throws RrdException { ! if(timestamps == null) { ! throw new RrdException("Timestamps not calculated yet"); ! } ! else { ! return timestamps; ! } } *************** *** 405,408 **** --- 425,437 ---- private void calculateDefs() throws IOException, RrdException { Def[] defs = getDefs(); + fetchRrdData(defs); + createTimestamps(defs); + for(int i = 0; i < defs.length; i++) { + normalizeRrdValues(defs[i]); + } + } + + private void fetchRrdData(Def[] defs) throws IOException, RrdException { + long tEndFixed = (tEnd == 0)? Util.getTime(): tEnd; for (int i = 0; i < defs.length; i++) { if (defs[i].getValues() == null) { *************** *** 420,434 **** try { rrd = getRrd(defs[i]); ! FetchRequest req = rrd.createFetchRequest(defs[i].getConsolFun(), tStart, tEnd); req.setFilter(dsNames); FetchData data = req.fetchData(); ! //System.out.println(data.getAggregate(defs[i].getDsName(), "AVERAGE")); ! double[] values = data.getValues(defs[i].getDsName()); ! normalizeDefValues(data.getTimestamps(), values, defs[i]); for (int j = i + 1; j < defs.length; j++) { if (defs[i].isCompatibleWith(defs[j])) { ! //System.out.println(data.getAggregate(defs[j].getDsName(), "AVERAGE")); ! values = data.getValues(defs[j].getDsName()); ! normalizeDefValues(data.getTimestamps(), values, defs[j]); } } --- 449,459 ---- try { rrd = getRrd(defs[i]); ! FetchRequest req = rrd.createFetchRequest(defs[i].getConsolFun(), tStart, tEndFixed); req.setFilter(dsNames); FetchData data = req.fetchData(); ! defs[i].setFetchData(data); for (int j = i + 1; j < defs.length; j++) { if (defs[i].isCompatibleWith(defs[j])) { ! defs[j].setFetchData(data); } } *************** *** 443,457 **** } ! private void normalizeDefValues(long[] dsTimestamps, double[] dsValues, Def def) { double[] values = new double[pixelCount]; int dsSegment = 1, accumPixels = 0; ! values[0] = (tStart == dsTimestamps[0])? dsValues[0]: dsValues[1]; double totalValue = 0D, totalTime = 0D; for(int pixel = 1; pixel < pixelCount; pixel++) { double t0 = timestamps[pixel - 1], t1 = timestamps[pixel]; while(t0 < t1) { ! double tLimit = Math.min(dsTimestamps[dsSegment], t1); double dt = tLimit - t0; ! double val = dsValues[dsSegment]; if(!Double.isNaN(val)) { totalValue += val * dt; --- 468,505 ---- } ! private void createTimestamps(Def[] defs) throws RrdException, IOException { ! // Fix zero ending timestamp if necessary ! if(tEnd == 0) { ! if(defs.length == 0) { ! throw new RrdException("Could not adjust zero ending timestamp, no DEF source provided"); ! } ! tEnd = defs[0].getEndingFetchTimestamp(); ! for(int i = 1; i < defs.length; i++) { ! tEnd = Math.min(tEnd, defs[i].getEndingFetchTimestamp()); ! } ! } ! // create timestamps ! timestamps = new double[pixelCount]; ! double span = tEnd - tStart; ! for(int i = 0; i < pixelCount; i++) { ! timestamps[i] = tStart + ((double) i / (double)(pixelCount - 1)) * span; ! } ! // determine pixelsPerStep ! pixelsPerStep = Math.max((int) Math.ceil(customStep / getSecondsPerPixel()), 1); ! } ! ! private void normalizeRrdValues(Def def) throws RrdException { ! long[] rrdTimestamps = def.getRrdTimestamps(); ! double[] rrdValues = def.getRrdValues(); double[] values = new double[pixelCount]; int dsSegment = 1, accumPixels = 0; ! values[0] = (tStart == rrdTimestamps[0])? rrdValues[0]: rrdValues[1]; double totalValue = 0D, totalTime = 0D; for(int pixel = 1; pixel < pixelCount; pixel++) { double t0 = timestamps[pixel - 1], t1 = timestamps[pixel]; while(t0 < t1) { ! double tLimit = Math.min(rrdTimestamps[dsSegment], t1); double dt = tLimit - t0; ! double val = rrdValues[dsSegment]; if(!Double.isNaN(val)) { totalValue += val * dt; *************** *** 459,463 **** } t0 = tLimit; ! if(t0 == dsTimestamps[dsSegment]) { dsSegment++; } --- 507,511 ---- } t0 = tLimit; ! if(t0 == rrdTimestamps[dsSegment]) { dsSegment++; } *************** *** 572,575 **** --- 620,632 ---- ///////////////////////////////////////////////////////////////// + private double getSecondsPerPixel() throws RrdException { + double secondsPerPixel = (double) (tEnd - tStart) / (double) (pixelCount - 1); + if(secondsPerPixel < 1.0) { + throw new RrdException("Time span [" + tStart + "," + tEnd + "] too narrow. " + + "The time span (in seconds) sohuld be greater than number of pixels [" + pixelCount + "]"); + } + return secondsPerPixel; + } + /** * Dumps timestamps and values of all datasources in a tabelar form. Very useful for debugging. *************** *** 605,629 **** return b.toString(); } ! /* public static void main(String[] args) throws IOException, RrdException { ! final long t1 = Util.getTimestamp(2003, 4, 1); ! final long t2 = Util.getTimestamp(2003, 5, 1); ! DataProcessor dp = new DataProcessor(t1, t2); // DEF datasource ! dp.addDatasource("x", "demo.rrd", "sun", "AVERAGE"); // DEF datasource ! dp.addDatasource("y", "demo.rrd", "shade", "AVERAGE"); // CDEF datasource ! dp.addDatasource("z", "x,y,+,2,/"); // SDEF datasource ! dp.addDatasource("w", "z", "AVERAGE"); // CDEF datasource ! dp.addDatasource("wz", "w,z,-"); // SDEF datasource, values should be close to zero ! dp.addDatasource("wzavg", "wz", "AVERAGE"); // action! dp.processData(); System.out.println(dp.dump()); } - //*/ } --- 662,694 ---- return b.toString(); } ! ! /** ! * Cute little demo. Uses demo.rrd file previously created by basic JRobin demo. ! * @param args ! * @throws IOException ! * @throws RrdException ! */ public static void main(String[] args) throws IOException, RrdException { ! long t1 = Util.getTimestamp(2003, 4, 1); ! String rrdPath = Util.getJRobinDemoPath("demo.rrd"); ! DataProcessor dp = new DataProcessor(t1, 0); ! //dp.setStep(2 * 86400); // DEF datasource ! dp.addDatasource("X", rrdPath, "sun", "AVERAGE"); // DEF datasource ! dp.addDatasource("Y", rrdPath, "shade", "AVERAGE"); // CDEF datasource ! dp.addDatasource("Z", "X,Y,+,2,/"); // SDEF datasource ! dp.addDatasource("AVG", "Z", "AVERAGE"); // CDEF datasource ! dp.addDatasource("DELTA", "Z,AVG,-"); // SDEF datasource, values should be close to zero ! dp.addDatasource("ALMOST ZERO", "DELTA", "AVERAGE"); // action! dp.processData(); + Date endingDate = new Date(dp.getEndingTimestamp() * 1000L); + System.out.println("Ending timestamp used: " + dp.getEndingTimestamp() + " (" + endingDate + ")\n"); System.out.println(dp.dump()); } } Index: Def.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/Def.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Def.java 25 Nov 2004 12:14:54 -0000 1.1 --- Def.java 26 Nov 2004 13:47:51 -0000 1.2 *************** *** 27,34 **** --- 27,39 ---- import org.jrobin.core.Util; + import org.jrobin.core.FetchData; + import org.jrobin.core.RrdException; + import java.io.IOException; class Def extends Source { private String path, dsName, consolFun, backend; + private FetchData fetchData; + private long endingFetchTimestamp; Def(String name, String path, String dsName, String consolFunc) { *************** *** 70,72 **** --- 75,94 ---- (backend != null && def.backend != null && backend.equals(def.backend))); } + + void setFetchData(FetchData fetchData) throws IOException { + this.fetchData = fetchData; + this.endingFetchTimestamp = fetchData.getMatchingArchive().getEndTime(); + } + + long[] getRrdTimestamps() { + return fetchData.getTimestamps(); + } + + double[] getRrdValues() throws RrdException { + return fetchData.getValues(dsName); + } + + long getEndingFetchTimestamp() throws IOException { + return endingFetchTimestamp; + } } |
From: Sasa M. <sa...@us...> - 2004-11-25 14:26:16
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6658/org/jrobin/data Modified Files: DataProcessor.java Log Message: Fixed javadoc for org.java.data.DataProcessor class. Index: DataProcessor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/DataProcessor.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** DataProcessor.java 25 Nov 2004 12:14:54 -0000 1.1 --- DataProcessor.java 25 Nov 2004 14:26:06 -0000 1.2 *************** *** 32,36 **** --- 32,62 ---- import java.io.IOException; + /** + * 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 org.jrobin.graph.Plottable Plottable} for more information.<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", "sun", "AVERAGE"); + * // DEF datasource + * dp.addDatasource("y", "demo.rrd", "shade", "AVERAGE"); + * // CDEF datasource, z = (x + y) / 2 + * dp.addDatasource("z", "x,y,+,2,/"); + * // ACTION! + * dp.processData(); + * System.out.println(dp.dump()); + * </pre> + */ public class DataProcessor implements ConsolFuns { + /** + * Constant used to determine the time step used in internal calculations. Note that AVERAGEs and TOTALs + * calculated for the data in RRD files are not affected with this value. + */ public static final int DEFAUL_PIXEL_COUNT = 400; *************** *** 43,53 **** private Map sources = new LinkedHashMap(); ! public DataProcessor(long tStart, long tEnd) { ! assert tStart < tEnd: "Invalid time span while constructing DataAnalyzer"; ! this.tStart = tStart; ! this.tEnd = tEnd; createTimestamps(); } ///////////////////////////////////////////////////////////////// // BASIC FUNCTIONS --- 69,102 ---- private Map sources = new LinkedHashMap(); ! /** ! * Creates new DataProcessor object for the given time span. ! * @param t1 Starting timestamp in seconds without milliseconds ! * @param t2 Ending timestamp in seconds without milliseconds ! */ ! public DataProcessor(long t1, long t2) { ! assert t1 < t2: "Invalid time span while constructing DataAnalyzer"; ! this.tStart = t1; ! this.tEnd = t2; createTimestamps(); } + /** + * Creates new DataProcessor object for the given time span. + * @param d1 Starting date + * @param d2 Ending date + */ + public DataProcessor(Date d1, Date d2) { + this(Util.getTimestamp(d1), Util.getTimestamp(d2)); + } + + /** + * Creates new DataProcessor object for the given time span. + * @param gc1 Starting Gregorian calendar date + * @param gc2 Ending Gregorian calendar date + */ + public DataProcessor(GregorianCalendar gc1, GregorianCalendar gc2) { + this(Util.getTimestamp(gc1), Util.getTimestamp(gc2)); + } + ///////////////////////////////////////////////////////////////// // BASIC FUNCTIONS *************** *** 62,77 **** --- 111,148 ---- } + /** + * Returns boolean value representing {@link org.jrobin.core.RrdDbPool RrdDbPool} usage policy. + * @return true, if the pool will be used 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; } + /** + * Returns the number of pixels (which is used to determine the length of time step + * used in internal calculations) + * @return Number of pixels (time steps) + */ public int getPixelCount() { return pixelCount; } + /** + * Sets the number of pixels. This number will be used to determine the length of time step + * used in internal calculations. You can freely change this value but, at the same time, + * you can be sure that AVERAGE and TOTAL values calculated for datasources in RRD files will not change. + * The default number of pixels is defined by {@link #DEFAUL_PIXEL_COUNT}. + * + * @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; *************** *** 79,82 **** --- 150,168 ---- } + /** + * Roughly corresponds to the --step option in RRDTool's graph/xport commands. Here is an explanation borrowed + * from RRDTool:<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> + * + * 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. + */ public void setStep(long step) { double secondsPerPixel = getSecondsPerPixel(); *************** *** 88,95 **** --- 174,196 ---- } + /** + * Returns timestamps for all pixels. + * @return array of timestamps in seconds - to preserve maximum precision, + * this values are not rounded to the nearest second. The length of this array is equal to the + * number of pixels. + */ public double[] getTimestamps() { 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 doubles. The length of this array is equal to the + * number of pixels. + * @throws RrdException Thrown if invalid datasource name is specified, + * or if datasource values are not yet calculated + */ public double[] getValues(String sourceName) throws RrdException { Source source = getSource(sourceName); *************** *** 101,104 **** --- 202,217 ---- } + /** + * Returns 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 + */ public double getAggregate(String sourceName, String consolFun) throws RrdException { Source source = getSource(sourceName); *************** *** 106,113 **** --- 219,249 ---- } + /** + * Returns array of datasource names defined in this DataProcessor. + * @return array of datasource names + */ public String[] getSourceNames() { return (String[]) sources.keySet().toArray(new String[0]); } + /** + * Returns an array of all datasource values for all datasources. Each row in this two-dimensional + * array represents an array of calculated values for a single datasource. The order of rows is the same + * as the order in which datasources were added to this DataProcessor object. + * @return All datasource values for all datasources. The first index describes is the index of the datasource, + * the second index is the index of the datasource value. In other words, the dimension of this array is + * <code>numberOfDatasources x number of pixels</code> + * @throws RrdException Thrown if invalid datasource name is specified, + * or if datasource values are not yet calculated + */ + public double[][] getValues() throws RrdException { + String[] names = getSourceNames(); + double[][] values = new double[names.length][]; + for(int i = 0; i < names.length; i++) { + values[i] = getValues(names[i]); + } + return values; + } + private Source getSource(String sourceName) throws RrdException { Object source = sources.get(sourceName); *************** *** 122,125 **** --- 258,269 ---- ///////////////////////////////////////////////////////////////// + /** + * <p>Adds a custom, {@link org.jrobin.graph.Plottable plottable} datasource (<b>PDEF</b>). + * The datapoints should be made available by a class extending + * {@link org.jrobin.graph.Plottable Plottable} class.</p> + * + * @param name source name. + * @param plottable class that extends Plottable class and is suited for graphing. + */ public void addDatasource(String name, Plottable plottable) { PDef pDef = new PDef(name, plottable); *************** *** 127,130 **** --- 271,283 ---- } + /** + * <p>Adds a custom source (<b>PDEF</b>). + * The datapoints should be made available by a class extending + * {@link org.jrobin.graph.Plottable Plottable}.</p> + * + * @param name Source name. + * @param plottable Class that extends Plottable class and is suited for graphing. + * @param index Integer referring to the datasource in the Plottable class. + */ public void addDatasource(String name, Plottable plottable, int index) { PDef pDef = new PDef(name, plottable, index); *************** *** 132,135 **** --- 285,297 ---- } + /** + * <p>Adds a custom source (<b>PDEF</b>). + * The datapoints should be made available by a class extending + * {@link org.jrobin.graph.Plottable Plottable}.</p> + * + * @param name Source name. + * @param plottable Class that extends Plottable class and is suited for graphing. + * @param sourceName String name referring to the datasource in the Plottable class. + */ public void addDatasource(String name, Plottable plottable, String sourceName) { PDef pDef = new PDef(name, plottable, sourceName); *************** *** 137,140 **** --- 299,328 ---- } + /** + * <p>Adds complex source (<b>CDEF</b>). + * Complex sources are evaluated using the supplied <code>RPN</code> expression.</p> + * + * <p>Complex source <code>name</code> can be used:</p> + * <ul> + * <li>To specify sources for line, area and stack plots.</li> + * <li>To define other complex sources.</li> + * </ul> + * + * <p>JRobin supports the following RPN functions, operators and constants: +, -, *, /, + * %, SIN, COS, LOG, EXP, FLOOR, CEIL, ROUND, POW, ABS, SQRT, RANDOM, LT, LE, GT, GE, EQ, + * IF, MIN, MAX, LIMIT, DUP, EXC, POP, UN, UNKN, NOW, TIME, PI, E, + * AND, OR, XOR, PREV, PREV(sourceName), INF, NEGINF, STEP, YEAR, MONTH, DATE, + * HOUR, MINUTE, SECOND and WEEK.</p> + * + * <p>JRobin does not force you to specify at least one simple source name as RRDTool.</p> + * + * <p>For more details on RPN see RRDTool's + * <a href="http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/manual/rrdgraph.html" target="man"> + * rrdgraph man page</a>.</p> + * + * @param name source name. + * @param rpnExpression RPN expression containig comma (or space) delimited simple and complex + * source names, RPN constants, functions and operators. + */ public void addDatasource(String name, String rpnExpression) { CDef cDef = new CDef(name, rpnExpression); *************** *** 142,145 **** --- 330,341 ---- } + /** + * <p>Adds static source (<b>SDEF</b>). Static sources are the result of a consolidation function applied + * to *any* other source that has been defined previously.</p> + * + * @param name source name. + * @param defName Name of the datasource to calculate the value from. + * @param consolFun Consolidation function to use for value calculation + */ public void addDatasource(String name, String defName, String consolFun) { SDef sDef = new SDef(name, defName, consolFun); *************** *** 147,150 **** --- 343,361 ---- } + /** + * <p>Adds simple datasource (<b>DEF</b>). Simple source <code>name</code> + * can be used:</p> + * <ul> + * <li>To specify sources for line, area and stack plots.</li> + * <li>To define complex sources + * </ul> + * + * @param name source name. + * @param file Path to RRD file. + * @param dsName Datasource name defined in the RRD file. + * @param consolFunc Consolidation function that will be used to extract data from the RRD + * file ("AVERAGE", "MIN", "MAX" or "LAST" - these string constants are conveniently defined + * in the {@link org.jrobin.core.ConsolFuns ConsolFuns} class). + */ public void addDatasource(String name, String file, String dsName, String consolFunc) { Def def = new Def(name, file, dsName, consolFunc); *************** *** 152,155 **** --- 363,381 ---- } + /** + * <p>Adds simple source (<b>DEF</b>). Source <code>name</code> can be used:</p> + * <ul> + * <li>To specify sources for line, area and stack plots.</li> + * <li>To define complex sources + * </ul> + * + * @param name Source name. + * @param file Path to RRD file. + * @param dsName Data source name defined in the RRD file. + * @param consolFunc Consolidation function that will be used to extract data from the RRD + * file ("AVERAGE", "MIN", "MAX" or "LAST" - these string constants are conveniently defined + * in the {@link org.jrobin.core.ConsolFuns ConsolFuns} class). + * @param backend Name of the RrdBackendFactory that should be used for this RrdDb. + */ public void addDatasource(String name, String file, String dsName, String consolFunc, String backend) { Def def = new Def(name, file, dsName, consolFunc, backend); *************** *** 161,164 **** --- 387,396 ---- ///////////////////////////////////////////////////////////////// + /** + * Method that should be called once all datasources are defined. Data will be fetched from + * RRD files, RPN expressions will be calculated, etc. + * @throws IOException Thrown in case of I/O error (while fetching data from RRD files) + * @throws RrdException Thrown in case of JRobin specific error + */ public void processData() throws IOException, RrdException { calculateDefs(); *************** *** 342,353 **** /** * Dumps timestamps and values of all datasources in a tabelar form. Very useful for debugging. ! * @return Dumped object content */ public String dump() throws RrdException { String[] names = getSourceNames(); ! double[][] values = new double[names.length][]; ! for(int i = 0; i < names.length; i++) { ! values[i] = getValues(names[i]); ! } StringBuffer buffer = new StringBuffer(); buffer.append(fmt("timestamp", 12)); --- 574,584 ---- /** * Dumps timestamps and values of all datasources in a tabelar form. Very useful for debugging. ! * @return Dumped object content. ! * @throws RrdException Thrown if nothing is calculated so far (the method {@link #processData()} ! * was not called). */ public String dump() throws RrdException { String[] names = getSourceNames(); ! double[][] values = getValues(); StringBuffer buffer = new StringBuffer(); buffer.append(fmt("timestamp", 12)); *************** *** 374,395 **** return b.toString(); } ! public static void main(String[] args) throws IOException, RrdException { final long t1 = Util.getTimestamp(2003, 4, 1); final long t2 = Util.getTimestamp(2003, 5, 1); ! DataProcessor da = new DataProcessor(t1, t2); ! da.addDatasource("x", "demo.rrd", "sun", "AVERAGE"); ! da.addDatasource("y", "demo.rrd", "shade", "AVERAGE"); ! da.addDatasource("zzzz", "x,y,+,2,/"); ! da.addDatasource("w", "PREV(x),PREV(y),+,2,/,1000,/"); ! da.setStep(86400); ! da.setPixelCount(100); ! da.processData(); ! //System.out.println("x=" + da.getAggregate("x", "AVERAGE")); ! //System.out.println("y=" + da.getAggregate("y", "AVERAGE")); ! //System.out.println(da.getAggregate("y", "MIN")); ! //System.out.println(da.getAggregate("y", "AVERAGE")); ! //System.out.println(da.getAggregate("y", "MAX")); ! System.out.println(da.dump()); } } --- 605,629 ---- return b.toString(); } ! /* public static void main(String[] args) throws IOException, RrdException { final long t1 = Util.getTimestamp(2003, 4, 1); final long t2 = Util.getTimestamp(2003, 5, 1); ! DataProcessor dp = new DataProcessor(t1, t2); ! // DEF datasource ! dp.addDatasource("x", "demo.rrd", "sun", "AVERAGE"); ! // DEF datasource ! dp.addDatasource("y", "demo.rrd", "shade", "AVERAGE"); ! // CDEF datasource ! dp.addDatasource("z", "x,y,+,2,/"); ! // SDEF datasource ! dp.addDatasource("w", "z", "AVERAGE"); ! // CDEF datasource ! dp.addDatasource("wz", "w,z,-"); ! // SDEF datasource, values should be close to zero ! dp.addDatasource("wzavg", "wz", "AVERAGE"); ! // action! ! dp.processData(); ! System.out.println(dp.dump()); } + //*/ } |
From: Sasa M. <sa...@us...> - 2004-11-25 14:26:15
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6658/org/jrobin/core Modified Files: FetchData.java Log Message: Fixed javadoc for org.java.data.DataProcessor class. Index: FetchData.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/FetchData.java,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** FetchData.java 25 Nov 2004 12:14:53 -0000 1.14 --- FetchData.java 25 Nov 2004 14:26:06 -0000 1.15 *************** *** 307,311 **** * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. * @deprecated This method may calculate averages slightly different from values displayed in the ! * corresponding graph. Use {@link org.jrobin.data.DataProcessor DataAnalyzer} class instead. */ public double getAggregate(String dsName, String consolFun) throws RrdException { --- 307,311 ---- * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. * @deprecated This method may calculate averages slightly different from values displayed in the ! * corresponding graph. Use {@link org.jrobin.data.DataProcessor DataProcessor} class instead. */ public double getAggregate(String dsName, String consolFun) throws RrdException { |
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10251/org/jrobin/data Modified Files: RpnCalculator.java Added Files: CDef.java DataProcessor.java Def.java PDef.java SDef.java Source.java Removed Files: DataStats.java Log Message: Added org.java.data.DataProcessor class. This class should be used to get datasource values for graphing purposes. AVERAGEs and TOTALs returned by this class will not change when the graph is resized. RPN calculator is greatly improved (it's very fast). --- NEW FILE: DataProcessor.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * 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.graph.Plottable; import org.jrobin.core.*; import java.util.*; import java.io.IOException; public class DataProcessor implements ConsolFuns { public static final int DEFAUL_PIXEL_COUNT = 400; private int pixelCount = DEFAUL_PIXEL_COUNT; private int pixelsPerStep = 1; private boolean poolUsed = false; final private long tStart, tEnd; private double[] timestamps; private Map sources = new LinkedHashMap(); public DataProcessor(long tStart, long tEnd) { assert tStart < tEnd: "Invalid time span while constructing DataAnalyzer"; this.tStart = tStart; this.tEnd = tEnd; createTimestamps(); } ///////////////////////////////////////////////////////////////// // BASIC FUNCTIONS ///////////////////////////////////////////////////////////////// private void createTimestamps() { timestamps = new double[pixelCount]; final double span = tEnd - tStart; for(int i = 0; i < pixelCount; i++) { timestamps[i] = tStart + ((double) i / (double)(pixelCount - 1)) * span; } } public boolean isPoolUsed() { return poolUsed; } public void setPoolUsed(boolean poolUsed) { this.poolUsed = poolUsed; } public int getPixelCount() { return pixelCount; } public void setPixelCount(int pixelCount) { this.pixelCount = pixelCount; createTimestamps(); } public void setStep(long step) { double secondsPerPixel = getSecondsPerPixel(); pixelsPerStep = Math.max((int) Math.ceil(step / secondsPerPixel), 1); } private double getSecondsPerPixel() { return (double) (tEnd - tStart) / (double) (pixelCount - 1); } public double[] getTimestamps() { return timestamps; } 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; } public double getAggregate(String sourceName, String consolFun) throws RrdException { Source source = getSource(sourceName); return source.getAggregate(consolFun, getSecondsPerPixel()); } public String[] getSourceNames() { return (String[]) sources.keySet().toArray(new String[0]); } private Source getSource(String sourceName) throws RrdException { Object source = sources.get(sourceName); if(source != null) { return (Source) source; } throw new RrdException("Unknown source: " + sourceName); } ///////////////////////////////////////////////////////////////// // DATASOURCE DEFINITIONS ///////////////////////////////////////////////////////////////// public void addDatasource(String name, Plottable plottable) { PDef pDef = new PDef(name, plottable); sources.put(name, pDef); } public void addDatasource(String name, Plottable plottable, int index) { PDef pDef = new PDef(name, plottable, index); sources.put(name, pDef); } public void addDatasource(String name, Plottable plottable, String sourceName) { PDef pDef = new PDef(name, plottable, sourceName); sources.put(name, pDef); } public void addDatasource(String name, String rpnExpression) { CDef cDef = new CDef(name, rpnExpression); sources.put(name, cDef); } public void addDatasource(String name, String defName, String consolFun) { SDef sDef = new SDef(name, defName, consolFun); sources.put(name, sDef); } public void addDatasource(String name, String file, String dsName, String consolFunc) { Def def = new Def(name, file, dsName, consolFunc); sources.put(name, def); } public void addDatasource(String name, String file, String dsName, String consolFunc, String backend) { Def def = new Def(name, file, dsName, consolFunc, backend); sources.put(name, def); } ///////////////////////////////////////////////////////////////// // MAIN FUNCTION ///////////////////////////////////////////////////////////////// public void processData() throws IOException, RrdException { calculateDefs(); calculatePDefs(); calculateSdefsAndCdefs(); } ///////////////////////////////////////////////////////////////// // DEFS CALCULATION ///////////////////////////////////////////////////////////////// private void calculateDefs() throws IOException, RrdException { Def[] defs = getDefs(); for (int i = 0; i < defs.length; i++) { if (defs[i].getValues() == null) { // not fetched yet Set dsNames = new HashSet(); dsNames.add(defs[i].getDsName()); // look for all other datasources with the same path and the same consolidation function for (int j = i + 1; j < defs.length; j++) { if (defs[i].isCompatibleWith(defs[j])) { dsNames.add(defs[j].getDsName()); } } // now we have everything RrdDb rrd = null; try { rrd = getRrd(defs[i]); FetchRequest req = rrd.createFetchRequest(defs[i].getConsolFun(), tStart, tEnd); req.setFilter(dsNames); FetchData data = req.fetchData(); //System.out.println(data.getAggregate(defs[i].getDsName(), "AVERAGE")); double[] values = data.getValues(defs[i].getDsName()); normalizeDefValues(data.getTimestamps(), values, defs[i]); for (int j = i + 1; j < defs.length; j++) { if (defs[i].isCompatibleWith(defs[j])) { //System.out.println(data.getAggregate(defs[j].getDsName(), "AVERAGE")); values = data.getValues(defs[j].getDsName()); normalizeDefValues(data.getTimestamps(), values, defs[j]); } } } finally { if (rrd != null) { releaseRrd(rrd, defs[i]); } } } } } private void normalizeDefValues(long[] dsTimestamps, double[] dsValues, Def def) { double[] values = new double[pixelCount]; int dsSegment = 1, accumPixels = 0; values[0] = (tStart == dsTimestamps[0])? dsValues[0]: dsValues[1]; double totalValue = 0D, totalTime = 0D; for(int pixel = 1; pixel < pixelCount; pixel++) { double t0 = timestamps[pixel - 1], t1 = timestamps[pixel]; while(t0 < t1) { double tLimit = Math.min(dsTimestamps[dsSegment], t1); double dt = tLimit - t0; double val = dsValues[dsSegment]; if(!Double.isNaN(val)) { totalValue += val * dt; totalTime += dt; } t0 = tLimit; if(t0 == dsTimestamps[dsSegment]) { dsSegment++; } } if(++accumPixels == pixelsPerStep || pixel == pixelCount - 1) { double average = (totalTime > 0)? totalValue / totalTime: Double.NaN; for(int i = 0; i < accumPixels; i++) { values[pixel - i] = average; } totalValue = totalTime = 0; accumPixels = 0; } } def.setValues(values); } private Def[] getDefs() { List defs = new ArrayList(); Iterator it = sources.values().iterator(); while (it.hasNext()) { Object source = it.next(); if(source instanceof Def) { defs.add(source); } } return (Def[]) defs.toArray(new Def[defs.size()]); } private RrdDb getRrd(Def def) throws IOException, RrdException { String path = def.getPath(), backend = def.getBackend(); if (poolUsed && backend == null) { return RrdDbPool.getInstance().requestRrdDb(path); } else if (backend != null) { return new RrdDb(path, true, RrdBackendFactory.getFactory(backend)); } else { return new RrdDb(path, true); } } private void releaseRrd(RrdDb rrd, Def def) throws IOException, RrdException { String backend = def.getBackend(); if (poolUsed && backend == null) { RrdDbPool.getInstance().release(rrd); } else { rrd.close(); } } ///////////////////////////////////////////////////////////////// // PLOTTABLE CALCULATION ///////////////////////////////////////////////////////////////// private void calculatePDefs() { PDef[] pDefs = getPDefs(); for(int i = 0; i < pDefs.length; i++) { double[] values = new double[pixelCount]; for(int j = 0; j < pixelCount; j++) { double t = timestamps[j]; values[j] = pDefs[i].getValue(t); } pDefs[i].setValues(values); } } private PDef[] getPDefs() { List pDefs = new ArrayList(); Iterator it = sources.values().iterator(); while (it.hasNext()) { Object source = it.next(); if(source instanceof PDef) { pDefs.add(source); } } return (PDef[]) pDefs.toArray(new PDef[pDefs.size()]); } ///////////////////////////////////////////////////////////////// // SDEFS AND CDEFS ///////////////////////////////////////////////////////////////// private void calculateSdefsAndCdefs() throws RrdException { Iterator it = sources.values().iterator(); while (it.hasNext()) { Object source = it.next(); if(source instanceof SDef) { calculateSDef((SDef) source); } else if(source instanceof CDef) { calculateCDef((CDef) source); } } } private void calculateCDef(CDef cDef) throws RrdException { RpnCalculator calc = new RpnCalculator(cDef.getRpnExpression(), cDef.getName(), this); cDef.setValues(calc.calculateValues()); } private void calculateSDef(SDef sDef) throws RrdException { String defName = sDef.getDefName(); String consolFun = sDef.getConsolFun(); Source source = getSource(defName); double value = source.getAggregate(consolFun, getSecondsPerPixel()); sDef.setValue(value, pixelCount); } ///////////////////////////////////////////////////////////////// // TRIVIA ///////////////////////////////////////////////////////////////// /** * Dumps timestamps and values of all datasources in a tabelar form. Very useful for debugging. * @return Dumped object content */ public String dump() throws RrdException { String[] names = getSourceNames(); double[][] values = new double[names.length][]; for(int i = 0; i < names.length; i++) { values[i] = getValues(names[i]); } StringBuffer buffer = new StringBuffer(); buffer.append(fmt("timestamp", 12)); for(int i = 0; i < names.length; i++) { buffer.append(fmt(names[i], 20)); } buffer.append("\n"); for(int i = 0; i < timestamps.length; i++) { long t = (long) Math.round(timestamps[i]); buffer.append(fmt("" + t, 12)); for(int j = 0; j < names.length; j++) { buffer.append(fmt(Util.formatDouble(values[j][i]), 20)); } buffer.append("\n"); } return buffer.toString(); } private static String fmt(String s, int length) { StringBuffer b = new StringBuffer(s); for(int i = 0; i < length - s.length(); i++) { b.append(' '); } return b.toString(); } public static void main(String[] args) throws IOException, RrdException { final long t1 = Util.getTimestamp(2003, 4, 1); final long t2 = Util.getTimestamp(2003, 5, 1); DataProcessor da = new DataProcessor(t1, t2); da.addDatasource("x", "demo.rrd", "sun", "AVERAGE"); da.addDatasource("y", "demo.rrd", "shade", "AVERAGE"); da.addDatasource("zzzz", "x,y,+,2,/"); da.addDatasource("w", "PREV(x),PREV(y),+,2,/,1000,/"); da.setStep(86400); da.setPixelCount(100); da.processData(); //System.out.println("x=" + da.getAggregate("x", "AVERAGE")); //System.out.println("y=" + da.getAggregate("y", "AVERAGE")); //System.out.println(da.getAggregate("y", "MIN")); //System.out.println(da.getAggregate("y", "AVERAGE")); //System.out.println(da.getAggregate("y", "MAX")); System.out.println(da.dump()); } } Index: RpnCalculator.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/RpnCalculator.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RpnCalculator.java 21 Nov 2004 13:25:39 -0000 1.1 --- RpnCalculator.java 25 Nov 2004 12:14:54 -0000 1.2 *************** *** 30,70 **** import java.util.StringTokenizer; ! import java.util.Map; ! import java.util.HashMap; ! ! /** ! * Class which implements simple RPN calculator (RRDTool-like). <p> ! * To calculate the value of expression: ! * <pre> ! * square_root[(x + y) * (x-y)] ! * </pre> ! * for <code>x=5, y=4</code>, than for <code>x=6, y=4</code>, use the following code: ! * <pre> ! * RpnCalculator c = new RpnCalculator("x,y,+,x,y,-,*,SQRT"); ! * c.setValue("x", 5); ! * c.setValue("y", 4); ! * System.out.println(c.calculate()); ! * // change the value of "x", and leave "y" as before ! * c.setValue("x", 6); ! * System.out.println(c.calculate()); ! * </pre> ! * Notes:<p> ! * <ul> ! * <li>If you call the {@link #setValue(double)} method with just one double argument, ! * it will set the value of variable named "value" by default. ! * <li>The method {@link #setTimestamp(long)} will set the value of variable "timestamp". ! * This special variable can be referenced in the RPN expression by using the token TIME. ! * <li>Once set, variable values remain preserved between consecutive {@link #calculate()} calls. You can overwrite ! * this values by calling the {@link #setValue(String, double)} method again. To get rid of all variable values, ! * use method {@link #clearValues()}. ! * </ul> ! * ! */ ! public class RpnCalculator { ! /** Default variable name for the {@link #setValue(double)} method ("value") */ ! public static final String VALUE_PLACEHOLDER = "value"; ! /** Default variable name for the {@link #setTimestamp(long)} method ("timestamp") */ ! public static final String TIMESTAMP_PLACEHOLDER = "timestamp"; private static final byte TKN_VAR = 0; private static final byte TKN_NUM = 1; --- 30,37 ---- import java.util.StringTokenizer; ! import java.util.Calendar; ! import java.util.GregorianCalendar; + class RpnCalculator { private static final byte TKN_VAR = 0; private static final byte TKN_NUM = 1; *************** *** 78,82 **** private static final byte TKN_LOG = 9; private static final byte TKN_EXP = 10; ! private static final byte TKN_FLOOR = 11; private static final byte TKN_CEIL = 12; private static final byte TKN_ROUND = 13; --- 45,49 ---- private static final byte TKN_LOG = 9; private static final byte TKN_EXP = 10; ! private static final byte TKN_FLOOR = 11; private static final byte TKN_CEIL = 12; private static final byte TKN_ROUND = 13; *************** *** 104,455 **** private static final byte TKN_E = 35; private static final byte TKN_AND = 36; ! private static final byte TKN_OR = 37; private static final byte TKN_XOR = 38; - private Map values = new HashMap(); private Token[] tokens; private RpnStack stack = new RpnStack(); ! private String rpnExpression; ! ! /** ! * Creates new RpnCalculator. RpnCalculator objects may be safely reused to calculate as many ! * expression values (for different variable values) as needed. ! * @param rpnExpression RPN expression to be used. RPN tokens should be comma (",") ! * or space (" ") delimited. ! */ ! public RpnCalculator(String rpnExpression) { this.rpnExpression = rpnExpression; ! createTokens(); ! } ! ! private void createTokens() { StringTokenizer st = new StringTokenizer(rpnExpression, ", "); tokens = new Token[st.countTokens()]; ! for(int i = 0; st.hasMoreTokens(); i++) { tokens[i] = createToken(st.nextToken()); } } ! private Token createToken(String str) { ! Token token = new Token(str); ! if(Util.isDouble(str)) { token.id = TKN_NUM; ! token.number = Util.parseDouble(str); } ! else if(str.equals("+")) { token.id = TKN_PLUS; } ! else if(str.equals("-")) { token.id = TKN_MINUS; } ! else if(str.equals("*")) { token.id = TKN_MULT; } ! else if(str.equals("/")) { token.id = TKN_DIV; } ! else if(str.equals("%")) { token.id = TKN_MOD; } ! else if(str.equals("SIN")) { token.id = TKN_SIN; } ! else if(str.equals("COS")) { token.id = TKN_COS; } ! else if(str.equals("LOG")) { token.id = TKN_LOG; } ! else if(str.equals("EXP")) { token.id = TKN_EXP; } ! else if(str.equals("FLOOR")) { token.id = TKN_FLOOR; } ! else if(str.equals("CEIL")) { token.id = TKN_CEIL; } ! else if(str.equals("ROUND")) { token.id = TKN_ROUND; } ! else if(str.equals("POW")) { token.id = TKN_POW; } ! else if(str.equals("ABS")) { token.id = TKN_ABS; } ! else if(str.equals("SQRT")) { token.id = TKN_SQRT; } ! else if(str.equals("RANDOM")) { token.id = TKN_RANDOM; } ! else if(str.equals("LT")) { token.id = TKN_LT; } ! else if(str.equals("LE")) { token.id = TKN_LE; } ! else if(str.equals("GT")) { token.id = TKN_GT; } ! else if(str.equals("GE")) { token.id = TKN_GE; } ! else if(str.equals("EQ")) { token.id = TKN_EQ; } ! else if(str.equals("IF")) { token.id = TKN_IF; } ! else if(str.equals("MIN")) { token.id = TKN_MIN; } ! else if(str.equals("MAX")) { token.id = TKN_MAX; } ! else if(str.equals("LIMIT")) { token.id = TKN_LIMIT; } ! else if(str.equals("DUP")) { token.id = TKN_DUP; } ! else if(str.equals("EXC")) { token.id = TKN_EXC; } ! else if(str.equals("POP")) { token.id = TKN_POP; } ! else if(str.equals("UN")) { token.id = TKN_UN; } ! else if(str.equals("UNKN")) { token.id = TKN_UNKN; } ! else if(str.equals("NOW")) { token.id = TKN_NOW; } ! else if(str.equals("TIME")) { token.id = TKN_TIME; } ! else if(str.equals("PI")) { token.id = TKN_PI; } ! else if(str.equals("E")) { token.id = TKN_E; } ! else if(str.equals("AND")) { token.id = TKN_AND; } ! else if(str.equals("OR")) { token.id = TKN_OR; } ! else if(str.equals("XOR")) { token.id = TKN_XOR; } else { token.id = TKN_VAR; } return token; } ! /** ! * Sets the value for the default variable if RPN expression ("value"). ! * @param value Value to be used in calculation ! */ ! public void setValue(double value) { ! setValue(VALUE_PLACEHOLDER, value); ! } ! ! /** ! * Sets the timestamp to be used in evaluation of the RPN expression. To use this ! * value in the RPN expression, use token TIME. ! * @param timestamp The value which will be used if token TIME is found in the RPN expression ! */ ! public void setTimestamp(long timestamp) { ! setValue(TIMESTAMP_PLACEHOLDER, timestamp); ! } ! ! /** ! * Sets new value for a variable in the RPN expression. ! * @param name Variable name ! * @param value Variable value ! */ ! public void setValue(String name, double value) { ! values.put(name, new Double(value)); ! } ! ! /** ! * Clears all values specified for variables in the RPN expression ! */ ! public void clearValues() { ! values.clear(); ! } ! ! /** ! * Evaluates RPN expression, by replacing variable placeholders with specified values. You are free ! * to call this method as many times as needed, with the same or modified variable values. ! * @return The value of the RPN expression ! * @throws org.jrobin.core.RrdException Thrown if some variable values are not specified before this method is called, or if the ! * RPN expression is not valid. ! */ ! public double calculate() throws RrdException { ! resetStack(); ! for(int i = 0; i < tokens.length; i++) { ! Token token = tokens[i]; ! double x1, x2, x3; ! switch(token.id) { ! case TKN_NUM: ! push(token.number); ! break; ! case TKN_VAR: ! push(getValue(token.str)); ! break; ! case TKN_PLUS: ! push(pop() + pop()); ! break; ! case TKN_MINUS: ! x2 = pop(); x1 = pop(); ! push(x1 - x2); ! break; ! case TKN_MULT: ! push(pop() * pop()); ! break; ! case TKN_DIV: ! x2 = pop(); x1 = pop(); ! push(x1 / x2); ! break; ! case TKN_MOD: ! x2 = pop(); x1 = pop(); ! push(x1 % x2); ! break; ! case TKN_SIN: ! push(Math.sin(pop())); ! break; ! case TKN_COS: ! push(Math.cos(pop())); ! break; ! case TKN_LOG: ! push(Math.log(pop())); ! break; ! case TKN_EXP: ! push(Math.exp(pop())); ! break; ! case TKN_FLOOR: ! push(Math.floor(pop())); ! break; ! case TKN_CEIL: ! push(Math.ceil(pop())); ! break; ! case TKN_ROUND: ! push(Math.round(pop())); ! break; ! case TKN_POW: ! x2 = pop(); x1 = pop(); ! push(Math.pow(x1, x2)); ! break; ! case TKN_ABS: ! push(Math.abs(pop())); ! break; ! case TKN_SQRT: ! push(Math.sqrt(pop())); ! break; ! case TKN_RANDOM: ! push(Math.random()); ! break; ! case TKN_LT: ! x2 = pop(); x1 = pop(); ! push(x1 < x2? 1: 0); ! break; ! case TKN_LE: ! x2 = pop(); x1 = pop(); ! push(x1 <= x2? 1: 0); ! break; ! case TKN_GT: ! x2 = pop(); x1 = pop(); ! push(x1 > x2? 1: 0); ! break; ! case TKN_GE: ! x2 = pop(); x1 = pop(); ! push(x1 >= x2? 1: 0); ! break; ! case TKN_EQ: ! x2 = pop(); x1 = pop(); ! push(x1 == x2? 1: 0); ! break; ! case TKN_IF: ! x3 = pop(); x2 = pop(); x1 = pop(); ! push(x1 != 0? x2: x3); ! break; ! case TKN_MIN: ! push(Math.min(pop(), pop())); ! break; ! case TKN_MAX: ! push(Math.max(pop(), pop())); ! break; ! case TKN_LIMIT: ! x3 = pop(); x2 = pop(); x1 = pop(); ! push(x1 < x2 || x1 > x3? Double.NaN: x1); ! break; ! case TKN_DUP: ! push(peek()); ! break; ! case TKN_EXC: ! x2 = pop(); x1 = pop(); ! push(x2); ! push(x1); ! break; ! case TKN_POP: ! pop(); ! break; ! case TKN_UN: ! push(Double.isNaN(pop())? 1: 0); ! break; ! case TKN_UNKN: ! push(Double.NaN); ! break; ! case TKN_NOW: ! push(Util.getTime()); ! break; ! case TKN_TIME: ! push(getValue(TIMESTAMP_PLACEHOLDER)); ! break; ! case TKN_PI: ! push(Math.PI); ! break; ! case TKN_E: ! push(Math.E); ! break; ! case TKN_AND: ! x2 = pop(); x1 = pop(); ! push((x1 != 0 && x2 != 0)? 1: 0); ! break; ! case TKN_OR: ! x2 = pop(); x1 = pop(); ! push((x1 != 0 || x2 != 0)? 1: 0); ! break; ! case TKN_XOR: ! x2 = pop(); x1 = pop(); ! push(((x1 != 0 && x2 == 0) || (x1 == 0 && x2 != 0))? 1: 0); ! break; ! default: ! throw new RrdException("Unexpected RPN token encountered [" + ! token.id + "," + token.str + "]"); } } ! double retVal = pop(); ! if(!isStackEmpty()) { ! throw new RrdException("Stack not empty at the end of calculation. " + ! "Probably bad RPN expression [" + rpnExpression + "]"); ! } ! return retVal; } ! private double getValue(String varName) throws RrdException { ! if(values.containsKey(varName)) { ! return ((Double) values.get(varName)).doubleValue(); ! } ! throw new RrdException("Value of variable [" + varName + "] not specified"); } --- 71,485 ---- private static final byte TKN_E = 35; private static final byte TKN_AND = 36; ! private static final byte TKN_OR = 37; private static final byte TKN_XOR = 38; + private static final byte TKN_PREV = 39; + private static final byte TKN_INF = 40; + private static final byte TKN_NEGINF = 41; + private static final byte TKN_STEP = 42; + private static final byte TKN_YEAR = 43; + private static final byte TKN_MONTH = 44; + private static final byte TKN_DATE = 45; + private static final byte TKN_HOUR = 46; + private static final byte TKN_MINUTE = 47; + private static final byte TKN_SECOND = 48; + private static final byte TKN_WEEK = 49; + + private String rpnExpression; + private String sourceName; + private DataProcessor dataProcessor; private Token[] tokens; private RpnStack stack = new RpnStack(); + private double[] calculatedValues; + private double[] timestamps; + private double timeStep; ! RpnCalculator(String rpnExpression, String sourceName, DataProcessor dataProcessor) throws RrdException { this.rpnExpression = rpnExpression; ! this.sourceName = sourceName; ! this.dataProcessor = dataProcessor; ! this.timestamps = dataProcessor.getTimestamps(); ! this.timeStep = this.timestamps[1] - this.timestamps[0]; ! this.calculatedValues = new double[this.timestamps.length]; StringTokenizer st = new StringTokenizer(rpnExpression, ", "); tokens = new Token[st.countTokens()]; ! for (int i = 0; st.hasMoreTokens(); i++) { tokens[i] = createToken(st.nextToken()); } } ! private Token createToken(String parsedText) throws RrdException { ! Token token = new Token(); ! if (Util.isDouble(parsedText)) { token.id = TKN_NUM; ! token.number = Util.parseDouble(parsedText); } ! else if (parsedText.equals("+")) { token.id = TKN_PLUS; } ! else if (parsedText.equals("-")) { token.id = TKN_MINUS; } ! else if (parsedText.equals("*")) { token.id = TKN_MULT; } ! else if (parsedText.equals("/")) { token.id = TKN_DIV; } ! else if (parsedText.equals("%")) { token.id = TKN_MOD; } ! else if (parsedText.equals("SIN")) { token.id = TKN_SIN; } ! else if (parsedText.equals("COS")) { token.id = TKN_COS; } ! else if (parsedText.equals("LOG")) { token.id = TKN_LOG; } ! else if (parsedText.equals("EXP")) { token.id = TKN_EXP; } ! else if (parsedText.equals("FLOOR")) { token.id = TKN_FLOOR; } ! else if (parsedText.equals("CEIL")) { token.id = TKN_CEIL; } ! else if (parsedText.equals("ROUND")) { token.id = TKN_ROUND; } ! else if (parsedText.equals("POW")) { token.id = TKN_POW; } ! else if (parsedText.equals("ABS")) { token.id = TKN_ABS; } ! else if (parsedText.equals("SQRT")) { token.id = TKN_SQRT; } ! else if (parsedText.equals("RANDOM")) { token.id = TKN_RANDOM; } ! else if (parsedText.equals("LT")) { token.id = TKN_LT; } ! else if (parsedText.equals("LE")) { token.id = TKN_LE; } ! else if (parsedText.equals("GT")) { token.id = TKN_GT; } ! else if (parsedText.equals("GE")) { token.id = TKN_GE; } ! else if (parsedText.equals("EQ")) { token.id = TKN_EQ; } ! else if (parsedText.equals("IF")) { token.id = TKN_IF; } ! else if (parsedText.equals("MIN")) { token.id = TKN_MIN; } ! else if (parsedText.equals("MAX")) { token.id = TKN_MAX; } ! else if (parsedText.equals("LIMIT")) { token.id = TKN_LIMIT; } ! else if (parsedText.equals("DUP")) { token.id = TKN_DUP; } ! else if (parsedText.equals("EXC")) { token.id = TKN_EXC; } ! else if (parsedText.equals("POP")) { token.id = TKN_POP; } ! else if (parsedText.equals("UN")) { token.id = TKN_UN; } ! else if (parsedText.equals("UNKN")) { token.id = TKN_UNKN; } ! else if (parsedText.equals("NOW")) { token.id = TKN_NOW; } ! else if (parsedText.equals("TIME")) { token.id = TKN_TIME; } ! else if (parsedText.equals("PI")) { token.id = TKN_PI; } ! else if (parsedText.equals("E")) { token.id = TKN_E; } ! else if (parsedText.equals("AND")) { token.id = TKN_AND; } ! else if (parsedText.equals("OR")) { token.id = TKN_OR; } ! else if (parsedText.equals("XOR")) { token.id = TKN_XOR; } + else if (parsedText.equals("PREV")) { + token.id = TKN_PREV; + token.variable = sourceName; + token.values = calculatedValues; + } + else if (parsedText.startsWith("PREV(") && parsedText.endsWith(")")) { + token.id = TKN_PREV; + token.variable = parsedText.substring(5, parsedText.length() - 1); + token.values = dataProcessor.getValues(token.variable); + } + else if (parsedText.equals("INF")) { + token.id = TKN_INF; + } + else if (parsedText.equals("NEGINF")) { + token.id = TKN_NEGINF; + } + else if (parsedText.equals("STEP")) { + token.id = TKN_STEP; + } + else if (parsedText.equals("YEAR")) { + token.id = TKN_YEAR; + } + else if (parsedText.equals("MONTH")) { + token.id = TKN_MONTH; + } + else if (parsedText.equals("DATE")) { + token.id = TKN_DATE; + } + else if (parsedText.equals("HOUR")) { + token.id = TKN_HOUR; + } + else if (parsedText.equals("MINUTE")) { + token.id = TKN_MINUTE; + } + else if (parsedText.equals("SECOND")) { + token.id = TKN_SECOND; + } + else if (parsedText.equals("WEEK")) { + token.id = TKN_WEEK; + } else { token.id = TKN_VAR; + token.variable = parsedText; + token.values = dataProcessor.getValues(token.variable); } return token; } ! double[] calculateValues() throws RrdException { ! for (int slot = 0; slot < timestamps.length; slot++) { ! resetStack(); ! for (int i = 0; i < tokens.length; i++) { ! Token token = tokens[i]; ! double x1, x2, x3; ! switch (token.id) { ! case TKN_NUM: ! push(token.number); ! break; ! case TKN_VAR: ! push(token.values[slot]); ! break; ! case TKN_PLUS: ! push(pop() + pop()); ! break; ! case TKN_MINUS: ! x2 = pop(); ! x1 = pop(); ! push(x1 - x2); ! break; ! case TKN_MULT: ! push(pop() * pop()); ! break; ! case TKN_DIV: ! x2 = pop(); ! x1 = pop(); ! push(x1 / x2); ! break; ! case TKN_MOD: ! x2 = pop(); ! x1 = pop(); ! push(x1 % x2); ! break; ! case TKN_SIN: ! push(Math.sin(pop())); ! break; ! case TKN_COS: ! push(Math.cos(pop())); ! break; ! case TKN_LOG: ! push(Math.log(pop())); ! break; ! case TKN_EXP: ! push(Math.exp(pop())); ! break; ! case TKN_FLOOR: ! push(Math.floor(pop())); ! break; ! case TKN_CEIL: ! push(Math.ceil(pop())); ! break; ! case TKN_ROUND: ! push(Math.round(pop())); ! break; ! case TKN_POW: ! x2 = pop(); ! x1 = pop(); ! push(Math.pow(x1, x2)); ! break; ! case TKN_ABS: ! push(Math.abs(pop())); ! break; ! case TKN_SQRT: ! push(Math.sqrt(pop())); ! break; ! case TKN_RANDOM: ! push(Math.random()); ! break; ! case TKN_LT: ! x2 = pop(); ! x1 = pop(); ! push(x1 < x2 ? 1 : 0); ! break; ! case TKN_LE: ! x2 = pop(); ! x1 = pop(); ! push(x1 <= x2 ? 1 : 0); ! break; ! case TKN_GT: ! x2 = pop(); ! x1 = pop(); ! push(x1 > x2 ? 1 : 0); ! break; ! case TKN_GE: ! x2 = pop(); ! x1 = pop(); ! push(x1 >= x2 ? 1 : 0); ! break; ! case TKN_EQ: ! x2 = pop(); ! x1 = pop(); ! push(x1 == x2 ? 1 : 0); ! break; ! case TKN_IF: ! x3 = pop(); ! x2 = pop(); ! x1 = pop(); ! push(x1 != 0 ? x2 : x3); ! break; ! case TKN_MIN: ! push(Math.min(pop(), pop())); ! break; ! case TKN_MAX: ! push(Math.max(pop(), pop())); ! break; ! case TKN_LIMIT: ! x3 = pop(); ! x2 = pop(); ! x1 = pop(); ! push(x1 < x2 || x1 > x3 ? Double.NaN : x1); ! break; ! case TKN_DUP: ! push(peek()); ! break; ! case TKN_EXC: ! x2 = pop(); ! x1 = pop(); ! push(x2); ! push(x1); ! break; ! case TKN_POP: ! pop(); ! break; ! case TKN_UN: ! push(Double.isNaN(pop()) ? 1 : 0); ! break; ! case TKN_UNKN: ! push(Double.NaN); ! break; ! case TKN_NOW: ! push(Util.getTime()); ! break; ! case TKN_TIME: ! push((long)Math.round(timestamps[slot])); ! break; ! case TKN_PI: ! push(Math.PI); ! break; ! case TKN_E: ! push(Math.E); ! break; ! case TKN_AND: ! x2 = pop(); ! x1 = pop(); ! push((x1 != 0 && x2 != 0) ? 1 : 0); ! break; ! case TKN_OR: ! x2 = pop(); ! x1 = pop(); ! push((x1 != 0 || x2 != 0) ? 1 : 0); ! break; ! case TKN_XOR: ! x2 = pop(); ! x1 = pop(); ! push(((x1 != 0 && x2 == 0) || (x1 == 0 && x2 != 0)) ? 1 : 0); ! break; ! case TKN_PREV: ! push((slot == 0)? Double.NaN: token.values[slot - 1]); ! break; ! case TKN_INF: ! push(Double.POSITIVE_INFINITY); ! break; ! case TKN_NEGINF: ! push(Double.NEGATIVE_INFINITY); ! break; ! case TKN_STEP: ! push(timeStep); ! break; ! case TKN_YEAR: ! push(getCalendarField(pop(), Calendar.YEAR)); ! break; ! case TKN_MONTH: ! push(getCalendarField(pop(), Calendar.MONTH)); ! break; ! case TKN_DATE: ! push(getCalendarField(pop(), Calendar.DAY_OF_MONTH)); ! break; ! case TKN_HOUR: ! push(getCalendarField(pop(), Calendar.HOUR_OF_DAY)); ! break; ! case TKN_MINUTE: ! push(getCalendarField(pop(), Calendar.MINUTE)); ! break; ! case TKN_SECOND: ! push(getCalendarField(pop(), Calendar.SECOND)); ! break; ! case TKN_WEEK: ! push(getCalendarField(pop(), Calendar.WEEK_OF_YEAR)); ! break; ! default: ! throw new RrdException("Unexpected RPN token encountered, token.id=" + token.id); ! } ! } ! calculatedValues[slot] = pop(); ! // check if stack is empty only on the first try ! if (slot == 0 && !isStackEmpty()) { ! throw new RrdException("Stack not empty at the end of calculation. " + ! "Probably bad RPN expression [" + rpnExpression + "]"); } } ! return calculatedValues; } ! private double getCalendarField(double timestamp, int field) { ! GregorianCalendar gc = new GregorianCalendar(); ! gc.setTimeInMillis((long)(timestamp * 1000)); ! return gc.get(field); } *************** *** 480,484 **** void push(double x) throws RrdException { ! if(pos >= MAX_STACK_SIZE) { throw new RrdException("PUSH failed, RPN stack full [" + MAX_STACK_SIZE + "]"); } --- 510,514 ---- void push(double x) throws RrdException { ! if (pos >= MAX_STACK_SIZE) { throw new RrdException("PUSH failed, RPN stack full [" + MAX_STACK_SIZE + "]"); } *************** *** 487,491 **** double pop() throws RrdException { ! if(pos <= 0) { throw new RrdException("POP failed, RPN stack is empty "); } --- 517,521 ---- double pop() throws RrdException { ! if (pos <= 0) { throw new RrdException("POP failed, RPN stack is empty "); } *************** *** 494,498 **** double peek() throws RrdException { ! if(pos <= 0) { throw new RrdException("PEEK failed, RPN stack is empty "); } --- 524,528 ---- double peek() throws RrdException { ! if (pos <= 0) { throw new RrdException("PEEK failed, RPN stack is empty "); } *************** *** 510,531 **** private class Token { ! byte id; ! String str; ! double number; ! ! Token(String str) { ! this.str = str; ! } ! } ! ! /* ! public static void main(String[] args) throws RrdException { ! RpnCalculator c = new RpnCalculator("x,y,+,x,y,-,*,SQRT"); ! c.setValue("x", 5); ! c.setValue("y", 4); ! System.out.println(c.calculate()); ! c.setValue("x", 6); ! System.out.println(c.calculate()); } - */ } --- 540,547 ---- private class Token { ! byte id = -1; ! double number = Double.NaN; ! String variable = null; ! double[] values = null; } } --- NEW FILE: PDef.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * 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.graph.Plottable; class PDef extends Source { private final Plottable plottable; PDef(String name, Plottable plottable) { super(name); this.plottable = plottable; } PDef(String name, final Plottable plottable, final int index) { super(name); this.plottable = new Plottable() { public double getValue(long timestamp) { return plottable.getValue(timestamp, index); } }; } PDef(String name, final Plottable plottable, final String sourceName) { super(name); this.plottable = new Plottable() { public double getValue(long timestamp) { return plottable.getValue(timestamp, sourceName); } }; } double getValue(double timestamp) { long t = (long) Math.round(timestamp); return plottable.getValue(t); } } --- NEW FILE: SDef.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * 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; class SDef extends Source { private String defName; private String consolFun; SDef(String name, String defName, String consolFun) { super(name); this.defName = defName; this.consolFun = consolFun; } String getDefName() { return defName; } String getConsolFun() { return consolFun; } void setValue(double value, int count) { double[] values = new double[count]; for(int i = 0; i < values.length; i++) { values[i] = value; } setValues(values); } } --- NEW FILE: Source.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * 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.ConsolFuns; import org.jrobin.core.RrdException; import org.jrobin.core.Util; abstract class Source implements ConsolFuns { final private String name; private double[] values; Source(String name) { this.name = name; } final String getName() { return name; } final void setValues(double[] values) { this.values = values; } final double[] getValues() { return values; } final double getAggregate(String consolFun, double secondsPerPixel) throws RrdException { if(values == null) { throw new RrdException("Could not calculate " + consolFun + " for datasource [" + name + "], datasource values are still not available"); } if(consolFun.equals(ConsolFuns.CF_FIRST)) { return values[1]; } else if(consolFun.equals(ConsolFuns.CF_LAST)) { return values[values.length - 1]; } else if(consolFun.equals(ConsolFuns.CF_MIN)) { return getMin(); } else if(consolFun.equals(ConsolFuns.CF_MAX)) { return getMax(); } else if(consolFun.equals(ConsolFuns.CF_AVERAGE)) { return getAverage(); } else if(consolFun.equals(ConsolFuns.CF_TOTAL)) { return getTotal(secondsPerPixel); } else { throw new RrdException("Unsupported consolidation function: " + consolFun); } } private double getTotal(double secondsPerPixel) { double sum = 0; for(int i = 1; i < values.length; i++) { if(!Double.isNaN(values[i])) { sum += values[i]; } } return sum * secondsPerPixel; } private double getAverage() { double sum = 0; int count = 0; for(int i = 1; i < values.length; i++) { if(!Double.isNaN(values[i])) { sum += values[i]; count++; } } return sum / count; } private double getMax() { double max = Double.NaN; for(int i = 1; i < values.length; i++) { max = Util.max(max, values[i]); } return max; } private double getMin() { double min = Double.NaN; for(int i = 1; i < values.length; i++) { min = Util.min(min, values[i]); } return min; } } --- NEW FILE: Def.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * 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.Util; import java.io.IOException; class Def extends Source { private String path, dsName, consolFun, backend; Def(String name, String path, String dsName, String consolFunc) { this(name, path, dsName, consolFunc, null); } Def(String name, String path, String dsName, String consolFunc, String backend) { super(name); this.path = path; this.dsName = dsName; this.consolFun = consolFunc; this.backend = backend; } String getPath() { return path; } String getCanonicalPath() throws IOException { return Util.getCanonicalPath(path); } String getDsName() { return dsName; } String getConsolFun() { return consolFun; } String getBackend() { return backend; } boolean isCompatibleWith(Def def) throws IOException { return getCanonicalPath().equals(def.getCanonicalPath()) && getConsolFun().equals(def.consolFun) && ((backend == null && def.backend == null) || (backend != null && def.backend != null && backend.equals(def.backend))); } } --- DataStats.java DELETED --- --- NEW FILE: CDef.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * 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; class CDef extends Source { private String rpnExpression; CDef(String name, String rpnExpression) { super(name); this.rpnExpression = rpnExpression; } String getRpnExpression() { return rpnExpression; } } |
From: Sasa M. <sa...@us...> - 2004-11-25 12:15:09
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10251/org/jrobin/core Modified Files: FetchData.java FetchRequest.java Util.java Log Message: Added org.java.data.DataProcessor class. This class should be used to get datasource values for graphing purposes. AVERAGEs and TOTALs returned by this class will not change when the graph is resized. RPN calculator is greatly improved (it's very fast). Index: FetchData.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/FetchData.java,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** FetchData.java 21 Nov 2004 13:25:38 -0000 1.13 --- FetchData.java 25 Nov 2004 12:14:53 -0000 1.14 *************** *** 26,37 **** package org.jrobin.core; - import org.jrobin.data.DataStats; - import org.jrobin.data.RpnCalculator; - import java.io.IOException; import java.io.OutputStream; import java.io.FileOutputStream; import java.io.ByteArrayOutputStream; - import java.text.DecimalFormat; /** --- 26,33 ---- *************** *** 57,61 **** * the values returned with {@link #getTimestamps() getTimestamps()} method.<p> * - * Use {@link #getStats(String, String)} method to calculate aggregates for the fetched data<p> */ public class FetchData implements RrdDataSet, ConsolFuns { --- 53,56 ---- *************** *** 248,257 **** /** ! * Dumps the content of the whole FetchData object to stdout. Useful for debugging. */ ! public void dump() { ! for (int i = 0; i < getRowCount(); i++) { ! System.out.println(getRow(i).dump()); } } --- 243,260 ---- /** ! * Dumps the content of the whole FetchData object. Useful for debugging. */ ! public String dump() { ! StringBuffer buffer = new StringBuffer(""); ! for (int row = 0; row < getRowCount(); row++) { ! buffer.append(timestamps[row]); ! buffer.append(": "); ! for(int dsIndex = 0; dsIndex < getColumnCount(); dsIndex++) { ! buffer.append(Util.formatDouble(values[dsIndex][row], true)); ! buffer.append(" "); ! } ! buffer.append("\n"); } + return buffer.toString(); } *************** *** 262,266 **** */ public String toString() { - final DecimalFormat df = new DecimalFormat("+0.0000000000E00"); // print header row StringBuffer buff = new StringBuffer(); --- 265,268 ---- *************** *** 276,280 **** for (int j = 0; j < dsNames.length; j++) { double value = values[j][i]; ! String valueStr = Double.isNaN(value) ? "nan" : df.format(value); buff.append(padWithBlanks(valueStr, 18)); } --- 278,282 ---- for (int j = 0; j < dsNames.length; j++) { double value = values[j][i]; ! String valueStr = Double.isNaN(value) ? "nan" : Util.formatDouble(value); buff.append(padWithBlanks(valueStr, 18)); } *************** *** 299,324 **** * @param dsName Datasource name * @param consolFun Consolidation function to be applied to fetched datasource values. - * Valid consolidation functions are "MIN", "MAX", "LAST" and "AVERAGE" - * (these string constants are conveniently defined in the {@link ConsolFuns} class). - * @return MIN, MAX, LAST or AVERAGE value calculated from the fetched data - * for the given datasource name - * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. - * @deprecated Use {@link #getStats(String) getStats(dsName)} method instead. - */ - public double getAggregate(String dsName, String consolFun) throws RrdException { - return getAggregate(dsName, consolFun, null); - } - - /** - * Returns aggregated value from the fetched data for a single datasource. - * Before applying aggrregation functions, specified RPN expression is applied to fetched - * data. For example, if you have a GAUGE datasource named 'feet' but you want to - * find the maximum fetched value in meters use something like:</p> - * <code>getAggregate("feet", ConsolFuns.MAX, "value,0.3048,*");</code> - * Note that 'value' in the RPN expression is a reserved word and stands for the - * original value (value fetched from the RRD)</p> - * - * @param dsName 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) --- 301,304 ---- *************** *** 326,351 **** * for the given datasource name * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. ! * @deprecated Use {@link #getStats(String, String) getStats(dsName, rpnExpression)} method instead. */ ! public double getAggregate(String dsName, String consolFun, String rpnExpression) ! throws RrdException { ! DataStats stats = getStats(dsName, rpnExpression); ! if (consolFun.equals(CF_MAX)) { ! return stats.getMax(); } ! else if (consolFun.equals(CF_MIN)) { ! return stats.getMin(); } ! else if (consolFun.equals(CF_LAST)) { ! return stats.getLast(); } ! else if (consolFun.equals(CF_FIRST)) { ! return stats.getFirst(); } ! else if (consolFun.equals(CF_AVERAGE)) { ! return stats.getAverage(); } ! else if (consolFun.equals(CF_TOTAL)) { ! return stats.getTotal(); } else { --- 306,330 ---- * for the given datasource name * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. ! * @deprecated This method may calculate averages slightly different from values displayed in the ! * corresponding graph. Use {@link org.jrobin.data.DataProcessor DataAnalyzer} class instead. */ ! public double getAggregate(String dsName, String consolFun) throws RrdException { ! if(consolFun.equals(CF_MAX)) { ! return getMax(dsName); } ! else if(consolFun.equals(CF_MIN)) { ! return getMin(dsName); } ! else if(consolFun.equals(CF_LAST)) { ! return getLast(dsName); } ! else if(consolFun.equals(CF_FIRST)) { ! return getFirst(dsName); } ! else if(consolFun.equals(CF_AVERAGE)) { ! return getAverage(dsName); } ! else if(consolFun.equals(CF_TOTAL)) { ! return getTotal(dsName); } else { *************** *** 354,398 **** } ! /** ! * Returns all aggregated values from the fetched data for a single datasource. ! * ! * @param dsName Datasource name ! * @return Object containing MIN, MAX, LAST, FIRST, AVERAGE and TOTAL values calculated from the fetched data ! * for the given datasource name ! * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. ! */ ! public DataStats getStats(String dsName) throws RrdException { ! return getStats(dsName, null); } ! /** ! * Returns all aggregated values from the fetched data for a single datasource. ! * Before applying aggrregation functions, specified RPN expression is applied to fetched ! * data. For example, if you have a GAUGE datasource named 'feet' but you want to ! * calculate aggregates in meters use something like:<p> ! * <pre> ! * getStats("feet", "value,0.3048,*"); ! * </pre> ! * Note that the placeholder 'value' in the RPN expression is a reserved word and stands for the ! * original value (value fetched from the RRD) ! * ! * @param dsName Datasource name ! * @return Object containing MIN, MAX, LAST, FIRST, AVERAGE and TOTAL values calculated from the fetched data ! * for the given datasource name and a given RPN expression ! * @throws RrdException Thrown if the given datasource name cannot be found in fetched data ! */ ! public DataStats getStats(String dsName, String rpnExpression) throws RrdException { ! double[] values = getValues(dsName), calculatedValues = values; ! if (rpnExpression != null) { ! calculatedValues = new double[values.length]; ! RpnCalculator rpnCalculator = new RpnCalculator(rpnExpression); ! for (int i = 0; i < values.length; i++) { ! rpnCalculator.setValue(values[i]); ! rpnCalculator.setTimestamp(timestamps[i]); ! calculatedValues[i] = rpnCalculator.calculate(); } } ! return new DataStats(timestamps, calculatedValues, ! request.getFetchStart(), request.getFetchEnd()); } --- 333,387 ---- } ! private double getMax(String dsName) throws RrdException { ! double values[] = getValues(dsName), max = Double.NaN; ! for(int i = 1; i < values.length; i++) { ! max = Util.max(max, values[i]); ! } ! return max; } ! private double getMin(String dsName) throws RrdException { ! double values[] = getValues(dsName), min = Double.NaN; ! for(int i = 1; i < values.length; i++) { ! min = Util.min(min, values[i]); ! } ! return min; ! } ! ! private double getLast(String dsName) throws RrdException { ! double values[] = getValues(dsName); ! return values[values.length - 1]; ! } ! ! private double getFirst(String dsName) throws RrdException { ! double values[] = getValues(dsName); ! return values[1]; ! } ! ! private double getAverage(String dsName) throws RrdException { ! double values[] = getValues(dsName), totalVal = 0D; ! long tStart = request.getFetchStart(), tEnd = request.getFetchEnd(), totalSecs = 0; ! for(int i = 1; i < values.length; i++) { ! long t1 = Math.max(tStart, timestamps[i - 1]), t2 = Math.min(tEnd, timestamps[i]); ! double value = values[i]; ! if(!Double.isNaN(value)) { ! totalSecs += (t2 - t1); ! totalVal += (t2 - t1) * value; } } ! return totalSecs > 0? totalVal / totalSecs: Double.NaN; ! } ! ! private double getTotal(String dsName) throws RrdException { ! double vals[] = getValues(dsName), totalVal = 0D; ! long tStart = request.getFetchStart(), tEnd = request.getFetchEnd(); ! for(int i = 1; i < vals.length; i++) { ! long t1 = Math.max(tStart, timestamps[i - 1]), t2 = Math.min(tEnd, timestamps[i]); ! double value = vals[i]; ! if(!Double.isNaN(value)) { ! totalVal += (t2 - t1) * value; ! } ! } ! return totalVal; } Index: Util.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Util.java,v retrieving revision 1.28 retrieving revision 1.29 diff -C2 -d -r1.28 -r1.29 *** Util.java 22 Nov 2004 13:34:51 -0000 1.28 --- Util.java 25 Nov 2004 12:14:53 -0000 1.29 *************** *** 142,145 **** --- 142,155 ---- /** + * Formats double as a string using exponential notation. Used for debugging + * throught the project. + * @param x value to be formatted + * @return string like "+1.234567E+02" + */ + public static String formatDouble(double x) { + return formatDouble(x, true); + } + + /** * Returns <code>Date</code> object for the given timestamp (in seconds, without * milliseconds) Index: FetchRequest.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/FetchRequest.java,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** FetchRequest.java 21 Jul 2004 08:27:40 -0000 1.7 --- FetchRequest.java 25 Nov 2004 12:14:53 -0000 1.8 *************** *** 27,30 **** --- 27,31 ---- import java.io.IOException; + import java.util.Set; /** *************** *** 72,75 **** --- 73,89 ---- /** * Sets request filter in order to fetch data only for + * the specified set of datasources (datasource names). + * If the filter is not set (or set to null), fetched data will + * containt values of all datasources defined in the corresponding RRD. + * To fetch data only from selected + * datasources, specify a set of datasource names as method argument. + * @param filter Set of datsource names to fetch data for. + */ + public void setFilter(Set filter) { + this.filter = (String[]) filter.toArray(new String[0]); + } + + /** + * Sets request filter in order to fetch data only for * a single datasource (datasource name). * If not set (or set to null), fetched data will |
From: Sasa M. <sa...@us...> - 2004-11-25 12:15:09
|
Update of /cvsroot/jrobin/src/org/jrobin/demo In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10251/org/jrobin/demo Modified Files: Demo.java Log Message: Added org.java.data.DataProcessor class. This class should be used to get datasource values for graphing purposes. AVERAGEs and TOTALs returned by this class will not change when the graph is resized. RPN calculator is greatly improved (it's very fast). Index: Demo.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/demo/Demo.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** Demo.java 19 Nov 2004 12:00:02 -0000 1.4 --- Demo.java 25 Nov 2004 12:14:54 -0000 1.5 *************** *** 136,143 **** println("== Dumping fetched data to XML format"); println(fetchData.exportXml()); - println("== Dumping fetch statistics for datasource 'sun'"); - println(fetchData.getStats("sun").dump()); - println("== Dumping fetch statistics for datasource 'shade'"); - println(fetchData.getStats("shade").dump()); println("== Fetch completed"); --- 136,139 ---- |
From: Sasa M. <sa...@us...> - 2004-11-22 13:35:15
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8320/org/jrobin/core Modified Files: RrdBackendFactory.java RrdDbPool.java RrdFileBackend.java Util.java Log Message: Default backend selection changed. Defaults to NIO for JDK >= 1.4.2, to FILE otherwise. Index: RrdDbPool.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDbPool.java,v retrieving revision 1.19 retrieving revision 1.20 diff -C2 -d -r1.19 -r1.20 *** RrdDbPool.java 12 Nov 2004 10:09:38 -0000 1.19 --- RrdDbPool.java 22 Nov 2004 13:34:51 -0000 1.20 *************** *** 466,470 **** private static String getCanonicalPath(String path) throws IOException { ! return RrdFileBackend.getCanonicalPath(path); } --- 466,470 ---- private static String getCanonicalPath(String path) throws IOException { ! return Util.getCanonicalPath(path); } Index: Util.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Util.java,v retrieving revision 1.27 retrieving revision 1.28 diff -C2 -d -r1.27 -r1.28 *** Util.java 18 Nov 2004 13:27:58 -0000 1.27 --- Util.java 22 Nov 2004 13:34:51 -0000 1.28 *************** *** 570,572 **** --- 570,582 ---- } + /** + * Returns canonical file path for the given file path + * @param path Absolute or relative file path + * @return Canonical file path + * @throws IOException Thrown if canonical file path could not be resolved + */ + public static String getCanonicalPath(String path) throws IOException { + return new File(path).getCanonicalPath(); + } + } \ No newline at end of file Index: RrdBackendFactory.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdBackendFactory.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** RrdBackendFactory.java 9 Nov 2004 11:36:53 -0000 1.8 --- RrdBackendFactory.java 22 Nov 2004 13:34:51 -0000 1.9 *************** *** 82,89 **** RrdSafeFileBackendFactory safeFactory = new RrdSafeFileBackendFactory(); registerFactory(safeFactory); ! ! // Here is the default backend factory ! defaultFactory = nioFactory; ! } catch (RrdException e) { throw new RuntimeException("FATAL: Cannot register RRD backend factories: " + e); --- 82,86 ---- RrdSafeFileBackendFactory safeFactory = new RrdSafeFileBackendFactory(); registerFactory(safeFactory); ! selectDefaultFactory(); } catch (RrdException e) { throw new RuntimeException("FATAL: Cannot register RRD backend factories: " + e); *************** *** 91,94 **** --- 88,102 ---- } + private static void selectDefaultFactory() throws RrdException { + String version = System.getProperty("java.version"); + if(version == null || version.startsWith("1.3.") || + version.startsWith("1.4.0") || version.startsWith("1.4.1")) { + setDefaultFactory("FILE"); + } + else { + setDefaultFactory("NIO"); + } + } + /** * Returns backend factory for the given backend factory name. Index: RrdFileBackend.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdFileBackend.java,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** RrdFileBackend.java 19 Oct 2004 10:14:03 -0000 1.11 --- RrdFileBackend.java 22 Nov 2004 13:34:51 -0000 1.12 *************** *** 28,32 **** import java.io.IOException; import java.io.RandomAccessFile; - import java.io.File; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; --- 28,31 ---- *************** *** 157,161 **** */ public static String getCanonicalPath(String path) throws IOException { ! return new File(path).getCanonicalPath(); } --- 156,160 ---- */ public static String getCanonicalPath(String path) throws IOException { ! return Util.getCanonicalPath(path); } |
From: Sasa M. <sa...@us...> - 2004-11-21 13:25:55
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14051/org/jrobin/core Modified Files: FetchData.java Removed Files: FetchDataStats.java RpnCalculator.java Log Message: org.jrobin.data package introduction --- RpnCalculator.java DELETED --- Index: FetchData.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/FetchData.java,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** FetchData.java 19 Nov 2004 13:43:52 -0000 1.12 --- FetchData.java 21 Nov 2004 13:25:38 -0000 1.13 *************** *** 26,29 **** --- 26,32 ---- package org.jrobin.core; + import org.jrobin.data.DataStats; + import org.jrobin.data.RpnCalculator; + import java.io.IOException; import java.io.OutputStream; *************** *** 327,331 **** public double getAggregate(String dsName, String consolFun, String rpnExpression) throws RrdException { ! FetchDataStats stats = getStats(dsName, rpnExpression); if (consolFun.equals(CF_MAX)) { return stats.getMax(); --- 330,334 ---- public double getAggregate(String dsName, String consolFun, String rpnExpression) throws RrdException { ! DataStats stats = getStats(dsName, rpnExpression); if (consolFun.equals(CF_MAX)) { return stats.getMax(); *************** *** 359,363 **** * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. */ ! public FetchDataStats getStats(String dsName) throws RrdException { return getStats(dsName, null); } --- 362,366 ---- * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. */ ! public DataStats getStats(String dsName) throws RrdException { return getStats(dsName, null); } *************** *** 379,414 **** * @throws RrdException Thrown if the given datasource name cannot be found in fetched data */ ! public FetchDataStats getStats(String dsName, String rpnExpression) throws RrdException { ! double[] values = getValues(dsName); ! long totalSecs = 0; ! double totalValue = 0.0, min = Double.NaN, max = Double.NaN; ! RpnCalculator rpnCalculator = null; if (rpnExpression != null) { ! rpnCalculator = new RpnCalculator(rpnExpression); ! } ! for (int i = 0; i < values.length - 1; i++) { ! long t1 = Math.max(request.getFetchStart(), timestamps[i]); ! long t2 = Math.min(request.getFetchEnd(), timestamps[i + 1]); ! double value = values[i + 1]; ! if (rpnCalculator != null) { ! rpnCalculator.setValue(value); ! rpnCalculator.setTimestamp(t2); ! value = rpnCalculator.calculate(); ! } ! if (!Double.isNaN(value)) { ! totalSecs += (t2 - t1); ! totalValue += (t2 - t1) * value; } - min = Util.min(min, value); - max = Util.max(max, value); } ! FetchDataStats stats = new FetchDataStats(); ! stats.setFirst(values[1]); ! stats.setLast(values[values.length - 1]); ! stats.setMax(max); ! stats.setMin(min); ! stats.setSeconds(totalSecs); ! stats.setTotal(totalValue); ! return stats; } --- 382,398 ---- * @throws RrdException Thrown if the given datasource name cannot be found in fetched data */ ! public DataStats getStats(String dsName, String rpnExpression) throws RrdException { ! double[] values = getValues(dsName), calculatedValues = values; if (rpnExpression != null) { ! calculatedValues = new double[values.length]; ! RpnCalculator rpnCalculator = new RpnCalculator(rpnExpression); ! for (int i = 0; i < values.length; i++) { ! rpnCalculator.setValue(values[i]); ! rpnCalculator.setTimestamp(timestamps[i]); ! calculatedValues[i] = rpnCalculator.calculate(); } } ! return new DataStats(timestamps, calculatedValues, ! request.getFetchStart(), request.getFetchEnd()); } --- FetchDataStats.java DELETED --- |
From: Sasa M. <sa...@us...> - 2004-11-21 13:25:55
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14051/org/jrobin/data Added Files: DataStats.java RpnCalculator.java Log Message: org.jrobin.data package introduction --- NEW FILE: RpnCalculator.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * 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.Util; import org.jrobin.core.RrdException; import java.util.StringTokenizer; import java.util.Map; import java.util.HashMap; /** * Class which implements simple RPN calculator (RRDTool-like). <p> * To calculate the value of expression: * <pre> * square_root[(x + y) * (x-y)] * </pre> * for <code>x=5, y=4</code>, than for <code>x=6, y=4</code>, use the following code: * <pre> * RpnCalculator c = new RpnCalculator("x,y,+,x,y,-,*,SQRT"); * c.setValue("x", 5); * c.setValue("y", 4); * System.out.println(c.calculate()); * // change the value of "x", and leave "y" as before * c.setValue("x", 6); * System.out.println(c.calculate()); * </pre> * Notes:<p> * <ul> * <li>If you call the {@link #setValue(double)} method with just one double argument, * it will set the value of variable named "value" by default. * <li>The method {@link #setTimestamp(long)} will set the value of variable "timestamp". * This special variable can be referenced in the RPN expression by using the token TIME. * <li>Once set, variable values remain preserved between consecutive {@link #calculate()} calls. You can overwrite * this values by calling the {@link #setValue(String, double)} method again. To get rid of all variable values, * use method {@link #clearValues()}. * </ul> * */ public class RpnCalculator { /** Default variable name for the {@link #setValue(double)} method ("value") */ public static final String VALUE_PLACEHOLDER = "value"; /** Default variable name for the {@link #setTimestamp(long)} method ("timestamp") */ public static final String TIMESTAMP_PLACEHOLDER = "timestamp"; private static final byte TKN_VAR = 0; private static final byte TKN_NUM = 1; private static final byte TKN_PLUS = 2; private static final byte TKN_MINUS = 3; private static final byte TKN_MULT = 4; private static final byte TKN_DIV = 5; private static final byte TKN_MOD = 6; private static final byte TKN_SIN = 7; private static final byte TKN_COS = 8; private static final byte TKN_LOG = 9; private static final byte TKN_EXP = 10; private static final byte TKN_FLOOR = 11; private static final byte TKN_CEIL = 12; private static final byte TKN_ROUND = 13; private static final byte TKN_POW = 14; private static final byte TKN_ABS = 15; private static final byte TKN_SQRT = 16; private static final byte TKN_RANDOM = 17; private static final byte TKN_LT = 18; private static final byte TKN_LE = 19; private static final byte TKN_GT = 20; private static final byte TKN_GE = 21; private static final byte TKN_EQ = 22; private static final byte TKN_IF = 23; private static final byte TKN_MIN = 24; private static final byte TKN_MAX = 25; private static final byte TKN_LIMIT = 26; private static final byte TKN_DUP = 27; private static final byte TKN_EXC = 28; private static final byte TKN_POP = 29; private static final byte TKN_UN = 30; private static final byte TKN_UNKN = 31; private static final byte TKN_NOW = 32; private static final byte TKN_TIME = 33; private static final byte TKN_PI = 34; private static final byte TKN_E = 35; private static final byte TKN_AND = 36; private static final byte TKN_OR = 37; private static final byte TKN_XOR = 38; private Map values = new HashMap(); private Token[] tokens; private RpnStack stack = new RpnStack(); private String rpnExpression; /** * Creates new RpnCalculator. RpnCalculator objects may be safely reused to calculate as many * expression values (for different variable values) as needed. * @param rpnExpression RPN expression to be used. RPN tokens should be comma (",") * or space (" ") delimited. */ public RpnCalculator(String rpnExpression) { this.rpnExpression = rpnExpression; createTokens(); } private void createTokens() { StringTokenizer st = new StringTokenizer(rpnExpression, ", "); tokens = new Token[st.countTokens()]; for(int i = 0; st.hasMoreTokens(); i++) { tokens[i] = createToken(st.nextToken()); } } private Token createToken(String str) { Token token = new Token(str); if(Util.isDouble(str)) { token.id = TKN_NUM; token.number = Util.parseDouble(str); } else if(str.equals("+")) { token.id = TKN_PLUS; } else if(str.equals("-")) { token.id = TKN_MINUS; } else if(str.equals("*")) { token.id = TKN_MULT; } else if(str.equals("/")) { token.id = TKN_DIV; } else if(str.equals("%")) { token.id = TKN_MOD; } else if(str.equals("SIN")) { token.id = TKN_SIN; } else if(str.equals("COS")) { token.id = TKN_COS; } else if(str.equals("LOG")) { token.id = TKN_LOG; } else if(str.equals("EXP")) { token.id = TKN_EXP; } else if(str.equals("FLOOR")) { token.id = TKN_FLOOR; } else if(str.equals("CEIL")) { token.id = TKN_CEIL; } else if(str.equals("ROUND")) { token.id = TKN_ROUND; } else if(str.equals("POW")) { token.id = TKN_POW; } else if(str.equals("ABS")) { token.id = TKN_ABS; } else if(str.equals("SQRT")) { token.id = TKN_SQRT; } else if(str.equals("RANDOM")) { token.id = TKN_RANDOM; } else if(str.equals("LT")) { token.id = TKN_LT; } else if(str.equals("LE")) { token.id = TKN_LE; } else if(str.equals("GT")) { token.id = TKN_GT; } else if(str.equals("GE")) { token.id = TKN_GE; } else if(str.equals("EQ")) { token.id = TKN_EQ; } else if(str.equals("IF")) { token.id = TKN_IF; } else if(str.equals("MIN")) { token.id = TKN_MIN; } else if(str.equals("MAX")) { token.id = TKN_MAX; } else if(str.equals("LIMIT")) { token.id = TKN_LIMIT; } else if(str.equals("DUP")) { token.id = TKN_DUP; } else if(str.equals("EXC")) { token.id = TKN_EXC; } else if(str.equals("POP")) { token.id = TKN_POP; } else if(str.equals("UN")) { token.id = TKN_UN; } else if(str.equals("UNKN")) { token.id = TKN_UNKN; } else if(str.equals("NOW")) { token.id = TKN_NOW; } else if(str.equals("TIME")) { token.id = TKN_TIME; } else if(str.equals("PI")) { token.id = TKN_PI; } else if(str.equals("E")) { token.id = TKN_E; } else if(str.equals("AND")) { token.id = TKN_AND; } else if(str.equals("OR")) { token.id = TKN_OR; } else if(str.equals("XOR")) { token.id = TKN_XOR; } else { token.id = TKN_VAR; } return token; } /** * Sets the value for the default variable if RPN expression ("value"). * @param value Value to be used in calculation */ public void setValue(double value) { setValue(VALUE_PLACEHOLDER, value); } /** * Sets the timestamp to be used in evaluation of the RPN expression. To use this * value in the RPN expression, use token TIME. * @param timestamp The value which will be used if token TIME is found in the RPN expression */ public void setTimestamp(long timestamp) { setValue(TIMESTAMP_PLACEHOLDER, timestamp); } /** * Sets new value for a variable in the RPN expression. * @param name Variable name * @param value Variable value */ public void setValue(String name, double value) { values.put(name, new Double(value)); } /** * Clears all values specified for variables in the RPN expression */ public void clearValues() { values.clear(); } /** * Evaluates RPN expression, by replacing variable placeholders with specified values. You are free * to call this method as many times as needed, with the same or modified variable values. * @return The value of the RPN expression * @throws org.jrobin.core.RrdException Thrown if some variable values are not specified before this method is called, or if the * RPN expression is not valid. */ public double calculate() throws RrdException { resetStack(); for(int i = 0; i < tokens.length; i++) { Token token = tokens[i]; double x1, x2, x3; switch(token.id) { case TKN_NUM: push(token.number); break; case TKN_VAR: push(getValue(token.str)); break; case TKN_PLUS: push(pop() + pop()); break; case TKN_MINUS: x2 = pop(); x1 = pop(); push(x1 - x2); break; case TKN_MULT: push(pop() * pop()); break; case TKN_DIV: x2 = pop(); x1 = pop(); push(x1 / x2); break; case TKN_MOD: x2 = pop(); x1 = pop(); push(x1 % x2); break; case TKN_SIN: push(Math.sin(pop())); break; case TKN_COS: push(Math.cos(pop())); break; case TKN_LOG: push(Math.log(pop())); break; case TKN_EXP: push(Math.exp(pop())); break; case TKN_FLOOR: push(Math.floor(pop())); break; case TKN_CEIL: push(Math.ceil(pop())); break; case TKN_ROUND: push(Math.round(pop())); break; case TKN_POW: x2 = pop(); x1 = pop(); push(Math.pow(x1, x2)); break; case TKN_ABS: push(Math.abs(pop())); break; case TKN_SQRT: push(Math.sqrt(pop())); break; case TKN_RANDOM: push(Math.random()); break; case TKN_LT: x2 = pop(); x1 = pop(); push(x1 < x2? 1: 0); break; case TKN_LE: x2 = pop(); x1 = pop(); push(x1 <= x2? 1: 0); break; case TKN_GT: x2 = pop(); x1 = pop(); push(x1 > x2? 1: 0); break; case TKN_GE: x2 = pop(); x1 = pop(); push(x1 >= x2? 1: 0); break; case TKN_EQ: x2 = pop(); x1 = pop(); push(x1 == x2? 1: 0); break; case TKN_IF: x3 = pop(); x2 = pop(); x1 = pop(); push(x1 != 0? x2: x3); break; case TKN_MIN: push(Math.min(pop(), pop())); break; case TKN_MAX: push(Math.max(pop(), pop())); break; case TKN_LIMIT: x3 = pop(); x2 = pop(); x1 = pop(); push(x1 < x2 || x1 > x3? Double.NaN: x1); break; case TKN_DUP: push(peek()); break; case TKN_EXC: x2 = pop(); x1 = pop(); push(x2); push(x1); break; case TKN_POP: pop(); break; case TKN_UN: push(Double.isNaN(pop())? 1: 0); break; case TKN_UNKN: push(Double.NaN); break; case TKN_NOW: push(Util.getTime()); break; case TKN_TIME: push(getValue(TIMESTAMP_PLACEHOLDER)); break; case TKN_PI: push(Math.PI); break; case TKN_E: push(Math.E); break; case TKN_AND: x2 = pop(); x1 = pop(); push((x1 != 0 && x2 != 0)? 1: 0); break; case TKN_OR: x2 = pop(); x1 = pop(); push((x1 != 0 || x2 != 0)? 1: 0); break; case TKN_XOR: x2 = pop(); x1 = pop(); push(((x1 != 0 && x2 == 0) || (x1 == 0 && x2 != 0))? 1: 0); break; default: throw new RrdException("Unexpected RPN token encountered [" + token.id + "," + token.str + "]"); } } double retVal = pop(); if(!isStackEmpty()) { throw new RrdException("Stack not empty at the end of calculation. " + "Probably bad RPN expression [" + rpnExpression + "]"); } return retVal; } private double getValue(String varName) throws RrdException { if(values.containsKey(varName)) { return ((Double) values.get(varName)).doubleValue(); } throw new RrdException("Value of variable [" + varName + "] not specified"); } private void push(double x) throws RrdException { stack.push(x); } private double pop() throws RrdException { return stack.pop(); } private double peek() throws RrdException { return stack.peek(); } private void resetStack() { stack.reset(); } private boolean isStackEmpty() { return stack.isEmpty(); } private class RpnStack { private static final int MAX_STACK_SIZE = 1000; private double[] stack = new double[MAX_STACK_SIZE]; private int pos = 0; void push(double x) throws RrdException { if(pos >= MAX_STACK_SIZE) { throw new RrdException("PUSH failed, RPN stack full [" + MAX_STACK_SIZE + "]"); } stack[pos++] = x; } double pop() throws RrdException { if(pos <= 0) { throw new RrdException("POP failed, RPN stack is empty "); } return stack[--pos]; } double peek() throws RrdException { if(pos <= 0) { throw new RrdException("PEEK failed, RPN stack is empty "); } return stack[pos - 1]; } void reset() { pos = 0; } boolean isEmpty() { return pos <= 0; } } private class Token { byte id; String str; double number; Token(String str) { this.str = str; } } /* public static void main(String[] args) throws RrdException { RpnCalculator c = new RpnCalculator("x,y,+,x,y,-,*,SQRT"); c.setValue("x", 5); c.setValue("y", 4); System.out.println(c.calculate()); c.setValue("x", 6); System.out.println(c.calculate()); } */ } --- NEW FILE: DataStats.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * 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.ConsolFuns; import org.jrobin.core.Util; import org.jrobin.core.RrdException; /** * General purpose class which calculate statistics (AVERAGE, MIN, MAX, LAST, FIRST and TOTAL) * for the given array of data values and corresponding timestamps. */ public class DataStats implements ConsolFuns { private long seconds = 0; private double total = 0.0; private double min = Double.NaN, max = Double.NaN; private double last = Double.NaN, first = Double.NaN; /** * Creates statistics for the given array of data values. * * @param times array of timestamps in seconds * @param values array of corresponding data values * @param tStart Time to be used as starting timestamp (in seconds) for statistics calculation * @param tEnd Time to be used as ending timestamp (in seconds) for statistics calculation */ public DataStats(long[] times, double[] values, long tStart, long tEnd) { assert times.length == values.length: "Incompatible time/value array lengths"; assert tStart < tEnd: "Startign timestamp must be less than ending timestamp"; accumulate(tStart, times[0], values[0]); for (int i = 0; i < values.length - 1; i++) { long t1 = Math.max(tStart, times[i]); long t2 = Math.min(tEnd, times[i + 1]); double value = values[i + 1]; accumulate(t1, t2, value); } accumulate(times[times.length - 1], tEnd, Double.NaN); } private boolean firstFound = false; private void accumulate(long t1, long t2, double value) { long dt = t2 - t1; if (dt > 0) { if (!Double.isNaN(value)) { seconds += dt; total += dt * value; } min = Util.min(min, value); max = Util.max(max, value); if (!firstFound) { first = value; firstFound = true; } last = value; } } /** * Returns data TOTAL * * @return TOTAL value */ public double getTotal() { return total; } /** * Returns MIN data value * * @return MIN value */ public double getMin() { return min; } /** * Returns MAX data value * * @return MAX value */ public double getMax() { return max; } /** * Returns LAST data value * * @return LAST value */ public double getLast() { return last; } /** * Returns FIRST data value * * @return FIRST value */ public double getFirst() { return first; } /** * Returns AVERAGE data value * * @return AVERAGE value */ public double getAverage() { return total / (double) seconds; } /** * Returns aggregated data value * * @param consolFun Consolidation function to be used * (AVERAGE, MIN, MAX, LAST, FIRST or TOTAL) * @return Aggregated value * @throws org.jrobin.core.RrdException Thrown if invalid consolidation function is supplied */ public double getAggregate(String consolFun) throws RrdException { if (consolFun.equals(CF_MAX)) { return getMax(); } else if (consolFun.equals(CF_MIN)) { return getMin(); } else if (consolFun.equals(CF_LAST)) { return getLast(); } else if (consolFun.equals(CF_AVERAGE)) { return getAverage(); } else if (consolFun.equals(CF_TOTAL)) { return getTotal(); } else { throw new RrdException("Unsupported consolidation function [" + consolFun + "]"); } } /** * Dumps all aggregated values in a human-readable form. * * @return A string containing all aggregated values. */ public String dump() { return "AVERAGE: " + getAverage() + "\n" + "MIN: " + min + "\n" + "MAX: " + max + "\n" + "LAST: " + last + "\n" + "FIRST: " + first + "\n" + "TOTAL: " + total + "\n" + "SECONDS: " + seconds; } /* public static void main(String[] args) { long[] t = {10, 12, 15, 20}; double[] x = { 1, 2, 5, 3}; long t1 = 11, t2 = 16; DataStats s = new DataStats(t, x, t1, t2); System.out.println(s.dump()); } */ } |
From: Sasa M. <sa...@us...> - 2004-11-21 13:24:04
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13711/org/jrobin/data Log Message: Directory /cvsroot/jrobin/src/org/jrobin/data added to the repository |
From: Sasa M. <sa...@us...> - 2004-11-19 13:44:10
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27170/org/jrobin/core Modified Files: FetchData.java FetchDataStats.java Log Message: Added split() method to the RrdToolkit class to split single RRD file into several new ones. Each new file contains only a single datasource. All archived values are preserved. Index: FetchData.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/FetchData.java,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** FetchData.java 18 Nov 2004 13:27:58 -0000 1.11 --- FetchData.java 19 Nov 2004 13:43:52 -0000 1.12 *************** *** 318,324 **** * @param dsName Datasource name * @param consolFun Consolidation function to be applied to fetched datasource values. ! * Valid consolidation functions are "MIN", "MAX", "LAST", "AVERAGE" and "TOTAL" * (these string constants are conveniently defined in the {@link ConsolFuns} class) ! * @return MIN, MAX, LAST, AVERAGE or TOTAL value calculated from the fetched data * for the given datasource name * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. --- 318,324 ---- * @param dsName 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 fetched data * for the given datasource name * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. *************** *** 337,340 **** --- 337,343 ---- return stats.getLast(); } + else if (consolFun.equals(CF_FIRST)) { + return stats.getFirst(); + } else if (consolFun.equals(CF_AVERAGE)) { return stats.getAverage(); *************** *** 352,356 **** * * @param dsName Datasource name ! * @return Object containing MIN, MAX, LAST, AVERAGE and TOTAL values calculated from the fetched data * for the given datasource name * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. --- 355,359 ---- * * @param dsName Datasource name ! * @return Object containing MIN, MAX, LAST, FIRST, AVERAGE and TOTAL values calculated from the fetched data * for the given datasource name * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. *************** *** 372,376 **** * * @param dsName Datasource name ! * @return Object containing MIN, MAX, LAST, AVERAGE and TOTAL values calculated from the fetched data * for the given datasource name and a given RPN expression * @throws RrdException Thrown if the given datasource name cannot be found in fetched data --- 375,379 ---- * * @param dsName Datasource name ! * @return Object containing MIN, MAX, LAST, FIRST, AVERAGE and TOTAL values calculated from the fetched data * for the given datasource name and a given RPN expression * @throws RrdException Thrown if the given datasource name cannot be found in fetched data *************** *** 379,383 **** double[] values = getValues(dsName); long totalSecs = 0; ! double totalValue = 0.0, min = Double.NaN, max = Double.NaN, last = Double.NaN; RpnCalculator rpnCalculator = null; if (rpnExpression != null) { --- 382,386 ---- double[] values = getValues(dsName); long totalSecs = 0; ! double totalValue = 0.0, min = Double.NaN, max = Double.NaN; RpnCalculator rpnCalculator = null; if (rpnExpression != null) { *************** *** 399,406 **** min = Util.min(min, value); max = Util.max(max, value); - last = value; } FetchDataStats stats = new FetchDataStats(); ! stats.setLast(last); stats.setMax(max); stats.setMin(min); --- 402,409 ---- min = Util.min(min, value); max = Util.max(max, value); } FetchDataStats stats = new FetchDataStats(); ! stats.setFirst(values[1]); ! stats.setLast(values[values.length - 1]); stats.setMax(max); stats.setMin(min); Index: FetchDataStats.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/FetchDataStats.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** FetchDataStats.java 18 Nov 2004 13:27:58 -0000 1.1 --- FetchDataStats.java 19 Nov 2004 13:43:52 -0000 1.2 *************** *** 32,36 **** public class FetchDataStats implements ConsolFuns { private long seconds; ! private double total, min, max, last; FetchDataStats() { --- 32,36 ---- public class FetchDataStats implements ConsolFuns { private long seconds; ! private double total, min, max, last, first; FetchDataStats() { *************** *** 58,61 **** --- 58,65 ---- } + void setFirst(double first) { + this.first = first; + } + /** * Returns TOTAL of the fetched data *************** *** 91,94 **** --- 95,106 ---- /** + * Returns FIRST of the fetched data + * @return FIRST of the fetched data + */ + public double getFirst() { + return first; + } + + /** * Returns AVERAGE of the fetched data * @return AVERAGE of the fetched data *************** *** 135,138 **** --- 147,151 ---- "MAX: " + Util.formatDouble(getMax(), true) + "\n" + "LAST: " + Util.formatDouble(getLast(), true) + "\n" + + "FIRST: " + Util.formatDouble(getFirst(), true) + "\n" + "TOTAL: " + Util.formatDouble(getTotal(), true); } |
From: Sasa M. <sa...@us...> - 2004-11-19 12:00:11
|
Update of /cvsroot/jrobin/src/org/jrobin/demo In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4753/org/jrobin/demo Modified Files: Demo.java Log Message: Added split() method to the RrdToolkit class to split single RRD file into several new ones. Each new file contains only a single datasource. All archived values are preserved. Index: Demo.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/demo/Demo.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Demo.java 5 Nov 2004 12:22:52 -0000 1.3 --- Demo.java 19 Nov 2004 12:00:02 -0000 1.4 *************** *** 1,4 **** - package org.jrobin.demo; - /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality --- 1,2 ---- *************** *** 26,29 **** --- 24,29 ---- */ + package org.jrobin.demo; + import org.jrobin.core.*; import org.jrobin.graph.RrdGraph; *************** *** 38,43 **** class Demo { - // static final String FACTORY_NAME = "NIO"; - static final long SEED = 1909752002L; static final Random RANDOM = new Random(SEED); --- 38,41 ---- *************** *** 49,54 **** public static void main(String[] args) throws RrdException, IOException { - // RrdDb.setDefaultFactory(FACTORY_NAME); - // setup println("== Starting demo"); RrdDb.setLockMode(RrdDb.NO_LOCKS); --- 47,50 ---- *************** *** 137,145 **** FetchData fetchData = request.fetchData(); println("== Data fetched. " + fetchData.getRowCount() + " points obtained"); ! for(int i = 0; i < fetchData.getRowCount(); i++) { ! println(fetchData.getRow(i).dump()); ! } ! println("== Dumping fetch data to XML format"); println(fetchData.exportXml()); println("== Fetch completed"); --- 133,143 ---- FetchData fetchData = request.fetchData(); println("== Data fetched. " + fetchData.getRowCount() + " points obtained"); ! println(fetchData.toString()); ! println("== Dumping fetched data to XML format"); println(fetchData.exportXml()); + println("== Dumping fetch statistics for datasource 'sun'"); + println(fetchData.getStats("sun").dump()); + println("== Dumping fetch statistics for datasource 'shade'"); + println(fetchData.getStats("shade").dump()); println("== Fetch completed"); |
From: Sasa M. <sa...@us...> - 2004-11-19 12:00:11
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4753/org/jrobin/core Modified Files: RrdDb.java RrdDef.java RrdToolkit.java Log Message: Added split() method to the RrdToolkit class to split single RRD file into several new ones. Each new file contains only a single datasource. All archived values are preserved. Index: RrdDef.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDef.java,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** RrdDef.java 21 Sep 2004 08:42:09 -0000 1.17 --- RrdDef.java 19 Nov 2004 12:00:01 -0000 1.18 *************** *** 26,33 **** package org.jrobin.core; ! import java.util.ArrayList; ! import java.util.Date; ! import java.util.GregorianCalendar; ! import java.util.StringTokenizer; import java.io.*; --- 26,30 ---- package org.jrobin.core; ! import java.util.*; import java.io.*; *************** *** 457,460 **** --- 454,467 ---- } + void saveSingleDatasource(String dsName) { + Iterator it = dsDefs.iterator(); + while(it.hasNext()) { + DsDef dsDef = (DsDef) it.next(); + if(!dsDef.getDsName().equals(dsName)) { + it.remove(); + } + } + } + void removeArchive(String consolFun, int steps) throws RrdException { ArcDef arcDef = findArchive(consolFun, steps); *************** *** 615,617 **** --- 622,638 ---- return true; } + + /** + * Removes all datasource definitions. + */ + public void removeDatasources() { + dsDefs.clear(); + } + + /** + * Removes all RRA archive definitions. + */ + public void removeArchives() { + arcDefs.clear(); + } } Index: RrdDb.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDb.java,v retrieving revision 1.33 retrieving revision 1.34 diff -C2 -d -r1.33 -r1.34 *** RrdDb.java 22 Oct 2004 12:30:50 -0000 1.33 --- RrdDb.java 19 Nov 2004 12:00:01 -0000 1.34 *************** *** 1112,1115 **** --- 1112,1131 ---- } + /** + * Returns the number of datasources defined in the file + * @return The number of datasources defined in the file + */ + public int getDsCount() { + return datasources.length; + } + + /** + * Returns the number of RRA arcihves defined in the file + * @return The number of RRA arcihves defined in the file + */ + public int getArcCount() { + return archives.length; + } + public static void main(String[] args) { System.out.println("JRobin Java Library :: RRDTool choice for the Java world"); Index: RrdToolkit.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdToolkit.java,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** RrdToolkit.java 27 Aug 2004 09:42:42 -0000 1.11 --- RrdToolkit.java 19 Nov 2004 12:00:01 -0000 1.12 *************** *** 39,42 **** --- 39,45 ---- * <p>All these operations can be performed on the copy of the original RRD file, or on the * original file itself (with possible backup file creation)</p> + * + * <p><b><u>IMPORTANT</u></b>: NEVER use methods found in this class on 'live' RRD files + * (files which are currently in use).</p> */ public class RrdToolkit { *************** *** 441,444 **** --- 444,469 ---- } } + + public void split(String sourcePath) throws IOException, RrdException { + RrdDb rrdSource = new RrdDb(sourcePath); + String[] dsNames = rrdSource.getDsNames(); + for(int i = 0; i < dsNames.length; i++) { + RrdDef rrdDef = rrdSource.getRrdDef(); + rrdDef.setPath(createSplitPath(dsNames[i], sourcePath)); + rrdDef.saveSingleDatasource(dsNames[i]); + RrdDb rrdDest = new RrdDb(rrdDef); + rrdSource.copyStateTo(rrdDest); + rrdDest.close(); + } + rrdSource.close(); + } + + private String createSplitPath(String dsName, String sourcePath) { + File file = new File(sourcePath); + String newName = dsName + "-" + file.getName(); + String path = file.getAbsolutePath(); + String parentDir = path.substring(0, 1 + path.lastIndexOf(Util.getFileSeparator())); + return parentDir + newName; + } } |
From: Sasa M. <sa...@us...> - 2004-11-18 13:28:07
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv782/org/jrobin/core Modified Files: FetchData.java RpnCalculator.java Util.java Added Files: FetchDataStats.java Log Message: Improved FetchData statistics. Class RpnCalculator is now public - can be used as a general purpose RPN calculation tool. Index: RpnCalculator.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RpnCalculator.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** RpnCalculator.java 20 May 2004 10:29:32 -0000 1.4 --- RpnCalculator.java 18 Nov 2004 13:27:58 -0000 1.5 *************** *** 27,346 **** import java.util.StringTokenizer; ! class RpnCalculator { ! static final String VAR_PLACEHOLDER = "value"; ! private static final byte TOK_VAR = 0; ! private static final byte TOK_NUM = 1; ! private static final byte TOK_PLUS = 2; ! private static final byte TOK_MINUS = 3; ! private static final byte TOK_MULT = 4; ! private static final byte TOK_DIV = 5; ! private static final byte TOK_MOD = 6; ! private static final byte TOK_SIN = 7; ! private static final byte TOK_COS = 8; ! private static final byte TOK_LOG = 9; ! private static final byte TOK_EXP = 10; ! private static final byte TOK_FLOOR = 11; ! private static final byte TOK_CEIL = 12; ! private static final byte TOK_ROUND = 13; ! private static final byte TOK_POW = 14; ! private static final byte TOK_ABS = 15; ! private static final byte TOK_SQRT = 16; ! private static final byte TOK_RANDOM = 17; ! private static final byte TOK_LT = 18; ! private static final byte TOK_LE = 19; ! private static final byte TOK_GT = 20; ! private static final byte TOK_GE = 21; ! private static final byte TOK_EQ = 22; ! private static final byte TOK_IF = 23; ! private static final byte TOK_MIN = 24; ! private static final byte TOK_MAX = 25; ! private static final byte TOK_LIMIT = 26; ! private static final byte TOK_DUP = 27; ! private static final byte TOK_EXC = 28; ! private static final byte TOK_POP = 29; ! private static final byte TOK_UN = 30; ! private static final byte TOK_UNKN = 31; ! // private static final byte TOK_NOW = 32; ! // private static final byte TOK_TIME = 33; ! private static final byte TOK_PI = 34; ! private static final byte TOK_E = 35; ! private static final byte TOK_AND = 36; ! private static final byte TOK_OR = 37; ! private static final byte TOK_XOR = 38; ! private String[] tokens; ! private byte[] tokenCodes; ! private double[] parsedDoubles; private RpnStack stack = new RpnStack(); private String rpnExpression; - private double value; - // private long timestamp; ! RpnCalculator(String rpnExpression) throws RrdException { this.rpnExpression = rpnExpression; createTokens(); } ! void setValue(double value) { ! this.value = value; ! } ! ! /* not supported yet ! public void setTimestamp(long timestamp) { ! this.timestamp = timestamp; ! } ! */ ! ! private void createTokens() throws RrdException { ! StringTokenizer st = new StringTokenizer(rpnExpression, ","); ! int count = st.countTokens(); ! tokens = new String[count]; ! tokenCodes = new byte[count]; ! parsedDoubles = new double[count]; for(int i = 0; st.hasMoreTokens(); i++) { ! String token = st.nextToken(); ! tokens[i] = token; ! byte tokenCode = findTokenCode(token); ! tokenCodes[i] = tokenCode; ! if(tokenCode == TOK_NUM) { ! parsedDoubles[i] = Double.parseDouble(token); ! } } } ! private byte findTokenCode(String token) throws RrdException { ! if(isVariable(token)) { ! return TOK_VAR; ! } ! else if(isNumber(token)) { ! return TOK_NUM; } ! else if(token.equals("+")) { ! return TOK_PLUS; } ! else if(token.equals("-")) { ! return TOK_MINUS; } ! else if(token.equals("*")) { ! return TOK_MULT; } ! else if(token.equals("/")) { ! return TOK_DIV; } ! else if(token.equals("%")) { ! return TOK_MOD; } ! else if(token.equals("SIN")) { ! return TOK_SIN; } ! else if(token.equals("COS")) { ! return TOK_COS; } ! else if(token.equals("LOG")) { ! return TOK_LOG; } ! else if(token.equals("EXP")) { ! return TOK_EXP; } ! else if(token.equals("FLOOR")) { ! return TOK_FLOOR; } ! else if(token.equals("CEIL")) { ! return TOK_CEIL; } ! else if(token.equals("ROUND")) { ! return TOK_ROUND; } ! else if(token.equals("POW")) { ! return TOK_POW; } ! else if(token.equals("ABS")) { ! return TOK_ABS; } ! else if(token.equals("SQRT")) { ! return TOK_SQRT; } ! else if(token.equals("RANDOM")) { ! return TOK_RANDOM; } ! else if(token.equals("LT")) { ! return TOK_LT; } ! else if(token.equals("LE")) { ! return TOK_LE; } ! else if(token.equals("GT")) { ! return TOK_GT; } ! else if(token.equals("GE")) { ! return TOK_GE; } ! else if(token.equals("EQ")) { ! return TOK_EQ; } ! else if(token.equals("IF")) { ! return TOK_IF; } ! else if(token.equals("MIN")) { ! return TOK_MIN; } ! else if(token.equals("MAX")) { ! return TOK_MAX; } ! else if(token.equals("LIMIT")) { ! return TOK_LIMIT; } ! else if(token.equals("DUP")) { ! return TOK_DUP; } ! else if(token.equals("EXC")) { ! return TOK_EXC; } ! else if(token.equals("POP")) { ! return TOK_POP; } ! else if(token.equals("UN")) { ! return TOK_UN; } ! else if(token.equals("UNKN")) { ! return TOK_UNKN; } ! ! /* not supported yet ! else if(token.equals("NOW")) { ! return TOK_NOW; } ! else if(token.equals("TIME")) { ! return TOK_TIME; } ! */ ! else if(token.equals("PI")) { ! return TOK_PI; } ! else if(token.equals("E")) { ! return TOK_E; } ! else if(token.equals("AND")) { ! return TOK_AND; } ! else if(token.equals("OR")) { ! return TOK_OR; } ! else if(token.equals("XOR")) { ! return TOK_XOR; } else { ! throw new RrdException("Unknown RPN token encountered: " + token); } } ! private static boolean isNumber(String token) { ! try { ! Double.parseDouble(token); ! return true; ! } ! catch(NumberFormatException nfe) { ! return false; ! } } ! private static boolean isVariable(String token) { ! return token.equals(VAR_PLACEHOLDER); } ! double calculate() throws RrdException { ! resetCalculator(); ! for(int i = 0; i < tokenCodes.length; i++) { ! byte tokenCode = tokenCodes[i]; double x1, x2, x3; ! switch(tokenCode) { ! case TOK_NUM: ! push(parsedDoubles[i]); break; ! case TOK_VAR: ! push(value); break; ! case TOK_PLUS: ! push(pop() + pop()); break; ! case TOK_MINUS: ! x2 = pop(); x1 = pop(); push(x1 - x2); break; ! case TOK_MULT: ! push(pop() * pop()); break; ! case TOK_DIV: ! x2 = pop(); x1 = pop(); push(x1 / x2); break; ! case TOK_MOD: ! x2 = pop(); x1 = pop(); push(x1 % x2); break; ! case TOK_SIN: ! push(Math.sin(pop())); break; ! case TOK_COS: ! push(Math.cos(pop())); break; ! case TOK_LOG: ! push(Math.log(pop())); break; ! case TOK_EXP: ! push(Math.exp(pop())); break; ! case TOK_FLOOR: ! push(Math.floor(pop())); break; ! case TOK_CEIL: ! push(Math.ceil(pop())); break; ! case TOK_ROUND: ! push(Math.round(pop())); break; ! case TOK_POW: ! x2 = pop(); x1 = pop(); push(Math.pow(x1, x2)); break; ! case TOK_ABS: ! push(Math.abs(pop())); break; ! case TOK_SQRT: ! push(Math.sqrt(pop())); break; ! case TOK_RANDOM: ! push(Math.random()); break; ! case TOK_LT: ! x2 = pop(); x1 = pop(); push(x1 < x2? 1: 0); break; ! case TOK_LE: ! x2 = pop(); x1 = pop(); push(x1 <= x2? 1: 0); break; ! case TOK_GT: ! x2 = pop(); x1 = pop(); push(x1 > x2? 1: 0); break; ! case TOK_GE: ! x2 = pop(); x1 = pop(); push(x1 >= x2? 1: 0); break; ! case TOK_EQ: ! x2 = pop(); x1 = pop(); push(x1 == x2? 1: 0); break; ! case TOK_IF: ! x3 = pop(); x2 = pop(); x1 = pop(); push(x1 != 0? x2: x3); break; ! case TOK_MIN: ! push(Math.min(pop(), pop())); break; ! case TOK_MAX: ! push(Math.max(pop(), pop())); break; ! case TOK_LIMIT: x3 = pop(); x2 = pop(); x1 = pop(); ! push(x1 < x2 || x1 > x3? Double.NaN: x1); break; ! case TOK_DUP: ! x1 = pop(); push(x1); push(x1); break; ! case TOK_EXC: ! x2 = pop(); x1 = pop(); push(x2); push(x1); break; ! case TOK_POP: ! pop(); break; ! case TOK_UN: ! push(Double.isNaN(pop())? 1: 0); break; ! case TOK_UNKN: ! push(Double.NaN); break; ! /* not supported yet ! case TOK_NOW: ! push(Util.getTime()); break; ! case TOK_TIME: ! push(timestamp); break; ! */ ! case TOK_PI: ! push(Math.PI); break; ! case TOK_E: ! push(Math.E); break; ! case TOK_AND: ! x2 = pop(); x1 = pop(); push((x1 != 0 && x2 != 0)? 1: 0); break; ! case TOK_OR: ! x2 = pop(); x1 = pop(); push((x1 != 0 || x2 != 0)? 1: 0); break; ! case TOK_XOR: x2 = pop(); x1 = pop(); ! push(((x1 != 0 && x2 == 0) || (x1 == 0 && x2 != 0))? 1: 0); break; default: throw new RrdException("Unexpected RPN token encountered [" + ! tokenCode + "]"); } } --- 27,437 ---- import java.util.StringTokenizer; + import java.util.Map; + import java.util.HashMap; ! /** ! * Class which implements simple RPN calculator (RRDTool-like). <p> ! * To calculate the value of expression: ! * <pre> ! * square_root[(x + y) * (x-y)] ! * </pre> ! * for <code>x=5, y=4</code>, than for <code>x=6, y=4</code>, use the following code: ! * <pre> ! * RpnCalculator c = new RpnCalculator("x,y,+,x,y,-,*,SQRT"); ! * c.setValue("x", 5); ! * c.setValue("y", 4); ! * System.out.println(c.calculate()); ! * // change the value of "x", and leave "y" as before ! * c.setValue("x", 6); ! * System.out.println(c.calculate()); ! * </pre> ! * Notes:<p> ! * <ul> ! * <li>If you call the {@link #setValue(double)} method with just one double argument, ! * it will set the value of variable named "value" by default. ! * <li>The method {@link #setTimestamp(long)} will set the value of variable "timestamp". ! * This special variable can be referenced in the RPN expression by using the token TIME. ! * <li>Once set, variable values remain preserved between consecutive {@link #calculate()} calls. You can overwrite ! * this values by calling the {@link #setValue(String, double)} method again. To get rid of all variable values, ! * use method {@link #clearValues()}. ! * </ul> ! * ! */ ! public class RpnCalculator { ! /** Default variable name for the {@link #setValue(double)} method ("value") */ ! public static final String VALUE_PLACEHOLDER = "value"; ! /** Default variable name for the {@link #setTimestamp(long)} method ("timestamp") */ ! public static final String TIMESTAMP_PLACEHOLDER = "timestamp"; ! private static final byte TKN_VAR = 0; ! private static final byte TKN_NUM = 1; ! private static final byte TKN_PLUS = 2; ! private static final byte TKN_MINUS = 3; ! private static final byte TKN_MULT = 4; ! private static final byte TKN_DIV = 5; ! private static final byte TKN_MOD = 6; ! private static final byte TKN_SIN = 7; ! private static final byte TKN_COS = 8; ! private static final byte TKN_LOG = 9; ! private static final byte TKN_EXP = 10; ! private static final byte TKN_FLOOR = 11; ! private static final byte TKN_CEIL = 12; ! private static final byte TKN_ROUND = 13; ! private static final byte TKN_POW = 14; ! private static final byte TKN_ABS = 15; ! private static final byte TKN_SQRT = 16; ! private static final byte TKN_RANDOM = 17; ! private static final byte TKN_LT = 18; ! private static final byte TKN_LE = 19; ! private static final byte TKN_GT = 20; ! private static final byte TKN_GE = 21; ! private static final byte TKN_EQ = 22; ! private static final byte TKN_IF = 23; ! private static final byte TKN_MIN = 24; ! private static final byte TKN_MAX = 25; ! private static final byte TKN_LIMIT = 26; ! private static final byte TKN_DUP = 27; ! private static final byte TKN_EXC = 28; ! private static final byte TKN_POP = 29; ! private static final byte TKN_UN = 30; ! private static final byte TKN_UNKN = 31; ! private static final byte TKN_NOW = 32; ! private static final byte TKN_TIME = 33; ! private static final byte TKN_PI = 34; ! private static final byte TKN_E = 35; ! private static final byte TKN_AND = 36; ! private static final byte TKN_OR = 37; ! private static final byte TKN_XOR = 38; ! private Map values = new HashMap(); ! private Token[] tokens; private RpnStack stack = new RpnStack(); private String rpnExpression; ! /** ! * Creates new RpnCalculator. RpnCalculator objects may be safely reused to calculate as many ! * expression values (for different variable values) as needed. ! * @param rpnExpression RPN expression to be used. RPN tokens should be comma (",") ! * or space (" ") delimited. ! */ ! public RpnCalculator(String rpnExpression) { this.rpnExpression = rpnExpression; createTokens(); } ! private void createTokens() { ! StringTokenizer st = new StringTokenizer(rpnExpression, ", "); ! tokens = new Token[st.countTokens()]; for(int i = 0; st.hasMoreTokens(); i++) { ! tokens[i] = createToken(st.nextToken()); } } ! private Token createToken(String str) { ! Token token = new Token(str); ! if(Util.isDouble(str)) { ! token.id = TKN_NUM; ! token.number = Util.parseDouble(str); } ! else if(str.equals("+")) { ! token.id = TKN_PLUS; } ! else if(str.equals("-")) { ! token.id = TKN_MINUS; } ! else if(str.equals("*")) { ! token.id = TKN_MULT; } ! else if(str.equals("/")) { ! token.id = TKN_DIV; } ! else if(str.equals("%")) { ! token.id = TKN_MOD; } ! else if(str.equals("SIN")) { ! token.id = TKN_SIN; } ! else if(str.equals("COS")) { ! token.id = TKN_COS; } ! else if(str.equals("LOG")) { ! token.id = TKN_LOG; } ! else if(str.equals("EXP")) { ! token.id = TKN_EXP; } ! else if(str.equals("FLOOR")) { ! token.id = TKN_FLOOR; } ! else if(str.equals("CEIL")) { ! token.id = TKN_CEIL; } ! else if(str.equals("ROUND")) { ! token.id = TKN_ROUND; } ! else if(str.equals("POW")) { ! token.id = TKN_POW; } ! else if(str.equals("ABS")) { ! token.id = TKN_ABS; } ! else if(str.equals("SQRT")) { ! token.id = TKN_SQRT; } ! else if(str.equals("RANDOM")) { ! token.id = TKN_RANDOM; } ! else if(str.equals("LT")) { ! token.id = TKN_LT; } ! else if(str.equals("LE")) { ! token.id = TKN_LE; } ! else if(str.equals("GT")) { ! token.id = TKN_GT; } ! else if(str.equals("GE")) { ! token.id = TKN_GE; } ! else if(str.equals("EQ")) { ! token.id = TKN_EQ; } ! else if(str.equals("IF")) { ! token.id = TKN_IF; } ! else if(str.equals("MIN")) { ! token.id = TKN_MIN; } ! else if(str.equals("MAX")) { ! token.id = TKN_MAX; } ! else if(str.equals("LIMIT")) { ! token.id = TKN_LIMIT; } ! else if(str.equals("DUP")) { ! token.id = TKN_DUP; } ! else if(str.equals("EXC")) { ! token.id = TKN_EXC; } ! else if(str.equals("POP")) { ! token.id = TKN_POP; } ! else if(str.equals("UN")) { ! token.id = TKN_UN; } ! else if(str.equals("UNKN")) { ! token.id = TKN_UNKN; } ! else if(str.equals("NOW")) { ! token.id = TKN_NOW; } ! else if(str.equals("TIME")) { ! token.id = TKN_TIME; } ! else if(str.equals("PI")) { ! token.id = TKN_PI; } ! else if(str.equals("E")) { ! token.id = TKN_E; } ! else if(str.equals("AND")) { ! token.id = TKN_AND; } ! else if(str.equals("OR")) { ! token.id = TKN_OR; } ! else if(str.equals("XOR")) { ! token.id = TKN_XOR; } else { ! token.id = TKN_VAR; } + return token; } ! /** ! * Sets the value for the default variable if RPN expression ("value"). ! * @param value Value to be used in calculation ! */ ! public void setValue(double value) { ! setValue(VALUE_PLACEHOLDER, value); } ! /** ! * Sets the timestamp to be used in evaluation of the RPN expression. To use this ! * value in the RPN expression, use token TIME. ! * @param timestamp The value which will be used if token TIME is found in the RPN expression ! */ ! public void setTimestamp(long timestamp) { ! setValue(TIMESTAMP_PLACEHOLDER, timestamp); } ! /** ! * Sets new value for a variable in the RPN expression. ! * @param name Variable name ! * @param value Variable value ! */ ! public void setValue(String name, double value) { ! values.put(name, new Double(value)); ! } ! ! /** ! * Clears all values specified for variables in the RPN expression ! */ ! public void clearValues() { ! values.clear(); ! } ! ! /** ! * Evaluates RPN expression, by replacing variable placeholders with specified values. You are free ! * to call this method as many times as needed, with the same or modified variable values. ! * @return The value of the RPN expression ! * @throws RrdException Thrown if some variable values are not specified before this method is called, or if the ! * RPN expression is not valid. ! */ ! public double calculate() throws RrdException { ! resetStack(); ! for(int i = 0; i < tokens.length; i++) { ! Token token = tokens[i]; double x1, x2, x3; ! switch(token.id) { ! case TKN_NUM: ! push(token.number); ! break; ! case TKN_VAR: ! push(getValue(token.str)); ! break; ! case TKN_PLUS: ! push(pop() + pop()); ! break; ! case TKN_MINUS: ! x2 = pop(); x1 = pop(); ! push(x1 - x2); ! break; ! case TKN_MULT: ! push(pop() * pop()); ! break; ! case TKN_DIV: ! x2 = pop(); x1 = pop(); ! push(x1 / x2); ! break; ! case TKN_MOD: ! x2 = pop(); x1 = pop(); ! push(x1 % x2); ! break; ! case TKN_SIN: ! push(Math.sin(pop())); ! break; ! case TKN_COS: ! push(Math.cos(pop())); ! break; ! case TKN_LOG: ! push(Math.log(pop())); ! break; ! case TKN_EXP: ! push(Math.exp(pop())); ! break; ! case TKN_FLOOR: ! push(Math.floor(pop())); ! break; ! case TKN_CEIL: ! push(Math.ceil(pop())); ! break; ! case TKN_ROUND: ! push(Math.round(pop())); ! break; ! case TKN_POW: ! x2 = pop(); x1 = pop(); ! push(Math.pow(x1, x2)); ! break; ! case TKN_ABS: ! push(Math.abs(pop())); ! break; ! case TKN_SQRT: ! push(Math.sqrt(pop())); ! break; ! case TKN_RANDOM: ! push(Math.random()); ! break; ! case TKN_LT: ! x2 = pop(); x1 = pop(); ! push(x1 < x2? 1: 0); ! break; ! case TKN_LE: ! x2 = pop(); x1 = pop(); ! push(x1 <= x2? 1: 0); ! break; ! case TKN_GT: ! x2 = pop(); x1 = pop(); ! push(x1 > x2? 1: 0); ! break; ! case TKN_GE: ! x2 = pop(); x1 = pop(); ! push(x1 >= x2? 1: 0); ! break; ! case TKN_EQ: ! x2 = pop(); x1 = pop(); ! push(x1 == x2? 1: 0); ! break; ! case TKN_IF: x3 = pop(); x2 = pop(); x1 = pop(); ! push(x1 != 0? x2: x3); ! break; ! case TKN_MIN: ! push(Math.min(pop(), pop())); ! break; ! case TKN_MAX: ! push(Math.max(pop(), pop())); ! break; ! case TKN_LIMIT: ! x3 = pop(); x2 = pop(); x1 = pop(); ! push(x1 < x2 || x1 > x3? Double.NaN: x1); ! break; ! case TKN_DUP: ! push(peek()); ! break; ! case TKN_EXC: x2 = pop(); x1 = pop(); ! push(x2); ! push(x1); ! break; ! case TKN_POP: ! pop(); ! break; ! case TKN_UN: ! push(Double.isNaN(pop())? 1: 0); ! break; ! case TKN_UNKN: ! push(Double.NaN); ! break; ! case TKN_NOW: ! push(Util.getTime()); ! break; ! case TKN_TIME: ! push(getValue(TIMESTAMP_PLACEHOLDER)); ! break; ! case TKN_PI: ! push(Math.PI); ! break; ! case TKN_E: ! push(Math.E); ! break; ! case TKN_AND: ! x2 = pop(); x1 = pop(); ! push((x1 != 0 && x2 != 0)? 1: 0); ! break; ! case TKN_OR: ! x2 = pop(); x1 = pop(); ! push((x1 != 0 || x2 != 0)? 1: 0); ! break; ! case TKN_XOR: ! x2 = pop(); x1 = pop(); ! push(((x1 != 0 && x2 == 0) || (x1 == 0 && x2 != 0))? 1: 0); ! break; default: throw new RrdException("Unexpected RPN token encountered [" + ! token.id + "," + token.str + "]"); } } *************** *** 348,374 **** if(!isStackEmpty()) { throw new RrdException("Stack not empty at the end of calculation. " + ! "Probably bad RPN expression"); } return retVal; } ! void push(double x) throws RrdException { stack.push(x); } ! double pop() throws RrdException { return stack.pop(); } ! void resetCalculator() { stack.reset(); } ! boolean isStackEmpty() { return stack.isEmpty(); } ! class RpnStack { ! static final int MAX_STACK_SIZE = 1000; private double[] stack = new double[MAX_STACK_SIZE]; private int pos = 0; --- 439,476 ---- if(!isStackEmpty()) { throw new RrdException("Stack not empty at the end of calculation. " + ! "Probably bad RPN expression [" + rpnExpression + "]"); } return retVal; } ! private double getValue(String varName) throws RrdException { ! if(values.containsKey(varName)) { ! return ((Double) values.get(varName)).doubleValue(); ! } ! throw new RrdException("Value of variable [" + varName + "] not specified"); ! } ! ! private void push(double x) throws RrdException { stack.push(x); } ! private double pop() throws RrdException { return stack.pop(); } ! private double peek() throws RrdException { ! return stack.peek(); ! } ! ! private void resetStack() { stack.reset(); } ! private boolean isStackEmpty() { return stack.isEmpty(); } ! private class RpnStack { ! private static final int MAX_STACK_SIZE = 1000; private double[] stack = new double[MAX_STACK_SIZE]; private int pos = 0; *************** *** 376,381 **** void push(double x) throws RrdException { if(pos >= MAX_STACK_SIZE) { ! throw new RrdException( ! "PUSH failed, RPN stack full [" + MAX_STACK_SIZE + "]"); } stack[pos++] = x; --- 478,482 ---- void push(double x) throws RrdException { if(pos >= MAX_STACK_SIZE) { ! throw new RrdException("PUSH failed, RPN stack full [" + MAX_STACK_SIZE + "]"); } stack[pos++] = x; *************** *** 389,392 **** --- 490,500 ---- } + double peek() throws RrdException { + if(pos <= 0) { + throw new RrdException("PEEK failed, RPN stack is empty "); + } + return stack[pos - 1]; + } + void reset() { pos = 0; *************** *** 394,407 **** boolean isEmpty() { ! return pos == 0; } } ! /* public static void main(String[] args) throws RrdException { ! RpnCalculator c = new RpnCalculator("2,3,/,value,+"); ! c.setValue(5); System.out.println(c.calculate()); } - */ } --- 502,527 ---- boolean isEmpty() { ! return pos <= 0; } } ! private class Token { ! byte id; ! String str; ! double number; ! ! Token(String str) { ! this.str = str; ! } ! } ! ! /** Just a small, trivial demo */ public static void main(String[] args) throws RrdException { ! RpnCalculator c = new RpnCalculator("x,y,+,x,y,-,*,SQRT"); ! c.setValue("x", 5); ! c.setValue("y", 4); ! System.out.println(c.calculate()); ! c.setValue("x", 6); System.out.println(c.calculate()); } } Index: FetchData.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/FetchData.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** FetchData.java 21 Sep 2004 08:42:09 -0000 1.10 --- FetchData.java 18 Nov 2004 13:27:58 -0000 1.11 *************** *** 53,56 **** --- 53,58 ---- * all values for the i-th datasource. Returned datasource values correspond to * the values returned with {@link #getTimestamps() getTimestamps()} method.<p> + * + * Use {@link #getStats(String, String)} method to calculate aggregates for the fetched data<p> */ public class FetchData implements RrdDataSet, ConsolFuns { *************** *** 64,68 **** this.matchingArchive = matchingArchive; this.dsNames = request.getFilter(); ! if(this.dsNames == null) { this.dsNames = matchingArchive.getParentDb().getDsNames(); } --- 66,70 ---- this.matchingArchive = matchingArchive; this.dsNames = request.getFilter(); ! if (this.dsNames == null) { this.dsNames = matchingArchive.getParentDb().getDsNames(); } *************** *** 81,94 **** * Returns the number of rows fetched from the corresponding RRD. * Each row represents datasource values for the specific timestamp. * @return Number of rows. */ ! public int getRowCount() { return timestamps.length; } ! /** * Returns the number of columns fetched from the corresponding RRD. * This number is always equal to the number of datasources defined * in the RRD. Each column represents values of a single datasource. * @return Number of columns (datasources). */ --- 83,98 ---- * Returns the number of rows fetched from the corresponding RRD. * Each row represents datasource values for the specific timestamp. + * * @return Number of rows. */ ! public int getRowCount() { return timestamps.length; } ! /** * Returns the number of columns fetched from the corresponding RRD. * This number is always equal to the number of datasources defined * in the RRD. Each column represents values of a single datasource. + * * @return Number of columns (datasources). */ *************** *** 100,111 **** * Returns the number of rows fetched from the corresponding RRD. * Each row represents datasource values for the specific timestamp. * @param rowIndex Row index. * @return FetchPoint object which represents datasource values for the ! * specific timestamp. */ public FetchPoint getRow(int rowIndex) { int numCols = getColumnCount(); FetchPoint point = new FetchPoint(timestamps[rowIndex], getColumnCount()); ! for(int dsIndex = 0; dsIndex < numCols; dsIndex++) { point.setValue(dsIndex, values[dsIndex][rowIndex]); } --- 104,117 ---- * Returns the number of rows fetched from the corresponding RRD. * Each row represents datasource values for the specific timestamp. + * * @param rowIndex Row index. * @return FetchPoint object which represents datasource values for the ! * specific timestamp. ! * @deprecated The usage of FetchPoint object is deprecated. */ public FetchPoint getRow(int rowIndex) { int numCols = getColumnCount(); FetchPoint point = new FetchPoint(timestamps[rowIndex], getColumnCount()); ! for (int dsIndex = 0; dsIndex < numCols; dsIndex++) { point.setValue(dsIndex, values[dsIndex][rowIndex]); } *************** *** 116,119 **** --- 122,126 ---- * Returns an array of timestamps covering the whole range specified in the * {@link FetchRequest FetchReguest} object. + * * @return Array of equidistant timestamps. */ *************** *** 124,127 **** --- 131,135 ---- /** * Returns the step with which this data was fetched. + * * @return Step as long. */ *************** *** 134,137 **** --- 142,146 ---- * Returned values correspond to timestamps * returned with {@link #getTimestamps() getTimestamps()} method. + * * @param dsIndex Datasource index. * @return Array of single datasource values. *************** *** 145,148 **** --- 154,158 ---- * Returned values correspond to timestamps * returned with {@link #getTimestamps() getTimestamps()} method. + * * @return Two-dimensional aray of all datasource values. */ *************** *** 150,158 **** return values; } ! /** * Returns all archived values for a single datasource. * Returned values correspond to timestamps * returned with {@link #getTimestamps() getTimestamps()} method. * @param dsName Datasource name. * @return Array of single datasource values. --- 160,169 ---- return values; } ! /** * Returns all archived values for a single datasource. * Returned values correspond to timestamps * returned with {@link #getTimestamps() getTimestamps()} method. + * * @param dsName Datasource name. * @return Array of single datasource values. *************** *** 160,165 **** */ public double[] getValues(String dsName) throws RrdException { ! for(int dsIndex = 0; dsIndex < getColumnCount(); dsIndex++) { ! if(dsName.equals(dsNames[dsIndex])) { return getValues(dsIndex); } --- 171,176 ---- */ public double[] getValues(String dsName) throws RrdException { ! for (int dsIndex = 0; dsIndex < getColumnCount(); dsIndex++) { ! if (dsName.equals(dsNames[dsIndex])) { return getValues(dsIndex); } *************** *** 170,173 **** --- 181,185 ---- /** * Returns {@link FetchRequest FetchRequest} object used to create this FetchData object. + * * @return Fetch request object. */ *************** *** 176,181 **** } ! /** * Returns the first timestamp in this FetchData object. * @return The smallest timestamp. */ --- 188,194 ---- } ! /** * Returns the first timestamp in this FetchData object. + * * @return The smallest timestamp. */ *************** *** 186,189 **** --- 199,203 ---- /** * Returns the last timestamp in this FecthData object. + * * @return The biggest timestamp. */ *************** *** 196,199 **** --- 210,214 ---- * timestamps specified in the fetch request. All datasource values are obtained * from round robin archives belonging to this archive. + * * @return Matching archive. */ *************** *** 206,209 **** --- 221,225 ---- * was filtered (data was fetched only for selected datasources), only datasources selected * for fetching are returned. + * * @return Array of datasource names. */ *************** *** 211,217 **** return dsNames; } ! /** * Retrieve the table index number of a datasource by name. Names are case sensitive. * @param dsName Name of the datasource for which to find the index. * @return Index number of the datasources in the value table. --- 227,234 ---- return dsNames; } ! /** * Retrieve the table index number of a datasource by name. Names are case sensitive. + * * @param dsName Name of the datasource for which to find the index. * @return Index number of the datasources in the value table. *************** *** 219,226 **** public int getDsIndex(String dsName) { // Let's assume the table of dsNames is always small, so it is not necessary to use a hashmap for lookups ! for (int i = 0; i < dsNames.length; i++) ! if ( dsNames[i].equals(dsName) ) return i; ! return -1; // Datasource not found ! } --- 236,244 ---- public int getDsIndex(String dsName) { // Let's assume the table of dsNames is always small, so it is not necessary to use a hashmap for lookups ! for (int i = 0; i < dsNames.length; i++) { ! if (dsNames[i].equals(dsName)) { return i; ! } ! } return -1; // Datasource not found ! } *************** *** 230,234 **** */ public void dump() { ! for(int i = 0; i < getRowCount(); i++) { System.out.println(getRow(i).dump()); } --- 248,252 ---- */ public void dump() { ! for (int i = 0; i < getRowCount(); i++) { System.out.println(getRow(i).dump()); } *************** *** 237,240 **** --- 255,259 ---- /** * Returns string representing fetched data in a RRDTool-like form. + * * @return Fetched data as a string in a rrdfetch-like output form. */ *************** *** 245,258 **** buff.append(padWithBlanks("", 10)); buff.append(" "); ! for(int i = 0; i < dsNames.length; i++) { buff.append(padWithBlanks(dsNames[i], 18)); } buff.append("\n \n"); ! for(int i = 0; i < timestamps.length; i++) { buff.append(padWithBlanks("" + timestamps[i], 10)); buff.append(":"); ! for(int j = 0; j < dsNames.length; j++) { double value = values[j][i]; ! String valueStr = Double.isNaN(value)? "nan": df.format(value); buff.append(padWithBlanks(valueStr, 18)); } --- 264,277 ---- buff.append(padWithBlanks("", 10)); buff.append(" "); ! for (int i = 0; i < dsNames.length; i++) { buff.append(padWithBlanks(dsNames[i], 18)); } buff.append("\n \n"); ! for (int i = 0; i < timestamps.length; i++) { buff.append(padWithBlanks("" + timestamps[i], 10)); buff.append(":"); ! for (int j = 0; j < dsNames.length; j++) { double value = values[j][i]; ! String valueStr = Double.isNaN(value) ? "nan" : df.format(value); buff.append(padWithBlanks(valueStr, 18)); } *************** *** 265,269 **** StringBuffer buff = new StringBuffer(""); int diff = width - input.length(); ! while(diff-- > 0) { buff.append(' '); } --- 284,288 ---- StringBuffer buff = new StringBuffer(""); int diff = width - input.length(); ! while (diff-- > 0) { buff.append(' '); } *************** *** 274,284 **** /** * Returns aggregated value from the fetched data for a single datasource. ! * @param dsName Datasource name * @param consolFun Consolidation function to be applied to fetched datasource values. ! * Valid consolidation functions are "MIN", "MAX", "LAST" and "AVERAGE" ! * (these string constants are conveniently defined in the {@link ConsolFuns} class). * @return MIN, MAX, LAST or AVERAGE value calculated from the fetched data ! * for the given datasource name * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. */ public double getAggregate(String dsName, String consolFun) throws RrdException { --- 293,305 ---- /** * Returns aggregated value from the fetched data for a single datasource. ! * ! * @param dsName Datasource name * @param consolFun Consolidation function to be applied to fetched datasource values. ! * Valid consolidation functions are "MIN", "MAX", "LAST" and "AVERAGE" ! * (these string constants are conveniently defined in the {@link ConsolFuns} class). * @return MIN, MAX, LAST or AVERAGE value calculated from the fetched data ! * for the given datasource name * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. + * @deprecated Use {@link #getStats(String) getStats(dsName)} method instead. */ public double getAggregate(String dsName, String consolFun) throws RrdException { *************** *** 289,318 **** * Returns aggregated value from the fetched data for a single datasource. * Before applying aggrregation functions, specified RPN expression is applied to fetched ! * data. For example, if you have a GAUGE datasource named 'foots' but you wont to * find the maximum fetched value in meters use something like:</p> ! * <code>getAggregate("foots", ConsolFuns.MAX, "value,0.3048,*");</code> * Note that 'value' in the RPN expression is a reserved word and stands for the ! * original value (value fetched from RRD)</p> ! * @param dsName Datasource name * @param consolFun Consolidation function to be applied to fetched datasource values. ! * Valid consolidation functions are "MIN", "MAX", "LAST" and "AVERAGE" ! * (these string constants are conveniently defined in the {@link ConsolFuns} class) ! * @return MIN, MAX, LAST or AVERAGE value calculated from the fetched data ! * for the given datasource name * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. */ public double getAggregate(String dsName, String consolFun, String rpnExpression) ! throws RrdException { ! if(consolFun.equals(CF_MAX)) { ! return getMax(dsName, rpnExpression); } ! else if(consolFun.equals(CF_MIN)) { ! return getMin(dsName, rpnExpression); } ! else if(consolFun.equals(CF_LAST)) { ! return getLast(dsName, rpnExpression); } ! else if(consolFun.equals(CF_AVERAGE)) { ! return getAverage(dsName, rpnExpression); } else { --- 310,345 ---- * Returns aggregated value from the fetched data for a single datasource. * Before applying aggrregation functions, specified RPN expression is applied to fetched ! * data. For example, if you have a GAUGE datasource named 'feet' but you want to * find the maximum fetched value in meters use something like:</p> ! * <code>getAggregate("feet", ConsolFuns.MAX, "value,0.3048,*");</code> * Note that 'value' in the RPN expression is a reserved word and stands for the ! * original value (value fetched from the RRD)</p> ! * ! * @param dsName Datasource name * @param consolFun Consolidation function to be applied to fetched datasource values. ! * Valid consolidation functions are "MIN", "MAX", "LAST", "AVERAGE" and "TOTAL" ! * (these string constants are conveniently defined in the {@link ConsolFuns} class) ! * @return MIN, MAX, LAST, AVERAGE or TOTAL value calculated from the fetched data ! * for the given datasource name * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. + * @deprecated Use {@link #getStats(String, String) getStats(dsName, rpnExpression)} method instead. */ public double getAggregate(String dsName, String consolFun, String rpnExpression) ! throws RrdException { ! FetchDataStats stats = getStats(dsName, rpnExpression); ! if (consolFun.equals(CF_MAX)) { ! return stats.getMax(); } ! else if (consolFun.equals(CF_MIN)) { ! return stats.getMin(); } ! else if (consolFun.equals(CF_LAST)) { ! return stats.getLast(); } ! else if (consolFun.equals(CF_AVERAGE)) { ! return stats.getAverage(); ! } ! else if (consolFun.equals(CF_TOTAL)) { ! return stats.getTotal(); } else { *************** *** 321,398 **** } ! private double getMax(String dsName, String rpnExpression) throws RrdException { ! RpnCalculator rpnCalculator = null; ! if(rpnExpression != null) { ! rpnCalculator = new RpnCalculator(rpnExpression); ! } ! double vals[] = getValues(dsName), max = Double.NaN; ! for(int i = 0; i < vals.length - 1; i++) { ! double value = vals[i + 1]; ! if(rpnCalculator != null) { ! rpnCalculator.setValue(value); ! value = rpnCalculator.calculate(); ! } ! max = Util.max(max, value); ! } ! return max; ! } ! ! private double getMin(String dsName, String rpnExpression) throws RrdException { ! RpnCalculator rpnCalculator = null; ! if(rpnExpression != null) { ! rpnCalculator = new RpnCalculator(rpnExpression); ! } ! double vals[] = getValues(dsName), min = Double.NaN; ! for(int i = 0; i < vals.length - 1; i++) { ! double value = vals[i + 1]; ! if(rpnCalculator != null) { ! rpnCalculator.setValue(value); ! value = rpnCalculator.calculate(); ! } ! min = Util.min(min, value); ! } ! return min; ! } ! ! private double getLast(String dsName, String rpnExpression) throws RrdException { ! RpnCalculator rpnCalculator = null; ! if(rpnExpression != null) { ! rpnCalculator = new RpnCalculator(rpnExpression); ! } ! double vals[] = getValues(dsName); ! double value = vals[vals.length - 1]; ! if(rpnCalculator != null) { ! rpnCalculator.setValue(value); ! value = rpnCalculator.calculate(); ! } ! return value; } ! private double getAverage(String dsName, String rpnExpression) throws RrdException { RpnCalculator rpnCalculator = null; ! if(rpnExpression != null) { rpnCalculator = new RpnCalculator(rpnExpression); } ! double vals[] = getValues(dsName); ! double totalVal = 0; ! long totalSecs = 0; ! for(int i = 0; i < vals.length - 1; i++) { long t1 = Math.max(request.getFetchStart(), timestamps[i]); long t2 = Math.min(request.getFetchEnd(), timestamps[i + 1]); ! double value = vals[i + 1]; ! if(rpnCalculator != null) { rpnCalculator.setValue(value); value = rpnCalculator.calculate(); } ! if(!Double.isNaN(value)) { ! totalSecs += (t2 - t1); ! totalVal += (t2 - t1) * value; } } ! return totalSecs > 0? totalVal / totalSecs: Double.NaN; } /** * Dumps fetch data to output stream in XML format. * @param outputStream Output stream to dump fetch data to * @throws IOException Thrown in case of I/O error --- 348,416 ---- } ! /** ! * Returns all aggregated values from the fetched data for a single datasource. ! * ! * @param dsName Datasource name ! * @return Object containing MIN, MAX, LAST, AVERAGE and TOTAL values calculated from the fetched data ! * for the given datasource name ! * @throws RrdException Thrown if the given datasource name cannot be found in fetched data. ! */ ! public FetchDataStats getStats(String dsName) throws RrdException { ! return getStats(dsName, null); } ! /** ! * Returns all aggregated values from the fetched data for a single datasource. ! * Before applying aggrregation functions, specified RPN expression is applied to fetched ! * data. For example, if you have a GAUGE datasource named 'feet' but you want to ! * calculate aggregates in meters use something like:<p> ! * <pre> ! * getStats("feet", "value,0.3048,*"); ! * </pre> ! * Note that the placeholder 'value' in the RPN expression is a reserved word and stands for the ! * original value (value fetched from the RRD) ! * ! * @param dsName Datasource name ! * @return Object containing MIN, MAX, LAST, AVERAGE and TOTAL values calculated from the fetched data ! * for the given datasource name and a given RPN expression ! * @throws RrdException Thrown if the given datasource name cannot be found in fetched data ! */ ! public FetchDataStats getStats(String dsName, String rpnExpression) throws RrdException { ! double[] values = getValues(dsName); ! long totalSecs = 0; ! double totalValue = 0.0, min = Double.NaN, max = Double.NaN, last = Double.NaN; RpnCalculator rpnCalculator = null; ! if (rpnExpression != null) { rpnCalculator = new RpnCalculator(rpnExpression); } ! for (int i = 0; i < values.length - 1; i++) { long t1 = Math.max(request.getFetchStart(), timestamps[i]); long t2 = Math.min(request.getFetchEnd(), timestamps[i + 1]); ! double value = values[i + 1]; ! if (rpnCalculator != null) { rpnCalculator.setValue(value); + rpnCalculator.setTimestamp(t2); value = rpnCalculator.calculate(); } ! if (!Double.isNaN(value)) { ! totalSecs += (t2 - t1); ! totalValue += (t2 - t1) * value; } + min = Util.min(min, value); + max = Util.max(max, value); + last = value; } ! FetchDataStats stats = new FetchDataStats(); ! stats.setLast(last); ! stats.setMax(max); ! stats.setMin(min); ! stats.setSeconds(totalSecs); ! stats.setTotal(totalValue); ! return stats; } /** * Dumps fetch data to output stream in XML format. + * * @param outputStream Output stream to dump fetch data to * @throws IOException Thrown in case of I/O error *************** *** 411,425 **** writer.closeTag(); // request writer.startTag("datasources"); ! for(int i = 0; i < dsNames.length; i++) { writer.writeTag("name", dsNames[i]); } writer.closeTag(); // datasources writer.startTag("data"); ! for(int i = 0; i < timestamps.length; i++) { writer.startTag("row"); writer.writeComment(Util.getDate(timestamps[i])); ! writer.writeTag("timestamp", timestamps[i]); writer.startTag("values"); ! for(int j = 0; j < dsNames.length; j++) { writer.writeTag("v", values[j][i]); } --- 429,443 ---- writer.closeTag(); // request writer.startTag("datasources"); ! for (int i = 0; i < dsNames.length; i++) { writer.writeTag("name", dsNames[i]); } writer.closeTag(); // datasources writer.startTag("data"); ! for (int i = 0; i < timestamps.length; i++) { writer.startTag("row"); writer.writeComment(Util.getDate(timestamps[i])); ! writer.writeTag("timestamp", timestamps[i]); writer.startTag("values"); ! for (int j = 0; j < dsNames.length; j++) { writer.writeTag("v", values[j][i]); } *************** *** 434,437 **** --- 452,456 ---- /** * Dumps fetch data to file in XML format. + * * @param filepath Path to destination file * @throws IOException Thrown in case of I/O error *************** *** 444,448 **** } finally { ! if(outputStream != null) { outputStream.close(); } --- 463,467 ---- } finally { ! if (outputStream != null) { outputStream.close(); } *************** *** 452,455 **** --- 471,475 ---- /** * Dumps fetch data in XML format. + * * @return String containing XML formatted fetch data * @throws IOException Thrown in case of I/O error Index: Util.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Util.java,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -d -r1.26 -r1.27 *** Util.java 8 Nov 2004 11:18:49 -0000 1.26 --- Util.java 18 Nov 2004 13:27:58 -0000 1.27 *************** *** 236,239 **** --- 236,254 ---- /** + * Checks if a string can be parsed as double. + * @param s Input string + * @return <code>true</code> if the string can be parsed as double, <code>false</code> otherwise + */ + public static boolean isDouble(String s) { + try { + Double.parseDouble(s); + return true; + } + catch(NumberFormatException nfe) { + return false; + } + } + + /** * Parses input string as a boolean value. The parser is case insensitive. * @param valueStr String representing boolean value *************** *** 545,551 **** /** ! * Compares two doubles, but returns true if x=y=Double.NaN (by default Double.NaN != Double.NaN) ! * @param x first value ! * @param y second value * @return <code>true</code> if x and y are both equal to Double.NaN, or if x == y. <code>false</code> otherwise */ --- 560,567 ---- /** ! * Compares two doubles but treats all NaNs as equal. ! * In Java (by default) Double.NaN == Double.NaN always returns <code>false</code> ! * @param x the first value ! * @param y the second value * @return <code>true</code> if x and y are both equal to Double.NaN, or if x == y. <code>false</code> otherwise */ --- NEW FILE: FetchDataStats.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@jr...) * Arne Vandamme (cob...@jr...) * * 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.core; /** * Dumb class which contains statistics (AVERAGE, MIN, MAX, LAST and TOTAL) calculated from the * {@link FetchData#getStats(String, String) FetchData} returned by a single {@link FetchRequest}. */ public class FetchDataStats implements ConsolFuns { private long seconds; private double total, min, max, last; FetchDataStats() { // just to prohibit explicit creation } void setSeconds(long seconds) { this.seconds = seconds; } void setTotal(double total) { this.total = total; } void setMin(double min) { this.min = min; } void setMax(double max) { this.max = max; } void setLast(double last) { this.last = last; } /** * Returns TOTAL of the fetched data * @return TOTAL of the fetched data */ public double getTotal() { return total; } /** * Returns MIN of the fetched data * @return MIN of the fetched data */ public double getMin() { return min; } /** * Returns MAX of the fetched data * @return MAX of the fetched data */ public double getMax() { return max; } /** * Returns LAST of the fetched data * @return LAST of the fetched data */ public double getLast() { return last; } /** * Returns AVERAGE of the fetched data * @return AVERAGE of the fetched data */ public double getAverage() { return total / (double) seconds; } /** * Returns aggregated value of the fetch data * @param consolFun Consolidation function to be used * (AVERAGE, MIN, MAX, LAST and TOTAL) * @return Aggregated value * @throws RrdException Thrown if invalid consolidation function is supplied */ public double getAggregate(String consolFun) throws RrdException { if (consolFun.equals(CF_MAX)) { return getMax(); } else if (consolFun.equals(CF_MIN)) { return getMin(); } else if (consolFun.equals(CF_LAST)) { return getLast(); } else if (consolFun.equals(CF_AVERAGE)) { return getAverage(); } else if (consolFun.equals(CF_TOTAL)) { return getTotal(); } else { throw new RrdException("Unsupported consolidation function [" + consolFun + "]"); } } /** * Dumps all aggregated values in a human-readable form. * @return A string containing all aggregated values. */ public String dump() { return "AVERAGE: " + Util.formatDouble(getAverage(), true) + "\n" + "MIN: " + Util.formatDouble(getMin(), true) + "\n" + "MAX: " + Util.formatDouble(getMax(), true) + "\n" + "LAST: " + Util.formatDouble(getLast(), true) + "\n" + "TOTAL: " + Util.formatDouble(getTotal(), true); } } |
From: Sasa M. <sa...@us...> - 2004-11-12 10:09:50
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14851/org/jrobin/core Modified Files: RrdDbPool.java Log Message: minor javadoc changes Index: RrdDbPool.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDbPool.java,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** RrdDbPool.java 19 Oct 2004 10:14:03 -0000 1.18 --- RrdDbPool.java 12 Nov 2004 10:09:38 -0000 1.19 *************** *** 30,34 **** /** * Class to represent the pool of open RRD files.<p> ! * <p/> * To open already existing RRD file with JRobin, you have to create a * {@link org.jrobin.core.RrdDb RrdDb} object by specifying RRD file path --- 30,34 ---- /** * Class to represent the pool of open RRD files.<p> ! * * To open already existing RRD file with JRobin, you have to create a * {@link org.jrobin.core.RrdDb RrdDb} object by specifying RRD file path *************** *** 36,40 **** * especially with large RRD files with many datasources and * several long archives.<p> ! * <p/> * In a multithreaded environment you might probably need a reference to the * same RRD file from two different threads (RRD file updates are performed in --- 36,40 ---- * especially with large RRD files with many datasources and * several long archives.<p> ! * * In a multithreaded environment you might probably need a reference to the * same RRD file from two different threads (RRD file updates are performed in *************** *** 42,77 **** * the RrdDb construction process more efficient it might be convenient to open all * RRD files in a centralized place. That's the purpose of RrdDbPool class.<p> ! * <p/> * How does it work? The typical usage scenario goes like this:<p> ! * <p/> * <pre> * // obtain instance to RrdDbPool object * RrdDbPool pool = RrdDbPool.getInstance(); ! * <p/> * // request a reference to RrdDb object * String path = "some_relative_or_absolute_path_to_any_RRD_file"; * RrdDb rrdDb = RrdDbPool.requestRrdDb(path); ! * <p/> * // reference obtained, do whatever you want with it... * ... * ... ! * <p/> * // once you don't need the reference, release it. * // DO NOT CALL rrdDb.close() - files no longer in use are eventually closed by the pool * pool.release(rrdDb); * </pre> ! * <p/> ! * It's that simple. When the reference is requested for the first time, ! * RrdDbPool will open the RRD file * for you and make some internal note that the RRD file is used only once. When the reference * to the same file (same RRD file path) is requested for the second time, the same RrdDb * reference will be returned, and its usage count will be increased by one. When the * reference is released its usage count will be decremented by one.<p> ! * <p/> * When the reference count drops to zero, RrdDbPool will not close the underlying * RRD file immediatelly. Instead of it, it will be marked as 'eligible for closing'. * If someone request the same RRD file again (before it gets closed), the same * reference will be returned again.<p> ! * <p/> * RrdDbPool has a 'garbage collector' which runs in a separate, low-priority * thread and gets activated only when the number of RRD files kept in the --- 42,76 ---- * the RrdDb construction process more efficient it might be convenient to open all * RRD files in a centralized place. That's the purpose of RrdDbPool class.<p> ! * * How does it work? The typical usage scenario goes like this:<p> ! * * <pre> * // obtain instance to RrdDbPool object * RrdDbPool pool = RrdDbPool.getInstance(); ! * * // request a reference to RrdDb object * String path = "some_relative_or_absolute_path_to_any_RRD_file"; * RrdDb rrdDb = RrdDbPool.requestRrdDb(path); ! * * // reference obtained, do whatever you want with it... * ... * ... ! * * // once you don't need the reference, release it. * // DO NOT CALL rrdDb.close() - files no longer in use are eventually closed by the pool * pool.release(rrdDb); * </pre> ! * ! * It's that simple. When the reference is requested for the first time, RrdDbPool will open the RRD file * for you and make some internal note that the RRD file is used only once. When the reference * to the same file (same RRD file path) is requested for the second time, the same RrdDb * reference will be returned, and its usage count will be increased by one. When the * reference is released its usage count will be decremented by one.<p> ! * * When the reference count drops to zero, RrdDbPool will not close the underlying * RRD file immediatelly. Instead of it, it will be marked as 'eligible for closing'. * If someone request the same RRD file again (before it gets closed), the same * reference will be returned again.<p> ! * * RrdDbPool has a 'garbage collector' which runs in a separate, low-priority * thread and gets activated only when the number of RRD files kept in the *************** *** 81,100 **** * RrdDbPool object keeps track of the time when each RRD file * becomes eligible for closing so that the oldest RRD file gets closed first.<p> ! * <p/> * Initial RrdDbPool capacity is set to {@link #INITIAL_CAPACITY}. Use {@link #setCapacity(int)} * method to change it at any time.<p> ! * <p/> * <b>WARNING:</b>Never use close() method on the reference returned from the pool. * When the reference is no longer needed, return it to the pool with the * {@link #release(RrdDb) release()} method.<p> ! * <p/> * However, you are not forced to use RrdDbPool methods to obtain RrdDb references * to RRD files, 'ordinary' RrdDb constructors are still available. But RrdDbPool class * offers serious performance improvement especially in complex applications with many * threads and many simultaneously open RRD files.<p> ! * <p/> * The pool is thread-safe. Not that the {@link RrdDb} objects returned from the pool are * also thread-safe<p> ! * <p/> * <b>WARNING:</b> The pool cannot be used to manipulate RrdDb objects * with {@link RrdBackend backends} different from default.<p> --- 80,103 ---- * RrdDbPool object keeps track of the time when each RRD file * becomes eligible for closing so that the oldest RRD file gets closed first.<p> ! * * Initial RrdDbPool capacity is set to {@link #INITIAL_CAPACITY}. Use {@link #setCapacity(int)} * method to change it at any time.<p> ! * * <b>WARNING:</b>Never use close() method on the reference returned from the pool. * When the reference is no longer needed, return it to the pool with the * {@link #release(RrdDb) release()} method.<p> ! * * However, you are not forced to use RrdDbPool methods to obtain RrdDb references * to RRD files, 'ordinary' RrdDb constructors are still available. But RrdDbPool class * offers serious performance improvement especially in complex applications with many * threads and many simultaneously open RRD files.<p> ! * * The pool is thread-safe. Not that the {@link RrdDb} objects returned from the pool are * also thread-safe<p> ! * ! * You should know that each operating system has its own internal limit on the number ! * of simultaneously open files. The capacity of your RrdDbPool should be ! * reasonably smaller than the limit imposed by your operating system.<p> ! * * <b>WARNING:</b> The pool cannot be used to manipulate RrdDb objects * with {@link RrdBackend backends} different from default.<p> |
From: Sasa M. <sa...@us...> - 2004-11-10 13:38:56
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17476/org/jrobin/core Modified Files: RrdSafeFileBackend.java RrdSafeFileBackendFactory.java Log Message: Added missing file headers Index: RrdSafeFileBackend.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdSafeFileBackend.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RrdSafeFileBackend.java 9 Nov 2004 11:36:53 -0000 1.1 --- RrdSafeFileBackend.java 10 Nov 2004 13:38:48 -0000 1.2 *************** *** 1,2 **** --- 1,27 ---- + /* ============================================================ + * JRobin : Pure java implementation of RRDTool's functionality + * ============================================================ + * + * Project Info: http://www.jrobin.org + * Project Lead: Sasa Markovic (sa...@jr...); + * + * (C) Copyright 2003, by Sasa Markovic. + * + * 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. + * + * Developers: Sasa Markovic (sa...@jr...) + * Arne Vandamme (cob...@jr...) + * + * 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.core; Index: RrdSafeFileBackendFactory.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdSafeFileBackendFactory.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RrdSafeFileBackendFactory.java 9 Nov 2004 11:36:53 -0000 1.1 --- RrdSafeFileBackendFactory.java 10 Nov 2004 13:38:48 -0000 1.2 *************** *** 1,2 **** --- 1,26 ---- + /* ============================================================ + * JRobin : Pure java implementation of RRDTool's functionality + * ============================================================ + * + * Project Info: http://www.jrobin.org + * Project Lead: Sasa Markovic (sa...@jr...); + * + * (C) Copyright 2003, by Sasa Markovic. + * + * 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. + * + * Developers: Sasa Markovic (sa...@jr...) + * Arne Vandamme (cob...@jr...) + * + * 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.core; |
From: Sasa M. <sa...@us...> - 2004-11-09 12:33:24
|
Update of /cvsroot/jrobin/src/org/jrobin/convertor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23843/org/jrobin/convertor Modified Files: Convertor.java Log Message: Minor changes Index: Convertor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/convertor/Convertor.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** Convertor.java 8 Nov 2004 14:01:36 -0000 1.5 --- Convertor.java 9 Nov 2004 12:33:13 -0000 1.6 *************** *** 27,30 **** --- 27,32 ---- import org.jrobin.core.RrdDb; + import org.jrobin.core.RrdException; + import java.io.*; import java.text.DecimalFormat; *************** *** 32,35 **** --- 34,38 ---- class Convertor { + private static final String FACTORY_NAME = "FILE"; private static final String SUFFIX = ".jrb"; private static final DecimalFormat secondsFormatter = new DecimalFormat("##0.000"); *************** *** 40,43 **** --- 43,53 ---- private Convertor(String[] files) { + try { + RrdDb.setDefaultFactory(FACTORY_NAME); + } + catch (RrdException e) { + e.printStackTrace(); + System.exit(-1); + } this.files = files; } |
From: Sasa M. <sa...@us...> - 2004-11-09 11:40:59
|
Update of /cvsroot/jrobin/src/org/jrobin/demo In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13322/org/jrobin/demo Modified Files: PlottableDemo.java StressTest.java Log Message: Minor changes to demos... Index: StressTest.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/demo/StressTest.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** StressTest.java 8 Nov 2004 11:18:49 -0000 1.3 --- StressTest.java 9 Nov 2004 11:40:50 -0000 1.4 *************** *** 124,128 **** // GRAPH printLapTime("Creating composite graph definition"); ! RrdGraphDef gdef = new RrdGraphDef(TIME_START, 0); // A 0 end time makes sure the last sample time i used gdef.setTitle("Temperatures"); gdef.setVerticalLabel("Fahrenheits"); --- 124,128 ---- // GRAPH printLapTime("Creating composite graph definition"); ! RrdGraphDef gdef = new RrdGraphDef(TIME_START, 0); // A 0 end time makes sure the last sample time i used gdef.setTitle("Temperatures"); gdef.setVerticalLabel("Fahrenheits"); Index: PlottableDemo.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/demo/PlottableDemo.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** PlottableDemo.java 28 Oct 2004 20:04:42 -0000 1.4 --- PlottableDemo.java 9 Nov 2004 11:40:50 -0000 1.5 *************** *** 38,45 **** class PlottableDemo { static final double[] SF_DOWNLOAD_COUNT = { ! 0, 0, 13, 34, 76, 72, 255, 144, 135, 194, 358, 304, 293 }; static final double[] SF_PAGE_HITS = { ! 0, 1072, 517, 979, 2132, 2532, 5515, 3519, 3500, 4942, 7858, 7797, 6570 }; static final GregorianCalendar[] SF_TIMESTAMPS = --- 38,45 ---- class PlottableDemo { static final double[] SF_DOWNLOAD_COUNT = { ! 0, 0, 13, 34, 76, 72, 255, 144, 135, 194, 358, 304, 293, 293, 289, 530, 252, 251 }; static final double[] SF_PAGE_HITS = { ! 0, 1072, 517, 979, 2132, 2532, 5515, 3519, 3500, 4942, 7858, 7797, 6570, 8415, 8368, 12353, 12711, 11008 }; static final GregorianCalendar[] SF_TIMESTAMPS = *************** *** 174,178 **** LinearInterpolator downloadsInterpolator = new LinearInterpolator(SF_TIMESTAMPS, SF_DOWNLOAD_COUNT); ! RrdGraphDef gDef = new RrdGraphDef(SF_TIMESTAMPS[0], SF_TIMESTAMPS[SF_TIMESTAMPS.length - 1]); gDef.setTitle("JRobin statistics at SourceForge"); --- 174,181 ---- LinearInterpolator downloadsInterpolator = new LinearInterpolator(SF_TIMESTAMPS, SF_DOWNLOAD_COUNT); ! LinearInterpolator trendInterpolator = ! new LinearInterpolator(SF_TIMESTAMPS, SF_PAGE_HITS); ! trendInterpolator.setInterpolationMethod(LinearInterpolator.INTERPOLATE_REGRESSION); ! RrdGraphDef gDef = new RrdGraphDef(SF_TIMESTAMPS[0], SF_TIMESTAMPS[SF_TIMESTAMPS.length - 1]); gDef.setTitle("JRobin statistics at SourceForge"); *************** *** 181,188 **** gDef.datasource("hits", hitsInterpolator); gDef.datasource("downloads", downloadsInterpolator); gDef.datasource("ratio", "downloads,0,EQ,UNKN,hits,downloads,/,IF"); gDef.area("hits", Color.GREEN, null); gDef.line("hits", Color.RED, "page hits", 2); ! gDef.area("downloads", Color.MAGENTA, "downloads@L"); gDef.vrule(new GregorianCalendar(2004, 0, 1), Color.BLUE, null, 3); gDef.setTimeAxis(TimeAxisUnit.MONTH, 1, TimeAxisUnit.MONTH, 1, "MMM", false); --- 184,193 ---- gDef.datasource("hits", hitsInterpolator); gDef.datasource("downloads", downloadsInterpolator); + gDef.datasource("trend", trendInterpolator); gDef.datasource("ratio", "downloads,0,EQ,UNKN,hits,downloads,/,IF"); gDef.area("hits", Color.GREEN, null); gDef.line("hits", Color.RED, "page hits", 2); ! gDef.area("downloads", Color.MAGENTA, "downloads"); ! gDef.line("trend", Color.ORANGE, "trend@L"); gDef.vrule(new GregorianCalendar(2004, 0, 1), Color.BLUE, null, 3); gDef.setTimeAxis(TimeAxisUnit.MONTH, 1, TimeAxisUnit.MONTH, 1, "MMM", false); |
From: Sasa M. <sa...@us...> - 2004-11-09 11:37:04
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12665/org/jrobin/core Modified Files: Archive.java Datasource.java Header.java RrdBackendFactory.java RrdDouble.java RrdDoubleArray.java RrdInt.java RrdLong.java RrdPrimitive.java RrdString.java Added Files: RrdSafeFileBackend.java RrdSafeFileBackendFactory.java Log Message: Major core update: added one more backend type (SAFE - basically it's a FILE, but with RRD file locking and minimal in-memory caching). Could be useful when RRD files are used by two JVMs running at the same time. Index: RrdPrimitive.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdPrimitive.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** RrdPrimitive.java 8 Nov 2004 11:18:49 -0000 1.9 --- RrdPrimitive.java 9 Nov 2004 11:36:53 -0000 1.10 *************** *** 36,48 **** private int byteCount; private final long pointer; ! RrdPrimitive(RrdUpdater updater, int type) throws IOException { ! this(updater, type, 1); } ! RrdPrimitive(RrdUpdater updater, int type, int count) throws IOException { this.backend = updater.getRrdBackend(); this.byteCount = RRD_PRIM_SIZES[type] * count; this.pointer = updater.getRrdAllocator().allocate(byteCount); } --- 36,50 ---- private int byteCount; private final long pointer; + private final boolean cachingAllowed; ! RrdPrimitive(RrdUpdater updater, int type, boolean isConstant) throws IOException { ! this(updater, type, 1, isConstant); } ! RrdPrimitive(RrdUpdater updater, int type, int count, boolean isConstant) throws IOException { this.backend = updater.getRrdBackend(); this.byteCount = RRD_PRIM_SIZES[type] * count; this.pointer = updater.getRrdAllocator().allocate(byteCount); + this.cachingAllowed = isConstant || backend.isCachingAllowed(); } *************** *** 111,115 **** final boolean isCachingAllowed() { ! return backend.isCachingAllowed(); } } --- 113,117 ---- final boolean isCachingAllowed() { ! return cachingAllowed; } } Index: Header.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Header.java,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** Header.java 22 Jul 2004 09:34:10 -0000 1.7 --- Header.java 9 Nov 2004 11:36:53 -0000 1.8 *************** *** 52,59 **** boolean shouldInitialize = rrdDef != null; this.parentDb = parentDb; ! signature = new RrdString(this); ! step = new RrdLong(this); ! dsCount = new RrdInt(this); ! arcCount = new RrdInt(this); lastUpdateTime = new RrdLong(this); if(shouldInitialize) { --- 52,59 ---- boolean shouldInitialize = rrdDef != null; this.parentDb = parentDb; ! signature = new RrdString(this, true); // constant, may be cached ! step = new RrdLong(this, true); // constant, may be cached ! dsCount = new RrdInt(this, true); // constant, may be cached ! arcCount = new RrdInt(this, true); // constant, may be cached lastUpdateTime = new RrdLong(this); if(shouldInitialize) { Index: Archive.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Archive.java,v retrieving revision 1.18 retrieving revision 1.19 diff -C2 -d -r1.18 -r1.19 *** Archive.java 21 Sep 2004 08:42:09 -0000 1.18 --- Archive.java 9 Nov 2004 11:36:53 -0000 1.19 *************** *** 52,59 **** boolean shouldInitialize = arcDef != null; this.parentDb = parentDb; ! consolFun = new RrdString(this); xff = new RrdDouble(this); ! steps = new RrdInt(this); ! rows = new RrdInt(this); if(shouldInitialize) { consolFun.set(arcDef.getConsolFun()); --- 52,59 ---- boolean shouldInitialize = arcDef != null; this.parentDb = parentDb; ! consolFun = new RrdString(this, true); // constant, may be cached xff = new RrdDouble(this); ! steps = new RrdInt(this, true); // constant, may be cached ! rows = new RrdInt(this, true); // constant, may be cached if(shouldInitialize) { consolFun.set(arcDef.getConsolFun()); Index: RrdInt.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdInt.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** RrdInt.java 8 Nov 2004 11:18:48 -0000 1.10 --- RrdInt.java 9 Nov 2004 11:36:53 -0000 1.11 *************** *** 32,39 **** private boolean cached = false; RrdInt(RrdUpdater updater) throws IOException { ! super(updater, RrdPrimitive.RRD_INT); } ! void set(int value) throws IOException { if(!isCachingAllowed()) { --- 32,43 ---- private boolean cached = false; + RrdInt(RrdUpdater updater, boolean isConstant) throws IOException { + super(updater, RrdPrimitive.RRD_INT, isConstant); + } + RrdInt(RrdUpdater updater) throws IOException { ! this(updater, false); } ! void set(int value) throws IOException { if(!isCachingAllowed()) { Index: RrdDouble.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDouble.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** RrdDouble.java 8 Nov 2004 11:18:48 -0000 1.10 --- RrdDouble.java 9 Nov 2004 11:36:53 -0000 1.11 *************** *** 32,37 **** private boolean cached = false; RrdDouble(RrdUpdater updater) throws IOException { ! super(updater, RrdDouble.RRD_DOUBLE); } --- 32,41 ---- private boolean cached = false; + RrdDouble(RrdUpdater updater, boolean isConstant) throws IOException { + super(updater, RrdDouble.RRD_DOUBLE, isConstant); + } + RrdDouble(RrdUpdater updater) throws IOException { ! super(updater, RrdDouble.RRD_DOUBLE, false); } Index: RrdString.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdString.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** RrdString.java 8 Nov 2004 11:18:49 -0000 1.10 --- RrdString.java 9 Nov 2004 11:36:53 -0000 1.11 *************** *** 31,36 **** private String cache; RrdString(RrdUpdater updater) throws IOException { ! super(updater, RrdPrimitive.RRD_STRING); } --- 31,40 ---- private String cache; + RrdString(RrdUpdater updater, boolean isConstant) throws IOException { + super(updater, RrdPrimitive.RRD_STRING, isConstant); + } + RrdString(RrdUpdater updater) throws IOException { ! this(updater, false); } Index: RrdLong.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdLong.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** RrdLong.java 8 Nov 2004 11:18:48 -0000 1.10 --- RrdLong.java 9 Nov 2004 11:36:53 -0000 1.11 *************** *** 32,37 **** private boolean cached = false; RrdLong(RrdUpdater updater) throws IOException { ! super(updater, RrdPrimitive.RRD_LONG); } --- 32,41 ---- private boolean cached = false; + RrdLong(RrdUpdater updater, boolean isConstant) throws IOException { + super(updater, RrdPrimitive.RRD_LONG, isConstant); + } + RrdLong(RrdUpdater updater) throws IOException { ! this(updater, false); } Index: RrdBackendFactory.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdBackendFactory.java,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** RrdBackendFactory.java 13 Jul 2004 18:42:19 -0000 1.7 --- RrdBackendFactory.java 9 Nov 2004 11:36:53 -0000 1.8 *************** *** 37,41 **** * Each factory creates unlimited number of specific backend objects. * ! * JRobin supports three different backend types (backend factories) out of the box:<p> * <ul> * <li>{@link RrdFileBackend}: objects of this class are created from the --- 37,41 ---- * Each factory creates unlimited number of specific backend objects. * ! * JRobin supports four different backend types (backend factories) out of the box:<p> * <ul> * <li>{@link RrdFileBackend}: objects of this class are created from the *************** *** 44,47 **** --- 44,55 ---- * RRD data in files on the disk. * + * <li>{@link RrdSafeFileBackend}: objects of this class are created from the + * {@link RrdSafeFileBackendFactory} class. It uses java.io.* package and RandomAccessFile class to store + * RRD data in files on the disk. This backend is SAFE: + * it locks the underlying RRD file during update/fetch operations, and caches only static + * parts of a RRD file in memory. Therefore, this backend is safe to be used when RRD files should + * be shared <b>between several JVMs</b> at the same time. However, this backend is *slow* since it does + * not use fast java.nio.* package (it's still based on the RandomAccessFile class). + * * <li>{@link RrdNioBackend}: objects of this class are created from the * {@link RrdNioBackendFactory} class. The backend uses java.io.* and java.nio.* *************** *** 72,75 **** --- 80,85 ---- RrdNioBackendFactory nioFactory = new RrdNioBackendFactory(); registerFactory(nioFactory); + RrdSafeFileBackendFactory safeFactory = new RrdSafeFileBackendFactory(); + registerFactory(safeFactory); // Here is the default backend factory *************** *** 87,90 **** --- 97,104 ---- * <li><b>FILE</b>: Default factory which creates backends based on the * java.io.* package. RRD data is stored in files on the disk + * <li><b>SAFE</b>: Default factory which creates backends based on the + * java.io.* package. RRD data is stored in files on the disk. This backend + * is "safe". Being safe means that RRD files can be safely shared between + * several JVM's. * <li><b>NIO</b>: Factory which creates backends based on the * java.nio.* package. RRD data is stored in files on the disk *************** *** 149,155 **** * Replaces the default backend factory with a new one. This method must be called before * the first RRD gets created. <p> ! * @param factoryName Name of the default factory. Out of the box, JRobin supports three ! * different RRD backends: "FILE" (java.io.* based), "NIO" (java.nio.* based) and "MEMORY" ! * (byte[] based). * @throws RrdException Thrown if invalid factory name is supplied or not called before * the first RRD is created. --- 163,170 ---- * Replaces the default backend factory with a new one. This method must be called before * the first RRD gets created. <p> ! * @param factoryName Name of the default factory. Out of the box, JRobin supports four ! * different RRD backends: "FILE" (java.io.* based), "SAFE" (java.io.* based - use this ! * backend if RRD files may be accessed from several JVMs at the same time), ! * "NIO" (java.nio.* based) and "MEMORY" (byte[] based). * @throws RrdException Thrown if invalid factory name is supplied or not called before * the first RRD is created. --- NEW FILE: RrdSafeFileBackendFactory.java --- package org.jrobin.core; import java.io.IOException; /** * Factory class which creates actual {@link RrdSafeFileBackend} objects. */ public class RrdSafeFileBackendFactory extends RrdFileBackendFactory { /** factory name, "SAFE" */ public static final String NAME = "SAFE"; /** * Creates RrdSafeFileBackend object for the given file path. * @param path File path * @param readOnly True, if the file should be accessed in read/only mode. * False otherwise. * @param lockMode This parameter is ignored since this backend implements its own * locking mechanism. * @return RrdSafeFileBackend object which handles all I/O operations for the given file path * @throws IOException Thrown in case of I/O error. */ protected RrdBackend open(String path, boolean readOnly, int lockMode) throws IOException { return new RrdSafeFileBackend(path, readOnly, lockMode); } /** * Returns the name of this factory. * @return Factory name (equals to string "SAFE") */ public String getFactoryName() { return NAME; } } --- NEW FILE: RrdSafeFileBackend.java --- package org.jrobin.core; import java.io.IOException; import java.nio.channels.FileLock; /** * JRobin backend which is used to store RRD data to ordinary files on the disk. This backend * is SAFE: it locks the underlying RRD file during update/fetch operations, and caches only static * parts of a RRD file in memory. Therefore, this backend is safe to be used when RRD files should * be shared between several JVMs at the same time. However, this backend is *slow* since it does * not use fast java.nio.* package (it's still based on the RandomAccessFile class). */ public class RrdSafeFileBackend extends RrdFileBackend { /** Number of locking retries. This backend will not give up if the first locking request fails. */ public static final int LOCK_RETRY_COUNT = 40; /** Number of milliseconds between locking retries */ public static final int LOCK_RETRY_DELAY = 50; // milliseconds private FileLock lock; /** * Creates RrdFileBackend object for the given file path, backed by RandomAccessFile object. * @param path Path to a file * @param readOnly True, if file should be open in a read-only mode. False otherwise * @param lockMode Ignored, since this backend implements its own locking mechanism * @throws IOException Thrown in case of I/O error */ public RrdSafeFileBackend(String path, boolean readOnly, int lockMode) throws IOException { // this backend implements its own locking mechanism - we'll simply ignore the suggested lockMode super(path, readOnly, RrdDb.NO_LOCKS); } private void lockFile() throws IOException { if(lock != null) { // lock already obtained return; } for(int i = 0; i < LOCK_RETRY_COUNT; i++) { lock = channel.tryLock(); if(lock != null) { return; } try { Thread.sleep(LOCK_RETRY_DELAY); } catch (InterruptedException e) { // NOP } } throw new IOException("Could not obtain lock on file: " + getPath() + "] after " + LOCK_RETRY_COUNT + " consecutive retries"); } private void unlockFile() throws IOException { if(lock != null) { lock.release(); lock = null; } } /** * Defines the caching policy for this backend. * @return <code>false</code> */ protected boolean isCachingAllowed() { return false; } /** * Locks the underlying RRD file just before the next RRD update operation. * @throws IOException Thrown if the file lock could not be obtained. */ protected void beforeUpdate() throws IOException { super.beforeUpdate(); lockFile(); } /** * Unlocks the underlying RRD file just after the RRD update operation. * @throws IOException Thrown if the lock could not be released. */ protected void afterUpdate() throws IOException { unlockFile(); super.afterUpdate(); } /** * Locks the underlying RRD file just before the next RRD fetch operation. * @throws IOException Thrown if the file lock could not be obtained. */ protected void beforeFetch() throws IOException { super.beforeFetch(); lockFile(); } /** * Unlocks the underlying RRD file just after the RRD fetch operation. * @throws IOException Thrown if the lock could not be released. */ protected void afterFetch() throws IOException { unlockFile(); super.afterFetch(); } /** * Releases the file lock before closing the RRD file (if not already released). * @throws IOException Thrown if the lock could not be released. */ protected void beforeClose() throws IOException { // just in case unlockFile(); super.beforeClose(); } } Index: Datasource.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Datasource.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** Datasource.java 21 Sep 2004 08:42:09 -0000 1.9 --- Datasource.java 9 Nov 2004 11:36:53 -0000 1.10 *************** *** 54,59 **** boolean shouldInitialize = dsDef != null; this.parentDb = parentDb; ! dsName = new RrdString(this); ! dsType = new RrdString(this); heartbeat = new RrdLong(this); minValue = new RrdDouble(this); --- 54,59 ---- boolean shouldInitialize = dsDef != null; this.parentDb = parentDb; ! dsName = new RrdString(this, true); // constant, may be cached ! dsType = new RrdString(this, true); // constant, may be cached heartbeat = new RrdLong(this); minValue = new RrdDouble(this); Index: RrdDoubleArray.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDoubleArray.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** RrdDoubleArray.java 20 May 2004 10:29:33 -0000 1.6 --- RrdDoubleArray.java 9 Nov 2004 11:36:53 -0000 1.7 *************** *** 32,36 **** RrdDoubleArray(RrdUpdater updater, int length) throws IOException { ! super(updater, RrdPrimitive.RRD_DOUBLE, length); this.length = length; } --- 32,36 ---- RrdDoubleArray(RrdUpdater updater, int length) throws IOException { ! super(updater, RrdPrimitive.RRD_DOUBLE, length, false); this.length = length; } |
From: Sasa M. <sa...@us...> - 2004-11-08 14:01:50
|
Update of /cvsroot/jrobin/src/org/jrobin/convertor In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15540/org/jrobin/convertor Modified Files: Convertor.java Log Message: Minor cosmetical improvements Index: Convertor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/convertor/Convertor.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** Convertor.java 5 Nov 2004 13:10:19 -0000 1.4 --- Convertor.java 8 Nov 2004 14:01:36 -0000 1.5 *************** *** 29,37 **** import java.io.*; import java.text.DecimalFormat; class Convertor { private static final String SUFFIX = ".jrb"; private static final DecimalFormat secondsFormatter = new DecimalFormat("##0.000"); ! private static final DecimalFormat countFormatter = new DecimalFormat("00000"); private String[] files; --- 29,38 ---- import java.io.*; import java.text.DecimalFormat; + import java.util.Date; class Convertor { private static final String SUFFIX = ".jrb"; private static final DecimalFormat secondsFormatter = new DecimalFormat("##0.000"); ! private static final DecimalFormat countFormatter = new DecimalFormat("0000"); private String[] files; *************** *** 43,46 **** --- 44,48 ---- private void convertAll() { + Date t1 = new Date(); final String ruler = "======================================================================="; println(ruler); *************** *** 54,58 **** println(ruler); println("Finished: " + totalCount + " total, " + ! goodCount + " OK, " + badCount + " failed."); } --- 56,67 ---- println(ruler); println("Finished: " + totalCount + " total, " + ! goodCount + " OK, " + badCount + " failed"); ! Date t2 = new Date(); ! double secs = (t2.getTime() - t1.getTime()) / 1000.0; ! println("Conversion took " + secondsFormatter.format(secs) + " sec"); ! if(totalCount > 0) { ! double avgSec = secs / totalCount; ! println("Average per-file conversion time: " + secondsFormatter.format(avgSec) + " sec"); ! } } *************** *** 62,66 **** try { File rrdFile = new File(path); ! print(countFormatter.format(totalCount) + " " + rrdFile.getName() + " "); String sourcePath = rrdFile.getCanonicalPath(); String destPath = sourcePath + SUFFIX; --- 71,76 ---- try { File rrdFile = new File(path); ! print(countFormatter.format(totalCount) + "/" + countFormatter.format(files.length) + ! " " + rrdFile.getName() + " "); String sourcePath = rrdFile.getCanonicalPath(); String destPath = sourcePath + SUFFIX; |
From: Sasa M. <sa...@us...> - 2004-11-08 11:21:48
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11971/org/jrobin/core Removed Files: RrdCacher.java Log Message: Removed RrdCacher class (consumes too much memory) - caching mechanism is now implemented in subclasses of the RrdPrimitive class (RrdInt, RrdLong, RrdDouble, RrdString) --- RrdCacher.java DELETED --- |
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11328/org/jrobin/core Modified Files: RrdBackend.java RrdDouble.java RrdInt.java RrdLong.java RrdMemoryBackend.java RrdPrimitive.java RrdString.java Util.java Log Message: Removed RrdCacher class (consumes too much memory) - caching mechanism is now implemented in subclasses of the RrdPrimitive class (RrdInt, RrdLong, RrdDouble, RrdString) Index: RrdString.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdString.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** RrdString.java 29 Jun 2004 12:59:35 -0000 1.9 --- RrdString.java 8 Nov 2004 11:18:49 -0000 1.10 *************** *** 29,32 **** --- 29,34 ---- class RrdString extends RrdPrimitive { + private String cache; + RrdString(RrdUpdater updater) throws IOException { super(updater, RrdPrimitive.RRD_STRING); *************** *** 34,47 **** void set(String value) throws IOException { ! if(cache.setString(value)) { writeString(value); } } String get() throws IOException { ! if(cache.isEmpty()) { ! cache.setString(readString()); ! } ! return cache.getString(); } } --- 36,51 ---- void set(String value) throws IOException { ! if(!isCachingAllowed()) { writeString(value); } + // caching allowed + else if(cache == null || !cache.equals(value)) { + // update cache + writeString(cache = value); + } } String get() throws IOException { ! return (cache != null)? cache: readString(); } } Index: RrdMemoryBackend.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdMemoryBackend.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** RrdMemoryBackend.java 29 Jun 2004 12:28:09 -0000 1.4 --- RrdMemoryBackend.java 8 Nov 2004 11:18:49 -0000 1.5 *************** *** 29,33 **** /** ! * Backend which is used to store all RRD bytes in memory.<p> */ public class RrdMemoryBackend extends RrdBackend { --- 29,33 ---- /** ! * Backend to be used to store all RRD bytes in memory.<p> */ public class RrdMemoryBackend extends RrdBackend { *************** *** 84,86 **** --- 84,95 ---- // NOP } + + /** + * This method is overriden to disable high-level caching in frontend JRobin classes. + * @return Always returns <code>false</code>. There is no need to cache anything in high-level classes + * since all RRD bytes are already in memory. + */ + protected boolean isCachingAllowed() { + return false; + } } Index: Util.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Util.java,v retrieving revision 1.25 retrieving revision 1.26 diff -C2 -d -r1.25 -r1.26 *** Util.java 27 Oct 2004 20:36:25 -0000 1.25 --- Util.java 8 Nov 2004 11:18:49 -0000 1.26 *************** *** 545,560 **** /** ! * Compares two doubles, but returns true if x = y = Double.NaN ! * @param x First double ! * @param y Second double ! * @return true, if doubles are equal, false otherwise. */ public static boolean equal(double x, double y) { ! if(Double.isNaN(x) && Double.isNaN(y)) { ! return true; ! } ! else { ! return x == y; ! } } --- 545,555 ---- /** ! * Compares two doubles, but returns true if x=y=Double.NaN (by default Double.NaN != Double.NaN) ! * @param x first value ! * @param y second value ! * @return <code>true</code> if x and y are both equal to Double.NaN, or if x == y. <code>false</code> otherwise */ public static boolean equal(double x, double y) { ! return (Double.isNaN(x) && Double.isNaN(y)) || (x == y); } Index: RrdLong.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdLong.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** RrdLong.java 29 Jun 2004 12:59:35 -0000 1.9 --- RrdLong.java 8 Nov 2004 11:18:48 -0000 1.10 *************** *** 29,32 **** --- 29,35 ---- class RrdLong extends RrdPrimitive { + private long cache; + private boolean cached = false; + RrdLong(RrdUpdater updater) throws IOException { super(updater, RrdPrimitive.RRD_LONG); *************** *** 34,47 **** void set(long value) throws IOException { ! if(cache.setLong(value)) { writeLong(value); } } long get() throws IOException { ! if(cache.isEmpty()) { ! cache.setLong(readLong()); ! } ! return cache.getLong(); } } --- 37,53 ---- void set(long value) throws IOException { ! if(!isCachingAllowed()) { writeLong(value); } + // caching allowed + else if(!cached || cache != value) { + // update cache + writeLong(cache = value); + cached = true; + } } long get() throws IOException { ! return cached? cache: readLong(); } } Index: RrdPrimitive.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdPrimitive.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** RrdPrimitive.java 29 Jun 2004 12:59:35 -0000 1.8 --- RrdPrimitive.java 8 Nov 2004 11:18:49 -0000 1.9 *************** *** 37,42 **** private final long pointer; - protected RrdCacher cache = new RrdCacher(); - RrdPrimitive(RrdUpdater updater, int type) throws IOException { this(updater, type, 1); --- 37,40 ---- *************** *** 49,53 **** } ! byte[] readBytes() throws IOException { byte[] b = new byte[byteCount]; backend.read(pointer, b); --- 47,51 ---- } ! final byte[] readBytes() throws IOException { byte[] b = new byte[byteCount]; backend.read(pointer, b); *************** *** 55,117 **** } ! void writeBytes(byte[] b) throws IOException { assert b.length == byteCount: "Invalid number of bytes supplied to RrdPrimitive.write method"; backend.write(pointer, b); } ! int readInt() throws IOException { return backend.readInt(pointer); } ! void writeInt(int value) throws IOException { backend.writeInt(pointer, value); } ! long readLong() throws IOException { return backend.readLong(pointer); } ! void writeLong(long value) throws IOException { backend.writeLong(pointer, value); } ! double readDouble() throws IOException { return backend.readDouble(pointer); } ! double readDouble(int index) throws IOException { long offset = pointer + index * RRD_PRIM_SIZES[RRD_DOUBLE]; return backend.readDouble(offset); } ! double[] readDouble(int index, int count) throws IOException { long offset = pointer + index * RRD_PRIM_SIZES[RRD_DOUBLE]; return backend.readDouble(offset, count); } ! void writeDouble(double value) throws IOException { backend.writeDouble(pointer, value); } ! void writeDouble(int index, double value, int count) throws IOException { long offset = pointer + index * RRD_PRIM_SIZES[RRD_DOUBLE]; backend.writeDouble(offset, value, count); } ! void writeDouble(int index, double[] values) throws IOException { long offset = pointer + index * RRD_PRIM_SIZES[RRD_DOUBLE]; backend.writeDouble(offset, values); } ! String readString() throws IOException { return backend.readString(pointer); } ! void writeString(String value) throws IOException { backend.writeString(pointer, value); } ! void clearCache() { ! cache.clearCache(); } } --- 53,115 ---- } ! final void writeBytes(byte[] b) throws IOException { assert b.length == byteCount: "Invalid number of bytes supplied to RrdPrimitive.write method"; backend.write(pointer, b); } ! final int readInt() throws IOException { return backend.readInt(pointer); } ! final void writeInt(int value) throws IOException { backend.writeInt(pointer, value); } ! final long readLong() throws IOException { return backend.readLong(pointer); } ! final void writeLong(long value) throws IOException { backend.writeLong(pointer, value); } ! final double readDouble() throws IOException { return backend.readDouble(pointer); } ! final double readDouble(int index) throws IOException { long offset = pointer + index * RRD_PRIM_SIZES[RRD_DOUBLE]; return backend.readDouble(offset); } ! final double[] readDouble(int index, int count) throws IOException { long offset = pointer + index * RRD_PRIM_SIZES[RRD_DOUBLE]; return backend.readDouble(offset, count); } ! final void writeDouble(double value) throws IOException { backend.writeDouble(pointer, value); } ! final void writeDouble(int index, double value, int count) throws IOException { long offset = pointer + index * RRD_PRIM_SIZES[RRD_DOUBLE]; backend.writeDouble(offset, value, count); } ! final void writeDouble(int index, double[] values) throws IOException { long offset = pointer + index * RRD_PRIM_SIZES[RRD_DOUBLE]; backend.writeDouble(offset, values); } ! final String readString() throws IOException { return backend.readString(pointer); } ! final void writeString(String value) throws IOException { backend.writeString(pointer, value); } ! final boolean isCachingAllowed() { ! return backend.isCachingAllowed(); } } Index: RrdBackend.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdBackend.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** RrdBackend.java 19 Oct 2004 10:14:02 -0000 1.9 --- RrdBackend.java 8 Nov 2004 11:18:48 -0000 1.10 *************** *** 192,199 **** * calls {@link #sync()} internally. */ ! public void beforeClose() throws IOException { sync(); } final void writeInt(long offset, int value) throws IOException { write(offset, getIntBytes(value)); --- 192,211 ---- * calls {@link #sync()} internally. */ ! protected void beforeClose() throws IOException { sync(); } + /** + * This method suggests the caching policy to the JRobin frontend (high-level) classes. If <code>true</code> + * is returned, frontent classes will cache frequently used parts of a RRD file in memory to improve + * performance. If </code>false</code> is returned, high level classes will never cache RRD file sections + * in memory. + * @return <code>true</code> if file caching is enabled, <code>false</code> otherwise. By default, the + * method returns <code>true</code> but it can be overriden in subclasses. + */ + protected boolean isCachingAllowed() { + return true; + } + final void writeInt(long offset, int value) throws IOException { write(offset, getIntBytes(value)); Index: RrdInt.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdInt.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** RrdInt.java 29 Jun 2004 12:59:35 -0000 1.9 --- RrdInt.java 8 Nov 2004 11:18:48 -0000 1.10 *************** *** 29,32 **** --- 29,35 ---- class RrdInt extends RrdPrimitive { + private int cache; + private boolean cached = false; + RrdInt(RrdUpdater updater) throws IOException { super(updater, RrdPrimitive.RRD_INT); *************** *** 34,47 **** void set(int value) throws IOException { ! if(cache.setInt(value)) { writeInt(value); } } int get() throws IOException { ! if(cache.isEmpty()) { ! cache.setInt(readInt()); ! } ! return cache.getInt(); } } --- 37,53 ---- void set(int value) throws IOException { ! if(!isCachingAllowed()) { writeInt(value); } + // caching allowed + else if(!cached || cache != value) { + // update cache + writeInt(cache = value); + cached = true; + } } int get() throws IOException { ! return cached? cache: readInt(); } } Index: RrdDouble.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDouble.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** RrdDouble.java 29 Jun 2004 12:59:35 -0000 1.9 --- RrdDouble.java 8 Nov 2004 11:18:48 -0000 1.10 *************** *** 29,32 **** --- 29,35 ---- class RrdDouble extends RrdPrimitive { + private double cache; + private boolean cached = false; + RrdDouble(RrdUpdater updater) throws IOException { super(updater, RrdDouble.RRD_DOUBLE); *************** *** 34,47 **** void set(double value) throws IOException { ! if(cache.setDouble(value)) { writeDouble(value); } } double get() throws IOException { ! if(cache.isEmpty()) { ! cache.setDouble(readDouble()); ! } ! return cache.getDouble(); } } --- 37,53 ---- void set(double value) throws IOException { ! if(!isCachingAllowed()) { writeDouble(value); } + // caching allowed + else if(!cached || !Util.equal(cache, value)) { + // update cache + writeDouble(cache = value); + cached = true; + } } double get() throws IOException { ! return cached? cache: readDouble(); } } |
From: Sasa M. <sa...@us...> - 2004-11-08 11:19:04
|
Update of /cvsroot/jrobin/src/org/jrobin/demo In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11328/org/jrobin/demo Modified Files: StressTest.java Log Message: Removed RrdCacher class (consumes too much memory) - caching mechanism is now implemented in subclasses of the RrdPrimitive class (RrdInt, RrdLong, RrdDouble, RrdString) |