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: DJ G. <djg...@us...> - 2005-09-06 21:26:34
|
Update of /cvsroot/jrobin/src/org/jrobin/core/timespec In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15592/src/org/jrobin/core/timespec Added Files: Tag: release-1-5-2 Epoch.java TimeParser.java TimeScanner.java TimeSpec.java TimeToken.java Log Message: fix import conflicts --- NEW FILE: TimeSpec.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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.timespec; import org.jrobin.core.RrdException; import org.jrobin.core.Util; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; /** * Simple class to represent time obtained by parsing at-style date specification (described * in detail on the rrdfetch man page. See javadoc for {@link org.jrobin.core.timespec.TimeParser} * for more information. */ public class TimeSpec { static final int TYPE_ABSOLUTE = 0; static final int TYPE_START = 1; static final int TYPE_END = 2; int type = TYPE_ABSOLUTE; int year, month, day, hour, min, sec; int wday; int dyear, dmonth, dday, dhour, dmin, dsec; String dateString; TimeSpec context; TimeSpec(String dateString) { this.dateString = dateString; } void localtime(long timestamp) { GregorianCalendar date = new GregorianCalendar(); date.setTime(new Date(timestamp * 1000L)); year = date.get(Calendar.YEAR) - 1900; month = date.get(Calendar.MONTH); day = date.get(Calendar.DAY_OF_MONTH); hour = date.get(Calendar.HOUR_OF_DAY); min = date.get(Calendar.MINUTE); sec = date.get(Calendar.SECOND); wday = date.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY; } GregorianCalendar getTime() throws RrdException { GregorianCalendar gc; // absoulte time, this is easy if(type == TYPE_ABSOLUTE) { gc = new GregorianCalendar(year + 1900, month, day, hour, min, sec); } // relative time, we need a context to evaluate it else if(context != null && context.type == TYPE_ABSOLUTE) { gc = context.getTime(); } // how would I guess what time it was? else { throw new RrdException("Relative times like '" + dateString + "' require proper absolute context to be evaluated"); } gc.add(Calendar.YEAR, dyear); gc.add(Calendar.MONTH, dmonth); gc.add(Calendar.DAY_OF_MONTH, dday); gc.add(Calendar.HOUR_OF_DAY, dhour); gc.add(Calendar.MINUTE, dmin); gc.add(Calendar.SECOND, dsec); return gc; } /** * Returns the corresponding timestamp (seconds since Epoch). Example:<p> * <pre> * TimeParser p = new TimeParser("now-1day"); * TimeSpec ts = p.parse(); * System.out.println("Timestamp was: " + ts.getTimestamp(); * </pre> * @return Timestamp (in seconds, no milliseconds) * @throws RrdException Thrown if this TimeSpec object does not represent absolute time. */ public long getTimestamp() throws RrdException { return Util.getTimestamp(getTime()); } String dump() { return (type == TYPE_ABSOLUTE? "ABSTIME": type == TYPE_START? "START": "END") + ": " + year + "/" + month + "/" + day + "/" + hour + "/" + min + "/" + sec + " (" + dyear + "/" + dmonth + "/" + dday + "/" + dhour + "/" + dmin + "/" + dsec + ")"; } /** * Use this static method to resolve relative time references and obtain the corresponding * Calendar objects. Example:<p> * <pre> * TimeParser pStart = new TimeParser("now-1month"); // starting time * TimeParser pEnd = new TimeParser("start+1week"); // ending time * TimeSpec specStart = pStart.parse(); * TimeSpec specEnd = pEnd.parse(); * GregorianCalendar[] gc = TimeSpec.getTimes(specStart, specEnd); * </pre> * @param spec1 Starting time specification * @param spec2 Ending time specification * @return Two element array containing Calendar objects * @throws RrdException Thrown if relative time references cannot be resolved */ public static Calendar[] getTimes(TimeSpec spec1, TimeSpec spec2) throws RrdException { if(spec1.type == TYPE_START || spec2.type == TYPE_END) { throw new RrdException("Recursive time specifications not allowed"); } spec1.context = spec2; spec2.context = spec1; return new Calendar[] { spec1.getTime(), spec2.getTime() }; } /** * Use this static method to resolve relative time references and obtain the corresponding * timestamps (seconds since epoch). Example:<p> * <pre> * TimeParser pStart = new TimeParser("now-1month"); // starting time * TimeParser pEnd = new TimeParser("start+1week"); // ending time * TimeSpec specStart = pStart.parse(); * TimeSpec specEnd = pEnd.parse(); * long[] ts = TimeSpec.getTimestamps(specStart, specEnd); * </pre> * @param spec1 Starting time specification * @param spec2 Ending time specification * @return array containing two timestamps (in seconds since epoch) * @throws RrdException Thrown if relative time references cannot be resolved */ public static long[] getTimestamps(TimeSpec spec1, TimeSpec spec2) throws RrdException { Calendar[] gcs = getTimes(spec1, spec2); return new long[] { Util.getTimestamp(gcs[0]), Util.getTimestamp(gcs[1]) }; } } --- NEW FILE: TimeParser.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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. */ /* * Java port of Tobi's original parsetime.c routine */ package org.jrobin.core.timespec; import org.jrobin.core.RrdException; import org.jrobin.core.Util; /** * Class which parses at-style time specification (describided in detail on the rrdfetch man page), * used in all RRDTool commands. This code is in most parts just a java port of Tobi's parsetime.c * code. */ public class TimeParser { private static final int PREVIOUS_OP = -1; TimeToken token; TimeScanner scanner; TimeSpec spec; int op = TimeToken.PLUS; int prev_multiplier = -1; /** * Constructs TimeParser instance from the given input string. * @param dateString at-style time specification (read rrdfetch man page * for the complete explanation) */ public TimeParser(String dateString) { scanner = new TimeScanner(dateString); spec = new TimeSpec(dateString); } private void expectToken(int desired, String errorMessage) throws RrdException { token = scanner.nextToken(); if (token.id != desired) { throw new RrdException(errorMessage); } } private void plusMinus(int doop) throws RrdException { if (doop >= 0) { op = doop; expectToken(TimeToken.NUMBER, "There should be number after " + (op == TimeToken.PLUS ? '+' : '-')); prev_multiplier = -1; /* reset months-minutes guessing mechanics */ } int delta = Integer.parseInt(token.value); token = scanner.nextToken(); if (token.id == TimeToken.MONTHS_MINUTES) { /* hard job to guess what does that -5m means: -5mon or -5min? */ switch (prev_multiplier) { case TimeToken.DAYS: case TimeToken.WEEKS: case TimeToken.MONTHS: case TimeToken.YEARS: token = scanner.resolveMonthsMinutes(TimeToken.MONTHS); break; case TimeToken.SECONDS: case TimeToken.MINUTES: case TimeToken.HOURS: token = scanner.resolveMonthsMinutes(TimeToken.MINUTES); break; default: if (delta < 6) { token = scanner.resolveMonthsMinutes(TimeToken.MONTHS); } else { token = scanner.resolveMonthsMinutes(TimeToken.MINUTES); } } } prev_multiplier = token.id; delta *= (op == TimeToken.PLUS) ? +1 : -1; switch (token.id) { case TimeToken.YEARS: spec.dyear += delta; return; case TimeToken.MONTHS: spec.dmonth += delta; return; case TimeToken.WEEKS: delta *= 7; /* FALLTHRU */ case TimeToken.DAYS: spec.dday += delta; return; case TimeToken.HOURS: spec.dhour += delta; return; case TimeToken.MINUTES: spec.dmin += delta; return; case TimeToken.SECONDS: default: // default is 'seconds' spec.dsec += delta; return; } // unreachable statement // throw new RrdException("Well-known time unit expected after " + delta); } private void timeOfDay() throws RrdException { int hour, minute = 0; /* save token status in case we must abort */ scanner.saveState(); /* first pick out the time of day - we assume a HH (COLON|DOT) MM time */ if (token.value.length() > 2) { return; } hour = Integer.parseInt(token.value); token = scanner.nextToken(); if (token.id == TimeToken.SLASH || token.id == TimeToken.DOT) { /* guess we are looking at a date */ token = scanner.restoreState(); return; } if (token.id == TimeToken.COLON) { expectToken(TimeToken.NUMBER, "Parsing HH:MM syntax, expecting MM as number, got none"); minute = Integer.parseInt(token.value); if (minute > 59) { throw new RrdException("Parsing HH:MM syntax, got MM = " + minute + " (>59!)"); } token = scanner.nextToken(); } /* check if an AM or PM specifier was given */ if (token.id == TimeToken.AM || token.id == TimeToken.PM) { if (hour > 12) { throw new RrdException("There cannot be more than 12 AM or PM hours"); } if (token.id == TimeToken.PM) { if (hour != 12) { /* 12:xx PM is 12:xx, not 24:xx */ hour += 12; } } else { if (hour == 12) { /* 12:xx AM is 00:xx, not 12:xx */ hour = 0; } } token = scanner.nextToken(); } else if (hour > 23) { /* guess it was not a time then ... */ token = scanner.restoreState(); return; } spec.hour = hour; spec.min = minute; spec.sec = 0; if (spec.hour == 24) { spec.hour = 0; spec.day++; } } private void assignDate(long mday, long mon, long year) throws RrdException { if (year > 138) { if (year > 1970) { year -= 1900; } else { throw new RrdException("Invalid year " + year + " (should be either 00-99 or >1900)"); } } else if (year >= 0 && year < 38) { year += 100; /* Allow year 2000-2037 to be specified as */ } /* 00-37 until the problem of 2038 year will */ /* arise for unices with 32-bit time_t */ if (year < 70) { throw new RrdException("Won't handle dates before epoch (01/01/1970), sorry"); } spec.year = (int) year; spec.month = (int) mon; spec.day = (int) mday; } private void day() throws RrdException { long mday = 0, wday, mon, year = spec.year; switch (token.id) { case TimeToken.YESTERDAY: spec.day--; /* FALLTRHU */ case TimeToken.TODAY: /* force ourselves to stay in today - no further processing */ token = scanner.nextToken(); break; case TimeToken.TOMORROW: spec.day++; token = scanner.nextToken(); break; case TimeToken.JAN: case TimeToken.FEB: case TimeToken.MAR: case TimeToken.APR: case TimeToken.MAY: case TimeToken.JUN: case TimeToken.JUL: case TimeToken.AUG: case TimeToken.SEP: case TimeToken.OCT: case TimeToken.NOV: case TimeToken.DEC: /* do month mday [year] */ mon = (token.id - TimeToken.JAN); expectToken(TimeToken.NUMBER, "the day of the month should follow month name"); mday = Long.parseLong(token.value); token = scanner.nextToken(); if (token.id == TimeToken.NUMBER) { year = Long.parseLong(token.value); token = scanner.nextToken(); } else { year = spec.year; } assignDate(mday, mon, year); break; case TimeToken.SUN: case TimeToken.MON: case TimeToken.TUE: case TimeToken.WED: case TimeToken.THU: case TimeToken.FRI: case TimeToken.SAT: /* do a particular day of the week */ wday = (token.id - TimeToken.SUN); spec.day += (wday - spec.wday); token = scanner.nextToken(); break; case TimeToken.NUMBER: /* get numeric <sec since 1970>, MM/DD/[YY]YY, or DD.MM.[YY]YY */ // int tlen = token.value.length(); mon = Long.parseLong(token.value); if (mon > 10L * 365L * 24L * 60L * 60L) { spec.localtime(mon); token = scanner.nextToken(); break; } if (mon > 19700101 && mon < 24000101) { /*works between 1900 and 2400 */ year = mon / 10000; mday = mon % 100; mon = (mon / 100) % 100; token = scanner.nextToken(); } else { token = scanner.nextToken(); if (mon <= 31 && (token.id == TimeToken.SLASH || token.id == TimeToken.DOT)) { int sep = token.id; expectToken(TimeToken.NUMBER, "there should be " + (sep == TimeToken.DOT ? "month" : "day") + " number after " + (sep == TimeToken.DOT ? '.' : '/')); mday = Long.parseLong(token.value); token = scanner.nextToken(); if (token.id == sep) { expectToken(TimeToken.NUMBER, "there should be year number after " + (sep == TimeToken.DOT ? '.' : '/')); year = Long.parseLong(token.value); token = scanner.nextToken(); } /* flip months and days for European timing */ if (sep == TimeToken.DOT) { long x = mday; mday = mon; mon = x; } } } mon--; if (mon < 0 || mon > 11) { throw new RrdException("Did you really mean month " + (mon + 1)); } if (mday < 1 || mday > 31) { throw new RrdException("I'm afraid that " + mday + " is not a valid day of the month"); } assignDate(mday, mon, year); break; } } /** * Parses the input string specified in the constructor. * @return Object representing parsed date/time. * @throws RrdException Thrown if the date string cannot be parsed. */ public TimeSpec parse() throws RrdException { long now = Util.getTime(); int hr = 0; /* this MUST be initialized to zero for midnight/noon/teatime */ /* establish the default time reference */ spec.localtime(now); token = scanner.nextToken(); switch (token.id) { case TimeToken.PLUS: case TimeToken.MINUS: break; /* jump to OFFSET-SPEC part */ case TimeToken.START: spec.type = TimeSpec.TYPE_START; /* FALLTHRU */ case TimeToken.END: if (spec.type != TimeSpec.TYPE_START) { spec.type = TimeSpec.TYPE_END; } spec.year = spec.month = spec.day = spec.hour = spec.min = spec.sec = 0; /* FALLTHRU */ case TimeToken.NOW: int time_reference = token.id; token = scanner.nextToken(); if (token.id == TimeToken.PLUS || token.id == TimeToken.MINUS) { break; } if (time_reference != TimeToken.NOW) { throw new RrdException("Words 'start' or 'end' MUST be followed by +|- offset"); } else if (token.id != TimeToken.EOF) { throw new RrdException("If 'now' is followed by a token it must be +|- offset"); } break; /* Only absolute time specifications below */ case TimeToken.NUMBER: timeOfDay(); if (token.id != TimeToken.NUMBER) { break; } /* fix month parsing */ case TimeToken.JAN: case TimeToken.FEB: case TimeToken.MAR: case TimeToken.APR: case TimeToken.MAY: case TimeToken.JUN: case TimeToken.JUL: case TimeToken.AUG: case TimeToken.SEP: case TimeToken.OCT: case TimeToken.NOV: case TimeToken.DEC: day(); if (token.id != TimeToken.NUMBER) { break; } timeOfDay(); break; /* evil coding for TEATIME|NOON|MIDNIGHT - we've initialized * hr to zero up above, then fall into this case in such a * way so we add +12 +4 hours to it for teatime, +12 hours * to it for noon, and nothing at all for midnight, then * set our rettime to that hour before leaping into the * month scanner */ case TimeToken.TEATIME: hr += 4; /* FALLTHRU */ case TimeToken.NOON: hr += 12; /* FALLTHRU */ case TimeToken.MIDNIGHT: spec.hour = hr; spec.min = 0; spec.sec = 0; token = scanner.nextToken(); day(); break; default: throw new RrdException("Unparsable time: " + token.value); } /* * the OFFSET-SPEC part * * (NOTE, the sc_tokid was prefetched for us by the previous code) */ if (token.id == TimeToken.PLUS || token.id == TimeToken.MINUS) { scanner.setContext(false); while (token.id == TimeToken.PLUS || token.id == TimeToken.MINUS || token.id == TimeToken.NUMBER) { if (token.id == TimeToken.NUMBER) { plusMinus(PREVIOUS_OP); } else { plusMinus(token.id); } token = scanner.nextToken(); /* We will get EOF eventually but that's OK, since token() will return us as many EOFs as needed */ } } /* now we should be at EOF */ if (token.id != TimeToken.EOF) { throw new RrdException("Unparsable trailing text: " + token.value); } return spec; } } --- NEW FILE: Epoch.java --- package org.jrobin.core.timespec; import org.jrobin.core.RrdException; import org.jrobin.core.Util; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; /** * Small swing-based utility to convert timestamps (seconds since epoch) to readable dates and vice versa. * Supports at-style time specification (like "now-2d", "noon yesterday") and other human-readable * data formats:<p> * <ul> * <li>MM/dd/yy HH:mm:ss * <li>dd.MM.yy HH:mm:ss * <li>dd.MM.yy HH:mm:ss * <li>MM/dd/yy HH:mm * <li>dd.MM.yy HH:mm * <li>yy-MM-dd HH:mm * <li>MM/dd/yy * <li>dd.MM.yy * <li>yy-MM-dd * <li>HH:mm MM/dd/yy * <li>HH:mm dd.MM.yy * <li>HH:mm yy-MM-dd * <li>HH:mm:ss MM/dd/yy * <li>HH:mm:ss dd.MM.yy * <li>HH:mm:ss yy-MM-dd * </ul> * The current timestamp is displayed in the title bar :)<p> */ public class Epoch extends JFrame { private static final String[] supportedFormats = { "MM/dd/yy HH:mm:ss", "dd.MM.yy HH:mm:ss", "yy-MM-dd HH:mm:ss", "MM/dd/yy HH:mm", "dd.MM.yy HH:mm", "yy-MM-dd HH:mm", "MM/dd/yy", "dd.MM.yy", "yy-MM-dd", "HH:mm MM/dd/yy", "HH:mm dd.MM.yy", "HH:mm yy-MM-dd", "HH:mm:ss MM/dd/yy", "HH:mm:ss dd.MM.yy", "HH:mm:ss yy-MM-dd" }; private static final SimpleDateFormat[] parsers = new SimpleDateFormat[supportedFormats.length]; private static final String helpText; private Timer timer = new Timer(1000, new ActionListener() { public void actionPerformed(ActionEvent e) { showTimestamp(); } }); static { for (int i = 0; i < parsers.length; i++) { parsers[i] = new SimpleDateFormat(supportedFormats[i]); parsers[i].setLenient(true); } StringBuffer tooltipBuff = new StringBuffer("<html><b>Supported input formats:</b><br>"); for (int i = 0; i < supportedFormats.length; i++) { tooltipBuff.append(supportedFormats[i] + "<br>"); } tooltipBuff.append("<b>AT-style time specification</b><br>"); tooltipBuff.append("timestamp<br><br>"); tooltipBuff.append("Copyright (C) 2003-2005 Sasa Markovic, All Rights Reserved</html>"); helpText = tooltipBuff.toString(); } private JLabel topLabel = new JLabel("Enter timestamp or readable date:"); private JTextField inputField = new JTextField(25); private JButton convertButton = new JButton("Convert"); private JButton helpButton = new JButton("Help"); private static final SimpleDateFormat OUTPUT_DATE_FORMAT = new SimpleDateFormat("MM/dd/yy HH:mm:ss EEE"); Epoch() { super("Epoch"); constructUI(); timer.start(); } private void constructUI() { JPanel c = (JPanel) getContentPane(); c.setLayout(new BorderLayout(3, 3)); c.add(topLabel, BorderLayout.NORTH); c.add(inputField, BorderLayout.WEST); c.add(convertButton, BorderLayout.CENTER); convertButton.setToolTipText(helpText); convertButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { convert(); } }); c.add(helpButton, BorderLayout.EAST); helpButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(helpButton, helpText, "Epoch Help", JOptionPane.INFORMATION_MESSAGE); } }); inputField.requestFocus(); getRootPane().setDefaultButton(convertButton); setResizable(false); setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); centerOnScreen(); setVisible(true); } void centerOnScreen() { Toolkit t = Toolkit.getDefaultToolkit(); Dimension screenSize = t.getScreenSize(); Dimension frameSize = getPreferredSize(); double x = (screenSize.getWidth() - frameSize.getWidth()) / 2; double y = (screenSize.getHeight() - frameSize.getHeight()) / 2; setLocation((int) x, (int) y); } private void convert() { String time = inputField.getText().trim(); if (time.length() > 0) { // try simple timestamp try { long timestamp = Long.parseLong(time); Date date = new Date(timestamp * 1000L); formatDate(date); } catch (NumberFormatException nfe) { // failed, try as a date try { inputField.setText("" + parseDate(time)); } catch (RrdException e) { inputField.setText("Could not convert, sorry"); } } } } private void showTimestamp() { long timestamp = Util.getTime(); setTitle(timestamp + " seconds since epoch"); } void formatDate(Date date) { inputField.setText(OUTPUT_DATE_FORMAT.format(date)); } private long parseDate(String time) throws RrdException { for (int i = 0; i < parsers.length; i++) { try { return Util.getTimestamp(parsers[i].parse(time)); } catch (ParseException e) { } } return new TimeParser(time).parse().getTimestamp(); } /** * Main method which runs this utility. * @param args Not used. */ public static void main(String[] args) { new Epoch(); } } --- NEW FILE: TimeToken.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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.timespec; class TimeToken { public static final int MIDNIGHT = 1; public static final int NOON = 2; public static final int TEATIME = 3; public static final int PM = 4; public static final int AM = 5; public static final int YESTERDAY = 6; public static final int TODAY = 7; public static final int TOMORROW = 8; public static final int NOW = 9; public static final int START = 10; public static final int END = 11; public static final int SECONDS = 12; public static final int MINUTES = 13; public static final int HOURS = 14; public static final int DAYS = 15; public static final int WEEKS = 16; public static final int MONTHS = 17; public static final int YEARS = 18; public static final int MONTHS_MINUTES = 19; public static final int NUMBER = 20; public static final int PLUS = 21; public static final int MINUS = 22; public static final int DOT = 23; public static final int COLON = 24; public static final int SLASH = 25; public static final int ID = 26; public static final int JUNK = 27; public static final int JAN = 28; public static final int FEB = 29; public static final int MAR = 30; public static final int APR = 31; public static final int MAY = 32; public static final int JUN = 33; public static final int JUL = 34; public static final int AUG = 35; public static final int SEP = 36; public static final int OCT = 37; public static final int NOV = 38; public static final int DEC = 39; public static final int SUN = 40; public static final int MON = 41; public static final int TUE = 42; public static final int WED = 43; public static final int THU = 44; public static final int FRI = 45; public static final int SAT = 46; public static final int EOF = -1; final String value; /* token name */ final int id; /* token id */ public TimeToken(String value, int id) { this.value = value; this.id = id; } public String toString() { return value + " [" + id + "]"; } } --- NEW FILE: TimeScanner.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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.timespec; class TimeScanner { private String dateString; private int pos, pos_save; private TimeToken token, token_save; static final TimeToken[] WORDS = { new TimeToken("midnight", TimeToken.MIDNIGHT), /* 00:00:00 of today or tomorrow */ new TimeToken("noon", TimeToken.NOON), /* 12:00:00 of today or tomorrow */ new TimeToken("teatime", TimeToken.TEATIME), /* 16:00:00 of today or tomorrow */ new TimeToken("am", TimeToken.AM), /* morning times for 0-12 clock */ new TimeToken("pm", TimeToken.PM), /* evening times for 0-12 clock */ new TimeToken("tomorrow", TimeToken.TOMORROW), new TimeToken("yesterday", TimeToken.YESTERDAY), new TimeToken("today", TimeToken.TODAY), new TimeToken("now", TimeToken.NOW), new TimeToken("n", TimeToken.NOW), new TimeToken("start", TimeToken.START), new TimeToken("s", TimeToken.START), new TimeToken("end", TimeToken.END), new TimeToken("e", TimeToken.END), new TimeToken("jan", TimeToken.JAN), new TimeToken("feb", TimeToken.FEB), new TimeToken("mar", TimeToken.MAR), new TimeToken("apr", TimeToken.APR), new TimeToken("may", TimeToken.MAY), new TimeToken("jun", TimeToken.JUN), new TimeToken("jul", TimeToken.JUL), new TimeToken("aug", TimeToken.AUG), new TimeToken("sep", TimeToken.SEP), new TimeToken("oct", TimeToken.OCT), new TimeToken("nov", TimeToken.NOV), new TimeToken("dec", TimeToken.DEC), new TimeToken("january", TimeToken.JAN), new TimeToken("february", TimeToken.FEB), new TimeToken("march", TimeToken.MAR), new TimeToken("april", TimeToken.APR), new TimeToken("may", TimeToken.MAY), new TimeToken("june", TimeToken.JUN), new TimeToken("july", TimeToken.JUL), new TimeToken("august", TimeToken.AUG), new TimeToken("september", TimeToken.SEP), new TimeToken("october", TimeToken.OCT), new TimeToken("november", TimeToken.NOV), new TimeToken("december", TimeToken.DEC), new TimeToken("sunday", TimeToken.SUN), new TimeToken("sun", TimeToken.SUN), new TimeToken("monday", TimeToken.MON), new TimeToken("mon", TimeToken.MON), new TimeToken("tuesday", TimeToken.TUE), new TimeToken("tue", TimeToken.TUE), new TimeToken("wednesday", TimeToken.WED), new TimeToken("wed", TimeToken.WED), new TimeToken("thursday", TimeToken.THU), new TimeToken("thu", TimeToken.THU), new TimeToken("friday", TimeToken.FRI), new TimeToken("fri", TimeToken.FRI), new TimeToken("saturday", TimeToken.SAT), new TimeToken("sat", TimeToken.SAT), new TimeToken(null, 0) /*** SENTINEL ***/ }; static TimeToken[] MULTIPLIERS = { new TimeToken("second", TimeToken.SECONDS), /* seconds multiplier */ new TimeToken("seconds", TimeToken.SECONDS), /* (pluralized) */ new TimeToken("sec", TimeToken.SECONDS), /* (generic) */ new TimeToken("s", TimeToken.SECONDS), /* (short generic) */ new TimeToken("minute", TimeToken.MINUTES), /* minutes multiplier */ new TimeToken("minutes", TimeToken.MINUTES), /* (pluralized) */ new TimeToken("min", TimeToken.MINUTES), /* (generic) */ new TimeToken("m", TimeToken.MONTHS_MINUTES), /* (short generic) */ new TimeToken("hour", TimeToken.HOURS), /* hours ... */ new TimeToken("hours", TimeToken.HOURS), /* (pluralized) */ new TimeToken("hr", TimeToken.HOURS), /* (generic) */ new TimeToken("h", TimeToken.HOURS), /* (short generic) */ new TimeToken("day", TimeToken.DAYS), /* days ... */ new TimeToken("days", TimeToken.DAYS), /* (pluralized) */ new TimeToken("d", TimeToken.DAYS), /* (short generic) */ new TimeToken("week", TimeToken.WEEKS), /* week ... */ new TimeToken("weeks", TimeToken.WEEKS), /* (pluralized) */ new TimeToken("wk", TimeToken.WEEKS), /* (generic) */ new TimeToken("w", TimeToken.WEEKS), /* (short generic) */ new TimeToken("month", TimeToken.MONTHS), /* week ... */ new TimeToken("months", TimeToken.MONTHS), /* (pluralized) */ new TimeToken("mon", TimeToken.MONTHS), /* (generic) */ new TimeToken("year", TimeToken.YEARS), /* year ... */ new TimeToken("years", TimeToken.YEARS), /* (pluralized) */ new TimeToken("yr", TimeToken.YEARS), /* (generic) */ new TimeToken("y", TimeToken.YEARS), /* (short generic) */ new TimeToken(null, 0) /*** SENTINEL ***/ }; TimeToken[] specials = WORDS; public TimeScanner(String dateString) { this.dateString = dateString; } void setContext(boolean parsingWords) { specials = parsingWords? WORDS: MULTIPLIERS; } TimeToken nextToken() { StringBuffer buffer = new StringBuffer(""); while (pos < dateString.length()) { char c = dateString.charAt(pos++); if (Character.isWhitespace(c) || c == '_' || c == ',') { continue; } buffer.append(c); if (Character.isDigit(c)) { // pick as many digits as possible while (pos < dateString.length()) { char next = dateString.charAt(pos); if (Character.isDigit(next)) { buffer.append(next); pos++; } else { break; } } String value = buffer.toString(); return token = new TimeToken(value, TimeToken.NUMBER); } if (Character.isLetter(c)) { // pick as many letters as possible while (pos < dateString.length()) { char next = dateString.charAt(pos); if (Character.isLetter(next)) { buffer.append(next); pos++; } else { break; } } String value = buffer.toString(); return token = new TimeToken(value, parseToken(value)); } switch (c) { case ':': return token = new TimeToken(":", TimeToken.COLON); case '.': return token = new TimeToken(".", TimeToken.DOT); case '+': return token = new TimeToken("+", TimeToken.PLUS); case '-': return token = new TimeToken("-", TimeToken.MINUS); case '/': return token = new TimeToken("/", TimeToken.SLASH); default: pos--; return token = new TimeToken(null, TimeToken.EOF); } } return token = new TimeToken(null, TimeToken.EOF); } TimeToken resolveMonthsMinutes(int newId) { assert token.id == TimeToken.MONTHS_MINUTES; assert newId == TimeToken.MONTHS || newId == TimeToken.MINUTES; return token = new TimeToken(token.value, newId); } void saveState() { token_save = token; pos_save = pos; } TimeToken restoreState() { pos = pos_save; return token = token_save; } private int parseToken(String arg) { for (int i = 0; specials[i].value != null; i++) { if (specials[i].value.equalsIgnoreCase(arg)) { return specials[i].id; } } return TimeToken.ID; } } |
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15592/src/org/jrobin/core Added Files: Tag: release-1-5-2 ArcDef.java ArcState.java Archive.java ConsolFuns.java DataImporter.java Datasource.java DsDef.java DsTypes.java FetchData.java FetchRequest.java Header.java Robin.java RrdAllocator.java RrdBackend.java RrdBackendFactory.java RrdDb.java RrdDbPool.java RrdDef.java RrdDefTemplate.java RrdDouble.java RrdDoubleArray.java RrdException.java RrdFileBackend.java RrdFileBackendFactory.java RrdInt.java RrdLong.java RrdMemoryBackend.java RrdMemoryBackendFactory.java RrdNioBackend.java RrdNioBackendFactory.java RrdPrimitive.java RrdSafeFileBackend.java RrdSafeFileBackendFactory.java RrdString.java RrdToolReader.java RrdToolkit.java RrdUpdater.java Sample.java Util.java XmlReader.java XmlTemplate.java XmlWriter.java Log Message: fix import conflicts --- NEW FILE: FetchData.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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; import org.jrobin.data.Aggregates; import org.jrobin.data.DataProcessor; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; /** * Class used to represent data fetched from the RRD. * Object of this class is created when the method * {@link org.jrobin.core.FetchRequest#fetchData() fetchData()} is * called on a {@link org.jrobin.core.FetchRequest FetchRequest} object.<p> * * Data returned from the RRD is, simply, just one big table filled with * timestamps and corresponding datasource values. * Use {@link #getRowCount() getRowCount()} method to count the number * of returned timestamps (table rows).<p> * * The first table column is filled with timestamps. Time intervals * between consecutive timestamps are guaranteed to be equal. Use * {@link #getTimestamps() getTimestamps()} method to get an array of * timestamps returned.<p> * * Remaining columns are filled with datasource values for the whole timestamp range, * on a column-per-datasource basis. Use {@link #getColumnCount() getColumnCount()} to find * the number of datasources and {@link #getValues(int) getValues(i)} method to obtain * all values for the i-th datasource. Returned datasource values correspond to * the values returned with {@link #getTimestamps() getTimestamps()} method.<p> * */ public class FetchData implements ConsolFuns { // anything fuuny will do private static final String RPN_SOURCE_NAME = "WHERE THE SPEECHLES UNITE IN A SILENT ACCORD"; private FetchRequest request; private String[] dsNames; private long[] timestamps; private double[][] values; private Archive matchingArchive; private long arcStep; private long arcEndTime; FetchData(Archive matchingArchive, FetchRequest request) throws IOException { this.matchingArchive = matchingArchive; this.arcStep = matchingArchive.getArcStep(); this.arcEndTime = matchingArchive.getEndTime(); this.dsNames = request.getFilter(); if (this.dsNames == null) { this.dsNames = matchingArchive.getParentDb().getDsNames(); } this.request = request; } void setTimestamps(long[] timestamps) { this.timestamps = timestamps; } void setValues(double[][] values) { this.values = values; } /** * 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). */ public int getColumnCount() { return dsNames.length; } /** * Returns an array of timestamps covering the whole range specified in the * {@link FetchRequest FetchReguest} object. * * @return Array of equidistant timestamps. */ public long[] getTimestamps() { return timestamps; } /** * Returns the step with which this data was fetched. * * @return Step as long. */ public long getStep() { return timestamps[1] - timestamps[0]; } /** * Returns all archived values for a single datasource. * Returned values correspond to timestamps * returned with {@link #getTimestamps() getTimestamps()} method. * * @param dsIndex Datasource index. * @return Array of single datasource values. */ public double[] getValues(int dsIndex) { return values[dsIndex]; } /** * Returns all archived values for all datasources. * Returned values correspond to timestamps * returned with {@link #getTimestamps() getTimestamps()} method. * * @return Two-dimensional aray of all datasource values. */ public double[][] getValues() { 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. * @throws RrdException Thrown if no matching datasource name is found. */ public double[] getValues(String dsName) throws RrdException { for (int dsIndex = 0; dsIndex < getColumnCount(); dsIndex++) { if (dsName.equals(dsNames[dsIndex])) { return getValues(dsIndex); } } throw new RrdException("Datasource [" + dsName + "] not found"); } /** * Returns a set of values created by applying RPN expression to the fetched data. * For example, if you have two datasources named <code>x</code> and <code>y</code> * in this FetchData and you want to calculate values for <code>(x+y)/2<code> use something like: <p> * <code>getRpnValues("x,y,+,2,/");</code><p> * @param rpnExpression RRDTool-like RPN expression * @return Calculated values * @throws RrdException Thrown if invalid RPN expression is supplied */ public double[] getRpnValues(String rpnExpression) throws RrdException { DataProcessor dataProcessor = createDataProcessor(rpnExpression); return dataProcessor.getValues(RPN_SOURCE_NAME); } /** * Returns {@link FetchRequest FetchRequest} object used to create this FetchData object. * * @return Fetch request object. */ public FetchRequest getRequest() { return request; } /** * Returns the first timestamp in this FetchData object. * * @return The smallest timestamp. */ public long getFirstTimestamp() { return timestamps[0]; } /** * Returns the last timestamp in this FecthData object. * * @return The biggest timestamp. */ public long getLastTimestamp() { return timestamps[timestamps.length - 1]; } /** * Returns Archive object which is determined to be the best match for the * timestamps specified in the fetch request. All datasource values are obtained * from round robin archives belonging to this archive. * * @return Matching archive. */ public Archive getMatchingArchive() { return matchingArchive; } /** * Returns array of datasource names found in the corresponding RRD. If the request * was filtered (data was fetched only for selected datasources), only datasources selected * for fetching are returned. * * @return Array of datasource names. */ public String[] getDsNames() { 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. */ 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 ! } /** * 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(); } /** * Returns string representing fetched data in a RRDTool-like form. * * @return Fetched data as a string in a rrdfetch-like output form. */ public String toString() { // print header row StringBuffer buff = new StringBuffer(); 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" : Util.formatDouble(value); buff.append(padWithBlanks(valueStr, 18)); } buff.append("\n"); } return buff.toString(); } private static String padWithBlanks(String input, int width) { StringBuffer buff = new StringBuffer(""); int diff = width - input.length(); while (diff-- > 0) { buff.append(' '); } buff.append(input); return buff.toString(); } /** * Returns single 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", "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. */ public double getAggregate(String dsName, String consolFun) throws RrdException { DataProcessor dp = createDataProcessor(null); return dp.getAggregate(dsName, consolFun); } /** * Returns aggregated value from the fetched data for a single datasource. * Before applying aggregation functions, specified RPN expression is applied to fetched data. * For example, if you have a gauge datasource named 'foots' but you want to find the maximum * fetched value in meters use something like: <p> * <code>getAggregate("foots", "MAX", "foots,0.3048,*");</code><p> * @param dsName Datasource name * @param consolFun Consolidation function (MIN, MAX, LAST, FIRST, AVERAGE or TOTAL) * @param rpnExpression RRDTool-like RPN expression * @return Aggregated value * @throws RrdException Thrown if the given datasource name cannot be found in fetched data, or if * invalid RPN expression is supplied * @throws IOException Thrown in case of I/O error (unlikely to happen) * @deprecated This method is preserved just for backward compatibility. */ public double getAggregate(String dsName, String consolFun, String rpnExpression) throws RrdException, IOException { // for backward compatibility rpnExpression = rpnExpression.replaceAll("value", dsName); return getRpnAggregate(rpnExpression, consolFun); } /** * Returns aggregated value for a set of values calculated by applying an RPN expression to the * fetched data. For example, if you have two datasources named <code>x</code> and <code>y</code> * in this FetchData and you want to calculate MAX value of <code>(x+y)/2<code> use something like: <p> * <code>getRpnAggregate("x,y,+,2,/", "MAX");</code><p> * @param rpnExpression RRDTool-like RPN expression * @param consolFun Consolidation function (MIN, MAX, LAST, FIRST, AVERAGE or TOTAL) * @return Aggregated value * @throws RrdException Thrown if invalid RPN expression is supplied */ public double getRpnAggregate(String rpnExpression, String consolFun) throws RrdException { DataProcessor dataProcessor = createDataProcessor(rpnExpression); return dataProcessor.getAggregate(RPN_SOURCE_NAME, consolFun); } /** * Returns all aggregated values (MIN, MAX, LAST, FIRST, AVERAGE or TOTAL) calculated from the fetched data * for a single datasource. * * @param dsName Datasource name. * @return Simple object containing all aggregated values. * @throws RrdException Thrown if the given datasource name cannot be found in the fetched data. */ public Aggregates getAggregates(String dsName) throws RrdException { DataProcessor dataProcessor = createDataProcessor(null); return dataProcessor.getAggregates(dsName); } /** * Returns all aggregated values for a set of values calculated by applying an RPN expression to the * fetched data. For example, if you have two datasources named <code>x</code> and <code>y</code> * in this FetchData and you want to calculate MIN, MAX, LAST, FIRST, AVERAGE and TOTAL value * of <code>(x+y)/2<code> use something like: <p> * <code>getRpnAggregates("x,y,+,2,/");</code><p> * @param rpnExpression RRDTool-like RPN expression * @return Object containing all aggregated values * @throws RrdException Thrown if invalid RPN expression is supplied */ public Aggregates getRpnAggregates(String rpnExpression) throws RrdException, IOException { DataProcessor dataProcessor = createDataProcessor(rpnExpression); return dataProcessor.getAggregates(RPN_SOURCE_NAME); } /** * 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:<p> * <a href="http://www.red.net/support/resourcecentre/leasedline/percentile.php">Rednet</a> or<br> * <a href="http://www.bytemark.co.uk/support/tech/95thpercentile.html">Bytemark</a>. * * @param dsName Datasource name * @return 95th percentile of fetched source values * @throws RrdException Thrown if invalid source name is supplied */ public double get95Percentile(String dsName) throws RrdException { DataProcessor dataProcessor = createDataProcessor(null); return dataProcessor.get95Percentile(dsName); } /** * Same as {@link #get95Percentile(String)}, but for a set of values calculated with the given * RPN expression. * @param rpnExpression RRDTool-like RPN expression * @return 95-percentile * @throws RrdException Thrown if invalid RPN expression is supplied */ public double getRpn95Percentile(String rpnExpression) throws RrdException { DataProcessor dataProcessor = createDataProcessor(rpnExpression); return dataProcessor.get95Percentile(RPN_SOURCE_NAME); } /** * 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 */ public void exportXml(OutputStream outputStream) throws IOException { XmlWriter writer = new XmlWriter(outputStream); writer.startTag("fetch_data"); writer.startTag("request"); writer.writeTag("file", request.getParentDb().getPath()); writer.writeComment(Util.getDate(request.getFetchStart())); writer.writeTag("start", request.getFetchStart()); writer.writeComment(Util.getDate(request.getFetchEnd())); writer.writeTag("end", request.getFetchEnd()); writer.writeTag("resolution", request.getResolution()); writer.writeTag("cf", request.getConsolFun()); 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]); } writer.closeTag(); // values writer.closeTag(); // row } writer.closeTag(); // data writer.closeTag(); // fetch_data writer.flush(); } /** * Dumps fetch data to file in XML format. * * @param filepath Path to destination file * @throws IOException Thrown in case of I/O error */ public void exportXml(String filepath) throws IOException { OutputStream outputStream = null; try { outputStream = new FileOutputStream(filepath); exportXml(outputStream); } finally { if (outputStream != null) { outputStream.close(); } } } /** * Dumps fetch data in XML format. * * @return String containing XML formatted fetch data * @throws IOException Thrown in case of I/O error */ public String exportXml() throws IOException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); exportXml(outputStream); return outputStream.toString(); } /** * Returns the step of the corresponding RRA archive * @return Archive step in seconds */ public long getArcStep() { return arcStep; } /** * Returns the timestamp of the last populated slot in the corresponding RRA archive * @return Timestamp in seconds */ public long getArcEndTime() { return arcEndTime; } private DataProcessor createDataProcessor(String rpnExpression) throws RrdException { DataProcessor dataProcessor = new DataProcessor(request.getFetchStart(), request.getFetchEnd()); for(int i = 0; i < dsNames.length; i++) { dataProcessor.addDatasource(dsNames[i], this); } if(rpnExpression != null) { dataProcessor.addDatasource(RPN_SOURCE_NAME, rpnExpression); try { dataProcessor.processData(); } catch(IOException ioe) { // highly unlikely, since all datasources have already calculated values throw new RuntimeException("Impossible error: " + ioe); } } return dataProcessor; } } --- NEW FILE: RrdFileBackend.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileLock; import java.util.HashSet; import java.util.Set; /** * JRobin backend which is used to store RRD data to ordinary files on the disk. This was the * default factory before 1.4.0 version<p> * <p/> * This backend is based on the RandomAccessFile class (java.io.* package). */ public class RrdFileBackend extends RrdBackend { private static final long LOCK_DELAY = 100; // 0.1sec private static Set<String> openFiles = new HashSet<String>(); /** read/write file status */ protected boolean readOnly; /** locking mode */ protected int lockMode; /** radnom access file handle */ protected RandomAccessFile file; /** file lock */ protected FileLock fileLock; /** * 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 Locking mode, as described in {@link RrdDb#getLockMode()} * @throws IOException Thrown in case of I/O error */ protected RrdFileBackend(String path, boolean readOnly, int lockMode) throws IOException { super(path); this.readOnly = readOnly; this.lockMode = lockMode; file = new RandomAccessFile(path, readOnly ? "r" : "rw"); try { lockFile(); registerWriter(); } catch(IOException ioe) { close(); throw ioe; } } private void lockFile() throws IOException { switch (lockMode) { case RrdDb.EXCEPTION_IF_LOCKED: fileLock = file.getChannel().tryLock(); if (fileLock == null) { // could not obtain lock throw new IOException("Access denied. " + "File [" + getPath() + "] already locked"); } break; case RrdDb.WAIT_IF_LOCKED: while (fileLock == null) { fileLock = file.getChannel().tryLock(); if (fileLock == null) { // could not obtain lock, wait a little, than try again try { Thread.sleep(LOCK_DELAY); } catch (InterruptedException e) { // NOP } } } break; case RrdDb.NO_LOCKS: break; } } private void registerWriter() throws IOException { if (!readOnly) { String path = getPath(); String canonicalPath = getCanonicalPath(path); synchronized (openFiles) { if (openFiles.contains(canonicalPath)) { throw new IOException("File \"" + path + "\" already open for R/W access. " + "You cannot open the same file for R/W access twice"); } else { openFiles.add(canonicalPath); } } } } /** * Closes the underlying RRD file. * * @throws IOException Thrown in case of I/O error */ public void close() throws IOException { unregisterWriter(); try { unlockFile(); } finally { file.close(); } } private void unlockFile() throws IOException { if (fileLock != null) { fileLock.release(); } } private void unregisterWriter() throws IOException { if (!readOnly) { String path = getPath(); String canonicalPath = getCanonicalPath(path); synchronized (openFiles) { openFiles.remove(canonicalPath); } } } /** * Returns canonical path to the file on the disk. * * @param path File path * @return Canonical file path * @throws IOException Thrown in case of I/O error */ public static String getCanonicalPath(String path) throws IOException { return Util.getCanonicalPath(path); } /** * Returns canonical path to the file on the disk. * * @return Canonical file path * @throws IOException Thrown in case of I/O error */ public String getCanonicalPath() throws IOException { return RrdFileBackend.getCanonicalPath(getPath()); } /** * Writes bytes to the underlying RRD file on the disk * * @param offset Starting file offset * @param b Bytes to be written. * @throws IOException Thrown in case of I/O error */ protected void write(long offset, byte[] b) throws IOException { file.seek(offset); file.write(b); } /** * Reads a number of bytes from the RRD file on the disk * * @param offset Starting file offset * @param b Buffer which receives bytes read from the file. * @throws IOException Thrown in case of I/O error. */ protected void read(long offset, byte[] b) throws IOException { file.seek(offset); if (file.read(b) != b.length) { throw new IOException("Not enough bytes available in file " + getPath()); } } /** * Returns RRD file length. * * @return File length. * @throws IOException Thrown in case of I/O error. */ public long getLength() throws IOException { return file.length(); } /** * Sets length of the underlying RRD file. This method is called only once, immediately * after a new RRD file gets created. * * @param length Length of the RRD file * @throws IOException Thrown in case of I/O error. */ protected void setLength(long length) throws IOException { file.setLength(length); } } --- NEW FILE: RrdFileBackendFactory.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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; import java.io.IOException; /** * Factory class which creates actual {@link RrdFileBackend} objects. This was the default * backend factory in JRobin before 1.4.0 release. */ public class RrdFileBackendFactory extends RrdBackendFactory { /** factory name, "FILE" */ public static final String NAME = "FILE"; /** * Creates RrdFileBackend 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 One of the following constants: {@link RrdDb#NO_LOCKS}, * {@link RrdDb#EXCEPTION_IF_LOCKED} or {@link RrdDb#WAIT_IF_LOCKED}. * @return RrdFileBackend 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 RrdFileBackend(path, readOnly, lockMode); } /** * Method to determine if a file with the given path already exists. * @param path File path * @return True, if such file exists, false otherwise. */ protected boolean exists(String path) { return Util.fileExists(path); } /** * Returns the name of this factory. * @return Factory name (equals to string "FILE") */ public String getFactoryName() { return NAME; } } --- NEW FILE: XmlTemplate.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.InputSource; import java.awt.*; import java.io.File; import java.io.IOException; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Class used as a base class for various XML template related classes. Class provides * methods for XML source parsing and XML tree traversing. XML source may have unlimited * number of placeholders (variables) in the format <code>${variable_name}</code>. * Methods are provided to specify variable values at runtime. * Note that this class has limited functionality: XML source gets parsed, and variable * values are collected. You have to extend this class to do something more useful.<p> */ public abstract class XmlTemplate { private static final String PATTERN_STRING = "\\$\\{(\\w+)\\}"; private static final Pattern PATTERN = Pattern.compile(PATTERN_STRING); protected Element root; private HashMap<String, Object> valueMap = new HashMap<String, Object>(); private HashSet<Node> validatedNodes = new HashSet<Node>(); protected XmlTemplate(InputSource xmlSource) throws IOException, RrdException { root = Util.Xml.getRootElement(xmlSource); } protected XmlTemplate(String xmlString) throws IOException, RrdException { root = Util.Xml.getRootElement(xmlString); } protected XmlTemplate(File xmlFile) throws IOException, RrdException { root = Util.Xml.getRootElement(xmlFile); } /** * Removes all placeholder-value mappings. */ public void clearValues() { valueMap.clear(); } /** * Sets value for a single XML template variable. Variable name should be specified * without leading '${' and ending '}' placeholder markers. For example, for a placeholder * <code>${start}</code>, specify <code>start</start> for the <code>name</code> parameter. * * @param name variable name * @param value value to be set in the XML template */ public void setVariable(String name, String value) { valueMap.put(name, value); } /** * Sets value for a single XML template variable. Variable name should be specified * without leading '${' and ending '}' placeholder markers. For example, for a placeholder * <code>${start}</code>, specify <code>start</start> for the <code>name</code> parameter. * * @param name variable name * @param value value to be set in the XML template */ public void setVariable(String name, int value) { valueMap.put(name, new Integer(value)); } /** * Sets value for a single XML template variable. Variable name should be specified * without leading '${' and ending '}' placeholder markers. For example, for a placeholder * <code>${start}</code>, specify <code>start</start> for the <code>name</code> parameter. * * @param name variable name * @param value value to be set in the XML template */ public void setVariable(String name, long value) { valueMap.put(name, new Long(value)); } /** * Sets value for a single XML template variable. Variable name should be specified * without leading '${' and ending '}' placeholder markers. For example, for a placeholder * <code>${start}</code>, specify <code>start</start> for the <code>name</code> parameter. * * @param name variable name * @param value value to be set in the XML template */ public void setVariable(String name, double value) { valueMap.put(name, new Double(value)); } /** * Sets value for a single XML template variable. Variable name should be specified * without leading '${' and ending '}' placeholder markers. For example, for a placeholder * <code>${start}</code>, specify <code>start</start> for the <code>name</code> parameter. * * @param name variable name * @param value value to be set in the XML template */ public void setVariable(String name, Color value) { String r = byteToHex(value.getRed()); String g = byteToHex(value.getGreen()); String b = byteToHex(value.getBlue()); String a = byteToHex(value.getAlpha()); valueMap.put(name, "#" + r + g + b + a); } private String byteToHex(int i) { String s = Integer.toHexString(i); while(s.length() < 2) { s = "0" + s; } return s; } /** * Sets value for a single XML template variable. Variable name should be specified * without leading '${' and ending '}' placeholder markers. For example, for a placeholder * <code>${start}</code>, specify <code>start</start> for the <code>name</code> parameter. * * @param name variable name * @param value value to be set in the XML template */ public void setVariable(String name, Date value) { setVariable(name, Util.getTimestamp(value)); } /** * Sets value for a single XML template variable. Variable name should be specified * without leading '${' and ending '}' placeholder markers. For example, for a placeholder * <code>${start}</code>, specify <code>start</start> for the <code>name</code> parameter. * * @param name variable name * @param value value to be set in the XML template */ public void setVariable(String name, Calendar value) { setVariable(name, Util.getTimestamp(value)); } /** * Sets value for a single XML template variable. Variable name should be specified * without leading '${' and ending '}' placeholder markers. For example, for a placeholder * <code>${start}</code>, specify <code>start</start> for the <code>name</code> parameter. * * @param name variable name * @param value value to be set in the XML template */ public void setVariable(String name, boolean value) { valueMap.put(name, "" + value); } /** * Searches the XML template to see if there are variables in there that * will need to be set. * * @return True if variables were detected, false if not. */ public boolean hasVariables() { return PATTERN.matcher(root.toString()).find(); } /** * Returns the list of variables that should be set in this template. * * @return List of variable names as an array of strings. */ public String[] getVariables() { ArrayList<String> list = new ArrayList<String>(); Matcher m = PATTERN.matcher(root.toString()); while (m.find()) { String var = m.group(1); if (!list.contains(var)) { list.add(var); } } return list.toArray(new String[list.size()]); } protected static Node[] getChildNodes(Node parentNode, String childName) { return Util.Xml.getChildNodes(parentNode, childName); } protected static Node[] getChildNodes(Node parentNode) { return Util.Xml.getChildNodes(parentNode, null); } protected static Node getFirstChildNode(Node parentNode, String childName) throws RrdException { return Util.Xml.getFirstChildNode(parentNode, childName); } protected boolean hasChildNode(Node parentNode, String childName) { return Util.Xml.hasChildNode(parentNode, childName); } protected String getChildValue(Node parentNode, String childName) throws RrdException { return getChildValue(parentNode, childName, true); } protected String getChildValue(Node parentNode, String childName, boolean trim) throws RrdException { String value = Util.Xml.getChildValue(parentNode, childName, trim); return resolveMappings(value); } protected String getValue(Node parentNode) { return getValue(parentNode, true); } protected String getValue(Node parentNode, boolean trim) { String value = Util.Xml.getValue(parentNode, trim); return resolveMappings(value); } private String resolveMappings(String templateValue) { if (templateValue == null) { return null; } Matcher matcher = PATTERN.matcher(templateValue); StringBuffer result = new StringBuffer(); int lastMatchEnd = 0; while (matcher.find()) { String var = matcher.group(1); if (valueMap.containsKey(var)) { // mapping found result.append(templateValue.substring(lastMatchEnd, matcher.start())); result.append(valueMap.get(var).toString()); lastMatchEnd = matcher.end(); } else { // no mapping found - this is illegal // throw runtime exception throw new IllegalArgumentException("No mapping found for template variable ${" + var + "}"); } } result.append(templateValue.substring(lastMatchEnd)); return result.toString(); } protected int getChildValueAsInt(Node parentNode, String childName) throws RrdException { String valueStr = getChildValue(parentNode, childName); return Integer.parseInt(valueStr); } protected int getValueAsInt(Node parentNode) { String valueStr = getValue(parentNode); return Integer.parseInt(valueStr); } protected long getChildValueAsLong(Node parentNode, String childName) throws RrdException { String valueStr = getChildValue(parentNode, childName); return Long.parseLong(valueStr); } protected long getValueAsLong(Node parentNode) { String valueStr = getValue(parentNode); return Long.parseLong(valueStr); } protected double getChildValueAsDouble(Node parentNode, String childName) throws RrdException { String valueStr = getChildValue(parentNode, childName); return Util.parseDouble(valueStr); } protected double getValueAsDouble(Node parentNode) { String valueStr = getValue(parentNode); return Util.parseDouble(valueStr); } protected boolean getChildValueAsBoolean(Node parentNode, String childName) throws RrdException { String valueStr = getChildValue(parentNode, childName); return Util.parseBoolean(valueStr); } protected boolean getValueAsBoolean(Node parentNode) { String valueStr = getValue(parentNode); return Util.parseBoolean(valueStr); } protected Paint getValueAsColor(Node parentNode) throws RrdException { String rgbStr = getValue(parentNode); return Util.parseColor(rgbStr); } protected boolean isEmptyNode(Node node) { // comment node or empty text node return node.getNodeName().equals("#comment") || (node.getNodeName().equals("#text") && node.getNodeValue().trim().length() == 0); } protected void validateTagsOnlyOnce(Node parentNode, String[] allowedChildNames) throws RrdException { // validate node only once if (validatedNodes.contains(parentNode)) { return; } Node[] childs = getChildNodes(parentNode); main: for (int i = 0; i < childs.length; i++) { String childName = childs[i].getNodeName(); for (int j = 0; j < allowedChildNames.length; j++) { if (allowedChildNames[j].equals(childName)) { // only one such tag is allowed allowedChildNames[j] = "<--removed-->"; continue main; } else if (allowedChildNames[j].equals(childName + "*")) { // several tags allowed continue main; } } if (!isEmptyNode(childs[i])) { throw new RrdException("Unexpected tag encountered: <" + childName + ">"); } } // everything is OK validatedNodes.add(parentNode); } } --- NEW FILE: RrdDouble.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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; import java.io.IOException; class RrdDouble extends RrdPrimitive { private double cache; 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); } 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(); } } --- NEW FILE: RrdUpdater.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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; import java.io.IOException; interface RrdUpdater { public RrdBackend getRrdBackend(); public void copyStateTo(RrdUpdater updater) throws IOException, RrdException; public RrdAllocator getRrdAllocator(); } --- NEW FILE: RrdString.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, 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...) * * * 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; import java.io.IOException; class RrdString extends RrdPrimitive { private String cache; RrdString(RrdUpdater updater, boolean isConstant) throws IOException { super(updater, RrdPrimitive.RRD_STRING, isConstant); } RrdString(RrdUpdater updater) throws IOException { this(updater, false); } 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(); } } --- NEW FILE: XmlWriter.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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; import java.awt.*; import java.io.File; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Stack; /** * Extremely simple utility class used to create XML documents. */ public class XmlWriter { static final String INDENT_STR = " "; private PrintWriter writer; private StringBuffer indent = new StringBuffer(""); private Stack<String> openTags = new Stack<String>(); /** * Creates XmlWriter with the specified output stream to send XML code to. * @param stream Output stream which receives XML code */ public XmlWriter(OutputStream stream) { writer = new PrintWriter(stream, true); } /** * Opens XML tag * @param tag XML tag name */ public void startTag(String tag) { writer.println(indent + "<" + tag + ">"); openTags.push(tag); indent.append(INDENT_STR); } /** * Closes the corresponding XML tag */ public void closeTag() { String tag = openTags.pop(); indent.setLength(indent.length() - INDENT_STR.length()); writer.println(indent + "</" + tag + ">"); } /** * Writes <tag>value</tag> to output stream * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, Object value) { if(value != null) { writer.println(indent + "<" + tag + ">" + escape(value.toString()) + "</" + tag + ">"); } else { writer.println(indent + "<" + tag + "></" + tag + ">"); } } /** * Writes <tag>value</tag> to output stream * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, int value) { writeTag(tag, "" + value); } /** * Writes <tag>value</tag> to output stream * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, long value) { writeTag(tag, "" + value); } /** * Writes <tag>value</tag> to output stream * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, double value, String nanString) { writeTag(tag, Util.formatDouble(value, nanString, true)); } /** * Writes <tag>value</tag> to output stream * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, double value) { writeTag(tag, Util.formatDouble(value, true)); } /** * Writes <tag>value</tag> to output stream * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, boolean value) { writeTag(tag, "" + value); } /** * Writes <tag>value</tag> to output stream * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, Color value) { int rgb = value.getRGB() & 0xFFFFFF; writeTag(tag, "#" + Integer.toHexString(rgb).toUpperCase()); } /** * Writes <tag>value</tag> to output stream * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, Font value) { startTag(tag); writeTag("name", value.getName()); int style = value.getStyle(); if((style & Font.BOLD) != 0 && (style & Font.ITALIC) != 0) { writeTag("style", "BOLDITALIC"); } else if((style & Font.BOLD) != 0) { writeTag("style", "BOLD"); } else if((style & Font.ITALIC) != 0) { writeTag("style", "ITALIC"); } else { writeTag("style", "PLAIN"); } writeTag("size", value.getSize()); closeTag(); } /** * Writes <tag>value</tag> to output stream * @param tag XML tag name * @param value value to be placed between <code><tag></code> and <code></tag></code> */ public void writeTag(String tag, File value) { writeTag(tag, value.getPath()); } /** * Flushes the output stream */ public void flush() { writer.flush(); } protected void finalize() { writer.close(); } /** * Writes XML comment to output stream * @param comment comment string */ public void writeComment(Object comment) { writer.println(indent + "<!-- " + escape(comment.toString()) + " -->"); } private static String escape(String s) { return s.replaceAll("<", "<").replaceAll(">", ">"); } } --- NEW FILE: RrdNioBackendFactory.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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; import java.io.IOException; /** * Factory class which creates actual {@link RrdNioBackend} objects. This is the default factory since * 1.4.0 version */ public class RrdNioBackendFactory extends RrdFileBackendFactory{ /** factory name, "NIO" */ public static final String NAME = "NIO"; /** See {@link #setSyncMode(int)} for explanation */ public static final int SYNC_ONCLOSE = 0; // will sync() only on close() /** See {@link #setSyncMode(int)} for explanation */ public static final int SYNC_BEFOREUPDATE = 1; /** See {@link #setSyncMode(int)} for explanation */ public static final int SYNC_AFTERUPDATE = 2; /** See {@link #setSyncMode(int)} for explanation */ public static final int SYNC_BEFOREFETCH = 3; /** See {@link #setSyncMode(int)} for explanation */ public static final int SYNC_AFTERFETCH = 4; /** See {@link #setSyncMode(int)} for explanation */ public static final int SYNC_BACKGROUND = 5; /** * Period in seconds between consecutive synchronizations when * sync-mode is set to SYNC_BACKGROUND. By default in-memory cache will be * transferred to the disc every 300 seconds (5 minutes). Default value can be * changed via {@link #setSyncPeriod(int)} method. */ public static final int DEFAULT_SYNC_PERIOD = 300; // seconds private static int syncMode = SYNC_BACKGROUND; private static int syncPeriod = DEFAULT_SYNC_PERIOD; /** * Returns the current synchronization mode between backend data in memory and data * in the persistent storage (disk file). * * @return Integer representing current synchronization mode (SYNC_ONCLOSE, * SYNC_BEFOREUPDATE, SYNC_AFTERUPDATE, SYNC_BEFOREFETCH, SYNC_AFTERFETCH or * SYNC_BACKGROUND). See {@link #setSyncMode(int)} for full explanation of these return values. */ public static int getSyncMode() { return syncMode; } /** * Sets the current synchronization mode between backend data in memory (backend cache) and * RRD data in the persistant storage (disk file).<p> * @param syncMode Desired synchronization mode. Possible values are:<p> * <ul> * <li>SYNC_ONCLOSE: synchronization will be performed only when {@link RrdDb#close()} * is called (RRD file is closed) or when {@link RrdDb#sync()} method is called. * <li>SYNC_BEFOREUPDATE: synchronization will be performed before each {@link Sample#update()} * call (right before RRD file is about to be updated). * <li>SYNC_AFTERUPDATE: synchronization will be performed after each {@link Sample#update()} * call (right after RRD file is updated). * <li>SYNC_BEFOREFETCH: synchronization will be performed before each * {@link FetchRequest#fetchData()} call (right before data is about to be fetched from a RRD file, * for example for graph creation) * <li>SYNC_AFTERFETCH: synchronization will be performed after each * {@link FetchRequest#fetchData()} call (right after data is fetched from a RRD file) * <li>SYNC_BACKGROUND (<b>default</b>): synchronization will be performed automatically * from a separate thread on a regular basis. Period of time between the two consecutive * synchronizations can be controlled with {@link #setSyncPeriod(int)}. * </ul> */ public static void setSyncMode(int syncMode) { RrdNioBackendFactory.syncMode = syncMode; } /** * Returns time between two consecutive background synchronizations. If not changed via * {@link #setSyncPeriod(int)} method call, defaults to {@link #DEFAULT_SYNC_PERIOD}. * See {@link #setSyncPeriod(int)} for more information. * @return Time in seconds between consecutive background synchronizations. */ public static int getSyncPeriod() { return syncPeriod; } /** * Sets time between consecutive background synchronizations. Method is effective only if * synchronization mode is set to SYNC_BACKGROUND. * @param syncPeriod Time in seconds between consecutive background synchronizations. */ public static void setSyncPeriod(int syncPeriod) { RrdNioBackendFactory.syncPeriod = syncPeriod; } /** * Creates RrdNioBackend 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 One of the following constants: {@link RrdDb#NO_LOCKS}, * {@link RrdDb#EXCEPTION_IF_LOCKED} or {@link RrdDb#WAIT_IF_LOCKED}. * @return RrdNioBackend 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 RrdNioBackend(path, readOnly, lockMode, syncMode, syncPeriod); } /** * Returns the name of this factory. * @return Factory name (equals to string "NIO") */ public String getFactoryName() { return NAME; } } --- NEW FILE: RrdSafeFileBackendFactory.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, 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...) * * * 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; 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: XmlReader.java --- /* ============================================================ * JRobin : Pure java implementation of RRDTool's functionality * ============================================================ * * Project Info: http://www.jrobin.org * Project Lead: Sasa Markovic (sa...@jr...); * * (C) Copyright 2003-2005, by Sasa Markovic. * * Developers: Sasa Markovic (sa...@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; import org.w3c.dom.Element; import org.w3c.dom.Node; import java.io.File; import java.io.IOException; class XmlReader extends DataImporter { private Element root; private Node[] dsNodes, arcNodes; XmlReader(String xmlFilePath) throws IOException, RrdException { root = Util.Xml.getRootElement(new File(xmlFilePath)); dsNodes = Util.Xml.getChildNodes(root, "ds"); arcNodes = Util.Xml.getChildNodes(root, "rra"); ... [truncated message content] |
From: DJ G. <djg...@us...> - 2005-09-06 19:37:42
|
Update of /cvsroot/jrobin/ant In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19566/ant Modified Files: Tag: release-1-4-0 build.xml Log Message: apply change to build.xml that's in the released 1.4.0 files Index: build.xml =================================================================== RCS file: /cvsroot/jrobin/ant/build.xml,v retrieving revision 1.3 retrieving revision 1.3.2.1 diff -C2 -d -r1.3 -r1.3.2.1 *** build.xml 12 Jul 2004 14:01:41 -0000 1.3 --- build.xml 6 Sep 2005 19:37:27 -0000 1.3.2.1 *************** *** 161,164 **** --- 161,165 ---- destdir="${cwd}/${javadoc}" packagenames="org.jrobin.core.*,org.jrobin.graph.*" + excludepackagenames="org.jrobin.core.jrrd.*" source="1.4" sourcepath="${cwd}/${src}" |
From: Arne V. <cob...@us...> - 2005-04-06 20:10:20
|
Update of /cvsroot/jrobin/src/org/jrobin/graph In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8322/org/jrobin/graph Modified Files: Area.java Gprint.java Grapher.java Line.java LinearInterpolator.java PlotDef.java RrdExportDef.java RrdExporter.java RrdGraphDefTemplate.java Stack.java Log Message: - First support of DataProcessor into Graph.* package. Index: Grapher.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/Grapher.java,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** Grapher.java 23 Jan 2005 20:31:26 -0000 1.21 --- Grapher.java 6 Apr 2005 20:10:10 -0000 1.22 *************** *** 39,42 **** --- 39,44 ---- import org.jrobin.core.RrdException; import org.jrobin.core.Util; + import org.jrobin.core.ConsolFuns; + import org.jrobin.data.Aggregates; /** *************** *** 131,135 **** startTime = graphDef.getStartTime(); ! endTime = graphDef.getStartTime(); } --- 133,137 ---- startTime = graphDef.getStartTime(); ! endTime = graphDef.getEndTime(); } *************** *** 341,345 **** super.calculateSeries( chartWidth ); ! numPoints = numRows; /** --- 343,353 ---- super.calculateSeries( chartWidth ); ! tsChart = processor.getTimestamps(); ! numPoints = tsChart.length; ! ! plotDefs = graphDef.getPlotDefs(); ! ! for ( int i = 0; i < plotDefs.length; i++ ) ! plotDefs[i].setProcessor( processor ); /** *************** *** 347,350 **** --- 355,359 ---- * this allows for much nicer graphing. */ + /* tsChart = new long[ chartWidth ]; plotDefs = graphDef.getPlotDefs(); *************** *** 365,368 **** --- 374,378 ---- tsChart[i] = t; } + */ } *************** *** 458,466 **** } // For autoscale, detect lower and upper limit of values for ( int i = 0; i < plotDefs.length; i++ ) { ! Source src = plotDefs[i].getSource(); ! // Only try autoscale when we do not have a rigid grid if ( !rigid && src != null ) --- 468,525 ---- } + // For autoscale, detect lower and upper limit of values for ( int i = 0; i < plotDefs.length; i++ ) { ! String srcName = plotDefs[i].getSourceName(); ! ! if ( srcName == null || "".equals( srcName ) ) continue; ! ! Aggregates agg = processor.getAggregates( srcName ); ! ! // Only try autoscale when we do not have a rigid grid ! if ( !rigid ) ! { ! double min = agg.getMin(); ! double max = agg.getMax(); ! ! // If the plotdef is a stack, evaluate ALL previous values to find a possible max ! if ( plotDefs[i].plotType == PlotDef.PLOT_STACK && i >= 1 ) ! { ! if ( plotDefs[i - 1].plotType == PlotDef.PLOT_STACK ) { // Use this source plus stack of previous ones ! ! for (int j = 0; j < tmpSeries.length; j++) ! { ! val = tmpSeries[j] + plotDefs[i].getValue(j, timestamps); ! ! if ( val < lowerValue ) lowerValue = val; ! if ( val > upperValue ) upperValue = val; ! ! tmpSeries[j] = val; ! } ! } ! else { // Use this source plus the previous one ! ! for (int j = 0; j < tmpSeries.length; j++) ! { ! val = plotDefs[i - 1].getValue(j, timestamps) + plotDefs[i].getValue(j, timestamps); ! ! if ( val < lowerValue ) lowerValue = val; ! if ( val > upperValue ) upperValue = val; ! ! tmpSeries[j] = val; ! } ! ! } ! } ! else // Only use min/max of a single datasource ! { ! if ( min < lowerValue ) lowerValue = min; ! if ( max > upperValue ) upperValue = max; ! } ! } ! ! /*Source src = plotDefs[i].getSource(); ! // Only try autoscale when we do not have a rigid grid if ( !rigid && src != null ) *************** *** 503,507 **** if ( max > upperValue ) upperValue = max; } ! } } --- 562,566 ---- if ( max > upperValue ) upperValue = max; } ! }*/ } *************** *** 509,513 **** vGrid = new ValueGrid( range, lowerValue, upperValue, graphDef.getValueAxis(), graphDef.getBaseValue() ); tGrid = new TimeGrid( startTime, endTime, graphDef.getTimeAxis(), graphDef.getFirstDayOfWeek() ); ! lowerValue = vGrid.getLowerValue(); upperValue = vGrid.getUpperValue(); --- 568,572 ---- vGrid = new ValueGrid( range, lowerValue, upperValue, graphDef.getValueAxis(), graphDef.getBaseValue() ); tGrid = new TimeGrid( startTime, endTime, graphDef.getTimeAxis(), graphDef.getFirstDayOfWeek() ); ! lowerValue = vGrid.getLowerValue(); upperValue = vGrid.getUpperValue(); *************** *** 724,728 **** } else if ( clist[i].commentType == Comment.CMT_GPRINT ) ! ((Gprint) clist[i]).setValue( sources, sourceIndex, valueFormat ); ArrayList tknpairs = clist[i].getTokens(); --- 783,787 ---- } else if ( clist[i].commentType == Comment.CMT_GPRINT ) ! ((Gprint) clist[i]).setValue( processor, valueFormat );//.setValue( sources, sourceIndex, valueFormat ); ArrayList tknpairs = clist[i].getTokens(); Index: RrdExportDef.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/RrdExportDef.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** RrdExportDef.java 21 Sep 2004 08:42:10 -0000 1.4 --- RrdExportDef.java 6 Apr 2005 20:10:10 -0000 1.5 *************** *** 33,36 **** --- 33,37 ---- import org.jrobin.core.RrdException; import org.jrobin.core.XmlWriter; + import org.jrobin.data.DataProcessor; /** *************** *** 69,72 **** --- 70,75 ---- protected ArrayList edefList = new ArrayList( 3 ); // holds the list of export data objects + private DataProcessor processor = new DataProcessor(); + // ================================================================ // -- Constructors *************** *** 127,135 **** public void setTimePeriod( long startTime, long endTime ) throws RrdException { ! if ( startTime < 0 || ( endTime != 0 && endTime <= startTime ) ) ! throw new RrdException( "Invalid start/end time: " + startTime + "/" + endTime ); ! ! this.startTime = startTime; ! this.endTime = endTime; } --- 130,134 ---- public void setTimePeriod( long startTime, long endTime ) throws RrdException { ! processor.setTimePeriod( startTime, endTime ); } *************** *** 166,170 **** public void setResolution( long resolution ) { ! this.resolution = resolution; } --- 165,169 ---- public void setResolution( long resolution ) { ! processor.setFetchRequestResolution( resolution ); } *************** *** 188,194 **** public void datasource( String name, String file, String dsName, String consolFunc ) throws RrdException { ! fetchSources.add( name, file, dsName, consolFunc ); ! ! numDefs++; } --- 187,191 ---- public void datasource( String name, String file, String dsName, String consolFunc ) throws RrdException { ! processor.addDatasource( name, file, dsName, consolFunc ); } *************** *** 213,219 **** public void datasource( String name, String file, String dsName, String consolFunc, String backend ) throws RrdException { ! fetchSources.add( name, file, dsName, consolFunc, backend ); ! ! numDefs++; } --- 210,214 ---- public void datasource( String name, String file, String dsName, String consolFunc, String backend ) throws RrdException { ! processor.addDatasource( name, file, dsName, consolFunc, backend ); } *************** *** 226,232 **** public void setDatasources( FetchSourceList datasourceList ) { fetchSources = datasourceList; ! numDefs = fetchSources.defCount(); } --- 221,229 ---- public void setDatasources( FetchSourceList datasourceList ) { + throw new RuntimeException( "Unsupported method: setDatasources(FetchSourceList)" ); // TODO Reimplement FetchSourceList functionality + /* fetchSources = datasourceList; ! numDefs = fetchSources.defCount();*/ } *************** *** 255,259 **** public void datasource( String name, String rpn ) { ! cdefList.add( new Cdef(name, rpn) ); } --- 252,256 ---- public void datasource( String name, String rpn ) { ! processor.addDatasource( name, rpn ); } *************** *** 269,274 **** public void datasource( String name, String defName, String consolFunc ) throws RrdException { ! cdefList.add( new Sdef(name, defName, consolFunc) ); ! numSdefs++; } --- 266,270 ---- public void datasource( String name, String defName, String consolFunc ) throws RrdException { ! processor.addDatasource( name, defName, consolFunc ); } *************** *** 282,286 **** public void datasource( String name, Plottable plottable ) { ! pdefList.add( new Pdef(name, plottable) ); } --- 278,282 ---- public void datasource( String name, Plottable plottable ) { ! processor.addDatasource( name, plottable ); } *************** *** 295,299 **** public void datasource( String name, Plottable plottable, int index ) { ! pdefList.add( new Pdef(name, plottable, index) ); } --- 291,295 ---- public void datasource( String name, Plottable plottable, int index ) { ! processor.addDatasource( name, plottable, index ); } *************** *** 308,312 **** public void datasource( String name, Plottable plottable, String sourceName ) { ! pdefList.add( new Pdef(name, plottable, sourceName) ); } --- 304,308 ---- public void datasource( String name, Plottable plottable, String sourceName ) { ! processor.addDatasource( name, plottable, sourceName ); } *************** *** 318,322 **** public void addExportData( ExportData edata ) { ! edefList.add( edata ); } --- 314,319 ---- public void addExportData( ExportData edata ) { ! throw new RuntimeException( "Unsupported method: addExportData(ExportData)" ); // TODO Reimplement ExportData functionality ! //edefList.add( edata ); } *************** *** 378,382 **** public void exportXmlTemplate( OutputStream stream ) { ! XmlWriter xml = new XmlWriter( stream ); xml.startTag("rrd_export_def"); --- 375,380 ---- public void exportXmlTemplate( OutputStream stream ) { ! throw new RuntimeException( "Unsupported method: exportXmlTemplate(OutputStream)" ); // TODO Reimplement XmlTemplate functionality ! /*XmlWriter xml = new XmlWriter( stream ); xml.startTag("rrd_export_def"); *************** *** 423,427 **** xml.flush(); ! xml.flush(); } --- 421,425 ---- xml.flush(); ! xml.flush();*/ } *************** *** 467,480 **** // -- Protected (package) methods // ================================================================ protected long getStartTime() { ! return startTime; } protected long getEndTime() { ! return endTime; } protected long getResolution() { ! return resolution; } --- 465,482 ---- // -- Protected (package) methods // ================================================================ + protected DataProcessor getProcessor() { + return processor; + } + protected long getStartTime() { ! return processor.getStartingTimestamp(); } protected long getEndTime() { ! return processor.getEndingTimestamp(); } protected long getResolution() { ! return processor.getFetchRequestResolution(); } Index: Line.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/Line.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Line.java 9 Jul 2004 12:22:15 -0000 1.6 --- Line.java 6 Apr 2005 20:10:10 -0000 1.7 *************** *** 106,109 **** --- 106,110 ---- Graphics2D gd = g.getGraphics(); + values = processor.getValues( sourceName ); int len = values.length; Index: RrdExporter.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/RrdExporter.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** RrdExporter.java 23 Jan 2005 20:31:26 -0000 1.9 --- RrdExporter.java 6 Apr 2005 20:10:10 -0000 1.10 *************** *** 30,33 **** --- 30,34 ---- import org.jrobin.core.*; + import org.jrobin.data.DataProcessor; /** *************** *** 49,52 **** --- 50,55 ---- protected HashMap sourceIndex; + protected DataProcessor processor; + RrdExporter( RrdExportDef def ) { *************** *** 64,67 **** --- 67,71 ---- { this.def = def; + processor = def.getProcessor(); } *************** *** 83,86 **** --- 87,93 ---- protected void calculateSeries( int maxRows ) throws RrdException, IOException { + processor.processData(); + /* + FetchSourceList fetchSources; ValueExtractor ve; *************** *** 444,450 **** this.startTime = startTime; this.endTime = ( changingEndTime ? finalEndTime : endTime ); } ! private Source getSource( String name ) throws RrdException { if ( !sourceIndex.containsKey(name) ) --- 451,458 ---- this.startTime = startTime; this.endTime = ( changingEndTime ? finalEndTime : endTime ); + */ } ! /*private Source getSource( String name ) throws RrdException { if ( !sourceIndex.containsKey(name) ) *************** *** 452,456 **** return sources[ ( (Integer) sourceIndex.get(name) ).intValue() ]; ! } /** --- 460,464 ---- return sources[ ( (Integer) sourceIndex.get(name) ).intValue() ]; ! }*/ /** *************** *** 464,468 **** protected ExportData createExportData() throws RrdException { ! if ( sources == null) throw new RrdException( "Sources not calculated, no data to return." ); --- 472,477 ---- protected ExportData createExportData() throws RrdException { ! throw new RuntimeException( "Unsupported method createExportData()" ); // TODO Reimplement ExportData creation ! /* if ( sources == null) throw new RrdException( "Sources not calculated, no data to return." ); *************** *** 494,501 **** System.arraycopy( timestamps, 0, reducedTs, 0, reducedNumRows ); ! return new ExportData( reducedTs, sourceSet, legends ); } ! private Def createReducedDef( Source origSrc ) { Def src = new Def( origSrc.getName(), reducedNumRows, reducedNumRows ); --- 503,510 ---- System.arraycopy( timestamps, 0, reducedTs, 0, reducedNumRows ); ! return new ExportData( reducedTs, sourceSet, legends );*/ } ! /*private Def createReducedDef( Source origSrc ) { Def src = new Def( origSrc.getName(), reducedNumRows, reducedNumRows ); *************** *** 506,510 **** return src; ! } /** --- 515,519 ---- return src; ! }*/ /** Index: Stack.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/Stack.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** Stack.java 9 Jul 2004 12:22:15 -0000 1.5 --- Stack.java 6 Apr 2005 20:10:10 -0000 1.6 *************** *** 74,78 **** else if ( lastPlotType == PlotDef.PLOT_AREA ) stack = new Area( source, values, color, true, visible ); ! stack.draw( g, xValues, stackValues, lastPlotType ); } --- 74,81 ---- else if ( lastPlotType == PlotDef.PLOT_AREA ) stack = new Area( source, values, color, true, visible ); ! ! stack.sourceName = sourceName; ! stack.processor = processor; ! stack.draw( g, xValues, stackValues, lastPlotType ); } Index: RrdGraphDefTemplate.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/RrdGraphDefTemplate.java,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** RrdGraphDefTemplate.java 27 Jul 2004 12:30:17 -0000 1.11 --- RrdGraphDefTemplate.java 6 Apr 2005 20:10:10 -0000 1.12 *************** *** 637,641 **** rrdGraphDef.setCanvasColor(Color.decode(colorStr)); } ! // LEFT PADDING else if(option.equals("left_padding")) { int padding = getValueAsInt(optionNode); --- 637,641 ---- rrdGraphDef.setCanvasColor(Color.decode(colorStr)); } ! // HORIZONTAL_LEFT PADDING else if(option.equals("left_padding")) { int padding = getValueAsInt(optionNode); Index: PlotDef.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/PlotDef.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** PlotDef.java 25 Jul 2004 12:28:49 -0000 1.6 --- PlotDef.java 6 Apr 2005 20:10:10 -0000 1.7 *************** *** 30,33 **** --- 30,34 ---- import org.jrobin.core.RrdException; import org.jrobin.core.XmlWriter; + import org.jrobin.data.DataProcessor; /** *************** *** 58,61 **** --- 59,64 ---- protected double[] values = null; + protected DataProcessor processor = null; + // ================================================================ // -- Constructors *************** *** 99,103 **** // ================================================================ // -- Protected methods ! // ================================================================ /** * Sets the Source for this PlotDef, based on the internal datasource name. --- 102,110 ---- // ================================================================ // -- Protected methods ! // ================================================================ ! void setProcessor( DataProcessor processor ) { ! this.processor = processor; ! } ! /** * Sets the Source for this PlotDef, based on the internal datasource name. *************** *** 131,137 **** * @return Double value of the datapoint. */ ! double getValue( int tblPos, long[] timestamps ) { ! return source.get( tblPos ); } --- 138,145 ---- * @return Double value of the datapoint. */ ! double getValue( int tblPos, long[] timestamps ) throws RrdException { ! return processor.getValues( sourceName )[tblPos]; ! //return source.get( tblPos ); } Index: LinearInterpolator.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/LinearInterpolator.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** LinearInterpolator.java 9 Jun 2004 09:44:48 -0000 1.3 --- LinearInterpolator.java 6 Apr 2005 20:10:10 -0000 1.4 *************** *** 44,51 **** */ public class LinearInterpolator extends Plottable { ! /** constant used to specify LEFT interpolation. * See {@link #setInterpolationMethod(int) setInterpolationMethod()} for explanation. */ public static final int INTERPOLATE_LEFT = 0; ! /** constant used to specify RIGHT interpolation. * See {@link #setInterpolationMethod(int) setInterpolationMethod()} for explanation. */ public static final int INTERPOLATE_RIGHT = 1; --- 44,51 ---- */ public class LinearInterpolator extends Plottable { ! /** constant used to specify HORIZONTAL_LEFT interpolation. * See {@link #setInterpolationMethod(int) setInterpolationMethod()} for explanation. */ public static final int INTERPOLATE_LEFT = 0; ! /** constant used to specify HORIZONTAL_RIGHT interpolation. * See {@link #setInterpolationMethod(int) setInterpolationMethod()} for explanation. */ public static final int INTERPOLATE_RIGHT = 1; Index: Area.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/Area.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Area.java 9 Jul 2004 12:22:14 -0000 1.6 --- Area.java 6 Apr 2005 20:10:10 -0000 1.7 *************** *** 26,29 **** --- 26,30 ---- import org.jrobin.core.XmlWriter; + import org.jrobin.core.RrdException; import java.awt.*; *************** *** 75,82 **** * @param lastPlotType Type of the previous PlotDef, used to determine PlotDef type of a stack. */ ! void draw( ChartGraphics g, int[] xValues, double[] stackValues, int lastPlotType ) { g.setColor( color ); int len = values.length; --- 76,84 ---- * @param lastPlotType Type of the previous PlotDef, used to determine PlotDef type of a stack. */ ! void draw( ChartGraphics g, int[] xValues, double[] stackValues, int lastPlotType ) throws RrdException { g.setColor( color ); + values = processor.getValues( sourceName ); int len = values.length; Index: Gprint.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/Gprint.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** Gprint.java 21 Sep 2004 08:42:10 -0000 1.8 --- Gprint.java 6 Apr 2005 20:10:10 -0000 1.9 *************** *** 33,36 **** --- 33,37 ---- import org.jrobin.core.XmlWriter; import org.jrobin.core.ConsolFuns; + import org.jrobin.data.DataProcessor; /** *************** *** 50,55 **** private static final Pattern VALUE_PATTERN = Pattern.compile(VALUE_MARKER); ! private String sourceName; ! private int aggregate; private int numDec = 3; // Show 3 decimal values by default private int strLen = -1; --- 51,57 ---- private static final Pattern VALUE_PATTERN = Pattern.compile(VALUE_MARKER); ! private String sourceName, aggName; ! private DataProcessor processor; ! private int aggregate; private int numDec = 3; // Show 3 decimal values by default private int strLen = -1; *************** *** 84,88 **** this.commentType = Comment.CMT_GPRINT; this.sourceName = sourceName; ! if ( consolFunc.equalsIgnoreCase(CF_AVERAGE) || consolFunc.equalsIgnoreCase("AVG") ) aggregate = Source.AGG_AVERAGE; --- 86,91 ---- this.commentType = Comment.CMT_GPRINT; this.sourceName = sourceName; ! this.aggName = consolFunc; ! if ( consolFunc.equalsIgnoreCase(CF_AVERAGE) || consolFunc.equalsIgnoreCase("AVG") ) aggregate = Source.AGG_AVERAGE; *************** *** 132,141 **** * @throws RrdException Thrown in case of a JRobin specific error. */ ! void setValue( Source[] sources, HashMap sourceIndex, ValueFormatter vFormat ) throws RrdException { ! try ! { ! double value = sources[ ((Integer) sourceIndex.get(sourceName)).intValue() ].getAggregate( aggregate ); ! // See if we need to use a specific value for the formatting double oldBase = vFormat.getBase(); --- 135,146 ---- * @throws RrdException Thrown in case of a JRobin specific error. */ ! //void setValue( Source[] sources, HashMap sourceIndex, ValueFormatter vFormat ) throws RrdException ! void setValue( DataProcessor processor, ValueFormatter vFormat ) throws RrdException { ! /*try ! {*/ ! //double value = sources[ ((Integer) sourceIndex.get(sourceName)).intValue() ].getAggregate( aggregate ); ! double value = processor.getAggregate( sourceName, aggName ); ! // See if we need to use a specific value for the formatting double oldBase = vFormat.getBase(); *************** *** 167,174 **** if ( baseValue != -1 ) vFormat.setBase( oldBase ); ! } catch (Exception e) { throw new RrdException( "Could not find datasource: " + sourceName ); ! } } --- 172,179 ---- if ( baseValue != -1 ) vFormat.setBase( oldBase ); ! /*} catch (Exception e) { throw new RrdException( "Could not find datasource: " + sourceName ); ! }*/ } |
From: Arne V. <cob...@us...> - 2005-04-06 20:10:18
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8322/org/jrobin/data Modified Files: Aggregates.java DataProcessor.java Log Message: - First support of DataProcessor into Graph.* package. Index: DataProcessor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/DataProcessor.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** DataProcessor.java 23 Jan 2005 20:31:25 -0000 1.10 --- DataProcessor.java 6 Apr 2005 20:10:09 -0000 1.11 *************** *** 72,77 **** private boolean poolUsed = DEFAULT_POOL_USAGE_POLICY; ! private final long tStart; ! private long tEnd, timestamps[]; private double dblTimestamps[]; // this will be adjusted later --- 72,78 ---- private boolean poolUsed = DEFAULT_POOL_USAGE_POLICY; ! private long generationTime = 0; ! ! private long tStart, tEnd, timestamps[]; private double dblTimestamps[]; // this will be adjusted later *************** *** 85,88 **** --- 86,94 ---- private Def[] defSources; + public DataProcessor() + { + // TODO Insert a check on valid timestamps later on + } + /** * Creates new DataProcessor object for the given time span. Ending timestamp may be set to zero. *************** *** 94,105 **** * @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); ! } } --- 100,106 ---- * @throws RrdException Thrown if invalid timestamps are supplied */ ! public DataProcessor(long t1, long t2) throws RrdException ! { ! setTimePeriod( t1, t2 ); } *************** *** 130,133 **** --- 131,145 ---- } + public void setTimePeriod( long t1, long t2 ) throws RrdException + { + if ((t1 < t2 && t1 > 0 && t2 > 0) || (t1 > 0 && t2 == 0)) { + tStart = t1; + tEnd = t2; + } + else { + throw new RrdException("Invalid timestamps specified: " + t1 + ", " + t2); + } + } + /** * Returns boolean value representing {@link org.jrobin.core.RrdDbPool RrdDbPool} usage policy. *************** *** 244,247 **** --- 256,268 ---- /** + * Returns the starting timestamp. + * + * @return Starting timestamp in seconds + */ + public long getStartingTimestamp() { + return tStart; + } + + /** * Returns consolidated timestamps created with the {@link #processData()} method. * *************** *** 572,575 **** --- 593,597 ---- */ public void processData() throws IOException, RrdException { + generationTime = System.currentTimeMillis(); extractDefs(); fetchRrdData(); *************** *** 689,692 **** --- 711,718 ---- } + public long getGenerationTime() { + return generationTime; + } + // PRIVATE METHODS Index: Aggregates.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/Aggregates.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Aggregates.java 15 Dec 2004 14:55:40 -0000 1.1 --- Aggregates.java 6 Apr 2005 20:10:09 -0000 1.2 *************** *** 102,106 **** */ public double getAggregate(String consolFun) throws RrdException { ! if(consolFun.equals(CF_AVERAGE)) { return average; } --- 102,106 ---- */ public double getAggregate(String consolFun) throws RrdException { ! if(consolFun.equals(CF_AVERAGE) || consolFun.equalsIgnoreCase( "AVG" ) ) { return average; } *************** *** 111,118 **** return last; } ! else if(consolFun.equals(CF_MAX)) { return max; } ! else if(consolFun.equals(CF_MIN)) { return min; } --- 111,118 ---- return last; } ! else if(consolFun.equals(CF_MAX) || consolFun.equalsIgnoreCase( "MAXIMUM" ) ) { return max; } ! else if(consolFun.equals(CF_MIN) || consolFun.equalsIgnoreCase( "MINIMUM" ) ) { return min; } |
From: Sasa M. <sa...@us...> - 2005-02-17 11:21:54
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13439/org/jrobin/core Modified Files: Util.java Log Message: Added two nice, simple methods to obtain timestamp(s) from (un)related at-style time specification(s) Index: Util.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Util.java,v retrieving revision 1.31 retrieving revision 1.32 diff -C2 -d -r1.31 -r1.32 *** Util.java 23 Jan 2005 20:31:25 -0000 1.31 --- Util.java 17 Feb 2005 11:21:45 -0000 1.32 *************** *** 32,35 **** --- 32,37 ---- import org.xml.sax.InputSource; import org.xml.sax.SAXException; + import org.jrobin.core.timespec.TimeSpec; + import org.jrobin.core.timespec.TimeParser; import javax.xml.parsers.ParserConfigurationException; *************** *** 250,253 **** --- 252,288 ---- } + /** + * Parses at-style time specification and returns the corresponding timestamp. For example:<p> + * <pre> + * long t = Util.getTimestamp("now-1d"); + * </pre> + * @param atStyleTimeSpec at-style time specification. For the complete explanation of the syntax + * allowed see RRDTool's <code>rrdfetch</code> man page.<p> + * @return timestamp in seconds since epoch. + * @throws RrdException Thrown if invalid time specification is supplied. + */ + public static long getTimestamp(String atStyleTimeSpec) throws RrdException { + TimeSpec timeSpec = new TimeParser(atStyleTimeSpec).parse(); + return timeSpec.getTimestamp(); + } + + /** + * Parses two related at-style time specifications and returns corresponding timestamps. For example:<p> + * <pre> + * long[] t = Util.getTimestamps("end-1d","now"); + * </pre> + * @param atStyleTimeSpec1 Starting at-style time specification. For the complete explanation of the syntax + * allowed see RRDTool's <code>rrdfetch</code> man page.<p> + * @param atStyleTimeSpec2 Ending at-style time specification. For the complete explanation of the syntax + * allowed see RRDTool's <code>rrdfetch</code> man page.<p> + * @return An array of two longs representing starting and ending timestamp in seconds since epoch. + * @throws RrdException Thrown if any input time specification is invalid. + */ + public static long[] getTimestamps(String atStyleTimeSpec1, String atStyleTimeSpec2) throws RrdException { + TimeSpec timeSpec1 = new TimeParser(atStyleTimeSpec1).parse(); + TimeSpec timeSpec2 = new TimeParser(atStyleTimeSpec2).parse(); + return TimeSpec.getTimestamps(timeSpec1, timeSpec2); + } + /** * Parses input string as a double value. If the value cannot be parsed, Double.NaN |
From: Sasa M. <sa...@us...> - 2005-02-17 10:43:27
|
Update of /cvsroot/jrobin/src/org/jrobin/cmd In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5165/org/jrobin/cmd Modified Files: RrdCreateCmd.java RrdFetchCmd.java RrdUpdateCmd.java RrdXportCmd.java Removed Files: Epoch.java TimeParser.java TimeScanner.java TimeSpec.java TimeToken.java Log Message: Classes used to parse AT-Style time specification moved to a separate package (org.jrobin.core.timespec). Index: RrdUpdateCmd.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/cmd/RrdUpdateCmd.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RrdUpdateCmd.java 16 Jul 2004 07:40:48 -0000 1.1 --- RrdUpdateCmd.java 17 Feb 2005 10:43:12 -0000 1.2 *************** *** 27,30 **** --- 27,33 ---- import org.jrobin.core.*; + import org.jrobin.core.timespec.TimeParser; + import org.jrobin.core.timespec.TimeSpec; + import java.io.IOException; --- TimeSpec.java DELETED --- Index: RrdCreateCmd.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/cmd/RrdCreateCmd.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** RrdCreateCmd.java 15 Jul 2004 14:23:53 -0000 1.2 --- RrdCreateCmd.java 17 Feb 2005 10:43:12 -0000 1.3 *************** *** 29,32 **** --- 29,34 ---- import org.jrobin.core.RrdDef; import org.jrobin.core.RrdDb; + import org.jrobin.core.timespec.TimeParser; + import org.jrobin.core.timespec.TimeSpec; import java.io.IOException; Index: RrdFetchCmd.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/cmd/RrdFetchCmd.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** RrdFetchCmd.java 16 Jul 2004 07:40:48 -0000 1.3 --- RrdFetchCmd.java 17 Feb 2005 10:43:12 -0000 1.4 *************** *** 30,33 **** --- 30,35 ---- import org.jrobin.core.FetchRequest; import org.jrobin.core.FetchData; + import org.jrobin.core.timespec.TimeParser; + import org.jrobin.core.timespec.TimeSpec; import java.io.IOException; --- TimeParser.java DELETED --- --- Epoch.java DELETED --- --- TimeScanner.java DELETED --- --- TimeToken.java DELETED --- Index: RrdXportCmd.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/cmd/RrdXportCmd.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** RrdXportCmd.java 27 Oct 2004 20:36:24 -0000 1.4 --- RrdXportCmd.java 17 Feb 2005 10:43:12 -0000 1.5 *************** *** 26,29 **** --- 26,31 ---- import org.jrobin.core.RrdException; + import org.jrobin.core.timespec.TimeParser; + import org.jrobin.core.timespec.TimeSpec; import org.jrobin.graph.RrdExportDef; import org.jrobin.graph.RrdExport; |
From: Sasa M. <sa...@us...> - 2005-02-17 10:43:27
|
Update of /cvsroot/jrobin/src/org/jrobin/core/timespec In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5165/org/jrobin/core/timespec Added Files: Epoch.java TimeParser.java TimeScanner.java TimeSpec.java TimeToken.java Log Message: Classes used to parse AT-Style time specification moved to a separate package (org.jrobin.core.timespec). --- NEW FILE: TimeSpec.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.timespec; import org.jrobin.core.RrdException; import org.jrobin.core.Util; import java.util.GregorianCalendar; import java.util.Date; import java.util.Calendar; /** * Simple class to represent time obtained by parsing at-style date specification (described * in detail on the rrdfetch man page. See javadoc {@link org.jrobin.core.timespec.TimeParser} for more information. */ public class TimeSpec { static final int TYPE_ABSOLUTE = 0; static final int TYPE_START = 1; static final int TYPE_END = 2; int type = TYPE_ABSOLUTE; int year, month, day, hour, min, sec; int wday; int dyear, dmonth, dday, dhour, dmin, dsec; String dateString; TimeSpec context; TimeSpec(String dateString) { this.dateString = dateString; } void localtime(long timestamp) { GregorianCalendar date = new GregorianCalendar(); date.setTime(new Date(timestamp * 1000L)); year = date.get(Calendar.YEAR) - 1900; month = date.get(Calendar.MONTH); day = date.get(Calendar.DAY_OF_MONTH); hour = date.get(Calendar.HOUR_OF_DAY); min = date.get(Calendar.MINUTE); sec = date.get(Calendar.SECOND); wday = date.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY; } GregorianCalendar getTime() throws RrdException { GregorianCalendar gc; // absoulte time, this is easy if(type == TYPE_ABSOLUTE) { gc = new GregorianCalendar(year + 1900, month, day, hour, min, sec); } // relative time, we need a context to evaluate it else if(context != null && context.type == TYPE_ABSOLUTE) { gc = context.getTime(); } // how would I guess what time it was? else { throw new RrdException("Relative times like '" + dateString + "' require proper absolute context to be evaluated"); } gc.add(Calendar.YEAR, dyear); gc.add(Calendar.MONTH, dmonth); gc.add(Calendar.DAY_OF_MONTH, dday); gc.add(Calendar.HOUR_OF_DAY, dhour); gc.add(Calendar.MINUTE, dmin); gc.add(Calendar.SECOND, dsec); return gc; } /** * Returns the corresponding timestamp (seconds since Epoch). Example:<p> * <pre> * TimeParser p = new TimeParser("now-1day"); * TimeSpec ts = p.parse(); * System.out.println("Timestamp was: " + ts.getTimestamp(); * </pre> * @return Timestamp (in seconds, no milliseconds) * @throws RrdException Thrown if this TimeSpec object does not represent absolute time. */ public long getTimestamp() throws RrdException { return Util.getTimestamp(getTime()); } String dump() { return (type == TYPE_ABSOLUTE? "ABSTIME": type == TYPE_START? "START": "END") + ": " + year + "/" + month + "/" + day + "/" + hour + "/" + min + "/" + sec + " (" + dyear + "/" + dmonth + "/" + dday + "/" + dhour + "/" + dmin + "/" + dsec + ")"; } /** * Use this static method to resolve relative time references and obtain the corresponding * GregorianCalendar objects. Example:<p> * <pre> * TimeParser pStart = new TimeParser("now-1month"); // starting time * TimeParser pEnd = new TimeParser("start+1week"); // ending time * TimeSpec specStart = pStart.parse(); * TimeSpec specEnd = pEnd.parse(); * GregorianCalendar[] gc = TimeSpec.getTimes(specStart, specEnd); * </pre> * @param spec1 Starting time specification * @param spec2 Ending time specification * @return * @throws RrdException Thrown if relative time references cannot be resolved */ public static GregorianCalendar[] getTimes(TimeSpec spec1, TimeSpec spec2) throws RrdException { if(spec1.type == TYPE_START || spec2.type == TYPE_END) { throw new RrdException("Recursive time specifications not allowed"); } spec1.context = spec2; spec2.context = spec1; return new GregorianCalendar[] { spec1.getTime(), spec2.getTime() }; } /** * Use this static method to resolve relative time references and obtain the corresponding * timestamps (seconds since epoch). Example:<p> * <pre> * TimeParser pStart = new TimeParser("now-1month"); // starting time * TimeParser pEnd = new TimeParser("start+1week"); // ending time * TimeSpec specStart = pStart.parse(); * TimeSpec specEnd = pEnd.parse(); * long[] ts = TimeSpec.getTimestamps(specStart, specEnd); * </pre> * @param spec1 Starting time specification * @param spec2 Ending time specification * @return * @throws RrdException Thrown if relative time references cannot be resolved */ public static long[] getTimestamps(TimeSpec spec1, TimeSpec spec2) throws RrdException { GregorianCalendar[] gcs = getTimes(spec1, spec2); return new long[] { Util.getTimestamp(gcs[0]), Util.getTimestamp(gcs[1]) }; } } --- NEW FILE: TimeParser.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. */ /* * Java port of Tobi's original parsetime.c routine */ package org.jrobin.core.timespec; import org.jrobin.core.RrdException; import org.jrobin.core.Util; /** * Class which parses at-style time specification (describided in detail on the rrdfetch man page), * used in all RRDTool commands. This code is in most parts just a java port of Tobi's parsetime.c * code. */ public class TimeParser { private static final int PREVIOUS_OP = -1; TimeToken token; TimeScanner scanner; TimeSpec spec; int op = TimeToken.PLUS; int prev_multiplier = -1; /** * Constructs TimeParser instance from the given input string. * @param dateString at-style time specification (read rrdfetch man page * for the complete explanation) */ public TimeParser(String dateString) { scanner = new TimeScanner(dateString); spec = new TimeSpec(dateString); } private void expectToken(int desired, String errorMessage) throws RrdException { token = scanner.nextToken(); if (token.id != desired) { throw new RrdException(errorMessage); } } private void plusMinus(int doop) throws RrdException { if (doop >= 0) { op = doop; expectToken(TimeToken.NUMBER, "There should be number after " + (op == TimeToken.PLUS ? '+' : '-')); prev_multiplier = -1; /* reset months-minutes guessing mechanics */ } int delta = Integer.parseInt(token.value); token = scanner.nextToken(); if (token.id == TimeToken.MONTHS_MINUTES) { /* hard job to guess what does that -5m means: -5mon or -5min? */ switch (prev_multiplier) { case TimeToken.DAYS: case TimeToken.WEEKS: case TimeToken.MONTHS: case TimeToken.YEARS: token = scanner.resolveMonthsMinutes(TimeToken.MONTHS); break; case TimeToken.SECONDS: case TimeToken.MINUTES: case TimeToken.HOURS: token = scanner.resolveMonthsMinutes(TimeToken.MINUTES); break; default: if (delta < 6) { token = scanner.resolveMonthsMinutes(TimeToken.MONTHS); } else { token = scanner.resolveMonthsMinutes(TimeToken.MINUTES); } } } prev_multiplier = token.id; delta *= (op == TimeToken.PLUS) ? +1 : -1; switch (token.id) { case TimeToken.YEARS: spec.dyear += delta; return; case TimeToken.MONTHS: spec.dmonth += delta; return; case TimeToken.WEEKS: delta *= 7; /* FALLTHRU */ case TimeToken.DAYS: spec.dday += delta; return; case TimeToken.HOURS: spec.dhour += delta; return; case TimeToken.MINUTES: spec.dmin += delta; return; case TimeToken.SECONDS: default: // default is 'seconds' spec.dsec += delta; return; } // unreachable statement // throw new RrdException("Well-known time unit expected after " + delta); } private void timeOfDay() throws RrdException { int hour, minute = 0; /* save token status in case we must abort */ scanner.saveState(); /* first pick out the time of day - we assume a HH (COLON|DOT) MM time */ if (token.value.length() > 2) { return; } hour = Integer.parseInt(token.value); token = scanner.nextToken(); if (token.id == TimeToken.SLASH || token.id == TimeToken.DOT) { /* guess we are looking at a date */ token = scanner.restoreState(); return; } if (token.id == TimeToken.COLON) { expectToken(TimeToken.NUMBER, "Parsing HH:MM syntax, expecting MM as number, got none"); minute = Integer.parseInt(token.value); if (minute > 59) { throw new RrdException("Parsing HH:MM syntax, got MM = " + minute + " (>59!)"); } token = scanner.nextToken(); } /* check if an AM or PM specifier was given */ if (token.id == TimeToken.AM || token.id == TimeToken.PM) { if (hour > 12) { throw new RrdException("There cannot be more than 12 AM or PM hours"); } if (token.id == TimeToken.PM) { if (hour != 12) { /* 12:xx PM is 12:xx, not 24:xx */ hour += 12; } } else { if (hour == 12) { /* 12:xx AM is 00:xx, not 12:xx */ hour = 0; } } token = scanner.nextToken(); } else if (hour > 23) { /* guess it was not a time then ... */ token = scanner.restoreState(); return; } spec.hour = hour; spec.min = minute; spec.sec = 0; if (spec.hour == 24) { spec.hour = 0; spec.day++; } } private void assignDate(long mday, long mon, long year) throws RrdException { if (year > 138) { if (year > 1970) { year -= 1900; } else { throw new RrdException("Invalid year " + year + " (should be either 00-99 or >1900)"); } } else if (year >= 0 && year < 38) { year += 100; /* Allow year 2000-2037 to be specified as */ } /* 00-37 until the problem of 2038 year will */ /* arise for unices with 32-bit time_t */ if (year < 70) { throw new RrdException("Won't handle dates before epoch (01/01/1970), sorry"); } spec.year = (int) year; spec.month = (int) mon; spec.day = (int) mday; } private void day() throws RrdException { long mday = 0, wday, mon, year = spec.year; switch (token.id) { case TimeToken.YESTERDAY: spec.day--; /* FALLTRHU */ case TimeToken.TODAY: /* force ourselves to stay in today - no further processing */ token = scanner.nextToken(); break; case TimeToken.TOMORROW: spec.day++; token = scanner.nextToken(); break; case TimeToken.JAN: case TimeToken.FEB: case TimeToken.MAR: case TimeToken.APR: case TimeToken.MAY: case TimeToken.JUN: case TimeToken.JUL: case TimeToken.AUG: case TimeToken.SEP: case TimeToken.OCT: case TimeToken.NOV: case TimeToken.DEC: /* do month mday [year] */ mon = (token.id - TimeToken.JAN); expectToken(TimeToken.NUMBER, "the day of the month should follow month name"); mday = Long.parseLong(token.value); token = scanner.nextToken(); if (token.id == TimeToken.NUMBER) { year = Long.parseLong(token.value); token = scanner.nextToken(); } else { year = spec.year; } assignDate(mday, mon, year); break; case TimeToken.SUN: case TimeToken.MON: case TimeToken.TUE: case TimeToken.WED: case TimeToken.THU: case TimeToken.FRI: case TimeToken.SAT: /* do a particular day of the week */ wday = (token.id - TimeToken.SUN); spec.day += (wday - spec.wday); token = scanner.nextToken(); break; case TimeToken.NUMBER: /* get numeric <sec since 1970>, MM/DD/[YY]YY, or DD.MM.[YY]YY */ // int tlen = token.value.length(); mon = Long.parseLong(token.value); if (mon > 10L * 365L * 24L * 60L * 60L) { spec.localtime(mon); token = scanner.nextToken(); break; } if (mon > 19700101 && mon < 24000101) { /*works between 1900 and 2400 */ year = mon / 10000; mday = mon % 100; mon = (mon / 100) % 100; token = scanner.nextToken(); } else { token = scanner.nextToken(); if (mon <= 31 && (token.id == TimeToken.SLASH || token.id == TimeToken.DOT)) { int sep = token.id; expectToken(TimeToken.NUMBER, "there should be " + (sep == TimeToken.DOT ? "month" : "day") + " number after " + (sep == TimeToken.DOT ? '.' : '/')); mday = Long.parseLong(token.value); token = scanner.nextToken(); if (token.id == sep) { expectToken(TimeToken.NUMBER, "there should be year number after " + (sep == TimeToken.DOT ? '.' : '/')); year = Long.parseLong(token.value); token = scanner.nextToken(); } /* flip months and days for European timing */ if (sep == TimeToken.DOT) { long x = mday; mday = mon; mon = x; } } } mon--; if (mon < 0 || mon > 11) { throw new RrdException("Did you really mean month " + (mon + 1)); } if (mday < 1 || mday > 31) { throw new RrdException("I'm afraid that " + mday + " is not a valid day of the month"); } assignDate(mday, mon, year); break; } } /** * Parses the input string specified in the constructor. * @return Object representing parsed date/time. * @throws RrdException Thrown if the date string cannot be parsed. */ public TimeSpec parse() throws RrdException { long now = Util.getTime(); int hr = 0; /* this MUST be initialized to zero for midnight/noon/teatime */ /* establish the default time reference */ spec.localtime(now); token = scanner.nextToken(); switch (token.id) { case TimeToken.PLUS: case TimeToken.MINUS: break; /* jump to OFFSET-SPEC part */ case TimeToken.START: spec.type = TimeSpec.TYPE_START; /* FALLTHRU */ case TimeToken.END: if (spec.type != TimeSpec.TYPE_START) { spec.type = TimeSpec.TYPE_END; } spec.year = spec.month = spec.day = spec.hour = spec.min = spec.sec = 0; /* FALLTHRU */ case TimeToken.NOW: int time_reference = token.id; token = scanner.nextToken(); if (token.id == TimeToken.PLUS || token.id == TimeToken.MINUS) { break; } if (time_reference != TimeToken.NOW) { throw new RrdException("Words 'start' or 'end' MUST be followed by +|- offset"); } else if (token.id != TimeToken.EOF) { throw new RrdException("If 'now' is followed by a token it must be +|- offset"); } break; /* Only absolute time specifications below */ case TimeToken.NUMBER: timeOfDay(); if (token.id != TimeToken.NUMBER) { break; } /* fix month parsing */ case TimeToken.JAN: case TimeToken.FEB: case TimeToken.MAR: case TimeToken.APR: case TimeToken.MAY: case TimeToken.JUN: case TimeToken.JUL: case TimeToken.AUG: case TimeToken.SEP: case TimeToken.OCT: case TimeToken.NOV: case TimeToken.DEC: day(); if (token.id != TimeToken.NUMBER) { break; } timeOfDay(); break; /* evil coding for TEATIME|NOON|MIDNIGHT - we've initialized * hr to zero up above, then fall into this case in such a * way so we add +12 +4 hours to it for teatime, +12 hours * to it for noon, and nothing at all for midnight, then * set our rettime to that hour before leaping into the * month scanner */ case TimeToken.TEATIME: hr += 4; /* FALLTHRU */ case TimeToken.NOON: hr += 12; /* FALLTHRU */ case TimeToken.MIDNIGHT: spec.hour = hr; spec.min = 0; spec.sec = 0; token = scanner.nextToken(); day(); break; default: throw new RrdException("Unparsable time: " + token.value); } /* * the OFFSET-SPEC part * * (NOTE, the sc_tokid was prefetched for us by the previous code) */ if (token.id == TimeToken.PLUS || token.id == TimeToken.MINUS) { scanner.setContext(false); while (token.id == TimeToken.PLUS || token.id == TimeToken.MINUS || token.id == TimeToken.NUMBER) { if (token.id == TimeToken.NUMBER) { plusMinus(PREVIOUS_OP); } else { plusMinus(token.id); } token = scanner.nextToken(); /* We will get EOF eventually but that's OK, since token() will return us as many EOFs as needed */ } } /* now we should be at EOF */ if (token.id != TimeToken.EOF) { throw new RrdException("Unparsable trailing text: " + token.value); } return spec; } /* public static void main(String[] args) throws IOException { BufferedReader r = new BufferedReader(new InputStreamReader(System.in)); while (true) { String s = r.readLine(); try { TimeParser p = new TimeParser(s); TimeSpec spec = p.parse(); System.out.println(spec.getTime().getTime()); // System.out.println(spec.dump()); } catch (RrdException e) { System.err.println("ERROR: " + e); } } } */ } --- NEW FILE: Epoch.java --- package org.jrobin.core.timespec; import org.jrobin.core.RrdException; import org.jrobin.core.Util; import javax.swing.*; import java.util.Date; import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.text.SimpleDateFormat; import java.text.ParseException; class Epoch extends JFrame implements Runnable { private static final String[] formats = { "MM/dd/yy HH:mm:ss", "dd.MM.yy HH:mm:ss", "yy-MM-dd HH:mm:ss", "MM/dd/yy HH:mm", "dd.MM.yy HH:mm", "yy-MM-dd HH:mm", "MM/dd/yy", "dd.MM.yy", "yy-MM-dd", "HH:mm MM/dd/yy", "HH:mm dd.MM.yy", "HH:mm yy-MM-dd", "HH:mm:ss MM/dd/yy", "HH:mm:ss dd.MM.yy", "HH:mm:ss yy-MM-dd" }; private static final SimpleDateFormat[] parsers = new SimpleDateFormat[formats.length]; private static final String helpText; static { for(int i = 0; i < parsers.length; i++) { parsers[i] = new SimpleDateFormat(formats[i]); parsers[i].setLenient(true); } StringBuffer tooltipBuff = new StringBuffer("<html><b>Supported input formats:</b><br>"); for(int i = 0; i < formats.length; i++) { tooltipBuff.append(formats[i] + "<br>"); } tooltipBuff.append("<b>RRDTool time format</b><br>"); tooltipBuff.append("... including timestamps</html>"); helpText = tooltipBuff.toString(); } private JLabel topLabel = new JLabel("Enter timestamp or readable date:"); private JTextField inputField = new JTextField(25); private JButton button = new JButton("Convert"); //private JLabel helpLabel = new JLabel(helpText); private static final SimpleDateFormat OUTPUT_DATE_FORMAT = new SimpleDateFormat("MM/dd/yy HH:mm:ss EEE"); Epoch() { super("Epoch"); constructUI(); setVisible(true); new Thread(this).start(); } private void constructUI() { JPanel c = (JPanel) getContentPane(); c.setLayout(new BorderLayout()); c.add(topLabel, BorderLayout.NORTH); c.add(inputField, BorderLayout.CENTER); c.add(button, BorderLayout.EAST); // c.add(helpLabel, BorderLayout.WEST); button.setToolTipText(helpText); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { convert(); } }); inputField.requestFocus(); getRootPane().setDefaultButton(button); setResizable(false); setDefaultCloseOperation(EXIT_ON_CLOSE); pack(); centerOnScreen(); } void centerOnScreen() { Toolkit t = Toolkit.getDefaultToolkit(); Dimension screenSize = t.getScreenSize(); Dimension frameSize = getPreferredSize(); double x = (screenSize.getWidth() - frameSize.getWidth()) / 2; double y = (screenSize.getHeight() - frameSize.getHeight()) / 2; setLocation((int) x, (int) y); } private void convert() { String time = inputField.getText().trim(); if(time.length() > 0) { // try simple timestamp try { long timestamp = Long.parseLong(time); Date date = new Date(timestamp * 1000L); formatDate(date); } catch(NumberFormatException nfe) { // failed, try as a date try { inputField.setText("" + parseDate(time)); } catch (RrdException e) { inputField.setText("Could not convert, sorry"); } } } } public void run() { for(;;) { Date now = new Date(); long timestamp = now.getTime() / 1000L; setTitle(timestamp + " seconds since epoch"); try { Thread.sleep(1000L); } catch (InterruptedException e) { } } } void formatDate(Date date) { inputField.setText(OUTPUT_DATE_FORMAT.format(date)); } private long parseDate(String time) throws RrdException { for(int i = 0; i < parsers.length; i++) { try { return Util.getTimestamp(parsers[i].parse(time)); } catch (ParseException e) { } } return new TimeParser(time).parse().getTimestamp(); } public static void main(String[] args) { new Epoch(); } } --- NEW FILE: TimeToken.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.timespec; class TimeToken { public static final int MIDNIGHT = 1; public static final int NOON = 2; public static final int TEATIME = 3; public static final int PM = 4; public static final int AM = 5; public static final int YESTERDAY = 6; public static final int TODAY = 7; public static final int TOMORROW = 8; public static final int NOW = 9; public static final int START = 10; public static final int END = 11; public static final int SECONDS = 12; public static final int MINUTES = 13; public static final int HOURS = 14; public static final int DAYS = 15; public static final int WEEKS = 16; public static final int MONTHS = 17; public static final int YEARS = 18; public static final int MONTHS_MINUTES = 19; public static final int NUMBER = 20; public static final int PLUS = 21; public static final int MINUS = 22; public static final int DOT = 23; public static final int COLON = 24; public static final int SLASH = 25; public static final int ID = 26; public static final int JUNK = 27; public static final int JAN = 28; public static final int FEB = 29; public static final int MAR = 30; public static final int APR = 31; public static final int MAY = 32; public static final int JUN = 33; public static final int JUL = 34; public static final int AUG = 35; public static final int SEP = 36; public static final int OCT = 37; public static final int NOV = 38; public static final int DEC = 39; public static final int SUN = 40; public static final int MON = 41; public static final int TUE = 42; public static final int WED = 43; public static final int THU = 44; public static final int FRI = 45; public static final int SAT = 46; public static final int EOF = -1; final String value; /* token name */ final int id; /* token id */ public TimeToken(String value, int id) { this.value = value; this.id = id; } public String toString() { return value + " [" + id + "]"; } } --- NEW FILE: TimeScanner.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.timespec; class TimeScanner { private String dateString; private int pos, pos_save; private TimeToken token, token_save; static final TimeToken[] WORDS = { new TimeToken("midnight", TimeToken.MIDNIGHT), /* 00:00:00 of today or tomorrow */ new TimeToken("noon", TimeToken.NOON), /* 12:00:00 of today or tomorrow */ new TimeToken("teatime", TimeToken.TEATIME), /* 16:00:00 of today or tomorrow */ new TimeToken("am", TimeToken.AM), /* morning times for 0-12 clock */ new TimeToken("pm", TimeToken.PM), /* evening times for 0-12 clock */ new TimeToken("tomorrow", TimeToken.TOMORROW), new TimeToken("yesterday", TimeToken.YESTERDAY), new TimeToken("today", TimeToken.TODAY), new TimeToken("now", TimeToken.NOW), new TimeToken("n", TimeToken.NOW), new TimeToken("start", TimeToken.START), new TimeToken("s", TimeToken.START), new TimeToken("end", TimeToken.END), new TimeToken("e", TimeToken.END), new TimeToken("jan", TimeToken.JAN), new TimeToken("feb", TimeToken.FEB), new TimeToken("mar", TimeToken.MAR), new TimeToken("apr", TimeToken.APR), new TimeToken("may", TimeToken.MAY), new TimeToken("jun", TimeToken.JUN), new TimeToken("jul", TimeToken.JUL), new TimeToken("aug", TimeToken.AUG), new TimeToken("sep", TimeToken.SEP), new TimeToken("oct", TimeToken.OCT), new TimeToken("nov", TimeToken.NOV), new TimeToken("dec", TimeToken.DEC), new TimeToken("january", TimeToken.JAN), new TimeToken("february", TimeToken.FEB), new TimeToken("march", TimeToken.MAR), new TimeToken("april", TimeToken.APR), new TimeToken("may", TimeToken.MAY), new TimeToken("june", TimeToken.JUN), new TimeToken("july", TimeToken.JUL), new TimeToken("august", TimeToken.AUG), new TimeToken("september", TimeToken.SEP), new TimeToken("october", TimeToken.OCT), new TimeToken("november", TimeToken.NOV), new TimeToken("december", TimeToken.DEC), new TimeToken("sunday", TimeToken.SUN), new TimeToken("sun", TimeToken.SUN), new TimeToken("monday", TimeToken.MON), new TimeToken("mon", TimeToken.MON), new TimeToken("tuesday", TimeToken.TUE), new TimeToken("tue", TimeToken.TUE), new TimeToken("wednesday", TimeToken.WED), new TimeToken("wed", TimeToken.WED), new TimeToken("thursday", TimeToken.THU), new TimeToken("thu", TimeToken.THU), new TimeToken("friday", TimeToken.FRI), new TimeToken("fri", TimeToken.FRI), new TimeToken("saturday", TimeToken.SAT), new TimeToken("sat", TimeToken.SAT), new TimeToken(null, 0) /*** SENTINEL ***/ }; static TimeToken[] MULTIPLIERS = { new TimeToken("second", TimeToken.SECONDS), /* seconds multiplier */ new TimeToken("seconds", TimeToken.SECONDS), /* (pluralized) */ new TimeToken("sec", TimeToken.SECONDS), /* (generic) */ new TimeToken("s", TimeToken.SECONDS), /* (short generic) */ new TimeToken("minute", TimeToken.MINUTES), /* minutes multiplier */ new TimeToken("minutes", TimeToken.MINUTES), /* (pluralized) */ new TimeToken("min", TimeToken.MINUTES), /* (generic) */ new TimeToken("m", TimeToken.MONTHS_MINUTES), /* (short generic) */ new TimeToken("hour", TimeToken.HOURS), /* hours ... */ new TimeToken("hours", TimeToken.HOURS), /* (pluralized) */ new TimeToken("hr", TimeToken.HOURS), /* (generic) */ new TimeToken("h", TimeToken.HOURS), /* (short generic) */ new TimeToken("day", TimeToken.DAYS), /* days ... */ new TimeToken("days", TimeToken.DAYS), /* (pluralized) */ new TimeToken("d", TimeToken.DAYS), /* (short generic) */ new TimeToken("week", TimeToken.WEEKS), /* week ... */ new TimeToken("weeks", TimeToken.WEEKS), /* (pluralized) */ new TimeToken("wk", TimeToken.WEEKS), /* (generic) */ new TimeToken("w", TimeToken.WEEKS), /* (short generic) */ new TimeToken("month", TimeToken.MONTHS), /* week ... */ new TimeToken("months", TimeToken.MONTHS), /* (pluralized) */ new TimeToken("mon", TimeToken.MONTHS), /* (generic) */ new TimeToken("year", TimeToken.YEARS), /* year ... */ new TimeToken("years", TimeToken.YEARS), /* (pluralized) */ new TimeToken("yr", TimeToken.YEARS), /* (generic) */ new TimeToken("y", TimeToken.YEARS), /* (short generic) */ new TimeToken(null, 0) /*** SENTINEL ***/ }; TimeToken[] specials = WORDS; public TimeScanner(String dateString) { this.dateString = dateString; } void setContext(boolean parsingWords) { specials = parsingWords? WORDS: MULTIPLIERS; } TimeToken nextToken() { StringBuffer buffer = new StringBuffer(""); while (pos < dateString.length()) { char c = dateString.charAt(pos++); if (Character.isWhitespace(c) || c == '_' || c == ',') { continue; } buffer.append(c); if (Character.isDigit(c)) { // pick as many digits as possible while (pos < dateString.length()) { char next = dateString.charAt(pos); if (Character.isDigit(next)) { buffer.append(next); pos++; } else { break; } } String value = buffer.toString(); return token = new TimeToken(value, TimeToken.NUMBER); } if (Character.isLetter(c)) { // pick as many letters as possible while (pos < dateString.length()) { char next = dateString.charAt(pos); if (Character.isLetter(next)) { buffer.append(next); pos++; } else { break; } } String value = buffer.toString(); return token = new TimeToken(value, parseToken(value)); } switch (c) { case ':': return token = new TimeToken(":", TimeToken.COLON); case '.': return token = new TimeToken(".", TimeToken.DOT); case '+': return token = new TimeToken("+", TimeToken.PLUS); case '-': return token = new TimeToken("-", TimeToken.MINUS); case '/': return token = new TimeToken("/", TimeToken.SLASH); default: pos--; return token = new TimeToken(null, TimeToken.EOF); } } return token = new TimeToken(null, TimeToken.EOF); } TimeToken resolveMonthsMinutes(int newId) { assert token.id == TimeToken.MONTHS_MINUTES; assert newId == TimeToken.MONTHS || newId == TimeToken.MINUTES; return token = new TimeToken(token.value, newId); } void saveState() { token_save = token; pos_save = pos; } TimeToken restoreState() { pos = pos_save; return token = token_save; } private int parseToken(String arg) { for (int i = 0; specials[i].value != null; i++) { if (specials[i].value.equalsIgnoreCase(arg)) { return specials[i].id; } } return TimeToken.ID; } } |
From: Sasa M. <sa...@us...> - 2005-02-17 10:41:11
|
Update of /cvsroot/jrobin/src/org/jrobin/core/timespec In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4830/org/jrobin/core/timespec Log Message: Directory /cvsroot/jrobin/src/org/jrobin/core/timespec added to the repository |
From: Sasa M. <sa...@us...> - 2005-02-17 10:18:33
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31562/org/jrobin/core Modified Files: Datasource.java Log Message: Performance improvement (10%) for COUNTER datatype as suggested on http://www.jrobin.org/phpBB2/viewtopic.php?t=122 Index: Datasource.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Datasource.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** Datasource.java 9 Nov 2004 11:36:53 -0000 1.10 --- Datasource.java 17 Feb 2005 10:18:18 -0000 1.11 *************** *** 40,43 **** --- 40,46 ---- public class Datasource implements RrdUpdater, DsTypes { + private static final double MAX_32_BIT = Math.pow(2, 32); + private static final double MAX_64_BIT = Math.pow(2, 64); + private RrdDb parentDb; // definition *************** *** 224,234 **** if(!Double.isNaN(newValue) && !Double.isNaN(oldValue)) { double diff = newValue - oldValue; - double max32bit = Math.pow(2, 32); - double max64bit = Math.pow(2, 64); if(diff < 0) { ! diff += max32bit; } if(diff < 0) { ! diff += max64bit - max32bit; } if(diff >= 0) { --- 227,235 ---- if(!Double.isNaN(newValue) && !Double.isNaN(oldValue)) { double diff = newValue - oldValue; if(diff < 0) { ! diff += MAX_32_BIT; } if(diff < 0) { ! diff += MAX_64_BIT - MAX_32_BIT; } if(diff >= 0) { |
From: Arne V. <cob...@us...> - 2005-01-23 20:31:36
|
Update of /cvsroot/jrobin/src/org/jrobin/graph In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26216/org/jrobin/graph Modified Files: ChartGraphics.java CustomArea.java CustomLine.java ExportData.java FetchSource.java Grapher.java RrdExporter.java RrdGraphDef.java Source.java ValueGrid.java Log Message: JRobin 2.0 - Additions and related changes Index: CustomLine.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/CustomLine.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** CustomLine.java 9 Jul 2004 12:22:15 -0000 1.4 --- CustomLine.java 23 Jan 2005 20:31:26 -0000 1.5 *************** *** 31,34 **** --- 31,35 ---- import org.jrobin.core.RrdException; import org.jrobin.core.XmlWriter; + import org.jrobin.core.Util; /** *************** *** 121,134 **** // Get X positions ! if ( xVal1 == Long.MIN_VALUE ) ax = g.getMinX(); ! else if ( xVal1 == Long.MAX_VALUE ) ax = g.getMaxX(); else ax = g.getX( xVal1 ); ! if ( xVal2 == Long.MIN_VALUE ) nx = g.getMinX(); ! else if ( xVal2 == Long.MAX_VALUE ) nx = g.getMaxX(); else --- 122,135 ---- // Get X positions ! if ( xVal1 == Util.MIN_LONG ) ax = g.getMinX(); ! else if ( xVal1 == Util.MAX_LONG ) ax = g.getMaxX(); else ax = g.getX( xVal1 ); ! if ( xVal2 == Util.MIN_LONG ) nx = g.getMinX(); ! else if ( xVal2 == Util.MAX_LONG ) nx = g.getMaxX(); else *************** *** 136,149 **** // Get Y positions ! if ( yVal1 == Double.MIN_VALUE ) ay = g.getMinY(); ! else if ( yVal1 == Double.MAX_VALUE ) ay = g.getMaxY(); else ay = g.getY( yVal1 ); ! if ( yVal2 == Double.MIN_VALUE ) ny = g.getMinY(); ! else if ( yVal2 == Double.MAX_VALUE ) ny = g.getMaxY(); else --- 137,150 ---- // Get Y positions ! if ( yVal1 == Util.MIN_DOUBLE ) ay = g.getMinY(); ! else if ( yVal1 == Util.MAX_DOUBLE ) ay = g.getMaxY(); else ay = g.getY( yVal1 ); ! if ( yVal2 == Util.MIN_DOUBLE ) ny = g.getMinY(); ! else if ( yVal2 == Util.MAX_DOUBLE ) ny = g.getMaxY(); else *************** *** 192,196 **** // Vrule ! if ( yVal1 == Double.MIN_VALUE && yVal2 == Double.MAX_VALUE ) return Double.NaN; --- 193,197 ---- // Vrule ! if ( yVal1 == Util.MIN_DOUBLE && yVal2 == Util.MAX_DOUBLE ) return Double.NaN; Index: Grapher.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/Grapher.java,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** Grapher.java 27 Jul 2004 12:30:17 -0000 1.20 --- Grapher.java 23 Jan 2005 20:31:26 -0000 1.21 *************** *** 38,41 **** --- 38,42 ---- import org.jrobin.core.RrdException; + import org.jrobin.core.Util; /** *************** *** 443,448 **** boolean rigid = false; ! double lowerValue = Double.MAX_VALUE; ! double upperValue = Double.MIN_VALUE; GridRange range = graphDef.getGridRange(); --- 444,449 ---- boolean rigid = false; ! double lowerValue = Util.MAX_DOUBLE; ! double upperValue = Util.MIN_DOUBLE; GridRange range = graphDef.getGridRange(); *************** *** 453,458 **** upperValue = range.getUpperValue(); ! if ( Double.isNaN(lowerValue) ) lowerValue = Double.MAX_VALUE; ! if ( Double.isNaN(upperValue) ) upperValue = Double.MIN_VALUE; } --- 454,459 ---- upperValue = range.getUpperValue(); ! if ( Double.isNaN(lowerValue) ) lowerValue = Util.MAX_DOUBLE; ! if ( Double.isNaN(upperValue) ) upperValue = Util.MIN_DOUBLE; } Index: ValueGrid.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/ValueGrid.java,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** ValueGrid.java 27 Oct 2004 20:36:26 -0000 1.14 --- ValueGrid.java 23 Jan 2005 20:31:26 -0000 1.15 *************** *** 26,29 **** --- 26,30 ---- import org.jrobin.core.RrdException; + import org.jrobin.core.Util; /** *************** *** 64,69 **** ValueGrid( GridRange gr, double low, double up, ValueAxisUnit vAxis, double base ) throws RrdException { ! double grLower = Double.MAX_VALUE; ! double grUpper = Double.MIN_VALUE; if ( gr != null ) --- 65,70 ---- ValueGrid( GridRange gr, double low, double up, ValueAxisUnit vAxis, double base ) throws RrdException { ! double grLower = Util.MAX_DOUBLE; ! double grUpper = Util.MIN_DOUBLE; if ( gr != null ) *************** *** 133,139 **** return; ! if ( Double.isNaN(upper) || upper == Double.MIN_VALUE || upper == Double.MAX_VALUE ) upper = 0.9; ! if ( Double.isNaN(lower) || lower == Double.MAX_VALUE || lower == Double.MIN_VALUE ) lower = 0; --- 134,140 ---- return; ! if ( Double.isNaN(upper) || upper == Util.MIN_DOUBLE || upper == Util.MAX_DOUBLE ) upper = 0.9; ! if ( Double.isNaN(lower) || lower == Util.MAX_DOUBLE || lower == Util.MIN_DOUBLE ) lower = 0; Index: ChartGraphics.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/ChartGraphics.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** ChartGraphics.java 9 Jul 2004 12:22:15 -0000 1.4 --- ChartGraphics.java 23 Jan 2005 20:31:26 -0000 1.5 *************** *** 91,95 **** void fillRect(int x1, int y1, int x2, int y2) { ! g.fillRect( x1, -y2, x2 - x1, - (y2 - y1) ); } --- 91,95 ---- void fillRect(int x1, int y1, int x2, int y2) { ! g.fillRect( x1, -y2, x2 - x1, (y2 - y1) ); } Index: RrdExporter.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/RrdExporter.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** RrdExporter.java 28 Oct 2004 20:04:43 -0000 1.8 --- RrdExporter.java 23 Jan 2005 20:31:26 -0000 1.9 *************** *** 91,95 **** fetchSources.setRrdOpener( rrdOpener ); ! long finalEndTime = Long.MAX_VALUE; boolean changingEndTime = false; --- 91,95 ---- fetchSources.setRrdOpener( rrdOpener ); ! long finalEndTime = Util.MAX_LONG; boolean changingEndTime = false; Index: Source.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/Source.java,v retrieving revision 1.14 retrieving revision 1.15 diff -C2 -d -r1.14 -r1.15 *** Source.java 28 Oct 2004 20:04:43 -0000 1.14 --- Source.java 23 Jan 2005 20:31:26 -0000 1.15 *************** *** 246,250 **** time = endTime; ! if ( lastTime > 0 && !Double.isNaN(value) && value != Double.MIN_VALUE && value != Double.MAX_VALUE ) { min = Util.min( min, value ); --- 246,250 ---- time = endTime; ! if ( lastTime > 0 && !Double.isNaN(value) && value != Util.MIN_DOUBLE && value != Util.MAX_DOUBLE ) { min = Util.min( min, value ); Index: CustomArea.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/CustomArea.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** CustomArea.java 27 Oct 2004 20:36:26 -0000 1.6 --- CustomArea.java 23 Jan 2005 20:31:26 -0000 1.7 *************** *** 96,109 **** // Get X positions ! if ( xVal1 == Long.MIN_VALUE ) ax = g.getMinX(); ! else if ( xVal1 == Long.MAX_VALUE ) ax = g.getMaxX(); else ax = g.getX( xVal1 ); ! if ( xVal2 == Long.MIN_VALUE ) nx = g.getMinX(); ! else if ( xVal2 == Long.MAX_VALUE ) nx = g.getMaxX(); else --- 96,109 ---- // Get X positions ! if ( xVal1 == Util.MIN_LONG ) ax = g.getMinX(); ! else if ( xVal1 == Util.MAX_LONG ) ax = g.getMaxX(); else ax = g.getX( xVal1 ); ! if ( xVal2 == Util.MIN_LONG ) nx = g.getMinX(); ! else if ( xVal2 == Util.MAX_LONG ) nx = g.getMaxX(); else *************** *** 137,140 **** --- 137,141 ---- // Always use the y value of the second specified point to stack on if ( yVal2 != Util.MAX_DOUBLE ) + { for (int i = 0; i < stackValues.length; i++) if ( xValues[i] < ax || xValues[i] > nx ) *************** *** 142,145 **** --- 143,147 ---- else stackValues[i] = g.getInverseY(ny); + } } *************** *** 147,151 **** * Retrieves the value for a specific point of the CustomArea. The CustomArea is always a rectangle, * this means the returned double value will always be equal to the (Y) value of the second datapoint. ! * In case of an unlimited CustomArea (second datapoint Y value is <code>Double.MAX_VALUE</code>) * the returned value is <code>Double.NaN</code>. * @param tblPos Table index of the datapoint to be retrieved. --- 149,153 ---- * Retrieves the value for a specific point of the CustomArea. The CustomArea is always a rectangle, * this means the returned double value will always be equal to the (Y) value of the second datapoint. ! * In case of an unlimited CustomArea (second datapoint Y value is <code>Util.MAX_DOUBLE</code>) * the returned value is <code>Double.NaN</code>. * @param tblPos Table index of the datapoint to be retrieved. *************** *** 168,177 **** // Stubbed method, irrelevant for this PlotDef ! void setSource( Source[] sources, HashMap sourceIndex ) throws RrdException { ! } // Stubbed, we don't need to set value for a Custom plotdef ! void setValue( int tableRow, long preciseTime, long[] reducedTimestamps ) { ! } void exportXmlTemplate( XmlWriter xml, String legend ) { --- 170,177 ---- // Stubbed method, irrelevant for this PlotDef ! void setSource( Source[] sources, HashMap sourceIndex ) throws RrdException {} // Stubbed, we don't need to set value for a Custom plotdef ! void setValue( int tableRow, long preciseTime, long[] reducedTimestamps ) {} void exportXmlTemplate( XmlWriter xml, String legend ) { Index: FetchSource.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/FetchSource.java,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** FetchSource.java 21 Sep 2004 08:42:10 -0000 1.11 --- FetchSource.java 23 Jan 2005 20:31:26 -0000 1.12 *************** *** 298,302 **** openRrd(); ! long minSampleTime = Long.MAX_VALUE, sampleTime = 0; for ( int i = 0; i < datasources.length; i++ ) --- 298,302 ---- openRrd(); ! long minSampleTime = Util.MAX_LONG, sampleTime = 0; for ( int i = 0; i < datasources.length; i++ ) *************** *** 329,333 **** openRrd(); ! long maxStep = Long.MIN_VALUE, minStep = Long.MAX_VALUE, step = 0; for ( int i = 0; i < datasources.length; i++ ) --- 329,333 ---- openRrd(); ! long maxStep = Util.MIN_LONG, minStep = Util.MAX_LONG, step = 0; for ( int i = 0; i < datasources.length; i++ ) Index: RrdGraphDef.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/RrdGraphDef.java,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** RrdGraphDef.java 21 Sep 2004 08:42:10 -0000 1.20 --- RrdGraphDef.java 23 Jan 2005 20:31:26 -0000 1.21 *************** *** 35,38 **** --- 35,39 ---- import org.jrobin.core.RrdException; import org.jrobin.core.XmlWriter; + import org.jrobin.core.Util; /** *************** *** 708,712 **** */ public void hrule(double value, Color color, String legend) throws RrdException { ! plotDefs.add( new CustomLine( Long.MIN_VALUE, value, Long.MAX_VALUE, value, color ) ); addLegend( legend, color ); } --- 709,713 ---- */ public void hrule(double value, Color color, String legend) throws RrdException { ! plotDefs.add( new CustomLine( Util.MIN_LONG, value, Util.MAX_LONG, value, color ) ); addLegend( legend, color ); } *************** *** 722,726 **** */ public void hrule(double value, Color color, String legend, int lineWidth) throws RrdException { ! plotDefs.add( new CustomLine( Long.MIN_VALUE, value, Long.MAX_VALUE, value, color, lineWidth ) ); addLegend( legend, color ); } --- 723,727 ---- */ public void hrule(double value, Color color, String legend, int lineWidth) throws RrdException { ! plotDefs.add( new CustomLine( Util.MIN_LONG, value, Util.MAX_LONG, value, color, lineWidth ) ); addLegend( legend, color ); } *************** *** 735,739 **** public void vrule( GregorianCalendar timestamp, Color color, String legend ) throws RrdException { long timeSecs = timestamp.getTimeInMillis() / 1000; ! plotDefs.add( new CustomLine( timeSecs, Double.MIN_VALUE, timeSecs, Double.MAX_VALUE, color ) ); addLegend( legend, color ); } --- 736,740 ---- public void vrule( GregorianCalendar timestamp, Color color, String legend ) throws RrdException { long timeSecs = timestamp.getTimeInMillis() / 1000; ! plotDefs.add( new CustomLine( timeSecs, Util.MIN_DOUBLE, timeSecs, Util.MAX_DOUBLE, color ) ); addLegend( legend, color ); } *************** *** 750,754 **** public void vrule( GregorianCalendar timestamp, Color color, String legend, int lineWidth ) throws RrdException { long timeSecs = timestamp.getTimeInMillis() / 1000; ! plotDefs.add( new CustomLine( timeSecs, Double.MIN_VALUE, timeSecs, Double.MAX_VALUE, color, lineWidth ) ); addLegend( legend, color ); } --- 751,755 ---- public void vrule( GregorianCalendar timestamp, Color color, String legend, int lineWidth ) throws RrdException { long timeSecs = timestamp.getTimeInMillis() / 1000; ! plotDefs.add( new CustomLine( timeSecs, Util.MIN_DOUBLE, timeSecs, Util.MAX_DOUBLE, color, lineWidth ) ); addLegend( legend, color ); } Index: ExportData.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/graph/ExportData.java,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** ExportData.java 28 Oct 2004 20:04:43 -0000 1.7 --- ExportData.java 23 Jan 2005 20:31:26 -0000 1.8 *************** *** 176,182 **** /** ! * Returns the number of columns in this dataset. * ! * @return Number of columns (datasources). */ public int getColumnCount() { --- 176,182 ---- /** ! * Returns the number of cells in this dataset. * ! * @return Number of cells (datasources). */ public int getColumnCount() { *************** *** 522,526 **** xml.append( "\t\t<end>" + timestamps[arraySize - 1] + "</end>\n" ); xml.append( "\t\t<rows>" + arraySize + "</rows>\n" ); ! xml.append( "\t\t<columns>" + sources.length + "</columns>\n" ); xml.append( "\t\t<legend>\n" ); for ( int i = 0; i < sources.length; i++ ) --- 522,526 ---- xml.append( "\t\t<end>" + timestamps[arraySize - 1] + "</end>\n" ); xml.append( "\t\t<rows>" + arraySize + "</rows>\n" ); ! xml.append( "\t\t<cells>" + sources.length + "</cells>\n" ); xml.append( "\t\t<legend>\n" ); for ( int i = 0; i < sources.length; i++ ) *************** *** 582,586 **** // -- Parse the metadata ! int columns = Util.Xml.getChildValueAsInt( meta, "columns" ); long step = Util.Xml.getChildValueAsLong( meta, "step" ); String[] dsNames = new String[ columns ]; --- 582,586 ---- // -- Parse the metadata ! int columns = Util.Xml.getChildValueAsInt( meta, "cells" ); long step = Util.Xml.getChildValueAsLong( meta, "step" ); String[] dsNames = new String[ columns ]; |
From: Arne V. <cob...@us...> - 2005-01-23 20:31:35
|
Update of /cvsroot/jrobin/src/org/jrobin/demo In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26216/org/jrobin/demo Modified Files: ComplexDemo.java Log Message: JRobin 2.0 - Additions and related changes Index: ComplexDemo.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/demo/ComplexDemo.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** ComplexDemo.java 27 Oct 2004 20:36:25 -0000 1.4 --- ComplexDemo.java 23 Jan 2005 20:31:26 -0000 1.5 *************** *** 40,44 **** * @author Arne Vandamme (cob...@jr...) */ ! class ComplexDemo { private static final String filename = "complexdemo"; --- 40,44 ---- * @author Arne Vandamme (cob...@jr...) */ ! public class ComplexDemo { private static final String filename = "complexdemo"; *************** *** 171,176 **** new GregorianCalendar(2003, 7, 19, 23, 00), Double.MAX_VALUE, Color.RED, "peak period"); ! def.area(new GregorianCalendar(2003, 7, 20, 5, 00), -Double.MAX_VALUE, ! new GregorianCalendar(2003, 7, 20, 8, 30), Double.MAX_VALUE, Color.LIGHT_GRAY, "quiet period\n"); def.comment(" Rise/descend:"); --- 171,176 ---- new GregorianCalendar(2003, 7, 19, 23, 00), Double.MAX_VALUE, Color.RED, "peak period"); ! def.area(new GregorianCalendar(2003, 7, 20, 5, 00), Util.MIN_DOUBLE, ! new GregorianCalendar(2003, 7, 20, 8, 30), Util.MAX_DOUBLE, Color.LIGHT_GRAY, "quiet period\n"); def.comment(" Rise/descend:"); *************** *** 190,194 **** graph.saveAsPNG(pngFile, 500, 300); gifFile = getPath(3, "gif"); ! graph.saveAsGIF(gifFile, 500, 300); jpgFile = getPath(3, "jpg"); graph.saveAsJPEG(jpgFile, 500, 300, 0.6F); --- 190,194 ---- graph.saveAsPNG(pngFile, 500, 300); gifFile = getPath(3, "gif"); ! graph.saveAsGIF(gifFile, 0, 0); jpgFile = getPath(3, "jpg"); graph.saveAsJPEG(jpgFile, 500, 300, 0.6F); |
From: Arne V. <cob...@us...> - 2005-01-23 20:31:34
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26216/org/jrobin/core Modified Files: FetchData.java RrdDataSet.java Util.java Log Message: JRobin 2.0 - Additions and related changes Index: FetchData.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/FetchData.java,v retrieving revision 1.17 retrieving revision 1.18 diff -C2 -d -r1.17 -r1.18 *** FetchData.java 16 Dec 2004 11:16:01 -0000 1.17 --- FetchData.java 23 Jan 2005 20:31:24 -0000 1.18 *************** *** 50,54 **** * timestamps returned.<p> * ! * Remaining columns are filled with datasource values for the whole timestamp range, * on a column-per-datasource basis. Use {@link #getColumnCount() getColumnCount()} to find * the number of datasources and {@link #getValues(int) getValues(i)} method to obtain --- 50,54 ---- * timestamps returned.<p> * ! * Remaining cells are filled with datasource values for the whole timestamp range, * on a column-per-datasource basis. Use {@link #getColumnCount() getColumnCount()} to find * the number of datasources and {@link #getValues(int) getValues(i)} method to obtain *************** *** 100,108 **** /** ! * 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). */ public int getColumnCount() { --- 100,108 ---- /** ! * Returns the number of cells 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 cells (datasources). */ public int getColumnCount() { Index: RrdDataSet.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdDataSet.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** RrdDataSet.java 21 Sep 2004 08:42:09 -0000 1.4 --- RrdDataSet.java 23 Jan 2005 20:31:25 -0000 1.5 *************** *** 44,50 **** /** ! * Returns the number of columns in this dataset. * ! * @return Number of columns (datasources). */ public int getColumnCount(); --- 44,50 ---- /** ! * Returns the number of cells in this dataset. * ! * @return Number of cells (datasources). */ public int getColumnCount(); Index: Util.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Util.java,v retrieving revision 1.30 retrieving revision 1.31 diff -C2 -d -r1.30 -r1.31 *** Util.java 15 Dec 2004 14:42:44 -0000 1.30 --- Util.java 23 Jan 2005 20:31:25 -0000 1.31 *************** *** 53,56 **** --- 53,59 ---- public class Util { + public static final long MAX_LONG = Long.MAX_VALUE; + public static final long MIN_LONG = -Long.MAX_VALUE; + public static final double MAX_DOUBLE = Double.MAX_VALUE; public static final double MIN_DOUBLE = -Double.MAX_VALUE; *************** *** 69,72 **** --- 72,88 ---- /** + * Converts an array of long primitives to an array of doubles. + * + * @return Same array but with all values as double. + */ + public static double[] toDoubleArray( final long[] array ) + { + double[] values = new double[ array.length ]; + for ( int i = 0; i < array.length; i++ ) + values[i] = array[i]; + return values; + } + + /** * Returns current timestamp in seconds (without milliseconds). Returned timestamp * is obtained with the following expression: <p> |
From: Arne V. <cob...@us...> - 2005-01-23 20:31:34
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26216/org/jrobin/data Modified Files: DataProcessor.java Log Message: JRobin 2.0 - Additions and related changes Index: DataProcessor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/DataProcessor.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** DataProcessor.java 18 Jan 2005 13:05:25 -0000 1.9 --- DataProcessor.java 23 Jan 2005 20:31:25 -0000 1.10 *************** *** 74,77 **** --- 74,78 ---- private final long tStart; private long tEnd, timestamps[]; + private double dblTimestamps[]; // this will be adjusted later private long step = 0; *************** *** 257,260 **** --- 258,278 ---- /** + * Returns the same as getTimestamps(), only as an array of double primitives. + * + * @return array of timestamps in seconds + */ + public double[] getTimestampsDouble() throws RrdException { + if ( timestamps == null ) { + throw new RrdException("Timestamps not calculated yet"); + } + else { + if ( dblTimestamps == null ) + dblTimestamps = Util.toDoubleArray( timestamps ); + + return dblTimestamps; + } + } + + /** * Returns calculated values for a single datasource. Corresponding timestamps can be obtained from * the {@link #getTimestamps()} method. |
From: Arne V. <cob...@us...> - 2005-01-23 20:31:34
|
Update of /cvsroot/jrobin/src/org/jrobin/core/jrrd In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26216/org/jrobin/core/jrrd Modified Files: DataChunk.java Log Message: JRobin 2.0 - Additions and related changes Index: DataChunk.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/jrrd/DataChunk.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** DataChunk.java 22 Jul 2004 09:34:10 -0000 1.1 --- DataChunk.java 23 Jan 2005 20:31:25 -0000 1.2 *************** *** 38,42 **** /** * Returns a summary of the contents of this data chunk. The first column is ! * the time (RRD format) and the following columns are the data source * values. * --- 38,42 ---- /** * Returns a summary of the contents of this data chunk. The first column is ! * the time (RRD format) and the following cells are the data source * values. * |
From: Arne V. <cob...@us...> - 2005-01-23 20:29:11
|
Update of /cvsroot/jrobin/src/org/jrobin/graphx In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25510/graphx Log Message: Directory /cvsroot/jrobin/src/org/jrobin/graphx added to the repository |
From: Sasa M. <sa...@us...> - 2005-01-18 13:05:36
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30851/org/jrobin/data Modified Files: DataProcessor.java Log Message: Added getter/setter for the desired archive step (fetch resolution) to be used while fetching data from RRD files. The method DataProcessor.setFetchRequestResolution() provides functionality necessary for the RrdGraphDef.setResolution() method. Index: DataProcessor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/DataProcessor.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** DataProcessor.java 31 Dec 2004 08:45:17 -0000 1.8 --- DataProcessor.java 18 Jan 2005 13:05:25 -0000 1.9 *************** *** 76,79 **** --- 76,81 ---- // this will be adjusted later private long step = 0; + // resolution to be used for RRD fetch operation + private long fetchRequestResolution = 1; // the order is important, ordinary HashMap is unordered *************** *** 204,207 **** --- 206,234 ---- /** + * Returns desired RRD archive step (reslution) in seconds to be used while fetching data + * from RRD files. In other words, this value will used as the last parameter of + * {@link RrdDb#createFetchRequest(String, long, long, long) RrdDb.createFetchRequest()} method + * when this method is called internally by this DataProcessor. + * + * @return Desired archive step (fetch resolution) in seconds. + */ + public long getFetchRequestResolution() { + return fetchRequestResolution; + } + + /** + * Sets desired RRD archive step in seconds to be used internally while fetching data + * from RRD files. In other words, this value will used as the last parameter of + * {@link RrdDb#createFetchRequest(String, long, long, long) RrdDb.createFetchRequest()} method + * when this method is called internally by this DataProcessor. If this method is never called, fetch + * request resolution defaults to 1 (smallest possible archive step will be chosen automatically). + * + * @param fetchRequestResolution Desired archive step (fetch resoltuion) in seconds. + */ + public void setFetchRequestResolution(long fetchRequestResolution) { + this.fetchRequestResolution = fetchRequestResolution; + } + + /** * Returns ending timestamp. Basically, this value is equal to the ending timestamp * specified in the constructor. However, if the ending timestamps was zero, it *************** *** 675,679 **** try { rrd = getRrd(defSources[i]); ! FetchRequest req = rrd.createFetchRequest(defSources[i].getConsolFun(), tStart, tEndFixed); req.setFilter(dsNames); FetchData data = req.fetchData(); --- 702,707 ---- try { rrd = getRrd(defSources[i]); ! FetchRequest req = rrd.createFetchRequest(defSources[i].getConsolFun(), ! tStart, tEndFixed, fetchRequestResolution); req.setFilter(dsNames); FetchData data = req.fetchData(); *************** *** 845,849 **** // uncomment and run again ! //dp.setStep(7300); // datasource definitions --- 873,880 ---- // uncomment and run again ! //dp.setFetchRequestResolution(86400); ! ! // uncomment and run again ! //dp.setStep(86500); // datasource definitions |
From: Sasa M. <sa...@us...> - 2004-12-31 08:45:30
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8220/org/jrobin/data Modified Files: DataProcessor.java Log Message: bugfix: http://www.jrobin.org/mantis/bug_view_page.php?bug_id=0000073 Index: DataProcessor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/DataProcessor.java,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** DataProcessor.java 29 Dec 2004 11:36:50 -0000 1.7 --- DataProcessor.java 31 Dec 2004 08:45:17 -0000 1.8 *************** *** 60,67 **** * no other value is specified with {@link #setStep(long) setStep()} method. */ ! public static final int DEFAUL_PIXEL_COUNT = 400; private static final double DEFAULT_PERCENTILE = 95.0; // % ! private int pixelCount = DEFAUL_PIXEL_COUNT; /** --- 60,67 ---- * no other value is specified with {@link #setStep(long) setStep()} method. */ ! public static final int DEFAULT_PIXEL_COUNT = 400; private static final double DEFAULT_PERCENTILE = 95.0; // % ! private int pixelCount = DEFAULT_PIXEL_COUNT; /** *************** *** 153,157 **** * the dimension of your graph.<p> * ! * The default number of pixels is defined by constant {@link #DEFAUL_PIXEL_COUNT} * and can be changed with a {@link #setPixelCount(int)} method. * --- 153,157 ---- * the dimension of your graph.<p> * ! * The default number of pixels is defined by constant {@link #DEFAULT_PIXEL_COUNT} * and can be changed with a {@link #setPixelCount(int)} method. * *************** *** 330,334 **** public double getPercentile(String sourceName, double percentile) throws RrdException { if(percentile <= 0.0 || percentile > 100.0) { ! throw new RrdException("Invalid percentile [" + percentile + "], sohuld be between 0 and 100"); } Source source = getSource(sourceName); --- 330,334 ---- public double getPercentile(String sourceName, double percentile) throws RrdException { if(percentile <= 0.0 || percentile > 100.0) { ! throw new RrdException("Invalid percentile [" + percentile + "], should be between 0 and 100"); } Source source = getSource(sourceName); |
From: Sasa M. <sa...@us...> - 2004-12-29 11:37:00
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv23330/org/jrobin/data Modified Files: Aggregator.java DataProcessor.java Def.java SDef.java Source.java Log Message: Added custom percentile boundary (different from 95%) Index: Source.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/Source.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Source.java 15 Dec 2004 14:55:41 -0000 1.3 --- Source.java 29 Dec 2004 11:36:50 -0000 1.4 *************** *** 63,69 **** } ! double get95Percentile(long tStart, long tEnd) throws RrdException { Aggregator agg = new Aggregator(timestamps, values); ! return agg.get95Percentile(tStart, tEnd); } } --- 63,69 ---- } ! double getPercentile(long tStart, long tEnd, double percentile) throws RrdException { Aggregator agg = new Aggregator(timestamps, values); ! return agg.getPercentile(tStart, tEnd, percentile); } } Index: Def.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/Def.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** Def.java 16 Dec 2004 11:16:03 -0000 1.4 --- Def.java 29 Dec 2004 11:36:50 -0000 1.5 *************** *** 107,115 **** } ! double get95Percentile(long tStart, long tEnd) throws RrdException { long[] t = getRrdTimestamps(); double[] v = getRrdValues(); Aggregator agg = new Aggregator(t, v); ! return agg.get95Percentile(tStart, tEnd); } --- 107,115 ---- } ! double getPercentile(long tStart, long tEnd, double percentile) throws RrdException { long[] t = getRrdTimestamps(); double[] v = getRrdValues(); Aggregator agg = new Aggregator(t, v); ! return agg.getPercentile(tStart, tEnd, percentile); } Index: DataProcessor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/DataProcessor.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** DataProcessor.java 16 Dec 2004 11:16:03 -0000 1.6 --- DataProcessor.java 29 Dec 2004 11:36:50 -0000 1.7 *************** *** 61,64 **** --- 61,66 ---- */ public static final int DEFAUL_PIXEL_COUNT = 400; + private static final double DEFAULT_PERCENTILE = 95.0; // % + private int pixelCount = DEFAUL_PIXEL_COUNT; *************** *** 278,281 **** --- 280,285 ---- /** + * This method is just an alias for {@link #getPercentile(String)} method. + * * Used by ISPs which charge for bandwidth utilization on a "95th percentile" basis.<p> * *************** *** 293,298 **** */ public double get95Percentile(String sourceName) throws RrdException { Source source = getSource(sourceName); ! return source.get95Percentile(tStart, tEnd); } --- 297,337 ---- */ public double get95Percentile(String sourceName) throws RrdException { + return getPercentile(sourceName); + } + + /** + * 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 getPercentile(String sourceName) throws RrdException { + return getPercentile(sourceName, DEFAULT_PERCENTILE); + } + + /** + * The same as {@link #getPercentile(String)} but with a possibility to define custom percentile boundary + * (different from 95). + * @param sourceName Datasource name. + * @param percentile Boundary percentile. Value of 95 (%) is suitable in most cases, but you are free + * to provide your own percentile boundary between zero and 100. + * @return Requested percentile of fetched source values + * @throws RrdException Thrown if invalid sourcename is supplied, or if the percentile value makes no sense. + */ + public double getPercentile(String sourceName, double percentile) throws RrdException { + if(percentile <= 0.0 || percentile > 100.0) { + throw new RrdException("Invalid percentile [" + percentile + "], sohuld be between 0 and 100"); + } Source source = getSource(sourceName); ! return source.getPercentile(tStart, tEnd, percentile); } Index: Aggregator.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/Aggregator.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Aggregator.java 16 Dec 2004 11:16:03 -0000 1.2 --- Aggregator.java 29 Dec 2004 11:36:50 -0000 1.3 *************** *** 72,76 **** } ! double get95Percentile(long tStart, long tEnd) { List valueList = new ArrayList(); // create a list of included datasource values (different from NaN) --- 72,76 ---- } ! double getPercentile(long tStart, long tEnd, double percentile) { List valueList = new ArrayList(); // create a list of included datasource values (different from NaN) *************** *** 91,96 **** // sort array Arrays.sort(valuesCopy); ! // skip top 5% values ! count -= (int) Math.ceil(count * 0.05); // if we have anything left... if (count > 0) { --- 91,97 ---- // sort array Arrays.sort(valuesCopy); ! // skip top (100% - percentile) values ! double topPercentile = (100.0 - percentile) / 100.0; ! count -= (int) Math.ceil(count * topPercentile); // if we have anything left... if (count > 0) { Index: SDef.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/SDef.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** SDef.java 15 Dec 2004 14:55:41 -0000 1.2 --- SDef.java 29 Dec 2004 11:36:50 -0000 1.3 *************** *** 64,68 **** } ! double get95Percentile(long tStart, long tEnd) throws RrdException { return value; } --- 64,68 ---- } ! double getPercentile(long tStart, long tEnd, double percentile) throws RrdException { return value; } |
From: Sasa M. <sa...@us...> - 2004-12-21 08:33:09
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv485/org/jrobin/core Modified Files: Header.java Log Message: Minor improvement (idea from http://www.jrobin.org/phpBB2/viewtopic.php?t=103) Index: Header.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Header.java,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** Header.java 9 Nov 2004 11:36:53 -0000 1.8 --- Header.java 21 Dec 2004 08:32:54 -0000 1.9 *************** *** 182,186 **** void validateHeader() throws IOException, RrdException { if(!isJRobinHeader()) { ! throw new RrdException("Not a JRobin RRD!"); } } --- 182,187 ---- void validateHeader() throws IOException, RrdException { if(!isJRobinHeader()) { ! String msg = "Invalid file header. File [" + parentDb.getCanonicalPath() + "] is not a JRobin RRD file"; ! throw new RrdException(msg); } } |
From: Sasa M. <sa...@us...> - 2004-12-17 09:27:56
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20196/org/jrobin/core Modified Files: RrdFileBackend.java RrdNioBackend.java RrdSafeFileBackend.java Log Message: Bugfix #72 Index: RrdSafeFileBackend.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdSafeFileBackend.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** RrdSafeFileBackend.java 10 Nov 2004 13:38:48 -0000 1.2 --- RrdSafeFileBackend.java 17 Dec 2004 09:27:47 -0000 1.3 *************** *** 62,66 **** } for(int i = 0; i < LOCK_RETRY_COUNT; i++) { ! lock = channel.tryLock(); if(lock != null) { return; --- 62,66 ---- } for(int i = 0; i < LOCK_RETRY_COUNT; i++) { ! lock = file.getChannel().tryLock(); if(lock != null) { return; Index: RrdNioBackend.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdNioBackend.java,v retrieving revision 1.20 retrieving revision 1.21 diff -C2 -d -r1.20 -r1.21 *** RrdNioBackend.java 2 Nov 2004 09:06:05 -0000 1.20 --- RrdNioBackend.java 17 Dec 2004 09:27:47 -0000 1.21 *************** *** 57,68 **** super(path, readOnly, lockMode); this.syncMode = syncMode; ! mapFile(); ! if(syncMode == RrdNioBackendFactory.SYNC_BACKGROUND && !readOnly) { ! syncTask = new TimerTask() { ! public void run() { ! sync(); ! } ! }; ! fileSyncTimer.schedule(syncTask, syncPeriod * 1000L, syncPeriod * 1000L); } } --- 57,76 ---- super(path, readOnly, lockMode); this.syncMode = syncMode; ! // try-catch block suggested by jroth ! // http://www.jrobin.org/mantis/bug_view_page.php?bug_id=0000072 ! try { ! mapFile(); ! if(syncMode == RrdNioBackendFactory.SYNC_BACKGROUND && !readOnly) { ! syncTask = new TimerTask() { ! public void run() { ! sync(); ! } ! }; ! fileSyncTimer.schedule(syncTask, syncPeriod * 1000L, syncPeriod * 1000L); ! } ! } ! catch(IOException ioe) { ! super.close(); ! throw ioe; } } *************** *** 73,77 **** FileChannel.MapMode mapMode = readOnly? FileChannel.MapMode.READ_ONLY: FileChannel.MapMode.READ_WRITE; ! byteBuffer = channel.map(mapMode, 0, length); } } --- 81,85 ---- FileChannel.MapMode mapMode = readOnly? FileChannel.MapMode.READ_ONLY: FileChannel.MapMode.READ_WRITE; ! byteBuffer = file.getChannel().map(mapMode, 0, length); } } Index: RrdFileBackend.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/RrdFileBackend.java,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** RrdFileBackend.java 22 Nov 2004 13:34:51 -0000 1.12 --- RrdFileBackend.java 17 Dec 2004 09:27:47 -0000 1.13 *************** *** 28,34 **** import java.io.IOException; import java.io.RandomAccessFile; - import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.util.HashSet; /** --- 28,34 ---- import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileLock; import java.util.HashSet; + import java.util.Set; /** *************** *** 41,45 **** private static final long LOCK_DELAY = 100; // 0.1sec ! private static HashSet openFiles = new HashSet(); /** read/write file status */ --- 41,45 ---- private static final long LOCK_DELAY = 100; // 0.1sec ! private static Set openFiles = new HashSet(); /** read/write file status */ *************** *** 50,55 **** /** radnom access file handle */ protected RandomAccessFile file; - /** file channel used to create locks */ - protected FileChannel channel; /** file lock */ protected FileLock fileLock; --- 50,53 ---- *************** *** 67,73 **** this.lockMode = lockMode; file = new RandomAccessFile(path, readOnly ? "r" : "rw"); ! channel = file.getChannel(); ! lockFile(); ! registerWriter(); } --- 65,76 ---- this.lockMode = lockMode; file = new RandomAccessFile(path, readOnly ? "r" : "rw"); ! try { ! lockFile(); ! registerWriter(); ! } ! catch(IOException ioe) { ! close(); ! throw ioe; ! } } *************** *** 75,79 **** switch (lockMode) { case RrdDb.EXCEPTION_IF_LOCKED: ! fileLock = channel.tryLock(); if (fileLock == null) { // could not obtain lock --- 78,82 ---- switch (lockMode) { case RrdDb.EXCEPTION_IF_LOCKED: ! fileLock = file.getChannel().tryLock(); if (fileLock == null) { // could not obtain lock *************** *** 83,87 **** case RrdDb.WAIT_IF_LOCKED: while (fileLock == null) { ! fileLock = channel.tryLock(); if (fileLock == null) { // could not obtain lock, wait a little, than try again --- 86,90 ---- case RrdDb.WAIT_IF_LOCKED: while (fileLock == null) { ! fileLock = file.getChannel().tryLock(); if (fileLock == null) { // could not obtain lock, wait a little, than try again *************** *** 123,129 **** public void close() throws IOException { unregisterWriter(); ! unlockFile(); ! channel.close(); ! file.close(); } --- 126,135 ---- public void close() throws IOException { unregisterWriter(); ! try { ! unlockFile(); ! } ! finally { ! file.close(); ! } } *************** *** 139,147 **** String canonicalPath = getCanonicalPath(path); synchronized (openFiles) { ! boolean removed = openFiles.remove(canonicalPath); ! if (!removed) { ! throw new IOException("File [" + file + "] could not be removed from the list of files " + ! "open for R/W access"); ! } } } --- 145,149 ---- String canonicalPath = getCanonicalPath(path); synchronized (openFiles) { ! openFiles.remove(canonicalPath); } } |
From: Sasa M. <sa...@us...> - 2004-12-16 11:16:19
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4926/org/jrobin/data Modified Files: Aggregator.java DataProcessor.java Def.java Log Message: Minor changes and improvements. Code polishing and optimizations. Index: DataProcessor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/DataProcessor.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** DataProcessor.java 15 Dec 2004 14:55:41 -0000 1.5 --- DataProcessor.java 16 Dec 2004 11:16:03 -0000 1.6 *************** *** 465,468 **** --- 465,484 ---- /** + * Adds DEF datasource with datasource values already available in the FetchData object. This method is + * used internally by JRobin and probably has no purpose outside of it. + * + * @param name Source name. + * @param fetchData Fetched data containing values for the given source name. + */ + public void addDatasource(String name, FetchData fetchData) { + Def def = new Def(name, fetchData); + sources.put(name, def); + } + + ///////////////////////////////////////////////////////////////// + // CALCULATIONS + ///////////////////////////////////////////////////////////////// + + /** * Method that should be called once all datasources are defined. Data will be fetched from * RRD files, RPN expressions will be calculated, etc. *************** *** 606,610 **** long tEndFixed = (tEnd == 0) ? Util.getTime() : tEnd; for (int i = 0; i < defSources.length; i++) { ! if (defSources[i].getValues() == null) { // not fetched yet Set dsNames = new HashSet(); --- 622,626 ---- long tEndFixed = (tEnd == 0) ? Util.getTime() : tEnd; for (int i = 0; i < defSources.length; i++) { ! if (!defSources[i].isLoaded()) { // not fetched yet Set dsNames = new HashSet(); *************** *** 644,650 **** throw new RrdException("Could not adjust zero ending timestamp, no DEF source provided"); } ! tEnd = defSources[0].getLastValidTimestamp(); for (int i = 1; i < defSources.length; i++) { ! tEnd = Math.min(tEnd, defSources[i].getLastValidTimestamp()); } if (tEnd <= tStart) { --- 660,666 ---- throw new RrdException("Could not adjust zero ending timestamp, no DEF source provided"); } ! tEnd = defSources[0].getArchiveEndTime(); for (int i = 1; i < defSources.length; i++) { ! tEnd = Math.min(tEnd, defSources[i].getArchiveEndTime()); } if (tEnd <= tStart) { Index: Def.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/Def.java,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Def.java 15 Dec 2004 14:55:41 -0000 1.3 --- Def.java 16 Dec 2004 11:16:03 -0000 1.4 *************** *** 35,39 **** private String path, dsName, consolFun, backend; private FetchData fetchData; ! private long lastValidTimestamp, fetchStep; Def(String name, String path, String dsName, String consolFunc) { --- 35,43 ---- private String path, dsName, consolFun, backend; private FetchData fetchData; ! ! Def(String name, FetchData fetchData) { ! this(name, null, name, null, null); ! setFetchData(fetchData); ! } Def(String name, String path, String dsName, String consolFunc) { *************** *** 76,83 **** } ! void setFetchData(FetchData fetchData) throws IOException { this.fetchData = fetchData; - this.lastValidTimestamp = fetchData.getMatchingArchive().getEndTime(); - this.fetchStep = fetchData.getMatchingArchive().getArcStep(); } --- 80,85 ---- } ! void setFetchData(FetchData fetchData) { this.fetchData = fetchData; } *************** *** 90,99 **** } ! long getLastValidTimestamp() { ! return lastValidTimestamp; } long getFetchStep() { ! return fetchStep; } --- 92,101 ---- } ! long getArchiveEndTime() { ! return fetchData.getArcEndTime(); } long getFetchStep() { ! return fetchData.getStep(); } *************** *** 111,113 **** --- 113,119 ---- return agg.get95Percentile(tStart, tEnd); } + + boolean isLoaded() { + return fetchData != null; + } } Index: Aggregator.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/Aggregator.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Aggregator.java 15 Dec 2004 14:55:41 -0000 1.1 --- Aggregator.java 16 Dec 2004 11:16:03 -0000 1.2 *************** *** 33,55 **** import java.util.Arrays; ! /** ! * Class used to calculate aggregated values (MIN, MAX, LAST, FIRST, AVERAGE, TOTAL and 95-PERCENTILE) for ! * the given arrays of timestamps and associated datasource values. ! */ ! public class Aggregator implements ConsolFuns { private long timestamps[], step; private double[] values; ! /** ! * Constructs Aggregator object. Note that you have to supply two arrays to the constructor: an array ! * of timestamps and an array of datasource values. Aggregator assumes that:<p> ! * <ul> ! * <li>these two arrays have the same length ! * <li>the time step between consecutive timestamps is constant. ! * </ul> ! * @param timestamps Array of timestamps (in seconds, without milliseconds) ! * @param values Array of corresponding datasource values ! */ ! public Aggregator(long[] timestamps, double[] values) { assert timestamps.length == values.length: "Incompatible timestamps/values arrays (unequal lengths)"; assert timestamps.length >= 2: "At least two timestamps must be supplied"; --- 33,41 ---- import java.util.Arrays; ! class Aggregator implements ConsolFuns { private long timestamps[], step; private double[] values; ! Aggregator(long[] timestamps, double[] values) { assert timestamps.length == values.length: "Incompatible timestamps/values arrays (unequal lengths)"; assert timestamps.length >= 2: "At least two timestamps must be supplied"; *************** *** 59,70 **** } ! /** ! * Returns an object representing all aggregated values (MIN, MAX, LAST, FIRST, AVERAGE, TOTAL) ! * calculated from arrays supplied in the constructor. ! * @param tStart Starting timestamp of aggregation interval ! * @param tEnd Ending timestamp of aggregation interval ! * @return Object containing all aggregated values. ! */ ! public Aggregates getAggregates(long tStart, long tEnd) { Aggregates agg = new Aggregates(); long totalSeconds = 0; --- 45,49 ---- } ! Aggregates getAggregates(long tStart, long tEnd) { Aggregates agg = new Aggregates(); long totalSeconds = 0; *************** *** 93,112 **** } ! /** ! * 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:<p> ! * <a href="http://www.red.net/support/resourcecentre/leasedline/percentile.php">Rednet</a> or<br> ! * <a href="http://www.bytemark.co.uk/support/tech/95thpercentile.html">Bytemark</a>. ! * ! * @param tStart Starting timestamp of aggregation interval ! * @param tEnd Ending timestamp of aggregation interval ! * @return 95-percentile value ! */ ! public double get95Percentile(long tStart, long tEnd) { List valueList = new ArrayList(); // create a list of included datasource values (different from NaN) --- 72,76 ---- } ! double get95Percentile(long tStart, long tEnd) { List valueList = new ArrayList(); // create a list of included datasource values (different from NaN) |
From: Sasa M. <sa...@us...> - 2004-12-16 11:16:17
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4926/org/jrobin/core Modified Files: FetchData.java Log Message: Minor changes and improvements. Code polishing and optimizations. Index: FetchData.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/FetchData.java,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** FetchData.java 15 Dec 2004 14:42:44 -0000 1.16 --- FetchData.java 16 Dec 2004 11:16:01 -0000 1.17 *************** *** 26,31 **** package org.jrobin.core; - import org.jrobin.data.Aggregator; import org.jrobin.data.Aggregates; import java.io.IOException; --- 26,31 ---- package org.jrobin.core; import org.jrobin.data.Aggregates; + import org.jrobin.data.DataProcessor; import java.io.IOException; *************** *** 58,69 **** */ public class FetchData implements RrdDataSet, ConsolFuns { private FetchRequest request; - private Archive matchingArchive; private String[] dsNames; private long[] timestamps; private double[][] values; FetchData(Archive matchingArchive, FetchRequest request) throws IOException { this.matchingArchive = matchingArchive; this.dsNames = request.getFilter(); if (this.dsNames == null) { --- 58,77 ---- */ public class FetchData implements RrdDataSet, ConsolFuns { + // anything fuuny will do + private static final String RPN_SOURCE_NAME = "WHERE THE SPEECHLES UNITE IN A SILENT ACCORD"; + private FetchRequest request; private String[] dsNames; private long[] timestamps; private double[][] values; + private Archive matchingArchive; + private long arcStep; + private long arcEndTime; + FetchData(Archive matchingArchive, FetchRequest request) throws IOException { this.matchingArchive = matchingArchive; + this.arcStep = matchingArchive.getArcStep(); + this.arcEndTime = matchingArchive.getEndTime(); this.dsNames = request.getFilter(); if (this.dsNames == null) { *************** *** 181,184 **** --- 189,206 ---- /** + * Returns a set of values created by applying RPN expression to the fetched data. + * For example, if you have two datasources named <code>x</code> and <code>y</code> + * in this FetchData and you want to calculate values for <code>(x+y)/2<code> use something like: <p> + * <code>getRpnValues("x,y,+,2,/");</code><p> + * @param rpnExpression RRDTool-like RPN expression + * @return Calculated values + * @throws RrdException Thrown if invalid RPN expression is supplied + */ + public double[] getRpnValues(String rpnExpression) throws RrdException { + DataProcessor dataProcessor = createDataProcessor(rpnExpression); + return dataProcessor.getValues(RPN_SOURCE_NAME); + } + + /** * Returns {@link FetchRequest FetchRequest} object used to create this FetchData object. * *************** *** 311,317 **** */ public double getAggregate(String dsName, String consolFun) throws RrdException { ! Aggregator aggregator = new Aggregator(getTimestamps(), getValues(dsName)); ! Aggregates agg = aggregator.getAggregates(request.getFetchStart(), request.getFetchEnd()); ! return agg.getAggregate(consolFun); } --- 333,375 ---- */ public double getAggregate(String dsName, String consolFun) throws RrdException { ! DataProcessor dp = createDataProcessor(null); ! return dp.getAggregate(dsName, consolFun); ! } ! ! /** ! * Returns aggregated value from the fetched data for a single datasource. ! * Before applying aggregation functions, specified RPN expression is applied to fetched data. ! * For example, if you have a gauge datasource named 'foots' but you want to find the maximum ! * fetched value in meters use something like: <p> ! * <code>getAggregate("foots", "MAX", "foots,0.3048,*");</code><p> ! * @param dsName Datasource name ! * @param consolFun Consolidation function (MIN, MAX, LAST, FIRST, AVERAGE or TOTAL) ! * @param rpnExpression RRDTool-like RPN expression ! * @return Aggregated value ! * @throws RrdException Thrown if the given datasource name cannot be found in fetched data, or if ! * invalid RPN expression is supplied ! * @throws IOException Thrown in case of I/O error (unlikely to happen) ! * @deprecated This method is preserved just for backward compatibility. ! */ ! public double getAggregate(String dsName, String consolFun, String rpnExpression) ! throws RrdException, IOException { ! // for backward compatibility ! rpnExpression = rpnExpression.replaceAll("value", dsName); ! return getRpnAggregate(rpnExpression, consolFun); ! } ! ! /** ! * Returns aggregated value for a set of values calculated by applying an RPN expression to the ! * fetched data. For example, if you have two datasources named <code>x</code> and <code>y</code> ! * in this FetchData and you want to calculate MAX value of <code>(x+y)/2<code> use something like: <p> ! * <code>getRpnAggregate("x,y,+,2,/", "MAX");</code><p> ! * @param rpnExpression RRDTool-like RPN expression ! * @param consolFun Consolidation function (MIN, MAX, LAST, FIRST, AVERAGE or TOTAL) ! * @return Aggregated value ! * @throws RrdException Thrown if invalid RPN expression is supplied ! */ ! public double getRpnAggregate(String rpnExpression, String consolFun) throws RrdException { ! DataProcessor dataProcessor = createDataProcessor(rpnExpression); ! return dataProcessor.getAggregate(RPN_SOURCE_NAME, consolFun); } *************** *** 325,331 **** */ public Aggregates getAggregates(String dsName) throws RrdException { ! Aggregator aggregator = new Aggregator(getTimestamps(), getValues(dsName)); ! Aggregates agg = aggregator.getAggregates(request.getFetchStart(), request.getFetchEnd()); ! return agg; } --- 383,403 ---- */ public Aggregates getAggregates(String dsName) throws RrdException { ! DataProcessor dataProcessor = createDataProcessor(null); ! return dataProcessor.getAggregates(dsName); ! } ! ! /** ! * Returns all aggregated values for a set of values calculated by applying an RPN expression to the ! * fetched data. For example, if you have two datasources named <code>x</code> and <code>y</code> ! * in this FetchData and you want to calculate MIN, MAX, LAST, FIRST, AVERAGE and TOTAL value ! * of <code>(x+y)/2<code> use something like: <p> ! * <code>getRpnAggregates("x,y,+,2,/");</code><p> ! * @param rpnExpression RRDTool-like RPN expression ! * @return Object containing all aggregated values ! * @throws RrdException Thrown if invalid RPN expression is supplied ! */ ! public Aggregates getRpnAggregates(String rpnExpression) throws RrdException, IOException { ! DataProcessor dataProcessor = createDataProcessor(rpnExpression); ! return dataProcessor.getAggregates(RPN_SOURCE_NAME); } *************** *** 346,351 **** */ public double get95Percentile(String dsName) throws RrdException { ! Aggregator aggregator = new Aggregator(getTimestamps(), getValues(dsName)); ! return aggregator.get95Percentile(request.getFetchStart(), request.getFetchEnd()); } --- 418,435 ---- */ public double get95Percentile(String dsName) throws RrdException { ! DataProcessor dataProcessor = createDataProcessor(null); ! return dataProcessor.get95Percentile(dsName); ! } ! ! /** ! * Same as {@link #get95Percentile(String)}, but for a set of values calculated with the given ! * RPN expression. ! * @param rpnExpression RRDTool-like RPN expression ! * @return 95-percentile ! * @throws RrdException Thrown if invalid RPN expression is supplied ! */ ! public double getRpn95Percentile(String rpnExpression) throws RrdException { ! DataProcessor dataProcessor = createDataProcessor(rpnExpression); ! return dataProcessor.get95Percentile(RPN_SOURCE_NAME); } *************** *** 420,422 **** --- 504,540 ---- return outputStream.toString(); } + + /** + * Returns the step of the corresponding RRA archive + * @return Archive step in seconds + */ + public long getArcStep() { + return arcStep; + } + + /** + * Returns the timestamp of the last populated slot in the corresponding RRA archive + * @return Timestamp in seconds + */ + public long getArcEndTime() { + return arcEndTime; + } + + private DataProcessor createDataProcessor(String rpnExpression) throws RrdException { + DataProcessor dataProcessor = new DataProcessor(request.getFetchStart(), request.getFetchEnd()); + for(int i = 0; i < dsNames.length; i++) { + dataProcessor.addDatasource(dsNames[i], this); + } + if(rpnExpression != null) { + dataProcessor.addDatasource(RPN_SOURCE_NAME, rpnExpression); + try { + dataProcessor.processData(); + } + catch(IOException ioe) { + // highly unlikely, since all datasources have already calculated values + throw new RuntimeException("Impossible error: " + ioe); + } + } + return dataProcessor; + } } |
From: Sasa M. <sa...@us...> - 2004-12-15 14:55:50
|
Update of /cvsroot/jrobin/src/org/jrobin/data In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv9264/org/jrobin/data Modified Files: CDef.java DataProcessor.java Def.java PDef.java RpnCalculator.java SDef.java Source.java Added Files: Aggregates.java Aggregator.java Normalizer.java Log Message: MAJOR changes to the DataProcessor. This class MUST be used as a data source for all graphing purposes: - it calculates all DEF, CDEF, SDEF and PDEF values by choosing the optimal time step (not equal to the pixel width as before); this makes DataProcessor (almost) completely independent from the graphing engine. Calculated timestamps and values are compatible with RRDXPORT command. - it calculates all aggregates (gprint-ed values) independently from the actual graph width (in other words, calulcated aggregates will not change if the graph width is changed) - it calculates 95-percentile values - it calculates per-pixel datasource and timestamp values once the number of pixels (graph width) is supplied The graph.* package should no longer perform *any* kind of data calculation without the DataProcessor class (RpnCalculator, for example, should be removed from the graph.* package). Index: DataProcessor.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/DataProcessor.java,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** DataProcessor.java 8 Dec 2004 14:02:37 -0000 1.4 --- DataProcessor.java 15 Dec 2004 14:55:41 -0000 1.5 *************** *** 44,54 **** * 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()); [...1207 lines suppressed...] + long[] t = dp.getTimestampsPerPixel(); + double[] v = dp.getValuesPerPixel("X"); + for(int i = 0; i < t.length; i++) { + System.out.println(t[i] + " " + Util.formatDouble(v[i])); + } + + // aggregates + System.out.println("\nAggregates for X"); + Aggregates agg = dp.getAggregates("X"); + System.out.println(agg.dump()); + System.out.println("\nAggregates for Y"); + agg = dp.getAggregates("Y"); + System.out.println(agg.dump()); + + // 95-percentile + System.out.println("\n95-percentile for X: " + Util.formatDouble(dp.get95Percentile("X"))); + System.out.println("95-percentile for Y: " + Util.formatDouble(dp.get95Percentile("Y"))); } } + Index: RpnCalculator.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/RpnCalculator.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** RpnCalculator.java 25 Nov 2004 12:14:54 -0000 1.2 --- RpnCalculator.java 15 Dec 2004 14:55:41 -0000 1.3 *************** *** 84,87 **** --- 84,89 ---- private static final byte TKN_SECOND = 48; private static final byte TKN_WEEK = 49; + private static final byte TKN_SIGN = 50; + private static final byte TKN_RND = 51; private String rpnExpression; *************** *** 92,96 **** private RpnStack stack = new RpnStack(); private double[] calculatedValues; ! private double[] timestamps; private double timeStep; --- 94,98 ---- private RpnStack stack = new RpnStack(); private double[] calculatedValues; ! private long[] timestamps; private double timeStep; *************** *** 266,269 **** --- 268,277 ---- token.id = TKN_WEEK; } + else if(parsedText.equals("SIGN")) { + token.id = TKN_SIGN; + } + else if(parsedText.equals("RND")) { + token.id = TKN_RND; + } else { token.id = TKN_VAR; *************** *** 464,467 **** --- 472,482 ---- push(getCalendarField(pop(), Calendar.WEEK_OF_YEAR)); break; + case TKN_SIGN: + x1 = pop(); + push(Double.isNaN(x1)? Double.NaN: x1 > 0? +1: x1 < 0? -1: 0); + break; + case TKN_RND: + push(Math.floor(pop() * Math.random())); + break; default: throw new RrdException("Unexpected RPN token encountered, token.id=" + token.id); --- NEW FILE: Aggregator.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 java.util.List; import java.util.ArrayList; import java.util.Arrays; /** * Class used to calculate aggregated values (MIN, MAX, LAST, FIRST, AVERAGE, TOTAL and 95-PERCENTILE) for * the given arrays of timestamps and associated datasource values. */ public class Aggregator implements ConsolFuns { private long timestamps[], step; private double[] values; /** * Constructs Aggregator object. Note that you have to supply two arrays to the constructor: an array * of timestamps and an array of datasource values. Aggregator assumes that:<p> * <ul> * <li>these two arrays have the same length * <li>the time step between consecutive timestamps is constant. * </ul> * @param timestamps Array of timestamps (in seconds, without milliseconds) * @param values Array of corresponding datasource values */ public Aggregator(long[] timestamps, double[] values) { assert timestamps.length == values.length: "Incompatible timestamps/values arrays (unequal lengths)"; assert timestamps.length >= 2: "At least two timestamps must be supplied"; this.timestamps = timestamps; this.values = values; this.step = timestamps[1] - timestamps[0]; } /** * Returns an object representing all aggregated values (MIN, MAX, LAST, FIRST, AVERAGE, TOTAL) * calculated from arrays supplied in the constructor. * @param tStart Starting timestamp of aggregation interval * @param tEnd Ending timestamp of aggregation interval * @return Object containing all aggregated values. */ public Aggregates getAggregates(long tStart, long tEnd) { Aggregates agg = new Aggregates(); long totalSeconds = 0; boolean firstFound = false; for (int i = 0; i < timestamps.length; i++) { long left = Math.max(timestamps[i] - step, tStart); long right = Math.min(timestamps[i], tEnd); long delta = right - left; if (delta > 0) { double value = values[i]; agg.min = Util.min(agg.min, value); agg.max = Util.max(agg.max, value); if (!firstFound) { agg.first = value; firstFound = true; } agg.last = value; if (!Double.isNaN(value)) { agg.total = Util.sum(agg.total, delta * value); totalSeconds += delta; } } } agg.average = totalSeconds > 0 ? (agg.total / totalSeconds) : Double.NaN; return agg; } /** * 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:<p> * <a href="http://www.red.net/support/resourcecentre/leasedline/percentile.php">Rednet</a> or<br> * <a href="http://www.bytemark.co.uk/support/tech/95thpercentile.html">Bytemark</a>. * * @param tStart Starting timestamp of aggregation interval * @param tEnd Ending timestamp of aggregation interval * @return 95-percentile value */ public double get95Percentile(long tStart, long tEnd) { List valueList = new ArrayList(); // create a list of included datasource values (different from NaN) for (int i = 0; i < timestamps.length; i++) { long left = Math.max(timestamps[i] - step, tStart); long right = Math.min(timestamps[i], tEnd); if (right > left && !Double.isNaN(values[i])) { valueList.add(new Double(values[i])); } } // create an array to work with int count = valueList.size(); if (count > 1) { double[] valuesCopy = new double[count]; for (int i = 0; i < count; i++) { valuesCopy[i] = ((Double) valueList.get(i)).doubleValue(); } // sort array Arrays.sort(valuesCopy); // skip top 5% values count -= (int) Math.ceil(count * 0.05); // if we have anything left... if (count > 0) { return valuesCopy[count - 1]; } } // not enough data available return Double.NaN; } /* public static void main(String[] args) { long[] t = {10, 20, 30, 40}; double[] v = {2, Double.NaN, 3, 1}; Aggregator agg = new Aggregator(t, v); System.out.println(agg.getAggregates(0, 40).dump()); } */ } Index: PDef.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/PDef.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PDef.java 25 Nov 2004 12:14:54 -0000 1.1 --- PDef.java 15 Dec 2004 14:55:41 -0000 1.2 *************** *** 54,60 **** } ! double getValue(double timestamp) { ! long t = (long) Math.round(timestamp); ! return plottable.getValue(t); } } --- 54,64 ---- } ! void calculateValues() { ! long[] times = getTimestamps(); ! double[] vals = new double[times.length]; ! for(int i = 0; i < times.length; i++) { ! vals[i] = plottable.getValue(times[i]); ! } ! setValues(vals); } } --- NEW FILE: Aggregates.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; /** * Simple class which holds aggregated values (MIN, MAX, FIRST, LAST, AVERAGE and TOTAL). You * don't need to create objects of this class directly. Objects of this class are returned from * <code>getAggregates()</code> method in * {@link org.jrobin.core.FetchData#getAggregates(String) FetchData} and * {@link DataProcessor#getAggregates(String)} DataProcessor} classes. */ public class Aggregates implements ConsolFuns { double min = Double.NaN, max = Double.NaN; double first = Double.NaN, last = Double.NaN; double average = Double.NaN, total = Double.NaN; Aggregates() { // NOP; } /** * Returns the minimal value * @return Minimal value */ public double getMin() { return min; } /** * Returns the maximum value * @return Maximum value */ public double getMax() { return max; } /** * Returns the first falue * @return First value */ public double getFirst() { return first; } /** * Returns the last value * @return Last value */ public double getLast() { return last; } /** * Returns average * @return Average value */ public double getAverage() { return average; } /** * Returns total value * @return Total value */ public double getTotal() { return total; } /** * Returns single aggregated value for the give consolidation function * @param consolFun Consolidation function: MIN, MAX, FIRST, LAST, AVERAGE, TOTAL. These constanst * are conveniently defined in the {@link org.jrobin.core.ConsolFuns ConsolFuns} interface. * @return Aggregated value * @throws RrdException Thrown if unsupported consolidation function is supplied */ public double getAggregate(String consolFun) throws RrdException { if(consolFun.equals(CF_AVERAGE)) { return average; } else if(consolFun.equals(CF_FIRST)) { return first; } else if(consolFun.equals(CF_LAST)) { return last; } else if(consolFun.equals(CF_MAX)) { return max; } else if(consolFun.equals(CF_MIN)) { return min; } else if(consolFun.equals(CF_TOTAL)) { return total; } else { throw new RrdException("Unknown consolidation function: " + consolFun); } } /** * Returns String representing all aggregated values. Just for debugging purposes. * @return String containing all aggregated values */ public String dump() { return "MIN=" + Util.formatDouble(min) + ", MAX=" + Util.formatDouble(max) + "\n" + "FIRST=" + Util.formatDouble(first) + ", LAST=" + Util.formatDouble(last) + "\n" + "AVERAGE=" + Util.formatDouble(average) + ", TOTAL=" + Util.formatDouble(total); } } Index: SDef.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/SDef.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** SDef.java 25 Nov 2004 12:14:54 -0000 1.1 --- SDef.java 15 Dec 2004 14:55:41 -0000 1.2 *************** *** 26,32 **** --- 26,35 ---- package org.jrobin.data; + import org.jrobin.core.RrdException; + class SDef extends Source { private String defName; private String consolFun; + private double value; SDef(String name, String defName, String consolFun) { *************** *** 44,53 **** } ! void setValue(double value, int count) { double[] values = new double[count]; ! for(int i = 0; i < values.length; i++) { values[i] = value; } setValues(values); } } --- 47,69 ---- } ! void setValue(double value) { ! this.value = value; ! int count = getTimestamps().length; double[] values = new double[count]; ! for(int i = 0; i < count; i++) { values[i] = value; } setValues(values); } + + Aggregates getAggregates(long tStart, long tEnd) throws RrdException { + Aggregates agg = new Aggregates(); + agg.first = agg.last = agg.min = agg.max = agg.average = value; + agg.total = value * (tEnd - tStart); + return agg; + } + + double get95Percentile(long tStart, long tEnd) throws RrdException { + return value; + } } Index: Source.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/Source.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Source.java 8 Dec 2004 14:02:37 -0000 1.2 --- Source.java 15 Dec 2004 14:55:41 -0000 1.3 *************** *** 28,38 **** import org.jrobin.core.ConsolFuns; import org.jrobin.core.RrdException; - import org.jrobin.core.Util; - - import java.util.Arrays; abstract class Source implements ConsolFuns { final private String name; ! private double[] values; Source(String name) { --- 28,36 ---- import org.jrobin.core.ConsolFuns; import org.jrobin.core.RrdException; abstract class Source implements ConsolFuns { final private String name; ! protected double[] values; ! protected long[] timestamps; Source(String name) { *************** *** 40,154 **** } ! 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); ! } ! } ! ! 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; ! 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; } } --- 38,69 ---- } ! String getName() { return name; } ! void setValues(double[] values) { this.values = values; } ! void setTimestamps(long[] timestamps) { ! this.timestamps = timestamps; } ! double[] getValues() { ! return values; } ! long[] getTimestamps() { ! return timestamps; } ! Aggregates getAggregates(long tStart, long tEnd) throws RrdException { ! Aggregator agg = new Aggregator(timestamps, values); ! return agg.getAggregates(tStart, tEnd); } ! double get95Percentile(long tStart, long tEnd) throws RrdException { ! Aggregator agg = new Aggregator(timestamps, values); ! return agg.get95Percentile(tStart, tEnd); } } Index: Def.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/data/Def.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** Def.java 26 Nov 2004 13:47:51 -0000 1.2 --- Def.java 15 Dec 2004 14:55:41 -0000 1.3 *************** *** 35,39 **** private String path, dsName, consolFun, backend; private FetchData fetchData; ! private long endingFetchTimestamp; Def(String name, String path, String dsName, String consolFunc) { --- 35,39 ---- private String path, dsName, consolFun, backend; private FetchData fetchData; ! private long lastValidTimestamp, fetchStep; Def(String name, String path, String dsName, String consolFunc) { *************** *** 78,82 **** void setFetchData(FetchData fetchData) throws IOException { this.fetchData = fetchData; ! this.endingFetchTimestamp = fetchData.getMatchingArchive().getEndTime(); } --- 78,83 ---- void setFetchData(FetchData fetchData) throws IOException { this.fetchData = fetchData; ! this.lastValidTimestamp = fetchData.getMatchingArchive().getEndTime(); ! this.fetchStep = fetchData.getMatchingArchive().getArcStep(); } *************** *** 89,94 **** } ! long getEndingFetchTimestamp() throws IOException { ! return endingFetchTimestamp; } } --- 90,113 ---- } ! long getLastValidTimestamp() { ! return lastValidTimestamp; ! } ! ! long getFetchStep() { ! return fetchStep; ! } ! ! Aggregates getAggregates(long tStart, long tEnd) throws RrdException { ! long[] t = getRrdTimestamps(); ! double[] v = getRrdValues(); ! Aggregator agg = new Aggregator(t, v); ! return agg.getAggregates(tStart, tEnd); ! } ! ! double get95Percentile(long tStart, long tEnd) throws RrdException { ! long[] t = getRrdTimestamps(); ! double[] v = getRrdValues(); ! Aggregator agg = new Aggregator(t, v); ! return agg.get95Percentile(tStart, tEnd); } } --- NEW FILE: Normalizer.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.util.Arrays; class Normalizer { private long[] timestamps; int count; long step; Normalizer(long[] timestamps) { this.timestamps = timestamps; this.step = timestamps[1] - timestamps[0]; this.count = timestamps.length; } double[] normalize(long[] rawTimestamps, double[] rawValues) { int rawCount = rawTimestamps.length; long rawStep = rawTimestamps[1] - rawTimestamps[0]; // check if we have a simple match if(rawCount == count && rawStep == step && rawTimestamps[0] == timestamps[0]) { return getCopyOf(rawValues); } // reset all normalized values to NaN double[] values = new double[count]; Arrays.fill(values, Double.NaN); for (int rawSeg = 0, seg = 0; rawSeg < rawCount && seg < count; rawSeg++) { double rawValue = rawValues[rawSeg]; if (!Double.isNaN(rawValue)) { long rawLeft = rawTimestamps[rawSeg] - rawStep; while (seg < count && rawLeft >= timestamps[seg]) { seg++; } boolean overlap = true; for (int fillSeg = seg; overlap && fillSeg < count; fillSeg++) { long left = timestamps[fillSeg] - step; long t1 = Math.max(rawLeft, left); long t2 = Math.min(rawTimestamps[rawSeg], timestamps[fillSeg]); if (t1 < t2) { values[fillSeg] = Util.sum(values[fillSeg], (t2 - t1) * rawValues[rawSeg]); } else { overlap = false; } } } } for (int seg = 0; seg < count; seg++) { values[seg] /= step; } return values; } private static double[] getCopyOf(double[] rawValues) { int n = rawValues.length; double[] values = new double[n]; for(int i = 0; i < n; i++) { values[i] = rawValues[i]; } return values; } private static void dump(long[] t, double[] v) { for(int i = 0; i < v.length; i++) { System.out.print("[" + t[i] + "," + v[i] + "] "); } System.out.println(""); } public static void main(String[] args) { long rawTime[] = {100, 120, 140, 160, 180, 200}; double rawValues[] = {10, 30, 20, Double.NaN, 50, 40}; long time[] = {60, 100, 140, 180, 220, 260, 300}; Normalizer n = new Normalizer(time); double[] values = n.normalize(rawTime, rawValues); dump(rawTime, rawValues); dump(time, values); } } |
From: Sasa M. <sa...@us...> - 2004-12-15 14:42:53
|
Update of /cvsroot/jrobin/src/org/jrobin/core In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6428/org/jrobin/core Modified Files: FetchData.java Util.java Log Message: Minor changes necessary to integrate FetchData class with the new data.* package. Index: FetchData.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/FetchData.java,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** FetchData.java 25 Nov 2004 14:26:06 -0000 1.15 --- FetchData.java 15 Dec 2004 14:42:44 -0000 1.16 *************** *** 26,29 **** --- 26,32 ---- package org.jrobin.core; + import org.jrobin.data.Aggregator; + import org.jrobin.data.Aggregates; + import java.io.IOException; import java.io.OutputStream; *************** *** 297,301 **** /** ! * Returns aggregated value from the fetched data for a single datasource. * * @param dsName Datasource name --- 300,304 ---- /** ! * Returns single aggregated value from the fetched data for a single datasource. * * @param dsName Datasource name *************** *** 306,387 **** * 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 DataProcessor} 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 { ! throw new RrdException("Unsupported consolidation function [" + consolFun + "]"); ! } ! } ! ! 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; } --- 309,351 ---- * 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 { ! Aggregator aggregator = new Aggregator(getTimestamps(), getValues(dsName)); ! Aggregates agg = aggregator.getAggregates(request.getFetchStart(), request.getFetchEnd()); ! return agg.getAggregate(consolFun); } ! /** ! * Returns all aggregated values (MIN, MAX, LAST, FIRST, AVERAGE or TOTAL) calculated from the fetched data ! * for a single datasource. ! * ! * @param dsName Datasource name. ! * @return Simple object containing all aggregated values. ! * @throws RrdException Thrown if the given datasource name cannot be found in the fetched data. ! */ ! public Aggregates getAggregates(String dsName) throws RrdException { ! Aggregator aggregator = new Aggregator(getTimestamps(), getValues(dsName)); ! Aggregates agg = aggregator.getAggregates(request.getFetchStart(), request.getFetchEnd()); ! return agg; } ! /** ! * 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:<p> ! * <a href="http://www.red.net/support/resourcecentre/leasedline/percentile.php">Rednet</a> or<br> ! * <a href="http://www.bytemark.co.uk/support/tech/95thpercentile.html">Bytemark</a>. ! * ! * @param dsName Datasource name ! * @return 95th percentile of fetched source values ! * @throws RrdException Thrown if invalid source name is supplied ! */ ! public double get95Percentile(String dsName) throws RrdException { ! Aggregator aggregator = new Aggregator(getTimestamps(), getValues(dsName)); ! return aggregator.get95Percentile(request.getFetchStart(), request.getFetchEnd()); } Index: Util.java =================================================================== RCS file: /cvsroot/jrobin/src/org/jrobin/core/Util.java,v retrieving revision 1.29 retrieving revision 1.30 diff -C2 -d -r1.29 -r1.30 *** Util.java 25 Nov 2004 12:14:53 -0000 1.29 --- Util.java 15 Dec 2004 14:42:44 -0000 1.30 *************** *** 90,94 **** * Rounds the given timestamp to the nearest whole "e;step"e;. Rounded value is obtained * from the following expression:<p> ! * <code>timestamp - timestamp % step;</code> * @param timestamp Timestamp in seconds * @param step Step in seconds --- 90,94 ---- * Rounds the given timestamp to the nearest whole "e;step"e;. Rounded value is obtained * from the following expression:<p> ! * <code>timestamp - timestamp % step;</code><p> * @param timestamp Timestamp in seconds * @param step Step in seconds *************** *** 123,127 **** } ! static double sum(double x, double y) { return Double.isNaN(x)? y: Double.isNaN(y)? x: x + y; } --- 123,133 ---- } ! /** ! * Calculates sum of two doubles, but treats NaNs as zeros. ! * @param x First double ! * @param y Second double ! * @return Sum(x,y) calculated as <code>Double.isNaN(x)? y: Double.isNaN(y)? x: x + y;</code> ! */ ! public static double sum(double x, double y) { return Double.isNaN(x)? y: Double.isNaN(y)? x: x + y; } *************** *** 142,146 **** /** ! * Formats double as a string using exponential notation. Used for debugging * throught the project. * @param x value to be formatted --- 148,152 ---- /** ! * Formats double as a string using exponential notation (RRDTool like). Used for debugging * throught the project. * @param x value to be formatted |