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; + } } |