true
if the deallocation is successful,
- * otherwise false
- */
- public abstract boolean run(final ByteBuffer directByteBuffer);
- }
-
- public static class OracleSunOpenJdkDeallocator extends Deallocator {
-
- private Method directByteBufferCleanerMethod;
-
- private Method cleanerCleanMethod;
-
- public OracleSunOpenJdkDeallocator() {
- super();
- try {
- final Class> directByteBufferClass = Class.forName("java.nio.DirectByteBuffer");
- directByteBufferCleanerMethod = directByteBufferClass.getDeclaredMethod("cleaner");
- /**
- * The return type is sun.misc.Cleaner in Java <= 1.8,
- * jdk.internal.ref.Cleaner in Java >= 1.9. Only the latter
- * implements the Runnable interface.
- */
- final Class> cleanerClass = directByteBufferCleanerMethod.getReturnType();
- if (Runnable.class.isAssignableFrom(cleanerClass)) {
- cleanerCleanMethod = Runnable.class.getDeclaredMethod("run");
- } else {
- cleanerCleanMethod = cleanerClass.getDeclaredMethod("clean");
- }
- } catch (ClassNotFoundException | NoSuchMethodException e) {
- logger.warn(
- "The initialization of the deallocator for Oracle Java, Sun Java and OpenJDK has failed", e);
- }
- }
-
- @Override
- public boolean run(final ByteBuffer directByteBuffer) {
- boolean success = false;
- if (directByteBufferCleanerMethod != null && cleanerCleanMethod != null) {
- final boolean directByteBufferCleanerMethodWasAccessible = directByteBufferCleanerMethod.isAccessible();
- final boolean cleanerCleanMethodWasAccessible = cleanerCleanMethod.isAccessible();
- try {
- // according to the Java documentation, by default, a reflected object is not accessible
- directByteBufferCleanerMethod.setAccessible(true);
- final Object cleaner = directByteBufferCleanerMethod.invoke(directByteBuffer);
- if (cleaner != null) {
- cleanerCleanMethod.setAccessible(true);
- cleanerCleanMethod.invoke(cleaner);
- success = true;
- }
- //} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- } catch (IllegalAccessException | RuntimeException | InvocationTargetException e) {
- // Replaced with RuntimeException for OpenJDK 9b181
- // throws a java.lang.reflect.InaccessibleObjectException extends RuntimeException which is only in Java 9
- // WARNING: An illegal reflective access operation has occurred
- // WARNING: Illegal reflective access by engine.misc.DeallocationHelper (file:/path/to/jrobin.jar) to field java.nio.DirectByteBuffer.att
- // WARNING: Please consider reporting this to the maintainers of engine.misc.DeallocationHelper
- // WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
- // WARNING: All illegal access operations will be denied in a future release
- // Thread terminated unexpectedly: Shutdown task net.i2p.router.web.StatSummarizer$Shutdown
- // java.lang.reflect.InaccessibleObjectException: Unable to make public void jdk.internal.ref.Cleaner.clean() accessible: module java.base does not "exports jdk.internal.ref" to unnamed module @381353a0
- // at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:337)
- // at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:281)
- // at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:198)
- // at java.base/java.lang.reflect.Method.setAccessible(Method.java:192)
- logger.warn("The deallocation of a direct NIO buffer has failed", e);
- } finally {
- directByteBufferCleanerMethod.setAccessible(directByteBufferCleanerMethodWasAccessible);
- cleanerCleanMethod.setAccessible(cleanerCleanMethodWasAccessible);
- }
- }
- return (success);
- }
- }
-
- public static class AndroidDeallocator extends Deallocator {
-
- private Method directByteBufferFreeMethod;
-
- public AndroidDeallocator() {
- super();
- try {
- final Class> directByteBufferClass = Class.forName("java.nio.DirectByteBuffer");
- directByteBufferFreeMethod = directByteBufferClass.getDeclaredMethod("free");
- } catch (ClassNotFoundException | NoSuchMethodException e) {
- logger.warn("The initialization of the deallocator for Android has failed", e);
- }
- }
-
- @Override
- public boolean run(final ByteBuffer directByteBuffer) {
- boolean success = false;
- if (directByteBufferFreeMethod != null) {
- final boolean directByteBufferFreeMethodWasAccessible = directByteBufferFreeMethod.isAccessible();
- try {
- directByteBufferFreeMethod.setAccessible(true);
- directByteBufferFreeMethod.invoke(directByteBuffer);
- success = true;
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- logger.warn("The deallocation of a direct NIO buffer has failed", e);
- } finally {
- directByteBufferFreeMethod.setAccessible(directByteBufferFreeMethodWasAccessible);
- }
- }
- return (success);
- }
- }
-
- public static class GnuClasspathDeallocator extends Deallocator {
-
- private Method vmDirectByteBufferFreeMethod;
-
- private Field bufferAddressField;
-
- public GnuClasspathDeallocator() {
- super();
- try {
- final Class> vmDirectByteBufferClass = Class.forName("java.nio.VMDirectByteBuffer");
- final Class> gnuClasspathPointerClass = Class.forName("gnu.classpath.Pointer");
- vmDirectByteBufferFreeMethod = vmDirectByteBufferClass.getDeclaredMethod("free",
- gnuClasspathPointerClass);
- bufferAddressField = Buffer.class.getDeclaredField("address");
- } catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException e) {
- logger.warn("The initialization of the deallocator for GNU Classpath has failed", e);
- }
- }
-
- @Override
- public boolean run(final ByteBuffer directByteBuffer) {
- boolean success = false;
- if (vmDirectByteBufferFreeMethod != null && bufferAddressField != null) {
- final boolean bufferAddressFieldWasAccessible = bufferAddressField.isAccessible();
- final boolean vmDirectByteBufferFreeMethodWasAccessible = vmDirectByteBufferFreeMethod.isAccessible();
- try {
- bufferAddressField.setAccessible(true);
- final Object address = bufferAddressField.get(directByteBuffer);
- if (address != null) {
- vmDirectByteBufferFreeMethod.setAccessible(true);
- vmDirectByteBufferFreeMethod.invoke(null, address);
- success = true;
- }
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- logger.warn("The deallocation of a direct NIO buffer has failed", e);
- } finally {
- bufferAddressField.setAccessible(bufferAddressFieldWasAccessible);
- vmDirectByteBufferFreeMethod.setAccessible(vmDirectByteBufferFreeMethodWasAccessible);
- }
- }
- return (success);
- }
- }
-
- public static class ApacheHarmonyDeallocator extends Deallocator {
-
- private Method directByteBufferFreeMethod;
-
- public ApacheHarmonyDeallocator() {
- super();
- try {
- final Class> directByteBufferClass = Class.forName("java.nio.DirectByteBuffer");
- directByteBufferFreeMethod = directByteBufferClass.getDeclaredMethod("free");
- } catch (ClassNotFoundException | NoSuchMethodException e) {
- logger.warn("The initialization of the deallocator for Apache Harmony has failed", e);
- }
- }
-
- @Override
- public boolean run(final ByteBuffer directByteBuffer) {
- boolean success = false;
- if (directByteBufferFreeMethod != null) {
- final boolean directByteBufferFreeMethodWasAccessible = directByteBufferFreeMethod.isAccessible();
- try {
- directByteBufferFreeMethod.setAccessible(true);
- directByteBufferFreeMethod.invoke(directByteBuffer);
- success = true;
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- logger.warn("The deallocation of a direct NIO buffer has failed", e);
- } finally {
- directByteBufferFreeMethod.setAccessible(directByteBufferFreeMethodWasAccessible);
- }
- }
- return (success);
- }
- }
-
- private Maptrue
if the known implementation details should
- * be ignored when looking for the classes and the fields used
- * for the native memory of the direct buffers (they are then
- * fully recomputed at runtime which is slower but safer),
- * otherwise false
- */
- public DeallocationHelper(final boolean ignoreClassesAndFieldsHints) {
- super();
- final List- *
- * For the complete explanation of all archive definition parameters, see RRDTool's - * rrdcreate man page. - * - * @author Sasa Markovic - */ - -public class ArcDef implements ConsolFuns { - /** - * array of valid consolidation function names - */ - public static final String CONSOL_FUNS[] = {CF_AVERAGE, CF_MAX, CF_MIN, CF_LAST}; - - private String consolFun; - private double xff; - private int steps, rows; - - /** - * Creates new archive definition object. This object should be passed as argument to - * {@link RrdDef#addArchive(ArcDef) addArchive()} method of - * {@link RrdDb RrdDb} object. - *
- *
For the complete explanation of all archive definition parameters, see RRDTool's - * rrdcreate man page
- * - * @param consolFun Consolidation function. Allowed values are "AVERAGE", "MIN", - * "MAX" and "LAST" (these string constants are conveniently defined in the - * {@link ConsolFuns} class). - * @param xff X-files factor, between 0 and 1. - * @param steps Number of archive steps. - * @param rows Number of archive rows. - * @throws RrdException Thrown if any parameter has illegal value. - */ - public ArcDef(final String consolFun, final double xff, final int steps, final int rows) throws RrdException { - this.consolFun = consolFun; - this.xff = xff; - this.steps = steps; - this.rows = rows; - validate(); - } - - /** - * Returns consolidation function. - * - * @return Consolidation function. - */ - public String getConsolFun() { - return consolFun; - } - - /** - * Returns the X-files factor. - * - * @return X-files factor value. - */ - public double getXff() { - return xff; - } - - /** - * Returns the number of primary RRD steps which complete a single archive step. - * - * @return Number of steps. - */ - public int getSteps() { - return steps; - } - - /** - * Returns the number of rows (aggregated values) stored in the archive. - * - * @return Number of rows. - */ - public int getRows() { - return rows; - } - - private void validate() throws RrdException { - if (!isValidConsolFun(consolFun)) { - throw new RrdException("Invalid consolidation function specified: " + consolFun); - } - if (Double.isNaN(xff) || xff < 0.0 || xff >= 1.0) { - throw new RrdException("Invalid xff, must be >= 0 and < 1: " + xff); - } - if (steps < 1 || rows < 2) { - throw new RrdException("Invalid steps/rows settings: " + steps + "/" + rows + - ". Minimal values allowed are steps=1, rows=2"); - } - } - - /** - * Returns string representing archive definition (RRDTool format). - * - * @return String containing all archive definition parameters. - */ - public String dump() { - return "RRA:" + consolFun + ":" + xff + ":" + steps + ":" + rows; - } - - /** - * Checks if two archive definitions are equal. - * Archive definitions are considered equal if they have the same number of steps - * and the same consolidation function. It is not possible to create RRD with two - * equal archive definitions. - * - * @param obj Archive definition to compare with. - * @returntrue
if archive definitions are equal,
- * false
otherwise.
- */
- public boolean equals(final Object obj) {
- if (obj instanceof ArcDef) {
- final ArcDef arcObj = (ArcDef) obj;
- return consolFun.equals(arcObj.consolFun) && steps == arcObj.steps;
- }
- return false;
- }
-
- public int hashCode() {
- return (consolFun.hashCode() + steps) * 53;
- }
-
- /**
- * Checks if function argument represents valid consolidation function name.
- *
- * @param consolFun Consolidation function to be checked
- * @return true
if consolFun
is valid consolidation function,
- * false
otherwise.
- */
- public static boolean isValidConsolFun(final String consolFun) {
- for (final String cFun : CONSOL_FUNS) {
- if (cFun.equals(consolFun)) {
- return true;
- }
- }
- return false;
- }
-
- void setRows(final int rows) {
- this.rows = rows;
- }
-
- boolean exactlyEqual(final ArcDef def) {
- return consolFun.equals(def.consolFun) && xff == def.xff &&
- steps == def.steps && rows == def.rows;
- }
-
- public String toString() {
- return "ArcDef@" + Integer.toHexString(hashCode()) + "[consolFun=" + consolFun + ",xff=" + xff + ",steps=" + steps + ",rows=" + rows + "]";
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/ArcState.java b/apps/jrobin/java/src/org/jrobin/core/ArcState.java
deleted file mode 100644
index 71f6dd297a..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/ArcState.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.IOException;
-
-/**
- * Class to represent internal RRD archive state for a single datasource. Objects of this
- * class are never manipulated directly, it's up to JRobin framework to manage
- * internal arcihve states.- * - * @author Sasa Markovic - */ -public class ArcState implements RrdUpdater { - private Archive parentArc; - - private RrdDouble accumValue; - private RrdLong nanSteps; - - ArcState(Archive parentArc, boolean shouldInitialize) throws IOException { - this.parentArc = parentArc; - accumValue = new RrdDouble(this); - nanSteps = new RrdLong(this); - if (shouldInitialize) { - Header header = parentArc.getParentDb().getHeader(); - long step = header.getStep(); - long lastUpdateTime = header.getLastUpdateTime(); - long arcStep = parentArc.getArcStep(); - long initNanSteps = (Util.normalize(lastUpdateTime, step) - - Util.normalize(lastUpdateTime, arcStep)) / step; - accumValue.set(Double.NaN); - nanSteps.set(initNanSteps); - } - } - - String dump() throws IOException { - return "accumValue:" + accumValue.get() + " nanSteps:" + nanSteps.get() + "\n"; - } - - void setNanSteps(long value) throws IOException { - nanSteps.set(value); - } - - /** - * Returns the number of currently accumulated NaN steps. - * - * @return Number of currently accumulated NaN steps. - * @throws IOException Thrown in case of I/O error - */ - public long getNanSteps() throws IOException { - return nanSteps.get(); - } - - void setAccumValue(double value) throws IOException { - accumValue.set(value); - } - - /** - * Returns the value accumulated so far. - * - * @return Accumulated value - * @throws IOException Thrown in case of I/O error - */ - public double getAccumValue() throws IOException { - return accumValue.get(); - } - - /** - * Returns the Archive object to which this ArcState object belongs. - * - * @return Parent Archive object. - */ - public Archive getParent() { - return parentArc; - } - - void appendXml(XmlWriter writer) throws IOException { - writer.startTag("ds"); - writer.writeTag("value", accumValue.get()); - writer.writeTag("unknown_datapoints", nanSteps.get()); - writer.closeTag(); // ds - } - - /** - * Copies object's internal state to another ArcState object. - * - * @param other New ArcState object to copy state to - * @throws IOException Thrown in case of I/O error - * @throws RrdException Thrown if supplied argument is not an ArcState object - */ - public void copyStateTo(RrdUpdater other) throws IOException, RrdException { - if (!(other instanceof ArcState)) { - throw new RrdException( - "Cannot copy ArcState object to " + other.getClass().getName()); - } - ArcState arcState = (ArcState) other; - arcState.accumValue.set(accumValue.get()); - arcState.nanSteps.set(nanSteps.get()); - } - - /** - * Returns the underlying storage (backend) object which actually performs all - * I/O operations. - * - * @return I/O backend object - */ - public RrdBackend getRrdBackend() { - return parentArc.getRrdBackend(); - } - - /** - * Required to implement RrdUpdater interface. You should never call this method directly. - * - * @return Allocator object - */ - public RrdAllocator getRrdAllocator() { - return parentArc.getRrdAllocator(); - } - - public String toString() { - return "ArcState@" + Integer.toHexString(hashCode()) + "[parentArc=" + parentArc + ",accumValue=" + accumValue + ",nanSteps=" + nanSteps + "]"; - } -} diff --git a/apps/jrobin/java/src/org/jrobin/core/Archive.java b/apps/jrobin/java/src/org/jrobin/core/Archive.java deleted file mode 100644 index 470bc75eb7..0000000000 --- a/apps/jrobin/java/src/org/jrobin/core/Archive.java +++ /dev/null @@ -1,418 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor. - * Copyright (c) 2011 The OpenNMS Group, Inc. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *******************************************************************************/ - -package org.jrobin.core; - -import java.io.IOException; - -/** - * Class to represent single RRD archive in a RRD with its internal state. - * Normally, you don't need methods to manipulate archive objects directly - * because JRobin framework does it automatically for you. - *
- * Each archive object consists of three parts: archive definition, archive state objects - * (one state object for each datasource) and round robin archives (one round robin for - * each datasource). API (read-only) is provided to access each of theese parts. - * - * @author Sasa Markovic - */ -public class Archive implements RrdUpdater, ConsolFuns { - private RrdDb parentDb; - // definition - private RrdString consolFun; - private RrdDouble xff; - private RrdInt steps, rows; - // state - private Robin[] robins; - private ArcState[] states; - - Archive(final RrdDb parentDb, final ArcDef arcDef) throws IOException { - final boolean shouldInitialize = arcDef != null; - this.parentDb = parentDb; - consolFun = new RrdString(this, true); // constant, may be cached - xff = new RrdDouble(this); - steps = new RrdInt(this, true); // constant, may be cached - rows = new RrdInt(this, true); // constant, may be cached - if (shouldInitialize) { - consolFun.set(arcDef.getConsolFun()); - xff.set(arcDef.getXff()); - steps.set(arcDef.getSteps()); - rows.set(arcDef.getRows()); - } - final int dsCount = parentDb.getHeader().getDsCount(); - states = new ArcState[dsCount]; - robins = new Robin[dsCount]; - final int numRows = rows.get(); - for (int i = 0; i < dsCount; i++) { - states[i] = new ArcState(this, shouldInitialize); - robins[i] = new Robin(this, numRows, shouldInitialize); - } - } - - // read from XML - Archive(final RrdDb parentDb, final DataImporter reader, final int arcIndex) throws IOException, RrdException,RrdException { - this(parentDb, new ArcDef( - reader.getConsolFun(arcIndex), reader.getXff(arcIndex), - reader.getSteps(arcIndex), reader.getRows(arcIndex))); - final int dsCount = parentDb.getHeader().getDsCount(); - for (int i = 0; i < dsCount; i++) { - // restore state - states[i].setAccumValue(reader.getStateAccumValue(arcIndex, i)); - states[i].setNanSteps(reader.getStateNanSteps(arcIndex, i)); - // restore robins - double[] values = reader.getValues(arcIndex, i); - robins[i].update(values); - } - } - - /** - * Returns archive time step in seconds. Archive step is equal to RRD step - * multiplied with the number of archive steps. - * - * @return Archive time step in seconds - * @throws IOException Thrown in case of I/O error. - */ - public long getArcStep() throws IOException { - final long step = parentDb.getHeader().getStep(); - return step * steps.get(); - } - - String dump() throws IOException { - final StringBuffer buffer = new StringBuffer("== ARCHIVE ==\n"); - buffer.append("RRA:").append(consolFun.get()).append(":").append(xff.get()).append(":").append(steps.get()). - append(":").append(rows.get()).append("\n"); - buffer.append("interval [").append(getStartTime()).append(", ").append(getEndTime()).append("]" + "\n"); - for (int i = 0; i < robins.length; i++) { - buffer.append(states[i].dump()); - buffer.append(robins[i].dump()); - } - return buffer.toString(); - } - - RrdDb getParentDb() { - return parentDb; - } - - public void archive(final int dsIndex, final double value, final long numStepUpdates) throws IOException { - final Robin robin = robins[dsIndex]; - final ArcState state = states[dsIndex]; - final long step = parentDb.getHeader().getStep(); - final long lastUpdateTime = parentDb.getHeader().getLastUpdateTime(); - long updateTime = Util.normalize(lastUpdateTime, step) + step; - final long arcStep = getArcStep(); - final String consolFunString = consolFun.get(); - final int numSteps = steps.get(); - final int numRows = rows.get(); - final double xffValue = xff.get(); - - // finish current step - long numUpdates = numStepUpdates; - while (numUpdates > 0) { - accumulate(state, value, consolFunString); - numUpdates--; - if (updateTime % arcStep == 0) { - finalizeStep(state, robin, consolFunString, numSteps, xffValue); - break; - } - else { - updateTime += step; - } - } - // update robin in bulk - final int bulkUpdateCount = (int) Math.min(numUpdates / numSteps, (long) numRows); - robin.bulkStore(value, bulkUpdateCount); - // update remaining steps - final long remainingUpdates = numUpdates % numSteps; - for (long i = 0; i < remainingUpdates; i++) { - accumulate(state, value, consolFunString); - } - } - - private void accumulate(final ArcState state, final double value, String consolFunString) throws IOException { - if (Double.isNaN(value)) { - state.setNanSteps(state.getNanSteps() + 1); - } - else { - final double accumValue = state.getAccumValue(); - if (consolFunString.equals(CF_MIN)) { - final double minValue = Util.min(accumValue, value); - if (minValue != accumValue) { - state.setAccumValue(minValue); - } - } - else if (consolFunString.equals(CF_MAX)) { - final double maxValue = Util.max(accumValue, value); - if (maxValue != accumValue) { - state.setAccumValue(maxValue); - } - } - else if (consolFunString.equals(CF_LAST)) { - state.setAccumValue(value); - } - else if (consolFunString.equals(CF_AVERAGE)) { - state.setAccumValue(Util.sum(accumValue, value)); - } - } - } - - private void finalizeStep(final ArcState state, final Robin robin, final String consolFunString, final long numSteps, final double xffValue) throws IOException { - final long nanSteps = state.getNanSteps(); - //double nanPct = (double) nanSteps / (double) arcSteps; - double accumValue = state.getAccumValue(); - if (nanSteps <= xffValue * numSteps && !Double.isNaN(accumValue)) { - if (consolFunString.equals(CF_AVERAGE)) { - accumValue /= (numSteps - nanSteps); - } - robin.store(accumValue); - } else { - robin.store(Double.NaN); - } - state.setAccumValue(Double.NaN); - state.setNanSteps(0); - } - - /** - * Returns archive consolidation function ("AVERAGE", "MIN", "MAX" or "LAST"). - * - * @return Archive consolidation function. - * @throws IOException Thrown in case of I/O error. - */ - public String getConsolFun() throws IOException { - return consolFun.get(); - } - - /** - * Returns archive X-files factor. - * - * @return Archive X-files factor (between 0 and 1). - * @throws IOException Thrown in case of I/O error. - */ - public double getXff() throws IOException { - return xff.get(); - } - - /** - * Returns the number of archive steps. - * - * @return Number of archive steps. - * @throws IOException Thrown in case of I/O error. - */ - public int getSteps() throws IOException { - return steps.get(); - } - - /** - * Returns the number of archive rows. - * - * @return Number of archive rows. - * @throws IOException Thrown in case of I/O error. - */ - public int getRows() throws IOException { - return rows.get(); - } - - /** - * Returns current starting timestamp. This value is not constant. - * - * @return Timestamp corresponding to the first archive row - * @throws IOException Thrown in case of I/O error. - */ - public long getStartTime() throws IOException { - final long endTime = getEndTime(); - final long arcStep = getArcStep(); - final long numRows = rows.get(); - return endTime - (numRows - 1) * arcStep; - } - - /** - * Returns current ending timestamp. This value is not constant. - * - * @return Timestamp corresponding to the last archive row - * @throws IOException Thrown in case of I/O error. - */ - public long getEndTime() throws IOException { - final long arcStep = getArcStep(); - final long lastUpdateTime = parentDb.getHeader().getLastUpdateTime(); - return Util.normalize(lastUpdateTime, arcStep); - } - - /** - * Returns the underlying archive state object. Each datasource has its - * corresponding ArcState object (archive states are managed independently - * for each RRD datasource). - * - * @param dsIndex Datasource index - * @return Underlying archive state object - */ - public ArcState getArcState(final int dsIndex) { - return states[dsIndex]; - } - - /** - * Returns the underlying round robin archive. Robins are used to store actual - * archive values on a per-datasource basis. - * - * @param dsIndex Index of the datasource in the RRD. - * @return Underlying round robin archive for the given datasource. - */ - public Robin getRobin(final int dsIndex) { - return robins[dsIndex]; - } - - FetchData fetchData(final FetchRequest request) throws IOException, RrdException { - final long arcStep = getArcStep(); - final long fetchStart = Util.normalize(request.getFetchStart(), arcStep); - long fetchEnd = Util.normalize(request.getFetchEnd(), arcStep); - if (fetchEnd < request.getFetchEnd()) { - fetchEnd += arcStep; - } - final long startTime = getStartTime(); - final long endTime = getEndTime(); - String[] dsToFetch = request.getFilter(); - if (dsToFetch == null) { - dsToFetch = parentDb.getDsNames(); - } - final int dsCount = dsToFetch.length; - final int ptsCount = (int) ((fetchEnd - fetchStart) / arcStep + 1); - final long[] timestamps = new long[ptsCount]; - final double[][] values = new double[dsCount][ptsCount]; - final long matchStartTime = Math.max(fetchStart, startTime); - final long matchEndTime = Math.min(fetchEnd, endTime); - double[][] robinValues = null; - if (matchStartTime <= matchEndTime) { - // preload robin values - final int matchCount = (int) ((matchEndTime - matchStartTime) / arcStep + 1); - final int matchStartIndex = (int) ((matchStartTime - startTime) / arcStep); - robinValues = new double[dsCount][]; - for (int i = 0; i < dsCount; i++) { - final int dsIndex = parentDb.getDsIndex(dsToFetch[i]); - robinValues[i] = robins[dsIndex].getValues(matchStartIndex, matchCount); - } - } - for (int ptIndex = 0; ptIndex < ptsCount; ptIndex++) { - final long time = fetchStart + ptIndex * arcStep; - timestamps[ptIndex] = time; - for (int i = 0; i < dsCount; i++) { - double value = Double.NaN; - if (time >= matchStartTime && time <= matchEndTime) { - // inbound time - final int robinValueIndex = (int) ((time - matchStartTime) / arcStep); - assert robinValues != null; - value = robinValues[i][robinValueIndex]; - } - values[i][ptIndex] = value; - } - } - final FetchData fetchData = new FetchData(this, request); - fetchData.setTimestamps(timestamps); - fetchData.setValues(values); - return fetchData; - } - - void appendXml(final XmlWriter writer) throws IOException { - writer.startTag("rra"); - writer.writeTag("cf", consolFun.get()); - writer.writeComment(getArcStep() + " seconds"); - writer.writeTag("pdp_per_row", steps.get()); - writer.writeTag("xff", xff.get()); - writer.startTag("cdp_prep"); - for (final ArcState state : states) { - state.appendXml(writer); - } - writer.closeTag(); // cdp_prep - writer.startTag("database"); - final long startTime = getStartTime(); - for (int i = 0; i < rows.get(); i++) { - final long time = startTime + i * getArcStep(); - writer.writeComment(Util.getDate(time) + " / " + time); - writer.startTag("row"); - for (final Robin robin : robins) { - writer.writeTag("v", robin.getValue(i)); - } - writer.closeTag(); // row - } - writer.closeTag(); // database - writer.closeTag(); // rra - } - - /** - * Copies object's internal state to another Archive object. - * - * @param other New Archive object to copy state to - * @throws IOException Thrown in case of I/O error - * @throws RrdException Thrown if supplied argument is not an Archive object - */ - public void copyStateTo(final RrdUpdater other) throws IOException, RrdException { - if (!(other instanceof Archive)) { - throw new RrdException("Cannot copy Archive object to " + other.getClass().getName()); - } - final Archive arc = (Archive) other; - if (!arc.consolFun.get().equals(consolFun.get())) { - throw new RrdException("Incompatible consolidation functions"); - } - if (arc.steps.get() != steps.get()) { - throw new RrdException("Incompatible number of steps"); - } - final int count = parentDb.getHeader().getDsCount(); - for (int i = 0; i < count; i++) { - final int j = Util.getMatchingDatasourceIndex(parentDb, i, arc.parentDb); - if (j >= 0) { - states[i].copyStateTo(arc.states[j]); - robins[i].copyStateTo(arc.robins[j]); - } - } - } - - /** - * Sets X-files factor to a new value. - * - * @param xff New X-files factor value. Must be >= 0 and < 1. - * @throws RrdException Thrown if invalid value is supplied - * @throws IOException Thrown in case of I/O error - */ - public void setXff(final double xff) throws RrdException, IOException { - if (xff < 0D || xff >= 1D) { - throw new RrdException("Invalid xff supplied (" + xff + "), must be >= 0 and < 1"); - } - this.xff.set(xff); - } - - /** - * Returns the underlying storage (backend) object which actually performs all - * I/O operations. - * - * @return I/O backend object - */ - public RrdBackend getRrdBackend() { - return parentDb.getRrdBackend(); - } - - /** - * Required to implement RrdUpdater interface. You should never call this method directly. - * - * @return Allocator object - */ - public RrdAllocator getRrdAllocator() { - return parentDb.getRrdAllocator(); - } - - public String toString() { - return "Archive@" + Integer.toHexString(hashCode()) + "[parentDb=" + parentDb + ",consolFun=" + consolFun + ",xff=" + xff + ",steps=" + steps + ",rows=" + rows + ",robins=" + robins + ",states=" + states + "]"; - } -} diff --git a/apps/jrobin/java/src/org/jrobin/core/ConsolFuns.java b/apps/jrobin/java/src/org/jrobin/core/ConsolFuns.java deleted file mode 100644 index ec9f4bd725..0000000000 --- a/apps/jrobin/java/src/org/jrobin/core/ConsolFuns.java +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor. - * Copyright (c) 2011 The OpenNMS Group, Inc. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *******************************************************************************/ -package org.jrobin.core; - -/** - * Simple interface to represent available consolidation functions - */ -public interface ConsolFuns { - /** - * Constant to represent AVERAGE consolidation function - */ - public static final String CF_AVERAGE = "AVERAGE"; - - /** - * Constant to represent MIN consolidation function - */ - public static final String CF_MIN = "MIN"; - - /** - * Constant to represent MAX consolidation function - */ - public static final String CF_MAX = "MAX"; - - /** - * Constant to represent LAST consolidation function - */ - public static final String CF_LAST = "LAST"; - - /** - * Constant to represent FIRST consolidation function - */ - public static final String CF_FIRST = "FIRST"; - - /** - * Constant to represent TOTAL consolidation function - */ - public static final String CF_TOTAL = "TOTAL"; -} diff --git a/apps/jrobin/java/src/org/jrobin/core/DataImporter.java b/apps/jrobin/java/src/org/jrobin/core/DataImporter.java deleted file mode 100644 index 9055005838..0000000000 --- a/apps/jrobin/java/src/org/jrobin/core/DataImporter.java +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor. - * Copyright (c) 2011 The OpenNMS Group, Inc. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *******************************************************************************/ - -package org.jrobin.core; - -import java.io.IOException; - -import org.jrobin.core.RrdException; - -abstract class DataImporter { - - // header - abstract String getVersion() throws RrdException, IOException; - - abstract long getLastUpdateTime() throws RrdException, IOException; - - abstract long getStep() throws RrdException, IOException; - - abstract int getDsCount() throws RrdException, IOException; - - abstract int getArcCount() throws RrdException, IOException; - - // datasource - abstract String getDsName(int dsIndex) throws RrdException, IOException; - - abstract String getDsType(int dsIndex) throws RrdException, IOException; - - abstract long getHeartbeat(int dsIndex) throws RrdException, IOException; - - abstract double getMinValue(int dsIndex) throws RrdException, IOException; - - abstract double getMaxValue(int dsIndex) throws RrdException, IOException; - - // datasource state - abstract double getLastValue(int dsIndex) throws RrdException, IOException; - - abstract double getAccumValue(int dsIndex) throws RrdException, IOException; - - abstract long getNanSeconds(int dsIndex) throws RrdException, IOException; - - // archive - abstract String getConsolFun(int arcIndex) throws RrdException, IOException; - - abstract double getXff(int arcIndex) throws RrdException, IOException; - - abstract int getSteps(int arcIndex) throws RrdException, IOException; - - abstract int getRows(int arcIndex) throws RrdException, IOException; - - // archive state - abstract double getStateAccumValue(int arcIndex, int dsIndex) throws RrdException, IOException; - - abstract int getStateNanSteps(int arcIndex, int dsIndex) throws RrdException, IOException; - - abstract double[] getValues(int arcIndex, int dsIndex) throws RrdException, IOException,RrdException; - - long getEstimatedSize() throws RrdException, IOException { - int dsCount = getDsCount(); - int arcCount = getArcCount(); - int rowCount = 0; - for (int i = 0; i < arcCount; i++) { - rowCount += getRows(i); - } - return RrdDef.calculateSize(dsCount, arcCount, rowCount); - } - - void release() throws RrdException, IOException { - // NOP - } - -} \ No newline at end of file diff --git a/apps/jrobin/java/src/org/jrobin/core/Datasource.java b/apps/jrobin/java/src/org/jrobin/core/Datasource.java deleted file mode 100644 index 3aca8d3d45..0000000000 --- a/apps/jrobin/java/src/org/jrobin/core/Datasource.java +++ /dev/null @@ -1,497 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor. - * Copyright (c) 2011 The OpenNMS Group, Inc. - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - *******************************************************************************/ - -package org.jrobin.core; - -import java.io.IOException; - -/** - * Class to represent single datasource within RRD. Each datasource object holds the - * following information: datasource definition (once set, never changed) and - * datasource state variables (changed whenever RRD gets updated). - *
- * Normally, you don't need to manipluate Datasource objects directly, it's up to
- * JRobin framework to do it for you.
- *
- * @author Sasa Markovic
- */
-
-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
- private RrdString dsName, dsType;
- private RrdLong heartbeat;
- private RrdDouble minValue, maxValue;
-
- // cache
- private String m_primitiveDsName = null;
- private String m_primitiveDsType = null;
-
- // state variables
- private RrdDouble lastValue;
- private RrdLong nanSeconds;
- private RrdDouble accumValue;
-
- Datasource(final RrdDb parentDb, final DsDef dsDef) throws IOException {
- boolean shouldInitialize = dsDef != null;
- this.parentDb = parentDb;
- dsName = new RrdString(this);
- dsType = new RrdString(this);
- heartbeat = new RrdLong(this);
- minValue = new RrdDouble(this);
- maxValue = new RrdDouble(this);
- lastValue = new RrdDouble(this);
- accumValue = new RrdDouble(this);
- nanSeconds = new RrdLong(this);
- if (shouldInitialize) {
- dsName.set(dsDef.getDsName());
- m_primitiveDsName = null;
- dsType.set(dsDef.getDsType());
- m_primitiveDsType = null;
- heartbeat.set(dsDef.getHeartbeat());
- minValue.set(dsDef.getMinValue());
- maxValue.set(dsDef.getMaxValue());
- lastValue.set(Double.NaN);
- accumValue.set(0.0);
- final Header header = parentDb.getHeader();
- nanSeconds.set(header.getLastUpdateTime() % header.getStep());
- }
- }
-
- Datasource(final RrdDb parentDb, final DataImporter reader, final int dsIndex) throws IOException, RrdException {
- this(parentDb, null);
- dsName.set(reader.getDsName(dsIndex));
- m_primitiveDsName = null;
- dsType.set(reader.getDsType(dsIndex));
- m_primitiveDsType = null;
- heartbeat.set(reader.getHeartbeat(dsIndex));
- minValue.set(reader.getMinValue(dsIndex));
- maxValue.set(reader.getMaxValue(dsIndex));
- lastValue.set(reader.getLastValue(dsIndex));
- accumValue.set(reader.getAccumValue(dsIndex));
- nanSeconds.set(reader.getNanSeconds(dsIndex));
- }
-
- String dump() throws IOException {
- return "== DATASOURCE ==\n" +
- "DS:" + dsName.get() + ":" + dsType.get() + ":" +
- heartbeat.get() + ":" + minValue.get() + ":" +
- maxValue.get() + "\nlastValue:" + lastValue.get() +
- " nanSeconds:" + nanSeconds.get() +
- " accumValue:" + accumValue.get() + "\n";
- }
-
- /**
- * Returns datasource name.
- *
- * @return Datasource name
- * @throws IOException Thrown in case of I/O error
- */
- public String getDsName() throws IOException {
- if (m_primitiveDsName == null) {
- m_primitiveDsName = dsName.get();
- }
- return m_primitiveDsName;
- }
-
- /**
- * Returns datasource type (GAUGE, COUNTER, DERIVE, ABSOLUTE).
- *
- * @return Datasource type.
- * @throws IOException Thrown in case of I/O error
- */
- public String getDsType() throws IOException {
- if (m_primitiveDsType == null) {
- m_primitiveDsType = dsType.get();
- }
- return m_primitiveDsType;
- }
-
- /**
- * Returns datasource heartbeat
- *
- * @return Datasource heartbeat
- * @throws IOException Thrown in case of I/O error
- */
-
- public long getHeartbeat() throws IOException {
- return heartbeat.get();
- }
-
- /**
- * Returns mimimal allowed value for this datasource.
- *
- * @return Minimal value allowed.
- * @throws IOException Thrown in case of I/O error
- */
- public double getMinValue() throws IOException {
- return minValue.get();
- }
-
- /**
- * Returns maximal allowed value for this datasource.
- *
- * @return Maximal value allowed.
- * @throws IOException Thrown in case of I/O error
- */
- public double getMaxValue() throws IOException {
- return maxValue.get();
- }
-
- /**
- * Returns last known value of the datasource.
- *
- * @return Last datasource value.
- * @throws IOException Thrown in case of I/O error
- */
- public double getLastValue() throws IOException {
- return lastValue.get();
- }
-
- /**
- * Returns value this datasource accumulated so far.
- *
- * @return Accumulated datasource value.
- * @throws IOException Thrown in case of I/O error
- */
- public double getAccumValue() throws IOException {
- return accumValue.get();
- }
-
- /**
- * Returns the number of accumulated NaN seconds.
- *
- * @return Accumulated NaN seconds.
- * @throws IOException Thrown in case of I/O error
- */
- public long getNanSeconds() throws IOException {
- return nanSeconds.get();
- }
-
- void process(final long newTime, final double newValue) throws IOException, RrdException {
- final Header header = parentDb.getHeader();
- final long step = header.getStep();
- final long oldTime = header.getLastUpdateTime();
- final long startTime = Util.normalize(oldTime, step);
- final long endTime = startTime + step;
- final double oldValue = lastValue.get();
- final double updateValue = calculateUpdateValue(oldTime, oldValue, newTime, newValue);
- if (newTime < endTime) {
- accumulate(oldTime, newTime, updateValue);
- }
- else {
- // should store something
- final long boundaryTime = Util.normalize(newTime, step);
- accumulate(oldTime, boundaryTime, updateValue);
- final double value = calculateTotal(startTime, boundaryTime);
- // how many updates?
- final long numSteps = (boundaryTime - endTime) / step + 1L;
- // ACTION!
- parentDb.archive(this, value, numSteps);
- // cleanup
- nanSeconds.set(0);
- accumValue.set(0.0);
- accumulate(boundaryTime, newTime, updateValue);
- }
- }
-
- private double calculateUpdateValue(final long oldTime, final double oldValue, final long newTime, final double newValue) throws IOException {
- double updateValue = Double.NaN;
- if (newTime - oldTime <= heartbeat.get()) {
- final String type = dsType.get();
- if (type.equals(DT_GAUGE)) {
- updateValue = newValue;
- }
- else if (type.equals(DT_ABSOLUTE)) {
- if (!Double.isNaN(newValue)) {
- updateValue = newValue / (newTime - oldTime);
- }
- }
- else if (type.equals(DT_DERIVE)) {
- if (!Double.isNaN(newValue) && !Double.isNaN(oldValue)) {
- updateValue = (newValue - oldValue) / (newTime - oldTime);
- }
- }
- else if (type.equals(DT_COUNTER)) {
- 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) {
- updateValue = diff / (newTime - oldTime);
- }
- }
- }
- if (!Double.isNaN(updateValue)) {
- final double minVal = minValue.get();
- final double maxVal = maxValue.get();
- if (!Double.isNaN(minVal) && updateValue < minVal) {
- updateValue = Double.NaN;
- }
- if (!Double.isNaN(maxVal) && updateValue > maxVal) {
- updateValue = Double.NaN;
- }
- }
- }
- lastValue.set(newValue);
- return updateValue;
- }
-
- private void accumulate(final long oldTime, final long newTime, final double updateValue) throws IOException {
- if (Double.isNaN(updateValue)) {
- nanSeconds.set(nanSeconds.get() + (newTime - oldTime));
- }
- else {
- accumValue.set(accumValue.get() + updateValue * (newTime - oldTime));
- }
- }
-
- private double calculateTotal(final long startTime, final long boundaryTime) throws IOException {
- double totalValue = Double.NaN;
- final long validSeconds = boundaryTime - startTime - nanSeconds.get();
- if (nanSeconds.get() <= heartbeat.get() && validSeconds > 0) {
- totalValue = accumValue.get() / validSeconds;
- }
- // IMPORTANT:
- // if datasource name ends with "!", we'll send zeros instead of NaNs
- // this might be handy from time to time
- if (Double.isNaN(totalValue) && dsName.get().endsWith(DsDef.FORCE_ZEROS_FOR_NANS_SUFFIX)) {
- totalValue = 0D;
- }
- return totalValue;
- }
-
- void appendXml(final XmlWriter writer) throws IOException {
- writer.startTag("ds");
- writer.writeTag("name", dsName.get());
- writer.writeTag("type", dsType.get());
- writer.writeTag("minimal_heartbeat", heartbeat.get());
- writer.writeTag("min", minValue.get());
- writer.writeTag("max", maxValue.get());
- writer.writeComment("PDP Status");
- writer.writeTag("last_ds", lastValue.get(), "UNKN");
- writer.writeTag("value", accumValue.get());
- writer.writeTag("unknown_sec", nanSeconds.get());
- writer.closeTag(); // ds
- }
-
- /**
- * Copies object's internal state to another Datasource object.
- *
- * @param other New Datasource object to copy state to
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if supplied argument is not a Datasource object
- */
- public void copyStateTo(final RrdUpdater other) throws IOException, RrdException {
- if (!(other instanceof Datasource)) {
- throw new RrdException("Cannot copy Datasource object to " + other.getClass().getName());
- }
- final Datasource datasource = (Datasource) other;
- if (!datasource.dsName.get().equals(dsName.get())) {
- throw new RrdException("Incomaptible datasource names");
- }
- if (!datasource.dsType.get().equals(dsType.get())) {
- throw new RrdException("Incomaptible datasource types");
- }
- datasource.lastValue.set(lastValue.get());
- datasource.nanSeconds.set(nanSeconds.get());
- datasource.accumValue.set(accumValue.get());
- }
-
- /**
- * Returns index of this Datasource object in the RRD.
- *
- * @return Datasource index in the RRD.
- * @throws IOException Thrown in case of I/O error
- */
- public int getDsIndex() throws IOException {
- try {
- return parentDb.getDsIndex(dsName.get());
- }
- catch (final RrdException e) {
- return -1;
- }
- }
-
- /**
- * Sets datasource heartbeat to a new value.
- *
- * @param heartbeat New heartbeat value
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if invalid (non-positive) heartbeat value is specified.
- */
- public void setHeartbeat(final long heartbeat) throws RrdException, IOException {
- if (heartbeat < 1L) {
- throw new RrdException("Invalid heartbeat specified: " + heartbeat);
- }
- this.heartbeat.set(heartbeat);
- }
-
- /**
- * Sets datasource name to a new value
- *
- * @param newDsName New datasource name
- * @throws RrdException Thrown if invalid data source name is specified (name too long, or
- * name already defined in the RRD
- * @throws IOException Thrown in case of I/O error
- */
- public void setDsName(final String newDsName) throws RrdException, IOException {
- if (newDsName.length() > RrdString.STRING_LENGTH) {
- throw new RrdException("Invalid datasource name specified: " + newDsName);
- }
- if (parentDb.containsDs(newDsName)) {
- throw new RrdException("Datasource already defined in this RRD: " + newDsName);
- }
- dsName.set(newDsName);
- m_primitiveDsName = null;
- }
-
- public void setDsType(final String newDsType) throws RrdException, IOException {
- if (!DsDef.isValidDsType(newDsType)) {
- throw new RrdException("Invalid datasource type: " + newDsType);
- }
- // set datasource type
- this.dsType.set(newDsType);
- m_primitiveDsType = null;
- // reset datasource status
- lastValue.set(Double.NaN);
- accumValue.set(0.0);
- // reset archive status
- final int dsIndex = parentDb.getDsIndex(dsName.get());
- final Archive[] archives = parentDb.getArchives();
- for (final Archive archive : archives) {
- archive.getArcState(dsIndex).setAccumValue(Double.NaN);
- }
- }
-
- /**
- * Sets minimum allowed value for this datasource. If filterArchivedValues
- * argment is set to true, all archived values less then minValue
will
- * be fixed to NaN.
- *
- * @param minValue New minimal value. Specify Double.NaN
if no minimal
- * value should be set
- * @param filterArchivedValues true, if archived datasource values should be fixed;
- * false, otherwise.
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if invalid minValue was supplied (not less then maxValue)
- */
- public void setMinValue(final double minValue, final boolean filterArchivedValues) throws IOException, RrdException {
- final double maxValue = this.maxValue.get();
- if (!Double.isNaN(minValue) && !Double.isNaN(maxValue) && minValue >= maxValue) {
- throw new RrdException("Invalid min/max values: " + minValue + "/" + maxValue);
- }
- this.minValue.set(minValue);
- if (!Double.isNaN(minValue) && filterArchivedValues) {
- final int dsIndex = getDsIndex();
- final Archive[] archives = parentDb.getArchives();
- for (final Archive archive : archives) {
- archive.getRobin(dsIndex).filterValues(minValue, Double.NaN);
- }
- }
- }
-
- /**
- * Sets maximum allowed value for this datasource. If filterArchivedValues
- * argment is set to true, all archived values greater then maxValue
will
- * be fixed to NaN.
- *
- * @param maxValue New maximal value. Specify Double.NaN
if no max
- * value should be set.
- * @param filterArchivedValues true, if archived datasource values should be fixed;
- * false, otherwise.
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if invalid maxValue was supplied (not greater then minValue)
- */
- public void setMaxValue(final double maxValue, final boolean filterArchivedValues) throws IOException, RrdException {
- final double minValue = this.minValue.get();
- if (!Double.isNaN(minValue) && !Double.isNaN(maxValue) && minValue >= maxValue) {
- throw new RrdException("Invalid min/max values: " + minValue + "/" + maxValue);
- }
- this.maxValue.set(maxValue);
- if (!Double.isNaN(maxValue) && filterArchivedValues) {
- final int dsIndex = getDsIndex();
- final Archive[] archives = parentDb.getArchives();
- for (final Archive archive : archives) {
- archive.getRobin(dsIndex).filterValues(Double.NaN, maxValue);
- }
- }
- }
-
- /**
- * Sets min/max values allowed for this datasource. If filterArchivedValues
- * argment is set to true, all archived values less then minValue
or
- * greater then maxValue
will be fixed to NaN.
- *
- * @param minValue New minimal value. Specify Double.NaN
if no min
- * value should be set.
- * @param maxValue New maximal value. Specify Double.NaN
if no max
- * value should be set.
- * @param filterArchivedValues true, if archived datasource values should be fixed;
- * false, otherwise.
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if invalid min/max values were supplied
- */
- public void setMinMaxValue(final double minValue, final double maxValue, final boolean filterArchivedValues) throws IOException, RrdException {
- if (!Double.isNaN(minValue) && !Double.isNaN(maxValue) && minValue >= maxValue) {
- throw new RrdException("Invalid min/max values: " + minValue + "/" + maxValue);
- }
- this.minValue.set(minValue);
- this.maxValue.set(maxValue);
- if (!(Double.isNaN(minValue) && Double.isNaN(maxValue)) && filterArchivedValues) {
- final int dsIndex = getDsIndex();
- final Archive[] archives = parentDb.getArchives();
- for (final Archive archive : archives) {
- archive.getRobin(dsIndex).filterValues(minValue, maxValue);
- }
- }
- }
-
- /**
- * Returns the underlying storage (backend) object which actually performs all
- * I/O operations.
- *
- * @return I/O backend object
- */
- public RrdBackend getRrdBackend() {
- return parentDb.getRrdBackend();
- }
-
- /**
- * Required to implement RrdUpdater interface. You should never call this method directly.
- *
- * @return Allocator object
- */
- public RrdAllocator getRrdAllocator() {
- return parentDb.getRrdAllocator();
- }
-
- public String toString() {
- return getClass().getName() + "@" + Integer.toHexString(hashCode()) + "[parentDb=" + parentDb
- + ",dsName=" + dsName + ",dsType=" + dsType + ",heartbeat=" + heartbeat
- + ",minValue=" + minValue + ",maxValue=" + maxValue + "]";
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/DsDef.java b/apps/jrobin/java/src/org/jrobin/core/DsDef.java
deleted file mode 100644
index 362c9d373e..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/DsDef.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-/**
- * Class to represent single data source definition within the RRD.
- * Datasource definition consists of the following five elements:
- *
- *
- * For the complete explanation of all source definition parameters, see RRDTool's - * rrdcreate man page. - * - * @author Sasa Markovic - */ -public class DsDef implements DsTypes { - /** - * array of valid source types - */ - public static final String[] DS_TYPES = {DT_GAUGE, DT_COUNTER, DT_DERIVE, DT_ABSOLUTE}; - static final String FORCE_ZEROS_FOR_NANS_SUFFIX = "!"; - - private String dsName, dsType; - private long heartbeat; - private double minValue, maxValue; - - /** - * Creates new data source definition object. This object should be passed as argument - * to {@link RrdDef#addDatasource(DsDef) addDatasource()} - * method of {@link RrdDb RrdDb} object. - *
- * For the complete explanation of all source definition parameters, see RRDTool's - * rrdcreate man page. - *
- * IMPORTANT NOTE: If datasource name ends with '!', corresponding archives will never
- * store NaNs as datasource values. In that case, NaN datasource values will be silently
- * replaced with zeros by the framework.
- *
- * @param dsName Data source name.
- * @param dsType Data source type. Valid values are "COUNTER", "GAUGE", "DERIVE"
- * and "ABSOLUTE" (these string constants are conveniently defined in the
- * {@link DsTypes} class).
- * @param heartbeat Hearbeat
- * @param minValue Minimal value. Use Double.NaN
if unknown.
- * @param maxValue Maximal value. Use Double.NaN
if unknown.
- * @throws RrdException Thrown if any parameter has illegal value.
- */
- public DsDef(final String dsName, final String dsType, final long heartbeat, final double minValue, final double maxValue) throws RrdException {
- this.dsName = dsName;
- this.dsType = dsType;
- this.heartbeat = heartbeat;
- this.minValue = minValue;
- this.maxValue = maxValue;
- validate();
- }
-
- /**
- * Returns data source name.
- *
- * @return Data source name.
- */
- public String getDsName() {
- return dsName;
- }
-
- /**
- * Returns source type.
- *
- * @return Source type ("COUNTER", "GAUGE", "DERIVE" or "ABSOLUTE").
- */
- public String getDsType() {
- return dsType;
- }
-
- /**
- * Returns source heartbeat.
- *
- * @return Source heartbeat.
- */
- public long getHeartbeat() {
- return heartbeat;
- }
-
- /**
- * Returns minimal calculated source value.
- *
- * @return Minimal value.
- */
- public double getMinValue() {
- return minValue;
- }
-
- /**
- * Returns maximal calculated source value.
- *
- * @return Maximal value.
- */
- public double getMaxValue() {
- return maxValue;
- }
-
- private void validate() throws RrdException {
- if (dsName == null) {
- throw new RrdException("Null datasource name specified");
- }
- if (dsName.length() == 0) {
- throw new RrdException("Datasource name length equal to zero");
- }
- if (dsName.length() > RrdPrimitive.STRING_LENGTH) {
- throw new RrdException("Datasource name [" + dsName + "] to long (" +
- dsName.length() + " chars found, only " + RrdPrimitive.STRING_LENGTH + " allowed");
- }
- if (!isValidDsType(dsType)) {
- throw new RrdException("Invalid datasource type specified: " + dsType);
- }
- if (heartbeat <= 0) {
- throw new RrdException("Invalid heartbeat, must be positive: " + heartbeat);
- }
- if (!Double.isNaN(minValue) && !Double.isNaN(maxValue) && minValue >= maxValue) {
- throw new RrdException("Invalid min/max values specified: " +
- minValue + "/" + maxValue);
- }
- }
-
- /**
- * Checks if function argument represents valid source type.
- *
- * @param dsType Source type to be checked.
- * @return true
if dsType
is valid type,
- * false
otherwise.
- */
- public static boolean isValidDsType(final String dsType) {
- for (final String type : DS_TYPES) {
- if (type.equals(dsType)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns string representing source definition (RRDTool format).
- *
- * @return String containing all data source definition parameters.
- */
- public String dump() {
- return "DS:" + dsName + ":" + dsType + ":" + heartbeat +
- ":" + Util.formatDouble(minValue, "U", false) +
- ":" + Util.formatDouble(maxValue, "U", false);
- }
-
- /**
- * Checks if two datasource definitions are equal.
- * Source definitions are treated as equal if they have the same source name.
- * It is not possible to create RRD with two equal archive definitions.
- *
- * @param obj Archive definition to compare with.
- * @return true
if archive definitions are equal,
- * false
otherwise.
- */
- public boolean equals(final Object obj) {
- if (obj instanceof DsDef) {
- final DsDef dsObj = (DsDef) obj;
- return dsName.equals(dsObj.dsName);
- }
- return false;
- }
-
- public int hashCode() {
- return dsName.hashCode() * 47;
- }
-
- boolean exactlyEqual(final DsDef def) {
- return dsName.equals(def.dsName) && dsType.equals(def.dsType) &&
- heartbeat == def.heartbeat && Util.equal(minValue, def.minValue) &&
- Util.equal(maxValue, def.maxValue);
- }
-
- public String toString() {
- return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()) + "[" + dump() + "]";
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/DsTypes.java b/apps/jrobin/java/src/org/jrobin/core/DsTypes.java
deleted file mode 100644
index 31330b043c..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/DsTypes.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core;
-
-/**
- * Simple interface to represent available datasource types.
- */
-public interface DsTypes {
- /**
- * Constant to represent GAUGE datasource type
- */
- public static final String DT_GAUGE = "GAUGE";
-
- /**
- * Constant to represent COUNTER datasource type
- */
- public static final String DT_COUNTER = "COUNTER";
-
- /**
- * Constant to represent DERIVE datasource type
- */
- public static final String DT_DERIVE = "DERIVE";
-
- /**
- * Constant to represent ABSOLUTE datasource type
- */
- public static final String DT_ABSOLUTE = "ABSOLUTE";
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/FetchData.java b/apps/jrobin/java/src/org/jrobin/core/FetchData.java
deleted file mode 100644
index cc57a87a42..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/FetchData.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 FetchRequest#fetchData() fetchData()} is
- * called on a {@link FetchRequest FetchRequest} object.
- *
- * 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). - *
- * 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. - *
- * 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.
- */
-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 x
and y
- * in this FetchData and you want to calculate values for (x+y)/2
use something like:
- *
- * getRpnValues("x,y,+,2,/");
- *
- * @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.
- *
- * @return String containing the contents of this object, 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 (String dsName : dsNames) {
- buff.append(padWithBlanks(dsName, 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:
- *
- * getAggregate("foots", "MAX", "foots,0.3048,*");
- *
- * @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 x
and y
- * in this FetchData and you want to calculate MAX value of (x+y)/2
use something like:
- *
- * getRpnAggregate("x,y,+,2,/", "MAX");
- *
- * @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 x
and y
- * in this FetchData and you want to calculate MIN, MAX, LAST, FIRST, AVERAGE and TOTAL value
- * of (x+y)/2
use something like:
- *
- * getRpnAggregates("x,y,+,2,/");
- *
- * @param rpnExpression RRDTool-like RPN expression
- * @return Object containing all aggregated values
- * @throws RrdException Thrown if invalid RPN expression is supplied
- * @throws IOException Thrown in case of I/O error
- */
- 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.
- *
- * 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. - *
- * Read more about this topic at:
- * Rednet or
- * Bytemark.
- *
- * @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 (String dsName : dsNames) {
- writer.writeTag("name", dsName);
- }
- 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 (String dsName : dsNames) {
- dataProcessor.addDatasource(dsName, 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;
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/FetchRequest.java b/apps/jrobin/java/src/org/jrobin/core/FetchRequest.java
deleted file mode 100644
index 5722acd975..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/FetchRequest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.IOException;
-import java.util.Set;
-
-/**
- * Class to represent fetch request. For the complete explanation of all
- * fetch parameters consult RRDTool's
- * rrdfetch man page.
- *
- * You cannot create
- * Normally, you don't need to manipulate the Header object directly - JRobin framework
- * does it for you.
- *
- * @author Sasa Markovic*
- */
-public class Header implements RrdUpdater {
- static final int SIGNATURE_LENGTH = 2;
- static final String SIGNATURE = "JR";
-
- static final String DEFAULT_SIGNATURE = "JRobin, version 0.1";
- static final String RRDTOOL_VERSION = "0001";
-
- private RrdDb parentDb;
-
- private RrdString signature;
- private RrdLong step;
- private RrdInt dsCount, arcCount;
- private RrdLong lastUpdateTime;
- private Long m_primitiveStep = null;
- private Integer m_primitiveDsCount = null;
- private Integer m_primitiveArcCount = null;
-
- Header(final RrdDb parentDb, final RrdDef rrdDef) throws IOException {
- final boolean shouldInitialize = rrdDef != null;
- this.parentDb = parentDb;
- signature = new RrdString(this); // NOT constant, may NOT be cached
- step = new RrdLong(this, true); // constant, may be cached
- dsCount = new RrdInt(this, true); // constant, may be cached
- arcCount = new RrdInt(this, true); // constant, may be cached
- lastUpdateTime = new RrdLong(this);
- if (shouldInitialize) {
- signature.set(DEFAULT_SIGNATURE);
- step.set(rrdDef.getStep());
- dsCount.set(rrdDef.getDsCount());
- arcCount.set(rrdDef.getArcCount());
- lastUpdateTime.set(rrdDef.getStartTime());
- }
- }
-
- Header(final RrdDb parentDb, final DataImporter reader) throws IOException, RrdException {
- this(parentDb, (RrdDef) null);
- final String version = reader.getVersion();
- final int intVersion = Integer.parseInt(version);
- if (intVersion > 3) {
- throw new RrdException("Could not unserialize xml version " + version);
- }
- signature.set(DEFAULT_SIGNATURE);
- step.set(reader.getStep());
- dsCount.set(reader.getDsCount());
- arcCount.set(reader.getArcCount());
- lastUpdateTime.set(reader.getLastUpdateTime());
- }
-
- /**
- * Returns RRD signature. Initially, the returned string will be
- * of the form JRobin, version x.x. Note: RRD format did not
- * change since Jrobin 1.0.0 release (and probably never will).
- *
- * @return RRD signature
- * @throws IOException Thrown in case of I/O error
- */
- public String getSignature() throws IOException {
- return signature.get();
- }
-
- public String getInfo() throws IOException {
- return getSignature().substring(SIGNATURE_LENGTH);
- }
-
- public void setInfo(String info) throws IOException {
- if (info != null && info.length() > 0) {
- signature.set(SIGNATURE + info);
- }
- else {
- signature.set(SIGNATURE);
- }
- }
-
- /**
- * Returns the last update time of the RRD.
- *
- * @return Timestamp (Unix epoch, no milliseconds) corresponding to the last update time.
- * @throws IOException Thrown in case of I/O error
- */
- public long getLastUpdateTime() throws IOException {
- return lastUpdateTime.get();
- }
-
- /**
- * Returns primary RRD time step.
- *
- * @return Primary time step in seconds
- * @throws IOException Thrown in case of I/O error
- */
- public long getStep() throws IOException {
- if (m_primitiveStep == null) {
- m_primitiveStep = step.get();
- }
- return m_primitiveStep;
- }
-
- /**
- * Returns the number of datasources defined in the RRD.
- *
- * @return Number of datasources defined
- * @throws IOException Thrown in case of I/O error
- */
- public int getDsCount() throws IOException {
- if (m_primitiveDsCount == null) {
- m_primitiveDsCount = dsCount.get();
- }
- return m_primitiveDsCount;
- }
-
- /**
- * Returns the number of archives defined in the RRD.
- *
- * @return Number of archives defined
- * @throws IOException Thrown in case of I/O error
- */
- public int getArcCount() throws IOException {
- if (m_primitiveArcCount == null) {
- m_primitiveArcCount = arcCount.get();
- }
- return m_primitiveArcCount;
- }
-
- public void setLastUpdateTime(final long lastUpdateTime) throws IOException {
- this.lastUpdateTime.set(lastUpdateTime);
- }
-
- String dump() throws IOException {
- return "== HEADER ==\n" +
- "signature:" + getSignature() +
- " lastUpdateTime:" + getLastUpdateTime() +
- " step:" + getStep() +
- " dsCount:" + getDsCount() +
- " arcCount:" + getArcCount() + "\n";
- }
-
- void appendXml(XmlWriter writer) throws IOException {
- writer.writeComment(signature.get());
- writer.writeTag("version", RRDTOOL_VERSION);
- writer.writeComment("Seconds");
- writer.writeTag("step", step.get());
- writer.writeComment(Util.getDate(lastUpdateTime.get()));
- writer.writeTag("lastupdate", lastUpdateTime.get());
- }
-
- /**
- * Copies object's internal state to another Header object.
- *
- * @param other New Header object to copy state to
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if supplied argument is not a Header object
- */
- public void copyStateTo(final RrdUpdater other) throws IOException, RrdException {
- if (!(other instanceof Header)) {
- throw new RrdException( "Cannot copy Header object to " + other.getClass().getName());
- }
- final Header header = (Header) other;
- header.signature.set(signature.get());
- header.lastUpdateTime.set(lastUpdateTime.get());
- }
-
- /**
- * Returns the underlying storage (backend) object which actually performs all
- * I/O operations.
- *
- * @return I/O backend object
- */
- public RrdBackend getRrdBackend() {
- return parentDb.getRrdBackend();
- }
-
- boolean isJRobinHeader() throws IOException {
- return signature.get().startsWith(SIGNATURE);
- }
-
- void validateHeader() throws IOException, RrdException {
- if (!isJRobinHeader()) {
- throw new RrdException("Invalid file header. File [" + parentDb.getCanonicalPath() + "] is not a JRobin RRD file");
- }
- }
-
- /**
- * Required to implement RrdUpdater interface. You should never call this method directly.
- *
- * @return Allocator object
- */
- public RrdAllocator getRrdAllocator() {
- return parentDb.getRrdAllocator();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/Robin.java b/apps/jrobin/java/src/org/jrobin/core/Robin.java
deleted file mode 100644
index 623bc80a94..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/Robin.java
+++ /dev/null
@@ -1,266 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.IOException;
-
-/**
- * Class to represent archive values for a single datasource. Robin class is the heart of
- * the so-called "round robin database" concept. Basically, each Robin object is a
- * fixed length array of double values. Each double value reperesents consolidated, archived
- * value for the specific timestamp. When the underlying array of double values gets completely
- * filled, new values will replace the oldest ones.
- *
- * Robin object does not hold values in memory - such object could be quite large.
- * Instead of it, Robin reads them from the backend I/O only when necessary.
- *
- * @author Sasa Markovic
- */
-public class Robin implements RrdUpdater {
- private Archive parentArc;
- private RrdInt pointer;
- private RrdDoubleArray values;
- private int rows;
-
- Robin(Archive parentArc, int rows, boolean shouldInitialize) throws IOException {
- this.parentArc = parentArc;
- this.pointer = new RrdInt(this);
- this.values = new RrdDoubleArray(this, rows);
- this.rows = rows;
- if (shouldInitialize) {
- pointer.set(0);
- values.set(0, Double.NaN, rows);
- }
- }
-
- /**
- * Fetches all archived values.
- *
- * @return Array of double archive values, starting from the oldest one.
- * @throws IOException Thrown in case of I/O specific error.
- */
- public double[] getValues() throws IOException {
- return getValues(0, rows);
- }
-
- // stores single value
- void store(double newValue) throws IOException {
- int position = pointer.get();
- values.set(position, newValue);
- pointer.set((position + 1) % rows);
- }
-
- // stores the same value several times
- void bulkStore(double newValue, int bulkCount) throws IOException {
- assert bulkCount <= rows: "Invalid number of bulk updates: " + bulkCount +
- " rows=" + rows;
- int position = pointer.get();
- // update tail
- int tailUpdateCount = Math.min(rows - position, bulkCount);
- values.set(position, newValue, tailUpdateCount);
- pointer.set((position + tailUpdateCount) % rows);
- // do we need to update from the start?
- int headUpdateCount = bulkCount - tailUpdateCount;
- if (headUpdateCount > 0) {
- values.set(0, newValue, headUpdateCount);
- pointer.set(headUpdateCount);
- }
- }
-
- void update(double[] newValues) throws IOException {
- assert rows == newValues.length: "Invalid number of robin values supplied (" + newValues.length +
- "), exactly " + rows + " needed";
- pointer.set(0);
- values.writeDouble(0, newValues);
- }
-
- /**
- * Updates archived values in bulk.
- *
- * @param newValues Array of double values to be stored in the archive
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if the length of the input array is different from the length of
- * this archive
- */
- public void setValues(double[] newValues) throws IOException, RrdException {
- if (rows != newValues.length) {
- throw new RrdException("Invalid number of robin values supplied (" + newValues.length +
- "), exactly " + rows + " needed");
- }
- update(newValues);
- }
-
- /**
- * (Re)sets all values in this archive to the same value.
- *
- * @param newValue New value
- * @throws IOException Thrown in case of I/O error
- */
- public void setValues(double newValue) throws IOException {
- double[] values = new double[rows];
- for (int i = 0; i < values.length; i++) {
- values[i] = newValue;
- }
- update(values);
- }
-
- String dump() throws IOException {
- StringBuffer buffer = new StringBuffer("Robin " + pointer.get() + "/" + rows + ": ");
- double[] values = getValues();
- for (double value : values) {
- buffer.append(Util.formatDouble(value, true)).append(" ");
- }
- buffer.append("\n");
- return buffer.toString();
- }
-
- /**
- * Returns the i-th value from the Robin archive.
- *
- * @param index Value index
- * @return Value stored in the i-th position (the oldest value has zero index)
- * @throws IOException Thrown in case of I/O specific error.
- */
- public double getValue(int index) throws IOException {
- int arrayIndex = (pointer.get() + index) % rows;
- return values.get(arrayIndex);
- }
-
- /**
- * Sets the i-th value in the Robin archive.
- *
- * @param index index in the archive (the oldest value has zero index)
- * @param value value to be stored
- * @throws IOException Thrown in case of I/O specific error.
- */
- public void setValue(int index, double value) throws IOException {
- int arrayIndex = (pointer.get() + index) % rows;
- values.set(arrayIndex, value);
- }
-
- double[] getValues(int index, int count) throws IOException {
- assert count <= rows: "Too many values requested: " + count + " rows=" + rows;
- int startIndex = (pointer.get() + index) % rows;
- int tailReadCount = Math.min(rows - startIndex, count);
- double[] tailValues = values.get(startIndex, tailReadCount);
- if (tailReadCount < count) {
- int headReadCount = count - tailReadCount;
- double[] headValues = values.get(0, headReadCount);
- double[] values = new double[count];
- int k = 0;
- for (double tailValue : tailValues) {
- values[k++] = tailValue;
- }
- for (double headValue : headValues) {
- values[k++] = headValue;
- }
- return values;
- }
- else {
- return tailValues;
- }
- }
-
- /**
- * Returns the Archive object to which this Robin object belongs.
- *
- * @return Parent Archive object
- */
- public Archive getParent() {
- return parentArc;
- }
-
- /**
- * Returns the size of the underlying array of archived values.
- *
- * @return Number of stored values
- */
- public int getSize() {
- return rows;
- }
-
- /**
- * Copies object's internal state to another Robin object.
- *
- * @param other New Robin object to copy state to
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if supplied argument is not a Robin object
- */
- public void copyStateTo(RrdUpdater other) throws IOException, RrdException {
- if (!(other instanceof Robin)) {
- throw new RrdException(
- "Cannot copy Robin object to " + other.getClass().getName());
- }
- Robin robin = (Robin) other;
- int rowsDiff = rows - robin.rows;
- if (rowsDiff == 0) {
- // Identical dimensions. Do copy in BULK to speed things up
- robin.pointer.set(pointer.get());
- robin.values.writeBytes(values.readBytes());
- }
- else {
- // different sizes
- for (int i = 0; i < robin.rows; i++) {
- int j = i + rowsDiff;
- robin.store(j >= 0 ? getValue(j) : Double.NaN);
- }
- }
- }
-
- /**
- * Filters values stored in this archive based on the given boundary.
- * Archived values found to be outside of
- *
- *
- *
- * To create your own backend in order to provide some custom type of RRD storage,
- * you should do the following:
- *
- *
- *
- *
- * Factory classes are used to create concrete {@link RrdBackend} implementations.
- * Each factory creates unlimited number of specific backend objects.
- *
- * JRobin supports four different backend types (backend factories) out of the box:
- *
- *
- *
- *
- * Each backend factory is identifed by its {@link #getFactoryName() name}. Constructors
- * are provided in the {@link RrdDb} class to create RrdDb objects (RRD databases)
- * backed with a specific backend.
- *
- * See javadoc for {@link RrdBackend} to find out how to create your custom backends.
- */
-public abstract class RrdBackendFactory {
- private static final HashMap
- *
- *
- * @param factoryName Name of the default factory. Out of the box, JRobin supports four
- * different RRD backends: "FILE" (java.io.* based), "SAFE" (java.io.* based - use this
- * backend if RRD files may be accessed from several JVMs at the same time),
- * "NIO" (java.nio.* based) and "MEMORY" (byte[] based).
- * @throws RrdException Thrown if invalid factory name is supplied or not called before
- * the first RRD is created.
- */
- public static void setDefaultFactory(final String factoryName) throws RrdException {
- // We will allow this only if no RRDs are created
- if (!RrdBackend.isInstanceCreated()) {
- defaultFactory = getFactory(factoryName);
- }
- else {
- throw new RrdException("Could not change the default backend factory. This method must be called before the first RRD gets created");
- }
- }
-
- /**
- * Whether or not the RRD backend has created an instance yet.
- *
- * @return True if the backend instance is created, false if not.
- */
- public static boolean isInstanceCreated() {
- return RrdBackend.isInstanceCreated();
- }
-
- /**
- * Creates RrdBackend object for the given storage path.
- *
- * @param path Storage path
- * @param readOnly True, if the storage should be accessed in read/only mode.
- * False otherwise.
- * @return Backend object which handles all I/O operations for the given storage path
- * @throws IOException Thrown in case of I/O error.
- */
- protected abstract RrdBackend open(String path, boolean readOnly) throws IOException;
-
- /**
- * Method to determine if a storage with the given path already exists.
- *
- * @param path Storage path
- * @return True, if such storage exists, false otherwise.
- * @throws IOException Thrown in case of I/O error.
- */
- protected abstract boolean exists(String path) throws IOException;
-
- /**
- * Returns the name (primary ID) for the factory.
- *
- * @return Name of the factory.
- */
- public abstract String getFactoryName();
-
- public String toString() {
- return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()) + "[name=" + getFactoryName() + "]";
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdDb.java b/apps/jrobin/java/src/org/jrobin/core/RrdDb.java
deleted file mode 100644
index 64544dc77e..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdDb.java
+++ /dev/null
@@ -1,1166 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Date;
-
-/**
- * Main class used to create and manipulate round robin databases (RRDs). Use this class to perform
- * update and fetch operations on exisiting RRDs, to create new RRD from
- * the definition (object of class {@link org.jrobin.core.RrdDef RrdDef}) or
- * from XML file (dumped content of RRDTool's or JRobin's RRD file).
- *
- * Each RRD is backed with some kind of storage. For example, RRDTool supports only one kind of
- * storage (disk file). On the contrary, JRobin gives you freedom to use other storage (backend) types
- * even to create your own backend types for some special purposes. JRobin by default stores
- * RRD data in files (as RRDTool), but you might choose to store RRD data in memory (this is
- * supported in JRobin), to use java.nio.* instead of java.io.* package for file manipulation
- * (also supported) or to store whole RRDs in the SQL database
- * (you'll have to extend some classes to do this).
- *
- * Note that JRobin uses binary format different from RRDTool's format. You cannot
- * use this class to manipulate RRD files created with RRDTool. However, if you perform
- * the same sequence of create, update and fetch operations, you will get exactly the same
- * results from JRobin and RRDTool.
- *
- * You will not be able to use JRobin API if you are not familiar with
- * basic RRDTool concepts. Good place to start is the
- * official RRD tutorial
- * and relevant RRDTool man pages: rrdcreate,
- * rrdupdate,
- * rrdfetch and
- * rrdgraph.
- * For RRDTool's advanced graphing capabilities (RPN extensions), also supported in JRobin,
- * there is an excellent
- * CDEF tutorial.
- *
- *
- * @see RrdBackend
- * @see RrdBackendFactory
- */
-public class RrdDb implements RrdUpdater {
- /**
- * prefix to identify external XML file source used in various RrdDb constructors
- */
- public static final String PREFIX_XML = "xml:/";
- /**
- * prefix to identify external RRDTool file source used in various RrdDb constructors
- */
- public static final String PREFIX_RRDTool = "rrdtool:/";
-
- // static final String RRDTOOL = "rrdtool";
- static final int XML_INITIAL_BUFFER_CAPACITY = 100000; // bytes
-
- private RrdBackend backend;
- private RrdAllocator allocator = new RrdAllocator();
-
- private Header header;
- private Datasource[] datasources;
- private Archive[] archives;
-
- private boolean closed = false;
-
- /**
- * Constructor used to create new RRD object from the definition. This RRD object will be backed
- * with a storage (backend) of the default type. Initially, storage type defaults to "NIO"
- * (RRD bytes will be put in a file on the disk). Default storage type can be changed with a static
- * {@link RrdBackendFactory#setDefaultFactory(String)} method call.
- *
- * New RRD file structure is specified with an object of class
- * {@link org.jrobin.core.RrdDef RrdDef}. The underlying RRD storage is created as soon
- * as the constructor returns.
- *
- * Typical scenario:
- *
- *
- * JRobin uses factories to create RRD backend objecs. There are three different
- * backend factories supplied with JRobin, and each factory has its unique name:
- *
- *
- * For example, to create RRD in memory, use the following code:
- *
- * New RRD file structure is specified with an object of class
- * {@link org.jrobin.core.RrdDef RrdDef}. The underlying RRD storage is created as soon
- * as the constructor returns.
- *
- * @param rrdDef RRD definition object
- * @param factory The factory which will be used to create storage for this RRD
- * @throws RrdException Thrown if invalid factory or definition is supplied
- * @throws IOException Thrown in case of I/O error
- * @see RrdBackendFactory
- */
- public RrdDb(RrdDef rrdDef, RrdBackendFactory factory) throws RrdException, IOException {
- rrdDef.validate();
- String path = rrdDef.getPath();
- backend = factory.open(path, false);
- try {
- backend.setLength(rrdDef.getEstimatedSize());
- // create header
- header = new Header(this, rrdDef);
- // create datasources
- DsDef[] dsDefs = rrdDef.getDsDefs();
- datasources = new Datasource[dsDefs.length];
- for (int i = 0; i < dsDefs.length; i++) {
- datasources[i] = new Datasource(this, dsDefs[i]);
- }
- // create archives
- ArcDef[] arcDefs = rrdDef.getArcDefs();
- archives = new Archive[arcDefs.length];
- for (int i = 0; i < arcDefs.length; i++) {
- archives[i] = new Archive(this, arcDefs[i]);
- }
- }
- catch (IOException e) {
- backend.close();
- throw e;
- }
- }
-
- /**
- * Constructor used to open already existing RRD. This RRD object will be backed
- * with a storage (backend) of the default type (file on the disk). Constructor
- * obtains read or read/write access to this RRD.
- *
- * @param path Path to existing RRD.
- * @param readOnly Should be set to Constructor used to open already existing RRD in R/W mode, with a default storage
- * (backend) type (file on the disk).
- *
- * @param path Path to existing RRD.
- * @throws IOException Thrown in case of I/O error.
- * @throws RrdException Thrown in case of JRobin specific error.
- */
- public RrdDb(String path) throws IOException, RrdException {
- this(path, false);
- }
-
- /**
- * Constructor used to open already existing RRD in R/W mode with a storage (backend) type
- * different from default.
- *
- * Newly created RRD will be backed with a default storage (backend) type
- * (file on the disk).
- *
- * JRobin and RRDTool use the same format for XML dump and this constructor should be used to
- * (re)create JRobin RRD files from XML dumps. First, dump the content of a RRDTool
- * RRD file (use command line):
- *
- *
- * Than, use the file
- *
- * or:
- *
- *
- * See documentation for {@link #dumpXml(java.lang.String) dumpXml()} method
- * to see how to convert JRobin files to RRDTool's format.
- *
- * To read RRDTool files directly, specify
- *
- * Note that the prefix
- *
- * JRobin and RRDTool use the same format for XML dump and this constructor should be used to
- * (re)create JRobin RRD files from XML dumps. First, dump the content of a RRDTool
- * RRD file (use command line):
- *
- *
- * Than, use the file
- *
- * or:
- *
- *
- * See documentation for {@link #dumpXml(java.lang.String) dumpXml()} method
- * to see how to convert JRobin files to RRDTool's format.
- *
- * To read RRDTool files directly, specify
- *
- * Note that the prefix
- * Once populated with data source values, call Sample's
- * {@link org.jrobin.core.Sample#update() update()} method to actually
- * store sample in the RRD associated with it.
- *
- * @param time Sample timestamp rounded to the nearest second (without milliseconds).
- * @return Fresh sample with the given timestamp and all data source values set to 'unknown'.
- * @throws IOException Thrown in case of I/O error.
- */
- public Sample createSample(long time) throws IOException {
- return new Sample(this, time);
- }
-
- /**
- * Creates new sample with the current timestamp and all data source values set to
- * 'unknown'. Use returned
- * Once populated with data source values, call Sample's
- * {@link org.jrobin.core.Sample#update() update()} method to actually
- * store sample in the RRD associated with it.
- *
- * @return Fresh sample with the current timestamp and all
- * data source values set to 'unknown'.
- * @throws IOException Thrown in case of I/O error.
- */
- public Sample createSample() throws IOException {
- return createSample(Util.getTime());
- }
-
- /**
- * Prepares fetch request to be executed on this RRD. Use returned
- * Prepares fetch request to be executed on this RRD. Use returned
- * Returns string representing complete internal RRD state. The returned
- * string can be printed to Returns internal index number for the given datasource name. This index is heavily
- * used by jrobin.graph package and has no value outside of it.
- * Suppose that you have a JRobin RRD file
- *
- * Use
- *
- * Example:
- *
- *
- *
- * @param factoryName Name of the backend factory to be set as default.
- * @throws RrdException Thrown if invalid factory name is supplied, or not called
- * before the first backend object (before the first RrdDb object) is created.
- */
- public static void setDefaultFactory(String factoryName) throws RrdException {
- RrdBackendFactory.setDefaultFactory(factoryName);
- }
-
- /**
- * Returns an array of last datasource values. The first value in the array corresponds
- * to the first datasource defined in the RrdDb and so on.
- *
- * @return Array of last datasource values
- * @throws IOException Thrown in case of I/O error
- */
- public synchronized double[] getLastDatasourceValues() throws IOException {
- double[] values = new double[datasources.length];
- for (int i = 0; i < values.length; i++) {
- values[i] = datasources[i].getLastValue();
- }
- return values;
- }
-
- /**
- * Returns the last stored value for the given datasource.
- *
- * @param dsName Datasource name
- * @return Last stored value for the given datasource
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if no datasource in this RrdDb matches the given datasource name
- */
- public synchronized double getLastDatasourceValue(String dsName) throws IOException, RrdException {
- int dsIndex = getDsIndex(dsName);
- return datasources[dsIndex].getLastValue();
- }
-
- /**
- * Returns the number of datasources defined in the file
- *
- * @return The number of datasources defined in the file
- */
- public int getDsCount() {
- return datasources.length;
- }
-
- /**
- * Returns the number of RRA arcihves defined in the file
- *
- * @return The number of RRA arcihves defined in the file
- */
- public int getArcCount() {
- return archives.length;
- }
-
- /**
- * Returns the last time when some of the archives in this RRD was updated. This time is not the
- * same as the {@link #getLastUpdateTime()} since RRD file can be updated without updating any of
- * the archives.
- *
- * @return last time when some of the archives in this RRD was updated
- * @throws IOException Thrown in case of I/O error
- */
- public long getLastArchiveUpdateTime() throws IOException {
- long last = 0;
- for (Archive archive : archives) {
- last = Math.max(last, archive.getEndTime());
- }
- return last;
- }
-
- public synchronized String getInfo() throws IOException {
- return header.getInfo();
- }
-
- public synchronized void setInfo(String info) throws IOException {
- header.setInfo(info);
- }
-
- public static void main(String[] args) {
- System.out.println("JRobin Java Library :: RRDTool choice for the Java world");
- System.out.println("==================================================================");
- System.out.println("JRobin base directory: " + Util.getJRobinHomeDirectory());
- long time = Util.getTime();
- System.out.println("Current timestamp: " + time + ": " + new Date(time * 1000L));
- System.out.println("------------------------------------------------------------------");
- System.out.println("For the latest information visit: http://www.jrobin.org");
- System.out.println("(C) 2003-2005 Sasa Markovic. All rights reserved.");
- }
-
- public String toString() {
- return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()) + "[" + new File(getPath()).getName() + "]";
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdDbPool.java b/apps/jrobin/java/src/org/jrobin/core/RrdDbPool.java
deleted file mode 100644
index 3be890f3ea..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdDbPool.java
+++ /dev/null
@@ -1,932 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.IOException;
-import java.util.HashMap;
-
-import org.jrobin.core.RrdException;
-
-/**
- * This class should be used to synchronize access to RRD files
- * in a multithreaded environment. This class should be also used to prevent openning of
- * too many RRD files at the same time (thus avoiding operating system limits)
- */
-
-public class RrdDbPool {
- /**
- * Initial capacity of the pool i.e. maximum number of simultaneously open RRD files. The pool will
- * never open too many RRD files at the same time.
- */
- public static final int INITIAL_CAPACITY = 200;
- private static RrdDbPool instance;
-
- private int capacity = INITIAL_CAPACITY;
- private HashMap
- *
- *
- *
-// *
-// * To open already existing RRD file with JRobin, you have to create a
-// * {@link org.jrobin.core.RrdDb RrdDb} object by specifying RRD file path
-// * as constructor argument. This operation can be time consuming
-// * especially with large RRD files with many datasources and
-// * several long archives.
-// *
-// * In a multithreaded environment you might probably need a reference to the
-// * same RRD file from two different threads (RRD file updates are performed in
-// * one thread but data fetching and graphing is performed in another one). To make
-// * the RrdDb construction process more efficient it might be convenient to open all
-// * RRD files in a centralized place. That's the purpose of RrdDbPool class.
-// *
-// * How does it work? The typical usage scenario goes like this:
-// *
-// *
-// *
-// * When the reference count drops to zero, RrdDbPool will not close the underlying
-// * RRD file immediatelly. Instead of it, it will be marked as 'eligible for closing'.
-// * If someone request the same RRD file again (before it gets closed), the same
-// * reference will be returned again.
-// *
-// * RrdDbPool has a 'garbage collector' which runs in a separate, low-priority
-// * thread and gets activated only when the number of RRD files kept in the
-// * pool is too big (greater than number returned from {@link #getCapacity getCapacity()}).
-// * Only RRD files with a reference count equal to zero
-// * will be eligible for closing. Unreleased RrdDb references are never invalidated.
-// * RrdDbPool object keeps track of the time when each RRD file
-// * becomes eligible for closing so that the oldest RRD file gets closed first.
-// *
-// * Initial RrdDbPool capacity is set to {@link #INITIAL_CAPACITY}. Use {@link #setCapacity(int)}
-// * method to change it at any time.
-// *
-// * WARNING:Never use close() method on the reference returned from the pool.
-// * When the reference is no longer needed, return it to the pool with the
-// * {@link #release(RrdDb) release()} method.
-// *
-// * However, you are not forced to use RrdDbPool methods to obtain RrdDb references
-// * to RRD files, 'ordinary' RrdDb constructors are still available. But RrdDbPool class
-// * offers serious performance improvement especially in complex applications with many
-// * threads and many simultaneously open RRD files.
-// *
-// * The pool is thread-safe. Not that the {@link RrdDb} objects returned from the pool are
-// * also thread-safe
-// *
-// * You should know that each operating system has its own internal limit on the number
-// * of simultaneously open files. The capacity of your RrdDbPool should be
-// * reasonably smaller than the limit imposed by your operating system.
-// *
-// * WARNING: The pool cannot be used to manipulate RrdDb objects
-// * with {@link RrdBackend backends} different from default.
-// */
-//public class RrdDbPool implements Runnable {
-// static final String GC_THREAD_NAME = "RrdDbPool GC thread";
-// static final String CLOSING_THREAD_NAME = "RrdDbPool closing thread";
-// private static final boolean DEBUG = false;
-//
-// // singleton pattern
-// private static RrdDbPool ourInstance;
-// private boolean closingOnExit = true;
-//
-// private Thread shutdownHook = new Thread(CLOSING_THREAD_NAME) {
-// public void run() {
-// try {
-// close();
-// }
-// catch (IOException e) {
-// e.printStackTrace();
-// }
-// }
-// };
-//
-// /**
-// * Constant to represent the maximum number of internally open RRD files
-// * which still does not force garbage collector (the process which closes RRD files) to run.
-// */
-// public static final int INITIAL_CAPACITY = 500;
-// private int capacity = INITIAL_CAPACITY, maxUsedCapacity;
-// private boolean active = true;
-//
-// /**
-// * Constant to represent the internal behaviour of the pool.
-// * Defaults to
-// *
-// * By default, the pool behaviour is 'flexible' (
-// *
-// * @param limitedCapacity
- * RRD definition (RrdDef object) consists of the following elements:
- *
- *
- *
- * @author Sasa Markovic
- */
-public class RrdDef {
- /**
- * default RRD step to be used if not specified in constructor (300 seconds)
- */
- public static final long DEFAULT_STEP = 300L;
- /**
- * if not specified in constructor, starting timestamp will be set to the
- * current timestamp plus DEFAULT_INITIAL_SHIFT seconds (-10)
- */
- public static final long DEFAULT_INITIAL_SHIFT = -10L;
-
- private String path;
- private long startTime = Util.getTime() + DEFAULT_INITIAL_SHIFT;
- private long step = DEFAULT_STEP;
- private ArrayList Creates new RRD definition object with the given path.
- * When this object is passed to
- * Creates new RRD definition object with the given path and step. Creates new RRD definition object with the given path, starting timestamp
- * and step.
- * IMPORTANT NOTE: If datasource name ends with '!', corresponding archives will never
- * store NaNs as datasource values. In that case, NaN datasource values will be silently
- * replaced with zeros by the framework.
- *
- * @param dsName Data source name.
- * @param dsType Data source type. Valid types are "COUNTER",
- * "GAUGE", "DERIVE" and "ABSOLUTE" (these string constants are conveniently defined in
- * the {@link DsTypes} class).
- * @param heartbeat Data source heartbeat.
- * @param minValue Minimal acceptable value. Use
- *
- *
- *
- * @param consolFun Consolidation function. Valid values are "AVERAGE",
- * "MIN", "MAX" and "LAST" (these constants are conveniently defined in the
- * {@link ConsolFuns} class)
- * @param xff X-files factor. Valid values are between 0 and 1.
- * @param steps Number of archive steps
- * @param rows Number of archive rows
- * @throws RrdException Thrown if archive with the same consolidation function
- * and the same number of steps is already added.
- */
- public void addArchive(final String consolFun, final double xff, final int steps, final int rows) throws RrdException {
- addArchive(new ArcDef(consolFun, xff, steps, rows));
- }
-
- /**
- * Adds single archive to RRD definition from a RRDTool-like
- * archive definition string. The string must have five elements separated with colons
- * (:) in the following order:
- *
- *
- *
- *
- * Here is an example of a properly formatted XML template with all available
- * options in it (unwanted options can be removed):
- *
- *
- * Typical usage scenario:
- *
- *
- * @return RrdDef object constructed from the underlying XML template,
- * with all placeholders replaced with real values. This object can be passed to the constructor
- * of the new RrdDb object.
- * @throws RrdException Thrown (in most cases) if the value for some placeholder
- * was not supplied through {@link XmlTemplate#setVariable(String, String) setVariable()}
- * method call
- */
- public RrdDef getRrdDef() throws RrdException {
- if (!root.getTagName().equals("rrd_def")) {
- throw new RrdException("XML definition must start with
- * This backend is based on the RandomAccessFile class (java.io.* package).
- */
-public class RrdFileBackend extends RrdBackend {
- /**
- * radnom access file handle
- */
- protected RandomAccessFile file;
-
- /**
- * 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
- * @throws IOException Thrown in case of I/O error
- */
- protected RrdFileBackend(final String path, final boolean readOnly) throws IOException {
- super(path, readOnly);
- this.file = new RandomAccessFile(path, readOnly ? "r" : "rw");
- }
-
- /**
- * Closes the underlying RRD file.
- *
- * @throws IOException Thrown in case of I/O error
- */
- public void close() throws IOException {
- file.close();
- }
-
- /**
- * 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);
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdFileBackendFactory.java b/apps/jrobin/java/src/org/jrobin/core/RrdFileBackendFactory.java
deleted file mode 100644
index e89959616f..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdFileBackendFactory.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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.
- * @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) throws IOException {
- return new RrdFileBackend(path, readOnly);
- }
-
- /**
- * 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;
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdInt.java b/apps/jrobin/java/src/org/jrobin/core/RrdInt.java
deleted file mode 100644
index 3213d541c9..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdInt.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.IOException;
-
-class RrdInt extends RrdPrimitive {
- private int cache;
- private boolean cached = false;
-
- RrdInt(final RrdUpdater updater, final boolean isConstant) throws IOException {
- super(updater, RrdPrimitive.RRD_INT, isConstant);
- }
-
- RrdInt(final RrdUpdater updater) throws IOException {
- this(updater, false);
- }
-
- void set(final int value) throws IOException {
- if (!isCachingAllowed()) {
- writeInt(value);
- }
- // caching allowed
- else if (!cached || cache != value) {
- // update cache
- writeInt(cache = value);
- cached = true;
- }
- }
-
- int get() throws IOException {
- return cached ? cache : readInt();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdJRobin14FileBackend.java b/apps/jrobin/java/src/org/jrobin/core/RrdJRobin14FileBackend.java
deleted file mode 100644
index 7e8ba8b09e..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdJRobin14FileBackend.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/* ============================================================
- * JRobin : Pure java implementation of RRDTool's functionality
- * ============================================================
- *
- * Project Info: http://www.jrobin.org
- * Project Lead: Sasa Markovic (saxon@jrobin.org);
- *
- * (C) Copyright 2003, by Sasa Markovic.
- *
- * Developers: Sasa Markovic (saxon@jrobin.org)
- * Arne Vandamme (cobralord@jrobin.org)
- *
- * This library is free software; you can redistribute it and/or modify it under the terms
- * of the GNU Lesser General Public License as published by the Free Software Foundation;
- * either version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License along with this
- * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-package org.jrobin.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.
- *
- * This backend is based on the RandomAccessFile class (java.io.* package).
- */
-public class RrdJRobin14FileBackend extends RrdBackend {
- private static final long LOCK_DELAY = 100; // 0.1sec
-
- private static Set
- */
-public class RrdMemoryBackend extends RrdBackend {
- private static final ReadWriteLock m_readWritelock = new ReentrantReadWriteLock();
- private static final Lock m_readLock = m_readWritelock.readLock();
- private static final Lock m_writeLock = m_readWritelock.writeLock();
-
- private byte[] buffer = new byte[0];
-
- protected RrdMemoryBackend(String path) {
- super(path);
- }
-
- protected void write(final long offset, final byte[] b) {
- m_writeLock.lock();
- try {
- int pos = (int) offset;
- for (final byte singleByte : b) {
- buffer[pos++] = singleByte;
- }
- } finally {
- m_writeLock.unlock();
- }
- }
-
- protected void read(final long offset, final byte[] b) throws IOException {
- m_readLock.lock();
- try {
- int pos = (int) offset;
- if (pos + b.length <= buffer.length) {
- for (int i = 0; i < b.length; i++) {
- b[i] = buffer[pos++];
- }
- }
- else {
- throw new IOException("Not enough bytes available in memory " + getPath());
- }
- } finally {
- m_readLock.unlock();
- }
- }
-
- /**
- * Returns the number of RRD bytes held in memory.
- *
- * @return Number of all RRD bytes.
- */
- public long getLength() {
- m_readLock.lock();
- try {
- return buffer.length;
- } finally {
- m_readLock.unlock();
- }
- }
-
- /**
- * Reserves a memory section as a RRD storage.
- *
- * @param newLength Number of bytes held in memory.
- * @throws IOException Thrown in case of I/O error.
- */
- protected void setLength(final long newLength) throws IOException {
- m_writeLock.lock();
- try {
- if (newLength > Integer.MAX_VALUE) {
- throw new IOException("Cannot create this big memory backed RRD");
- }
- buffer = new byte[(int) newLength];
- } finally {
- m_writeLock.unlock();
- }
- }
-
- /**
- * This method is required by the base class definition, but it does not
- * releases any memory resources at all.
- */
- public void close() {
- // NOP
- }
-
- /**
- * This method is overridden to disable high-level caching in frontend JRobin classes.
- *
- * @return Always returns
- * Calling {@link RrdDb#close() close()} on RrdDb objects does not release any memory at all
- * (RRD data must be available for the next
- *
- * IMPORTANT: NEVER use methods found in this class on 'live' RRD files
- * (files which are currently in use).
- */
-public class RrdToolkit {
- /**
- * Creates a new RRD file with one more datasource in it. RRD file is created based on the
- * existing one (the original RRD file is not modified at all). All data from
- * the original RRD file is copied to the new one.
- *
- * @param sourcePath path to a RRD file to import data from (will not be modified)
- * @param destPath path to a new RRD file (will be created)
- * @param newDatasource Datasource definition to be added to the new RRD file
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public static void addDatasource(String sourcePath, String destPath, DsDef newDatasource)
- throws IOException, RrdException {
- if (Util.sameFilePath(sourcePath, destPath)) {
- throw new RrdException("Source and destination paths are the same");
- }
- RrdDb rrdSource = new RrdDb(sourcePath);
- try {
- RrdDef rrdDef = rrdSource.getRrdDef();
- rrdDef.setPath(destPath);
- rrdDef.addDatasource(newDatasource);
- RrdDb rrdDest = new RrdDb(rrdDef);
- try {
- rrdSource.copyStateTo(rrdDest);
- }
- finally {
- rrdDest.close();
- }
- }
- finally {
- rrdSource.close();
- }
- }
-
- /**
- * Adds one more datasource to a RRD file. WARNING: This method is potentialy dangerous! It will modify your RRD file.
- * It is highly recommended to preserve the original RRD file (saveBackup
- * should be set to Before applying this method, be sure that the specified RRD file is not in use
- * (not open) Removes single datasource from a RRD file. WARNING: This method is potentialy dangerous! It will modify your RRD file.
- * It is highly recommended to preserve the original RRD file (saveBackup
- * should be set to Before applying this method, be sure that the specified RRD file is not in use
- * (not open) Adds one more archive to a RRD file. WARNING: This method is potentialy dangerous! It will modify your RRD file.
- * It is highly recommended to preserve the original RRD file (saveBackup
- * should be set to Before applying this method, be sure that the specified RRD file is not in use
- * (not open) Removes one archive from a RRD file. WARNING: This method is potentialy dangerous! It will modify your RRD file.
- * It is highly recommended to preserve the original RRD file (saveBackup
- * should be set to Before applying this method, be sure that the specified RRD file is not in use
- * (not open)
- * To update a RRD with JRobin use the following procedure:
- *
- *
- * Newly created Sample object contains all data source values set to 'unknown'.
- * You should specifify only 'known' data source values. However, if you want to specify
- * 'unknown' values too, use
- * You don't have to supply all datasource values. Unspecified values will be treated
- * as unknowns. To specify unknown value in the argument string, use letter 'U'.
- *
- * @param timeAndValues String made by concatenating sample timestamp with corresponding
- * data source values delmited with colons. For example:
- *
- * Method will throw an exception if timestamp is invalid (cannot be parsed as Long, and is not 'N'
- * or 'NOW'). Datasource value which cannot be parsed as 'double' will be silently set to NaN.
- * @return This Creates sample with the timestamp and data source values supplied
- * in the argument string and stores sample in the corresponding RRD.
- * This method is just a shortcut for:
- *
- *
- *
- * @return timestamp in seconds since epoch.
- * @throws RrdException Thrown if invalid time specification is supplied.
- */
- public static long getTimestamp(final String atStyleTimeSpec) throws RrdException {
- final TimeSpec timeSpec = new TimeParser(atStyleTimeSpec).parse();
- return timeSpec.getTimestamp();
- }
-
- /**
- * Parses two related at-style time specifications and returns corresponding timestamps. For example:
- *
- * @param atStyleTimeSpec2 Ending at-style time specification. For the complete explanation of the syntax
- * allowed see RRDTool's
- * @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(final String atStyleTimeSpec1, final String atStyleTimeSpec2) throws RrdException {
- final TimeSpec timeSpec1 = new TimeParser(atStyleTimeSpec1).parse();
- final 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
- * is returned (NumberFormatException is never thrown).
- *
- * @param valueStr String representing double value
- * @return a double corresponding to the input string
- */
- public static double parseDouble(final String valueStr) {
- double value;
- try {
- value = Double.parseDouble(valueStr);
- }
- catch (final NumberFormatException nfe) {
- value = Double.NaN;
- }
- return value;
- }
-
- /**
- * Checks if a string can be parsed as double.
- *
- * @param s Input string
- * @return
- * The function assumes that all JRobin .class files are placed under
- * the <root>/classes subdirectory and that all jars (libraries) are placed in the
- * <root>/lib subdirectory (the original JRobin directory structure).
- *
- * @return absolute path to JRobin's home directory
- */
- public static String getJRobinHomeDirectory() {
- final String className = Util.class.getName().replace('.', '/');
- String uri = Util.class.getResource("/" + className + ".class").toString();
- //System.out.println(uri);
- if (uri.startsWith("file:/")) {
- uri = uri.substring(6);
- File file = new File(uri);
- // let's go 5 steps backwards
- for (int i = 0; i < 5; i++) {
- file = file.getParentFile();
- }
- uri = file.getAbsolutePath();
- }
- else if (uri.startsWith("jar:file:/")) {
- uri = uri.substring(9, uri.lastIndexOf('!'));
- File file = new File(uri);
- // let's go 2 steps backwards
- for (int i = 0; i < 2; i++) {
- file = file.getParentFile();
- }
- uri = file.getAbsolutePath();
- }
- else {
- uri = null;
- }
- return uri;
- }
-
- /**
- * Compares two doubles but treats all NaNs as equal.
- * In Java (by default) Double.NaN == Double.NaN always returns
- */
-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
- * Currently this can read RRD files that were generated on Solaris (Sparc)
- * and Linux (x86).
- *
- * @author Ciaran Treanor
- * @version $Revision$
- */
-public class RRDFile implements Constants {
-
- boolean bigEndian;
- boolean debug;
- int alignment;
- RandomAccessFile ras;
- byte[] buffer;
-
- RRDFile(String name) throws IOException, RrdException {
- this(new File(name));
- }
-
- RRDFile(File file) throws IOException, RrdException {
-
- ras = new RandomAccessFile(file, "r");
- buffer = new byte[128];
-
- this.debug = false;
- initDataLayout(file);
- }
-
- private void initDataLayout(File file) throws IOException, RrdException {
-
- if (file.exists()) { // Load the data formats from the file
- int bytes = ras.read(buffer, 0, 24);
- if (bytes < 24) {
- throw new RrdException("Invalid RRD file");
- }
-
- int index;
-
- if ((index = indexOf(FLOAT_COOKIE_BIG_ENDIAN, buffer)) != -1) {
- bigEndian = true;
- }
- else if ((index = indexOf(FLOAT_COOKIE_LITTLE_ENDIAN, buffer))
- != -1) {
- bigEndian = false;
- }
- else {
- throw new RrdException("Invalid RRD file");
- }
-
- switch (index) {
-
- case 12:
- alignment = 4;
- break;
-
- case 16:
- alignment = 8;
- break;
-
- default :
- throw new RuntimeException("Unsupported architecture - neither 32-bit nor 64-bit, or maybe the file is corrupt");
- }
- }
- else { // Default to data formats for this hardware architecture
- }
-
- ras.seek(0); // Reset file pointer to start of file
- }
-
- private int indexOf(byte[] pattern, byte[] array) {
- return (new String(array)).indexOf(new String(pattern));
- }
-
- boolean isBigEndian() {
- return bigEndian;
- }
-
- int getAlignment() {
- return alignment;
- }
-
- double readDouble() throws IOException, RrdException {
- if(debug) {
- System.out.print("Read 8 bytes (Double) from offset "+ras.getFilePointer()+":");
- }
-
- //double value;
- byte[] tx = new byte[8];
-
- if(ras.read(buffer, 0, 8) != 8) {
- throw new RrdException("Invalid RRD file");
- }
-
- if (bigEndian) {
- tx = buffer;
- }
- else {
- for (int i = 0; i < 8; i++) {
- tx[7 - i] = buffer[i];
- }
- }
-
- DataInputStream reverseDis =
- new DataInputStream(new ByteArrayInputStream(tx));
-
- Double result = reverseDis.readDouble();
- if(this.debug) {
- System.out.println(result);
- }
- return result;
- }
-
- int readInt() throws IOException, RrdException {
- return readInt(false);
- }
-
- /**
- * Reads the next integer (4 or 8 bytes depending on alignment), advancing the file pointer
- * and returns it
- * If the alignment is 8-bytes (64-bit), then 8 bytes are read, but only the lower 4-bytes (32-bits) are
- * returned. The upper 4 bytes are ignored.
- *
- * @return the 32-bit integer read from the file
- * @throws IOException - A file access error
- * @throws RrdException - Not enough bytes were left in the file to read the integer.
- */
- int readInt(boolean dump) throws IOException, RrdException {
- //An integer is "alignment" bytes long - 4 bytes on 32-bit, 8 on 64-bit.
- if(this.debug) {
- System.out.print("Read "+alignment+" bytes (int) from offset "+ras.getFilePointer()+":");
- }
-
- if(ras.read(buffer, 0, alignment) != alignment) {
- throw new RrdException("Invalid RRD file");
- }
-
- int value;
-
- if (bigEndian) {
- if(alignment == 8) {
- //For big-endian, the low 4-bytes of the 64-bit integer are the last 4 bytes
- value = (0xFF & buffer[7]) | ((0xFF & buffer[6]) << 8)
- | ((0xFF & buffer[5]) << 16) | ((0xFF & buffer[4]) << 24);
- } else {
- value = (0xFF & buffer[3]) | ((0xFF & buffer[2]) << 8)
- | ((0xFF & buffer[1]) << 16) | ((0xFF & buffer[0]) << 24);
- }
- }
- else {
- //For little-endian, there's no difference between 4 and 8 byte alignment.
- // The first 4 bytes are the low end of a 64-bit number
- value = (0xFF & buffer[0]) | ((0xFF & buffer[1]) << 8)
- | ((0xFF & buffer[2]) << 16) | ((0xFF & buffer[3]) << 24);
- }
-
- if(this.debug) {
- System.out.println(value);
- }
- return value;
- }
-
- String readString(int maxLength) throws IOException, RrdException {
- if(this.debug) {
- System.out.print("Read "+maxLength+" bytes (string) from offset "+ras.getFilePointer()+":");
- }
- maxLength = ras.read(buffer, 0, maxLength);
- if(maxLength == -1) {
- throw new RrdException("Invalid RRD file");
- }
-
- String result = new String(buffer, 0, maxLength).trim();
- if(this.debug) {
- System.out.println( result +":");
- }
- return result;
- }
-
- void skipBytes(final int n) throws IOException {
- int bytesSkipped = ras.skipBytes(n);
- if(this.debug) {
- System.out.println("Skipping "+bytesSkipped+" bytes");
- }
- }
-
- int align(int boundary) throws IOException {
-
- int skip = (int) (boundary - (ras.getFilePointer() % boundary)) % boundary;
-
- if (skip != 0) {
- skip = ras.skipBytes(skip);
- }
- if(this.debug) {
- System.out.println("Aligning to boundary "+ boundary +". Offset is now "+ras.getFilePointer());
- }
- return skip;
- }
-
- int align() throws IOException {
- return align(alignment);
- }
-
- long info() throws IOException {
- return ras.getFilePointer();
- }
-
- long getFilePointer() throws IOException {
- return ras.getFilePointer();
- }
-
- void close() throws IOException {
- ras.close();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/jrrd/RRDatabase.java b/apps/jrobin/java/src/org/jrobin/core/jrrd/RRDatabase.java
deleted file mode 100644
index 0a39f1f161..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/jrrd/RRDatabase.java
+++ /dev/null
@@ -1,508 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core.jrrd;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.text.DecimalFormat;
-import java.text.NumberFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-
-import org.jrobin.core.RrdException;
-
-/**
- * Instances of this class model
- * Round Robin Database
- * (RRD) files.
- *
- * @author Ciaran Treanor
- * @version $Revision$
- */
-public class RRDatabase {
-
- RRDFile rrdFile;
-
- // RRD file name
- private String name;
- Header header;
- ArrayList
- *
- */
-public class Epoch extends JFrame {
- private static final long serialVersionUID = 1L;
- 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("Supported input formats:
- *
- *
- *
- * WARNING: So far, this class cannot handle NaN datasource values
- * (an exception will be thrown by the constructor). Future releases might change this.
- */
-public class CubicSplineInterpolator extends Plottable {
- private double[] x;
- private double[] y;
-
- // second derivates come here
- private double[] y2;
-
- // internal spline variables
- private int n, klo, khi;
-
- /**
- * Creates cubic spline interpolator from arrays of timestamps and corresponding
- * datasource values.
- *
- * @param timestamps timestamps in seconds
- * @param values corresponding datasource values
- * @throws RrdException Thrown if supplied arrays do not contain at least 3 values, or if
- * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
- */
- public CubicSplineInterpolator(long[] timestamps, double[] values) throws RrdException {
- this.x = new double[timestamps.length];
- for (int i = 0; i < timestamps.length; i++) {
- this.x[i] = timestamps[i];
- }
- this.y = values;
- validate();
- spline();
- }
-
- /**
- * Creates cubic spline interpolator from arrays of Date objects and corresponding
- * datasource values.
- *
- * @param dates Array of Date objects
- * @param values corresponding datasource values
- * @throws RrdException Thrown if supplied arrays do not contain at least 3 values, or if
- * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
- */
- public CubicSplineInterpolator(Date[] dates, double[] values) throws RrdException {
- this.x = new double[dates.length];
- for (int i = 0; i < dates.length; i++) {
- this.x[i] = Util.getTimestamp(dates[i]);
- }
- this.y = values;
- validate();
- spline();
- }
-
- /**
- * Creates cubic spline interpolator from arrays of GregorianCalendar objects and corresponding
- * datasource values.
- *
- * @param dates Array of GregorianCalendar objects
- * @param values corresponding datasource values
- * @throws RrdException Thrown if supplied arrays do not contain at least 3 values, or if
- * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
- */
- public CubicSplineInterpolator(Calendar[] dates, double[] values) throws RrdException {
- this.x = new double[dates.length];
- for (int i = 0; i < dates.length; i++) {
- this.x[i] = Util.getTimestamp(dates[i]);
- }
- this.y = values;
- validate();
- spline();
- }
-
- /**
- * Creates cubic spline interpolator for an array of 2D-points.
- *
- * @param x x-axis point coordinates
- * @param y y-axis point coordinates
- * @throws RrdException Thrown if supplied arrays do not contain at least 3 values, or if
- * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
- */
- public CubicSplineInterpolator(double[] x, double[] y) throws RrdException {
- this.x = x;
- this.y = y;
- validate();
- spline();
- }
-
- private void validate() throws RrdException {
- boolean ok = true;
- if (x.length != y.length || x.length < 3) {
- ok = false;
- }
- for (int i = 0; i < x.length - 1 && ok; i++) {
- if (x[i] >= x[i + 1] || Double.isNaN(y[i])) {
- ok = false;
- }
- }
- if (!ok) {
- throw new RrdException("Invalid plottable data supplied");
- }
- }
-
- private void spline() {
- n = x.length;
- y2 = new double[n];
- double[] u = new double[n - 1];
- y2[0] = y2[n - 1] = 0.0;
- u[0] = 0.0; // natural spline
- for (int i = 1; i <= n - 2; i++) {
- double sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
- double p = sig * y2[i - 1] + 2.0;
- y2[i] = (sig - 1.0) / p;
- u[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
- u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
- }
- for (int k = n - 2; k >= 0; k--) {
- y2[k] = y2[k] * y2[k + 1] + u[k];
- }
- // prepare everything for getValue()
- klo = 0;
- khi = n - 1;
- }
-
- /**
- * Calculates spline-interpolated y-value for the corresponding x-value. Call
- * this if you need spline-interpolated values in your code.
- *
- * @param xval x-value
- * @return inteprolated y-value
- */
- public double getValue(double xval) {
- if (xval < x[0] || xval > x[n - 1]) {
- return Double.NaN;
- }
- if (xval < x[klo] || xval > x[khi]) {
- // out of bounds
- klo = 0;
- khi = n - 1;
- }
- while (khi - klo > 1) {
- // find bounding interval using bisection method
- int k = (khi + klo) >>> 1;
- if (x[k] > xval) {
- khi = k;
- }
- else {
- klo = k;
- }
- }
- double h = x[khi] - x[klo];
- double a = (x[khi] - xval) / h;
- double b = (xval - x[klo]) / h;
- return a * y[klo] + b * y[khi] +
- ((a * a * a - a) * y2[klo] + (b * b * b - b) * y2[khi]) * (h * h) / 6.0;
- }
-
- /**
- * Method overriden from the base class. This method will be called by the framework. Call
- * this method only if you need spline-interpolated values in your code.
- *
- * @param timestamp timestamp in seconds
- * @return inteprolated datasource value
- */
- public double getValue(long timestamp) {
- return getValue((double) timestamp);
- }
-
-}
diff --git a/apps/jrobin/java/src/org/jrobin/data/DataProcessor.java b/apps/jrobin/java/src/org/jrobin/data/DataProcessor.java
deleted file mode 100644
index a258068342..0000000000
--- a/apps/jrobin/java/src/org/jrobin/data/DataProcessor.java
+++ /dev/null
@@ -1,936 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.data;
-
-import org.jrobin.core.*;
-
-import java.io.IOException;
-import java.util.*;
-
-/**
- * Class which should be used for all calculations based on the data fetched from RRD files. This class
- * supports ordinary DEF datasources (defined in RRD files), CDEF datasources (RPN expressions evaluation),
- * SDEF (static datasources - extension of JRobin) and PDEF (plottables, see
- * {@link Plottable Plottable} for more information.
- *
- * Typical class usage:
- *
- *
- * The default number of pixels is defined by constant {@link #DEFAULT_PIXEL_COUNT}
- * and can be changed with a {@link #setPixelCount(int)} method.
- *
- * @param pixelCount The number of pixels. If you process RRD data in order to display it on the graph,
- * this should be the width of your graph.
- */
- public void setPixelCount(int pixelCount) {
- this.pixelCount = pixelCount;
- }
-
- /**
- * Returns the number of pixels (target graph width). See {@link #setPixelCount(int)} for more information.
- *
- * @return Target graph width
- */
- public int getPixelCount() {
- return pixelCount;
- }
-
- /**
- * Roughly corresponds to the --step option in RRDTool's graph/xport commands. Here is an explanation borrowed
- * from RRDTool:
- *
- * "By default rrdgraph calculates the width of one pixel in the time
- * domain and tries to get data at that resolution from the RRD. With
- * this switch you can override this behavior. If you want rrdgraph to
- * get data at 1 hour resolution from the RRD, then you can set the
- * step to 3600 seconds. Note, that a step smaller than 1 pixel will
- * be silently ignored."
- *
- * I think this option is not that useful, but it's here just for compatibility.
- *
- * @param step Time step at which data should be fetched from RRD files. If this method is not used,
- * the step will be equal to the smallest RRD step of all processed RRD files. If no RRD file is processed,
- * the step will be roughly equal to the with of one graph pixel (in seconds).
- */
- public void setStep(long step) {
- this.step = step;
- }
-
- /**
- * Returns the time step used for data processing. Initially, this method returns zero.
- * Once {@link #processData()} is finished, the method will return the real value used for
- * all internal computations. Roughly corresponds to the --step option in RRDTool's graph/xport commands.
- *
- * @return Step used for data processing.
- */
- public long getStep() {
- return step;
- }
-
- /**
- * Returns desired RRD archive step (reslution) in seconds to be used while fetching data
- * from RRD files. In other words, this value will used as the last parameter of
- * {@link RrdDb#createFetchRequest(String, long, long, long) RrdDb.createFetchRequest()} method
- * when this method is called internally by this DataProcessor.
- *
- * @return Desired archive step (fetch resolution) in seconds.
- */
- public long getFetchRequestResolution() {
- return fetchRequestResolution;
- }
-
- /**
- * Sets desired RRD archive step in seconds to be used internally while fetching data
- * from RRD files. In other words, this value will used as the last parameter of
- * {@link RrdDb#createFetchRequest(String, long, long, long) RrdDb.createFetchRequest()} method
- * when this method is called internally by this DataProcessor. If this method is never called, fetch
- * request resolution defaults to 1 (smallest possible archive step will be chosen automatically).
- *
- * @param fetchRequestResolution Desired archive step (fetch resoltuion) in seconds.
- */
- public void setFetchRequestResolution(long fetchRequestResolution) {
- this.fetchRequestResolution = fetchRequestResolution;
- }
-
- /**
- * Returns ending timestamp. Basically, this value is equal to the ending timestamp
- * specified in the constructor. However, if the ending timestamps was zero, it
- * will be replaced with the real timestamp when the {@link #processData()} method returns. The real
- * value will be calculated from the last update times of processed RRD files.
- *
- * @return Ending timestamp in seconds
- */
- public long getEndingTimestamp() {
- return tEnd;
- }
-
- /**
- * Returns consolidated timestamps created with the {@link #processData()} method.
- *
- * @return array of timestamps in seconds
- * @throws RrdException thrown if timestamps are not calculated yet
- */
- public long[] getTimestamps() throws RrdException {
- if (timestamps == null) {
- throw new RrdException("Timestamps not calculated yet");
- }
- else {
- return timestamps;
- }
- }
-
- /**
- * Returns calculated values for a single datasource. Corresponding timestamps can be obtained from
- * the {@link #getTimestamps()} method.
- *
- * @param sourceName Datasource name
- * @return an array of datasource values
- * @throws RrdException Thrown if invalid datasource name is specified,
- * or if datasource values are not yet calculated (method {@link #processData()}
- * was not called)
- */
- public double[] getValues(String sourceName) throws RrdException {
- Source source = getSource(sourceName);
- double[] values = source.getValues();
- if (values == null) {
- throw new RrdException("Values not available for source [" + sourceName + "]");
- }
- return values;
- }
-
- /**
- * Returns single aggregated value for a single datasource.
- *
- * @param sourceName Datasource name
- * @param consolFun Consolidation function to be applied to fetched datasource values.
- * Valid consolidation functions are MIN, MAX, LAST, FIRST, AVERAGE and TOTAL
- * (these string constants are conveniently defined in the {@link ConsolFuns} class)
- * @return MIN, MAX, LAST, FIRST, AVERAGE or TOTAL value calculated from the data
- * for the given datasource name
- * @throws RrdException Thrown if invalid datasource name is specified,
- * or if datasource values are not yet calculated (method {@link #processData()}
- * was not called)
- */
- public double getAggregate(String sourceName, String consolFun) throws RrdException {
- Source source = getSource(sourceName);
- return source.getAggregates(tStart, tEnd).getAggregate(consolFun);
- }
-
- /**
- * Returns all (MIN, MAX, LAST, FIRST, AVERAGE and TOTAL) aggregated values for a single datasource.
- *
- * @param sourceName Datasource name
- * @return Object containing all aggregated values
- * @throws RrdException Thrown if invalid datasource name is specified,
- * or if datasource values are not yet calculated (method {@link #processData()}
- * was not called)
- */
- public Aggregates getAggregates(String sourceName) throws RrdException {
- Source source = getSource(sourceName);
- return source.getAggregates(tStart, tEnd);
- }
-
- /**
- * This method is just an alias for {@link #getPercentile(String)} method.
- *
- * Used by ISPs which charge for bandwidth utilization on a "95th percentile" basis.
- *
- * 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.
- *
- * Read more about this topic at
- * Rednet or
- * Bytemark.
- *
- * @param sourceName Datasource name
- * @return 95th percentile of fetched source values
- * @throws RrdException Thrown if invalid source name is supplied
- */
- public double get95Percentile(String sourceName) throws RrdException {
- return getPercentile(sourceName);
- }
-
- /**
- * Used by ISPs which charge for bandwidth utilization on a "95th percentile" basis.
- *
- * 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.
- *
- * Read more about this topic at
- * Rednet or
- * Bytemark.
- *
- * @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 + "], should be between 0 and 100");
- }
- Source source = getSource(sourceName);
- return source.getPercentile(tStart, tEnd, percentile);
- }
-
- /**
- * Returns array of datasource names defined in this DataProcessor.
- *
- * @return array of datasource names
- */
- public String[] getSourceNames() {
- return sources.keySet().toArray(new String[0]);
- }
-
- /**
- * Returns an array of all datasource values for all datasources. Each row in this two-dimensional
- * array represents an array of calculated values for a single datasource. The order of rows is the same
- * as the order in which datasources were added to this DataProcessor object.
- *
- * @return All datasource values for all datasources. The first index is the index of the datasource,
- * the second index is the index of the datasource value. The number of datasource values is equal
- * to the number of timestamps returned with {@link #getTimestamps()} method.
- * @throws RrdException Thrown if invalid datasource name is specified,
- * or if datasource values are not yet calculated (method {@link #processData()}
- * was not called)
- */
- public double[][] getValues() throws RrdException {
- String[] names = getSourceNames();
- double[][] values = new double[names.length][];
- for (int i = 0; i < names.length; i++) {
- values[i] = getValues(names[i]);
- }
- return values;
- }
-
- private Source getSource(String sourceName) throws RrdException {
- Source source = sources.get(sourceName);
- if (source != null) {
- return source;
- }
- throw new RrdException("Unknown source: " + sourceName);
- }
-
- /////////////////////////////////////////////////////////////////
- // DATASOURCE DEFINITIONS
- /////////////////////////////////////////////////////////////////
-
- /**
- * Adds a custom, {@link org.jrobin.data.Plottable plottable} datasource (PDEF).
- * The datapoints should be made available by a class extending
- * {@link org.jrobin.data.Plottable Plottable} class.
- *
- *
- * @param name source name.
- * @param plottable class that extends Plottable class and is suited for graphing.
- */
- public void addDatasource(String name, Plottable plottable) {
- PDef pDef = new PDef(name, plottable);
- sources.put(name, pDef);
- }
-
- /**
- * Adds complex source (CDEF).
- * Complex sources are evaluated using the supplied
- * Complex source
- * JRobin supports the following RPN functions, operators and constants: +, -, *, /,
- * %, SIN, COS, LOG, EXP, FLOOR, CEIL, ROUND, POW, ABS, SQRT, RANDOM, LT, LE, GT, GE, EQ,
- * IF, MIN, MAX, LIMIT, DUP, EXC, POP, UN, UNKN, NOW, TIME, PI, E,
- * AND, OR, XOR, PREV, PREV(sourceName), INF, NEGINF, STEP, YEAR, MONTH, DATE,
- * HOUR, MINUTE, SECOND, WEEK, SIGN and RND.
- *
- * JRobin does not force you to specify at least one simple source name as RRDTool.
- *
- * For more details on RPN see RRDTool's
- *
- * rrdgraph man page.
- *
- * @param name source name.
- * @param rpnExpression RPN expression containig comma (or space) delimited simple and complex
- * source names, RPN constants, functions and operators.
- */
- public void addDatasource(String name, String rpnExpression) {
- CDef cDef = new CDef(name, rpnExpression);
- sources.put(name, cDef);
- }
-
- /**
- * Adds static source (SDEF). Static sources are the result of a consolidation function applied
- * to *any* other source that has been defined previously.
- *
- * @param name source name.
- * @param defName Name of the datasource to calculate the value from.
- * @param consolFun Consolidation function to use for value calculation
- */
- public void addDatasource(String name, String defName, String consolFun) {
- SDef sDef = new SDef(name, defName, consolFun);
- sources.put(name, sDef);
- }
-
- /**
- * Adds simple datasource (DEF). Simple source Adds simple source (DEF). Source
- * Interpolation algorithm returns different values based on the value passed to
- * {@link #setInterpolationMethod(int) setInterpolationMethod()}. If not set, interpolation
- * method defaults to standard linear interpolation ({@link #INTERPOLATE_LINEAR}).
- * Interpolation method handles NaN datasource
- * values gracefully.
- */
-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;
- /**
- * constant used to specify LINEAR interpolation (default interpolation method).
- * See {@link #setInterpolationMethod(int) setInterpolationMethod()} for explanation.
- */
- public static final int INTERPOLATE_LINEAR = 2;
- /**
- * constant used to specify LINEAR REGRESSION as interpolation method.
- * See {@link #setInterpolationMethod(int) setInterpolationMethod()} for explanation.
- */
- public static final int INTERPOLATE_REGRESSION = 3;
-
- private int lastIndexUsed = 0;
- private int interpolationMethod = INTERPOLATE_LINEAR;
-
- private long[] timestamps;
- private double[] values;
-
- // used only if INTERPOLATE_BESTFIT is specified
- double b0 = Double.NaN, b1 = Double.NaN;
-
- /**
- * Creates LinearInterpolator from arrays of timestamps and corresponding datasource values.
- *
- * @param timestamps timestamps in seconds
- * @param values corresponding datasource values
- * @throws RrdException Thrown if supplied arrays do not contain at least two values, or if
- * timestamps are not ordered, or array lengths are not equal.
- */
- public LinearInterpolator(long[] timestamps, double[] values) throws RrdException {
- this.timestamps = timestamps;
- this.values = values;
- validate();
- }
-
- /**
- * Creates LinearInterpolator from arrays of timestamps and corresponding datasource values.
- *
- * @param dates Array of Date objects
- * @param values corresponding datasource values
- * @throws RrdException Thrown if supplied arrays do not contain at least two values, or if
- * timestamps are not ordered, or array lengths are not equal.
- */
- public LinearInterpolator(Date[] dates, double[] values) throws RrdException {
- this.values = values;
- timestamps = new long[dates.length];
- for (int i = 0; i < dates.length; i++) {
- timestamps[i] = Util.getTimestamp(dates[i]);
- }
- validate();
- }
-
- /**
- * Creates LinearInterpolator from arrays of timestamps and corresponding datasource values.
- *
- * @param dates array of GregorianCalendar objects
- * @param values corresponding datasource values
- * @throws RrdException Thrown if supplied arrays do not contain at least two values, or if
- * timestamps are not ordered, or array lengths are not equal.
- */
- public LinearInterpolator(Calendar[] dates, double[] values) throws RrdException {
- this.values = values;
- timestamps = new long[dates.length];
- for (int i = 0; i < dates.length; i++) {
- timestamps[i] = Util.getTimestamp(dates[i]);
- }
- validate();
- }
-
- private void validate() throws RrdException {
- boolean ok = true;
- if (timestamps.length != values.length || timestamps.length < 2) {
- ok = false;
- }
- for (int i = 0; i < timestamps.length - 1 && ok; i++) {
- if (timestamps[i] >= timestamps[i + 1]) {
- ok = false;
- }
- }
- if (!ok) {
- throw new RrdException("Invalid plottable data supplied");
- }
- }
-
- /**
- * Sets interpolation method to be used. Suppose that we have two timestamp/value pairs:
- *
- * The fourth available interpolation method is INTERPOLATE_REGRESSION. This method uses
- * simple linear regression to interpolate supplied data with a simple straight line which does not
- * necessarily pass through all data points. The slope of the best-fit line will be chosen so that the
- * total square distance of real data points from from the best-fit line is at minimum.
- *
- * The full explanation of this inteprolation method can be found
- * here.
- *
- * @param interpolationMethod Should be Interface to be used for custom datasources.
- * If you wish to use a custom datasource in a graph, you should create a class implementing this interface
- * that represents that datasource, and then pass this class on to the RrdGraphDef.
- * The text printed below the actual graph can be formated by appending
- * special escaped characters at the end of a text. When ever such a
- * character occurs, all pending text is pushed onto the graph according to
- * the character specified.
- *
- * Valid markers are: \j for justified, \l for left aligned, \r for right
- * aligned and \c for centered.
- *
- * Normally there are two space characters inserted between every two
- * items printed into the graph. The space following a string can be
- * suppressed by putting a \g at the end of the string. The \g also squashes
- * any space inside the string if it is at the very end of the string.
- * This can be used in connection with %s to suppress empty unit strings.
- *
- * A special case is COMMENT:\s this inserts some additional vertical
- * space before placing the next row of legends.
- *
- * When text has to be formated without special instructions from your
- * side, RRDTool will automatically justify the text as soon as one string
- * goes over the right edge. If you want to prevent the justification
- * without forcing a newline, you can use the special tag \J at the end of
- * the string to disable the auto justification.
- */
-public class RrdGraphDef implements RrdGraphConstants {
- boolean poolUsed = false; // ok
- boolean antiAliasing = false; // ok
- String filename = RrdGraphConstants.IN_MEMORY_IMAGE; // ok
- long startTime, endTime; // ok
- TimeAxisSetting timeAxisSetting = null; // ok
- ValueAxisSetting valueAxisSetting = null; // ok
- boolean altYGrid = false; // ok
- boolean noMinorGrid = false; // ok
- boolean altYMrtg = false; // ok
- boolean altAutoscale = false; // ok
- boolean altAutoscaleMax = false; // ok
- int unitsExponent = Integer.MAX_VALUE; // ok
- int unitsLength = DEFAULT_UNITS_LENGTH; // ok
- String verticalLabel = null; // ok
- int width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT; // ok
- boolean interlaced = false; // ok
- String imageInfo = null; // ok
- String imageFormat = DEFAULT_IMAGE_FORMAT; // ok
- float imageQuality = DEFAULT_IMAGE_QUALITY; // ok
- String backgroundImage = null; // ok
- String overlayImage = null; // ok
- String unit = null; // ok
- String signature = "Created with JRobin"; // ok
- boolean lazy = false; // ok
- double minValue = Double.NaN; // ok
- double maxValue = Double.NaN; // ok
- boolean rigid = false; // ok
- double base = DEFAULT_BASE; // ok
- boolean logarithmic = false; // ok
- Paint[] colors = new Paint[]{
- // ok
- DEFAULT_CANVAS_COLOR,
- DEFAULT_BACK_COLOR,
- DEFAULT_SHADEA_COLOR,
- DEFAULT_SHADEB_COLOR,
- DEFAULT_GRID_COLOR,
- DEFAULT_MGRID_COLOR,
- DEFAULT_FONT_COLOR,
- DEFAULT_FRAME_COLOR,
- DEFAULT_ARROW_COLOR
- };
- boolean noLegend = false; // ok
- boolean onlyGraph = false; // ok
- boolean forceRulesLegend = false; // ok
- String title = null; // ok
- long step = 0; // ok
- Font[] fonts = new Font[FONTTAG_NAMES.length];
- boolean drawXGrid = true; // ok
- boolean drawYGrid = true; // ok
- int firstDayOfWeek = FIRST_DAY_OF_WEEK; // ok
- boolean showSignature = true;
- File fontDir = null;
-
- List
- * Otherwise, you have to configure three elements making up the x-axis labels
- * and grid. The base grid, the major grid and the labels.
- * The configuration is based on the idea that you first specify a well
- * known amount of time and then say how many times
- * it has to pass between each minor/major grid line or label. For the label
- * you have to define two additional items: The precision of the label
- * in seconds and the format used to generate the text
- * of the label.
- *
- * For example, if you wanted a graph with a base grid every 10 minutes and a major
- * one every hour, with labels every hour you would use the following
- * x-axis definition.
- *
- *
- * The precision in this example is 0 because the %X format is exact.
- * If the label was the name of the day, we would have had a precision
- * of 24 hours, because when you say something like 'Monday' you mean
- * the whole day and not Monday morning 00:00. Thus the label should
- * be positioned at noon. By defining a precision of 24 hours or
- * rather 86400 seconds, you make sure that this happens.
- *
- * @param minorUnit Minor grid unit. Minor grid, major grid and label units
- * can be one of the following constants defined in
- * {@link RrdGraphConstants}: {@link RrdGraphConstants#SECOND SECOND},
- * {@link RrdGraphConstants#MINUTE MINUTE}, {@link RrdGraphConstants#HOUR HOUR},
- * {@link RrdGraphConstants#DAY DAY}, {@link RrdGraphConstants#WEEK WEEK},
- * {@link RrdGraphConstants#MONTH MONTH}, {@link RrdGraphConstants#YEAR YEAR}.
- * @param minorUnitCount Number of minor grid units between minor grid lines.
- * @param majorUnit Major grid unit.
- * @param majorUnitCount Number of major grid units between major grid lines.
- * @param labelUnit Label unit.
- * @param labelUnitCount Number of label units between labels.
- * @param labelSpan Label precision
- * @param simpleDateFormat Date format (SimpleDateFormat pattern of strftime-like pattern)
- */
- public void setTimeAxis(int minorUnit, int minorUnitCount, int majorUnit, int majorUnitCount,
- int labelUnit, int labelUnitCount, int labelSpan, String simpleDateFormat) {
- timeAxisSetting = new TimeAxisSetting(minorUnit, minorUnitCount, majorUnit, majorUnitCount,
- labelUnit, labelUnitCount, labelSpan, simpleDateFormat);
- }
-
- /**
- * Sets vertical axis grid and labels. Makes vertical grid lines appear
- * at gridStep interval. Every labelFactor*gridStep, a major grid line is printed,
- * along with label showing the value of the grid line.
- *
- * @param gridStep Minor grid step
- * @param labelFactor Specifies how many minor minor grid steps will appear between labels
- * (major grid lines)
- */
- public void setValueAxis(double gridStep, int labelFactor) {
- valueAxisSetting = new ValueAxisSetting(gridStep, labelFactor);
- }
-
- /**
- * Places Y grid dynamically based on graph Y range. Algorithm ensures
- * that you always have grid, that there are enough but not too many
- * grid lines and the grid is metric. That is grid lines are placed
- * every 1, 2, 5 or 10 units.
- *
- * @param altYGrid true, if Y grid should be calculated dynamically (defaults to false)
- */
- public void setAltYGrid(boolean altYGrid) {
- this.altYGrid = altYGrid;
- }
-
- /**
- * Use this method to turn off minor grid lines (printed by default)
- *
- * @param noMinorGrid true, to turn off, false to turn on (default)
- */
- public void setNoMinorGrid(boolean noMinorGrid) {
- this.noMinorGrid = noMinorGrid;
- }
-
- /**
- * Use this method to request MRTG-like graph (false by default)
- *
- * @param altYMrtg true, to create MRTG-like graph, false otherwise (default)
- */
- public void setAltYMrtg(boolean altYMrtg) {
- this.altYMrtg = altYMrtg;
- }
-
- /**
- * Computes Y range based on function absolute minimum and maximum
- * values. Default algorithm uses predefined set of ranges. This is
- * good in many cases but it fails miserably when you need to graph
- * something like 260 + 0.001 * sin(x). Default algorithm will use Y
- * range from 250 to 300 and on the graph you will see almost straight
- * line. With --alt-autoscale Y range will be from slightly less the
- * 260 - 0.001 to slightly more then 260 + 0.001 and periodic behavior
- * will be seen.
- *
- * @param altAutoscale true to request alternative autoscaling, false otherwise
- * (default).
- */
- public void setAltAutoscale(boolean altAutoscale) {
- this.altAutoscale = altAutoscale;
- }
-
- /**
- * Computes Y range based on function absolute minimum and maximum
- * values. Where setAltAutoscale(true) will modify both the absolute maximum AND
- * minimum values, this option will only affect the maximum value. The
- * minimum value, if not defined elsewhere, will be 0. This
- * option can be useful when graphing router traffic when the WAN line
- * uses compression, and thus the throughput may be higher than the
- * WAN line speed.
- *
- * @param altAutoscaleMax true to request alternative autoscaling, false
- * otherwise (default)
- */
- public void setAltAutoscaleMax(boolean altAutoscaleMax) {
- this.altAutoscaleMax = altAutoscaleMax;
- }
-
- /**
- * Sets the 10**unitsExponent scaling of the y-axis values. Normally
- * values will be scaled to the appropriate units (k, M, etc.). However
- * you may wish to display units always in k (Kilo, 10e3) even if
- * the data is in the M (Mega, 10e6) range for instance. Value should
- * be an integer which is a multiple of 3 between -18 and 18, inclu-
- * sive. It is the exponent on the units you which to use. For example,
- * use 3 to display the y-axis values in k (Kilo, 10e3, thou-
- * sands), use -6 to display the y-axis values in u (Micro, 10e-6,
- * millionths). Use a value of 0 to prevent any scaling of the y-axis
- * values.
- *
- * @param unitsExponent the 10**unitsExponent value for scaling y-axis values.
- */
- public void setUnitsExponent(int unitsExponent) {
- this.unitsExponent = unitsExponent;
- }
-
- /**
- * Sets the character width on the left side of the graph for
- * y-axis values.
- *
- * @param unitsLength Number of characters on the left side of the graphs
- * reserved for vertical axis labels.
- */
- public void setUnitsLength(int unitsLength) {
- this.unitsLength = unitsLength;
- }
-
- /**
- * Sets vertical label on the left side of the graph. This is normally used
- * to specify the units used.
- *
- * @param verticalLabel Vertical axis label
- */
- public void setVerticalLabel(String verticalLabel) {
- this.verticalLabel = verticalLabel;
- }
-
- /**
- * Sets width of the drawing area within the graph. This affects the total
- * size of the image.
- *
- * @param width Width of the drawing area.
- */
- public void setWidth(int width) {
- this.width = width;
- }
-
- /**
- * Sets height of the drawing area within the graph. This affects the total
- * size of the image.
- *
- * @param height Height of the drawing area.
- */
- public void setHeight(int height) {
- this.height = height;
- }
-
- /**
- * Creates interlaced GIF image (currently not supported,
- * method is present only for RRDTool comaptibility).
- *
- * @param interlaced true, if GIF image should be interlaced.
- */
- public void setInterlaced(boolean interlaced) {
- this.interlaced = interlaced;
- }
-
- /**
- * Creates additional image information.
- * After the image has been created, the graph function uses imageInfo
- * format string (printf-like) to create output similar to
- * the {@link #print(String, String, String)} function.
- * The format string is supplied with the following parameters:
- * filename, xsize and ysize (in that particular order).
- *
- * For example, in order to generate an IMG tag
- * suitable for including the graph into a web page, the command
- * would look like this:
- *
- * If you want to define an upper-limit which will not move in any
- * event you have to use {@link #setRigid(boolean)} method as well.
- *
- * @param maxValue Maximal value displayed on the graph.
- */
- public void setMaxValue(double maxValue) {
- this.maxValue = maxValue;
- }
-
- /**
- * Sets rigid boundaries mode. Normally JRObin will automatically expand
- * the lower and upper limit if the graph contains a value outside the
- * valid range. With the
- * Requires that the other datasource has already been defined otherwise it throws an exception
- * (we need to look at the existing data source to extract the required data)
- *
- * @param name - the new virtual datasource name
- * @param sourceName - the datasource from which to extract the percentile. Must be a previously
- * defined virtula datasource
- * @param percentile - the percentile to extract from the source datasource
- */
- public void datasource(String name, String sourceName, double percentile) {
- sources.add(new PercentileDef(name, sourceName, percentile));
- }
-
- /**
- * Creates a new static virtual datasource that performs a percentile calculation on an
- * another named datasource to yield a single value.
- *
- * Requires that the other datasource has already been defined otherwise it throws an exception
- * (we need to look at the existing data source to extract the required data)
- *
- * @param name - the new virtual datasource name
- * @param sourceName - the datasource from which to extract the percentile. Must be a previously
- * defined virtula datasource
- * @param percentile - the percentile to extract from the source datasource
- * @param includenan - whether to include NaNs in the percentile calculations.
- */
- public void datasource(String name, String sourceName, double percentile, boolean includenan) {
- sources.add(new PercentileDef(name, sourceName, percentile, includenan));
- }
-
- /**
- * Calculates the chosen consolidation function CF over the given datasource
- * and creates the result by using the given format string. In
- * the format string there should be a '%[l]f', '%[l]g' or '%[l]e' marker in
- * the place where the number should be printed.
- *
- * If an additional '%s' is found AFTER the marker, the value will be
- * scaled and an appropriate SI magnitude unit will be printed in
- * place of the '%s' marker. The scaling will take the '--base' argument
- * into consideration!
- *
- * If a '%S' is used instead of a '%s', then instead of calculating
- * the appropriate SI magnitude unit for this value, the previously
- * calculated SI magnitude unit will be used. This is useful if you
- * want all the values in a print statement to have the same SI magnitude
- * unit. If there was no previous SI magnitude calculation made,
- * then '%S' behaves like a '%s', unless the value is 0, in which case
- * it does not remember a SI magnitude unit and a SI magnitude unit
- * will only be calculated when the next '%s' is seen or the next '%S'
- * for a non-zero value.
- *
- * Print results are collected in the {@link RrdGraphInfo} object which is retrieved
- * from the {@link RrdGraph object} once the graph is created.
- *
- * @param srcName Virtual source name
- * @param consolFun Consolidation function to be applied to the source
- * @param format Format string (like "average = %10.3f %s")
- */
- public void print(String srcName, String consolFun, String format) {
- comments.add(new PrintText(srcName, consolFun, format, false));
- }
-
- /**
- * This method does basically the same thing as {@link #print(String, String, String)},
- * but the result is printed on the graph itself, below the chart area.
- *
- * @param srcName Virtual source name
- * @param consolFun Consolidation function to be applied to the source
- * @param format Format string (like "average = %10.3f %s")
- */
- public void gprint(String srcName, String consolFun, String format) {
- comments.add(new PrintText(srcName, consolFun, format, true));
- }
-
- /**
- * Comment to be printed on the graph.
- *
- * @param text Comment text
- */
- public void comment(String text) {
- comments.add(new CommentText(text));
- }
-
- /**
- * Draws a horizontal rule into the graph and optionally adds a legend
- *
- * @param value Position of the rule
- * @param color Rule color
- * @param legend Legend text. If null, legend text will be omitted.
- */
- public void hrule(double value, Paint color, String legend) {
- hrule(value, color, legend, 1.0F);
- }
-
- /**
- * Draws a horizontal rule into the graph and optionally adds a legend
- *
- * @param value Position of the rule
- * @param color Rule color
- * @param legend Legend text. If null, legend text will be omitted.
- * @param width Rule width
- */
- public void hrule(double value, Paint color, String legend, float width) {
- LegendText legendText = new LegendText(color, legend);
- comments.add(legendText);
- plotElements.add(new HRule(value, color, legendText, width));
- }
-
- /**
- * Draws a vertical rule into the graph and optionally adds a legend
- *
- * @param timestamp Position of the rule (seconds since epoch)
- * @param color Rule color
- * @param legend Legend text. Use null to omit the text.
- */
- public void vrule(long timestamp, Paint color, String legend) {
- vrule(timestamp, color, legend, 1.0F);
- }
-
- /**
- * Draws a vertical rule into the graph and optionally adds a legend
- *
- * @param timestamp Position of the rule (seconds since epoch)
- * @param color Rule color
- * @param legend Legend text. Use null to omit the text.
- * @param width Rule width
- */
- public void vrule(long timestamp, Paint color, String legend, float width) {
- LegendText legendText = new LegendText(color, legend);
- comments.add(legendText);
- plotElements.add(new VRule(timestamp, color, legendText, width));
- }
-
- /**
- * Plots requested data as a line, using the color and the line width specified.
- *
- * @param srcName Virtual source name
- * @param color Line color
- * @param legend Legend text
- * @param width Line width (default: 1.0F)
- */
- public void line(String srcName, Paint color, String legend, float width) {
- if (legend != null) {
- comments.add(new LegendText(color, legend));
- }
- plotElements.add(new Line(srcName, color, width));
- }
-
- /**
- * Plots requested data as a line, using the color specified. Line width is assumed to be
- * 1.0F.
- *
- * @param srcName Virtual source name
- * @param color Line color
- * @param legend Legend text
- */
- public void line(String srcName, Paint color, String legend) {
- line(srcName, color, legend, 1F);
- }
-
- /**
- * Plots requested data in the form of the filled area starting from zero,
- * using the color specified.
- *
- * @param srcName Virtual source name.
- * @param color Color of the filled area.
- * @param legend Legend text.
- */
- public void area(String srcName, Paint color, String legend) {
- area(srcName, color);
- if ((legend != null) && (legend.length() > 0)) {
- LegendText legendText = new LegendText(color, legend);
- comments.add(legendText);
- }
- }
-
- /**
- * Plots requested data in the form of the filled area starting from zero,
- * using the color specified.
- *
- * @param srcName Virtual source name.
- * @param color Color of the filled area.
- */
- public void area(String srcName, Paint color) {
- plotElements.add(new Area(srcName, color));
- }
-
- /**
- * Does the same as {@link #line(String, java.awt.Paint, String)},
- * but the graph gets stacked on top of the
- * previous LINE, AREA or STACK graph. Depending on the type of the
- * previous graph, the STACK will be either a LINE or an AREA. This
- * obviously implies that the first STACK must be preceded by an AREA
- * or LINE.
- *
- * Note, that when you STACK onto *UNKNOWN* data, JRobin will not
- * draw any graphics ... *UNKNOWN* is not zero.
- *
- * @param srcName Virtual source name
- * @param color Stacked graph color
- * @param legend Legend text
- * @throws RrdException Thrown if this STACK has no previously defined AREA, STACK or LINE
- * graph bellow it.
- */
- public void stack(String srcName, Paint color, String legend) throws RrdException {
- // find parent AREA or LINE
- SourcedPlotElement parent = null;
- for (int i = plotElements.size() - 1; i >= 0; i--) {
- PlotElement plotElement = plotElements.get(i);
- if (plotElement instanceof SourcedPlotElement) {
- parent = (SourcedPlotElement) plotElement;
- break;
- }
- }
- if (parent == null) {
- throw new RrdException("You have to stack graph onto something (line or area)");
- }
- else {
- LegendText legendText = new LegendText(color, legend);
- comments.add(legendText);
- plotElements.add(new Stack(parent, srcName, color));
- }
- }
-
- /**
- * Sets visibility of the X-axis grid.
- *
- * @param drawXGrid True if X-axis grid should be created (default), false otherwise.
- */
- public void setDrawXGrid(boolean drawXGrid) {
- this.drawXGrid = drawXGrid;
- }
-
- /**
- * Sets visibility of the Y-axis grid.
- *
- * @param drawYGrid True if Y-axis grid should be created (default), false otherwise.
- */
- public void setDrawYGrid(boolean drawYGrid) {
- this.drawYGrid = drawYGrid;
- }
-
- /**
- * Sets image quality. Relevant only for JPEG images.
- *
- * @param imageQuality (0F=worst, 1F=best).
- */
- public void setImageQuality(float imageQuality) {
- this.imageQuality = imageQuality;
- }
-
- /**
- * Controls if the chart area of the image should be antialiased or not.
- *
- * @param antiAliasing use true to turn antialiasing on, false to turn it off (default)
- */
- public void setAntiAliasing(boolean antiAliasing) {
- this.antiAliasing = antiAliasing;
- }
-
- /**
- * Shows or hides graph signature (gator) in the top right corner of the graph
- *
- * @param showSignature true, if signature should be seen (default), false otherwise
- */
- public void setShowSignature(boolean showSignature) {
- this.showSignature = showSignature;
- }
-
- /**
- * Sets first day of the week.
- *
- * @param firstDayOfWeek One of the following constants:
- * {@link RrdGraphConstants#MONDAY MONDAY},
- * {@link RrdGraphConstants#TUESDAY TUESDAY},
- * {@link RrdGraphConstants#WEDNESDAY WEDNESDAY},
- * {@link RrdGraphConstants#THURSDAY THURSDAY},
- * {@link RrdGraphConstants#FRIDAY FRIDAY},
- * {@link RrdGraphConstants#SATURDAY SATURDAY},
- * {@link RrdGraphConstants#SUNDAY SUNDAY}
- */
- public void setFirstDayOfWeek(int firstDayOfWeek) {
- this.firstDayOfWeek = firstDayOfWeek;
- }
-
- // helper methods
-
- int printStatementCount() {
- int count = 0;
- for (CommentText comment : comments) {
- if (comment instanceof PrintText) {
- if (comment.isPrint()) {
- count++;
- }
- }
- }
- return count;
- }
-
- boolean shouldPlot() {
- if (plotElements.size() > 0) {
- return true;
- }
- for (CommentText comment : comments) {
- if (comment.isValidGraphElement()) {
- return true;
- }
- }
- return false;
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/graph/RrdGraphDefTemplate.java b/apps/jrobin/java/src/org/jrobin/graph/RrdGraphDefTemplate.java
deleted file mode 100644
index 7b0c7f1c51..0000000000
--- a/apps/jrobin/java/src/org/jrobin/graph/RrdGraphDefTemplate.java
+++ /dev/null
@@ -1,982 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.graph;
-
-import org.jrobin.core.RrdException;
-import org.jrobin.core.Util;
-import org.jrobin.core.XmlTemplate;
-import org.w3c.dom.Node;
-import org.xml.sax.InputSource;
-
-import java.awt.*;
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Class used to create an arbitrary number of RrdGraphDef (graph definition) objects
- * from a single XML template. XML template can be supplied as an XML InputSource,
- * XML file or XML formatted string.
- *
- * Here is an example of a properly formatted XML template with all available options in it
- * (unwanted options can be removed/ignored):
- *
- *
- *
- * Typical usage scenario:
- *
- *
+ *
+ * WARNING: So far, this class cannot handle NaN datasource values
+ * (an exception will be thrown by the constructor). Future releases might change this.
+ */
+public class CubicSplineInterpolator extends Plottable {
+ private double[] x;
+ private double[] y;
+
+ // second derivates come here
+ private double[] y2;
+
+ // internal spline variables
+ private int n, klo, khi;
+
+ /**
+ * Creates cubic spline interpolator from arrays of timestamps and corresponding
+ * datasource values.
+ *
+ * @param timestamps timestamps in seconds
+ * @param values corresponding datasource values
+ * @throws java.lang.IllegalArgumentException Thrown if supplied arrays do not contain at least 3 values, or if
+ * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
+ */
+ public CubicSplineInterpolator(long[] timestamps, double[] values) {
+ this.x = new double[timestamps.length];
+ for (int i = 0; i < timestamps.length; i++) {
+ this.x[i] = timestamps[i];
+ }
+ this.y = values;
+ validate();
+ spline();
+ }
+
+ /**
+ * Creates cubic spline interpolator from arrays of Date objects and corresponding
+ * datasource values.
+ *
+ * @param dates Array of Date objects
+ * @param values corresponding datasource values
+ * @throws java.lang.IllegalArgumentException Thrown if supplied arrays do not contain at least 3 values, or if
+ * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
+ */
+ public CubicSplineInterpolator(Date[] dates, double[] values) {
+ this.x = new double[dates.length];
+ for (int i = 0; i < dates.length; i++) {
+ this.x[i] = Util.getTimestamp(dates[i]);
+ }
+ this.y = values;
+ validate();
+ spline();
+ }
+
+ /**
+ * Creates cubic spline interpolator from arrays of GregorianCalendar objects and corresponding
+ * datasource values.
+ *
+ * @param dates Array of GregorianCalendar objects
+ * @param values corresponding datasource values
+ * @throws java.lang.IllegalArgumentException Thrown if supplied arrays do not contain at least 3 values, or if
+ * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
+ */
+ public CubicSplineInterpolator(Calendar[] dates, double[] values) {
+ this.x = new double[dates.length];
+ for (int i = 0; i < dates.length; i++) {
+ this.x[i] = Util.getTimestamp(dates[i]);
+ }
+ this.y = values;
+ validate();
+ spline();
+ }
+
+ /**
+ * Creates cubic spline interpolator for an array of 2D-points.
+ *
+ * @param x x-axis point coordinates
+ * @param y y-axis point coordinates
+ * @throws java.lang.IllegalArgumentException Thrown if supplied arrays do not contain at least 3 values, or if
+ * timestamps are not ordered, or array lengths are not equal, or some datasource value is NaN.
+ */
+ public CubicSplineInterpolator(double[] x, double[] y) {
+ this.x = x;
+ this.y = y;
+ validate();
+ spline();
+ }
+
+ private void validate() {
+ boolean ok = true;
+ if (x.length != y.length || x.length < 3) {
+ ok = false;
+ }
+ for (int i = 0; i < x.length - 1 && ok; i++) {
+ if (x[i] >= x[i + 1] || Double.isNaN(y[i])) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ throw new IllegalArgumentException("Invalid plottable data supplied");
+ }
+ }
+
+ private void spline() {
+ n = x.length;
+ y2 = new double[n];
+ double[] u = new double[n - 1];
+ y2[0] = y2[n - 1] = 0.0;
+ u[0] = 0.0; // natural spline
+ for (int i = 1; i <= n - 2; i++) {
+ double sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
+ double p = sig * y2[i - 1] + 2.0;
+ y2[i] = (sig - 1.0) / p;
+ u[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
+ u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
+ }
+ for (int k = n - 2; k >= 0; k--) {
+ y2[k] = y2[k] * y2[k + 1] + u[k];
+ }
+ // prepare everything for getValue()
+ klo = 0;
+ khi = n - 1;
+ }
+
+ /**
+ * Calculates spline-interpolated y-value for the corresponding x-value. Call
+ * this if you need spline-interpolated values in your code.
+ *
+ * @param xval x-value
+ * @return inteprolated y-value
+ */
+ public double getValue(double xval) {
+ if (xval < x[0] || xval > x[n - 1]) {
+ return Double.NaN;
+ }
+ if (xval < x[klo] || xval > x[khi]) {
+ // out of bounds
+ klo = 0;
+ khi = n - 1;
+ }
+ while (khi - klo > 1) {
+ // find bounding interval using bisection method
+ int k = (khi + klo) / 2;
+ if (x[k] > xval) {
+ khi = k;
+ }
+ else {
+ klo = k;
+ }
+ }
+ double h = x[khi] - x[klo];
+ double a = (x[khi] - xval) / h;
+ double b = (xval - x[klo]) / h;
+ return a * y[klo] + b * y[khi] +
+ ((a * a * a - a) * y2[klo] + (b * b * b - b) * y2[khi]) * (h * h) / 6.0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Method overridden from the base class. This method will be called by the framework. Call
+ * this method only if you need spline-interpolated values in your code.
+ */
+ public double getValue(long timestamp) {
+ return getValue((double)timestamp);
+ }
+
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/data/DataProcessor.java b/apps/jrobin/java/src/org/rrd4j/data/DataProcessor.java
new file mode 100644
index 0000000000..7780f782c7
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/data/DataProcessor.java
@@ -0,0 +1,901 @@
+package org.rrd4j.data;
+
+import org.rrd4j.ConsolFun;
+import org.rrd4j.core.FetchData;
+import org.rrd4j.core.FetchRequest;
+import org.rrd4j.core.RrdBackendFactory;
+import org.rrd4j.core.RrdDb;
+import org.rrd4j.core.RrdDbPool;
+import org.rrd4j.core.Util;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+
+/**
+ * Class which should be used for all calculations based on the data fetched from RRD files. This class
+ * supports ordinary DEF datasources (defined in RRD files), CDEF datasources (RPN expressions evaluation),
+ * SDEF (static datasources - extension of Rrd4j) and PDEF (plottables, see
+ * {@link org.rrd4j.data.Plottable Plottable} for more information. Typical class usage: Sets the number of pixels (target graph width). This number is used only to calculate pixel coordinates
+ * for Rrd4j graphs (methods {@link #getValuesPerPixel(String)} and {@link #getTimestampsPerPixel()}),
+ * but has influence neither on datasource values calculated with the
+ * {@link #processData()} method nor on aggregated values returned from {@link #getAggregates(String)}
+ * and similar methods. In other words, aggregated values will not change once you decide to change
+ * the dimension of your graph. Roughly corresponds to the --step option in RRDTool's graph/xport commands. Here is an explanation borrowed
+ * from RRDTool: "By default rrdgraph calculates the width of one pixel in the time
+ * domain and tries to get data at that resolution from the RRD. With
+ * this switch you can override this behavior. If you want rrdgraph to
+ * get data at 1 hour resolution from the RRD, then you can set the
+ * step to 3600 seconds. Note, that a step smaller than 1 pixel will
+ * be silently ignored." I think this option is not that useful, but it's here just for compatibility.
+ *
+ * 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.
+ *
+ * Read more about this topic at
+ * Rednet or
+ * Bytemark.
+ *
+ * @param sourceName Datasource name
+ * @return 95th percentile of fetched source values
+ * @deprecated Use {@link Variable} based method instead.
+ */
+ @Deprecated
+ public double get95Percentile(String sourceName) {
+ return getPercentile(sourceName);
+ }
+
+ /**
+ * Used by ISPs which charge for bandwidth utilization on a "95th percentile" basis.
+ *
+ * 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.
+ *
+ * Read more about this topic at
+ * Rednet or
+ * Bytemark.
+ *
+ * @param sourceName Datasource name
+ * @return 95th percentile of fetched source values
+ * @deprecated Use {@link Variable} based method instead.
+ */
+ @Deprecated
+ public double getPercentile(String sourceName) {
+ 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
+ * @deprecated Use {@link Variable} based method instead.
+ */
+ @Deprecated
+ public double getPercentile(String sourceName, double percentile) {
+ if (percentile <= 0.0 || percentile > 100.0) {
+ throw new IllegalArgumentException("Invalid percentile [" + percentile + "], should be between 0 and 100");
+ }
+ Source source = getSource(sourceName);
+ return source.getPercentile(tStart, tEnd, percentile);
+ }
+
+ /**
+ * Returns array of datasource names defined in this DataProcessor.
+ *
+ * @return array of datasource names
+ */
+ public String[] getSourceNames() {
+ return sources.keySet().toArray(new String[sources.keySet().size()]);
+ }
+
+ /**
+ * Returns an array of all datasource values for all datasources. Each row in this two-dimensional
+ * array represents an array of calculated values for a single datasource. The order of rows is the same
+ * as the order in which datasources were added to this DataProcessor object.
+ *
+ * @return All datasource values for all datasources. The first index is the index of the datasource,
+ * the second index is the index of the datasource value. The number of datasource values is equal
+ * to the number of timestamps returned with {@link #getTimestamps()} method.
+ * @throws java.lang.IllegalArgumentException Thrown if invalid datasource name is specified,
+ * or if datasource values are not yet calculated (method {@link #processData()}
+ * was not called)
+ */
+ public double[][] getValues() {
+ String[] names = getSourceNames();
+ double[][] values = new double[names.length][];
+ for (int i = 0; i < names.length; i++) {
+ values[i] = getValues(names[i]);
+ }
+ return values;
+ }
+
+ Source getSource(String sourceName) {
+ Source source = sources.get(sourceName);
+ if (source != null) {
+ return source;
+ }
+ throw new IllegalArgumentException("Unknown source: " + sourceName);
+ }
+
+ /////////////////////////////////////////////////////////////////
+ // DATASOURCE DEFINITIONS
+ /////////////////////////////////////////////////////////////////
+
+ /**
+ * Adds a custom, {@link org.rrd4j.data.Plottable plottable} datasource (PDEF).
+ * The datapoints should be made available by a class extending
+ * {@link org.rrd4j.data.Plottable Plottable} class.
+ *
+ * @param name source name.
+ * @param plottable class that extends Plottable class and is suited for graphing.
+ */
+ public void addDatasource(String name, Plottable plottable) {
+ PDef pDef = new PDef(name, plottable);
+ sources.put(name, pDef);
+ }
+
+ /**
+ * Adds complex source (CDEF).
+ * Complex sources are evaluated using the supplied
+ * Rrd4j does not force you to specify at least one simple source name as RRDTool.
+ *
+ * For more details on RPN see RRDTool's
+ *
+ * rrdgraph man page.
+ *
+ * @param name source name.
+ * @param rpnExpression RPN expression containing comma delimited simple and complex
+ * source names, RPN constants, functions and operators.
+ */
+ public void addDatasource(String name, String rpnExpression) {
+ CDef cDef = new CDef(name, rpnExpression);
+ sources.put(name, cDef);
+ }
+
+ /**
+ * Adds static source (SDEF). Static sources are the result of a consolidation function applied
+ * to any other source that has been defined previously.
+ *
+ * @param name source name.
+ * @param defName Name of the datasource to calculate the value from.
+ * @param consolFun Consolidation function to use for value calculation
+ * @deprecated Use {@link Variable} based method instead.
+ */
+ @Deprecated
+ public void addDatasource(String name, String defName, ConsolFun consolFun) {
+ VDef sDef = new VDef(name, defName, consolFun.getVariable());
+ sources.put(name, sDef);
+ }
+
+ /**
+ * Creates a datasource that performs a percentile calculation on an
+ * another named datasource to yield a single value.
+ *
+ * Requires that the other datasource has already been defined; otherwise, it'll
+ * end up with no data
+ *
+ * @param name - the new virtual datasource name
+ * @param sourceName - the datasource from which to extract the percentile. Must be a previously
+ * defined virtual datasource
+ * @param percentile - the percentile to extract from the source datasource
+ * @deprecated Use {@link Variable} based method instead.
+ */
+ @Deprecated
+ public void addDatasource(String name, String sourceName, double percentile) {
+ sources.put(name, new VDef(name, sourceName, new Variable.PERCENTILE(percentile)));
+ }
+
+ /**
+ * Creates a datasource that performs a variable calculation on an
+ * another named datasource to yield a single combined timestampe/value.
+ *
+ * Requires that the other datasource has already been defined; otherwise, it'll
+ * end up with no data
+ *
+ * @param name - the new virtual datasource name
+ * @param defName - the datasource from which to extract the percentile. Must be a previously
+ * defined virtual datasource
+ * @param var - a new instance of a Variable used to do the calculation
+ */
+ public void addDatasource(String name, String defName, Variable var) {
+ VDef sDef = new VDef(name, defName, var);
+ sources.put(name, sDef);
+ }
+
+ /**
+ * Adds simple datasource (DEF). Simple source Adds simple source (DEF). Source Adds simple source (DEF). Source Class used to interpolate datasource values from the collection of (timestamp, values)
+ * points. This class is suitable for linear interpolation only. Interpolation algorithm returns different values based on the value passed to
+ * {@link #setInterpolationMethod(Method) setInterpolationMethod()}. If not set, interpolation
+ * method defaults to standard linear interpolation ({@link org.rrd4j.data.LinearInterpolator.Method#LINEAR}).
+ * Interpolation method handles NaN datasource
+ * values gracefully. Sets interpolation method to be used. Suppose that we have two timestamp/value pairs: If not set, interpolation method defaults to The fourth available interpolation method is INTERPOLATE_REGRESSION. This method uses
+ * simple linear regression to interpolate supplied data with a simple straight line which does not
+ * necessarily pass through all data points. The slope of the best-fit line will be chosen so that the
+ * total square distance of real data points from from the best-fit line is at minimum. This method is deprecated, one should use {@link #setInterpolationMethod(Method) setInterpolationMethod()} instead. The full explanation of this interpolation method can be found
+ * here. Sets interpolation method to be used. Suppose that we have two timestamp/value pairs: If not set, interpolation method defaults to The fourth available interpolation method is REGRESSION. This method uses
+ * simple linear regression to interpolate supplied data with a simple straight line which does not
+ * necessarily pass through all data points. The slope of the best-fit line will be chosen so that the
+ * total square distance of real data points from from the best-fit line is at minimum. The full explanation of this interpolation method can be found
+ * here. calculate. If you wish to use a custom datasource in a graph, you should create a class implementing this interface
+ * that represents that datasource, and then pass this class on to the RrdGraphDef. loadImage. Creates graph from the corresponding {@link org.rrd4j.graph.RrdGraphDef} object. The graph will be created using customs {@link javax.imageio.ImageWriter} and {@link javax.imageio.ImageWriteParam} given. The ImageWriter type and ImageWriteParam settings have priority other the RrdGraphDef settings.
+
+ * @param gdef Graph definition
+ * @param writer
+ * @param param
+ * @throws IOException Thrown in case of I/O error
+ * @since 3.5
+ */
+ public RrdGraph(RrdGraphDef gdef, ImageWriter writer, ImageWriteParam param) throws IOException {
+ this.gdef = gdef;
+ signature = gdef.getSignature();
+ im = new ImageParameters();
+ worker = new ImageWorker(1, 1); // Dummy worker, just to start with something
+ this.writer = writer;
+ this.param = param;
+ try {
+ createGraph();
+ }
+ finally {
+ worker.dispose();
+ worker = null;
+ dproc = null;
+ }
+ }
+
+ /**
+ * Returns complete graph information in a single object.
+ *
+ * @return Graph information (width, height, filename, image bytes, etc...)
+ */
+ public RrdGraphInfo getRrdGraphInfo() {
+ return info;
+ }
+
+ private ImageWriteParam getImageParams() {
+ ImageWriteParam iwp = writer.getDefaultWriteParam();
+ ImageWriterSpi imgProvider = writer.getOriginatingProvider();
+ //If lossy compression, use the quality
+ if (! imgProvider.isFormatLossless()) {
+ iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+ iwp.setCompressionQuality(gdef.imageQuality);
+ }
+
+ if (iwp.canWriteProgressive()) {
+ iwp.setProgressiveMode(gdef.interlaced ? ImageWriteParam.MODE_DEFAULT:ImageWriteParam.MODE_DISABLED);
+ }
+ return iwp;
+ }
+
+ private void createGraph() throws IOException {
+ boolean lazy = lazyCheck();
+ if (!lazy || gdef.printStatementCount() != 0) {
+ fetchData();
+ resolveTextElements();
+ if (gdef.shouldPlot() && !lazy) {
+ calculatePlotValues();
+ findMinMaxValues();
+ identifySiUnit();
+ expandValueRange();
+ removeOutOfRangeRules();
+ removeOutOfRangeSpans();
+ initializeLimits();
+ placeLegends();
+ createImageWorker();
+ drawBackground();
+ drawData();
+ drawGrid();
+ drawAxis();
+ drawText();
+ drawLegend();
+ drawRules();
+ drawSpans();
+ gator();
+ drawOverlay();
+ saveImage();
+ }
+ }
+ collectInfo();
+ }
+
+ private void collectInfo() {
+ info.filename = gdef.filename;
+ info.width = im.xgif;
+ info.height = im.ygif;
+ for (CommentText comment : gdef.comments) {
+ if (comment instanceof PrintText) {
+ PrintText pt = (PrintText) comment;
+ if (pt.isPrint()) {
+ info.addPrintLine(pt.resolvedText);
+ }
+ }
+ }
+ if (gdef.imageInfo != null) {
+ info.imgInfo = Util.sprintf(gdef.locale, gdef.imageInfo, gdef.filename, im.xgif, im.ygif);
+ }
+ }
+
+ private void saveImage() throws IOException {
+ if (! RrdGraphConstants.IN_MEMORY_IMAGE.equals(gdef.filename)) {
+ info.stream = worker.saveImage(gdef.filename, writer, param);
+ }
+ else {
+ info.stream = worker.getImageBytes(writer, param);
+ }
+ }
+
+ private void drawOverlay() throws IOException {
+ if (gdef.overlayImage != null) {
+ worker.loadImage(gdef.overlayImage);
+ }
+ }
+
+ private void gator() {
+ if (!gdef.onlyGraph && gdef.showSignature) {
+ worker.setTextAntiAliasing(gdef.textAntiAliasing);
+ Font font = gdef.getFont(FONTTAG_WATERMARK);
+ int x = (int) (im.xgif - 2 - worker.getFontAscent(font));
+ int y = 4;
+ worker.transform(x, y, Math.PI / 2);
+ worker.drawString(signature, 0, 0, font, Color.LIGHT_GRAY);
+ worker.reset();
+ worker.setTextAntiAliasing(false);
+ }
+ }
+
+ private void drawRules() {
+ worker.clip(im.xorigin + 1, im.yorigin - gdef.height - 1, gdef.width - 1, gdef.height + 2);
+ for (PlotElement pe : gdef.plotElements) {
+ if (pe instanceof HRule) {
+ HRule hr = (HRule) pe;
+ if (hr.value >= im.minval && hr.value <= im.maxval) {
+ int y = mapper.ytr(hr.value);
+ worker.drawLine(im.xorigin, y, im.xorigin + im.xsize, y, hr.color, hr.stroke);
+ }
+ }
+ else if (pe instanceof VRule) {
+ VRule vr = (VRule) pe;
+ if (vr.timestamp >= im.start && vr.timestamp <= im.end) {
+ int x = mapper.xtr(vr.timestamp);
+ worker.drawLine(x, im.yorigin, x, im.yorigin - im.ysize, vr.color, vr.stroke);
+ }
+ }
+ }
+ worker.reset();
+ }
+
+ private void drawSpans() {
+ worker.clip(im.xorigin + 1, im.yorigin - gdef.height - 1, gdef.width - 1, gdef.height + 2);
+ for (PlotElement pe : gdef.plotElements) {
+ if (pe instanceof HSpan) {
+ HSpan hr = (HSpan) pe;
+ int ys = mapper.ytr(hr.start);
+ int ye = mapper.ytr(hr.end);
+ int height = ys - ye;
+ worker.fillRect(im.xorigin, ys - height, im.xsize, height, hr.color);
+ }
+ else if (pe instanceof VSpan) {
+ VSpan vr = (VSpan) pe;
+ int xs = mapper.xtr(vr.start);
+ int xe = mapper.xtr(vr.end);
+ worker.fillRect(xs, im.yorigin - im.ysize, xe - xs, im.ysize, vr.color);
+ }
+ }
+ worker.reset();
+ }
+
+ private void drawText() {
+ if (!gdef.onlyGraph) {
+ worker.setTextAntiAliasing(gdef.textAntiAliasing);
+ if (gdef.title != null) {
+ int x = im.xgif / 2 - (int) (worker.getStringWidth(gdef.title, gdef.getFont(FONTTAG_TITLE)) / 2);
+ int y = PADDING_TOP + (int) worker.getFontAscent(gdef.getFont(FONTTAG_TITLE));
+ worker.drawString(gdef.title, x, y, gdef.getFont(FONTTAG_TITLE), gdef.getColor(ElementsNames.font));
+ }
+ if (gdef.verticalLabel != null) {
+ int x = PADDING_LEFT;
+ int y = im.yorigin - im.ysize / 2 + (int) worker.getStringWidth(gdef.verticalLabel, gdef.getFont(FONTTAG_UNIT)) / 2;
+ int ascent = (int) worker.getFontAscent(gdef.getFont(FONTTAG_UNIT));
+ worker.transform(x, y, -Math.PI / 2);
+ worker.drawString(gdef.verticalLabel, 0, ascent, gdef.getFont(FONTTAG_UNIT), gdef.getColor(ElementsNames.font));
+ worker.reset();
+ }
+ worker.setTextAntiAliasing(false);
+ }
+ }
+
+ private void drawGrid() {
+ if (!gdef.onlyGraph) {
+ worker.setTextAntiAliasing(gdef.textAntiAliasing);
+ Paint shade1 = gdef.getColor(ElementsNames.shadea);
+ Paint shade2 = gdef.getColor(ElementsNames.shadeb);
+ Stroke borderStroke = new BasicStroke(1);
+ worker.drawLine(0, 0, im.xgif - 1, 0, shade1, borderStroke);
+ worker.drawLine(1, 1, im.xgif - 2, 1, shade1, borderStroke);
+ worker.drawLine(0, 0, 0, im.ygif - 1, shade1, borderStroke);
+ worker.drawLine(1, 1, 1, im.ygif - 2, shade1, borderStroke);
+ worker.drawLine(im.xgif - 1, 0, im.xgif - 1, im.ygif - 1, shade2, borderStroke);
+ worker.drawLine(0, im.ygif - 1, im.xgif - 1, im.ygif - 1, shade2, borderStroke);
+ worker.drawLine(im.xgif - 2, 1, im.xgif - 2, im.ygif - 2, shade2, borderStroke);
+ worker.drawLine(1, im.ygif - 2, im.xgif - 2, im.ygif - 2, shade2, borderStroke);
+ if (gdef.drawXGrid) {
+ new TimeAxis(this).draw();
+ }
+ if (gdef.drawYGrid) {
+ boolean ok;
+ if (gdef.altYMrtg) {
+ ok = new ValueAxisMrtg(this).draw();
+ }
+ else if (gdef.logarithmic) {
+ ok = new ValueAxisLogarithmic(this).draw();
+ }
+ else {
+ ok = new ValueAxis(this).draw();
+ }
+ if (!ok) {
+ String msg = "No Data Found";
+ worker.drawString(msg,
+ im.xgif / 2 - (int) worker.getStringWidth(msg, gdef.getFont(FONTTAG_TITLE)) / 2,
+ (2 * im.yorigin - im.ysize) / 2,
+ gdef.getFont(FONTTAG_TITLE), gdef.getColor(ElementsNames.font));
+ }
+ }
+ worker.setTextAntiAliasing(false);
+ }
+ }
+
+ private void drawData() {
+ worker.setAntiAliasing(gdef.antiAliasing);
+ worker.clip(im.xorigin, im.yorigin - gdef.height - 1, gdef.width, gdef.height + 2);
+ double areazero = mapper.ytr((im.minval > 0.0) ? im.minval : (im.maxval < 0.0) ? im.maxval : 0.0);
+ double[] x = gdef.downsampler == null ? xtr(dproc.getTimestamps()) : null;
+ double[] lastY = null;
+ // draw line, area and stack
+ for (PlotElement plotElement : gdef.plotElements) {
+ if (plotElement instanceof SourcedPlotElement) {
+ SourcedPlotElement source = (SourcedPlotElement) plotElement;
+ double[] y;
+ if (gdef.downsampler != null) {
+ DataSet set = gdef.downsampler.downsize(dproc.getTimestamps(), source.getValues());
+ x = xtr(set.timestamps);
+ y = ytr(set.values);
+ } else {
+ y = ytr(source.getValues());
+ }
+ if (Line.class.isAssignableFrom(source.getClass())) {
+ worker.drawPolyline(x, y, source.color, ((Line)source).stroke );
+ }
+ else if (Area.class.isAssignableFrom(source.getClass())) {
+ if(source.parent == null) {
+ worker.fillPolygon(x, areazero, y, source.color);
+ }
+ else {
+ worker.fillPolygon(x, lastY, y, source.color);
+ worker.drawPolyline(x, lastY, source.getParentColor(), new BasicStroke(0));
+ }
+ }
+ else if (source instanceof Stack) {
+ Stack stack = (Stack) source;
+ float width = stack.getParentLineWidth();
+ if (width >= 0F) {
+ // line
+ worker.drawPolyline(x, y, stack.color, new BasicStroke(width));
+ }
+ else {
+ // area
+ worker.fillPolygon(x, lastY, y, stack.color);
+ worker.drawPolyline(x, lastY, stack.getParentColor(), new BasicStroke(0));
+ }
+ }
+ else {
+ // should not be here
+ throw new IllegalStateException("Unknown plot source: " + source.getClass().getName());
+ }
+ lastY = y;
+ }
+ }
+ worker.reset();
+ worker.setAntiAliasing(false);
+ }
+
+ private void drawAxis() {
+ if (!gdef.onlyGraph) {
+ Paint gridColor = gdef.getColor(ElementsNames.grid);
+ Paint xaxisColor = gdef.getColor(ElementsNames.xaxis);
+ Paint yaxisColor = gdef.getColor(ElementsNames.yaxis);
+ Paint arrowColor = gdef.getColor(ElementsNames.arrow);
+ Stroke stroke = new BasicStroke(1);
+ worker.drawLine(im.xorigin + im.xsize, im.yorigin, im.xorigin + im.xsize, im.yorigin - im.ysize,
+ gridColor, stroke);
+ worker.drawLine(im.xorigin, im.yorigin - im.ysize, im.xorigin + im.xsize, im.yorigin - im.ysize,
+ gridColor, stroke);
+ worker.drawLine(im.xorigin - 4, im.yorigin, im.xorigin + im.xsize + 4, im.yorigin,
+ xaxisColor, stroke);
+ worker.drawLine(im.xorigin, im.yorigin + 4, im.xorigin, im.yorigin - im.ysize - 4,
+ yaxisColor, stroke);
+ //Do X axis arrow
+ double[] Xarrow_x = {
+ im.xorigin + im.xsize + 4,
+ im.xorigin + im.xsize + 9,
+ im.xorigin + im.xsize + 4,
+ };
+ double[] Xarrow_y = {
+ im.yorigin - 3,
+ im.yorigin + 0,
+ im.yorigin + 3,
+ };
+ worker.fillPolygon(Xarrow_x, im.yorigin + 3.0, Xarrow_y, arrowColor);
+
+ //Do y axis arrow
+ double[] Yarrow_x = {
+ im.xorigin - 3,
+ im.xorigin,
+ im.xorigin + 3,
+ };
+ double[] Yarrow_y = {
+ im.yorigin - im.ysize - 4,
+ im.yorigin - im.ysize - 9,
+ im.yorigin - im.ysize - 4,
+ };
+ worker.fillPolygon(Yarrow_x, im.yorigin - im.ysize - 4.0, Yarrow_y, arrowColor);
+ }
+ }
+
+ private void drawBackground() throws IOException {
+ worker.fillRect(0, 0, im.xgif, im.ygif, gdef.getColor(ElementsNames.back));
+ if (gdef.backgroundImage != null) {
+ worker.loadImage(gdef.backgroundImage);
+ }
+ worker.fillRect(im.xorigin, im.yorigin - im.ysize, im.xsize, im.ysize, gdef.getColor(ElementsNames.canvas));
+ }
+
+ private void createImageWorker() {
+ worker.resize(im.xgif, im.ygif);
+ }
+
+ private void placeLegends() {
+ if (!gdef.noLegend && !gdef.onlyGraph) {
+ int border = (int) (getFontCharWidth(FontTag.LEGEND) * PADDING_LEGEND);
+ LegendComposer lc = new LegendComposer(this, border, im.ygif, im.xgif - 2 * border);
+ im.ygif = lc.placeComments() + PADDING_BOTTOM;
+ }
+ }
+
+ private void initializeLimits() {
+ im.xsize = gdef.width;
+ im.ysize = gdef.height;
+ im.unitslength = gdef.unitsLength;
+
+ if (gdef.onlyGraph) {
+ im.xorigin = 0;
+ }
+ else {
+ im.xorigin = (int) (PADDING_LEFT + im.unitslength * getFontCharWidth(FontTag.UNIT));
+ }
+
+ if (!gdef.onlyGraph && gdef.verticalLabel != null) {
+ im.xorigin += getFontHeight(FONTTAG_UNIT);
+ }
+
+ if (gdef.onlyGraph) {
+ im.yorigin = im.ysize;
+ }
+ else {
+ im.yorigin = PADDING_TOP + im.ysize;
+ }
+
+ mapper = new Mapper(this);
+
+ if (!gdef.onlyGraph && gdef.title != null) {
+ im.yorigin += getFontHeight(FONTTAG_TITLE) + PADDING_TITLE;
+ }
+
+ if (gdef.onlyGraph) {
+ im.xgif = im.xsize;
+ im.ygif = im.yorigin;
+ }
+ else {
+ im.xgif = PADDING_RIGHT + im.xsize + im.xorigin;
+ im.ygif = im.yorigin + (int) (PADDING_PLOT * getFontHeight(FONTTAG_DEFAULT));
+ }
+ }
+
+ private void removeOutOfRangeRules() {
+ for (PlotElement plotElement : gdef.plotElements) {
+ if (plotElement instanceof HRule) {
+ ((HRule) plotElement).setLegendVisibility(im.minval, im.maxval, gdef.forceRulesLegend);
+ }
+ else if (plotElement instanceof VRule) {
+ ((VRule) plotElement).setLegendVisibility(im.start, im.end, gdef.forceRulesLegend);
+ }
+ }
+ }
+
+ private void removeOutOfRangeSpans() {
+ for (PlotElement plotElement : gdef.plotElements) {
+ if (plotElement instanceof HSpan) {
+ ((HSpan) plotElement).setLegendVisibility(im.minval, im.maxval, gdef.forceRulesLegend);
+ }
+ else if (plotElement instanceof VSpan) {
+ ((VSpan) plotElement).setLegendVisibility(im.start, im.end, gdef.forceRulesLegend);
+ }
+ }
+ }
+
+ private void expandValueRange() {
+ im.ygridstep = (gdef.valueAxisSetting != null) ? gdef.valueAxisSetting.gridStep : Double.NaN;
+ im.ylabfact = (gdef.valueAxisSetting != null) ? gdef.valueAxisSetting.labelFactor : 0;
+ if (!gdef.rigid && !gdef.logarithmic) {
+ double scaled_min, scaled_max, adj;
+ if (Double.isNaN(im.ygridstep)) {
+ if (gdef.altYMrtg) { /* mrtg */
+ im.decimals = Math.ceil(Math.log10(Math.max(Math.abs(im.maxval), Math.abs(im.minval))));
+ im.quadrant = 0;
+ if (im.minval < 0) {
+ im.quadrant = 2;
+ if (im.maxval <= 0) {
+ im.quadrant = 4;
+ }
+ }
+ switch (im.quadrant) {
+ case 2:
+ im.scaledstep = Math.ceil(50 * Math.pow(10, -(im.decimals)) * Math.max(Math.abs(im.maxval),
+ Math.abs(im.minval))) * Math.pow(10, im.decimals - 2);
+ scaled_min = -2 * im.scaledstep;
+ scaled_max = 2 * im.scaledstep;
+ break;
+ case 4:
+ im.scaledstep = Math.ceil(25 * Math.pow(10,
+ -(im.decimals)) * Math.abs(im.minval)) * Math.pow(10, im.decimals - 2);
+ scaled_min = -4 * im.scaledstep;
+ scaled_max = 0;
+ break;
+ default: /* quadrant 0 */
+ im.scaledstep = Math.ceil(25 * Math.pow(10, -(im.decimals)) * im.maxval) *
+ Math.pow(10, im.decimals - 2);
+ scaled_min = 0;
+ scaled_max = 4 * im.scaledstep;
+ break;
+ }
+ im.minval = scaled_min;
+ im.maxval = scaled_max;
+ }
+ else if (gdef.altAutoscale || (gdef.altAutoscaleMin && gdef.altAutoscaleMax)) {
+ /* measure the amplitude of the function. Make sure that
+ graph boundaries are slightly higher then max/min vals
+ so we can see amplitude on the graph */
+ double delt, fact;
+
+ delt = im.maxval - im.minval;
+ adj = delt * 0.1;
+ fact = 2.0 * Math.pow(10.0,
+ Math.floor(Math.log10(Math.max(Math.abs(im.minval), Math.abs(im.maxval)))) - 2);
+ if (delt < fact) {
+ adj = (fact - delt) * 0.55;
+ }
+ im.minval -= adj;
+ im.maxval += adj;
+ }
+ else if (gdef.altAutoscaleMin) {
+ /* measure the amplitude of the function. Make sure that
+ graph boundaries are slightly lower than min vals
+ so we can see amplitude on the graph */
+ adj = (im.maxval - im.minval) * 0.1;
+ im.minval -= adj;
+ }
+ else if (gdef.altAutoscaleMax) {
+ /* measure the amplitude of the function. Make sure that
+ graph boundaries are slightly higher than max vals
+ so we can see amplitude on the graph */
+ adj = (im.maxval - im.minval) * 0.1;
+ im.maxval += adj;
+ }
+ else {
+ scaled_min = im.minval / im.magfact;
+ scaled_max = im.maxval / im.magfact;
+ for (int i = 1; SENSIBLE_VALUES[i] > 0; i++) {
+ if (SENSIBLE_VALUES[i - 1] >= scaled_min && SENSIBLE_VALUES[i] <= scaled_min) {
+ im.minval = SENSIBLE_VALUES[i] * im.magfact;
+ }
+ if (-SENSIBLE_VALUES[i - 1] <= scaled_min && -SENSIBLE_VALUES[i] >= scaled_min) {
+ im.minval = -SENSIBLE_VALUES[i - 1] * im.magfact;
+ }
+ if (SENSIBLE_VALUES[i - 1] >= scaled_max && SENSIBLE_VALUES[i] <= scaled_max) {
+ im.maxval = SENSIBLE_VALUES[i - 1] * im.magfact;
+ }
+ if (-SENSIBLE_VALUES[i - 1] <= scaled_max && -SENSIBLE_VALUES[i] >= scaled_max) {
+ im.maxval = -SENSIBLE_VALUES[i] * im.magfact;
+ }
+ }
+ }
+ }
+ else {
+ im.minval = (double) im.ylabfact * im.ygridstep *
+ Math.floor(im.minval / ((double) im.ylabfact * im.ygridstep));
+ im.maxval = (double) im.ylabfact * im.ygridstep *
+ Math.ceil(im.maxval / ((double) im.ylabfact * im.ygridstep));
+ }
+
+ }
+ }
+
+ private void identifySiUnit() {
+ im.unitsexponent = gdef.unitsExponent;
+ im.base = gdef.base;
+ if (!gdef.logarithmic) {
+ int symbcenter = 6;
+ double digits;
+ if (im.unitsexponent != Integer.MAX_VALUE) {
+ digits = Math.floor(im.unitsexponent / 3.0);
+ }
+ else {
+ digits = Math.floor(Math.log(Math.max(Math.abs(im.minval), Math.abs(im.maxval))) / Math.log(im.base));
+ }
+ im.magfact = Math.pow(im.base, digits);
+ if (((digits + symbcenter) < SYMBOLS.length) && ((digits + symbcenter) >= 0)) {
+ im.symbol = SYMBOLS[(int) digits + symbcenter];
+ }
+ else {
+ im.symbol = '?';
+ }
+ }
+ }
+
+ private void findMinMaxValues() {
+ double minval = Double.NaN, maxval = Double.NaN;
+ for (PlotElement pe : gdef.plotElements) {
+ if (pe instanceof SourcedPlotElement) {
+ minval = Util.min(((SourcedPlotElement) pe).getMinValue(), minval);
+ maxval = Util.max(((SourcedPlotElement) pe).getMaxValue(), maxval);
+ }
+ }
+ if (Double.isNaN(minval)) {
+ minval = 0D;
+ }
+ if (Double.isNaN(maxval)) {
+ maxval = 1D;
+ }
+ im.minval = gdef.minValue;
+ im.maxval = gdef.maxValue;
+ /* adjust min and max values */
+ if (Double.isNaN(im.minval) || ((!gdef.logarithmic && !gdef.rigid) && im.minval > minval)) {
+ im.minval = minval;
+ }
+ if (Double.isNaN(im.maxval) || (!gdef.rigid && im.maxval < maxval)) {
+ if (gdef.logarithmic) {
+ im.maxval = maxval * 1.1;
+ }
+ else {
+ im.maxval = maxval;
+ }
+ }
+ /* make sure min is smaller than max */
+ if (im.minval > im.maxval) {
+ im.minval = 0.99 * im.maxval;
+ }
+ /* make sure min and max are not equal */
+ if (Math.abs(im.minval - im.maxval) < .0000001) {
+ im.maxval *= 1.01;
+ if (!gdef.logarithmic) {
+ im.minval *= 0.99;
+ }
+ /* make sure min and max are not both zero */
+ if (im.maxval == 0.0) {
+ im.maxval = 1.0;
+ }
+ }
+ }
+
+ private void calculatePlotValues() {
+ for (PlotElement pe : gdef.plotElements) {
+ if (pe instanceof SourcedPlotElement) {
+ ((SourcedPlotElement) pe).assignValues(dproc);
+ }
+ }
+ }
+
+ private void resolveTextElements() {
+ ValueScaler valueScaler = new ValueScaler(gdef.base);
+ for (CommentText comment : gdef.comments) {
+ comment.resolveText(gdef.locale, dproc, valueScaler);
+ }
+ }
+
+ private void fetchData() throws IOException {
+ dproc = new DataProcessor(gdef.startTime, gdef.endTime);
+ dproc.setPoolUsed(gdef.poolUsed);
+ dproc.setTimeZone(gdef.tz);
+ if (gdef.step > 0) {
+ dproc.setStep(gdef.step);
+ dproc.setFetchRequestResolution(gdef.step);
+ }
+ for (Source src : gdef.sources) {
+ src.requestData(dproc);
+ }
+ dproc.processData();
+ im.start = gdef.startTime;
+ im.end = gdef.endTime;
+ }
+
+ private boolean lazyCheck() {
+ // redraw if lazy option is not set or file does not exist
+ if (!gdef.lazy || !Util.fileExists(gdef.filename)) {
+ return false; // 'false' means 'redraw'
+ }
+ // redraw if not enough time has passed
+ long secPerPixel = (gdef.endTime - gdef.startTime) / gdef.width;
+ long elapsed = Util.getTimestamp() - Util.getLastModified(gdef.filename);
+ return elapsed <= secPerPixel;
+ }
+
+ private void drawLegend() {
+ if (!gdef.onlyGraph && !gdef.noLegend) {
+ worker.setTextAntiAliasing(gdef.textAntiAliasing);
+ int ascent = (int) worker.getFontAscent(gdef.getFont(FONTTAG_LEGEND));
+ int box = (int) getBox(), boxSpace = (int) (getBoxSpace());
+ for (CommentText c : gdef.comments) {
+ if (c.isValidGraphElement()) {
+ int x = c.x, y = c.y + ascent;
+ if (c instanceof LegendText) {
+ // draw with BOX
+ worker.fillRect(x, y - box, box, box, gdef.getColor(ElementsNames.frame));
+ worker.fillRect(x + 1, y - box + 1, box - 2, box - 2, gdef.getColor(ElementsNames.canvas));
+ worker.fillRect(x + 1, y - box + 1, box - 2, box - 2, gdef.getColor(ElementsNames.back));
+ worker.fillRect(x + 1, y - box + 1, box - 2, box - 2, ((LegendText) c).legendColor);
+ worker.drawString(c.resolvedText, x + boxSpace, y, gdef.getFont(FONTTAG_LEGEND), gdef.getColor(ElementsNames.font));
+ }
+ else {
+ worker.drawString(c.resolvedText, x, y, gdef.getFont(FONTTAG_LEGEND), gdef.getColor(ElementsNames.font));
+ }
+ }
+ }
+ worker.setTextAntiAliasing(false);
+ }
+ }
+
+ // helper methods
+
+ double getFontHeight(FontTag fonttag) {
+ return worker.getFontHeight(gdef.getFont(fonttag));
+ }
+
+ double getFontCharWidth(FontTag fonttag) {
+ return worker.getStringWidth("a", gdef.getFont(fonttag));
+ }
+
+ @Deprecated
+ double getSmallFontHeight() {
+ return getFontHeight(FONTTAG_LEGEND);
+ }
+
+ double getTitleFontHeight() {
+ return getFontHeight(FONTTAG_TITLE);
+ }
+
+ double getInterlegendSpace() {
+ return getFontCharWidth(FONTTAG_LEGEND) * LEGEND_INTERSPACING;
+ }
+
+ double getLeading() {
+ return getFontHeight(FONTTAG_LEGEND) * LEGEND_LEADING;
+ }
+
+ double getSmallLeading() {
+ return getFontHeight(FONTTAG_LEGEND) * LEGEND_LEADING_SMALL;
+ }
+
+ double getBoxSpace() {
+ return Math.ceil(getFontHeight(FONTTAG_LEGEND) * LEGEND_BOX_SPACE);
+ }
+
+ private double getBox() {
+ return getFontHeight(FONTTAG_LEGEND) * LEGEND_BOX;
+ }
+
+ private double[] xtr(long[] timestamps) {
+ double[] timestampsDev = new double[2 * timestamps.length - 1];
+ for (int i = 0, j = 0; i < timestamps.length; i += 1, j += 2) {
+ timestampsDev[j] = mapper.xtr(timestamps[i]);
+ if (i < timestamps.length - 1) {
+ timestampsDev[j + 1] = timestampsDev[j];
+ }
+ }
+ return timestampsDev;
+ }
+
+ private double[] ytr(double[] values) {
+ double[] valuesDev = new double[2 * values.length - 1];
+ for (int i = 0, j = 0; i < values.length; i += 1, j += 2) {
+ if (Double.isNaN(values[i])) {
+ valuesDev[j] = Double.NaN;
+ }
+ else {
+ valuesDev[j] = mapper.ytr(values[i]);
+ }
+ if (j > 0) {
+ valuesDev[j - 1] = valuesDev[j];
+ }
+ }
+ return valuesDev;
+ }
+
+ /**
+ * Renders this graph onto graphing device
+ *
+ * @param g Graphics handle
+ */
+ public void render(Graphics g) {
+ byte[] imageData = getRrdGraphInfo().getBytes();
+ ImageIcon image = new ImageIcon(imageData);
+ image.paintIcon(null, g, 0, 0);
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/RrdGraphConstants.java b/apps/jrobin/java/src/org/rrd4j/graph/RrdGraphConstants.java
new file mode 100644
index 0000000000..04d088ddf6
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/RrdGraphConstants.java
@@ -0,0 +1,420 @@
+package org.rrd4j.graph;
+
+import java.awt.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * Class to represent various constants used for graphing. No methods are specified.
+ */
+public interface RrdGraphConstants {
+ /**
+ * Default graph starting time
+ */
+ String DEFAULT_START = "end-1d";
+ /**
+ * Default graph ending time
+ */
+ String DEFAULT_END = "now";
+
+ /**
+ * HH:mm time format
+ */
+ String HH_MM = "HH:mm";
+
+ /**
+ * Constant to represent second
+ */
+ int SECOND = Calendar.SECOND;
+ /**
+ * Constant to represent minute
+ */
+ int MINUTE = Calendar.MINUTE;
+ /**
+ * Constant to represent hour
+ */
+ int HOUR = Calendar.HOUR_OF_DAY;
+ /**
+ * Constant to represent day
+ */
+ int DAY = Calendar.DAY_OF_MONTH;
+ /**
+ * Constant to represent week
+ */
+ int WEEK = Calendar.WEEK_OF_YEAR;
+ /**
+ * Constant to represent month
+ */
+ int MONTH = Calendar.MONTH;
+ /**
+ * Constant to represent year
+ */
+ int YEAR = Calendar.YEAR;
+
+ /**
+ * Constant to represent Monday
+ */
+ int MONDAY = Calendar.MONDAY;
+ /**
+ * Constant to represent Tuesday
+ */
+ int TUESDAY = Calendar.TUESDAY;
+ /**
+ * Constant to represent Wednesday
+ */
+ int WEDNESDAY = Calendar.WEDNESDAY;
+ /**
+ * Constant to represent Thursday
+ */
+ int THURSDAY = Calendar.THURSDAY;
+ /**
+ * Constant to represent Friday
+ */
+ int FRIDAY = Calendar.FRIDAY;
+ /**
+ * Constant to represent Saturday
+ */
+ int SATURDAY = Calendar.SATURDAY;
+ /**
+ * Constant to represent Sunday
+ */
+ int SUNDAY = Calendar.SUNDAY;
+
+ /**
+ * Index of the canvas color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_CANVAS = 0;
+ /**
+ * Index of the background color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_BACK = 1;
+ /**
+ * Index of the top-left graph shade color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_SHADEA = 2;
+ /**
+ * Index of the bottom-right graph shade color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_SHADEB = 3;
+ /**
+ * Index of the minor grid color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_GRID = 4;
+ /**
+ * Index of the major grid color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_MGRID = 5;
+ /**
+ * Index of the font color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_FONT = 6;
+ /**
+ * Index of the frame color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_FRAME = 7;
+ /**
+ * Index of the arrow color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_ARROW = 8;
+ /**
+ * Index of the x-axis color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_XAXIS = 9;
+ /**
+ * Index of the yaxis color. Used in {@link RrdGraphDef#setColor(int, java.awt.Paint)}
+ */
+ @Deprecated
+ int COLOR_YAXIS = 10;
+
+ /**
+ * Default first day of the week (obtained from the default locale)
+ */
+ int FIRST_DAY_OF_WEEK = Calendar.getInstance(Locale.getDefault()).getFirstDayOfWeek();
+
+ /**
+ * Default graph canvas color
+ */
+ Color DEFAULT_CANVAS_COLOR = Color.WHITE;
+ /**
+ * Default graph background color
+ */
+ Color DEFAULT_BACK_COLOR = new Color(245, 245, 245);
+ /**
+ * Default top-left graph shade color
+ */
+ Color DEFAULT_SHADEA_COLOR = new Color(200, 200, 200);
+ /**
+ * Default bottom-right graph shade color
+ */
+ Color DEFAULT_SHADEB_COLOR = new Color(150, 150, 150);
+ /**
+ * Default minor grid color
+ */
+ Color DEFAULT_GRID_COLOR = new Color(171, 171, 171, 95);
+ /**
+ * Default major grid color
+ */
+ Color DEFAULT_MGRID_COLOR = new Color(255, 91, 91, 95);
+ /**
+ * Default font color
+ */
+ Color DEFAULT_FONT_COLOR = Color.BLACK;
+ /**
+ * Default frame color
+ */
+ Color DEFAULT_FRAME_COLOR = Color.BLACK;
+ /**
+ * Default arrow color
+ */
+ Color DEFAULT_ARROW_COLOR = new Color(128, 31, 31);
+ /**
+ * Default x-axis color
+ */
+ Color DEFAULT_XAXIS_COLOR = Color.BLACK;
+ /**
+ * Default x-axis color
+ */
+ Color DEFAULT_YAXIS_COLOR = Color.BLACK;
+
+ /**
+ * An transparent color
+ */
+ Color BLIND_COLOR = new Color(0, 0, 0, 0);
+
+ /**
+ * Constant to represent left alignment marker
+ */
+ @Deprecated
+ String ALIGN_LEFT_MARKER = Markers.ALIGN_LEFT_MARKER.marker;
+ /**
+ * Constant to represent left alignment marker, without new line
+ */
+ @Deprecated
+ String ALIGN_LEFTNONL_MARKER = Markers.ALIGN_LEFTNONL_MARKER.marker;
+ /**
+ * Constant to represent centered alignment marker
+ */
+ @Deprecated
+ String ALIGN_CENTER_MARKER = Markers.ALIGN_CENTER_MARKER.marker;
+ /**
+ * Constant to represent right alignment marker
+ */
+ @Deprecated
+ String ALIGN_RIGHT_MARKER = Markers.ALIGN_RIGHT_MARKER.marker;
+ /**
+ * Constant to represent justified alignment marker
+ */
+ @Deprecated
+ String ALIGN_JUSTIFIED_MARKER = Markers.ALIGN_JUSTIFIED_MARKER.marker;
+ /**
+ * Constant to represent "glue" marker
+ */
+ @Deprecated
+ String GLUE_MARKER = Markers.GLUE_MARKER.marker;
+ /**
+ * Constant to represent vertical spacing marker
+ */
+ @Deprecated
+ String VERTICAL_SPACING_MARKER = Markers.VERTICAL_SPACING_MARKER.marker;
+ /**
+ * Constant to represent no justification markers
+ */
+ @Deprecated
+ String NO_JUSTIFICATION_MARKER = Markers.NO_JUSTIFICATION_MARKER.marker;
+
+ /**
+ * Constant to represent in-memory image name
+ */
+ String IN_MEMORY_IMAGE = "-";
+
+ /**
+ * Default units length
+ */
+ int DEFAULT_UNITS_LENGTH = 9;
+ /**
+ * Default graph width
+ */
+ int DEFAULT_WIDTH = 400;
+ /**
+ * Default graph height
+ */
+ int DEFAULT_HEIGHT = 100;
+ /**
+ * Default image format
+ */
+ String DEFAULT_IMAGE_FORMAT = "gif";
+ /**
+ * Default image quality, used only for jpeg graphs
+ */
+ float DEFAULT_IMAGE_QUALITY = 0.8F; // only for jpegs, not used for png/gif
+ /**
+ * Default value base
+ */
+ double DEFAULT_BASE = 1000;
+
+ /**
+ * Font constructor, to use embedded fonts
+ */
+ static class FontConstructor {
+ private FontConstructor() {}
+
+ /**
+ * Return the default RRD4J's default font for the given strength
+ * @param type {@link java.awt.Font#BOLD} for a bold fond, any other value return plain style.
+ * @param size the size for the new Font
+ * @return a new {@link java.awt.Font} instance
+ */
+ public static Font getFont(int type, int size) {
+ String fontPath;
+ if (type == Font.BOLD)
+ fontPath = "/DejaVuSansMono-Bold.ttf";
+ else
+ fontPath = "/DejaVuSansMono.ttf";
+
+ try (InputStream fontstream = RrdGraphConstants.class.getResourceAsStream(fontPath)) {
+ return Font.createFont(Font.TRUETYPE_FONT, fontstream).deriveFont(type == Font.BOLD ? Font.BOLD : Font.PLAIN, size);
+ } catch (FontFormatException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Default graph small font
+ */
+ static final Font DEFAULT_SMALL_FONT = FontConstructor.getFont(Font.PLAIN, 10);
+ /**
+ * Default graph large font
+ */
+ static final Font DEFAULT_LARGE_FONT = FontConstructor.getFont(Font.BOLD, 12);
+ /**
+ * Font for the Gator
+ */
+ static final Font GATOR_FONT = FontConstructor.getFont(Font.PLAIN, 9);
+ /**
+ * Used internally
+ */
+ double LEGEND_LEADING = 1.2; // chars
+ /**
+ * Used internally
+ */
+ double LEGEND_LEADING_SMALL = 0.7; // chars
+ /**
+ * Used internally
+ */
+ double LEGEND_BOX_SPACE = 1.2; // chars
+ /**
+ * Used internally
+ */
+ double LEGEND_BOX = 0.9; // chars
+ /**
+ * Used internally
+ */
+ int LEGEND_INTERSPACING = 2; // chars
+ /**
+ * Used internally
+ */
+ int PADDING_LEFT = 10; // pix
+ /**
+ * Used internally
+ */
+ int PADDING_TOP = 12; // pix
+ /**
+ * Used internally
+ */
+ int PADDING_TITLE = 6; // pix
+ /**
+ * Used internally
+ */
+ int PADDING_RIGHT = 16; // pix
+ /**
+ * Used internally
+ */
+ int PADDING_PLOT = 2; //chars
+ /**
+ * Used internally
+ */
+ int PADDING_LEGEND = 2; // chars
+ /**
+ * Used internally
+ */
+ int PADDING_BOTTOM = 6; // pix
+ /**
+ * Used internally
+ */
+ int PADDING_VLABEL = 7; // pix
+
+ /**
+ * Stroke used to draw grid
+ */
+ Stroke GRID_STROKE = new BasicStroke(1);
+
+ /**
+ * Stroke used to draw ticks
+ */
+ Stroke TICK_STROKE = new BasicStroke(1);
+
+ /**
+ * Allowed font tag names which can be used in {@link org.rrd4j.graph.RrdGraphDef#setFont(org.rrd4j.graph.RrdGraphConstants.FontTag, java.awt.Font)} method
+ */
+ public enum FontTag {
+ /**
+ * Index of the default font. Used in {@link org.rrd4j.graph.RrdGraphDef#setFont(org.rrd4j.graph.RrdGraphConstants.FontTag, java.awt.Font)}
+ */
+ DEFAULT,
+ /**
+ * Index of the title font. Used in {@link org.rrd4j.graph.RrdGraphDef#setFont(org.rrd4j.graph.RrdGraphConstants.FontTag, java.awt.Font)}
+ */
+ TITLE,
+ /**
+ * Index of the axis label font. Used in {@link org.rrd4j.graph.RrdGraphDef#setFont(org.rrd4j.graph.RrdGraphConstants.FontTag, java.awt.Font)}
+ */
+ AXIS,
+ /**
+ * Index of the vertical unit label font. Used in {@link org.rrd4j.graph.RrdGraphDef#setFont(org.rrd4j.graph.RrdGraphConstants.FontTag, java.awt.Font)}
+ */
+ UNIT,
+ /**
+ * Index of the graph legend font. Used in {@link org.rrd4j.graph.RrdGraphDef#setFont(org.rrd4j.graph.RrdGraphConstants.FontTag, java.awt.Font)}
+ */
+ LEGEND,
+ /**
+ * Index of the edge watermark font. Used in {@link org.rrd4j.graph.RrdGraphDef#setFont(org.rrd4j.graph.RrdGraphConstants.FontTag, java.awt.Font)}
+ */
+ WATERMARK;
+
+ public void set(Font f, Font[] fonts) {
+ fonts[this.ordinal()] = f;
+ }
+
+ public Font get(Font f, Font[] fonts) {
+ return fonts[this.ordinal()];
+ }
+
+ }
+
+ FontTag FONTTAG_DEFAULT = FontTag.DEFAULT;
+
+ FontTag FONTTAG_TITLE = FontTag.TITLE;
+
+ FontTag FONTTAG_AXIS = FontTag.AXIS;
+
+ FontTag FONTTAG_UNIT = FontTag.AXIS;
+
+ FontTag FONTTAG_LEGEND = FontTag.LEGEND;
+
+ FontTag FONTTAG_WATERMARK = FontTag.WATERMARK;
+
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/RrdGraphDef.java b/apps/jrobin/java/src/org/rrd4j/graph/RrdGraphDef.java
new file mode 100644
index 0000000000..7e8446e822
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/RrdGraphDef.java
@@ -0,0 +1,1668 @@
+package org.rrd4j.graph;
+
+import java.awt.BasicStroke;
+import java.awt.Font;
+import java.awt.Paint;
+import java.awt.Stroke;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import org.rrd4j.ConsolFun;
+import org.rrd4j.core.FetchData;
+import org.rrd4j.core.RrdBackendFactory;
+import org.rrd4j.core.Util;
+import org.rrd4j.data.DataProcessor;
+import org.rrd4j.data.Plottable;
+import org.rrd4j.data.Variable;
+
+/**
+ * Class which should be used to define new Rrd4j graph. Once constructed and populated with data
+ * object of this class should be passed to the constructor of the {@link org.rrd4j.graph.RrdGraph} class which
+ * will actually create the graph. The text printed below the actual graph can be formated by appending
+ * special escaped characters at the end of a text. When ever such a
+ * character occurs, all pending text is pushed onto the graph according to
+ * the character specified. Valid markers are: \j for justified, \l for left aligned, \r for right
+ * aligned and \c for centered. Normally there are two space characters inserted between every two
+ * items printed into the graph. The space following a string can be
+ * suppressed by putting a \g at the end of the string. The \g also squashes
+ * any space inside the string if it is at the very end of the string.
+ * This can be used in connection with %s to suppress empty unit strings. A special case is COMMENT:\s this inserts some additional vertical
+ * space before placing the next row of legends. When text has to be formated without special instructions from your
+ * side, RRDTool will automatically justify the text as soon as one string
+ * goes over the right edge. If you want to prevent the justification
+ * without forcing a newline, you can use the special tag \J at the end of
+ * the string to disable the auto justification. Configures x-axis grid and labels. The x-axis label is quite complex to configure.
+ * So if you don't have very special needs, you can rely on the autoconfiguration to
+ * get this right. Otherwise, you have to configure three elements making up the x-axis labels
+ * and grid. The base grid, the major grid and the labels.
+ * The configuration is based on the idea that you first specify a well
+ * known amount of time and then say how many times
+ * it has to pass between each minor/major grid line or label. For the label
+ * you have to define two additional items: The precision of the label
+ * in seconds and the format used to generate the text
+ * of the label. For example, if you wanted a graph with a base grid every 10 minutes and a major
+ * one every hour, with labels every hour you would use the following
+ * x-axis definition. The precision in this example is 0 because the %X format is exact.
+ * If the label was the name of the day, we would have had a precision
+ * of 24 hours, because when you say something like 'Monday' you mean
+ * the whole day and not Monday morning 00:00. Thus the label should
+ * be positioned at noon. By defining a precision of 24 hours or
+ * rather 86400 seconds, you make sure that this happens. Creates additional image information.
+ * After the image has been created, the graph function uses imageInfo
+ * format string (printf-like) to create output similar to
+ * the {@link #print(String, ConsolFun, String)} function.
+ * The format string is supplied with the following parameters:
+ * filename, xsize and ysize (in that particular order). For example, in order to generate an IMG tag
+ * suitable for including the graph into a web page, the command
+ * would look like this: Defines the value normally located at the upper border of the
+ * graph. If the graph contains higher values, the upper border will
+ * move upwards to accommodate these values as well. If you want to define an upper-limit which will not move in any
+ * event you have to use {@link #setRigid(boolean)} method as well. Calculates the chosen consolidation function CF over the given datasource
+ * and creates the result by using the given format string. In
+ * the format string there should be a '%[l]f', '%[l]g' or '%[l]e' marker in
+ * the place where the number should be printed. If an additional '%s' is found AFTER the marker, the value will be
+ * scaled and an appropriate SI magnitude unit will be printed in
+ * place of the '%s' marker. The scaling will take the '--base' argument into consideration! If a '%S' is used instead of a '%s', then instead of calculating
+ * the appropriate SI magnitude unit for this value, the previously
+ * calculated SI magnitude unit will be used. This is useful if you
+ * want all the values in a print statement to have the same SI magnitude unit.
+ * If there was no previous SI magnitude calculation made,
+ * then '%S' behaves like a '%s', unless the value is 0, in which case
+ * it does not remember a SI magnitude unit and a SI magnitude unit
+ * will only be calculated when the next '%s' is seen or the next '%S'
+ * for a non-zero value. Print results are collected in the {@link org.rrd4j.graph.RrdGraphInfo} object which is retrieved
+ * from the {@link RrdGraph object} once the graph is created. Read the value of a variable (VDEF) and prints the value by using the given format string. In
+ * the format string there should be a '%[l]f', '%[l]g' or '%[l]e' marker in
+ * the place where the number should be printed. If an additional '%s' is found AFTER the marker, the value will be
+ * scaled and an appropriate SI magnitude unit will be printed in
+ * place of the '%s' marker. The scaling will take the '--base' argument into consideration! If a '%S' is used instead of a '%s', then instead of calculating
+ * the appropriate SI magnitude unit for this value, the previously
+ * calculated SI magnitude unit will be used. This is useful if you
+ * want all the values in a print statement to have the same SI magnitude unit.
+ * If there was no previous SI magnitude calculation made,
+ * then '%S' behaves like a '%s', unless the value is 0, in which case
+ * it does not remember a SI magnitude unit and a SI magnitude unit
+ * will only be calculated when the next '%s' is seen or the next '%S'
+ * for a non-zero value. Print results are collected in the {@link org.rrd4j.graph.RrdGraphInfo} object which is retrieved
+ * from the {@link RrdGraph object} once the graph is created. Read the value of a variable (VDEF) and prints the the value or the time stamp, according to the strftime flag
+ * by using the given format string. In
+ * and creates the result by using the given format string. In
+ * the format string there should be a '%[l]f', '%[l]g' or '%[l]e' marker in
+ * the place where the number should be printed. If an additional '%s' is found AFTER the marker, the value will be
+ * scaled and an appropriate SI magnitude unit will be printed in
+ * place of the '%s' marker. The scaling will take the '--base' argument into consideration! If a '%S' is used instead of a '%s', then instead of calculating
+ * the appropriate SI magnitude unit for this value, the previously
+ * calculated SI magnitude unit will be used. This is useful if you
+ * want all the values in a print statement to have the same SI magnitude unit.
+ * If there was no previous SI magnitude calculation made,
+ * then '%S' behaves like a '%s', unless the value is 0, in which case
+ * it does not remember a SI magnitude unit and a SI magnitude unit
+ * will only be calculated when the next '%s' is seen or the next '%S'
+ * for a non-zero value. Print results are collected in the {@link org.rrd4j.graph.RrdGraphInfo} object which is retrieved
+ * from the {@link RrdGraph object} once the graph is created. Read the value of a variable (VDEF) and prints the value by using the given format string. In
+ * the format string there should be a '%[l]f', '%[l]g' or '%[l]e' marker in
+ * the place where the number should be printed. If an additional '%s' is found AFTER the marker, the value will be
+ * scaled and an appropriate SI magnitude unit will be printed in
+ * place of the '%s' marker. The scaling will take the '--base' argument into consideration! If a '%S' is used instead of a '%s', then instead of calculating
+ * the appropriate SI magnitude unit for this value, the previously
+ * calculated SI magnitude unit will be used. This is useful if you
+ * want all the values in a print statement to have the same SI magnitude unit.
+ * If there was no previous SI magnitude calculation made,
+ * then '%S' behaves like a '%s', unless the value is 0, in which case
+ * it does not remember a SI magnitude unit and a SI magnitude unit
+ * will only be calculated when the next '%s' is seen or the next '%S'
+ * for a non-zero value. Read the value of a variable (VDEF) and prints the the value or the time stamp, according to the strftime flag
+ * by using the given format string. In
+ * and creates the result by using the given format string. In
+ * the format string there should be a '%[l]f', '%[l]g' or '%[l]e' marker in
+ * the place where the number should be printed. If an additional '%s' is found AFTER the marker, the value will be
+ * scaled and an appropriate SI magnitude unit will be printed in
+ * place of the '%s' marker. The scaling will take the '--base' argument into consideration! If a '%S' is used instead of a '%s', then instead of calculating
+ * the appropriate SI magnitude unit for this value, the previously
+ * calculated SI magnitude unit will be used. This is useful if you
+ * want all the values in a print statement to have the same SI magnitude unit.
+ * If there was no previous SI magnitude calculation made,
+ * then '%S' behaves like a '%s', unless the value is 0, in which case
+ * it does not remember a SI magnitude unit and a SI magnitude unit
+ * will only be calculated when the next '%s' is seen or the next '%S'
+ * for a non-zero value. print results are added to the graph as a legend. Does the same as {@link #line(String, java.awt.Paint)},
+ * but the graph gets stacked on top of the
+ * previous LINE, AREA or STACK graph. Depending on the type of the
+ * previous graph, the STACK will be either a LINE or an AREA. This
+ * obviously implies that the first STACK must be preceded by an AREA
+ * or LINE. Note, that when you STACK onto *UNKNOWN* data, Rrd4j will not
+ * draw any graphics ... *UNKNOWN* is not zero. Does the same as {@link #line(String, java.awt.Paint, String)},
+ * but the graph gets stacked on top of the
+ * previous LINE, AREA or STACK graph. Depending on the type of the
+ * previous graph, the STACK will be either a LINE or an AREA. This
+ * obviously implies that the first STACK must be preceded by an AREA
+ * or LINE.
+ *
+ * It overides the firstDayOfWeek
+ *
+ * @param locale the locale to set
+ */
+ public void setLocale(Locale locale) {
+ this.locale = locale;
+ this.firstDayOfWeek = Calendar.getInstance(Locale.getDefault()).getFirstDayOfWeek();
+ }
+
+ /**
+ * Set the time zone used for the legend.
+ *
+ * @param tz the time zone to set
+ */
+ public void setTimeZone(TimeZone tz) {
+ this.tz = tz;
+ }
+
+ /**
+ * Set the Stroke used to draw grid
+ *
+ * @param gridStroke a {@link java.awt.Stroke} object.
+ */
+ public void setGridStroke(Stroke gridStroke) {
+ this.gridStroke = gridStroke;
+ }
+
+ /**
+ * Set the stroke used to draw ticks
+ *
+ * @param tickStroke a {@link java.awt.Stroke} object.
+ */
+ public void setTickStroke(Stroke tickStroke) {
+ this.tickStroke = tickStroke;
+ }
+
+ /**
+ * Allows to set a downsampler, used to improved the visual representation of graph.
+ *
+ * More details can be found on Sveinn Steinarsson's thesis
+ *
+ * @param downsampler The downsampler that will be used
+ */
+ public void setDownsampler(DownSampler downsampler) {
+ this.downsampler = downsampler;
+ }
+
+ int printStatementCount() {
+ int count = 0;
+ for (CommentText comment : comments) {
+ if (comment instanceof PrintText) {
+ if (comment.isPrint()) {
+ count++;
+ }
+ }
+ }
+ return count;
+ }
+
+ boolean shouldPlot() {
+ if (plotElements.size() > 0) {
+ return true;
+ }
+ for (CommentText comment : comments) {
+ if (comment.isValidGraphElement()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Paint getColor(ElementsNames element) {
+ return colors[element.ordinal()];
+ }
+
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/RrdGraphInfo.java b/apps/jrobin/java/src/org/rrd4j/graph/RrdGraphInfo.java
new file mode 100644
index 0000000000..1a3e73ce16
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/RrdGraphInfo.java
@@ -0,0 +1,127 @@
+package org.rrd4j.graph;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class to represent successfully created Rrd4j graph. Objects of this class are created by method
+ * {@link org.rrd4j.graph.RrdGraph#getRrdGraphInfo()}.
+ */
+public class RrdGraphInfo {
+ String filename;
+ int width, height;
+ InputStream stream;
+ String imgInfo;
+ private List
+ * RRD4J supports all standard operations on Round Robin Database (RRD) files: CREATE, UPDATE, FETCH,
+ * LAST, DUMP, XPORT and GRAPH. RRD4J's API is made for those who are familiar with RRDTool's concepts
+ * and logic, but prefer to work with pure java. If you provide the same data to RRDTool and RRD4J,
+ * you will get very similar results and graphs.
+ *
+ * RRD4J does not use native functions and libraries, has no Runtime.exec() calls and does not require
+ * RRDTool to be present. RRD4J is distributed as a software library (jar files) and comes with full
+ * java source code (Apache License 2.0).
+ *
+ * You will not understand a single thing here if you are not already familiar with RRDTool. Basic
+ * concepts and terms (such as: datasource, archive, datasource type, consolidation functions, archive steps/rows,
+ * heartbeat, RRD step, RPN, graph DEFs and CDEFs) are not explained here because they have exactly the same
+ * meaning in RRD4J and RRDTool. If you are a novice RRDTool/RRD4J user,
+ * this annotated RRDTool tutorial is a
+ * good place to start. A, adapted version for RRD4J is available
+ */
+package org.rrd4j;
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java
index 8e8619a498..9b06a16bba 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryListener.java
@@ -13,14 +13,16 @@ import net.i2p.util.Log;
import net.i2p.util.SecureFile;
import net.i2p.util.SecureFileOutputStream;
-import org.jrobin.core.Archive;
-import org.jrobin.core.RrdBackendFactory;
-import org.jrobin.core.RrdDb;
-import org.jrobin.core.RrdDef;
-import org.jrobin.core.RrdException;
-import org.jrobin.core.RrdMemoryBackendFactory;
-import org.jrobin.core.RrdNioBackendFactory;
-import org.jrobin.core.Sample;
+import org.rrd4j.ConsolFun;
+import org.rrd4j.DsType;
+import org.rrd4j.core.Archive;
+import org.rrd4j.core.RrdBackendFactory;
+import org.rrd4j.core.RrdDb;
+import org.rrd4j.core.RrdDef;
+import org.rrd4j.core.RrdException;
+import org.rrd4j.core.RrdMemoryBackendFactory;
+import org.rrd4j.core.RrdNioBackendFactory;
+import org.rrd4j.core.Sample;
/**
* Creates and updates the in-memory or on-disk RRD database,
@@ -35,7 +37,8 @@ public class SummaryListener implements RateSummaryListener {
static final String RRD_DIR = "rrd";
private static final String RRD_PREFIX = "rrd-";
private static final String RRD_SUFFIX = ".jrb";
- static final String CF = "AVERAGE";
+ static final ConsolFun CF = ConsolFun.AVERAGE;
+ static final DsType DS = DsType.GAUGE;
private static final double XFF = 0.9d;
private static final int STEPS = 1;
@@ -88,14 +91,14 @@ public class SummaryListener implements RateSummaryListener {
stopListening();
if (path != null)
(new File(path)).delete();
- } catch (IOException ioe) {
- _log.error("Error adding", ioe);
- stopListening();
} catch (RrdException re) {
// this can happen after the time slews backwards, so don't make it an error
// org.jrobin.core.RrdException: Bad sample timestamp 1264343107. Last update time was 1264343172, at least one second step is required
if (_log.shouldLog(Log.WARN))
_log.warn("Error adding", re);
+ } catch (IOException ioe) {
+ _log.error("Error adding", ioe);
+ stopListening();
}
}
}
@@ -149,8 +152,8 @@ public class SummaryListener implements RateSummaryListener {
// for info on the heartbeat, xff, steps, etc, see the rrdcreate man page, aka
// http://www.jrobin.org/support/man/rrdcreate.html
long heartbeat = period*10/1000;
- def.addDatasource(_name, "GAUGE", heartbeat, Double.NaN, Double.NaN);
- def.addDatasource(_eventName, "GAUGE", heartbeat, 0, Double.NaN);
+ def.addDatasource(_name, DS, heartbeat, Double.NaN, Double.NaN);
+ def.addDatasource(_eventName, DS, heartbeat, 0, Double.NaN);
if (_isPersistent) {
_rows = (int) Math.max(MIN_ROWS, Math.min(MAX_ROWS, THREE_MONTHS / period));
} else {
@@ -187,6 +190,7 @@ public class SummaryListener implements RateSummaryListener {
"\nContact packager.";
_log.log(Log.CRIT, s);
System.out.println(s);
+ StatSummarizer.setDisabled(_context);
} catch (Throwable t) {
_log.error("Error starting RRD for stat " + baseName, t);
}
@@ -203,9 +207,7 @@ public class SummaryListener implements RateSummaryListener {
_rate.setSummaryListener(null);
if (!_isPersistent) {
// close() does not release resources for memory backend
- try {
- ((RrdMemoryBackendFactory)RrdBackendFactory.getFactory(RrdMemoryBackendFactory.NAME)).delete(_db.getPath());
- } catch (RrdException re) {}
+ ((RrdMemoryBackendFactory)RrdBackendFactory.getFactory("MEMORY")).delete(_db.getPath());
}
_db = null;
}
@@ -254,7 +256,7 @@ public class SummaryListener implements RateSummaryListener {
/** @since 0.8.7 */
String getBackendName() {
- return _isPersistent ? RrdNioBackendFactory.NAME : RrdMemoryBackendFactory.NAME;
+ return _isPersistent ? "NIO" : "MEMORY";
}
/** @since 0.8.7 */
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java
index 02a53e2db6..fb25b13347 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryRenderer.java
@@ -1,8 +1,10 @@
package net.i2p.router.web;
+import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
+import java.awt.Stroke;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
@@ -22,9 +24,11 @@ import static net.i2p.router.web.GraphConstants.*;
import net.i2p.util.Log;
import net.i2p.util.SystemVersion;
-import org.jrobin.core.RrdException;
-import org.jrobin.graph.RrdGraph;
-import org.jrobin.graph.RrdGraphDef;
+import org.rrd4j.ConsolFun;
+import org.rrd4j.core.RrdException;
+import org.rrd4j.graph.ElementsNames;
+import org.rrd4j.graph.RrdGraph;
+import org.rrd4j.graph.RrdGraphDef;
/**
* Generate the RRD graph png images,
@@ -46,6 +50,8 @@ class SummaryRenderer {
private static final Color AREA_COLOR = new Color(100, 160, 200, 200);
private static final Color LINE_COLOR = new Color(0, 30, 110, 255);
private static final Color RESTART_BAR_COLOR = new Color(223, 13, 13, 255);
+ // hide the arrow, full transparent
+ private static final Color ARROW_COLOR = new Color(0, 0, 0, 0);
private static final boolean IS_WIN = SystemVersion.isWindows();
private static final String DEFAULT_FONT_NAME = IS_WIN ?
"Lucida Console" : "Monospaced";
@@ -58,6 +64,8 @@ class SummaryRenderer {
private static final int SIZE_LEGEND = 10;
private static final int SIZE_TITLE = 13;
private static final long[] RATES = new long[] { 60*60*1000 };
+ // dotted line
+ private static final Stroke GRID_STROKE = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 1, new float[] {1, 1}, 0);
public SummaryRenderer(I2PAppContext ctx, SummaryListener lsnr) {
_log = ctx.logManager().getLog(SummaryRenderer.class);
@@ -78,35 +86,6 @@ class SummaryRenderer {
@Deprecated
public static synchronized void render(I2PAppContext ctx, OutputStream out, String filename) throws IOException {
throw new UnsupportedOperationException();
-/*****
- long end = ctx.clock().now() - 60*1000;
- long start = end - 60*1000*SummaryListener.PERIODS;
- try {
- RrdGraphDefTemplate template = new RrdGraphDefTemplate(filename);
- RrdGraphDef def = template.getRrdGraphDef();
- def.setTimeSpan(start/1000, end/1000); // ignore the periods in the template
- // FIXME not clear how to get the height and width from the template
- int width = DEFAULT_X;
- int height = DEFAULT_Y;
- def.setWidth(width);
- def.setHeight(height);
-
- RrdGraph graph = new RrdGraph(def);
- int totalWidth = graph.getRrdGraphInfo().getWidth();
- int totalHeight = graph.getRrdGraphInfo().getHeight();
- BufferedImage img = new BufferedImage(totalWidth, totalHeight, BufferedImage.TYPE_USHORT_565_RGB);
- Graphics gfx = img.getGraphics();
- graph.render(gfx);
- ImageOutputStream ios = new MemoryCacheImageOutputStream(out);
- ImageIO.write(img, "png", ios);
- } catch (RrdException re) {
- //_log.error("Error rendering " + filename, re);
- throw new IOException("Error plotting: " + re.getLocalizedMessage());
- } catch (IOException ioe) {
- //_log.error("Error rendering " + filename, ioe);
- throw ioe;
- }
-*****/
}
public void render(OutputStream out) throws IOException { render(out, DEFAULT_X, DEFAULT_Y,
@@ -148,13 +127,14 @@ class SummaryRenderer {
RrdGraphDef def = new RrdGraphDef();
// Override defaults
- def.setColor(RrdGraphDef.COLOR_BACK, BACK_COLOR);
- def.setColor(RrdGraphDef.COLOR_SHADEA, SHADEA_COLOR);
- def.setColor(RrdGraphDef.COLOR_SHADEB, SHADEB_COLOR);
- def.setColor(RrdGraphDef.COLOR_GRID, GRID_COLOR);
- def.setColor(RrdGraphDef.COLOR_MGRID, MGRID_COLOR);
- def.setColor(RrdGraphDef.COLOR_FONT, FONT_COLOR);
- def.setColor(RrdGraphDef.COLOR_FRAME, FRAME_COLOR);
+ def.setColor(ElementsNames.back, BACK_COLOR);
+ def.setColor(ElementsNames.shadea, SHADEA_COLOR);
+ def.setColor(ElementsNames.shadeb, SHADEB_COLOR);
+ def.setColor(ElementsNames.grid, GRID_COLOR);
+ def.setColor(ElementsNames.mgrid, MGRID_COLOR);
+ def.setColor(ElementsNames.font, FONT_COLOR);
+ def.setColor(ElementsNames.frame, FRAME_COLOR);
+ def.setColor(ElementsNames.arrow, ARROW_COLOR);
// improve text legibility
String lang = Messages.getLanguage(_context);
@@ -176,6 +156,7 @@ class SummaryRenderer {
def.setFont(RrdGraphDef.FONTTAG_DEFAULT, small);
// AXIS is unused, we do not set any axis labels
def.setFont(RrdGraphDef.FONTTAG_AXIS, small);
+ // rrd4j sets UNIT = AXIS in RrdGraphConstants, may be bug, maybe not, no use setting them different here
def.setFont(RrdGraphDef.FONTTAG_UNIT, small);
def.setFont(RrdGraphDef.FONTTAG_LEGEND, legnd);
def.setFont(RrdGraphDef.FONTTAG_TITLE, large);
@@ -234,8 +215,8 @@ class SummaryRenderer {
}
if (!hideLegend) {
def.gprint(plotName, SummaryListener.CF, " " + _t("Avg") + ": %.2f%s");
- def.gprint(plotName, "MAX", ' ' + _t("Max") + ": %.2f%S");
- def.gprint(plotName, "LAST", ' ' + _t("Now") + ": %.2f%S\\l");
+ def.gprint(plotName, ConsolFun.MAX, ' ' + _t("Max") + ": %.2f%S");
+ def.gprint(plotName, ConsolFun.LAST, ' ' + _t("Now") + ": %.2f%S\\l");
}
String plotName2 = null;
if (lsnr2 != null) {
@@ -247,8 +228,8 @@ class SummaryRenderer {
def.line(plotName2, LINE_COLOR, descr2 + "\\l", 2);
if (!hideLegend) {
def.gprint(plotName2, SummaryListener.CF, " " + _t("Avg") + ": %.2f%s");
- def.gprint(plotName2, "MAX", ' ' + _t("Max") + ": %.2f%S");
- def.gprint(plotName2, "LAST", ' ' + _t("Now") + ": %.2f%S\\l");
+ def.gprint(plotName2, ConsolFun.MAX, ' ' + _t("Max") + ": %.2f%S");
+ def.gprint(plotName2, ConsolFun.LAST, ' ' + _t("Now") + ": %.2f%S\\l");
}
}
if (!hideLegend) {
@@ -290,6 +271,8 @@ class SummaryRenderer {
}
//System.out.println("rendering: path=" + path + " dsNames[0]=" + dsNames[0] + " dsNames[1]=" + dsNames[1] + " lsnr.getName=" + _listener.getName());
def.setAntiAliasing(false);
+ def.setTextAntiAliasing(true);
+ def.setGridStroke(GRID_STROKE);
//System.out.println("Rendering: \n" + def.exportXmlTemplate());
//System.out.println("*****************\nData: \n" + _listener.getData().dump());
def.setWidth(width);
diff --git a/build.xml b/build.xml
index 1067069239..681040cb9a 100644
--- a/build.xml
+++ b/build.xml
@@ -842,7 +842,7 @@
FetchRequest
directly (no public constructor
- * is provided). Use {@link RrdDb#createFetchRequest(String, long, long, long)
- * createFetchRequest()} method of your {@link RrdDb RrdDb} object.
- *
- * @author Sasa Markovic
- */
-public class FetchRequest {
- private RrdDb parentDb;
- private String consolFun;
- private long fetchStart;
- private long fetchEnd;
- private long resolution;
- private String[] filter;
-
- public FetchRequest(RrdDb parentDb, String consolFun, long fetchStart, long fetchEnd, long resolution) throws RrdException {
- this.parentDb = parentDb;
- this.consolFun = consolFun;
- this.fetchStart = fetchStart;
- this.fetchEnd = fetchEnd;
- this.resolution = resolution;
- validate();
- }
-
- /**
- * Sets request filter in order to fetch data only for
- * the specified array of datasources (datasource names).
- * If not set (or set to null), fetched data will
- * containt values of all datasources defined in the corresponding RRD.
- * To fetch data only from selected
- * datasources, specify an array of datasource names as method argument.
- *
- * @param filter Array of datsources (datsource names) to fetch data from.
- */
- public void setFilter(String[] filter) {
- this.filter = filter;
- }
-
- /**
- * Sets request filter in order to fetch data only for
- * the specified set of datasources (datasource names).
- * If the filter is not set (or set to null), fetched data will
- * containt values of all datasources defined in the corresponding RRD.
- * To fetch data only from selected
- * datasources, specify a set of datasource names as method argument.
- *
- * @param filter Set of datsource names to fetch data for.
- */
- public void setFilter(Set[minValue, maxValue]
interval (inclusive)
- * will be silently replaced with NaN
.
- *
- * @param minValue lower boundary
- * @param maxValue upper boundary
- * @throws IOException Thrown in case of I/O error
- */
- public void filterValues(double minValue, double maxValue) throws IOException {
- for (int i = 0; i < rows; i++) {
- double value = values.get(i);
- if (!Double.isNaN(minValue) && !Double.isNaN(value) && minValue > value) {
- values.set(i, Double.NaN);
- }
- if (!Double.isNaN(maxValue) && !Double.isNaN(value) && maxValue < value) {
- values.set(i, Double.NaN);
- }
- }
- }
-
- /**
- * Returns the underlying storage (backend) object which actually performs all
- * I/O operations.
- *
- * @return I/O backend object
- */
- public RrdBackend getRrdBackend() {
- return parentArc.getRrdBackend();
- }
-
- /**
- * Required to implement RrdUpdater interface. You should never call this method directly.
- *
- * @return Allocator object
- */
- public RrdAllocator getRrdAllocator() {
- return parentArc.getRrdAllocator();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdAllocator.java b/apps/jrobin/java/src/org/jrobin/core/RrdAllocator.java
deleted file mode 100644
index f3b2058630..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdAllocator.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.IOException;
-
-class RrdAllocator {
- private long allocationPointer = 0L;
-
- long allocate(long byteCount) throws IOException {
- long pointer = allocationPointer;
- allocationPointer += byteCount;
- return pointer;
- }
-}
\ No newline at end of file
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdBackend.java b/apps/jrobin/java/src/org/jrobin/core/RrdBackend.java
deleted file mode 100644
index d15c5857b8..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdBackend.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.IOException;
-
-/**
- * Base implementation class for all backend classes. Each Round Robin Database object
- * ({@link RrdDb} object) is backed with a single RrdBackend object which performs
- * actual I/O operations on the underlying storage. JRobin supports
- * three different bakcends out of the box:
- *
- *
- *
- *
- */
-public abstract class RrdBackend {
- private static boolean s_instanceCreated = false;
- private String m_path = null;
- private boolean m_readOnly = false;
-
- /**
- * Creates backend for a RRD storage with the given path.
- *
- * @param path String identifying RRD storage. For files on the disk, this
- * argument should represent file path. Other storage types might interpret
- * this argument differently.
- */
- protected RrdBackend(final String path) {
- this(path, false);
- }
-
- protected RrdBackend(final String path, final boolean readOnly) {
- m_path = path;
- m_readOnly = readOnly;
- RrdBackend.setInstanceCreated();
- }
-
- /**
- * Returns path to the storage.
- *
- * @return Storage path
- */
- public String getPath() {
- return m_path;
- }
-
- /**
- * Is the RRD ReadOnly?
- *
- * @return True if the RRD is read only, false if not.
- */
- public boolean isReadOnly() {
- return m_readOnly;
- }
-
- /**
- * Writes an array of bytes to the underlying storage starting from the given
- * storage offset.
- *
- * @param offset Storage offset.
- * @param b Array of bytes that should be copied to the underlying storage
- * @throws IOException Thrown in case of I/O error
- */
- protected abstract void write(long offset, byte[] b) throws IOException;
-
- /**
- * Reads an array of bytes from the underlying storage starting from the given
- * storage offset.
- *
- * @param offset Storage offset.
- * @param b Array which receives bytes from the underlying storage
- * @throws IOException Thrown in case of I/O error
- */
- protected abstract void read(long offset, byte[] b) throws IOException;
-
- /**
- * Returns the number of RRD bytes in the underlying storage.
- *
- * @return Number of RRD bytes in the storage.
- * @throws IOException Thrown in case of I/O error.
- */
- public abstract long getLength() throws IOException;
-
- /**
- * Sets the number of bytes in the underlying RRD storage.
- * This method is called only once, immediately after a new RRD storage gets created.
- *
- * @param length Length of the underlying RRD storage in bytes.
- * @throws IOException Thrown in case of I/O error.
- */
- protected abstract void setLength(long length) throws IOException;
-
- /**
- * Closes the underlying backend.
- * @throws IOException Thrown in case of I/O error.
- */
- public void close() throws IOException {
- }
-
- /**
- * This method suggests the caching policy to the JRobin frontend (high-level) classes. If true
- * is returned, frontent classes will cache frequently used parts of a RRD file in memory to improve
- * performance. If false
is returned, high level classes will never cache RRD file sections
- * in memory.
- *
- * @return true
if file caching is enabled, false
otherwise. By default, the
- * method returns true
but it can be overriden in subclasses.
- */
- protected boolean isCachingAllowed() {
- return true;
- }
-
- /**
- * Reads all RRD bytes from the underlying storage
- *
- * @return RRD bytes
- * @throws IOException Thrown in case of I/O error
- */
- public final byte[] readAll() throws IOException {
- final byte[] b = new byte[(int) getLength()];
- read(0, b);
- return b;
- }
-
- final void writeInt(final long offset, final int value) throws IOException {
- write(offset, getIntBytes(value));
- }
-
- final void writeLong(final long offset, final long value) throws IOException {
- write(offset, getLongBytes(value));
- }
-
- final void writeDouble(final long offset, final double value) throws IOException {
- write(offset, getDoubleBytes(value));
- }
-
- final void writeDouble(final long offset, final double value, final int count) throws IOException {
- final byte[] b = getDoubleBytes(value);
- final byte[] image = new byte[8 * count];
- for (int i = 0, k = 0; i < count; i++) {
- image[k++] = b[0];
- image[k++] = b[1];
- image[k++] = b[2];
- image[k++] = b[3];
- image[k++] = b[4];
- image[k++] = b[5];
- image[k++] = b[6];
- image[k++] = b[7];
- }
- write(offset, image);
- }
-
- final void writeDouble(final long offset, final double[] values) throws IOException {
- final int count = values.length;
- final byte[] image = new byte[8 * count];
- for (int i = 0, k = 0; i < count; i++) {
- final byte[] b = getDoubleBytes(values[i]);
- image[k++] = b[0];
- image[k++] = b[1];
- image[k++] = b[2];
- image[k++] = b[3];
- image[k++] = b[4];
- image[k++] = b[5];
- image[k++] = b[6];
- image[k++] = b[7];
- }
- write(offset, image);
- }
-
- final void writeString(final long offset, final String rawValue) throws IOException {
- final String value = rawValue.trim();
- final byte[] b = new byte[RrdPrimitive.STRING_LENGTH * 2];
- for (int i = 0, k = 0; i < RrdPrimitive.STRING_LENGTH; i++) {
- final char c = (i < value.length()) ? value.charAt(i) : ' ';
- final byte[] cb = getCharBytes(c);
- b[k++] = cb[0];
- b[k++] = cb[1];
- }
- write(offset, b);
- }
-
- final int readInt(final long offset) throws IOException {
- final byte[] b = new byte[4];
- read(offset, b);
- return getInt(b);
- }
-
- final long readLong(final long offset) throws IOException {
- final byte[] b = new byte[8];
- read(offset, b);
- return getLong(b);
- }
-
- final double readDouble(final long offset) throws IOException {
- final byte[] b = new byte[8];
- read(offset, b);
- return getDouble(b);
- }
-
- final double[] readDouble(final long offset, final int count) throws IOException {
- final int byteCount = 8 * count;
- final byte[] image = new byte[byteCount];
- read(offset, image);
- final double[] values = new double[count];
- for (int i = 0, k = -1; i < count; i++) {
- final byte[] b = new byte[] {
- image[++k], image[++k], image[++k], image[++k],
- image[++k], image[++k], image[++k], image[++k]
- };
- values[i] = getDouble(b);
- }
- return values;
- }
-
- final String readString(final long offset) throws IOException {
- final byte[] b = new byte[RrdPrimitive.STRING_LENGTH * 2];
- final char[] c = new char[RrdPrimitive.STRING_LENGTH];
- read(offset, b);
- for (int i = 0, k = -1; i < RrdPrimitive.STRING_LENGTH; i++) {
- final byte[] cb = new byte[] {b[++k], b[++k]};
- c[i] = getChar(cb);
- }
- return new String(c).trim();
- }
-
- // static helper methods
-
- private static byte[] getIntBytes(final int value) {
- final byte[] b = new byte[4];
- b[0] = (byte) ((value >>> 24) & 0xFF);
- b[1] = (byte) ((value >>> 16) & 0xFF);
- b[2] = (byte) ((value >>> 8) & 0xFF);
- b[3] = (byte) ((value) & 0xFF);
- return b;
- }
-
- private static byte[] getLongBytes(final long value) {
- final byte[] b = new byte[8];
- b[0] = (byte) ((int) (value >>> 56) & 0xFF);
- b[1] = (byte) ((int) (value >>> 48) & 0xFF);
- b[2] = (byte) ((int) (value >>> 40) & 0xFF);
- b[3] = (byte) ((int) (value >>> 32) & 0xFF);
- b[4] = (byte) ((int) (value >>> 24) & 0xFF);
- b[5] = (byte) ((int) (value >>> 16) & 0xFF);
- b[6] = (byte) ((int) (value >>> 8) & 0xFF);
- b[7] = (byte) ((int) (value) & 0xFF);
- return b;
- }
-
- private static byte[] getCharBytes(final char value) {
- final byte[] b = new byte[2];
- b[0] = (byte) ((value >>> 8) & 0xFF);
- b[1] = (byte) ((value) & 0xFF);
- return b;
- }
-
- private static byte[] getDoubleBytes(final double value) {
- return getLongBytes(Double.doubleToLongBits(value));
- }
-
- private static int getInt(final byte[] b) {
- assert b.length == 4: "Invalid number of bytes for integer conversion";
- return ((b[0] << 24) & 0xFF000000) + ((b[1] << 16) & 0x00FF0000) +
- ((b[2] << 8) & 0x0000FF00) + (b[3] & 0x000000FF);
- }
-
- private static long getLong(final byte[] b) {
- assert b.length == 8: "Invalid number of bytes for long conversion";
- int high = getInt(new byte[] {b[0], b[1], b[2], b[3]});
- int low = getInt(new byte[] {b[4], b[5], b[6], b[7]});
- return ((long) (high) << 32) + (low & 0xFFFFFFFFL);
- }
-
- private static char getChar(final byte[] b) {
- assert b.length == 2: "Invalid number of bytes for char conversion";
- return (char) (((b[0] << 8) & 0x0000FF00)
- + (b[1] & 0x000000FF));
- }
-
- private static double getDouble(final byte[] b) {
- assert b.length == 8: "Invalid number of bytes for double conversion";
- return Double.longBitsToDouble(getLong(b));
- }
-
- private static void setInstanceCreated() {
- s_instanceCreated = true;
- }
-
- static boolean isInstanceCreated() {
- return s_instanceCreated;
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdBackendFactory.java b/apps/jrobin/java/src/org/jrobin/core/RrdBackendFactory.java
deleted file mode 100644
index 42ebbd7610..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdBackendFactory.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.IOException;
-import java.util.HashMap;
-
-/**
- * Base (abstract) backend factory class which holds references to all concrete
- * backend factories and defines abstract methods which must be implemented in
- * all concrete factory implementations.
- *
- *
- *
- *
- * @return Backend factory for the given factory name
- * @throws RrdException Thrown if no factory with the given name
- * is available.
- */
- public static synchronized RrdBackendFactory getFactory(final String name) throws RrdException {
- final RrdBackendFactory factory = factories.get(name);
- if (factory != null) {
- return factory;
- }
- throw new RrdException("No backend factory found with the name specified [" + name + "]");
- }
-
- /**
- * Registers new (custom) backend factory within the JRobin framework.
- *
- * @param factory Factory to be registered
- * @throws RrdException Thrown if the name of the specified factory is already
- * used.
- */
- public static synchronized void registerFactory(final RrdBackendFactory factory) throws RrdException {
- final String name = factory.getFactoryName();
- if (!factories.containsKey(name)) {
- factories.put(name, factory);
- }
- else {
- throw new RrdException("Backend factory of this name2 (" + name + ") already exists and cannot be registered");
- }
- }
-
- /**
- * Registers new (custom) backend factory within the JRobin framework and sets this
- * factory as the default.
- *
- * @param factory Factory to be registered and set as default
- * @throws RrdException Thrown if the name of the specified factory is already
- * used.
- */
- public static synchronized void registerAndSetAsDefaultFactory(final RrdBackendFactory factory) throws RrdException {
- registerFactory(factory);
- setDefaultFactory(factory.getFactoryName());
- }
-
- /**
- * Returns the defaul backend factory. This factory is used to construct
- * {@link RrdDb} objects if no factory is specified in the RrdDb constructor.
- *
- * @return Default backend factory.
- */
- public static RrdBackendFactory getDefaultFactory() {
- return defaultFactory;
- }
-
- /**
- * Replaces the default backend factory with a new one. This method must be called before
- * the first RRD gets created.
- * // create new RRD definition
- * RrdDef def = new RrdDef("test.rrd", 300);
- * def.addDatasource("input", DsTypes.DT_COUNTER, 600, 0, Double.NaN);
- * def.addDatasource("output", DsTypes.DT_COUNTER, 600, 0, Double.NaN);
- * def.addArchive(ConsolFuns.CF_AVERAGE, 0.5, 1, 600);
- * def.addArchive(ConsolFuns.CF_AVERAGE, 0.5, 6, 700);
- * def.addArchive(ConsolFuns.CF_AVERAGE, 0.5, 24, 797);
- * def.addArchive(ConsolFuns.CF_AVERAGE, 0.5, 288, 775);
- * def.addArchive(ConsolFuns.CF_MAX, 0.5, 1, 600);
- * def.addArchive(ConsolFuns.CF_MAX, 0.5, 6, 700);
- * def.addArchive(ConsolFuns.CF_MAX, 0.5, 24, 797);
- * def.addArchive(ConsolFuns.CF_MAX, 0.5, 288, 775);
- *
- * // RRD definition is now completed, create the database!
- * RrdDb rrd = new RrdDb(def);
- * // new RRD file has been created on your disk
- *
- *
- * @param rrdDef Object describing the structure of the new RRD file.
- * @throws IOException Thrown in case of I/O error.
- * @throws RrdException Thrown if invalid RrdDef object is supplied.
- */
- public RrdDb(RrdDef rrdDef) throws RrdException, IOException {
- this(rrdDef, RrdFileBackendFactory.getDefaultFactory());
- }
-
- /**
- * Constructor used to create new RRD object from the definition object but with a storage
- * (backend) different from default.
- *
- *
- *
- * RrdBackendFactory factory = RrdBackendFactory.getFactory("MEMORY");
- * RrdDb rrdDb = new RrdDb(rrdDef, factory);
- * rrdDb.close();
- *
- * false
if you want to update
- * the underlying RRD. If you want just to fetch data from the RRD file
- * (read-only access), specify true
. If you try to update RRD file
- * open in read-only mode (m_readOnly
set to true
),
- * IOException
will be thrown.
- * @throws IOException Thrown in case of I/O error.
- * @throws RrdException Thrown in case of JRobin specific error.
- */
- public RrdDb(String path, boolean readOnly) throws IOException, RrdException {
- this(path, readOnly, RrdBackendFactory.getDefaultFactory());
- }
-
- /**
- * Constructor used to open already existing RRD backed
- * with a storage (backend) different from default. Constructor
- * obtains read or read/write access to this RRD.
- *
- * @param path Path to existing RRD.
- * @param readOnly Should be set to false
if you want to update
- * the underlying RRD. If you want just to fetch data from the RRD file
- * (read-only access), specify true
. If you try to update RRD file
- * open in read-only mode (m_readOnly
set to true
),
- * IOException
will be thrown.
- * @param factory Backend factory which will be used for this RRD.
- * @throws FileNotFoundException Thrown if the requested file does not exist.
- * @throws IOException Thrown in case of general I/O error (bad RRD file, for example).
- * @throws RrdException Thrown in case of JRobin specific error.
- * @see RrdBackendFactory
- */
- public RrdDb(String path, boolean readOnly, RrdBackendFactory factory)
- throws FileNotFoundException, IOException, RrdException {
- // opens existing RRD file - throw exception if the file does not exist...
- if (!factory.exists(path)) {
- throw new FileNotFoundException("Could not open " + path + " [non existent]");
- }
- backend = factory.open(path, readOnly);
- try {
- // restore header
- header = new Header(this, (RrdDef) null);
- header.validateHeader();
- // restore datasources
- int dsCount = header.getDsCount();
- datasources = new Datasource[dsCount];
- for (int i = 0; i < dsCount; i++) {
- datasources[i] = new Datasource(this, null);
- }
- // restore archives
- int arcCount = header.getArcCount();
- archives = new Archive[arcCount];
- for (int i = 0; i < arcCount; i++) {
- archives[i] = new Archive(this, null);
- }
- }
- catch (RrdException e) {
- backend.close();
- throw e;
- }
- catch (IOException e) {
- backend.close();
- throw e;
- }
- }
-
- /**
- *
- *
- * rrdtool dump
command).
- *
- * rrdtool dump original.rrd > original.xml
- *
- * original.xml
to create JRobin RRD file named
- * copy.rrd
:
- *
- * RrdDb rrd = new RrdDb("copy.rrd", "original.xml");
- *
- *
- * RrdDb rrd = new RrdDb("copy.rrd", "xml:/original.xml");
- *
- * rrdtool:/
prefix in the
- * externalPath
argument. For example, to create JRobin compatible file named
- * copy.rrd
from the file original.rrd
created with RRDTool, use
- * the following code:
- *
- * RrdDb rrd = new RrdDb("copy.rrd", "rrdtool:/original.rrd");
- *
- * xml:/
or rrdtool:/
is necessary to distinguish
- * between XML and RRDTool's binary sources. If no prefix is supplied, XML format is assumed.
- *
- * @param rrdPath Path to a RRD file which will be created
- * @param externalPath Path to an external file which should be imported, with an optional
- * xml:/
or rrdtool:/
prefix.
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public RrdDb(String rrdPath, String externalPath) throws IOException, RrdException, RrdException {
- this(rrdPath, externalPath, RrdBackendFactory.getDefaultFactory());
- }
-
- /**
- * Constructor used to create RRD files from external file sources with a backend type
- * different from default. Supported external file sources are:
- *
- *
- * rrdtool dump
command).
- *
- * rrdtool dump original.rrd > original.xml
- *
- * original.xml
to create JRobin RRD file named
- * copy.rrd
:
- *
- * RrdDb rrd = new RrdDb("copy.rrd", "original.xml");
- *
- *
- * RrdDb rrd = new RrdDb("copy.rrd", "xml:/original.xml");
- *
- * rrdtool:/
prefix in the
- * externalPath
argument. For example, to create JRobin compatible file named
- * copy.rrd
from the file original.rrd
created with RRDTool, use
- * the following code:
- *
- * RrdDb rrd = new RrdDb("copy.rrd", "rrdtool:/original.rrd");
- *
- * xml:/
or rrdtool:/
is necessary to distinguish
- * between XML and RRDTool's binary sources. If no prefix is supplied, XML format is assumed.
- *
- * @param rrdPath Path to RRD which will be created
- * @param externalPath Path to an external file which should be imported, with an optional
- * xml:/
or rrdtool:/
prefix.
- * @param factory Backend factory which will be used to create storage (backend) for this RRD.
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of JRobin specific error
- * @see RrdBackendFactory
- */
- public RrdDb(String rrdPath, String externalPath, RrdBackendFactory factory)
- throws IOException, RrdException {
- DataImporter reader;
- if (externalPath.startsWith(PREFIX_RRDTool)) {
- String rrdToolPath = externalPath.substring(PREFIX_RRDTool.length());
- reader = new RrdToolReader(rrdToolPath);
- }
- else if (externalPath.startsWith(PREFIX_XML)) {
- externalPath = externalPath.substring(PREFIX_XML.length());
- reader = new XmlReader(externalPath);
- }
- else {
- reader = new XmlReader(externalPath);
- }
- backend = factory.open(rrdPath, false);
- try {
- backend.setLength(reader.getEstimatedSize());
- // create header
- header = new Header(this, reader);
- // create datasources
- datasources = new Datasource[reader.getDsCount()];
- for (int i = 0; i < datasources.length; i++) {
- datasources[i] = new Datasource(this, reader, i);
- }
- // create archives
- archives = new Archive[reader.getArcCount()];
- for (int i = 0; i < archives.length; i++) {
- archives[i] = new Archive(this, reader, i);
- }
- reader.release();
- }
- catch (RrdException e) {
- backend.close();
- throw e;
- }
- catch (IOException e) {
- backend.close();
- throw e;
- }
- }
-
- public RrdDb(final File file) throws IOException, RrdException {
- this(file.getPath());
- }
-
- public RrdDb(final File file, final boolean readOnly) throws IOException, RrdException {
- this(file.getPath(), readOnly);
- }
-
- /**
- * Closes RRD. No further operations are allowed on this RrdDb object.
- *
- * @throws IOException Thrown in case of I/O related error.
- */
- public synchronized void close() throws IOException {
- if (!closed) {
- closed = true;
- backend.close();
- }
- }
-
- /**
- * Returns true if the RRD is closed.
- *
- * @return true if closed, false otherwise
- */
- public boolean isClosed() {
- return closed;
- }
-
- /**
- * Returns RRD header.
- *
- * @return Header object
- */
- public Header getHeader() {
- return header;
- }
-
- /**
- * Returns Datasource object for the given datasource index.
- *
- * @param dsIndex Datasource index (zero based)
- * @return Datasource object
- */
- public Datasource getDatasource(int dsIndex) {
- return datasources[dsIndex];
- }
-
- /**
- * Returns Archive object for the given archive index.
- *
- * @param arcIndex Archive index (zero based)
- * @return Archive object
- */
- public Archive getArchive(int arcIndex) {
- return archives[arcIndex];
- }
-
- /**
- * Returns an array of datasource names defined in RRD.
- *
- * @return Array of datasource names.
- * @throws IOException Thrown in case of I/O error.
- */
- public String[] getDsNames() throws IOException {
- int n = datasources.length;
- String[] dsNames = new String[n];
- for (int i = 0; i < n; i++) {
- dsNames[i] = datasources[i].getDsName();
- }
- return dsNames;
- }
-
- /**
- * Creates new sample with the given timestamp and all datasource values set to
- * 'unknown'. Use returned Sample
object to specify
- * datasource values for the given timestamp. See documentation for
- * {@link org.jrobin.core.Sample Sample} for an explanation how to do this.
- * Sample
object to specify
- * datasource values for the current timestamp. See documentation for
- * {@link org.jrobin.core.Sample Sample} for an explanation how to do this.
- * FetchRequest
object and its {@link org.jrobin.core.FetchRequest#fetchData() fetchData()}
- * method to actually fetch data from the RRD file.FetchRequest
object and its {@link org.jrobin.core.FetchRequest#fetchData() fetchData()}
- * method to actually fetch data from this RRD. Data will be fetched with the smallest
- * possible resolution (see RRDTool's
- * rrdfetch man page
- * for the explanation of the resolution parameter).stdout
and/or used for debugging purposes.true
if datasource is present in this RRD, false
otherwise
- * @throws IOException Thrown in case of I/O error.
- */
- public boolean containsDs(String dsName) throws IOException {
- for (Datasource datasource : datasources) {
- if (datasource.getDsName().equals(dsName)) {
- return true;
- }
- }
- return false;
- }
-
- Datasource[] getDatasources() {
- return datasources;
- }
-
- Archive[] getArchives() {
- return archives;
- }
-
- /**
- * Writes the RRD content to OutputStream using XML format. This format
- * is fully compatible with RRDTool's XML dump format and can be used for conversion
- * purposes or debugging.
- *
- * @param destination Output stream to receive XML data
- * @throws IOException Thrown in case of I/O related error
- */
- public synchronized void dumpXml(OutputStream destination) throws IOException {
- XmlWriter writer = new XmlWriter(destination);
- writer.startTag("rrd");
- // dump header
- header.appendXml(writer);
- // dump datasources
- for (Datasource datasource : datasources) {
- datasource.appendXml(writer);
- }
- // dump archives
- for (Archive archive : archives) {
- archive.appendXml(writer);
- }
- writer.closeTag();
- writer.flush();
- }
-
- /**
- * This method is just an alias for {@link #dumpXml(OutputStream) dumpXml} method.
- *
- * @param destination Output stream to receive XML data
- * @throws IOException Thrown in case of I/O related error
- */
- public synchronized void exportXml(OutputStream destination) throws IOException {
- dumpXml(destination);
- }
-
- /**
- * Returns string representing internal RRD state in XML format. This format
- * is fully compatible with RRDTool's XML dump format and can be used for conversion
- * purposes or debugging.
- *
- * @return Internal RRD state in XML format.
- * @throws IOException Thrown in case of I/O related error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public synchronized String getXml() throws IOException, RrdException {
- ByteArrayOutputStream destination = new ByteArrayOutputStream(XML_INITIAL_BUFFER_CAPACITY);
- dumpXml(destination);
- return destination.toString();
- }
-
- /**
- * This method is just an alias for {@link #getXml() getXml} method.
- *
- * @return Internal RRD state in XML format.
- * @throws IOException Thrown in case of I/O related error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public synchronized String exportXml() throws IOException, RrdException {
- return getXml();
- }
-
- /**
- * Dumps internal RRD state to XML file.
- * Use this XML file to convert your JRobin RRD to RRDTool format.
- * original.rrd
and you want
- * to convert it to RRDTool format. First, execute the following java code:
- * RrdDb rrd = new RrdDb("original.rrd");
- * rrd.dumpXml("original.xml");
- * original.xml
file to create the corresponding RRDTool file
- * (from your command line):
- * rrdtool restore copy.rrd original.xml
- *
- * @param filename Path to XML file which will be created.
- * @throws IOException Thrown in case of I/O related error.
- * @throws RrdException Thrown in case of JRobin related error.
- */
- public synchronized void dumpXml(String filename) throws IOException, RrdException {
- OutputStream outputStream = null;
- try {
- outputStream = new FileOutputStream(filename, false);
- dumpXml(outputStream);
- }
- finally {
- if (outputStream != null) {
- outputStream.close();
- }
- }
- }
-
- /**
- * This method is just an alias for {@link #dumpXml(String) dumpXml(String)} method.
- *
- * @param filename Path to XML file which will be created.
- * @throws IOException Thrown in case of I/O related error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public synchronized void exportXml(String filename) throws IOException, RrdException {
- dumpXml(filename);
- }
-
- /**
- * Returns time of last update operation as timestamp (in seconds).
- *
- * @return Last update time (in seconds).
- * @throws IOException Thrown in case of I/O related error
- */
- public synchronized long getLastUpdateTime() throws IOException {
- return header.getLastUpdateTime();
- }
-
- /**
- * Returns RRD definition object which can be used to create new RRD
- * with the same creation parameters but with no data in it.
- *
- * RrdDb rrd1 = new RrdDb("original.rrd");
- * RrdDef def = rrd1.getRrdDef();
- * // fix path
- * def.setPath("empty_copy.rrd");
- * // create new RRD file
- * RrdDb rrd2 = new RrdDb(def);
- *
- *
- * @return RRD definition.
- * @throws IOException Thrown in case of I/O related error.
- * @throws RrdException Thrown in case of JRobin specific error.
- */
- public synchronized RrdDef getRrdDef() throws RrdException, IOException {
- // set header
- long startTime = header.getLastUpdateTime();
- long step = header.getStep();
- String path = backend.getPath();
- RrdDef rrdDef = new RrdDef(path, startTime, step);
- // add datasources
- for (Datasource datasource : datasources) {
- DsDef dsDef = new DsDef(datasource.getDsName(),
- datasource.getDsType(), datasource.getHeartbeat(),
- datasource.getMinValue(), datasource.getMaxValue());
- rrdDef.addDatasource(dsDef);
- }
- // add archives
- for (Archive archive : archives) {
- ArcDef arcDef = new ArcDef(archive.getConsolFun(),
- archive.getXff(), archive.getSteps(), archive.getRows());
- rrdDef.addArchive(arcDef);
- }
- return rrdDef;
- }
-
- protected void finalize() throws Throwable {
- super.finalize();
- close();
- }
-
- /**
- * Copies object's internal state to another RrdDb object.
- *
- * @param other New RrdDb object to copy state to
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if supplied argument is not a compatible RrdDb object
- */
- public synchronized void copyStateTo(RrdUpdater other) throws IOException, RrdException {
- if (!(other instanceof RrdDb)) {
- throw new RrdException("Cannot copy RrdDb object to " + other.getClass().getName());
- }
- RrdDb otherRrd = (RrdDb) other;
- header.copyStateTo(otherRrd.header);
- for (int i = 0; i < datasources.length; i++) {
- int j = Util.getMatchingDatasourceIndex(this, i, otherRrd);
- if (j >= 0) {
- datasources[i].copyStateTo(otherRrd.datasources[j]);
- }
- }
- for (int i = 0; i < archives.length; i++) {
- int j = Util.getMatchingArchiveIndex(this, i, otherRrd);
- if (j >= 0) {
- archives[i].copyStateTo(otherRrd.archives[j]);
- }
- }
- }
-
- /**
- * Returns Datasource object corresponding to the given datasource name.
- *
- * @param dsName Datasource name
- * @return Datasource object corresponding to the give datasource name or null
- * if not found.
- * @throws IOException Thrown in case of I/O error
- */
- public Datasource getDatasource(String dsName) throws IOException {
- try {
- return getDatasource(getDsIndex(dsName));
- }
- catch (RrdException e) {
- return null;
- }
- }
-
- /**
- * Returns index of Archive object with the given consolidation function and the number
- * of steps. Exception is thrown if such archive could not be found.
- *
- * @param consolFun Consolidation function
- * @param steps Number of archive steps
- * @return Requested Archive object
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown if no such archive could be found
- */
- public int getArcIndex(String consolFun, int steps) throws RrdException, IOException {
- for (int i = 0; i < archives.length; i++) {
- if (archives[i].getConsolFun().equals(consolFun) &&
- archives[i].getSteps() == steps) {
- return i;
- }
- }
- throw new RrdException("Could not find archive " + consolFun + "/" + steps);
- }
-
- /**
- * Returns Archive object with the given consolidation function and the number
- * of steps.
- *
- * @param consolFun Consolidation function
- * @param steps Number of archive steps
- * @return Requested Archive object or null if no such archive could be found
- * @throws IOException Thrown in case of I/O error
- */
- public Archive getArchive(String consolFun, int steps) throws IOException {
- try {
- return getArchive(getArcIndex(consolFun, steps));
- }
- catch (RrdException e) {
- return null;
- }
- }
-
- /**
- * Returns canonical path to the underlying RRD file. Note that this method makes sense just for
- * ordinary RRD files created on the disk - an exception will be thrown for RRD objects created in
- * memory or with custom backends.
- *
- * @return Canonical path to RRD file;
- * @throws IOException Thrown in case of I/O error or if the underlying backend is
- * not derived from RrdFileBackend.
- */
- public String getCanonicalPath() throws IOException {
- if (backend instanceof RrdFileBackend) {
- return ((RrdFileBackend) backend).getCanonicalPath();
- }
- else {
- throw new IOException("The underlying backend has no canonical path");
- }
- }
-
- /**
- * Returns path to this RRD.
- *
- * @return Path to this RRD.
- */
- public String getPath() {
- return backend.getPath();
- }
-
- /**
- * Returns backend object for this RRD which performs actual I/O operations.
- *
- * @return RRD backend for this RRD.
- */
- public RrdBackend getRrdBackend() {
- return backend;
- }
-
- /**
- * Required to implement RrdUpdater interface. You should never call this method directly.
- *
- * @return Allocator object
- */
- public RrdAllocator getRrdAllocator() {
- return allocator;
- }
-
- /**
- * Returns an array of bytes representing the whole RRD.
- *
- * @return All RRD bytes
- * @throws IOException Thrown in case of I/O related error.
- */
- public synchronized byte[] getBytes() throws IOException {
- return backend.readAll();
- }
-
- /**
- * Sets default backend factory to be used. This method is just an alias for
- * {@link RrdBackendFactory#setDefaultFactory(java.lang.String)}.
- *
- *
- * @param path Path to existing RRD file
- * @return reference for the give RRD file
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public synchronized RrdDb requestRrdDb(String path) throws IOException, RrdException {
- String canonicalPath = Util.getCanonicalPath(path);
- while (!rrdMap.containsKey(canonicalPath) && rrdMap.size() >= capacity) {
- try {
- wait();
- }
- catch (InterruptedException e) {
- throw new RrdException(e);
- }
- }
- if (rrdMap.containsKey(canonicalPath)) {
- // already open, just increase usage count
- RrdEntry entry = rrdMap.get(canonicalPath);
- entry.count++;
- return entry.rrdDb;
- }
- else {
- // not open, open it now and add to the map
- RrdDb rrdDb = new RrdDb(canonicalPath);
- rrdMap.put(canonicalPath, new RrdEntry(rrdDb));
- return rrdDb;
- }
- }
-
- /**
- * Requests a RrdDb reference for the given RRD file definition object.
- *
- *
- * @param rrdDef Definition of the RRD file to be created
- * @return Reference to the newly created RRD file
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public synchronized RrdDb requestRrdDb(RrdDef rrdDef) throws IOException, RrdException {
- String canonicalPath = Util.getCanonicalPath(rrdDef.getPath());
- while (rrdMap.containsKey(canonicalPath) || rrdMap.size() >= capacity) {
- try {
- wait();
- }
- catch (InterruptedException e) {
- throw new RrdException(e);
- }
- }
- RrdDb rrdDb = new RrdDb(rrdDef);
- rrdMap.put(canonicalPath, new RrdEntry(rrdDb));
- return rrdDb;
- }
-
- /**
- * Requests a RrdDb reference for the given path. The file will be created from
- * external data (from XML dump, RRD file or RRDTool's binary RRD file).
- *
- *
- * @param path Path to RRD file which should be created
- * @param sourcePath Path to external data which is to be converted to JRobin's native RRD file format
- * @return Reference to the newly created RRD file
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public synchronized RrdDb requestRrdDb(String path, String sourcePath)
- throws IOException, RrdException,RrdException {
- String canonicalPath = Util.getCanonicalPath(path);
- while (rrdMap.containsKey(canonicalPath) || rrdMap.size() >= capacity) {
- try {
- wait();
- }
- catch (InterruptedException e) {
- throw new RrdException(e);
- }
- }
- RrdDb rrdDb = new RrdDb(canonicalPath, sourcePath);
- rrdMap.put(canonicalPath, new RrdEntry(rrdDb));
- return rrdDb;
- }
-
- /**
- * Releases RrdDb reference previously obtained from the pool. When a reference is released, its usage
- * count is decremented by one. If usage count drops to zero, the underlying RRD file will be closed.
- *
- * @param rrdDb RrdDb reference to be returned to the pool
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public synchronized void release(RrdDb rrdDb) throws IOException, RrdException {
- // null pointer should not kill the thread, just ignore it
- if (rrdDb == null) {
- return;
- }
- String canonicalPath = Util.getCanonicalPath(rrdDb.getPath());
- if (!rrdMap.containsKey(canonicalPath)) {
- throw new RrdException("Could not release [" + canonicalPath + "], the file was never requested");
- }
- RrdEntry entry = rrdMap.get(canonicalPath);
- if (--entry.count <= 0) {
- // no longer used
- rrdMap.remove(canonicalPath);
- notifyAll();
- entry.rrdDb.close();
- }
- }
-
- /**
- * Returns the maximum number of simultaneously open RRD files.
- *
- * @return maximum number of simultaneously open RRD files
- */
- public synchronized int getCapacity() {
- return capacity;
- }
-
- /**
- * Sets the maximum number of simultaneously open RRD files.
- *
- * @param capacity Maximum number of simultaneously open RRD files.
- */
- public synchronized void setCapacity(int capacity) {
- this.capacity = capacity;
- }
-
- /**
- * Returns an array of open file names.
- *
- * @return Array with canonical paths to open RRD files held in the pool.
- */
- public synchronized String[] getOpenFiles() {
- return rrdMap.keySet().toArray(new String[0]);
- }
-
- /**
- * Returns the number of open RRD files.
- *
- * @return Number of currently open RRD files held in the pool.
- */
- public synchronized int getOpenFileCount() {
- return rrdMap.size();
- }
-
- private final static class RrdEntry {
- RrdDb rrdDb;
- int count;
-
- RrdEntry(final RrdDb rrdDb) {
- this.rrdDb = rrdDb;
- this.count = 1;
- }
- }
-}
-
-// OLDER VERSION IS HERE
-
-///* ============================================================
-// * JRobin : Pure java implementation of RRDTool's functionality
-// * ============================================================
-// *
-// * Project Info: http://www.jrobin.org
-// * Project Lead: Sasa Markovic (saxon@jrobin.org);
-// *
-// * (C) Copyright 2003-2005, by Sasa Markovic.
-// *
-// * Developers: Sasa Markovic (saxon@jrobin.org)
-// *
-// *
-// * This library is free software; you can redistribute it and/or modify it under the terms
-// * of the GNU Lesser General Public License as published by the Free Software Foundation;
-// * either version 2.1 of the License, or (at your option) any later version.
-// *
-// * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// * See the GNU Lesser General Public License for more details.
-// *
-// * You should have received a copy of the GNU Lesser General Public License along with this
-// * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
-// * Boston, MA 02111-1307, USA.
-// */
-//package org.jrobin.core;
-//
-//import java.io.IOException;
-//import java.util.HashMap;
-//import java.util.Iterator;
-//import java.util.LinkedHashMap;
-//import java.util.Set;
-//
-///**
-// * Class to represent the pool of open RRD files.
-// * // obtain instance to RrdDbPool object
-// * RrdDbPool pool = RrdDbPool.getInstance();
-// *
-// * // request a reference to RrdDb object
-// * String path = "some_relative_or_absolute_path_to_any_RRD_file";
-// * RrdDb rrdDb = RrdDbPool.requestRrdDb(path);
-// *
-// * // reference obtained, do whatever you want with it...
-// * ...
-// * ...
-// *
-// * // once you don't need the reference, release it.
-// * // DO NOT CALL rrdDb.close() - files no longer in use are eventually closed by the pool
-// * pool.release(rrdDb);
-// *
-// *
-// * It's that simple. When the reference is requested for the first time, RrdDbPool will open the RRD file
-// * for you and make some internal note that the RRD file is used only once. When the reference
-// * to the same file (same RRD file path) is requested for the second time, the same RrdDb
-// * reference will be returned, and its usage count will be increased by one. When the
-// * reference is released its usage count will be decremented by one.true
but can be changed at runtime. See
-// * {@link #setLimitedCapacity(boolean)} for more information.
-// */
-// public static final boolean LIMITED_CAPACITY = false;
-// private boolean limitedCapacity = LIMITED_CAPACITY;
-//
-// /**
-// * Constant to represent the priority of the background thread which closes excessive RRD files
-// * which are no longer in use.
-// */
-// public static final int GC_THREAD_PRIORITY = /** Thread.NORM_PRIORITY - */ 1;
-//
-// private HashMapTrue
, if all RRD files are to be closed
-// * when application invokes System.exit()
.
-// * False
otherwise. The default behaviour is true
-// * (all RRD files will be closed on exit).
-// */
-// public synchronized boolean isClosingOnExit() {
-// return closingOnExit;
-// }
-//
-// /**
-// * Sets the exiting behaviour of RrdDbPool.
-// * @param closingOnExit True
, if all RRD files are to be closed
-// * when application invokes System.exit()
.
-// * False
otherwise. The default behaviour is true
-// * (all RRD files will be closed on exit).
-// */
-// public synchronized void setClosingOnExit(boolean closingOnExit) {
-// Runtime runtime = Runtime.getRuntime();
-// runtime.removeShutdownHook(shutdownHook);
-// if(closingOnExit) {
-// runtime.addShutdownHook(shutdownHook);
-// }
-// this.closingOnExit = closingOnExit;
-// }
-//
-// private void startGarbageCollector() {
-// Thread gcThread = new Thread(this, GC_THREAD_NAME);
-// gcThread.setPriority(GC_THREAD_PRIORITY);
-// gcThread.setDaemon(true);
-// gcThread.start();
-// }
-//
-// /**
-// * Returns a reference to an existing RRD file with the specified path.
-// * If the file is already open in the pool, existing reference to it will be returned.
-// * Otherwise, the file is open and a newly created reference to it is returned.
-// *
-// * @param path Relative or absolute path to a RRD file.
-// * @return Reference to a RrdDb object (RRD file).
-// * @throws IOException Thrown in case of I/O error.
-// * @throws RrdException Thrown in case of JRobin specific error.
-// */
-// public synchronized RrdDb requestRrdDb(String path) throws IOException, RrdException {
-// proveActive();
-// poolRequestsCount++;
-// String canonicalPath = getCanonicalPath(path);
-// for(;;) {
-// RrdEntry rrdEntry = rrdMap.get(canonicalPath);
-// if (rrdEntry != null) {
-// // already open, use it!
-// reportUsage(canonicalPath, rrdEntry);
-// poolHitsCount++;
-//// debug("CACHED: " + rrdEntry.dump());
-// return rrdEntry.getRrdDb();
-// }
-// else if(!limitedCapacity || rrdMap.size() < capacity) {
-// // not found, open it
-// RrdDb rrdDb = createRrdDb(path, null);
-// rrdEntry = new RrdEntry(rrdDb);
-// addRrdEntry(canonicalPath, rrdEntry);
-//// debug("ADDED: " + rrdEntry.dump());
-// return rrdDb;
-// }
-// else {
-// // we have to wait
-// try {
-// wait();
-// }
-// catch (InterruptedException e) {
-// throw new RrdException("Request for file '" + path + "' was interrupted");
-// }
-// }
-// }
-// }
-//
-// /**
-// * Returns a reference to a new RRD file. The new file will have the specified
-// * relative or absolute path, and its contents will be provided from the specified
-// * XML file (RRDTool comaptible).
-// *
-// * @param path Relative or absolute path to a new RRD file.
-// * @param xmlPath Relative or absolute path to an existing XML dump file (RRDTool comaptible)
-// * @return Reference to a RrdDb object (RRD file).
-// * @throws IOException Thrown in case of I/O error.
-// * @throws RrdException Thrown in case of JRobin specific error.
-// */
-// public synchronized RrdDb requestRrdDb(String path, String xmlPath)
-// throws IOException, RrdException {
-// return requestNewRrdDb(path, xmlPath);
-// }
-//
-// /**
-// * Returns a reference to a new RRD file. The new file will be created based on the
-// * definition contained in a RrdDef object.
-// *
-// * @param rrdDef RRD definition object
-// * @return Reference to a RrdDb object (RRD file).
-// * @throws IOException Thrown in case of I/O error.
-// * @throws RrdException Thrown in case of JRobin specific error.
-// */
-// public synchronized RrdDb requestRrdDb(RrdDef rrdDef) throws IOException, RrdException {
-// return requestNewRrdDb(rrdDef.getPath(), rrdDef);
-// }
-//
-// private RrdDb requestNewRrdDb(String path, Object creationDef) throws IOException, RrdException {
-// proveActive();
-// poolRequestsCount++;
-// String canonicalPath = getCanonicalPath(path);
-// for(;;) {
-// RrdEntry rrdEntry = rrdMap.get(canonicalPath);
-// if(rrdEntry != null) {
-// // already open
-// removeIfIdle(canonicalPath, rrdEntry);
-// }
-// else if(!limitedCapacity || rrdMap.size() < capacity) {
-// RrdDb rrdDb = createRrdDb(path, creationDef);
-// RrdEntry newRrdEntry = new RrdEntry(rrdDb);
-// addRrdEntry(canonicalPath, newRrdEntry);
-//// debug("ADDED: " + newRrdEntry.dump());
-// return rrdDb;
-// }
-// else {
-// // we have to wait
-// try {
-// wait();
-// }
-// catch (InterruptedException e) {
-// throw new RrdException("Request for file '" + path + "' was interrupted");
-// }
-// }
-// }
-// }
-//
-// private RrdDb createRrdDb(String path, Object creationDef) throws RrdException, IOException {
-// if(creationDef == null) {
-// // existing RRD
-// return new RrdDb(path, getFactory());
-// }
-// else if(creationDef instanceof String) {
-// // XML input
-// return new RrdDb(path, (String) creationDef, getFactory());
-// }
-// else if(creationDef instanceof RrdDef) {
-// // RrdDef
-// return new RrdDb((RrdDef) creationDef, getFactory());
-// }
-// else {
-// throw new RrdException("Unexpected input object type: " +
-// creationDef.getClass().getName());
-// }
-// }
-//
-// private void reportUsage(String canonicalPath, RrdEntry rrdEntry) {
-// if (rrdEntry.reportUsage() == 1) {
-// // must not be garbage collected
-// rrdIdleMap.remove(canonicalPath);
-// }
-// }
-//
-// private void reportRelease(String canonicalPath, RrdEntry rrdEntry) {
-// if (rrdEntry.reportRelease() == 0) {
-// // ready to be garbage collected
-// rrdIdleMap.put(canonicalPath, rrdEntry);
-// }
-// }
-//
-// private void addRrdEntry(String canonicalPath, RrdEntry newRrdEntry) {
-// rrdMap.put(canonicalPath, newRrdEntry);
-// maxUsedCapacity = Math.max(rrdMap.size(), maxUsedCapacity);
-// // notify waiting threads
-// notifyAll();
-// }
-//
-// private void removeIfIdle(String canonicalPath, RrdEntry rrdEntry)
-// throws RrdException, IOException {
-// // already open, check if active (not released)
-// if (rrdEntry.isInUse()) {
-// // not released, not allowed here
-// throw new RrdException("Cannot create new RrdDb file: " +
-// "File '" + canonicalPath + "' already in use");
-// } else {
-// // open but released... safe to close it
-//// debug("WILL BE RECREATED: " + rrdEntry.dump());
-// removeRrdEntry(canonicalPath, rrdEntry);
-// }
-// }
-//
-// private void removeRrdEntry(String canonicalPath, RrdEntry rrdEntry) throws IOException {
-// rrdEntry.closeRrdDb();
-// rrdMap.remove(canonicalPath);
-// rrdIdleMap.remove(canonicalPath);
-//// debug("REMOVED: " + rrdEntry.dump());
-// }
-//
-// /**
-// * Method used to report that the reference to a RRD file is no longer needed. File that
-// * is no longer needed (all references to it are released) is marked 'eligible for
-// * closing'. It will be eventually closed by the pool when the number of open RRD files
-// * becomes too big. Most recently released files will be closed last.
-// *
-// * @param rrdDb Reference to RRD file that is no longer needed.
-// * @throws IOException Thrown in case of I/O error.
-// * @throws RrdException Thrown in case of JRobin specific error.
-// */
-// public synchronized void release(RrdDb rrdDb) throws IOException, RrdException {
-// proveActive();
-// if (rrdDb == null) {
-// // we don't want NullPointerException
-// return;
-// }
-// if (rrdDb.isClosed()) {
-// throw new RrdException("File " + rrdDb.getPath() + " already closed");
-// }
-// String canonicalPath = getCanonicalPath(rrdDb.getPath());
-// if (rrdMap.containsKey(canonicalPath)) {
-// RrdEntry rrdEntry = rrdMap.get(canonicalPath);
-// reportRelease(canonicalPath, rrdEntry);
-//// debug("RELEASED: " + rrdEntry.dump());
-// } else {
-// throw new RrdException("RRD file " + rrdDb.getPath() + " not in the pool");
-// }
-// // notify waiting threads
-// notifyAll();
-// }
-//
-// /**
-// * This method runs garbage collector in a separate thread. If the number of
-// * open RRD files kept in the pool is too big (greater than number
-// * returned from {@link #getCapacity getCapacity()}), garbage collector will try
-// * to close and remove RRD files with a reference count equal to zero.
-// * Never call this method directly.
-// */
-// public void run() {
-//// debug("GC: started");
-// while (active) {
-// synchronized (this) {
-// if (rrdMap.size() >= capacity && rrdIdleMap.size() > 0) {
-// try {
-// String canonicalPath = rrdIdleMap.keySet().iterator().next();
-// RrdEntry rrdEntry = rrdIdleMap.get(canonicalPath);
-//// debug("GC: closing " + rrdEntry.dump());
-// removeRrdEntry(canonicalPath, rrdEntry);
-// } catch (IOException e) {
-// e.printStackTrace();
-// }
-// notifyAll();
-// }
-// else {
-// try {
-//// debug("GC: waiting");
-// wait();
-//// debug("GC: running");
-// } catch (InterruptedException e) {
-// e.printStackTrace();
-// }
-// }
-// }
-// }
-// }
-//
-// protected void finalize() throws IOException {
-// close();
-// }
-//
-// /**
-// * Clears the internal state of the pool entirely. All open RRD files are closed.
-// *
-// * @throws IOException Thrown in case of I/O related error.
-// */
-// public synchronized void reset() throws IOException {
-// Iteratortrue
, if dumped information should contain paths to open files
-// * currently held in the pool, false
otherwise
-// * @return Internal pool state (with an optional list of open RRD files and
-// * the current number of usages for each one).
-// * @throws IOException Thrown in case of I/O error.
-// */
-// public synchronized String dump(boolean dumpFiles) throws IOException {
-// StringBuffer buff = new StringBuffer();
-// buff.append("==== POOL DUMP ===========================\n");
-// buff.append("open=" + rrdMap.size() + ", idle=" + rrdIdleMap.size() + "\n");
-// buff.append("capacity=" + capacity + ", " + "maxUsedCapacity=" + maxUsedCapacity + "\n");
-// buff.append("hits=" + poolHitsCount + ", " + "requests=" + poolRequestsCount + "\n");
-// buff.append("efficiency=" + getPoolEfficiency() + "\n");
-// if(dumpFiles) {
-// buff.append("---- CACHED FILES ------------------------\n");
-// Iteratortrue
if the pool is 'flexible' (by not imposing the strict
-// * limit on the number of simultaneously open files), false
otherwise.
-// */
-// public synchronized boolean isLimitedCapacity() {
-// return limitedCapacity;
-// }
-//
-// /**
-// * Sets the behaviour of the pool. If true
is passed as argument, the pool will never
-// * open more than {@link #getCapacity()} files at any time. If set to false
,
-// * the pool might keep more open files, but only for a short period of time. This method might be
-// * useful if you want avoid OS limits when it comes to the number of simultaneously open files.limitedCapacity
property defaults
-// * to falsetrue
if the pool should be 'flexible' (not imposing the strict
-// * limit on the number of simultaneously open files), false
otherwise.
-// */
-// public synchronized void setLimitedCapacity(boolean limitedCapacity) {
-// this.limitedCapacity = limitedCapacity;
-// }
-//
-// private void proveActive() throws IOException {
-// if(!active) {
-// throw new IOException("RrdDbPool is already closed");
-// }
-// }
-//
-// /**
-// * Checks if the pool is active. You can request RrdDb references only from the active pool. The
-// * pool is deactived when the {@link #close()} method is called.
-// * @return true
if active, false
otherwise.
-// */
-// public synchronized boolean isActive() {
-// return active;
-// }
-//}
-//
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdDef.java b/apps/jrobin/java/src/org/jrobin/core/RrdDef.java
deleted file mode 100644
index e5369761d8..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdDef.java
+++ /dev/null
@@ -1,694 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.*;
-
-/**
- * Class to represent definition of new Round Robin Database (RRD).
- * Object of this class is used to create
- * new RRD from scratch - pass its reference as a RrdDb
constructor
- * argument (see documentation for {@link RrdDb RrdDb} class). RrdDef
- * object does not actually create new RRD. It just holds all necessary
- * information which will be used during the actual creation process.
- *
- *
- * RrdDef provides API to set all these elements. For the complete explanation of all
- * RRD definition parameters, see RRDTool's
- * rrdcreate man page.
- * RrdDb
constructor, new RRD will be created using the
- * specified path. DsDef
.
- *
- * @param dsDef Datasource definition.
- * @throws RrdException Thrown if new datasource definition uses already used data
- * source name.
- */
- public void addDatasource(final DsDef dsDef) throws RrdException {
- if (dsDefs.contains(dsDef)) {
- throw new RrdException("Datasource already defined: " + dsDef.dump());
- }
- dsDefs.add(dsDef);
- }
-
- /**
- * Adds single datasource to RRD definition by specifying its data source name, source type,
- * heartbeat, minimal and maximal value. For the complete explanation of all data
- * source definition parameters see RRDTool's
- * rrdcreate man page.
- * Double.NaN
if unknown.
- * @param maxValue Maximal acceptable value. Use Double.NaN
if unknown.
- * @throws RrdException Thrown if new datasource definition uses already used data
- * source name.
- */
- public void addDatasource(final String dsName, final String dsType, final long heartbeat, final double minValue, final double maxValue) throws RrdException {
- addDatasource(new DsDef(dsName, dsType, heartbeat, minValue, maxValue));
- }
-
- /**
- * Adds single datasource to RRD definition from a RRDTool-like
- * datasource definition string. The string must have six elements separated with colons
- * (:) in the following order:
- *
- * DS:name:type:heartbeat:minValue:maxValue
- *
- * For example:
- *
- * DS:input:COUNTER:600:0:U
- *
- * For more information on datasource definition parameters see rrdcreate
- * man page.
- *
- * @param rrdToolDsDef Datasource definition string with the syntax borrowed from RRDTool.
- * @throws RrdException Thrown if invalid string is supplied.
- */
- public void addDatasource(final String rrdToolDsDef) throws RrdException {
- final RrdException rrdException = new RrdException("Wrong rrdtool-like datasource definition: " + rrdToolDsDef);
- final StringTokenizer tokenizer = new StringTokenizer(rrdToolDsDef, ":");
- if (tokenizer.countTokens() != 6) {
- throw rrdException;
- }
- final String[] tokens = new String[6];
- for (int curTok = 0; tokenizer.hasMoreTokens(); curTok++) {
- tokens[curTok] = tokenizer.nextToken();
- }
- if (!tokens[0].equalsIgnoreCase("DS")) {
- throw rrdException;
- }
- final String dsName = tokens[1];
- final String dsType = tokens[2];
- long dsHeartbeat;
- try {
- dsHeartbeat = Long.parseLong(tokens[3]);
- }
- catch (final NumberFormatException nfe) {
- throw rrdException;
- }
- double minValue = Double.NaN;
- if (!tokens[4].equalsIgnoreCase("U")) {
- try {
- minValue = Double.parseDouble(tokens[4]);
- }
- catch (final NumberFormatException nfe) {
- throw rrdException;
- }
- }
- double maxValue = Double.NaN;
- if (!tokens[5].equalsIgnoreCase("U")) {
- try {
- maxValue = Double.parseDouble(tokens[5]);
- }
- catch (final NumberFormatException nfe) {
- throw rrdException;
- }
- }
- addDatasource(new DsDef(dsName, dsType, dsHeartbeat, minValue, maxValue));
- }
-
- /**
- * Adds data source definitions to RRD definition in bulk.
- *
- * @param dsDefs Array of data source definition objects.
- * @throws RrdException Thrown if duplicate data source name is used.
- */
- public void addDatasource(final DsDef[] dsDefs) throws RrdException {
- for (final DsDef dsDef : dsDefs) {
- addDatasource(dsDef);
- }
- }
-
- /**
- * Adds single archive definition represented with object of class ArcDef
.
- *
- * @param arcDef Archive definition.
- * @throws RrdException Thrown if archive with the same consolidation function
- * and the same number of steps is already added.
- */
- public void addArchive(final ArcDef arcDef) throws RrdException {
- if (arcDefs.contains(arcDef)) {
- throw new RrdException("Archive already defined: " + arcDef.dump());
- }
- arcDefs.add(arcDef);
- }
-
- /**
- * Adds archive definitions to RRD definition in bulk.
- *
- * @param arcDefs Array of archive definition objects
- * @throws RrdException Thrown if RRD definition already contains archive with
- * the same consolidation function and the same number of steps.
- */
- public void addArchive(final ArcDef[] arcDefs) throws RrdException {
- for (final ArcDef arcDef : arcDefs) {
- addArchive(arcDef);
- }
- }
-
- /**
- * Adds single archive definition by specifying its consolidation function, X-files factor,
- * number of steps and rows. For the complete explanation of all archive
- * definition parameters see RRDTool's
- * rrdcreate man page.
- *
- * RRA:consolidationFunction:XFilesFactor:steps:rows
- *
- * For example:
- *
- * RRA:AVERAGE:0.5:10:1000
- *
- * For more information on archive definition parameters see rrdcreate
- * man page.
- *
- * @param rrdToolArcDef Archive definition string with the syntax borrowed from RRDTool.
- * @throws RrdException Thrown if invalid string is supplied.
- */
- public void addArchive(final String rrdToolArcDef) throws RrdException {
- final RrdException rrdException = new RrdException("Wrong rrdtool-like archive definition: " + rrdToolArcDef);
- final StringTokenizer tokenizer = new StringTokenizer(rrdToolArcDef, ":");
- if (tokenizer.countTokens() != 5) {
- throw rrdException;
- }
- final String[] tokens = new String[5];
- for (int curTok = 0; tokenizer.hasMoreTokens(); curTok++) {
- tokens[curTok] = tokenizer.nextToken();
- }
- if (!tokens[0].equalsIgnoreCase("RRA")) {
- throw rrdException;
- }
- final String consolFun = tokens[1];
- double xff;
- try {
- xff = Double.parseDouble(tokens[2]);
- }
- catch (final NumberFormatException nfe) {
- throw rrdException;
- }
- int steps;
- try {
- steps = Integer.parseInt(tokens[3]);
- }
- catch (final NumberFormatException nfe) {
- throw rrdException;
- }
- int rows;
- try {
- rows = Integer.parseInt(tokens[4]);
- }
- catch (final NumberFormatException nfe) {
- throw rrdException;
- }
- addArchive(new ArcDef(consolFun, xff, steps, rows));
- }
-
- void validate() throws RrdException {
- if (dsDefs.size() == 0) {
- throw new RrdException("No RRD datasource specified. At least one is needed.");
- }
- if (arcDefs.size() == 0) {
- throw new RrdException("No RRD archive specified. At least one is needed.");
- }
- }
-
- /**
- * Returns all data source definition objects specified so far.
- *
- * @return Array of data source definition objects
- */
- public DsDef[] getDsDefs() {
- return dsDefs.toArray(new DsDef[0]);
- }
-
- /**
- * Returns all archive definition objects specified so far.
- *
- * @return Array of archive definition objects.
- */
- public ArcDef[] getArcDefs() {
- return arcDefs.toArray(new ArcDef[0]);
- }
-
- /**
- * Returns number of defined datasources.
- *
- * @return Number of defined datasources.
- */
- public int getDsCount() {
- return dsDefs.size();
- }
-
- /**
- * Returns number of defined archives.
- *
- * @return Number of defined archives.
- */
- public int getArcCount() {
- return arcDefs.size();
- }
-
- /**
- * Returns string that represents all specified RRD creation parameters. Returned string
- * has the syntax of RRDTool's create
command.
- *
- * @return Dumped content of RrdDb
object.
- */
- public String dump() {
- final StringBuffer buffer = new StringBuffer("create \"");
- buffer.append(path).append("\"");
- buffer.append(" --start ").append(getStartTime());
- buffer.append(" --step ").append(getStep()).append(" ");
- for (final DsDef dsDef : dsDefs) {
- buffer.append(dsDef.dump()).append(" ");
- }
- for (final ArcDef arcDef : arcDefs) {
- buffer.append(arcDef.dump()).append(" ");
- }
- return buffer.toString().trim();
- }
-
- String getRrdToolCommand() {
- return dump();
- }
-
- void removeDatasource(final String dsName) throws RrdException {
- for (int i = 0; i < dsDefs.size(); i++) {
- final DsDef dsDef = dsDefs.get(i);
- if (dsDef.getDsName().equals(dsName)) {
- dsDefs.remove(i);
- return;
- }
- }
- throw new RrdException("Could not find datasource named '" + dsName + "'");
- }
-
- void saveSingleDatasource(final String dsName) {
- final Iterator
- *
- *
- * @param obj The second RrdDef object
- * @return true if RrdDefs match exactly, false otherwise
- */
- public boolean equals(final Object obj) {
- if (obj == null || !(obj instanceof RrdDef)) {
- return false;
- }
- final RrdDef rrdDef2 = (RrdDef) obj;
- // check primary RRD step
- if (step != rrdDef2.step) {
- return false;
- }
- // check datasources
- final DsDef[] dsDefs = getDsDefs();
- final DsDef[] dsDefs2 = rrdDef2.getDsDefs();
- if (dsDefs.length != dsDefs2.length) {
- return false;
- }
- for (final DsDef dsDef : dsDefs) {
- boolean matched = false;
- for (final DsDef dsDef2 : dsDefs2) {
- if (dsDef.exactlyEqual(dsDef2)) {
- matched = true;
- break;
- }
- }
- // this datasource could not be matched
- if (!matched) {
- return false;
- }
- }
- // check archives
- final ArcDef[] arcDefs = getArcDefs();
- final ArcDef[] arcDefs2 = rrdDef2.getArcDefs();
- if (arcDefs.length != arcDefs2.length) {
- return false;
- }
- for (final ArcDef arcDef : arcDefs) {
- boolean matched = false;
- for (final ArcDef arcDef2 : arcDefs2) {
- if (arcDef.exactlyEqual(arcDef2)) {
- matched = true;
- break;
- }
- }
- // this archive could not be matched
- if (!matched) {
- return false;
- }
- }
- // everything matches
- return true;
- }
-
- public int hashCode() {
- int hashCode = (int)step;
- for (final DsDef dsDef : dsDefs) {
- hashCode *= dsDef.hashCode();
- }
- for (final ArcDef arcDef : arcDefs) {
- hashCode *= arcDef.hashCode();
- }
- return hashCode;
- }
-
- /**
- * Removes all datasource definitions.
- */
- public void removeDatasources() {
- dsDefs.clear();
- }
-
- /**
- * Removes all RRA archive definitions.
- */
- public void removeArchives() {
- arcDefs.clear();
- }
-
- public String toString() {
- return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()) + "[arcDefs=[" + join(getArcDefs()) + "],dsDefs=[" + join(getDsDefs()) + "]]";
- }
-
- private String join(final Object[] objs) {
- final StringBuffer sb = new StringBuffer();
- for (int i = 0; i < objs.length; i++) {
- sb.append(objs[i]);
- if (i != (objs.length - 1)) {
- sb.append(",");
- }
- }
- return sb.toString();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdDefTemplate.java b/apps/jrobin/java/src/org/jrobin/core/RrdDefTemplate.java
deleted file mode 100644
index 7e667a8072..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdDefTemplate.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core;
-
-import org.w3c.dom.Node;
-import org.xml.sax.InputSource;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Calendar;
-
-/**
- * Class used to create an arbitrary number of {@link RrdDef} (RRD definition) objects
- * from a single XML template. XML template can be supplied as an XML InputSource,
- * XML file or XML formatted string.
- *
- * <rrd_def>
- * <path>test.rrd</path>
- * <!-- not mandatory -->
- * <start>1000123456</start>
- * <!-- not mandatory -->
- * <step>300</step>
- * <!-- at least one datasource must be supplied -->
- * <datasource>
- * <name>input</name>
- * <type>COUNTER</type>
- * <heartbeat>300</heartbeat>
- * <min>0</min>
- * <max>U</max>
- * </datasource>
- * <datasource>
- * <name>temperature</name>
- * <type>GAUGE</type>
- * <heartbeat>400</heartbeat>
- * <min>U</min>
- * <max>1000</max>
- * </datasource>
- * <!-- at least one archive must be supplied -->
- * <archive>
- * <cf>AVERAGE</cf>
- * <xff>0.5</xff>
- * <steps>1</steps>
- * <rows>600</rows>
- * </archive>
- * <archive>
- * <cf>MAX</cf>
- * <xff>0.6</xff>
- * <steps>6</steps>
- * <rows>7000</rows>
- * </archive>
- * </rrd_def>
- *
- * Notes on the template syntax:
- *
- * Any template value (text between <some_tag>
and
- * </some_tag>
) can be replaced with
- * a variable of the following form: ${variable_name}
. Use
- * {@link XmlTemplate#setVariable(String, String) setVariable()}
- * methods from the base class to replace template variables with real values
- * at runtime.
- *
- *
- * You should create new RrdDefTemplate object only once for each XML template. Single template
- * object can be reused to create as many RrdDef objects as needed, with different values
- * specified for template variables. XML synatax check is performed only once - the first
- * definition object gets created relatively slowly, but it will be created much faster next time.
- */
-public class RrdDefTemplate extends XmlTemplate {
- /**
- * Creates RrdDefTemplate object from any parsable XML input source. Read general information
- * for this class to find an example of a properly formatted RrdDef XML source.
- *
- * @param xmlInputSource Xml input source
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of XML related error (parsing error, for example)
- */
- public RrdDefTemplate(InputSource xmlInputSource) throws IOException, RrdException {
- super(xmlInputSource);
- }
-
- /**
- * Creates RrdDefTemplate object from the string containing XML template.
- * Read general information for this class to see an example of a properly formatted XML source.
- *
- * @param xmlString String containing XML template
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of XML related error (parsing error, for example)
- */
- public RrdDefTemplate(String xmlString) throws IOException, RrdException {
- super(xmlString);
- }
-
- /**
- * Creates RrdDefTemplate object from the file containing XML template.
- * Read general information for this class to see an example of a properly formatted XML source.
- *
- * @param xmlFile File object representing file with XML template
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of XML related error (parsing error, for example)
- */
- public RrdDefTemplate(File xmlFile) throws IOException, RrdException {
- super(xmlFile);
- }
-
- /**
- * Returns RrdDef object constructed from the underlying XML template. Before this method
- * is called, values for all non-optional placeholders must be supplied. To specify
- * placeholder values at runtime, use some of the overloaded
- * {@link XmlTemplate#setVariable(String, String) setVariable()} methods. Once this method
- * returns, all placeholder values are preserved. To remove them all, call inhereted
- * {@link XmlTemplate#clearValues() clearValues()} method explicitly.
- * <rrd_def>
- * <path>${path}</path>
- * <step>300</step>
- * ...
- *
- *
- * RrdDefTemplate t = new RrdDefTemplate(new File(template.xml));
- *
- *
- * t.setVariable("path", "demo/test.rrd");
- *
- *
- * RrdDef def = t.getRrdDef();
- * RrdDb rrd = new RrdDb(def);
- * rrd.close();
- *
- * RrdException
- * (for various JRobin related errors) or IOException
- * (for various I/O errors).
- *
- * @author Sasa Markovic
- */
-public class RrdException extends Exception {
- private static final long serialVersionUID = 6999702149227009855L;
-
- public RrdException() {
- super();
- }
-
- public RrdException(final String message) {
- super(message);
- }
-
- public RrdException(final Throwable cause) {
- super(cause);
- }
-
- public RrdException(final String message, final Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdFileBackend.java b/apps/jrobin/java/src/org/jrobin/core/RrdFileBackend.java
deleted file mode 100644
index ee213f6a11..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdFileBackend.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.IOException;
-import java.io.RandomAccessFile;
-
-/**
- * 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.
- * false
. There is no need to cache anything in high-level classes
- * since all RRD bytes are already in memory.
- */
- protected boolean isCachingAllowed() {
- return false;
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdMemoryBackendFactory.java b/apps/jrobin/java/src/org/jrobin/core/RrdMemoryBackendFactory.java
deleted file mode 100644
index e326deecd5..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdMemoryBackendFactory.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.util.HashMap;
-
-/**
- * Factory class which creates actual {@link RrdMemoryBackend} objects. JRobin's support
- * for in-memory RRDs is still experimental. You should know that all active RrdMemoryBackend
- * objects are held in memory, each backend object stores RRD data in one big byte array. This
- * implementation is therefore quite basic and memory hungry but runs very fast.
- * new RrdDb(path)
call. To release allocated
- * memory, you'll have to call {@link #delete(String) delete(path)} method of this class.
- */
-public class RrdMemoryBackendFactory extends RrdBackendFactory {
- /**
- * factory name, "MEMORY"
- */
- public static final String NAME = "MEMORY";
- private HashMapfalse
- */
- protected boolean isCachingAllowed() {
- return false;
- }
-
- public static String getLockInfo() {
- return counters.getInfo();
- }
-
- static class Counters {
- long locks, quickLocks, unlocks, locked, errors;
-
- synchronized void registerQuickLock() {
- locks++;
- quickLocks++;
- locked++;
- }
-
- synchronized void registerDelayedLock() {
- locks++;
- locked++;
- }
-
- synchronized void registerUnlock() {
- unlocks++;
- locked--;
- }
-
- synchronized void registerError() {
- errors++;
- }
-
- synchronized String getInfo() {
- return "LOCKS=" + locks + ", " + "UNLOCKS=" + unlocks + ", " +
- "DELAYED_LOCKS=" + (locks - quickLocks) + ", " + "LOCKED=" + locked + ", " +
- "ERRORS=" + errors;
- }
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdSafeFileBackendFactory.java b/apps/jrobin/java/src/org/jrobin/core/RrdSafeFileBackendFactory.java
deleted file mode 100644
index ae6fb4e9c4..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdSafeFileBackendFactory.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core;
-
-import java.io.IOException;
-
-/**
- * Factory class which creates actual {@link RrdSafeFileBackend} objects.
- */
-public class RrdSafeFileBackendFactory extends RrdFileBackendFactory {
- /**
- * Default time (in milliseconds) this backend will wait for a file lock.
- */
- public static final long LOCK_WAIT_TIME = 3000L;
- private static long lockWaitTime = LOCK_WAIT_TIME;
-
- /**
- * Default time between two consecutive file locking attempts.
- */
- public static final long LOCK_RETRY_PERIOD = 50L;
- private static long lockRetryPeriod = LOCK_RETRY_PERIOD;
-
- /**
- * factory name, "SAFE"
- */
- public static final String NAME = "SAFE";
-
- /**
- * Creates RrdSafeFileBackend object for the given file path.
- *
- * @param path File path
- * @param readOnly This parameter is ignored
- * @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) throws IOException {
- return new RrdSafeFileBackend(path, lockWaitTime, lockRetryPeriod);
- }
-
- /**
- * Returns the name of this factory.
- *
- * @return Factory name (equals to string "SAFE")
- */
- public String getFactoryName() {
- return NAME;
- }
-
- /**
- * Returns time this backend will wait for a file lock.
- *
- * @return Time (in milliseconds) this backend will wait for a file lock.
- */
- public static long getLockWaitTime() {
- return lockWaitTime;
- }
-
- /**
- * Sets time this backend will wait for a file lock.
- *
- * @param lockWaitTime Maximum lock wait time (in milliseconds)
- */
- public static void setLockWaitTime(long lockWaitTime) {
- RrdSafeFileBackendFactory.lockWaitTime = lockWaitTime;
- }
-
- /**
- * Returns time between two consecutive file locking attempts.
- *
- * @return Time (im milliseconds) between two consecutive file locking attempts.
- */
- public static long getLockRetryPeriod() {
- return lockRetryPeriod;
- }
-
- /**
- * Sets time between two consecutive file locking attempts.
- *
- * @param lockRetryPeriod time (in milliseconds) between two consecutive file locking attempts.
- */
- public static void setLockRetryPeriod(long lockRetryPeriod) {
- RrdSafeFileBackendFactory.lockRetryPeriod = lockRetryPeriod;
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdString.java b/apps/jrobin/java/src/org/jrobin/core/RrdString.java
deleted file mode 100644
index 14be148e60..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdString.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.IOException;
-
-class RrdString extends RrdPrimitive {
- private String cache;
-
- RrdString(final RrdUpdater updater, final boolean isConstant) throws IOException {
- super(updater, RrdPrimitive.RRD_STRING, isConstant);
- }
-
- RrdString(final RrdUpdater updater) throws IOException {
- this(updater, false);
- }
-
- void set(final 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();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdToolReader.java b/apps/jrobin/java/src/org/jrobin/core/RrdToolReader.java
deleted file mode 100644
index 97f9c121ee..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdToolReader.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core;
-
-import java.io.IOException;
-
-import org.jrobin.core.jrrd.RRDatabase;
-
-class RrdToolReader extends DataImporter {
- private RRDatabase rrd;
-
- RrdToolReader(String rrdPath) throws IOException,RrdException {
- rrd = new RRDatabase(rrdPath);
- }
-
- String getVersion() {
- return rrd.getHeader().getVersion();
- }
-
- long getLastUpdateTime() {
- return Util.getTimestamp(rrd.getLastUpdate());
- }
-
- long getStep() {
- return rrd.getHeader().getPDPStep();
- }
-
- int getDsCount() {
- return rrd.getHeader().getDSCount();
- }
-
- int getArcCount() throws RrdException, IOException {
- return rrd.getNumArchives();
- }
-
- String getDsName(int dsIndex) {
- return rrd.getDataSource(dsIndex).getName();
- }
-
- String getDsType(int dsIndex) {
- return rrd.getDataSource(dsIndex).getType().toString();
- }
-
- long getHeartbeat(int dsIndex) {
- return rrd.getDataSource(dsIndex).getMinimumHeartbeat();
- }
-
- double getMinValue(int dsIndex) {
- return rrd.getDataSource(dsIndex).getMinimum();
- }
-
- double getMaxValue(int dsIndex) {
- return rrd.getDataSource(dsIndex).getMaximum();
- }
-
- double getLastValue(int dsIndex) {
- String valueStr = rrd.getDataSource(dsIndex).getPDPStatusBlock().getLastReading();
- return Util.parseDouble(valueStr);
- }
-
- double getAccumValue(int dsIndex) {
- return rrd.getDataSource(dsIndex).getPDPStatusBlock().getValue();
- }
-
- long getNanSeconds(int dsIndex) {
- return rrd.getDataSource(dsIndex).getPDPStatusBlock().getUnknownSeconds();
- }
-
- String getConsolFun(int arcIndex) {
- return rrd.getArchive(arcIndex).getType().toString();
- }
-
- double getXff(int arcIndex) {
- return rrd.getArchive(arcIndex).getXff();
- }
-
- int getSteps(int arcIndex) {
- return rrd.getArchive(arcIndex).getPdpCount();
- }
-
- int getRows(int arcIndex) throws RrdException, IOException {
- return rrd.getArchive(arcIndex).getRowCount();
- }
-
- double getStateAccumValue(int arcIndex, int dsIndex) throws RrdException, IOException {
- return rrd.getArchive(arcIndex).getCDPStatusBlock(dsIndex).getValue();
- }
-
- int getStateNanSteps(int arcIndex, int dsIndex) throws RrdException, IOException {
- return rrd.getArchive(arcIndex).getCDPStatusBlock(dsIndex).getUnknownDatapoints();
- }
-
- double[] getValues(int arcIndex, int dsIndex) throws RrdException, IOException,RrdException {
- return rrd.getArchive(arcIndex).getValues()[dsIndex];
- }
-
- void release() throws IOException {
- if (rrd != null) {
- rrd.close();
- rrd = null;
- }
- }
-
- protected void finalize() throws Throwable {
- super.finalize();
- release();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/RrdToolkit.java b/apps/jrobin/java/src/org/jrobin/core/RrdToolkit.java
deleted file mode 100644
index 6e68348d62..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/RrdToolkit.java
+++ /dev/null
@@ -1,658 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.core;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.Arrays;
-
-/**
- * Class used to perform various complex operations on RRD files. Use an instance of the
- * RrdToolkit class to:
- *
- *
- * All these operations can be performed on the copy of the original RRD file, or on the
- * original file itself (with possible backup file creation).
- * true
). The backup file will be created in the same
- * directory as the original one with .bak
extension added to the
- * original name.true
). The backup file will be created in the same
- * directory as the original one with .bak
extension added to the
- * original name.true
). The backup file will be created in the same
- * directory as the original one with .bak
extension added to the
- * original name.true
). The backup file will be created in the same
- * directory as the original one with .bak
extension added to the
- * original name.true
if archived values less than
- * newMinValue
should be set to NaN; set to false, otherwise.
- * @throws RrdException Thrown in case of JRobin specific error
- * @throws IOException Thrown in case of I/O error
- */
- public static void setDsMinValue(String sourcePath, String datasourceName,
- double newMinValue, boolean filterArchivedValues) throws RrdException, IOException {
- RrdDb rrd = new RrdDb(sourcePath);
- try {
- Datasource ds = rrd.getDatasource(datasourceName);
- ds.setMinValue(newMinValue, filterArchivedValues);
- }
- finally {
- rrd.close();
- }
- }
-
- /**
- * Sets datasource max value to a new value.
- *
- * @param sourcePath Path to exisiting RRD file (will be updated)
- * @param datasourceName Name of the datasource in the specified RRD file
- * @param newMaxValue New max value for the datasource
- * @param filterArchivedValues set to true
if archived values greater than
- * newMaxValue
should be set to NaN; set to false, otherwise.
- * @throws RrdException Thrown in case of JRobin specific error
- * @throws IOException Thrown in case of I/O error
- */
- public static void setDsMaxValue(String sourcePath, String datasourceName,
- double newMaxValue, boolean filterArchivedValues) throws RrdException, IOException {
- RrdDb rrd = new RrdDb(sourcePath);
- try {
- Datasource ds = rrd.getDatasource(datasourceName);
- ds.setMaxValue(newMaxValue, filterArchivedValues);
- }
- finally {
- rrd.close();
- }
- }
-
- /**
- * Updates valid value range for the given datasource.
- *
- * @param sourcePath Path to exisiting RRD file (will be updated)
- * @param datasourceName Name of the datasource in the specified RRD file
- * @param newMinValue New min value for the datasource
- * @param newMaxValue New max value for the datasource
- * @param filterArchivedValues set to true
if archived values outside
- * of the specified min/max range should be replaced with NaNs.
- * @throws RrdException Thrown in case of JRobin specific error
- * @throws IOException Thrown in case of I/O error
- */
- public static void setDsMinMaxValue(String sourcePath, String datasourceName,
- double newMinValue, double newMaxValue, boolean filterArchivedValues)
- throws RrdException, IOException {
- RrdDb rrd = new RrdDb(sourcePath);
- try {
- Datasource ds = rrd.getDatasource(datasourceName);
- ds.setMinMaxValue(newMinValue, newMaxValue, filterArchivedValues);
- }
- finally {
- rrd.close();
- }
- }
-
- /**
- * Sets single archive's X-files factor to a new value.
- *
- * @param sourcePath Path to existing RRD file (will be updated)
- * @param consolFun Consolidation function of the target archive
- * @param steps Number of sptes of the target archive
- * @param newXff New X-files factor for the target archive
- * @throws RrdException Thrown in case of JRobin specific error
- * @throws IOException Thrown in case of I/O error
- */
- public static void setArcXff(String sourcePath, String consolFun, int steps,
- double newXff) throws RrdException, IOException {
- RrdDb rrd = new RrdDb(sourcePath);
- try {
- Archive arc = rrd.getArchive(consolFun, steps);
- arc.setXff(newXff);
- }
- finally {
- rrd.close();
- }
- }
-
- /**
- * Creates new RRD file based on the existing one, but with a different
- * size (number of rows) for a single archive. The archive to be resized
- * is identified by its consolidation function and the number of steps.
- *
- * @param sourcePath Path to the source RRD file (will not be modified)
- * @param destPath Path to the new RRD file (will be created)
- * @param consolFun Consolidation function of the archive to be resized
- * @param numSteps Number of steps of the archive to be resized
- * @param newRows New archive size (number of archive rows)
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public static void resizeArchive(String sourcePath, String destPath, String consolFun,
- int numSteps, int newRows)
- throws IOException, RrdException {
- if (Util.sameFilePath(sourcePath, destPath)) {
- throw new RrdException("Source and destination paths are the same");
- }
- if (newRows < 2) {
- throw new RrdException("New arcihve size must be at least 2");
- }
- RrdDb rrdSource = new RrdDb(sourcePath);
- try {
- RrdDef rrdDef = rrdSource.getRrdDef();
- ArcDef arcDef = rrdDef.findArchive(consolFun, numSteps);
- if (arcDef.getRows() != newRows) {
- arcDef.setRows(newRows);
- rrdDef.setPath(destPath);
- RrdDb rrdDest = new RrdDb(rrdDef);
- try {
- rrdSource.copyStateTo(rrdDest);
- }
- finally {
- rrdDest.close();
- }
- }
- }
- finally {
- rrdSource.close();
- }
- }
-
- /**
- * Modifies existing RRD file, by resizing its chosen archive. The archive to be resized
- * is identified by its consolidation function and the number of steps.
- *
- * @param sourcePath Path to the RRD file (will be modified)
- * @param consolFun Consolidation function of the archive to be resized
- * @param numSteps Number of steps of the archive to be resized
- * @param newRows New archive size (number of archive rows)
- * @param saveBackup true, if backup of the original file should be created;
- * false, otherwise
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public static void resizeArchive(String sourcePath, String consolFun,
- int numSteps, int newRows, boolean saveBackup)
- throws IOException, RrdException {
- String destPath = Util.getTmpFilename();
- resizeArchive(sourcePath, destPath, consolFun, numSteps, newRows);
- copyFile(destPath, sourcePath, saveBackup);
- }
-
- private static void deleteFile(File file) throws IOException {
- if (file.exists() && !file.delete()) {
- throw new IOException("Could not delete file: " + file.getCanonicalPath());
- }
- }
-
- /**
- * Splits single RRD file with several datasources into a number of smaller RRD files
- * with a single datasource in it. All archived values are preserved. If
- * you have a RRD file named 'traffic.rrd' with two datasources, 'in' and 'out', this
- * method will create two files (with a single datasource, in the same directory)
- * named 'in-traffic.rrd' and 'out-traffic.rrd'.
- *
- * @param sourcePath Path to a RRD file with multiple datasources defined
- * @throws IOException Thrown in case of I/O error
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public static void split(String sourcePath) throws IOException, RrdException {
- RrdDb rrdSource = new RrdDb(sourcePath);
- try {
- String[] dsNames = rrdSource.getDsNames();
- for (String dsName : dsNames) {
- RrdDef rrdDef = rrdSource.getRrdDef();
- rrdDef.setPath(createSplitPath(dsName, sourcePath));
- rrdDef.saveSingleDatasource(dsName);
- RrdDb rrdDest = new RrdDb(rrdDef);
- try {
- rrdSource.copyStateTo(rrdDest);
- }
- finally {
- rrdDest.close();
- }
- }
- }
- finally {
- rrdSource.close();
- }
- }
-
- /**
- * Returns list of canonical file names with the specified extension in the given directory. This
- * method is not RRD related, but might come handy to create a quick list of all RRD files
- * in the given directory.
- *
- * @param directory Source directory
- * @param extension File extension (like ".rrd", ".jrb", ".rrd.jrb")
- * @param resursive true if all subdirectories should be traversed for the same extension, false otherwise
- * @return Array of sorted canonical file names with the given extension
- * @throws IOException Thrown in case of I/O error
- */
- public static String[] getCanonicalPaths(String directory, final String extension, boolean resursive)
- throws IOException {
- File baseDir = new File(directory);
- if (!baseDir.isDirectory()) {
- throw new IOException("Not a directory: " + directory);
- }
- List
- *
- * Double.NaN
.
- *
- * @author Sasa Markovic
- */
-public class Sample {
- private RrdDb parentDb;
- private long time;
- private String[] dsNames;
- private double[] values;
-
- Sample(final RrdDb parentDb, final long time) throws IOException {
- this.parentDb = parentDb;
- this.time = time;
- this.dsNames = parentDb.getDsNames();
- values = new double[dsNames.length];
- clearCurrentValues();
- }
-
- private Sample clearCurrentValues() {
- for (int i = 0; i < values.length; i++) {
- values[i] = Double.NaN;
- }
- return this;
- }
-
- /**
- * Sets single data source value in the sample.
- *
- * @param dsName Data source name.
- * @param value Data source value.
- * @return This Sample
object
- * @throws RrdException Thrown if invalid data source name is supplied.
- */
- public Sample setValue(final String dsName, final double value) throws RrdException {
- for (int i = 0; i < values.length; i++) {
- if (dsNames[i].equals(dsName)) {
- values[i] = value;
- return this;
- }
- }
- throw new RrdException("Datasource " + dsName + " not found");
- }
-
- /**
- * Sets single datasource value using data source index. Data sources are indexed by
- * the order specified during RRD creation (zero-based).
- *
- * @param i Data source index
- * @param value Data source values
- * @return This Sample
object
- * @throws RrdException Thrown if data source index is invalid.
- */
- public Sample setValue(final int i, final double value) throws RrdException {
- if (i < values.length) {
- values[i] = value;
- return this;
- }
- else {
- throw new RrdException("Sample datasource index " + i + " out of bounds");
- }
- }
-
- /**
- * Sets some (possibly all) data source values in bulk. Data source values are
- * assigned in the order of their definition inside the RRD.
- *
- * @param values Data source values.
- * @return This Sample
object
- * @throws RrdException Thrown if the number of supplied values is zero or greater
- * than the number of data sources defined in the RRD.
- */
- public Sample setValues(final double[] values) throws RrdException {
- if (values.length <= this.values.length) {
- System.arraycopy(values, 0, this.values, 0, values.length);
- return this;
- }
- else {
- throw new RrdException("Invalid number of values specified (found " + values.length + ", only " + dsNames.length + " allowed)");
- }
- }
-
- /**
- * Returns all current data source values in the sample.
- *
- * @return Data source values.
- */
- public double[] getValues() {
- return values;
- }
-
- /**
- * Returns sample timestamp (in seconds, without milliseconds).
- *
- * @return Sample timestamp.
- */
- public long getTime() {
- return time;
- }
-
- /**
- * Sets sample timestamp. Timestamp should be defined in seconds (without milliseconds).
- *
- * @param time New sample timestamp.
- * @return This Sample
object
- */
- public Sample setTime(final long time) {
- this.time = time;
- return this;
- }
-
- /**
- * Returns an array of all data source names. If you try to set value for the data source
- * name not in this array, an exception is thrown.
- *
- * @return Acceptable data source names.
- */
- public String[] getDsNames() {
- return dsNames;
- }
-
- /**
- * Sets sample timestamp and data source values in a fashion similar to RRDTool.
- * Argument string should be composed in the following way:
- * timestamp:value1:value2:...:valueN
.
- *
- * 1005234132:12.2:35.6:U:24.5
- * NOW:12.2:35.6:U:24.5
- *
- * 'N' stands for the current timestamp (can be replaced with 'NOW')Sample
object
- * @throws RrdException Thrown if too many datasource values are supplied
- */
- public Sample set(final String timeAndValues) throws RrdException {
- final StringTokenizer tokenizer = new StringTokenizer(timeAndValues, ":", false);
- final int tokenCount = tokenizer.countTokens();
- if (tokenCount > values.length + 1) {
- throw new RrdException("Invalid number of values specified (found " + values.length + ", " + dsNames.length + " allowed)");
- }
- final String timeToken = tokenizer.nextToken();
- try {
- time = Long.parseLong(timeToken);
- }
- catch (final NumberFormatException nfe) {
- if (timeToken.equalsIgnoreCase("N") || timeToken.equalsIgnoreCase("NOW")) {
- time = Util.getTime();
- }
- else {
- throw new RrdException("Invalid sample timestamp: " + timeToken);
- }
- }
- for (int i = 0; tokenizer.hasMoreTokens(); i++) {
- try {
- values[i] = Double.parseDouble(tokenizer.nextToken());
- }
- catch (final NumberFormatException nfe) {
- // NOP, value is already set to NaN
- }
- }
- return this;
- }
-
- /**
- * Stores sample in the corresponding RRD. If the update operation succeedes,
- * all datasource values in the sample will be set to Double.NaN (unknown) values.
- *
- * @throws IOException Thrown in case of I/O error.
- * @throws RrdException Thrown in case of JRobin related error.
- */
- public void update() throws IOException, RrdException {
- parentDb.store(this);
- clearCurrentValues();
- }
-
- /**
- *
- * set(timeAndValues);
- * update();
- *
- *
- * @param timeAndValues String made by concatenating sample timestamp with corresponding
- * data source values delmited with colons. For example:
- * 1005234132:12.2:35.6:U:24.5
- * NOW:12.2:35.6:U:24.5
- * @throws IOException Thrown in case of I/O error.
- * @throws RrdException Thrown in case of JRobin related error.
- */
- public void setAndUpdate(final String timeAndValues) throws IOException, RrdException {
- set(timeAndValues);
- update();
- }
-
- /**
- * Dumps sample content using the syntax of RRDTool's update command.
- *
- * @return Sample dump.
- */
- public String dump() {
- final StringBuffer buffer = new StringBuffer("update \"");
- buffer.append(parentDb.getRrdBackend().getPath()).append("\" ").append(time);
- for (final double value : values) {
- buffer.append(":");
- buffer.append(Util.formatDouble(value, "U", false));
- }
- return buffer.toString();
- }
-
- String getRrdToolCommand() {
- return dump();
- }
-
- public String toString() {
- return getClass().getSimpleName() + "@" + "[parentDb=" + parentDb + ",time=" + new Date(time * 1000L) + ",dsNames=[" + printList(dsNames) + "],values=[" + printList(values) + "]]";
- }
-
- private String printList(final Object[] dsNames) {
- if (dsNames == null) return "null";
- final StringBuffer sb = new StringBuffer();
- for (int i = 0; i < dsNames.length; i++) {
- if (i == dsNames.length - 1) {
- sb.append(dsNames[i]);
- } else {
- sb.append(dsNames[i]).append(", ");
- }
- }
- return sb.toString();
- }
-
- private String printList(final double[] values) {
- if (values == null) return "null";
- final StringBuffer sb = new StringBuffer();
- for (int i = 0; i < values.length; i++) {
- if (i == values.length - 1) {
- sb.append(values[i]);
- } else {
- sb.append(values[i]).append(", ");
- }
- }
- return sb.toString();
- }
-
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/SyncManager.java b/apps/jrobin/java/src/org/jrobin/core/SyncManager.java
deleted file mode 100644
index 71bba51cb2..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/SyncManager.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.jrobin.core;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-
-
-public final class SyncManager {
- private int m_syncPeriod = RrdNioBackendFactory.DEFAULT_SYNC_PERIOD;
- private Timer m_timer = null;
- private Map(System.currentTimeMillis() + 500L) / 1000L
- *
- * @return Current timestamp
- */
- public static long getTime() {
- return (System.currentTimeMillis() + 500L) / 1000L;
- }
-
- /**
- * Just an alias for {@link #getTime()} method.
- *
- * @return Current timestamp (without milliseconds)
- */
- public static long getTimestamp() {
- return getTime();
- }
-
- /**
- * Rounds the given timestamp to the nearest whole "step". Rounded value is obtained
- * from the following expression:
- * timestamp - timestamp % step;
- *
- * @param timestamp Timestamp in seconds
- * @param step Step in seconds
- * @return "Rounded" timestamp
- */
- public static long normalize(long timestamp, long step) {
- return timestamp - timestamp % step;
- }
-
- /**
- * Returns the greater of two double values, but treats NaN as the smallest possible
- * value. Note that Math.max()
behaves differently for NaN arguments.
- *
- * @param x an argument
- * @param y another argument
- * @return the lager of arguments
- */
- public static double max(double x, double y) {
- return Double.isNaN(x) ? y : Double.isNaN(y) ? x : Math.max(x, y);
- }
-
- /**
- * Returns the smaller of two double values, but treats NaN as the greatest possible
- * value. Note that Math.min()
behaves differently for NaN arguments.
- *
- * @param x an argument
- * @param y another argument
- * @return the smaller of arguments
- */
- public static double min(double x, double y) {
- return Double.isNaN(x) ? y : Double.isNaN(y) ? x : Math.min(x, y);
- }
-
- /**
- * Calculates sum of two doubles, but treats NaNs as zeros.
- *
- * @param x First double
- * @param y Second double
- * @return Sum(x,y) calculated as Double.isNaN(x)? y: Double.isNaN(y)? x: x + y;
- */
- public static double sum(double x, double y) {
- return Double.isNaN(x) ? y : Double.isNaN(y) ? x : x + y;
- }
-
- static String formatDouble(double x, String nanString, boolean forceExponents) {
- if (Double.isNaN(x)) {
- return nanString;
- }
- if (forceExponents) {
- return df.format(x);
- }
- return "" + x;
- }
-
- static String formatDouble(double x, boolean forceExponents) {
- return formatDouble(x, "" + Double.NaN, forceExponents);
- }
-
- /**
- * Formats double as a string using exponential notation (RRDTool like). Used for debugging
- * throught the project.
- *
- * @param x value to be formatted
- * @return string like "+1.234567E+02"
- */
- public static String formatDouble(double x) {
- return formatDouble(x, true);
- }
-
- /**
- * Returns Date
object for the given timestamp (in seconds, without
- * milliseconds)
- *
- * @param timestamp Timestamp in seconds.
- * @return Corresponding Date object.
- */
- public static Date getDate(long timestamp) {
- return new Date(timestamp * 1000L);
- }
-
- /**
- * Returns Calendar
object for the given timestamp
- * (in seconds, without milliseconds)
- *
- * @param timestamp Timestamp in seconds.
- * @return Corresponding Calendar object.
- */
- public static Calendar getCalendar(long timestamp) {
- Calendar calendar = Calendar.getInstance();
- calendar.setTimeInMillis(timestamp * 1000L);
- return calendar;
- }
-
- /**
- * Returns Calendar
object for the given Date object
- *
- * @param date Date object
- * @return Corresponding Calendar object.
- */
- public static Calendar getCalendar(Date date) {
- Calendar calendar = Calendar.getInstance();
- calendar.setTime(date);
- return calendar;
- }
-
- /**
- * Returns timestamp (unix epoch) for the given Date object
- *
- * @param date Date object
- * @return Corresponding timestamp (without milliseconds)
- */
- public static long getTimestamp(final Date date) {
- // round to whole seconds, ignore milliseconds
- return (date.getTime() + 499L) / 1000L;
- }
-
- /**
- * Returns timestamp (unix epoch) for the given Calendar object
- *
- * @param gc Calendar object
- * @return Corresponding timestamp (without milliseconds)
- */
- public static long getTimestamp(final Calendar gc) {
- return getTimestamp(gc.getTime());
- }
-
- /**
- * Returns timestamp (unix epoch) for the given year, month, day, hour and minute.
- *
- * @param year Year
- * @param month Month (zero-based)
- * @param day Day in month
- * @param hour Hour
- * @param min Minute
- * @return Corresponding timestamp
- */
- public static long getTimestamp(final int year, final int month, final int day, final int hour, final int min) {
- final Calendar calendar = Calendar.getInstance();
- calendar.clear();
- calendar.set(year, month, day, hour, min);
- return Util.getTimestamp(calendar);
- }
-
- /**
- * Returns timestamp (unix epoch) for the given year, month and day.
- *
- * @param year Year
- * @param month Month (zero-based)
- * @param day Day in month
- * @return Corresponding timestamp
- */
- public static long getTimestamp(int year, int month, int day) {
- return Util.getTimestamp(year, month, day, 0, 0);
- }
-
- /**
- * Parses at-style time specification and returns the corresponding timestamp. For example:
- * long t = Util.getTimestamp("now-1d");
- *
- *
- * @param atStyleTimeSpec at-style time specification. For the complete explanation of the syntax
- * allowed see RRDTool's rrdfetch
man page.
- * long[] t = Util.getTimestamps("end-1d","now");
- *
- *
- * @param atStyleTimeSpec1 Starting at-style time specification. For the complete explanation of the syntax
- * allowed see RRDTool's rrdfetch
man page.rrdfetch
man page.true
if the string can be parsed as double, false
otherwise
- */
- public static boolean isDouble(final String s) {
- try {
- Double.parseDouble(s);
- return true;
- }
- catch (final NumberFormatException nfe) {
- return false;
- }
- }
-
- /**
- * Parses input string as a boolean value. The parser is case insensitive.
- *
- * @param valueStr String representing boolean value
- * @return true
, if valueStr equals to 'true', 'on', 'yes', 'y' or '1';
- * false
in all other cases.
- */
- public static boolean parseBoolean(final String valueStr) {
- return valueStr.equalsIgnoreCase("true") ||
- valueStr.equalsIgnoreCase("on") ||
- valueStr.equalsIgnoreCase("yes") ||
- valueStr.equalsIgnoreCase("y") ||
- valueStr.equalsIgnoreCase("1");
- }
-
- /**
- * Parses input string as color. The color string should be of the form #RRGGBB (no alpha specified,
- * opaque color) or #RRGGBBAA (alpa specified, transparent colors). Leading character '#' is
- * optional.
- *
- * @param valueStr Input string, for example #FFAA24, #AABBCC33, 010203 or ABC13E4F
- * @return Paint object
- * @throws RrdException If the input string is not 6 or 8 characters long (without optional '#')
- */
- public static Paint parseColor(final String valueStr) throws RrdException {
- final String c = valueStr.startsWith("#") ? valueStr.substring(1) : valueStr;
- if (c.length() != 6 && c.length() != 8) {
- throw new RrdException("Invalid color specification: " + valueStr);
- }
- final String r = c.substring(0, 2), g = c.substring(2, 4), b = c.substring(4, 6);
- if (c.length() == 6) {
- return new Color(Integer.parseInt(r, 16), Integer.parseInt(g, 16), Integer.parseInt(b, 16));
- }
- else {
- final String a = c.substring(6);
- return new Color(Integer.parseInt(r, 16), Integer.parseInt(g, 16),
- Integer.parseInt(b, 16), Integer.parseInt(a, 16));
- }
- }
-
- /**
- * Returns file system separator string.
- *
- * @return File system separator ("/" on Unix, "\" on Windows)
- */
- public static String getFileSeparator() {
- return System.getProperty("file.separator");
- }
-
- /**
- * Returns path to user's home directory.
- *
- * @return Path to users home directory, with file separator appended.
- */
- public static String getUserHomeDirectory() {
- return System.getProperty("user.home") + getFileSeparator();
- }
-
- /**
- * Returns path to directory used for placement of JRobin demo graphs and creates it
- * if necessary.
- *
- * @return Path to demo directory (defaults to $HOME/jrobin/) if directory exists or
- * was successfully created. Null if such directory could not be created.
- */
- public static String getJRobinDemoDirectory() {
- final String homeDirPath = getUserHomeDirectory() + JROBIN_DIR + getFileSeparator();
- final File homeDirFile = new File(homeDirPath);
- return (homeDirFile.exists() || homeDirFile.mkdirs()) ? homeDirPath : null;
- }
-
- /**
- * Returns full path to the file stored in the demo directory of JRobin
- *
- * @param filename Partial path to the file stored in the demo directory of JRobin
- * (just name and extension, without parent directories)
- * @return Full path to the file
- */
- public static String getJRobinDemoPath(final String filename) {
- final String demoDir = getJRobinDemoDirectory();
- if (demoDir != null) {
- return demoDir + filename;
- }
- else {
- return null;
- }
- }
-
- static boolean sameFilePath(final String path1, final String path2) throws IOException {
- final File file1 = new File(path1);
- final File file2 = new File(path2);
- return file1.getCanonicalPath().equals(file2.getCanonicalPath());
- }
-
- static int getMatchingDatasourceIndex(final RrdDb rrd1, final int dsIndex, final RrdDb rrd2) throws IOException {
- final String dsName = rrd1.getDatasource(dsIndex).getDsName();
- try {
- return rrd2.getDsIndex(dsName);
- }
- catch (final RrdException e) {
- return -1;
- }
- }
-
- static int getMatchingArchiveIndex(final RrdDb rrd1, final int arcIndex, final RrdDb rrd2) throws IOException {
- final Archive archive = rrd1.getArchive(arcIndex);
- final String consolFun = archive.getConsolFun();
- final int steps = archive.getSteps();
- try {
- return rrd2.getArcIndex(consolFun, steps);
- }
- catch (final RrdException e) {
- return -1;
- }
- }
-
- static String getTmpFilename() throws IOException {
- return File.createTempFile("JROBIN_", ".tmp").getCanonicalPath();
- }
-
- static final String ISO_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; // ISO
-
- /**
- * Creates Calendar object from a string. The string should represent
- * either a long integer (UNIX timestamp in seconds without milliseconds,
- * like "1002354657") or a human readable date string in the format "yyyy-MM-dd HH:mm:ss"
- * (like "2004-02-25 12:23:45").
- *
- * @param timeStr Input string
- * @return Calendar object
- */
- public static Calendar getCalendar(final String timeStr) {
- // try to parse it as long
- try {
- return Util.getCalendar(Long.parseLong(timeStr));
- }
- catch (final NumberFormatException nfe) {
- // not a long timestamp, try to parse it as data
- final SimpleDateFormat df = new SimpleDateFormat(ISO_DATE_FORMAT);
- df.setLenient(false);
- try {
- return Util.getCalendar(df.parse(timeStr));
- }
- catch (final ParseException pe) {
- throw new IllegalArgumentException("Time/date not in " + ISO_DATE_FORMAT + " format: " + timeStr);
- }
- }
- }
-
- /**
- * Various DOM utility functions
- */
- public static class Xml {
- public static Node[] getChildNodes(final Node parentNode) {
- return getChildNodes(parentNode, null);
- }
-
- public static Node[] getChildNodes(final Node parentNode, final String childName) {
- final ArrayListgetLapTime()
method call.
- */
- public static String getLapTime() {
- final long newLap = System.currentTimeMillis();
- final double seconds = (newLap - lastLap) / 1000.0;
- lastLap = newLap;
- return "[" + seconds + " sec]";
- }
-
- /**
- * Returns the root directory of the JRobin distribution. Useful in some demo applications,
- * probably of no use anywhere else.
- * false
- *
- * @param x the first value
- * @param y the second value
- * @return true
if x and y are both equal to Double.NaN, or if x == y. false
otherwise
- */
- public static boolean equal(final double x, final double y) {
- return (Double.isNaN(x) && Double.isNaN(y)) || (x == y);
- }
-
- /**
- * Returns canonical file path for the given file path
- *
- * @param path Absolute or relative file path
- * @return Canonical file path
- * @throws IOException Thrown if canonical file path could not be resolved
- */
- public static String getCanonicalPath(final String path) throws IOException {
- return new File(path).getCanonicalPath();
- }
-
- /**
- * Returns last modification time for the given file.
- *
- * @param file File object representing file on the disk
- * @return Last modification time in seconds (without milliseconds)
- */
- public static long getLastModified(final String file) {
- return (new File(file).lastModified() + 500L) / 1000L;
- }
-
- /**
- * Checks if the file with the given file name exists
- *
- * @param filename File name
- * @return true
if file exists, false
otherwise
- */
- public static boolean fileExists(final String filename) {
- return new File(filename).exists();
- }
-
- /**
- * Finds max value for an array of doubles (NaNs are ignored). If all values in the array
- * are NaNs, NaN is returned.
- *
- * @param values Array of double values
- * @return max value in the array (NaNs are ignored)
- */
- public static double max(final double[] values) {
- double max = Double.NaN;
- for (final double value : values) {
- max = Util.max(max, value);
- }
- return max;
- }
-
- /**
- * Finds min value for an array of doubles (NaNs are ignored). If all values in the array
- * are NaNs, NaN is returned.
- *
- * @param values Array of double values
- * @return min value in the array (NaNs are ignored)
- */
- public static double min(final double[] values) {
- double min = Double.NaN;
- for (final double value : values) {
- min = Util.min(min, value);
- }
- return min;
- }
-
- /**
- * Equivalent of the C-style sprintf function. Sorry, it works only in Java5.
- *
- * @param format Format string
- * @param args Arbitrary list of arguments
- * @return Formatted string
- */
- public static String sprintf(final String format, final Object ... args) {
- final String fmt = format.replaceAll("([^%]|^)%([^a-zA-Z%]*)l(f|g|e)", "$1%$2$3");
- return String.format(fmt, args);
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/XmlReader.java b/apps/jrobin/java/src/org/jrobin/core/XmlReader.java
deleted file mode 100644
index c373287bb0..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/XmlReader.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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");
- }
-
- String getVersion() throws RrdException {
- return Util.Xml.getChildValue(root, "version");
- }
-
- long getLastUpdateTime() throws RrdException {
- return Util.Xml.getChildValueAsLong(root, "lastupdate");
- }
-
- long getStep() throws RrdException {
- return Util.Xml.getChildValueAsLong(root, "step");
- }
-
- int getDsCount() {
- return dsNodes.length;
- }
-
- int getArcCount() {
- return arcNodes.length;
- }
-
- String getDsName(int dsIndex) throws RrdException {
- return Util.Xml.getChildValue(dsNodes[dsIndex], "name");
- }
-
- String getDsType(int dsIndex) throws RrdException {
- return Util.Xml.getChildValue(dsNodes[dsIndex], "type");
- }
-
- long getHeartbeat(int dsIndex) throws RrdException {
- return Util.Xml.getChildValueAsLong(dsNodes[dsIndex], "minimal_heartbeat");
- }
-
- double getMinValue(int dsIndex) throws RrdException {
- return Util.Xml.getChildValueAsDouble(dsNodes[dsIndex], "min");
- }
-
- double getMaxValue(int dsIndex) throws RrdException {
- return Util.Xml.getChildValueAsDouble(dsNodes[dsIndex], "max");
- }
-
- double getLastValue(int dsIndex) throws RrdException {
- return Util.Xml.getChildValueAsDouble(dsNodes[dsIndex], "last_ds");
- }
-
- double getAccumValue(int dsIndex) throws RrdException {
- return Util.Xml.getChildValueAsDouble(dsNodes[dsIndex], "value");
- }
-
- long getNanSeconds(int dsIndex) throws RrdException {
- return Util.Xml.getChildValueAsLong(dsNodes[dsIndex], "unknown_sec");
- }
-
- String getConsolFun(int arcIndex) throws RrdException {
- return Util.Xml.getChildValue(arcNodes[arcIndex], "cf");
- }
-
- double getXff(int arcIndex) throws RrdException {
- return Util.Xml.getChildValueAsDouble(arcNodes[arcIndex], "xff");
- }
-
- int getSteps(int arcIndex) throws RrdException {
- return Util.Xml.getChildValueAsInt(arcNodes[arcIndex], "pdp_per_row");
- }
-
- double getStateAccumValue(int arcIndex, int dsIndex) throws RrdException {
- Node cdpNode = Util.Xml.getFirstChildNode(arcNodes[arcIndex], "cdp_prep");
- Node[] dsNodes = Util.Xml.getChildNodes(cdpNode, "ds");
- return Util.Xml.getChildValueAsDouble(dsNodes[dsIndex], "value");
- }
-
- int getStateNanSteps(int arcIndex, int dsIndex) throws RrdException {
- Node cdpNode = Util.Xml.getFirstChildNode(arcNodes[arcIndex], "cdp_prep");
- Node[] dsNodes = Util.Xml.getChildNodes(cdpNode, "ds");
- return Util.Xml.getChildValueAsInt(dsNodes[dsIndex], "unknown_datapoints");
- }
-
- int getRows(int arcIndex) throws RrdException {
- Node dbNode = Util.Xml.getFirstChildNode(arcNodes[arcIndex], "database");
- Node[] rows = Util.Xml.getChildNodes(dbNode, "row");
- return rows.length;
- }
-
- double[] getValues(int arcIndex, int dsIndex) throws RrdException {
- Node dbNode = Util.Xml.getFirstChildNode(arcNodes[arcIndex], "database");
- Node[] rows = Util.Xml.getChildNodes(dbNode, "row");
- double[] values = new double[rows.length];
- for (int i = 0; i < rows.length; i++) {
- Node[] vNodes = Util.Xml.getChildNodes(rows[i], "v");
- Node vNode = vNodes[dsIndex];
- values[i] = Util.parseDouble(vNode.getFirstChild().getNodeValue().trim());
- }
- return values;
- }
-}
\ No newline at end of file
diff --git a/apps/jrobin/java/src/org/jrobin/core/XmlTemplate.java b/apps/jrobin/java/src/org/jrobin/core/XmlTemplate.java
deleted file mode 100644
index 595bf68a28..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/XmlTemplate.java
+++ /dev/null
@@ -1,342 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 ${variable_name}
.
- * 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.${start}
, specify start
for the name
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
- * ${start}
, specify start
for the name
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, 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
- * ${start}
, specify start
for the name
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, 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
- * ${start}
, specify start
for the name
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, 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
- * ${start}
, specify start
for the name
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
- * ${start}
, specify start
for the name
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
- * ${start}
, specify start
for the name
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
- * ${start}
, specify start
for the name
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<tag>
and </tag>
- */
- 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 <tag>
and </tag>
- */
- 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 <tag>
and </tag>
- */
- 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 <tag>
and </tag>
- * @param nanString string to display if the value is NaN.
- */
- 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 <tag>
and </tag>
- */
- 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 <tag>
and </tag>
- */
- 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 <tag>
and </tag>
- */
- 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 <tag>
and </tag>
- */
- 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 <tag>
and </tag>
- */
- public void writeTag(String tag, File value) {
- writeTag(tag, value.getPath());
- }
-
- /**
- * Flushes the output stream
- */
- public void flush() {
- writer.flush();
- }
-
- protected void finalize() throws Throwable {
- super.finalize();
- writer.close();
- }
-
- /**
- * Writes XML comment to output stream
- *
- * @param comment comment string
- */
- public void writeComment(Object comment) {
- writer.println(indent + "");
- }
-
- private static String escape(String s) {
- return s.replaceAll("<", "<").replaceAll(">", ">");
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/jrrd/Archive.java b/apps/jrobin/java/src/org/jrobin/core/jrrd/Archive.java
deleted file mode 100644
index 92da227094..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/jrrd/Archive.java
+++ /dev/null
@@ -1,426 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core.jrrd;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.text.DecimalFormat;
-import java.text.NumberFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Iterator;
-
-import org.jrobin.core.RrdException;
-
-/**
- * Instances of this class model an archive section of an RRD file.
- *
- * @author Ciaran Treanor
- * @version $Revision$
- */
-public class Archive {
-
- RRDatabase db;
- long offset;
- long dataOffset;
- long size;
- ConsolidationFunctionType type;
- int rowCount;
- int pdpCount;
- double xff;
- ArrayListCDPStatusBlock
at the specified position in this archive.
- *
- * @param index index of CDPStatusBlock
to return.
- * @return the CDPStatusBlock
at the specified position in this archive.
- */
- public CDPStatusBlock getCDPStatusBlock(int index) {
- return cdpStatusBlocks.get(index);
- }
-
- /**
- * Returns an iterator over the CDP status blocks in this archive in proper sequence.
- *
- * @return an iterator over the CDP status blocks in this archive in proper sequence.
- * @see CDPStatusBlock
- */
- public IteratorConsolidationFunctionType
with the given name.
- *
- * @param s name of the ConsolidationFunctionType
required.
- * @return a ConsolidationFunctionType
with the given name.
- */
- public static ConsolidationFunctionType get(final String s) {
-
- if (STR_AVERAGE.equalsIgnoreCase(s)) {
- return AVERAGE;
- }
- else if (STR_MIN.equalsIgnoreCase(s)) {
- return MIN;
- }
- else if (STR_MAX.equalsIgnoreCase(s)) {
- return MAX;
- }
- else if (STR_LAST.equalsIgnoreCase(s)) {
- return LAST;
- }
- else {
- throw new IllegalArgumentException("Invalid ConsolidationFunctionType: " + s);
- }
- }
-
- /**
- * Compares this object against the specified object.
- *
- * @return true
if the objects are the same,
- * false
otherwise.
- */
- public boolean equals(final Object o) {
-
- if (!(o instanceof ConsolidationFunctionType)) {
- throw new IllegalArgumentException("Not a ConsolidationFunctionType");
- }
-
- return (((ConsolidationFunctionType) o).type == type)
- ? true
- : false;
- }
-
- public int hashCode() {
- return type * 93;
- }
-
- /**
- * Returns a string representation of this object.
- *
- * @return a string representation of this object.
- */
- public String toString() {
-
- String strType;
-
- switch (type) {
-
- case _AVERAGE:
- strType = STR_AVERAGE;
- break;
-
- case _MIN:
- strType = STR_MIN;
- break;
-
- case _MAX:
- strType = STR_MAX;
- break;
-
- case _LAST:
- strType = STR_LAST;
- break;
-
- default :
- throw new RuntimeException("This should never happen");
- }
-
- return strType;
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/jrrd/Constants.java b/apps/jrobin/java/src/org/jrobin/core/jrrd/Constants.java
deleted file mode 100644
index c7f6ca3a53..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/jrrd/Constants.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core.jrrd;
-
-interface Constants {
-
- int DS_NAM_SIZE = 20;
- int DST_SIZE = 20;
- int CF_NAM_SIZE = 20;
- int LAST_DS_LEN = 30;
- static String COOKIE = "RRD";
- static String VERSION = "0001";
- static String VERSION3 = "0003";
- double FLOAT_COOKIE = 8.642135E130;
- static byte[] FLOAT_COOKIE_BIG_ENDIAN = {0x5B, 0x1F, 0x2B, 0x43,
- (byte) 0xC7, (byte) 0xC0, 0x25,
- 0x2F};
- static byte[] FLOAT_COOKIE_LITTLE_ENDIAN = {0x2F, 0x25, (byte) 0xC0,
- (byte) 0xC7, 0x43, 0x2B, 0x1F,
- 0x5B};
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/jrrd/DataChunk.java b/apps/jrobin/java/src/org/jrobin/core/jrrd/DataChunk.java
deleted file mode 100644
index 48b5a6aa67..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/jrrd/DataChunk.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core.jrrd;
-
-/**
- * Models a chunk of result data from an RRDatabase.
- *
- * @author Ciaran Treanor
- * @version $Revision$
- */
-public class DataChunk {
-
- private static final String NEWLINE = System.getProperty("line.separator");
- long startTime;
- int start;
- int end;
- long step;
- int dsCount;
- double[][] data;
- int rows;
-
- DataChunk(long startTime, int start, int end, long step, int dsCount, int rows) {
- this.startTime = startTime;
- this.start = start;
- this.end = end;
- this.step = step;
- this.dsCount = dsCount;
- this.rows = rows;
- data = new double[rows][dsCount];
- }
-
- /**
- * 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.
- *
- * @return a summary of the contents of this data chunk.
- */
- public String toString() {
-
- StringBuffer sb = new StringBuffer();
- long time = startTime;
-
- for (int row = 0; row < rows; row++, time += step) {
- sb.append(time);
- sb.append(": ");
-
- for (int ds = 0; ds < dsCount; ds++) {
- sb.append(data[row][ds]);
- sb.append(" ");
- }
-
- sb.append(NEWLINE);
- }
-
- return sb.toString();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/jrrd/DataSource.java b/apps/jrobin/java/src/org/jrobin/core/jrrd/DataSource.java
deleted file mode 100644
index ac90eca331..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/jrrd/DataSource.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core.jrrd;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.text.NumberFormat;
-
-import org.jrobin.core.RrdException;
-
-/**
- * Instances of this class model a data source in an RRD file.
- *
- * @author Ciaran Treanor
- * @version $Revision$
- */
-public class DataSource {
-
- long offset;
- long size;
- String name;
- DataSourceType type;
- int minimumHeartbeat;
- double minimum;
- double maximum;
- PDPStatusBlock pdpStatusBlock;
-
- DataSource(RRDFile file) throws IOException,RrdException {
-
- offset = file.getFilePointer();
- name = file.readString(Constants.DS_NAM_SIZE);
- type = DataSourceType.get(file.readString(Constants.DST_SIZE));
-
- file.align(8);
-
- minimumHeartbeat = file.readInt(true);
-
- file.align(8);
-
- minimum = file.readDouble();
- maximum = file.readDouble();
-
- // Skip rest of ds_def_t.par[]
- file.align();
- file.skipBytes(56);
-
- size = file.getFilePointer() - offset;
- }
-
- void loadPDPStatusBlock(RRDFile file) throws IOException,RrdException {
- pdpStatusBlock = new PDPStatusBlock(file);
- }
-
- /**
- * Returns the primary data point status block for this data source.
- *
- * @return the primary data point status block for this data source.
- */
- public PDPStatusBlock getPDPStatusBlock() {
- return pdpStatusBlock;
- }
-
- /**
- * Returns the minimum required heartbeat for this data source.
- *
- * @return the minimum required heartbeat for this data source.
- */
- public int getMinimumHeartbeat() {
- return minimumHeartbeat;
- }
-
- /**
- * Returns the minimum value input to this data source can have.
- *
- * @return the minimum value input to this data source can have.
- */
- public double getMinimum() {
- return minimum;
- }
-
- /**
- * Returns the type this data source is.
- *
- * @return the type this data source is.
- * @see DataSourceType
- */
- public DataSourceType getType() {
- return type;
- }
-
- /**
- * Returns the maximum value input to this data source can have.
- *
- * @return the maximum value input to this data source can have.
- */
- public double getMaximum() {
- return maximum;
- }
-
- /**
- * Returns the name of this data source.
- *
- * @return the name of this data source.
- */
- public String getName() {
- return name;
- }
-
- void printInfo(PrintStream s, NumberFormat numberFormat) {
-
- StringBuffer sb = new StringBuffer("ds[");
-
- sb.append(name);
- s.print(sb);
- s.print("].type = \"");
- s.print(type);
- s.println("\"");
- s.print(sb);
- s.print("].minimal_heartbeat = ");
- s.println(minimumHeartbeat);
- s.print(sb);
- s.print("].min = ");
- s.println(Double.isNaN(minimum)
- ? "NaN"
- : numberFormat.format(minimum));
- s.print(sb);
- s.print("].max = ");
- s.println(Double.isNaN(maximum)
- ? "NaN"
- : numberFormat.format(maximum));
- s.print(sb);
- s.print("].last_ds = ");
- s.println(pdpStatusBlock.lastReading);
- s.print(sb);
- s.print("].value = ");
-
- double value = pdpStatusBlock.value;
-
- s.println(Double.isNaN(value)
- ? "NaN"
- : numberFormat.format(value));
- s.print(sb);
- s.print("].unknown_sec = ");
- s.println(pdpStatusBlock.unknownSeconds);
- }
-
- void toXml(PrintStream s) {
-
- s.println("\tDataSourceType
with the given name.
- *
- * @param s name of the DataSourceType
required.
- * @return a DataSourceType
with the given name.
- */
- public static DataSourceType get(final String s) {
-
- if (STR_COUNTER.equalsIgnoreCase(s)) {
- return COUNTER;
- }
- else if (STR_ABSOLUTE.equalsIgnoreCase(s)) {
- return ABSOLUTE;
- }
- else if (STR_GAUGE.equalsIgnoreCase(s)) {
- return GAUGE;
- }
- else if (STR_DERIVE.equalsIgnoreCase(s)) {
- return DERIVE;
- }
- else {
- throw new IllegalArgumentException("Invalid DataSourceType");
- }
- }
-
- /**
- * Compares this object against the specified object.
- *
- * @return true
if the objects are the same,
- * false
otherwise.
- */
- public boolean equals(final Object obj) {
-
- if (!(obj instanceof DataSourceType)) {
- throw new IllegalArgumentException("Not a DataSourceType");
- }
-
- return (((DataSourceType) obj).type == type)
- ? true
- : false;
- }
-
- public int hashCode() {
- return type * 37;
- }
-
- /**
- * Returns a string representation of this object.
- *
- * @return a string representation of this object.
- */
- public String toString() {
-
- String strType;
-
- switch (type) {
-
- case _COUNTER:
- strType = STR_COUNTER;
- break;
-
- case _ABSOLUTE:
- strType = STR_ABSOLUTE;
- break;
-
- case _GAUGE:
- strType = STR_GAUGE;
- break;
-
- case _DERIVE:
- strType = STR_DERIVE;
- break;
-
- default :
- // Don't you just hate it when you see a line like this?
- throw new RuntimeException("This should never happen");
- }
-
- return strType;
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/jrrd/Header.java b/apps/jrobin/java/src/org/jrobin/core/jrrd/Header.java
deleted file mode 100644
index c301e3aceb..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/jrrd/Header.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core.jrrd;
-
-import java.io.IOException;
-
-import org.jrobin.core.RrdException;
-
-/**
- * Instances of this class model the header section of an RRD file.
- *
- * @author Ciaran Treanor
- * @version $Revision$
- */
-public class Header implements Constants {
-
- static final long offset = 0;
- long size;
- String version;
- int intVersion;
- int dsCount;
- int rraCount;
- int pdpStep;
-
- Header(RRDFile file) throws IOException,RrdException {
-
- if (!file.readString(4).equals(COOKIE)) {
- throw new IOException("Invalid COOKIE");
- }
-
- version = file.readString(5);
- intVersion = Integer.parseInt(version);
- if( intVersion > 3 ) {
- throw new IOException("Unsupported RRD version (" + version + ")");
- }
-
- file.align();
-
- // Consume the FLOAT_COOKIE
- file.readDouble();
-
- dsCount = file.readInt();
- rraCount = file.readInt();
- pdpStep = file.readInt();
-
- // Skip rest of stat_head_t.par
- file.align();
- file.skipBytes(80);
-
- size = file.getFilePointer() - offset;
- }
-
- /**
- * Returns the version of the database.
- *
- * @return the version of the database.
- */
- public String getVersion() {
- return version;
- }
-
- public int getIntVersion() {
- return intVersion;
- }
-
- /**
- * Returns the number of DataSource
s in the database.
- *
- * @return the number of DataSource
s in the database.
- */
- public int getDSCount() {
- return dsCount;
- }
-
- /**
- * Returns the number of Archive
s in the database.
- *
- * @return the number of Archive
s in the database.
- */
- public int getRRACount() {
- return rraCount;
- }
-
- /**
- * Returns the primary data point interval in seconds.
- *
- * @return the primary data point interval in seconds.
- */
- public int getPDPStep() {
- return pdpStep;
- }
-
- /**
- * Returns a summary the contents of this header.
- *
- * @return a summary of the information contained in this header.
- */
- public String toString() {
-
- StringBuffer sb = new StringBuffer("[Header: OFFSET=0x00, SIZE=0x");
-
- sb.append(Long.toHexString(size));
- sb.append(", version=");
- sb.append(version);
- sb.append(", dsCount=");
- sb.append(dsCount);
- sb.append(", rraCount=");
- sb.append(rraCount);
- sb.append(", pdpStep=");
- sb.append(pdpStep);
- sb.append("]");
-
- return sb.toString();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/jrrd/Main.java b/apps/jrobin/java/src/org/jrobin/core/jrrd/Main.java
deleted file mode 100644
index c7f17b7a89..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/jrrd/Main.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core.jrrd;
-
-import java.io.IOException;
-
-import org.jrobin.core.RrdException;
-
-/**
- * Show some of the things jRRD can do.
- *
- * @author Ciaran Treanor
- * @version $Revision$
- */
-public class Main {
-
- public Main(String rrdFile) {
-
- RRDatabase rrd = null;
- DataChunk chunk = null;
-
- try {
- rrd = new RRDatabase(rrdFile);
- chunk = rrd.getData(ConsolidationFunctionType.AVERAGE);
- } catch (Exception e) {
- e.printStackTrace();
-
- return;
- }
-
- try {
- rrd.toXml(System.out);
- } catch (RrdException e) {
- e.printStackTrace();
- return;
- }
- // Dump the database as XML.
- rrd.printInfo(System.out); // Dump the database header information.
- System.out.println(rrd); // Dump a summary of the contents of the database.
- System.out.println(chunk); // Dump the chunk.
-
- try {
- rrd.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- static void usage(int status) {
- System.err.println("Usage: " + Main.class.getName() + " rrdfile");
- System.exit(status);
- }
-
- public static void main(String[] args) {
- if (args.length != 1) {
- usage(1);
- }
- new Main(args[0]);
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/jrrd/PDPStatusBlock.java b/apps/jrobin/java/src/org/jrobin/core/jrrd/PDPStatusBlock.java
deleted file mode 100644
index 449897bf67..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/jrrd/PDPStatusBlock.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core.jrrd;
-
-import java.io.IOException;
-
-import org.jrobin.core.RrdException;
-
-/**
- * Instances of this class model the primary data point status from an RRD file.
- *
- * @author Ciaran Treanor
- * @version $Revision$
- */
-public class PDPStatusBlock {
-
- long offset;
- long size;
- String lastReading;
- int unknownSeconds;
- double value;
-
- PDPStatusBlock(RRDFile file) throws IOException,RrdException {
-
- offset = file.getFilePointer();
- lastReading = file.readString(Constants.LAST_DS_LEN);
-
- file.align(4);
-
- unknownSeconds = file.readInt();
-
- file.align(8); //8 bytes per scratch value in pdp_prep; align on that
-
- value = file.readDouble();
-
- // Skip rest of pdp_prep_t.par[]
- file.skipBytes(64);
-
- size = file.getFilePointer() - offset;
- }
-
- /**
- * Returns the last reading from the data source.
- *
- * @return the last reading from the data source.
- */
- public String getLastReading() {
- return lastReading;
- }
-
- /**
- * Returns the current value of the primary data point.
- *
- * @return the current value of the primary data point.
- */
- public double getValue() {
- return value;
- }
-
- /**
- * Returns the number of seconds of the current primary data point is
- * unknown data.
- *
- * @return the number of seconds of the current primary data point is unknown data.
- */
- public int getUnknownSeconds() {
- return unknownSeconds;
- }
-
- /**
- * Returns a summary the contents of this PDP status block.
- *
- * @return a summary of the information contained in this PDP status block.
- */
- public String toString() {
-
- StringBuffer sb = new StringBuffer("[PDPStatus: OFFSET=0x");
-
- sb.append(Long.toHexString(offset));
- sb.append(", SIZE=0x");
- sb.append(Long.toHexString(size));
- sb.append(", lastReading=");
- sb.append(lastReading);
- sb.append(", unknownSeconds=");
- sb.append(unknownSeconds);
- sb.append(", value=");
- sb.append(value);
- sb.append("]");
-
- return sb.toString();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/jrrd/RRDFile.java b/apps/jrobin/java/src/org/jrobin/core/jrrd/RRDFile.java
deleted file mode 100644
index 7badf305e2..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/jrrd/RRDFile.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.core.jrrd;
-
-import java.io.ByteArrayInputStream;
-import java.io.DataInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-
-import org.jrobin.core.RrdException;
-
-/**
- * This class is a quick hack to read information from an RRD file. Writing
- * to RRD files is not currently supported. As I said, this is a quick hack.
- * Some thought should be put into the overall design of the file IO.
- * Header
for this database.
- *
- * @return the Header
for this database.
- */
- public Header getHeader() {
- return header;
- }
-
- /**
- * Returns the date this database was last updated. To convert this date to
- * the form returned by rrdtool last
call Date.getTime() and
- * divide the result by 1000.
- *
- * @return the date this database was last updated.
- */
- public Date getLastUpdate() {
- return lastUpdate;
- }
-
- /**
- * Returns the DataSource
at the specified position in this database.
- *
- * @param index index of DataSource
to return.
- * @return the DataSource
at the specified position in this database
- */
- public DataSource getDataSource(int index) {
- return dataSources.get(index);
- }
-
- /**
- * Returns an iterator over the data sources in this database in proper sequence.
- *
- * @return an iterator over the data sources in this database in proper sequence.
- */
- public IteratorArchive
at the specified position in this database.
- *
- * @param index index of Archive
to return.
- * @return the Archive
at the specified position in this database.
- */
- public Archive getArchive(int index) {
- return archives.get(index);
- }
-
- /**
- * Returns an iterator over the archives in this database in proper sequence.
- *
- * @return an iterator over the archives in this database in proper sequence.
- */
- public Iteratordouble
- * is 0.0000000000E0.
- *
- * @param s the PrintStream to print the header information to.
- */
- public void printInfo(PrintStream s) {
-
- NumberFormat numberFormat = new DecimalFormat("0.0000000000E0");
-
- printInfo(s, numberFormat);
- }
-
- /**
- * Returns data from the database corresponding to the given consolidation
- * function and a step size of 1.
- *
- * @param type the consolidation function that should have been applied to
- * the data.
- * @return the raw data.
- * @throws RrdException if there was a problem locating a data archive with
- * the requested consolidation function.
- * @throws IOException if there was a problem reading data from the database.
- */
- public DataChunk getData(ConsolidationFunctionType type)
- throws RrdException, IOException {
- return getData(type, 1L);
- }
-
- /**
- * Returns data from the database corresponding to the given consolidation
- * function.
- *
- * @param type the consolidation function that should have been applied to
- * the data.
- * @param step the step size to use.
- * @return the raw data.
- * @throws RrdException if there was a problem locating a data archive with
- * the requested consolidation function.
- * @throws IOException if there was a problem reading data from the database.
- */
- public DataChunk getData(ConsolidationFunctionType type, long step)
- throws RrdException, IOException {
-
- ArrayListdouble
s as.
- */
- public void printInfo(PrintStream s, NumberFormat numberFormat) {
-
- s.print("filename = \"");
- s.print(name);
- s.println("\"");
- s.print("rrd_version = \"");
- s.print(header.version);
- s.println("\"");
- s.print("step = ");
- s.println(header.pdpStep);
- s.print("last_update = ");
- s.println(lastUpdate.getTime() / 1000);
-
- for (Iterator
- *
- * The current timestamp is displayed in the title bar :)
");
- for (String supportedFormat : supportedFormats) {
- tooltipBuff.append(supportedFormat).append("
");
- }
- tooltipBuff.append("AT-style time specification
");
- tooltipBuff.append("timestamp
");
- tooltipBuff.append("Copyright (C) 2003-2005 Sasa Markovic, All Rights Reserved");
- 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 (SimpleDateFormat parser : parsers) {
- try {
- return Util.getTimestamp(parser.parse(time));
- }
- catch (ParseException e) {
- // NOP
- }
- }
- return new TimeParser(time).parse().getTimestamp();
- }
-
- /**
- * Main method which runs this utility.
- *
- * @param args Not used.
- */
- public static void main(String[] args) {
- new Epoch();
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/timespec/TimeParser.java b/apps/jrobin/java/src/org/jrobin/core/timespec/TimeParser.java
deleted file mode 100644
index b957ecc140..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/timespec/TimeParser.java
+++ /dev/null
@@ -1,443 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 (described 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;
- break;
- case TimeToken.MONTHS:
- spec.dmonth += delta;
- break;
- case TimeToken.WEEKS:
- delta *= 7;
- spec.dday += delta;
- break;
- case TimeToken.DAYS:
- spec.dday += delta;
- break;
- case TimeToken.HOURS:
- spec.dhour += delta;
- break;
- case TimeToken.MINUTES:
- spec.dmin += delta;
- break;
- case TimeToken.SECONDS:
- default: // default is 'seconds'
- spec.dsec += delta;
- break;
- }
- // unreachable statement
- // throw new RrdException("Well-known time unit expected after " + delta);
- }
-
- /**
- * Try and read a "timeofday" specification. This method will be called
- * when we see a plain number at the start of a time, which means we could be
- * reading a time, or a day. If it turns out to be a date, then this method restores
- * the scanner state to what it was at entry, and returns without setting anything.
- * @throws RrdException
- */
- 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) {
- //Definitely not an hour specification; probably a date or something. Give up now
- return;
- }
- hour = Integer.parseInt(token.value);
- token = scanner.nextToken();
- if (token.id == TimeToken.SLASH) {
- /* guess we are looking at a date */
- token = scanner.restoreState();
- return;
- }
- if (token.id == TimeToken.COLON || token.id == TimeToken.DOT) {
- expectToken(TimeToken.NUMBER, "Parsing HH:MM or HH.MM syntax, expecting MM as number, got none");
- minute = Integer.parseInt(token.value);
- if (minute > 59) {
- throw new RrdException("Parsing HH:MM or HH.MM syntax, got MM = " +
- minute + " (>59!)");
- }
- token = scanner.nextToken();
- if(token.id == TimeToken.DOT) {
- //Oh look, another dot; must have actually been a date in DD.MM.YYYY format. Give up and return
- token = scanner.restoreState();
- return;
- }
-
- }
- /* 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, probably a date ... */
- 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--;
- token = scanner.nextToken();
- break;
- 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
- * TimeParser p = new TimeParser("now-1day");
- * TimeSpec ts = p.parse();
- * System.out.println("Timestamp was: " + ts.getTimestamp();
- *
- *
- * @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:
- * 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);
- *
- *
- * @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:
- * 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);
- *
- *
- * @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])
- };
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/core/timespec/TimeToken.java b/apps/jrobin/java/src/org/jrobin/core/timespec/TimeToken.java
deleted file mode 100644
index 64b2057e71..0000000000
--- a/apps/jrobin/java/src/org/jrobin/core/timespec/TimeToken.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 EPOCH = 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 + "]";
- }
-}
\ No newline at end of file
diff --git a/apps/jrobin/java/src/org/jrobin/data/Aggregates.java b/apps/jrobin/java/src/org/jrobin/data/Aggregates.java
deleted file mode 100644
index f2194b5935..0000000000
--- a/apps/jrobin/java/src/org/jrobin/data/Aggregates.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
- * getAggregates()
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;
- double stdev = Double.NaN, lslslope = Double.NaN;
- double lslint = Double.NaN, lslcorrel = 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 stdev value
- *
- * @return Stdev value
- */
- public double getStdev() {
- return stdev;
- }
-
- /**
- * Returns Least Squares Line Slope value
- *
- * @return lslslope value
- */
- public double getLSLSlope() {
- return stdev;
- }
-
- /**
- * Returns Least Squares Line y-intercept value
- *
- * @return lslint value
- */
- public double getLSLInt() {
- return lslint;
- }
-
- /**
- * Returns Least Squares Line Correlation Coefficient
- *
- * @return lslcorrel value
- */
- public double getLSLCorrel() {
- return lslcorrel;
- }
-
- /**
- * Returns single aggregated value for the give consolidation function
- *
- * @param consolFun Consolidation function: MIN, MAX, FIRST, LAST, AVERAGE, TOTAL. These constants
- * 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 if (consolFun.equals("STDEV")) {
- return stdev;
- }
- else if (consolFun.equals("LSLSLOPE")) {
- return lslslope;
- }
- else if (consolFun.equals("LSLINT")) {
- return lslint;
- }
- else if (consolFun.equals("LSLCORREL")) {
- return lslcorrel;
- }
- 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);
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/data/Aggregator.java b/apps/jrobin/java/src/org/jrobin/data/Aggregator.java
deleted file mode 100644
index 05ceccbbc9..0000000000
--- a/apps/jrobin/java/src/org/jrobin/data/Aggregator.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.data;
-
-import org.jrobin.core.ConsolFuns;
-import org.jrobin.core.Util;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-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";
- this.timestamps = timestamps;
- this.values = values;
- this.step = timestamps[1] - timestamps[0];
- }
-
- Aggregates getAggregates(long tStart, long tEnd) {
- Aggregates agg = new Aggregates();
- int cnt = 0;
- int lslstep = 0;
- boolean firstFound = false;
- double SUMx, SUMy, SUMxy, SUMxx, SUMyy;
- SUMx = 0.0;
- SUMy = 0.0;
- SUMxy = 0.0;
- SUMxx = 0.0;
- SUMyy = 0.0;
-
- 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;
-
- // delta is only >= 0 when the timestamp for a given buck is within the range of tStart and tEnd
- 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;
- } else if (delta >= step) { // an entire bucket is included in this range
- agg.last = value;
-
- /*
- * Algorithmically, we're only updating last if it's either the first
- * bucket encountered, or it's a "full" bucket.
-
- if ( !isInRange(tEnd, left, right) ||
- (isInRange(tEnd, left, right) && !Double.isNaN(value))
- ) {
- agg.last = value;
- }
- */
-
- }
- if (!Double.isNaN(value)) {
- cnt++;
- SUMx += lslstep;
- SUMxx += lslstep * lslstep;
- SUMy = Util.sum(SUMy, value);
- SUMxy = Util.sum(SUMxy, lslstep * value);
- SUMyy = Util.sum(SUMyy, value * value);
- }
- lslstep ++;
- }
- }
- agg.average = cnt > 0 ? (SUMy / cnt) : Double.NaN;
-
- // Work on STDEV
- if (cnt > 0) {
- double stdevSum = 0.0;
- 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;
-
- // delta is only >= 0 when the timestamp for a given buck is within the range of tStart and tEnd
- if (delta >= 0) {
- double value = values[i];
- if (!Double.isNaN(value)) {
- stdevSum = Util.sum(stdevSum, Math.pow((value - agg.average), 2.0));
- }
- }
- }
- agg.stdev = Math.pow(stdevSum / cnt, 0.5);
-
- /* Bestfit line by linear least squares method */
- agg.lslslope = (SUMx * SUMy - cnt * SUMxy) / (SUMx * SUMx - cnt * SUMxx);
- agg.lslint = (SUMy - agg.lslslope * SUMx) / cnt;
- agg.lslcorrel =
- (SUMxy - (SUMx * SUMy) / cnt) /
- Math.sqrt((SUMxx - (SUMx * SUMx) / cnt) * (SUMyy - (SUMy * SUMy) / cnt));
- }
- agg.total = SUMy * step;
-
- return agg;
- }
-
- double getPercentile(long tStart, long tEnd, double percentile) {
- return getPercentile(tStart, tEnd, percentile, false);
- }
-
- double getPercentile(long tStart, long tEnd, double percentile, boolean includenan) {
- List
- * final long t1 = ...
- * final long t2 = ...
- * DataProcessor dp = new DataProcessor(t1, t2);
- * // DEF datasource
- * dp.addDatasource("x", "demo.rrd", "some_source", "AVERAGE");
- * // DEF datasource
- * dp.addDatasource("y", "demo.rrd", "some_other_source", "AVERAGE");
- * // CDEF datasource, z = (x + y) / 2
- * dp.addDatasource("z", "x,y,+,2,/");
- * // ACTION!
- * dp.processData();
- * // Dump calculated values
- * System.out.println(dp.dump());
- *
- */
-public class DataProcessor implements ConsolFuns {
- /**
- * Constant representing the default number of pixels on a JRobin graph (will be used if
- * no other value is specified with {@link #setStep(long) setStep()} method.
- */
- public static final int DEFAULT_PIXEL_COUNT = 600;
- private static final double DEFAULT_PERCENTILE = 95.0; // %
-
- private int pixelCount = DEFAULT_PIXEL_COUNT;
-
- /**
- * Constant that defines the default {@link RrdDbPool} usage policy. Defaults to false
- * (i.e. the pool will not be used to fetch data from RRD files)
- */
- public static final boolean DEFAULT_POOL_USAGE_POLICY = false;
- private boolean poolUsed = DEFAULT_POOL_USAGE_POLICY;
-
- private final long tStart;
- private long tEnd, timestamps[];
- private long lastRrdArchiveUpdateTime = 0;
- // this will be adjusted later
- private long step = 0;
- // resolution to be used for RRD fetch operation
- private long fetchRequestResolution = 1;
-
- // the order is important, ordinary HashMap is unordered
- private MapRPN
expression.
- * name
can be used:
- *
- *
- * name
- * can be used:
- *
- *
- * @param name source name.
- * @param file Path to RRD file.
- * @param dsName Datasource name defined in the RRD file.
- * @param consolFunc Consolidation function that will be used to extract data from the RRD
- * file ("AVERAGE", "MIN", "MAX" or "LAST" - these string constants are conveniently defined
- * in the {@link org.jrobin.core.ConsolFuns ConsolFuns} class).
- */
- public void addDatasource(String name, String file, String dsName, String consolFunc) {
- Def def = new Def(name, file, dsName, consolFunc);
- sources.put(name, def);
- }
-
- /**
- * name
can be used:
- *
- *
- * @param name Source name.
- * @param file Path to RRD file.
- * @param dsName Data source name defined in the RRD file.
- * @param consolFunc Consolidation function that will be used to extract data from the RRD
- * file ("AVERAGE", "MIN", "MAX" or "LAST" - these string constants are conveniently defined
- * in the {@link org.jrobin.core.ConsolFuns ConsolFuns} class).
- * @param backend Name of the RrdBackendFactory that should be used for this RrdDb.
- */
- public void addDatasource(String name, String file, String dsName, String consolFunc, String backend) {
- Def def = new Def(name, file, dsName, consolFunc, backend);
- sources.put(name, def);
- }
-
- /**
- * 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);
- }
-
- /**
- * Creates a new VDEF datasource that performs a percentile calculation on an
- * another named datasource to yield a single value.
- *
- * Requires that the other datasource has already been defined; otherwise, it'll
- * end up with no data
- *
- * @param name - the new virtual datasource name
- * @param sourceName - the datasource from which to extract the percentile. Must be a previously
- * defined virtual datasource
- * @param percentile - the percentile to extract from the source datasource
- */
- public void addDatasource(String name, String sourceName, double percentile) {
- Source source = sources.get(sourceName);
- sources.put(name, new PercentileDef(name, source, percentile));
- }
-
- /**
- * Creates a new VDEF datasource that performs a percentile calculation on an
- * another named datasource to yield a single value.
- *
- * Requires that the other datasource has already been defined; otherwise, it'll
- * end up with no data
- *
- * @param name - the new virtual datasource name
- * @param sourceName - the datasource from which to extract the percentile. Must be a previously
- * defined virtual datasource
- * @param percentile - the percentile to extract from the source datasource
- * @param ignorenan - true if we include Double.NaN
- */
- public void addDatasource(String name, String sourceName, double percentile, boolean ignorenan) {
- Source source = sources.get(sourceName);
- sources.put(name, new PercentileDef(name, source, percentile, ignorenan));
- }
-
- /////////////////////////////////////////////////////////////////
- // CALCULATIONS
- /////////////////////////////////////////////////////////////////
-
- /**
- * Method that should be called once all datasources are defined. Data will be fetched from
- * RRD files, RPN expressions will be calculated, etc.
- *
- * @throws IOException Thrown in case of I/O error (while fetching data from RRD files)
- * @throws RrdException Thrown in case of JRobin specific error
- */
- public void processData() throws IOException, RrdException {
- extractDefs();
- fetchRrdData();
- fixZeroEndingTimestamp();
- chooseOptimalStep();
- createTimestamps();
- assignTimestampsToSources();
- normalizeRrdValues();
- calculateNonRrdSources();
- }
-
- /**
- * Method used to calculate datasource values which should be presented on the graph
- * based on the desired graph width. Each value returned represents a single pixel on the graph.
- * Corresponding timestamp can be found in the array returned from {@link #getTimestampsPerPixel()}
- * method.
- *
- * @param sourceName Datasource name
- * @param pixelCount Graph width
- * @return Per-pixel datasource values
- * @throws RrdException Thrown if datasource values are not yet calculated (method {@link #processData()}
- * was not called)
- */
- public double[] getValuesPerPixel(String sourceName, int pixelCount) throws RrdException {
- setPixelCount(pixelCount);
- return getValuesPerPixel(sourceName);
- }
-
- /**
- * Method used to calculate datasource values which should be presented on the graph
- * based on the graph width set with a {@link #setPixelCount(int)} method call.
- * Each value returned represents a single pixel on the graph. Corresponding timestamp can be
- * found in the array returned from {@link #getTimestampsPerPixel()} method.
- *
- * @param sourceName Datasource name
- * @return Per-pixel datasource values
- * @throws RrdException Thrown if datasource values are not yet calculated (method {@link #processData()}
- * was not called)
- */
- public double[] getValuesPerPixel(String sourceName) throws RrdException {
- double[] values = getValues(sourceName);
- double[] pixelValues = new double[pixelCount];
- Arrays.fill(pixelValues, Double.NaN);
- long span = tEnd - tStart;
- // this is the ugliest nested loop I have ever made
- for (int pix = 0, ref = 0; pix < pixelCount; pix++) {
- double t = tStart + (double) (span * pix) / (double) (pixelCount - 1);
- while (ref < timestamps.length) {
- if (t <= timestamps[ref] - step) {
- // too left, nothing to do, already NaN
- break;
- }
- else if (t <= timestamps[ref]) {
- // in brackets, get this value
- pixelValues[pix] = values[ref];
- break;
- }
- else {
- // too right
- ref++;
- }
- }
- }
- return pixelValues;
- }
-
- /**
- * Calculates timestamps which correspond to individual pixels on the graph.
- *
- * @param pixelCount Graph width
- * @return Array of timestamps
- */
- public long[] getTimestampsPerPixel(int pixelCount) {
- setPixelCount(pixelCount);
- return getTimestampsPerPixel();
- }
-
- /**
- * Calculates timestamps which correspond to individual pixels on the graph
- * based on the graph width set with a {@link #setPixelCount(int)} method call.
- *
- * @return Array of timestamps
- */
- public long[] getTimestampsPerPixel() {
- long[] times = new long[pixelCount];
- long span = tEnd - tStart;
- for (int i = 0; i < pixelCount; i++) {
- times[i] = Math.round(tStart + (double) (span * i) / (double) (pixelCount - 1));
- }
- return times;
- }
-
- /**
- * Dumps timestamps and values of all datasources in a tabelar form. Very useful for debugging.
- *
- * @return Dumped object content.
- * @throws RrdException Thrown if nothing is calculated so far (the method {@link #processData()}
- * was not called).
- */
- public String dump() throws RrdException {
- String[] names = getSourceNames();
- double[][] values = getValues();
- StringBuilder buffer = new StringBuilder();
- buffer.append(format("timestamp", 12));
- for (String name : names) {
- buffer.append(format(name, 20));
- }
- buffer.append("\n");
- for (int i = 0; i < timestamps.length; i++) {
- buffer.append(format("" + timestamps[i], 12));
- for (int j = 0; j < names.length; j++) {
- buffer.append(format(Util.formatDouble(values[j][i]), 20));
- }
- buffer.append("\n");
- }
- return buffer.toString();
- }
-
- /**
- * Returns time when last RRD archive was updated (all RRD files are considered).
- *
- * @return Last archive update time for all RRD files in this DataProcessor
- */
- public long getLastRrdArchiveUpdateTime() {
- return lastRrdArchiveUpdateTime;
- }
-
- // PRIVATE METHODS
-
- private void extractDefs() {
- List
- * (t, 100)
and (t + 100, 300)
. Here are the results interpolator
- * returns for t + 50 seconds, for various interpolationMethods
:
- *
- *
- * If not set, interpolation method defaults to INTERPOLATE_LEFT: 100
- * INTERPOLATE_RIGHT: 300
- * INTERPOLATE_LINEAR: 200
- * INTERPOLATE_LINEAR
.
- * INTERPOLATE_LEFT
,
- * INTERPOLATE_RIGHT
, INTERPOLATE_LINEAR
or
- * INTERPOLATE_REGRESSION
. Any other value will be interpreted as
- * INTERPOLATE_LINEAR (default).
- */
- public void setInterpolationMethod(int interpolationMethod) {
- switch (interpolationMethod) {
- case INTERPOLATE_REGRESSION:
- calculateBestFitLine();
- this.interpolationMethod = interpolationMethod;
- break;
- case INTERPOLATE_LEFT:
- case INTERPOLATE_RIGHT:
- case INTERPOLATE_LINEAR:
- this.interpolationMethod = interpolationMethod;
- break;
- default:
- this.interpolationMethod = INTERPOLATE_LINEAR;
- }
- }
-
- private void calculateBestFitLine() {
- int count = timestamps.length, validCount = 0;
- double ts = 0.0, vs = 0.0;
- for (int i = 0; i < count; i++) {
- if (!Double.isNaN(values[i])) {
- ts += timestamps[i];
- vs += values[i];
- validCount++;
- }
- }
- if (validCount <= 1) {
- // just one not-NaN point
- b0 = b1 = Double.NaN;
- return;
- }
- ts /= validCount;
- vs /= validCount;
- double s1 = 0, s2 = 0;
- for (int i = 0; i < count; i++) {
- if (!Double.isNaN(values[i])) {
- double dt = timestamps[i] - ts;
- double dv = values[i] - vs;
- s1 += dt * dv;
- s2 += dt * dt;
- }
- }
- b1 = s1 / s2;
- b0 = vs - b1 * ts;
- }
-
- /**
- * Method overriden from the base class. This method will be called by the framework. Call
- * this method only if you need interpolated values in your code.
- *
- * @param timestamp timestamp in seconds
- * @return inteprolated datasource value
- */
- public double getValue(long timestamp) {
- if (interpolationMethod == INTERPOLATE_REGRESSION) {
- return b0 + b1 * timestamp;
- }
- int count = timestamps.length;
- // check if out of range
- if (timestamp < timestamps[0] || timestamp > timestamps[count - 1]) {
- return Double.NaN;
- }
- // find matching segment
- int startIndex = lastIndexUsed;
- if (timestamp < timestamps[lastIndexUsed]) {
- // backward reading, shift to the first timestamp
- startIndex = 0;
- }
- for (int i = startIndex; i < count; i++) {
- if (timestamps[i] == timestamp) {
- return values[i];
- }
- if (i < count - 1 && timestamps[i] < timestamp && timestamp < timestamps[i + 1]) {
- // matching segment found
- lastIndexUsed = i;
- switch (interpolationMethod) {
- case INTERPOLATE_LEFT:
- return values[i];
- case INTERPOLATE_RIGHT:
- return values[i + 1];
- case INTERPOLATE_LINEAR:
- double slope = (values[i + 1] - values[i]) /
- (timestamps[i + 1] - timestamps[i]);
- return values[i] + slope * (timestamp - timestamps[i]);
- default:
- return Double.NaN;
- }
- }
- }
- // should not be here ever, but let's satisfy the compiler
- return Double.NaN;
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/data/Normalizer.java b/apps/jrobin/java/src/org/jrobin/data/Normalizer.java
deleted file mode 100644
index 34c177e741..0000000000
--- a/apps/jrobin/java/src/org/jrobin/data/Normalizer.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.data;
-
-import org.jrobin.core.Util;
-
-import java.util.Arrays;
-
-class Normalizer {
- final private long[] timestamps;
- final int count;
- final 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];
- System.arraycopy(rawValues, 0, values, 0, n);
- return values;
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/data/PDef.java b/apps/jrobin/java/src/org/jrobin/data/PDef.java
deleted file mode 100644
index b6bb1f315c..0000000000
--- a/apps/jrobin/java/src/org/jrobin/data/PDef.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-
-package org.jrobin.data;
-
-class PDef extends Source {
- private final Plottable plottable;
-
- PDef(String name, Plottable plottable) {
- super(name);
- this.plottable = plottable;
- }
-
- 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);
- }
-}
diff --git a/apps/jrobin/java/src/org/jrobin/data/PercentileDef.java b/apps/jrobin/java/src/org/jrobin/data/PercentileDef.java
deleted file mode 100644
index 853f4d9501..0000000000
--- a/apps/jrobin/java/src/org/jrobin/data/PercentileDef.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011 Craig Miskell
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.data;
-
-import org.jrobin.core.RrdException;
-
-public class PercentileDef extends Source {
-
- private Source m_source;
-
- private double m_value;
-
- private double m_percentile;
-
- @SuppressWarnings("unused")
- private boolean m_ignorenan;
-
- PercentileDef(String name, Source source, double percentile) {
- this(name, source, percentile, false);
- }
-
- PercentileDef(String name, Source source, double percentile, boolean ignorenan) {
- super(name);
-
- m_percentile = percentile;
- m_ignorenan = ignorenan;
- m_source = source;
-
- //The best we can do at this point; until this object has it's value realized over a
- // particular time period (with calculate()), there's not much else to do
- this.setValue(Double.NaN);
- }
-
- /**
- * Realize the calculation of this definition, over the given time period
- *
- * @param tStart the time period start
- * @param tEnd the time period end
- * @throws RrdException Thrown if we cannot get a percentile value for the time period.
- */
- public void calculate(long tStart, long tEnd) throws RrdException {
- if(m_source != null) {
- this.setValue(m_source.getPercentile(tStart, tEnd, m_percentile));
- }
- }
-
- /**
- * Takes the given value and puts it in each position in the 'values' array.
- * @param value
- */
- private void setValue(double value) {
- this.m_value = value;
- long[] times = getTimestamps();
- if( times != null ) {
- int count = times.length;
- double[] values = new double[count];
- for (int i = 0; i < count; i++) {
- values[i] = m_value;
- }
- setValues(values);
- }
- }
-
- @Override
- void setTimestamps(long[] timestamps) {
- super.setTimestamps(timestamps);
- //And now also call setValue with the current value, to sort out "values"
- setValue(m_value);
- }
-
- /**
- * Same as SDef; the aggregates of a static value are all just the
- * same static value.
- *
- * Assumes this def has been realized by calling calculate(), otherwise
- * the aggregated values will be NaN
- */
- @Override
- Aggregates getAggregates(long tStart, long tEnd) throws RrdException {
- Aggregates agg = new Aggregates();
- agg.first = agg.last = agg.min = agg.max = agg.average = m_value;
- agg.total = m_value * (tEnd - tStart);
- return agg;
- }
-
- /**
- * Returns just the calculated percentile; the "Xth" percentile of a static value is
- * the static value itself.
- *
- * Assumes this def has been realized by calling calculate(), otherwise
- * the aggregated values will be NaN
- */
- @Override
- double getPercentile(long tStart, long tEnd, double percentile)
- throws RrdException {
- return m_value;
- }
-
-}
diff --git a/apps/jrobin/java/src/org/jrobin/data/Plottable.java b/apps/jrobin/java/src/org/jrobin/data/Plottable.java
deleted file mode 100644
index b8c879608e..0000000000
--- a/apps/jrobin/java/src/org/jrobin/data/Plottable.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2001-2005 Sasa Markovic and Ciaran Treanor.
- * Copyright (c) 2011 The OpenNMS Group, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *******************************************************************************/
-package org.jrobin.data;
-
-/**
- *
- * setTimeAxis(RrdGraphConstants.MINUTE, 10,
- * RrdGraphConstants.HOUR, 1,
- * RrdGraphConstants.HOUR, 1,
- * 0, "%H:%M")
- *
- *
- * setImageInfo("<IMG SRC='/img/%s' WIDTH='%d' HEIGHT='%d' ALT='Demo'>");
- *
- *
- * @param imageInfo Image info format. Use %s placeholder for filename, %d placeholder for
- * image width and height.
- */
- public void setImageInfo(String imageInfo) {
- this.imageInfo = imageInfo;
- }
-
- /**
- * Sets image format.
- *
- * @param imageFormat "PNG", "GIF" or "JPG".
- */
- public void setImageFormat(String imageFormat) {
- this.imageFormat = imageFormat;
- }
-
- /**
- * Sets background image - currently, only PNG images can be used as background.
- *
- * @param backgroundImage Path to background image
- */
- public void setBackgroundImage(String backgroundImage) {
- this.backgroundImage = backgroundImage;
- }
-
- /**
- * Sets overlay image - currently, only PNG images can be used as overlay. Overlay image is
- * printed on the top of the image, once it is completely created.
- *
- * @param overlayImage Path to overlay image
- */
- public void setOverlayImage(String overlayImage) {
- this.overlayImage = overlayImage;
- }
-
- /**
- * Sets unit to be displayed on y axis. It is wise to use only short units on graph, however.
- *
- * @param unit Unit description
- */
- public void setUnit(String unit) {
- this.unit = unit;
- }
-
- /**
- * Creates graph only if the current graph is out of date or not existent.
- *
- * @param lazy true, if graph should be 'lazy', false otherwise (defualt)
- */
- public void setLazy(boolean lazy) {
- this.lazy = lazy;
- }
-
- /**
- * Sets the lower limit of a graph. But rather, this is the
- * maximum lower bound of a graph. For example, the value -100 will
- * result in a graph that has a lower limit of -100 or less. Use this
- * method to expand graphs down.
- *
- * @param minValue Minimal value displayed on the graph
- */
- public void setMinValue(double minValue) {
- this.minValue = minValue;
- }
-
- /**
- * Defines the value normally located at the upper border of the
- * graph. If the graph contains higher values, the upper border will
- * move upwards to accommodate these values as well.
- * true
argument you can disable this behavior.
- *
- * @param rigid true if uper and lower limits should not be expanded to accomodate
- * values outside of the specified range. False otherwise (default).
- */
- public void setRigid(boolean rigid) {
- this.rigid = rigid;
- }
-
- /**
- * Sets default base for magnitude scaling. If you are graphing memory
- * (and NOT network traffic) this switch should be set to 1024 so that 1Kb is 1024 byte.
- * For traffic measurement, 1 kb/s is 1000 b/s.
- *
- * @param base Base value (defaults to 1000.0)
- */
- public void setBase(double base) {
- this.base = base;
- }
-
- /**
- * Sets logarithmic y-axis scaling.
- *
- * @param logarithmic true, for logarithmic scaling, false otherwise (default).
- */
- public void setLogarithmic(boolean logarithmic) {
- this.logarithmic = logarithmic;
- }
-
- /**
- * Overrides the colors for the standard elements of the graph. The colorTag
- * must be one of the following constants defined in the
- * {@link RrdGraphConstants}:
- * {@link RrdGraphConstants#COLOR_BACK COLOR_BACK} background,
- * {@link RrdGraphConstants#COLOR_CANVAS COLOR_CANVAS} canvas,
- * {@link RrdGraphConstants#COLOR_SHADEA COLOR_SHADEA} left/top border,
- * {@link RrdGraphConstants#COLOR_SHADEB COLOR_SHADEB} right/bottom border,
- * {@link RrdGraphConstants#COLOR_GRID COLOR_GRID} major grid,
- * {@link RrdGraphConstants#COLOR_MGRID COLOR_MGRID} minor grid,
- * {@link RrdGraphConstants#COLOR_FONT COLOR_FONT} font,
- * {@link RrdGraphConstants#COLOR_FRAME COLOR_FRAME} axis of the graph,
- * {@link RrdGraphConstants#COLOR_ARROW COLOR_ARROW} arrow. This method can
- * be called multiple times to set several colors.
- *
- * @param colorTag Color tag, as explained above.
- * @param color Any color (paint) you like
- * @throws RrdException Thrown if invalid colorTag is supplied.
- */
- public void setColor(int colorTag, Paint color) throws RrdException {
- if (colorTag >= 0 && colorTag < colors.length) {
- colors[colorTag] = color;
- }
- else {
- throw new RrdException("Invalid color index specified: " + colorTag);
- }
- }
-
- /**
- * Overrides the colors for the standard elements of the graph by element name.
- * See {@link #setColor(int, java.awt.Paint)} for full explanation.
- *
- * @param colorName One of the following strings: "BACK", "CANVAS", "SHADEA", "SHADEB",
- * "GRID", "MGRID", "FONT", "FRAME", "ARROW"
- * @param color Any color (paint) you like
- * @throws RrdException Thrown if invalid element name is supplied.
- */
- public void setColor(String colorName, Paint color) throws RrdException {
- setColor(getColorTagByName(colorName), color);
- }
-
- private static int getColorTagByName(String colorName) throws RrdException {
- for (int i = 0; i < COLOR_NAMES.length; i++) {
- if (COLOR_NAMES[i].equalsIgnoreCase(colorName)) {
- return i;
- }
- }
- throw new RrdException("Unknown color name specified: " + colorName);
- }
-
- /**
- * Suppress generation of legend, only render the graph.
- *
- * @param noLegend true if graph legend should be omitted. False otherwise (default).
- */
- public void setNoLegend(boolean noLegend) {
- this.noLegend = noLegend;
- }
-
- /**
- * Suppresses anything but the graph, works only for height < 64.
- *
- * @param onlyGraph true if only graph should be created, false otherwise (default).
- */
- public void setOnlyGraph(boolean onlyGraph) {
- this.onlyGraph = onlyGraph;
- }
-
- /**
- * Force the generation of HRULE and VRULE legend even if those HRULE
- * or VRULE will not be drawn because out of graph boundaries.
- *
- * @param forceRulesLegend true if rule legend should be always printed,
- * false otherwise (default).
- */
- public void setForceRulesLegend(boolean forceRulesLegend) {
- this.forceRulesLegend = forceRulesLegend;
- }
-
- /**
- * Defines a title to be written into the graph.
- *
- * @param title Graph title.
- */
- public void setTitle(String title) {
- this.title = title;
- }
-
- /**
- * Suggests which time step should be used by JRobin while processing data from RRD files.
- *
- * @param step Desired time step (don't use this method if you don't know what you're doing).
- */
- public void setStep(long step) {
- this.step = step;
- }
-
- /**
- * Get the default small font for graphing.
- *
- * @return the font
- */
- public Font getSmallFont() {
- return this.fonts[FONTTAG_DEFAULT];
- }
-
- /**
- * Get the default large font for graphing.
- *
- * @return the font
- */
- public Font getLargeFont() {
- return this.fonts[FONTTAG_TITLE];
- }
-
- /**
- * Sets default font for graphing. Note that JRobin will behave unpredictably if proportional
- * font is selected.
- *
- * @param smallFont Default font for graphing. Use only monospaced fonts.
- * @throws RrdException Thrown if invalid fontTag is supplied.
- */
- public void setSmallFont(final Font smallFont) throws RrdException{
- this.setFont(FONTTAG_DEFAULT, smallFont);
- }
-
- /**
- * Sets title font.
- *
- * @param largeFont Font to be used for graph title.
- * @throws RrdException Thrown if invalid fontTag is supplied.
- */
- public void setLargeFont(final Font largeFont) throws RrdException {
- this.setFont(FONTTAG_TITLE, largeFont);
- }
-
- /**
- * Sets font to be used for a specific font tag. The fontTag
- * must be one of the following constants defined in the
- * {@link RrdGraphConstants}:
- * {@link RrdGraphConstants#FONTTAG_DEFAULT FONTTAG_DEFAULT} default font,,
- * {@link RrdGraphConstants#FONTTAG_TITLE FONTTAG_TITLE} title,
- * {@link RrdGraphConstants#FONTTAG_AXIS FONTTAG_AXIS} grid axis,,
- * {@link RrdGraphConstants#FONTTAG_UNIT FONTTAG_UNIT} vertical unit label,,
- * {@link RrdGraphConstants#FONTTAG_LEGEND FONTTAG_LEGEND} legend,
- * {@link RrdGraphConstants#FONTTAG_WATERMARK FONTTAG_WATERMARK} watermark.
- * This method can be called multiple times to set several fonts.
- *
- * @param fontTag Font tag, as explained above.
- * @param font Font to be used for tag
- * @throws RrdException Thrown if invalid fontTag is supplied.
- */
- public void setFont(final int fontTag, final Font font) throws RrdException {
- this.setFont(fontTag, font, false);
- }
-
- /**
- * Sets font.
- *
- * @param fontTag Font tag, as explained above.
- * @param font Font to be used for tag
- * @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
- * @throws RrdException Thrown if invalid fontTag is supplied.
- */
- public void setFont(final int fontTag, final Font font, final boolean setAll) throws RrdException {
- this.setFont(fontTag, font, setAll, false);
- }
-
- /**
- * Sets font.
- *
- * @param fontTag Font tag, as explained above.
- * @param font Font to be used for tag
- * @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
- * @param keepSizes Boolean to flag whether to keep original font sizes if setting all fonts.
- */
- public void setFont(final int fontTag, final Font font, final boolean setAll, final boolean keepSizes) {
- if (fontTag == FONTTAG_DEFAULT && setAll) {
- if (keepSizes) {
- this.fonts[FONTTAG_DEFAULT] = font.deriveFont(this.fonts[FONTTAG_DEFAULT].getSize());
- this.fonts[FONTTAG_TITLE] = font.deriveFont(this.fonts[FONTTAG_TITLE].getSize());
- this.fonts[FONTTAG_AXIS] = font.deriveFont(this.fonts[FONTTAG_AXIS].getSize());
- this.fonts[FONTTAG_UNIT] = font.deriveFont(this.fonts[FONTTAG_UNIT].getSize());
- this.fonts[FONTTAG_LEGEND] = font.deriveFont(this.fonts[FONTTAG_LEGEND].getSize());
- this.fonts[FONTTAG_WATERMARK] = font.deriveFont(this.fonts[FONTTAG_WATERMARK].getSize());
- } else {
- this.fonts[FONTTAG_DEFAULT] = font;
- this.fonts[FONTTAG_TITLE] = null;
- this.fonts[FONTTAG_AXIS] = null;
- this.fonts[FONTTAG_UNIT] = null;
- this.fonts[FONTTAG_LEGEND] = null;
- this.fonts[FONTTAG_WATERMARK] = null;
- }
- } else {
- this.fonts[fontTag] = font;
- }
- }
-
- /**
- * Sets font.
- *
- * @param fontTag Font tag as String, as explained in {@link RrdGraphDef#setFont setFont(int, java.awt.Font)}.
- * @param font Font to be used for tag
- * @throws RrdException Thrown if invalid fontTag is supplied.
- */
- public void setFont(final String fontTag, final Font font) throws RrdException {
- this.setFont(getFontTagByName(fontTag), font);
- }
-
- /**
- * Sets font.
- *
- * @param fontTag Font tag as String, as explained in {@link RrdGraphDef#setFont setFont(int, java.awt.Font)}.
- * @param font Font to be used for tag
- * @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
- * @throws RrdException Thrown if invalid fontTag is supplied.
- */
- public void setFont(final String fontTag, final Font font, final boolean setAll) throws RrdException {
- this.setFont(getFontTagByName(fontTag), font, setAll);
- }
-
- /**
- * Sets font.
- *
- * @param fontTag Font tag as String, as explained in {@link RrdGraphDef#setFont setFont(int, java.awt.Font)}.
- * @param font Font to be used for tag
- * @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
- * @param keepSizes Boolean to flag whether to keep original font sizes if setting all fonts.
- * @throws RrdException Thrown if invalid fontTag is supplied.
- */
- public void setFont(final String fontTag, final Font font, final boolean setAll, final boolean keepSizes) throws RrdException {
- this.setFont(getFontTagByName(fontTag), font, setAll, keepSizes);
- }
-
- private static int getFontTagByName(String tagName) throws RrdException {
- for (int i = 0; i < FONTTAG_NAMES.length; i++) {
- if (FONTTAG_NAMES[i].equalsIgnoreCase(tagName)) {
- return i;
- }
- }
- throw new RrdException("Unknown tag name specified: " + tagName);
- }
-
- public Font getFont(int tag) {
- return this.fonts[tag] == null ? this.fonts[FONTTAG_DEFAULT] : this.fonts[tag];
- }
-
- /**
- * Defines virtual datasource. This datasource can then be used
- * in other methods like {@link #datasource(String, String)} or
- * {@link #gprint(String, String, String)}.
- *
- * @param name Source name
- * @param rrdPath Path to RRD file
- * @param dsName Datasource name in the specified RRD file
- * @param consolFun Consolidation function (AVERAGE, MIN, MAX, LAST)
- */
- public void datasource(String name, String rrdPath, String dsName, String consolFun) {
- sources.add(new Def(name, rrdPath, dsName, consolFun));
- }
-
- /**
- * Defines virtual datasource. This datasource can then be used
- * in other methods like {@link #datasource(String, String)} or
- * {@link #gprint(String, String, String)}.
- *
- * @param name Source name
- * @param rrdPath Path to RRD file
- * @param dsName Datasource name in the specified RRD file
- * @param consolFun Consolidation function (AVERAGE, MIN, MAX, LAST)
- * @param backend Backend to be used while fetching data from a RRD file.
- */
- public void datasource(String name, String rrdPath, String dsName, String consolFun, String backend) {
- sources.add(new Def(name, rrdPath, dsName, consolFun, backend));
- }
-
- /**
- * Create a new virtual datasource by evaluating a mathematical
- * expression, specified in Reverse Polish Notation (RPN).
- *
- * @param name Source name
- * @param rpnExpression RPN expression.
- */
- public void datasource(String name, String rpnExpression) {
- sources.add(new CDef(name, rpnExpression));
- }
-
- /**
- * Creates a new (static) virtual datasource. The value of the datasource is constant. This value is
- * evaluated by applying the given consolidation function to another virtual datasource.
- *
- * @param name Source name
- * @param defName Other source name
- * @param consolFun Consolidation function to be applied to other datasource.
- */
- public void datasource(String name, String defName, String consolFun) {
- sources.add(new SDef(name, defName, consolFun));
- }
-
- /**
- * Creates a new (plottable) datasource. Datasource values are obtained from the given plottable
- * object.
- *
- * @param name Source name.
- * @param plottable Plottable object.
- */
- public void datasource(String name, Plottable plottable) {
- sources.add(new PDef(name, plottable));
- }
-
- /**
- * Creates a new static virtual datasource that performs a percentile calculation on an
- * another named datasource to yield a single value.
- *
- * <rrd_graph_def>
- * <!-- use '-' to represent in-memory graph -->
- * <filename>test.png</filename>
- * <!--
- * starting and ending timestamps can be specified by
- * using at-style time specification, or by specifying
- * exact timestamps since epoch (without milliseconds)
- * -->
- * <span>
- * <start>now - 1d</start>
- * <end>now</end>
- * </span>
- * <options>
- * <!--
- * specify 'true' if you want to use RrdDbPool while
- * creating graph
- * -->
- * <use_pool>false</use_pool>
- * <anti_aliasing>true</anti_aliasing>
- * <time_grid>
- * <show_grid>true</show_grid>
- * <!-- allowed units: second, minute, hour, day, week, month, year -->
- * <minor_grid_unit>minute</minor_grid_unit>
- * <minor_grid_unit_count>60</minor_grid_unit_count>
- * <major_grid_unit>hour</major_grid_unit>
- * <major_grid_unit_count>2</major_grid_unit_count>
- * <label_unit>hour</label_unit>
- * <label_unit_count>2</label_unit_count>
- * <label_span>1200</label_span>
- * <!-- use SimpleDateFormat or strftime-like format to format labels -->
- * <label_format>dd-MMM-yy</label_format>
- * </time_grid>
- * <value_grid>
- * <show_grid>true</show_grid>
- * <grid_step>100.0</grid_step>
- * <label_factor>5</label_factor>
- * </value_grid>
- * <no_minor_grid>true</no_minor_grid>
- * <alt_y_grid>true</alt_y_grid>
- * <alt_y_mrtg>true</alt_y_mrtg>
- * <alt_autoscale>true</alt_autoscale>
- * <alt_autoscale_max>true</alt_autoscale_max>
- * <units_exponent>3</units_exponent>
- * <units_length>13</units_length>
- * <vertical_label>Speed (kbits/sec)</vertical_label>
- * <width>444</width>
- * <height>222</height>
- * <interlaced>true</interlaced>
- * <image_info>filename = %s, width=%d, height=%d</image_info>
- * <image_format>png</image_format>
- * <image_quality>0.8</image_quality>
- * <background_image>luka.png</background_image>
- * <overlay_image>luka.png</overlay_image>
- * <unit>kilos</unit>
- * <lazy>false</lazy>
- * <min_value>0</min_value>
- * <max_value>5000</max_value>
- * <rigid>true</rigid>
- * <base>1000</base>
- * <logarithmic>false</logarithmic>
- * <colors>
- * <canvas>#FFFFFF</canvas>
- * <back>#FFFFFF</back>
- * <shadea>#AABBCC</shadea>
- * <shadeb>#DDDDDD</shadeb>
- * <grid>#FF0000</grid>
- * <mgrid>#00FF00</mgrid>
- * <font>#FFFFFF</font>
- * <frame>#EE00FF</frame>
- * <arrow>#FF0000</arrow>
- * </colors>
- * <no_legend>false</no_legend>
- * <only_graph>false</only_graph>
- * <force_rules_legend>false</force_rules_legend>
- * <title>This is a title</title>
- * <step>300</step>
- * <fonts>
- * <small_font>
- * <name>Courier</name>
- * <style>bold italic</style>
- * <size>12</size>
- * </small_font>
- * <large_font>
- * <name>Courier</name>
- * <style>plain</style>
- * <size>11</size>
- * </large_font>
- * </fonts>
- * <first_day_of_week>SUNDAY</first_day_of_week>
- * </options>
- * <datasources>
- * <def>
- * <name>x</name>
- * <rrd>test.rrd</rrd>
- * <source>sun</source>
- * <cf>AVERAGE</cf>
- * <backend>FILE</backend>
- * </def>
- * <def>
- * <name>y</name>
- * <rrd>test.rrd</rrd>
- * <source>shade</source>
- * <cf>AVERAGE</cf>
- * </def>
- * <cdef>
- * <name>x_plus_y</name>
- * <rpn>x,y,+</rpn>
- * </cdef>
- * <cdef>
- * <name>x_minus_y</name>
- * <rpn>x,y,-</rpn>
- * </cdef>
- * <sdef>
- * <name>x_avg</name>
- * <source>x</source>
- * <cf>AVERAGE</cf>
- * </sdef>
- * <sdef>
- * <name>y_max</name>
- * <source>y</source>
- * <cf>MAX</cf>
- * </sdef>
- * </datasources>
- * <graph>
- * <area>
- * <datasource>x</datasource>
- * <color>#FF0000</color>
- * <legend>X value\r</legend>
- * </area>
- * <stack>
- * <datasource>y</datasource>
- * <color>#00FF00</color>
- * <legend>Y value\r</legend>
- * </stack>
- * <line>
- * <datasource>x</datasource>
- * <color>#FF0000</color>
- * <legend>X value\r</legend>
- * <width>2</width>
- * </line>
- * <print>
- * <datasource>x</datasource>
- * <cf>AVERAGE</cf>
- * <format>Average is %7.3f\c</format>
- * </print>
- * <gprint>
- * <datasource>y</datasource>
- * <cf>MAX</cf>
- * <format>Max is %7.3f\c</format>
- * </gprint>
- * <hrule>
- * <value>1250</value>
- * <color>#0000FF</color>
- * <legend>This is a horizontal rule</legend>
- * </hrule>
- * <vrule>
- * <time>now-6h</time>
- * <color>#0000FF</color>
- * <legend>This is a vertical rule</legend>
- * </vrule>
- * <comment>Simple comment</comment>
- * <comment>One more comment\c</comment>
- * </graph>
- * </rrd_graph_def>
- *
- * Notes on the template syntax:
- *
- *
- * Any template value (text between true
, on
, yes
, y
,
- * or 1
to specify boolean true
value (anything else will
- * be treated as false
).
- * <some_tag>
and
- * </some_tag>
) can be replaced with
- * a variable of the following form: ${variable_name}
. Use
- * {@link XmlTemplate#setVariable(String, String) setVariable()}
- * methods from the base class to replace
- * template variables with real values at runtime.
- *
- *
- * You should create new RrdGraphDefTemplate object only once for each XML template. Single template
- * object can be reused to create as many RrdGraphDef objects as needed, with different values
- * specified for template variables. XML synatax check is performed only once - the first graph
- * definition object gets created relatively slowly, but it will be created much faster next time.
- */
-public class RrdGraphDefTemplate extends XmlTemplate implements RrdGraphConstants {
- static final Color BLIND_COLOR = new Color(0, 0, 0, 0);
-
- private RrdGraphDef rrdGraphDef;
-
- /**
- * Creates template object from any parsable XML source
- *
- * @param inputSource XML source
- * @throws IOException thrown in case of I/O error
- * @throws RrdException usually thrown in case of XML related error
- */
- public RrdGraphDefTemplate(InputSource inputSource) throws IOException, RrdException {
- super(inputSource);
- }
-
- /**
- * Creates template object from the file containing XML template code
- *
- * @param xmlFile file containing XML template
- * @throws IOException thrown in case of I/O error
- * @throws RrdException usually thrown in case of XML related error
- */
- public RrdGraphDefTemplate(File xmlFile) throws IOException, RrdException {
- super(xmlFile);
- }
-
- /**
- * Creates template object from the string containing XML template code
- *
- * @param xmlString string containing XML template
- * @throws IOException thrown in case of I/O error
- * @throws RrdException usually thrown in case of XML related error
- */
- public RrdGraphDefTemplate(String xmlString) throws IOException, RrdException {
- super(xmlString);
- }
-
- /**
- * Creates RrdGraphDef object which can be used to create RrdGraph
- * object (actual JRobin graphs). Before this method is called, all template variables (if any)
- * must be resolved (replaced with real values).
- * See {@link XmlTemplate#setVariable(String, String) setVariable()} method information to
- * understand how to supply values for template variables.
- *
- * @return Graph definition which can be used to create RrdGraph object (actual JRobin graphs)
- * @throws RrdException Thrown if parsed XML template contains invalid (unrecognized) tags
- */
- public RrdGraphDef getRrdGraphDef() throws RrdException {
- // basic check
- if (!root.getTagName().equals("rrd_graph_def")) {
- throw new RrdException("XML definition must start with
- * <rrd_graph_def>
- * ...
- * <span>
- * <start>${start}</start>
- * <end>${end}</end>
- * </span>
- * ...
- *
- *
- * RrdGraphDefTemplate t = new RrdGraphDefTemplate(new File(template.xml));
- *
- *
- * t.setVariable("start", new GregorianCalendar(2004, 2, 25));
- * t.setVariable("end", new GregorianCalendar(2004, 2, 26));
- *
- *
- * RrdGraphDef gdef = t.getRrdGraphDef();
- * RrdGraph g = new RrdGraph(gdef);
- *
- * getAggregates()
method in
+ * {@link org.rrd4j.core.FetchData#getAggregates(String) FetchData} and
+ * {@link org.rrd4j.data.DataProcessor#getAggregates(String)} DataProcessor classes.
+ *
+ * @deprecated This class is deprecated. Uses instance of {@link org.rrd4j.data.Variable}, used with {@link org.rrd4j.data.DataProcessor#addDatasource(String, String, Variable)}.
+ */
+@Deprecated
+public class Aggregates {
+ double min = Double.NaN, max = Double.NaN;
+ double first = Double.NaN, last = Double.NaN;
+ double average = Double.NaN, total = Double.NaN;
+
+ /**
+ * 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 value
+ *
+ * @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 constants
+ * are conveniently defined in the {@link org.rrd4j.ConsolFun ConsolFun} interface.
+ * @return Aggregated value
+ * @throws java.lang.IllegalArgumentException Thrown if unsupported consolidation function is supplied
+ */
+ public double getAggregate(ConsolFun consolFun) {
+ switch (consolFun) {
+ case AVERAGE:
+ return average;
+ case FIRST:
+ return first;
+ case LAST:
+ return last;
+ case MAX:
+ return max;
+ case MIN:
+ return min;
+ case TOTAL:
+ return total;
+ }
+ throw new IllegalArgumentException("Unknown consolidation function: " + consolFun);
+ }
+
+ /**
+ * Returns String representing all aggregated values. Just for debugging purposes.
+ *
+ * @return String containing all aggregated values
+ */
+ public String dump() {
+ StringBuilder bl = new StringBuilder();
+ for(ConsolFun cf: ConsolFun.values()) {
+ bl.append(cf.name() + '=' + Util.formatDouble(this.getAggregate(cf)));
+ }
+ return bl.toString();
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/data/Aggregator.java b/apps/jrobin/java/src/org/rrd4j/data/Aggregator.java
new file mode 100644
index 0000000000..bfbc8f6dd8
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/data/Aggregator.java
@@ -0,0 +1,93 @@
+package org.rrd4j.data;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+class Aggregator {
+ private final long timestamps[], step;
+ private final 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";
+ this.timestamps = timestamps;
+ this.values = values;
+ this.step = timestamps[1] - timestamps[0];
+ }
+
+ @Deprecated
+ Aggregates getAggregates(long tStart, long tEnd) {
+ Aggregates agg = new Aggregates();
+ long totalSeconds = 0;
+ int cnt = 0;
+
+ 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;
+
+ // delta is only > 0 when the time stamp for a given buck is within the range of tStart and tEnd
+ if (delta > 0) {
+ double value = values[i];
+
+ if (!Double.isNaN(value)) {
+ totalSeconds += delta;
+ cnt++;
+
+ if (cnt == 1) {
+ agg.last = agg.first = agg.total = agg.min = agg.max = value;
+ }
+ else {
+ if (delta >= step) { // an entire bucket is included in this range
+ agg.last = value;
+ }
+
+ agg.min = Math.min(agg.min, value);
+ agg.max = Math.max(agg.max, value);
+ agg.total += value;
+
+ }
+ }
+ }
+ }
+
+ if(cnt > 0) {
+ agg.average = agg.total / totalSeconds;
+ }
+
+ return agg;
+ }
+
+ double getPercentile(long tStart, long tEnd, double percentile) {
+ List
+ * final long t1 = ...
+ * final long t2 = ...
+ * DataProcessor dp = new DataProcessor(t1, t2);
+ * // DEF datasource
+ * dp.addDatasource("x", "demo.rrd", "some_source", "AVERAGE");
+ * // DEF datasource
+ * dp.addDatasource("y", "demo.rrd", "some_other_source", "AVERAGE");
+ * // CDEF datasource, z = (x + y) / 2
+ * dp.addDatasource("z", "x,y,+,2,/");
+ * // ACTION!
+ * dp.processData();
+ * // Dump calculated values
+ * System.out.println(dp.dump());
+ *
+ */
+public class DataProcessor {
+
+ /**
+ * Constant representing the default number of pixels on a Rrd4j graph (will be used if
+ * no other value is specified with {@link #setStep(long) setStep()} method.
+ */
+ public static final int DEFAULT_PIXEL_COUNT = 600;
+ /** Constant DEFAULT_PERCENTILE=95.0
*/
+ public static final double DEFAULT_PERCENTILE = 95.0; // %
+
+ private int pixelCount = DEFAULT_PIXEL_COUNT;
+
+ /**
+ * Constant that defines the default {@link RrdDbPool} usage policy. Defaults to false
+ * (i.e. the pool will not be used to fetch data from RRD files)
+ */
+ public static final boolean DEFAULT_POOL_USAGE_POLICY = false;
+ private boolean poolUsed = DEFAULT_POOL_USAGE_POLICY;
+ private RrdDbPool pool = null;
+
+ private final long tStart;
+ private long tEnd, timestamps[];
+ private long lastRrdArchiveUpdateTime = 0;
+ // this will be adjusted later
+ private long step = 0;
+ // resolution to be used for RRD fetch operation
+ private long fetchRequestResolution = 1;
+ // The timezone to use
+ private TimeZone tz = TimeZone.getDefault();
+
+ // the order is important, ordinary HashMap is unordered
+ private MapRPN
expression.name
can be used:
+ *
+ *
+ *
+ * The supported RPN functions, operators and constants are detailed at
+ * RRD4J's wiki.
+ * name
+ * can be used:
+ *
+ *
+ * @param name source name.
+ * @param file Path to RRD file.
+ * @param dsName Datasource name defined in the RRD file.
+ * @param consolFunc Consolidation function that will be used to extract data from the RRD
+ */
+ public void addDatasource(String name, String file, String dsName, ConsolFun consolFunc) {
+ Def def = new Def(name, file, dsName, consolFunc);
+ sources.put(name, def);
+ }
+
+ /**
+ * name
can be used:
+ *
+ *
+ * @param name Source name.
+ * @param file Path to RRD file.
+ * @param dsName Data source name defined in the RRD file.
+ * @param consolFunc Consolidation function that will be used to extract data from the RRD
+ * file ("AVERAGE", "MIN", "MAX" or "LAST" - these string constants are conveniently defined
+ * in the {@link org.rrd4j.ConsolFun ConsolFun} class).
+ * @param backend Name of the RrdBackendFactory that should be used for this RrdDb.
+ * @deprecated uses {@link #addDatasource(String, String, String, ConsolFun, RrdBackendFactory)} instead
+ */
+ @Deprecated
+ public void addDatasource(String name, String file, String dsName, ConsolFun consolFunc, String backend) {
+ Def def = new Def(name, file, dsName, consolFunc, RrdBackendFactory.getFactory(backend));
+ sources.put(name, def);
+ }
+
+ /**
+ * name
can be used:
+ *
+ *
+ * @param name Source name.
+ * @param file Path to RRD file.
+ * @param dsName Data source name defined in the RRD file.
+ * @param consolFunc Consolidation function that will be used to extract data from the RRD
+ * file ("AVERAGE", "MIN", "MAX" or "LAST" - these string constants are conveniently defined
+ * in the {@link org.rrd4j.ConsolFun ConsolFun} class).
+ * @param backend Name of the RrdBackendFactory that should be used for this RrdDb.
+ */
+ public void addDatasource(String name, String file, String dsName, ConsolFun consolFunc, RrdBackendFactory backend) {
+ Def def = new Def(name, file, dsName, consolFunc, backend);
+ sources.put(name, def);
+ }
+
+ /**
+ * Adds DEF datasource with datasource values already available in the FetchData object. This method is
+ * used internally by Rrd4j 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);
+ }
+
+ /**
+ * Adds DEF datasource with datasource values already available in the FetchData object. This method is
+ * used internally by Rrd4j and probably has no purpose outside of it.
+ * The values will be extracted from dsName in fetchData.
+ *
+ * @param name Source name.
+ * @param dsName Source name in the fetch data.
+ * @param fetchData Fetched data containing values for the given source name.
+ */
+ public void addDatasource(String name, String dsName, FetchData fetchData) {
+ Def def = new Def(name, dsName, 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.
+ *
+ * @throws java.io.IOException Thrown in case of I/O error (while fetching data from RRD files)
+ */
+ public void processData() throws IOException {
+ extractDefs();
+ fetchRrdData();
+ fixZeroEndingTimestamp();
+ chooseOptimalStep();
+ createTimestamps();
+ assignTimestampsToSources();
+ normalizeRrdValues();
+ calculateNonRrdSources();
+ }
+
+ /**
+ * Method used to calculate datasource values which should be presented on the graph
+ * based on the desired graph width. Each value returned represents a single pixel on the graph.
+ * Corresponding timestamp can be found in the array returned from {@link #getTimestampsPerPixel()}
+ * method.
+ *
+ * @param sourceName Datasource name
+ * @param pixelCount Graph width
+ * @return Per-pixel datasource values
+ * @throws java.lang.IllegalArgumentException Thrown if datasource values are not yet calculated (method {@link #processData()}
+ * was not called)
+ */
+ public double[] getValuesPerPixel(String sourceName, int pixelCount) {
+ setPixelCount(pixelCount);
+ return getValuesPerPixel(sourceName);
+ }
+
+ /**
+ * Method used to calculate datasource values which should be presented on the graph
+ * based on the graph width set with a {@link #setPixelCount(int)} method call.
+ * Each value returned represents a single pixel on the graph. Corresponding timestamp can be
+ * found in the array returned from {@link #getTimestampsPerPixel()} method.
+ *
+ * @param sourceName Datasource name
+ * @return Per-pixel datasource values
+ * @throws java.lang.IllegalArgumentException Thrown if datasource values are not yet calculated (method {@link #processData()}
+ * was not called)
+ */
+ public double[] getValuesPerPixel(String sourceName) {
+ double[] values = getValues(sourceName);
+ double[] pixelValues = new double[pixelCount];
+ Arrays.fill(pixelValues, Double.NaN);
+ long span = tEnd - tStart;
+ // this is the ugliest nested loop I have ever made
+ for (int pix = 0, ref = 0; pix < pixelCount; pix++) {
+ double t = tStart + (double) (span * pix) / (double) (pixelCount - 1);
+ while (ref < timestamps.length) {
+ if (t <= timestamps[ref] - step) {
+ // too left, nothing to do, already NaN
+ break;
+ }
+ else if (t <= timestamps[ref]) {
+ // in brackets, get this value
+ pixelValues[pix] = values[ref];
+ break;
+ }
+ else {
+ // too right
+ ref++;
+ }
+ }
+ }
+ return pixelValues;
+ }
+
+ /**
+ * Calculates timestamps which correspond to individual pixels on the graph.
+ *
+ * @param pixelCount Graph width
+ * @return Array of timestamps
+ */
+ public long[] getTimestampsPerPixel(int pixelCount) {
+ setPixelCount(pixelCount);
+ return getTimestampsPerPixel();
+ }
+
+ /**
+ * Calculates timestamps which correspond to individual pixels on the graph
+ * based on the graph width set with a {@link #setPixelCount(int)} method call.
+ *
+ * @return Array of timestamps
+ */
+ public long[] getTimestampsPerPixel() {
+ long[] times = new long[pixelCount];
+ long span = tEnd - tStart;
+ for (int i = 0; i < pixelCount; i++) {
+ times[i] = Math.round(tStart + (double) (span * i) / (double) (pixelCount - 1));
+ }
+ return times;
+ }
+
+ /**
+ * Dumps timestamps and values of all datasources in a tabular form. Very useful for debugging.
+ *
+ * @return Dumped object content.
+ */
+ public String dump() {
+ String[] names = getSourceNames();
+ double[][] values = getValues();
+ StringBuilder buffer = new StringBuilder();
+ buffer.append(format("timestamp", 12));
+ for (String name : names) {
+ buffer.append(format(name, 20));
+ }
+ buffer.append("\n");
+ for (int i = 0; i < timestamps.length; i++) {
+ buffer.append(format(Long.toString(timestamps[i]), 12));
+ for (int j = 0; j < names.length; j++) {
+ buffer.append(format(Util.formatDouble(values[j][i]), 20));
+ }
+ buffer.append("\n");
+ }
+ return buffer.toString();
+ }
+
+ /**
+ * Returns time when last RRD archive was updated (all RRD files are considered).
+ *
+ * @return Last archive update time for all RRD files in this DataProcessor
+ */
+ public long getLastRrdArchiveUpdateTime() {
+ return lastRrdArchiveUpdateTime;
+ }
+
+ // PRIVATE METHODS
+
+ private void extractDefs() {
+ List
+ * (t, 100)
and (t + 100, 300)
. Here are the results interpolator
+ * returns for t + 50 seconds, for various interpolationMethods
:
+ *
+ * INTERPOLATE_LEFT: 100
+ * INTERPOLATE_RIGHT: 300
+ * INTERPOLATE_LINEAR: 200
+ * INTERPOLATE_LINEAR
.INTERPOLATE_LEFT
,
+ * INTERPOLATE_RIGHT
, INTERPOLATE_LINEAR
or
+ * INTERPOLATE_REGRESSION
. Any other value will be interpreted as
+ * INTERPOLATE_LINEAR (default).
+ * @deprecated uses {@link #setInterpolationMethod(Method)} instead.
+ */
+ @Deprecated
+ public void setInterpolationMethod(int interpolationMethod) {
+ if (interpolationMethod >= Method.values().length || interpolationMethod < 0) {
+ setInterpolationMethod(Method.LINEAR);
+ } else {
+ setInterpolationMethod(Method.values()[interpolationMethod]);
+ }
+ }
+
+ /**
+ *
+ * (t, 100)
and (t + 100, 300)
. Here are the results interpolator
+ * returns for t + 50 seconds, for various interpolationMethods
:
+ *
+ * LEFT: 100
+ * RIGHT: 300
+ * LINEAR: 200
+ * INTERPOLATE_LINEAR
.
+ * setTimeAxis(RrdGraphConstants.MINUTE, 10,
+ * RrdGraphConstants.HOUR, 1,
+ * RrdGraphConstants.HOUR, 1,
+ * 0, "%H:%M")
+ *
+ *
+ *
+ * setImageInfo("<IMG SRC='/img/%s' WIDTH='%d' HEIGHT='%d' ALT='Demo'>");
+ *
+ *
+ * @param imageInfo Image info format. Use %s placeholder for filename, %d placeholder for
+ * image width and height.
+ */
+ public void setImageInfo(String imageInfo) {
+ this.imageInfo = imageInfo;
+ }
+
+ /**
+ * Sets image format.
+ *
+ * @param imageFormat Any value as return by {@link javax.imageio.ImageIO#getReaderFormatNames}
+ */
+ public void setImageFormat(String imageFormat) {
+ this.imageFormat = imageFormat;
+ }
+
+ /**
+ * Sets background image - currently, only PNG images can be used as background.
+ *
+ * @param backgroundImage Path to background image
+ */
+ public void setBackgroundImage(String backgroundImage) {
+ this.backgroundImage = backgroundImage;
+ }
+
+ /**
+ * Sets overlay image - currently, only PNG images can be used as overlay. Overlay image is
+ * printed on the top of the image, once it is completely created.
+ *
+ * @param overlayImage Path to overlay image
+ */
+ public void setOverlayImage(String overlayImage) {
+ this.overlayImage = overlayImage;
+ }
+
+ /**
+ * Sets unit to be displayed on y axis. It is wise to use only short units on graph, however.
+ *
+ * @param unit Unit description
+ */
+ public void setUnit(String unit) {
+ this.unit = unit;
+ }
+
+ /**
+ * Creates graph only if the current graph is out of date or not existent.
+ *
+ * @param lazy true, if graph should be 'lazy', false otherwise (default)
+ */
+ public void setLazy(boolean lazy) {
+ this.lazy = lazy;
+ }
+
+ /**
+ * Sets the lower limit of a graph. But rather, this is the
+ * maximum lower bound of a graph. For example, the value -100 will
+ * result in a graph that has a lower limit of -100 or less. Use this
+ * method to expand graphs down.
+ *
+ * @param minValue Minimal value displayed on the graph
+ */
+ public void setMinValue(double minValue) {
+ this.minValue = minValue;
+ }
+
+ /**
+ * true
argument you can disable this behavior.
+ *
+ * @param rigid true if upper and lower limits should not be expanded to accommodate
+ * values outside of the specified range. False otherwise (default).
+ */
+ public void setRigid(boolean rigid) {
+ this.rigid = rigid;
+ }
+
+ /**
+ * Sets default base for magnitude scaling. If you are graphing memory
+ * (and NOT network traffic) this switch should be set to 1024 so that 1Kb is 1024 byte.
+ * For traffic measurement, 1 kb/s is 1000 b/s.
+ *
+ * @param base Base value (defaults to 1000.0)
+ */
+ public void setBase(double base) {
+ this.base = base;
+ }
+
+ /**
+ * Sets logarithmic y-axis scaling.
+ *
+ * @param logarithmic true, for logarithmic scaling, false otherwise (default).
+ */
+ public void setLogarithmic(boolean logarithmic) {
+ this.logarithmic = logarithmic;
+ }
+
+ /**
+ * Overrides the colors for the standard elements of the graph. The
+ * colorTag must be one of the following constants defined in the {@link org.rrd4j.graph.RrdGraphConstants}:
+ * {@link org.rrd4j.graph.RrdGraphConstants#COLOR_BACK COLOR_BACK}ground,
+ * {@link org.rrd4j.graph.RrdGraphConstants#COLOR_CANVAS COLOR_CANVAS},
+ * {@link org.rrd4j.graph.RrdGraphConstants#COLOR_XAXIS COLOR_XAXIS},
+ * {@link org.rrd4j.graph.RrdGraphConstants#COLOR_SHADEA COLOR_SHADEA} left/top border,
+ * {@link org.rrd4j.graph.RrdGraphConstants#COLOR_SHADEB COLOR_SHADEB} right/bottom border,
+ * {@link org.rrd4j.graph.RrdGraphConstants#COLOR_GRID COLOR_GRID},
+ * {@link org.rrd4j.graph.RrdGraphConstants#COLOR_MGRID COLOR_MGRID} major grid,
+ * {@link org.rrd4j.graph.RrdGraphConstants#COLOR_FONT COLOR_FONT},
+ * {@link org.rrd4j.graph.RrdGraphConstants#COLOR_FRAME COLOR_FRAME} and axis of the graph or
+ * {@link org.rrd4j.graph.RrdGraphConstants#COLOR_ARROW COLOR_ARROW}. This
+ * method can be called multiple times to set several colors.
+ *
+ * @param colorTag Color tag, as explained above.
+ * @param color Any color (paint) you like
+ * @deprecated Using {@link #setColor(ElementsNames, Paint)}
+ */
+ @Deprecated
+ public void setColor(int colorTag, Paint color) {
+ if (colorTag >= 0 && colorTag < colors.length) {
+ colors[colorTag] = color;
+ } else {
+ throw new IllegalArgumentException("Invalid color index specified: " + colorTag);
+ }
+ }
+
+ /**
+ * Overrides the colors for the standard elements of the graph.
+ * @param colorTag
+ * @param color
+ */
+ public void setColor(ElementsNames colorTag, Paint color) {
+ colors[colorTag.ordinal()] = color;
+ }
+
+ /**
+ * Overrides the colors for the standard elements of the graph by element name.
+ * See {@link #setColor(int, java.awt.Paint)} for full explanation.
+ *
+ * @param colorName One of the following strings: "BACK", "CANVAS", "SHADEA", "SHADEB",
+ * "GRID", "MGRID", "FONT", "FRAME", "ARROW", "XAXIS", "YAXIS"
+ * @param color Any color (paint) you like
+ * @deprecated Using {@link #setColor(ElementsNames, Paint)}
+ */
+ @Deprecated
+ public void setColor(String colorName, Paint color) {
+ setColor(ElementsNames.valueOf(colorName.toLowerCase(Locale.ENGLISH)).ordinal(), color);
+ }
+
+ /**
+ * Suppress generation of legend, only render the graph.
+ *
+ * @param noLegend true if graph legend should be omitted. False otherwise (default).
+ */
+ public void setNoLegend(boolean noLegend) {
+ this.noLegend = noLegend;
+ }
+
+ /**
+ * Suppresses anything but the graph, works only for height < 64.
+ *
+ * @param onlyGraph true if only graph should be created, false otherwise (default).
+ */
+ public void setOnlyGraph(boolean onlyGraph) {
+ this.onlyGraph = onlyGraph;
+ }
+
+ /**
+ * Force the generation of HRULE and VRULE legend even if those HRULE
+ * or VRULE will not be drawn because out of graph boundaries.
+ *
+ * @param forceRulesLegend true if rule legend should be always printed,
+ * false otherwise (default).
+ */
+ public void setForceRulesLegend(boolean forceRulesLegend) {
+ this.forceRulesLegend = forceRulesLegend;
+ }
+
+ /**
+ * Defines a title to be written into the graph.
+ *
+ * @param title Graph title.
+ */
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ /**
+ * Suggests which time step should be used by Rrd4j while processing data from RRD files.
+ *
+ * @param step Desired time step (don't use this method if you don't know what you're doing).
+ */
+ public void setStep(long step) {
+ this.step = step;
+ }
+
+ /**
+ * This method reset the font set to it's default values. With the flag rrdtool set to true, it's not the old
+ * default set that is used, but the one taken from rrdtool. So use false to keep compatibility with previous version
+ * and true for a graph matching rrdtool's
+ *
+ * @param rrdtool true to use rrdtool font set
+ */
+ public void setFontSet(boolean rrdtool) {
+ if(rrdtool) {
+ // We add a factor to the font size, rrdtool and java don't agree about font size
+ float rrdtoolfactor = 12f/9;
+ fonts = new Font[] {
+ DEFAULT_SMALL_FONT.deriveFont(8.0f * rrdtoolfactor), // FONTTAG_DEFAULT
+ DEFAULT_SMALL_FONT.deriveFont(9.0f * rrdtoolfactor), // FONTTAG_TITLE
+ DEFAULT_SMALL_FONT.deriveFont(7.0f * rrdtoolfactor), // FONTTAG_AXIS
+ DEFAULT_SMALL_FONT.deriveFont(8.0f * rrdtoolfactor), // FONTTAG_UNIT
+ DEFAULT_SMALL_FONT.deriveFont(8.0f * rrdtoolfactor), // FONTTAG_LEGEND
+ DEFAULT_SMALL_FONT.deriveFont(5.5f * rrdtoolfactor) // FONTTAG_WATERMARK
+ };
+ } else {
+ fonts = new Font[] {
+ DEFAULT_SMALL_FONT, // FONTTAG_DEFAULT
+ DEFAULT_LARGE_FONT, // FONTTAG_TITLE
+ DEFAULT_SMALL_FONT, // FONTTAG_AXIS
+ DEFAULT_SMALL_FONT, // FONTTAG_UNIT
+ DEFAULT_SMALL_FONT, // FONTTAG_LEGEND
+ GATOR_FONT // FONTTAG_WATERMARK
+ };
+ }
+ }
+
+ /**
+ * Sets default font for graphing. Note that Rrd4j will behave unpredictably if proportional
+ * font is selected.
+ *
+ * @param smallFont Default font for graphing. Use only monospaced fonts.
+ * @deprecated Use {@link Variable} based method instead.
+ */
+ @Deprecated
+ public void setSmallFont(final Font smallFont) {
+ this.setFont(FontTag.DEFAULT, smallFont);
+ }
+
+ /**
+ * Sets title font.
+ *
+ * @param largeFont Font to be used for graph title.
+ * @deprecated Use {@link Variable} based method instead.
+ */
+ @Deprecated
+ public void setLargeFont(final Font largeFont) {
+ this.setFont(FontTag.TITLE, largeFont);
+ }
+
+ /**
+ * Sets font to be used for a specific font tag. The fontTag
+ * must be one of the following constants defined in the
+ * {@link RrdGraphConstants}:
+ * {@link RrdGraphConstants#FONTTAG_DEFAULT FONTTAG_DEFAULT} default font,,
+ * {@link RrdGraphConstants#FONTTAG_TITLE FONTTAG_TITLE} title,
+ * {@link RrdGraphConstants#FONTTAG_AXIS FONTTAG_AXIS} grid axis,,
+ * {@link RrdGraphConstants#FONTTAG_UNIT FONTTAG_UNIT} vertical unit label,,
+ * {@link RrdGraphConstants#FONTTAG_LEGEND FONTTAG_LEGEND} legend,
+ * {@link RrdGraphConstants#FONTTAG_WATERMARK FONTTAG_WATERMARK} watermark.
+ * This method can be called multiple times to set several fonts.
+ *
+ * @param fontTag Font tag, as explained above.
+ * @param font Font to be used for tag
+ */
+ public void setFont(final FontTag fontTag, final Font font) {
+ this.setFont(fontTag, font, false);
+ }
+
+ /**
+ * Sets font.
+ *
+ * @param fontTag Font tag, as explained above.
+ * @param font Font to be used for tag
+ * @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
+ */
+ public void setFont(final FontTag fontTag, final Font font, final boolean setAll) {
+ this.setFont(fontTag, font, setAll, false);
+ }
+
+ /**
+ * Sets font.
+ *
+ * @param fontTag Font tag, as explained above.
+ * @param font Font to be used for tag
+ * @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
+ * @param keepSizes Boolean to flag whether to keep original font sizes if setting all fonts.
+ */
+ public void setFont(final FontTag fontTag, final Font font, final boolean setAll, final boolean keepSizes) {
+ if (fontTag == FontTag.DEFAULT && setAll) {
+ if (keepSizes) {
+ this.fonts[FONTTAG_DEFAULT.ordinal()] = font.deriveFont(this.fonts[FONTTAG_DEFAULT.ordinal()].getSize());
+ this.fonts[FONTTAG_TITLE.ordinal()] = font.deriveFont(this.fonts[FONTTAG_TITLE.ordinal()].getSize());
+ this.fonts[FONTTAG_AXIS.ordinal()] = font.deriveFont(this.fonts[FONTTAG_AXIS.ordinal()].getSize());
+ this.fonts[FONTTAG_UNIT.ordinal()] = font.deriveFont(this.fonts[FONTTAG_UNIT.ordinal()].getSize());
+ this.fonts[FONTTAG_LEGEND.ordinal()] = font.deriveFont(this.fonts[FONTTAG_LEGEND.ordinal()].getSize());
+ this.fonts[FONTTAG_WATERMARK.ordinal()] = font.deriveFont(this.fonts[FONTTAG_WATERMARK.ordinal()].getSize());
+ }
+ else {
+ this.fonts[FONTTAG_DEFAULT.ordinal()] = font;
+ this.fonts[FONTTAG_TITLE.ordinal()] = null;
+ this.fonts[FONTTAG_AXIS.ordinal()] = null;
+ this.fonts[FONTTAG_UNIT.ordinal()] = null;
+ this.fonts[FONTTAG_LEGEND.ordinal()] = null;
+ this.fonts[FONTTAG_WATERMARK.ordinal()] = null;
+ }
+ } else {
+ this.fonts[fontTag.ordinal()] = font;
+ }
+ }
+
+ /**
+ * Sets font.
+ *
+ * @param fontTag Font tag as String, as explained in {@link #setFont(org.rrd4j.graph.RrdGraphConstants.FontTag, Font, boolean)}.
+ * @param font Font to be used for tag
+ */
+ public void setFont(final String fontTag, final Font font) {
+ this.setFont(FontTag.valueOf(fontTag), font);
+ }
+
+ /**
+ * Sets font.
+ *
+ * @param fontTag Font tag as String, as explained in {@link #setFont(org.rrd4j.graph.RrdGraphConstants.FontTag, Font, boolean)}.
+ * @param font Font to be used for tag
+ * @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
+ */
+ public void setFont(final String fontTag, final Font font, final boolean setAll) {
+ this.setFont(FontTag.valueOf(fontTag), font, setAll);
+ }
+
+ /**
+ * Sets font.
+ *
+ * @param fontTag Font tag as String, as explained in {@link #setFont(org.rrd4j.graph.RrdGraphConstants.FontTag, Font, boolean)}.
+ * @param font Font to be used for tag
+ * @param setAll Boolean to flag whether to set all fonts if fontTag == FONTTAG_DEFAULT
+ * @param keepSizes Boolean to flag whether to keep original font sizes if setting all fonts.
+ */
+ public void setFont(final String fontTag, final Font font, final boolean setAll, final boolean keepSizes) {
+ this.setFont(FontTag.valueOf(fontTag), font, setAll, keepSizes);
+ }
+
+ public Font getFont(final FontTag tag) {
+ return this.fonts[tag.ordinal()] == null ? this.fonts[FONTTAG_DEFAULT.ordinal()] : this.fonts[tag.ordinal()];
+ }
+
+
+ /**
+ * Defines virtual datasource. This datasource can then be used
+ * in other methods like {@link #datasource(String, String)} or
+ * {@link #gprint(String, ConsolFun, String)}.
+ *
+ * @param name Source name
+ * @param rrdPath Path to RRD file
+ * @param dsName Datasource name in the specified RRD file
+ * @param consolFun Consolidation function (AVERAGE, MIN, MAX, LAST)
+ */
+ public void datasource(String name, String rrdPath, String dsName, ConsolFun consolFun) {
+ sources.add(new Def(name, rrdPath, dsName, consolFun));
+ }
+
+ /**
+ * Defines virtual datasource. This datasource can then be used
+ * in other methods like {@link #datasource(String, String)} or
+ * {@link #gprint(String, ConsolFun, String)}.
+ *
+ * @param name Source name
+ * @param rrdPath Path to RRD file
+ * @param dsName Datasource name in the specified RRD file
+ * @param consolFun Consolidation function (AVERAGE, MIN, MAX, LAST)
+ * @param backend Backend to be used while fetching data from a RRD file.
+ *
+ * @deprecated Uses {@link #datasource(String, String, String, ConsolFun, RrdBackendFactory)} instead
+ */
+ @Deprecated
+ public void datasource(String name, String rrdPath, String dsName, ConsolFun consolFun, String backend) {
+ sources.add(new Def(name, rrdPath, dsName, consolFun, RrdBackendFactory.getFactory(backend)));
+ }
+
+ /**
+ * Defines virtual datasource. This datasource can then be used
+ * in other methods like {@link #datasource(String, String)} or
+ * {@link #gprint(String, ConsolFun, String)}.
+ *
+ * @param name Source name
+ * @param rrdPath Path to RRD file
+ * @param dsName Datasource name in the specified RRD file
+ * @param consolFun Consolidation function (AVERAGE, MIN, MAX, LAST)
+ * @param backend Backend to be used while fetching data from a RRD file.
+ */
+ public void datasource(String name, String rrdPath, String dsName, ConsolFun consolFun, RrdBackendFactory backend) {
+ sources.add(new Def(name, rrdPath, dsName, consolFun, backend));
+ }
+
+ /**
+ * Create a new virtual datasource by evaluating a mathematical
+ * expression, specified in Reverse Polish Notation (RPN).
+ *
+ * @param name Source name
+ * @param rpnExpression RPN expression.
+ */
+ public void datasource(String name, String rpnExpression) {
+ sources.add(new CDef(name, rpnExpression));
+ }
+
+ /**
+ * Creates a new (static) virtual datasource. The value of the datasource is constant. This value is
+ * evaluated by applying the given consolidation function to another virtual datasource.
+ *
+ * @param name Source name
+ * @param defName Other source name
+ * @param consolFun Consolidation function to be applied to other datasource.
+ * @deprecated Use {@link Variable} based method instead.
+ */
+ @Deprecated
+ public void datasource(String name, String defName, ConsolFun consolFun) {
+ datasource(name, defName, consolFun.getVariable());
+ }
+
+ public void datasource(String name, String defName, Variable var) {
+ sources.add(new VDef(name, defName, var));
+ }
+
+ /**
+ * Creates a new (plottable) datasource. Datasource values are obtained from the given plottable
+ * object.
+ *
+ * @param name Source name.
+ * @param plottable Plottable object.
+ */
+ public void datasource(String name, Plottable plottable) {
+ sources.add(new PDef(name, plottable));
+ }
+
+ /**
+ * Creates a new 'fetched' datasource. Datasource values are obtained from the
+ * given {@link org.rrd4j.core.FetchData} object.
+ *
+ * @param name Source name.
+ * @param fetchData FetchData object.
+ */
+ public void datasource(String name, FetchData fetchData) {
+ sources.add(new TDef(name, name, fetchData));
+ }
+
+ /**
+ * Creates a new 'fetched' datasource. Datasource values are obtained from the
+ * given {@link org.rrd4j.core.FetchData} object.
+ * Values will be extracted from the datasource dsName in the fetchData
+ *
+ * @param name Source name.
+ * @param dsName Source name in fetchData.
+ * @param fetchData FetchData object.
+ */
+ public void datasource(String name, String dsName, FetchData fetchData) {
+ sources.add(new TDef(name, dsName, fetchData));
+ }
+
+ /**
+ * Create a new virtual datasource to get the 95th percentile value from another datasource
+ *
+ * @param name Source name.
+ * @param defName Other source name.
+ * @deprecated Use {@link Variable} based method instead.
+ */
+ @Deprecated
+ public void percentile(String name, String defName) {
+ percentile(name, defName, DataProcessor.DEFAULT_PERCENTILE);
+ }
+
+ /**
+ * Create a new virtual datasource to get a percentile value from another datasource
+ *
+ * @param name Source name.
+ * @param defName Other source name.
+ * @param percent The percent value.
+ * @deprecated Use {@link Variable} based method instead.
+ */
+ @Deprecated
+ public void percentile(String name, String defName, double percent) {
+ datasource(name, defName, new Variable.PERCENTILE(percent));
+ }
+
+ /**
+ *
+ *
+ */
+public class SimpleTimeLabelFormat implements TimeLabelFormat {
+
+ private final String format;
+
+ /**
+ * Create a new instance using a format string that is either an strftime patter or a simple
+ * date format pattern.
+ *
+ * @param format
+ */
+ public SimpleTimeLabelFormat(String format) {
+ // escape strftime like format string
+ this.format = format.replaceAll("%([^%])", "%1\\$t$1");
+ }
+
+ @Override
+ public String format(Calendar calendar, Locale locale) {
+ if (format.contains("%")) {
+ // strftime like format string
+ return String.format(locale, format, calendar);
+ } else {
+ SimpleDateFormat sdf = new SimpleDateFormat(format);
+ sdf.setCalendar(calendar);
+ return sdf.format(calendar.getTime());
+ }
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/Source.java b/apps/jrobin/java/src/org/rrd4j/graph/Source.java
new file mode 100644
index 0000000000..430ea314cf
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/Source.java
@@ -0,0 +1,13 @@
+package org.rrd4j.graph;
+
+import org.rrd4j.data.DataProcessor;
+
+abstract class Source {
+ final String name;
+
+ Source(String name) {
+ this.name = name;
+ }
+
+ abstract void requestData(DataProcessor dproc);
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/SourcedPlotElement.java b/apps/jrobin/java/src/org/rrd4j/graph/SourcedPlotElement.java
new file mode 100644
index 0000000000..bd00c735b9
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/SourcedPlotElement.java
@@ -0,0 +1,67 @@
+package org.rrd4j.graph;
+
+import org.rrd4j.core.Util;
+import org.rrd4j.data.DataProcessor;
+
+import java.awt.*;
+
+class SourcedPlotElement extends PlotElement {
+ final String srcName;
+ final SourcedPlotElement parent;
+ double[] values;
+
+ SourcedPlotElement(String srcName, Paint color) {
+ super(color);
+ this.srcName = srcName;
+ this.parent = null;
+ }
+
+ SourcedPlotElement(String srcName, Paint color, SourcedPlotElement parent) {
+ super(color);
+ this.srcName = srcName;
+ this.parent = parent;
+ }
+
+ void assignValues(DataProcessor dproc) {
+ if(parent == null) {
+ values = dproc.getValues(srcName);
+ }
+ else {
+ values = stackValues(dproc);
+ }
+ }
+
+ double[] stackValues(DataProcessor dproc) {
+ double[] parentValues = parent.getValues();
+ double[] procValues = dproc.getValues(srcName);
+ double[] stacked = new double[procValues.length];
+ for (int i = 0; i < stacked.length; i++) {
+ if (Double.isNaN(parentValues[i])) {
+ stacked[i] = procValues[i];
+ }
+ else if (Double.isNaN(procValues[i])){
+ stacked[i] = parentValues[i];
+ }
+ else {
+ stacked[i] = parentValues[i] + procValues[i];
+ }
+ }
+ return stacked;
+ }
+
+ Paint getParentColor() {
+ return parent != null ? parent.color : null;
+ }
+
+ double[] getValues() {
+ return values;
+ }
+
+ double getMinValue() {
+ return Util.min(values);
+ }
+
+ double getMaxValue() {
+ return Util.max(values);
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/Span.java b/apps/jrobin/java/src/org/rrd4j/graph/Span.java
new file mode 100644
index 0000000000..7d7ec1c7d7
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/Span.java
@@ -0,0 +1,12 @@
+package org.rrd4j.graph;
+
+import java.awt.*;
+
+class Span extends PlotElement {
+ final LegendText legend;
+
+ Span(Paint color, LegendText legend) {
+ super(color);
+ this.legend = legend;
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/Stack.java b/apps/jrobin/java/src/org/rrd4j/graph/Stack.java
new file mode 100644
index 0000000000..9ab42e6df5
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/Stack.java
@@ -0,0 +1,46 @@
+package org.rrd4j.graph;
+
+import org.rrd4j.data.DataProcessor;
+
+import java.awt.*;
+
+class Stack extends SourcedPlotElement {
+
+ Stack(SourcedPlotElement parent, String srcName, Paint color) {
+ super(srcName, color, parent);
+ }
+
+ void assignValues(DataProcessor dproc) {
+ double[] parentValues = parent.getValues();
+ double[] procValues = dproc.getValues(srcName);
+ values = new double[procValues.length];
+ for (int i = 0; i < values.length; i++) {
+ if (Double.isNaN(parentValues[i])) {
+ values[i] = procValues[i];
+ }
+ else if (Double.isNaN(procValues[i])){
+ values[i] = parentValues[i];
+ }
+ else {
+ values[i] = parentValues[i] + procValues[i];
+
+ }
+ }
+ }
+
+ float getParentLineWidth() {
+ if (parent instanceof Line) {
+ return ((Line) parent).stroke.getLineWidth();
+ }
+ else if (parent instanceof Area) {
+ return -1F;
+ }
+ else /* if(parent instanceof Stack) */ {
+ return ((Stack) parent).getParentLineWidth();
+ }
+ }
+
+ Paint getParentColor() {
+ return parent.color;
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/TDef.java b/apps/jrobin/java/src/org/rrd4j/graph/TDef.java
new file mode 100644
index 0000000000..dcddb8694d
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/TDef.java
@@ -0,0 +1,22 @@
+package org.rrd4j.graph;
+
+import org.rrd4j.core.FetchData;
+import org.rrd4j.data.DataProcessor;
+
+/** @author Mathias Bogaert */
+class TDef extends Source {
+ private final FetchData fetchData;
+ private final String dsName;
+
+ TDef(String name, String dsName, FetchData fetchData) {
+ super(name);
+ this.dsName = dsName;
+ this.fetchData = fetchData;
+ }
+
+ @Override
+ void requestData(DataProcessor dproc) {
+ dproc.addDatasource(name, dsName, fetchData);
+ }
+
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/TimeAxis.java b/apps/jrobin/java/src/org/rrd4j/graph/TimeAxis.java
new file mode 100644
index 0000000000..2f6068c5d2
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/TimeAxis.java
@@ -0,0 +1,211 @@
+package org.rrd4j.graph;
+
+import java.awt.Font;
+import java.awt.Paint;
+import java.util.Calendar;
+import java.util.Date;
+
+class TimeAxis extends Axis {
+ private static final TimeAxisSetting[] tickSettings = {
+ new TimeAxisSetting(0, SECOND, 30, MINUTE, 5, MINUTE, 5, 0, HH_MM),
+ new TimeAxisSetting(2, MINUTE, 1, MINUTE, 5, MINUTE, 5, 0, HH_MM),
+ new TimeAxisSetting(5, MINUTE, 2, MINUTE, 10, MINUTE, 10, 0, HH_MM),
+ new TimeAxisSetting(10, MINUTE, 5, MINUTE, 20, MINUTE, 20, 0, HH_MM),
+ new TimeAxisSetting(30, MINUTE, 10, HOUR, 1, HOUR, 1, 0, HH_MM),
+ new TimeAxisSetting(60, MINUTE, 30, HOUR, 2, HOUR, 2, 0, HH_MM),
+ new TimeAxisSetting(180, HOUR, 1, HOUR, 6, HOUR, 6, 0, HH_MM),
+ new TimeAxisSetting(600, HOUR, 6, DAY, 1, DAY, 1, 24 * 3600, "EEE"),
+ new TimeAxisSetting(1800, HOUR, 12, DAY, 1, DAY, 2, 24 * 3600, "EEE"),
+ new TimeAxisSetting(3600, DAY, 1, WEEK, 1, WEEK, 1, 7 * 24 * 3600, "'Week 'w"),
+ new TimeAxisSetting(3 * 3600L, WEEK, 1, MONTH, 1, WEEK, 2, 7 * 24 * 3600, "'Week 'w"),
+ new TimeAxisSetting(6 * 3600L, MONTH, 1, MONTH, 1, MONTH, 1, 30 * 24 * 3600, "MMM"),
+ new TimeAxisSetting(48 * 3600L, MONTH, 1, MONTH, 3, MONTH, 3, 30 * 24 * 3600, "MMM"),
+ new TimeAxisSetting(10 * 24 * 3600L, YEAR, 1, YEAR, 1, YEAR, 1, 365 * 24 * 3600, "yy"),
+ new TimeAxisSetting(-1, MONTH, 0, MONTH, 0, MONTH, 0, 0, "")
+ };
+
+ private final ImageParameters im;
+ private final ImageWorker worker;
+ private final RrdGraphDef gdef;
+ private final Mapper mapper;
+ private TimeAxisSetting tickSetting;
+
+ private final double secPerPix;
+ private final Calendar calendar;
+
+ TimeAxis(RrdGraph rrdGraph) {
+ this(rrdGraph, rrdGraph.worker);
+ }
+
+ /**
+ * Used for test
+ */
+ TimeAxis(RrdGraph rrdGraph, ImageWorker worker) {
+ this.im = rrdGraph.im;
+ this.worker = worker;
+ this.gdef = rrdGraph.gdef;
+ this.mapper = rrdGraph.mapper;
+ this.secPerPix = (im.end - im.start) / (double) im.xsize;
+ this.calendar = Calendar.getInstance(gdef.tz, gdef.locale);
+ this.calendar.setFirstDayOfWeek(gdef.firstDayOfWeek);
+ }
+
+ boolean draw() {
+ chooseTickSettings();
+ // early return, avoid exceptions
+ if (tickSetting == null) {
+ return false;
+ }
+
+ drawMinor();
+ drawMajor();
+ drawLabels();
+
+ return true;
+ }
+
+ private void drawMinor() {
+ if (!gdef.noMinorGrid) {
+ adjustStartingTime(tickSetting.minorUnit, tickSetting.minorUnitCount);
+ Paint color = gdef.getColor(ElementsNames.grid);
+ int y0 = im.yorigin, y1 = y0 - im.ysize;
+ for (int status = getTimeShift(); status <= 0; status = getTimeShift()) {
+ if (status == 0) {
+ long time = calendar.getTime().getTime() / 1000L;
+ int x = mapper.xtr(time);
+ worker.drawLine(x, y0 - 1, x, y0 + 1, color, gdef.tickStroke);
+ worker.drawLine(x, y0, x, y1, color, gdef.gridStroke);
+ }
+ findNextTime(tickSetting.minorUnit, tickSetting.minorUnitCount);
+ }
+ }
+ }
+
+ private void drawMajor() {
+ adjustStartingTime(tickSetting.majorUnit, tickSetting.majorUnitCount);
+ Paint color = gdef.getColor(ElementsNames.mgrid);
+ int y0 = im.yorigin, y1 = y0 - im.ysize;
+ for (int status = getTimeShift(); status <= 0; status = getTimeShift()) {
+ if (status == 0) {
+ long time = calendar.getTime().getTime() / 1000L;
+ int x = mapper.xtr(time);
+ worker.drawLine(x, y0 - 2, x, y0 + 2, color, gdef.tickStroke);
+ worker.drawLine(x, y0, x, y1, color, gdef.gridStroke);
+ }
+ findNextTime(tickSetting.majorUnit, tickSetting.majorUnitCount);
+ }
+ }
+
+ private void drawLabels() {
+ Font font = gdef.getFont(FONTTAG_AXIS);
+ Paint color = gdef.getColor(ElementsNames.font);
+ adjustStartingTime(tickSetting.labelUnit, tickSetting.labelUnitCount);
+ int y = im.yorigin + (int) worker.getFontHeight(font) + 2;
+ for (int status = getTimeShift(); status <= 0; status = getTimeShift()) {
+ String label = tickSetting.format.format(calendar, gdef.locale);
+ long time = calendar.getTime().getTime() / 1000L;
+ int x1 = mapper.xtr(time);
+ int x2 = mapper.xtr(time + tickSetting.labelSpan);
+ int labelWidth = (int) worker.getStringWidth(label, font);
+ int x = x1 + (x2 - x1 - labelWidth) / 2;
+ if (x >= im.xorigin && x + labelWidth <= im.xorigin + im.xsize) {
+ worker.drawString(label, x, y, font, color);
+ }
+ findNextTime(tickSetting.labelUnit, tickSetting.labelUnitCount);
+ }
+ }
+
+ private void findNextTime(int timeUnit, int timeUnitCount) {
+ switch (timeUnit) {
+ case SECOND:
+ calendar.add(Calendar.SECOND, timeUnitCount);
+ break;
+ case MINUTE:
+ calendar.add(Calendar.MINUTE, timeUnitCount);
+ break;
+ case HOUR:
+ calendar.add(Calendar.HOUR_OF_DAY, timeUnitCount);
+ break;
+ case DAY:
+ calendar.add(Calendar.DAY_OF_MONTH, timeUnitCount);
+ break;
+ case WEEK:
+ calendar.add(Calendar.DAY_OF_MONTH, 7 * timeUnitCount);
+ break;
+ case MONTH:
+ calendar.add(Calendar.MONTH, timeUnitCount);
+ break;
+ case YEAR:
+ calendar.add(Calendar.YEAR, timeUnitCount);
+ break;
+ }
+ }
+
+ private int getTimeShift() {
+ long time = calendar.getTime().getTime() / 1000L;
+ return (time < im.start) ? -1 : (time > im.end) ? +1 : 0;
+ }
+
+ private void adjustStartingTime(int timeUnit, int timeUnitCount) {
+ calendar.setTime(new Date(im.start * 1000L));
+ switch (timeUnit) {
+ case SECOND:
+ calendar.add(Calendar.SECOND, -(calendar.get(Calendar.SECOND) % timeUnitCount));
+ break;
+ case MINUTE:
+ calendar.set(Calendar.SECOND, 0);
+ calendar.add(Calendar.MINUTE, -(calendar.get(Calendar.MINUTE) % timeUnitCount));
+ break;
+ case HOUR:
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.add(Calendar.HOUR_OF_DAY, -(calendar.get(Calendar.HOUR_OF_DAY) % timeUnitCount));
+ break;
+ case DAY:
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ break;
+ case WEEK:
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ int diffDays = calendar.get(Calendar.DAY_OF_WEEK) - calendar.getFirstDayOfWeek();
+ if (diffDays < 0) {
+ diffDays += 7;
+ }
+ calendar.add(Calendar.DAY_OF_MONTH, -diffDays);
+ break;
+ case MONTH:
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ calendar.set(Calendar.DAY_OF_MONTH, 1);
+ calendar.add(Calendar.MONTH, -(calendar.get(Calendar.MONTH) % timeUnitCount));
+ break;
+ case YEAR:
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ calendar.set(Calendar.DAY_OF_MONTH, 1);
+ calendar.set(Calendar.MONTH, 0);
+ calendar.add(Calendar.YEAR, -(calendar.get(Calendar.YEAR) % timeUnitCount));
+ break;
+ }
+ }
+
+ private void chooseTickSettings() {
+ if (gdef.timeAxisSetting != null) {
+ tickSetting = new TimeAxisSetting(gdef.timeAxisSetting);
+ }
+ else {
+ for (int i = 0; tickSettings[i].secPerPix >= 0 && secPerPix > tickSettings[i].secPerPix; i++) {
+ tickSetting = tickSettings[i];
+ }
+ }
+ if (gdef.timeLabelFormat != null) {
+ tickSetting = tickSetting.withLabelFormat(gdef.timeLabelFormat);
+ }
+ }
+
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/TimeAxisSetting.java b/apps/jrobin/java/src/org/rrd4j/graph/TimeAxisSetting.java
new file mode 100644
index 0000000000..0fb1cc3f56
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/TimeAxisSetting.java
@@ -0,0 +1,57 @@
+package org.rrd4j.graph;
+
+class TimeAxisSetting {
+ final long secPerPix;
+ final int minorUnit, minorUnitCount, majorUnit, majorUnitCount;
+ final int labelUnit, labelUnitCount, labelSpan;
+ final TimeLabelFormat format;
+
+ TimeAxisSetting(long secPerPix, int minorUnit, int minorUnitCount, int majorUnit, int majorUnitCount,
+ int labelUnit, int labelUnitCount, int labelSpan, TimeLabelFormat format) {
+ this.secPerPix = secPerPix;
+ this.minorUnit = minorUnit;
+ this.minorUnitCount = minorUnitCount;
+ this.majorUnit = majorUnit;
+ this.majorUnitCount = majorUnitCount;
+ this.labelUnit = labelUnit;
+ this.labelUnitCount = labelUnitCount;
+ this.labelSpan = labelSpan;
+ this.format = format;
+ }
+
+ TimeAxisSetting(TimeAxisSetting s) {
+ this.secPerPix = s.secPerPix;
+ this.minorUnit = s.minorUnit;
+ this.minorUnitCount = s.minorUnitCount;
+ this.majorUnit = s.majorUnit;
+ this.majorUnitCount = s.majorUnitCount;
+ this.labelUnit = s.labelUnit;
+ this.labelUnitCount = s.labelUnitCount;
+ this.labelSpan = s.labelSpan;
+ this.format = s.format;
+ }
+
+ TimeAxisSetting(int minorUnit, int minorUnitCount, int majorUnit, int majorUnitCount,
+ int labelUnit, int labelUnitCount, int labelSpan, TimeLabelFormat format) {
+ this(0, minorUnit, minorUnitCount, majorUnit, majorUnitCount,
+ labelUnit, labelUnitCount, labelSpan, format);
+ }
+
+ TimeAxisSetting(long secPerPix, int minorUnit, int minorUnitCount, int majorUnit, int majorUnitCount,
+ int labelUnit, int labelUnitCount, int labelSpan, String format) {
+ this(secPerPix, minorUnit, minorUnitCount, majorUnit, majorUnitCount,
+ labelUnit, labelUnitCount, labelSpan, new SimpleTimeLabelFormat(format));
+ }
+
+ TimeAxisSetting(int minorUnit, int minorUnitCount, int majorUnit, int majorUnitCount,
+ int labelUnit, int labelUnitCount, int labelSpan, String format) {
+ this(0, minorUnit, minorUnitCount, majorUnit, majorUnitCount,
+ labelUnit, labelUnitCount, labelSpan, new SimpleTimeLabelFormat(format));
+ }
+
+ TimeAxisSetting withLabelFormat(TimeLabelFormat f) {
+ return new TimeAxisSetting(
+ secPerPix, minorUnit, minorUnitCount, majorUnit, majorUnitCount,
+ labelUnit, labelUnitCount, labelSpan, f);
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/TimeLabelFormat.java b/apps/jrobin/java/src/org/rrd4j/graph/TimeLabelFormat.java
new file mode 100644
index 0000000000..4f7a2d33e6
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/TimeLabelFormat.java
@@ -0,0 +1,19 @@
+package org.rrd4j.graph;
+
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * Simplified version of DateFormat for just defining how to map a timestamp into a label for
+ * presentation.
+ */
+public interface TimeLabelFormat {
+ /**
+ * Format a timestamp.
+ *
+ * @param calendar calendar to use for the formatter
+ * @param locale locale that will be used with {@code String.format}
+ * @return formatted string for the timestamp
+ */
+ String format(Calendar calendar, Locale locale);
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/VDef.java b/apps/jrobin/java/src/org/rrd4j/graph/VDef.java
new file mode 100644
index 0000000000..6161020a9e
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/VDef.java
@@ -0,0 +1,20 @@
+package org.rrd4j.graph;
+
+import org.rrd4j.data.DataProcessor;
+import org.rrd4j.data.Variable;
+
+class VDef extends Source {
+ private final String defName;
+ private final Variable var;
+
+ VDef(String name, String defName, Variable var) {
+ super(name);
+ this.defName = defName;
+ this.var = var;
+ }
+
+ void requestData(DataProcessor dproc) {
+ dproc.addDatasource(name, defName, var);
+ }
+
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/VRule.java b/apps/jrobin/java/src/org/rrd4j/graph/VRule.java
new file mode 100644
index 0000000000..12f1d6f59c
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/VRule.java
@@ -0,0 +1,17 @@
+package org.rrd4j.graph;
+
+import java.awt.BasicStroke;
+import java.awt.Paint;
+
+class VRule extends Rule {
+ final long timestamp;
+
+ VRule(long timestamp, Paint color, LegendText legend, BasicStroke stroke) {
+ super(color, legend, stroke);
+ this.timestamp = timestamp;
+ }
+
+ void setLegendVisibility(long minval, long maxval, boolean forceLegend) {
+ legend.enabled &= (forceLegend || (timestamp >= minval && timestamp <= maxval));
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/VSpan.java b/apps/jrobin/java/src/org/rrd4j/graph/VSpan.java
new file mode 100644
index 0000000000..1e4b6339b2
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/VSpan.java
@@ -0,0 +1,25 @@
+package org.rrd4j.graph;
+
+import java.awt.Paint;
+
+class VSpan extends Span {
+ final long start;
+ final long end;
+
+ VSpan(long start, long end, Paint color, LegendText legend) {
+ super(color, legend);
+ this.start = start;
+ this.end = end;
+ assert(start < end);
+ }
+
+ private boolean checkRange(long v, long min, long max) {
+ return v >= min && v <= max;
+ }
+
+ void setLegendVisibility(long min, long max, boolean forceLegend) {
+ legend.enabled = legend.enabled && (forceLegend
+ || checkRange(start, min, max)
+ || checkRange(end, min, max));
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/ValueAxis.java b/apps/jrobin/java/src/org/rrd4j/graph/ValueAxis.java
new file mode 100644
index 0000000000..d97c3f932d
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/ValueAxis.java
@@ -0,0 +1,249 @@
+package org.rrd4j.graph;
+
+import java.awt.Font;
+import java.awt.Paint;
+
+import org.rrd4j.core.Util;
+
+class ValueAxis extends Axis {
+ private static final YLabel[] ylabels = {
+ new YLabel(0.1, 1, 2, 5, 10),
+ new YLabel(0.2, 1, 5, 10, 20),
+ new YLabel(0.5, 1, 2, 4, 10),
+ new YLabel(1.0, 1, 2, 5, 10),
+ new YLabel(2.0, 1, 5, 10, 20),
+ new YLabel(5.0, 1, 2, 4, 10),
+ new YLabel(10.0, 1, 2, 5, 10),
+ new YLabel(20.0, 1, 5, 10, 20),
+ new YLabel(50.0, 1, 2, 4, 10),
+ new YLabel(100.0, 1, 2, 5, 10),
+ new YLabel(200.0, 1, 5, 10, 20),
+ new YLabel(500.0, 1, 2, 4, 10),
+ new YLabel(1000.0, 1, 2, 5, 10),
+ new YLabel(2000.0, 1, 5, 10, 20),
+ new YLabel(5000.0, 1, 2, 4, 10),
+ new YLabel(10000.0, 1, 2, 5, 10),
+ new YLabel(20000.0, 1, 5, 10, 20),
+ new YLabel(50000.0, 1, 2, 4, 10),
+ new YLabel(100000.0, 1, 2, 5, 10),
+ new YLabel(0.0, 0, 0, 0, 0)
+ };
+
+ private final ImageParameters im;
+ private final ImageWorker worker;
+ private final RrdGraphDef gdef;
+ private final Mapper mapper;
+
+ ValueAxis(RrdGraph rrdGraph) {
+ this(rrdGraph, rrdGraph.worker);
+ }
+
+ ValueAxis(RrdGraph rrdGraph, ImageWorker worker) {
+ this.im = rrdGraph.im;
+ this.gdef = rrdGraph.gdef;
+ this.worker = worker;
+ this.mapper = rrdGraph.mapper;
+ }
+
+ boolean draw() {
+ Font font = gdef.getFont(FONTTAG_AXIS);
+ Paint gridColor = gdef.getColor(ElementsNames.grid);
+ Paint mGridColor = gdef.getColor(ElementsNames.mgrid);
+ Paint fontColor = gdef.getColor(ElementsNames.font);
+ int labelOffset = (int) (worker.getFontAscent(font) / 2);
+ int labfact;
+ double range = im.maxval - im.minval;
+ double scaledrange = range / im.magfact;
+ double gridstep;
+ if (Double.isNaN(scaledrange)) {
+ return false;
+ }
+ String labfmt = null;
+ if (Double.isNaN(im.ygridstep)) {
+ if (gdef.altYGrid) {
+ /* find the value with max number of digits. Get number of digits */
+ int decimals = (int) Math.ceil(Math.log10(Math.max(Math.abs(im.maxval),
+ Math.abs(im.minval))));
+ if (decimals <= 0) /* everything is small. make place for zero */ {
+ decimals = 1;
+ }
+ int fractionals = (int) Math.floor(Math.log10(range));
+ if (fractionals < 0) /* small amplitude. */ {
+ labfmt = Util.sprintf(gdef.locale, "%%%d.%df", decimals - fractionals + 1, -fractionals + 1);
+ }
+ else {
+ labfmt = Util.sprintf(gdef.locale, "%%%d.1f", decimals + 1);
+ }
+ gridstep = Math.pow(10, fractionals);
+ if (gridstep == 0) /* range is one -> 0.1 is reasonable scale */ {
+ gridstep = 0.1;
+ }
+ /* should have at least 5 lines but no more then 15 */
+ if (range / gridstep < 5) {
+ gridstep /= 10;
+ }
+ if (range / gridstep > 15) {
+ gridstep *= 10;
+ }
+ if (range / gridstep > 5) {
+ labfact = 1;
+ if (range / gridstep > 8) {
+ labfact = 2;
+ }
+ }
+ else {
+ gridstep /= 5;
+ labfact = 5;
+ }
+ }
+ else {
+ //Start looking for a minimum of 3 labels, but settle for 2 or 1 if need be
+ int minimumLabelCount = 3;
+ YLabel selectedYLabel = null;
+ while(selectedYLabel == null) {
+ selectedYLabel = findYLabel(minimumLabelCount);
+ minimumLabelCount--;
+ }
+ gridstep = selectedYLabel.grid * im.magfact;
+ labfact = findLabelFactor(selectedYLabel);
+ }
+ }
+ else {
+ gridstep = im.ygridstep;
+ labfact = im.ylabfact;
+ }
+ int x0 = im.xorigin, x1 = x0 + im.xsize;
+ int sgrid = (int) (im.minval / gridstep - 1);
+ int egrid = (int) (im.maxval / gridstep + 1);
+ double scaledstep = gridstep / im.magfact;
+ for (int i = sgrid; i <= egrid; i++) {
+ int y = mapper.ytr(gridstep * i);
+ if (y >= im.yorigin - im.ysize && y <= im.yorigin) {
+ if (i % labfact == 0) {
+ String graph_label;
+ if (i == 0 || im.symbol == ' ') {
+ if (scaledstep < 1) {
+ if (i != 0 && gdef.altYGrid) {
+ graph_label = Util.sprintf(gdef.locale, labfmt, scaledstep * i);
+ }
+ else {
+ graph_label = Util.sprintf(gdef.locale, "%4.1f", scaledstep * i);
+ }
+ }
+ else {
+ graph_label = Util.sprintf(gdef.locale, "%4.0f", scaledstep * i);
+ }
+ }
+ else {
+ if (scaledstep < 1) {
+ graph_label = Util.sprintf(gdef.locale, "%4.1f %c", scaledstep * i, im.symbol);
+ }
+ else {
+ graph_label = Util.sprintf(gdef.locale, "%4.0f %c", scaledstep * i, im.symbol);
+ }
+ }
+ int length = (int) (worker.getStringWidth(graph_label, font));
+ worker.drawString(graph_label, x0 - length - PADDING_VLABEL, y + labelOffset, font, fontColor);
+ worker.drawLine(x0 - 2, y, x0 + 2, y, mGridColor, gdef.tickStroke);
+ worker.drawLine(x1 - 2, y, x1 + 2, y, mGridColor, gdef.tickStroke);
+ worker.drawLine(x0, y, x1, y, mGridColor, gdef.gridStroke);
+ }
+ else if (!(gdef.noMinorGrid)) {
+ worker.drawLine(x0 - 1, y, x0 + 1, y, gridColor, gdef.tickStroke);
+ worker.drawLine(x1 - 1, y, x1 + 1, y, gridColor, gdef.tickStroke);
+ worker.drawLine(x0, y, x1, y, gridColor, gdef.gridStroke);
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Finds an acceptable YLabel object for the current graph
+ * If the graph covers positive and negative on the y-axis, then
+ * desiredMinimumLabelCount is checked as well, to ensure the chosen YLabel definition
+ * will result in the required number of labels
+ *
+ * Returns null if none are acceptable (none the right size or with
+ * enough labels)
+ */
+ private YLabel findYLabel(int desiredMinimumLabelCount) {
+ double scaledrange = this.getScaledRange();
+ int labelFactor;
+ //Check each YLabel definition to see if it's acceptable
+ for (int i = 0; ylabels[i].grid > 0; i++) {
+ YLabel thisYLabel = ylabels[i];
+ //First cut is whether this gridstep would give enough space per gridline
+ if (this.getPixelsPerGridline(thisYLabel) > 5 ) {
+ //Yep; now we might have to check the number of labels
+ if(im.minval < 0.0 && im.maxval > 0.0) {
+ //The graph covers positive and negative values, so we need the
+ // desiredMinimumLabelCount number of labels, which is going to
+ // usually be 3, then maybe 2, then only as a last resort, 1.
+ // So, we need to find out what the label factor would be
+ // if we chose this ylab definition
+ labelFactor = findLabelFactor(thisYLabel);
+ if(labelFactor == -1) {
+ //Default to too many to satisfy the label count test, unless we're looking for just 1
+ // in which case be sure to satisfy the label count test
+ labelFactor = desiredMinimumLabelCount==1?1:desiredMinimumLabelCount+1;
+ }
+ //Adding one? Think fenceposts (need one more than just dividing length by space between)
+ int labelCount = ((int)(scaledrange/thisYLabel.grid)/labelFactor)+1;
+ if(labelCount > desiredMinimumLabelCount) {
+ return thisYLabel; //Enough pixels, *and* enough labels
+ }
+
+ } else {
+ //Only positive or negative on the graph y-axis. No need to
+ // care about the label count.
+ return thisYLabel;
+ }
+ }
+ }
+
+ double val = 1;
+ while(val < scaledrange) {
+ val = val * 10;
+ }
+ return new YLabel(val/10, 1, 2, 5, 10);
+ }
+
+ /**
+ * Find the smallest labelFactor acceptable (can fit labels) for the given YLab definition
+ * Returns the label factor if one is ok, otherwise returns -1 if none are acceptable
+ */
+ private int findLabelFactor(YLabel thisYLabel) {
+ int pixel = this.getPixelsPerGridline(thisYLabel);
+ int fontHeight = (int) Math.ceil(worker.getFontHeight(gdef.getFont(FONTTAG_AXIS)));
+ for (int j = 0; j < 4; j++) {
+ if (pixel * thisYLabel.labelFacts[j] >= 2 * fontHeight) {
+ return thisYLabel.labelFacts[j];
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Finds the number of pixels per gridline that the given YLabel definition will result in
+ */
+ private int getPixelsPerGridline(YLabel thisYLabel) {
+ double scaledrange = this.getScaledRange();
+ return (int) (im.ysize / (scaledrange / thisYLabel.grid));
+ }
+
+ private double getScaledRange() {
+ double range = im.maxval - im.minval;
+ return range / im.magfact;
+ }
+
+ static class YLabel {
+ final double grid;
+ final int[] labelFacts;
+
+ YLabel(double grid, int lfac1, int lfac2, int lfac3, int lfac4) {
+ this.grid = grid;
+ labelFacts = new int[]{lfac1, lfac2, lfac3, lfac4};
+ }
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/ValueAxisLogarithmic.java b/apps/jrobin/java/src/org/rrd4j/graph/ValueAxisLogarithmic.java
new file mode 100644
index 0000000000..fca83a5ae1
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/ValueAxisLogarithmic.java
@@ -0,0 +1,195 @@
+package org.rrd4j.graph;
+
+import org.rrd4j.core.Util;
+
+import java.awt.*;
+
+class ValueAxisLogarithmic extends Axis {
+ private static final double[][] yloglab = {
+ {1e9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1e3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1e1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1e1, 1, 2.5, 5, 7.5, 0, 0, 0, 0, 0, 0, 0},
+ {1e1, 1, 2, 4, 6, 8, 0, 0, 0, 0, 0, 0},
+ {1e1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ };
+
+ private final ImageParameters im;
+ private final ImageWorker worker;
+ private final RrdGraphDef gdef;
+ private final int fontHeight;
+ private final Mapper mapper;
+
+ ValueAxisLogarithmic(RrdGraph rrdGraph) {
+ this(rrdGraph, rrdGraph.worker);
+ }
+
+ ValueAxisLogarithmic(RrdGraph rrdGraph, ImageWorker worker) {
+ this.im = rrdGraph.im;
+ this.gdef = rrdGraph.gdef;
+ this.worker = worker;
+ this.fontHeight = (int) Math.ceil(worker.getFontHeight(gdef.getFont(FONTTAG_AXIS)));
+ this.mapper = rrdGraph.mapper;
+ }
+
+ boolean draw() {
+ Font font = gdef.getFont(FONTTAG_AXIS);
+ Paint gridColor = gdef.getColor(ElementsNames.grid);
+ Paint mGridColor = gdef.getColor(ElementsNames.mgrid);
+ Paint fontColor = gdef.getColor(ElementsNames.font);
+ int labelOffset = (int) (worker.getFontAscent(font) / 2);
+
+ if (im.maxval == im.minval) {
+ return false;
+ }
+ double pixpex = (double) im.ysize / (log10(im.maxval) - log10(im.minval));
+ if (Double.isNaN(pixpex)) {
+ return false;
+ }
+ double minstep, pixperstep;
+ int minoridx = 0, majoridx = 0;
+ for (int i = 0; yloglab[i][0] > 0; i++) {
+ minstep = log10(yloglab[i][0]);
+ for (int ii = 1; yloglab[i][ii + 1] > 0; ii++) {
+ if (yloglab[i][ii + 2] == 0) {
+ minstep = log10(yloglab[i][ii + 1]) - log10(yloglab[i][ii]);
+ break;
+ }
+ }
+ pixperstep = pixpex * minstep;
+ if (pixperstep > 5) {
+ minoridx = i;
+ }
+ if (pixperstep > 2 * fontHeight) {
+ majoridx = i;
+ }
+ }
+
+ // Draw minor grid for positive values
+ double positiveMin = (im.minval > 0.0) ? im.minval : 0.0;
+ int x0 = im.xorigin, x1 = x0 + im.xsize;
+ if (yloglab[minoridx][0] == 0 || yloglab[majoridx][0] == 0) {
+ return false;
+ }
+ for (double value = Math.pow(10, log10(positiveMin)
+ - log10(positiveMin) % log10(yloglab[minoridx][0]));
+ value <= im.maxval;
+ value *= yloglab[minoridx][0]) {
+ if (value < positiveMin) continue;
+ int i = 0;
+ while (yloglab[minoridx][++i] > 0) {
+ int y = mapper.ytr(value * yloglab[minoridx][i]);
+ if (y <= im.yorigin - im.ysize) {
+ break;
+ }
+ worker.drawLine(x0 - 1, y, x0 + 1, y, gridColor, gdef.tickStroke);
+ worker.drawLine(x1 - 1, y, x1 + 1, y, gridColor, gdef.tickStroke);
+ worker.drawLine(x0, y, x1, y, gridColor, gdef.gridStroke);
+ }
+ }
+
+ // Draw minor grid for negative values
+ double negativeMin = -1.0 * ((im.maxval < 0.0) ? im.maxval : 0.0);
+ for (double value = Math.pow(10, log10(negativeMin)
+ - log10(negativeMin) % log10(yloglab[minoridx][0]));
+ value <= -1.0 * im.minval;
+ value *= yloglab[minoridx][0]) {
+ if (value < negativeMin) continue;
+ int i = 0;
+ while (yloglab[minoridx][++i] > 0) {
+ int y = mapper.ytr(-1.0 * value * yloglab[minoridx][i]);
+ if (y <= im.yorigin - im.ysize) {
+ break;
+ }
+ worker.drawLine(x0 - 1, y, x0 + 1, y, gridColor, gdef.tickStroke);
+ worker.drawLine(x1 - 1, y, x1 + 1, y, gridColor, gdef.tickStroke);
+ worker.drawLine(x0, y, x1, y, gridColor, gdef.gridStroke);
+ }
+ }
+
+ // If it has positive and negative, always have a tick mark at 0
+ boolean skipFirst = false;
+ if (im.minval < 0.0 && im.maxval > 0.0) {
+ skipFirst = true;
+ int y = mapper.ytr(0.0);
+ worker.drawLine(x0 - 2, y, x0 + 2, y, mGridColor, gdef.tickStroke);
+ worker.drawLine(x1 - 2, y, x1 + 2, y, mGridColor, gdef.tickStroke);
+ worker.drawLine(x0, y, x1, y, mGridColor, gdef.gridStroke);
+ String graph_label = Util.sprintf(gdef.locale, "%3.0e", 0.0);
+ int length = (int) (worker.getStringWidth(graph_label, font));
+ worker.drawString(graph_label, x0 - length - PADDING_VLABEL, y + labelOffset, font, fontColor);
+ }
+
+ // Draw major grid for positive values
+ int iter = 0;
+ for (double value = Math.pow(10, log10(positiveMin)
+ - (log10(positiveMin) % log10(yloglab[majoridx][0])));
+ value <= im.maxval;
+ value *= yloglab[majoridx][0]) {
+ if (value < positiveMin) {
+ continue;
+ }
+ ++iter;
+ if (skipFirst && iter == 1) {
+ continue;
+ }
+ int i = 0;
+ while (yloglab[majoridx][++i] > 0) {
+ int y = mapper.ytr(value * yloglab[majoridx][i]);
+ if (y <= im.yorigin - im.ysize) {
+ break;
+ }
+ worker.drawLine(x0 - 2, y, x0 + 2, y, mGridColor, gdef.tickStroke);
+ worker.drawLine(x1 - 2, y, x1 + 2, y, mGridColor, gdef.tickStroke);
+ worker.drawLine(x0, y, x1, y, mGridColor, gdef.gridStroke);
+ String graph_label = Util.sprintf(gdef.locale, "%3.0e", value * yloglab[majoridx][i]);
+ int length = (int) (worker.getStringWidth(graph_label, font));
+ worker.drawString(graph_label, x0 - length - PADDING_VLABEL, y + labelOffset, font, fontColor);
+ }
+ }
+
+ // Draw major grid for negative values
+ iter = 0;
+ for (double value = Math.pow(10, log10(negativeMin)
+ - (log10(negativeMin) % log10(yloglab[majoridx][0])));
+ value <= -1.0 * im.minval;
+ value *= yloglab[majoridx][0]) {
+ if (value < negativeMin) {
+ continue;
+ }
+ ++iter;
+ if (skipFirst && iter == 1) {
+ continue;
+ }
+ int i = 0;
+ while (yloglab[majoridx][++i] > 0) {
+ int y = mapper.ytr(-1.0 * value * yloglab[majoridx][i]);
+ if (y <= im.yorigin - im.ysize) {
+ break;
+ }
+ worker.drawLine(x0 - 2, y, x0 + 2, y, mGridColor, gdef.tickStroke);
+ worker.drawLine(x1 - 2, y, x1 + 2, y, mGridColor, gdef.tickStroke);
+ worker.drawLine(x0, y, x1, y, mGridColor, gdef.gridStroke);
+ String graph_label = Util.sprintf(gdef.locale, "%3.0e", -1.0 * value * yloglab[majoridx][i]);
+ int length = (int) (worker.getStringWidth(graph_label, font));
+ worker.drawString(graph_label, x0 - length - PADDING_VLABEL, y + labelOffset, font, fontColor);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Compute logarithm for the purposes of y-axis.
+ */
+ static double log10(double v) {
+ double lv = Math.log10(Math.abs(v));
+ if (lv < 0) {
+ // Don't cross the sign line, round to 0 if that's the case
+ return 0.0;
+ } else {
+ return Math.copySign(lv, v);
+ }
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/ValueAxisMrtg.java b/apps/jrobin/java/src/org/rrd4j/graph/ValueAxisMrtg.java
new file mode 100644
index 0000000000..2da2f397bc
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/ValueAxisMrtg.java
@@ -0,0 +1,66 @@
+package org.rrd4j.graph;
+
+import org.rrd4j.core.Util;
+
+import java.awt.*;
+
+class ValueAxisMrtg extends Axis {
+
+ private final ImageParameters im;
+ private final ImageWorker worker;
+ private final RrdGraphDef gdef;
+
+ ValueAxisMrtg(RrdGraph rrdGraph) {
+ this(rrdGraph, rrdGraph.worker);
+ }
+
+ ValueAxisMrtg(RrdGraph rrdGraph, ImageWorker worker) {
+ this.im = rrdGraph.im;
+ this.gdef = rrdGraph.gdef;
+ this.worker = worker;
+ im.unit = gdef.unit;
+ }
+
+ boolean draw() {
+ Font font = gdef.getFont(FONTTAG_AXIS);
+ Paint mGridColor = gdef.getColor(ElementsNames.mgrid);
+ Paint fontColor = gdef.getColor(ElementsNames.font);
+ int labelOffset = (int) (worker.getFontAscent(font) / 2);
+
+ if (Double.isNaN((im.maxval - im.minval) / im.magfact)) {
+ return false;
+ }
+
+ int xLeft = im.xorigin;
+ int xRight = im.xorigin + im.xsize;
+ String labfmt;
+ if (im.scaledstep / im.magfact * Math.max(Math.abs(im.quadrant), Math.abs(4 - im.quadrant)) <= 1.0) {
+ labfmt = "%5.2f";
+ }
+ else {
+ labfmt = Util.sprintf(gdef.locale, "%%4.%df", 1 - ((im.scaledstep / im.magfact > 10.0 || Math.ceil(im.scaledstep / im.magfact) == im.scaledstep / im.magfact) ? 1 : 0));
+ }
+ if (im.symbol != ' ' || im.unit != null) {
+ labfmt += " ";
+ }
+ if (im.symbol != ' ') {
+ labfmt += Character.toString(im.symbol);
+ }
+ if (im.unit != null) {
+ labfmt += im.unit;
+ }
+ for (int i = 0; i <= 4; i++) {
+ int y = im.yorigin - im.ysize * i / 4;
+ if (y >= im.yorigin - im.ysize && y <= im.yorigin) {
+ String graph_label = Util.sprintf(gdef.locale, labfmt, im.scaledstep / im.magfact * (i - im.quadrant));
+ int length = (int) (worker.getStringWidth(graph_label, font));
+ worker.drawString(graph_label, xLeft - length - PADDING_VLABEL, y + labelOffset, font, fontColor);
+ worker.drawLine(xLeft - 2, y, xLeft + 2, y, mGridColor, gdef.tickStroke);
+ worker.drawLine(xRight - 2, y, xRight + 2, y, mGridColor, gdef.tickStroke);
+ worker.drawLine(xLeft, y, xRight, y, mGridColor, gdef.gridStroke);
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/ValueAxisSetting.java b/apps/jrobin/java/src/org/rrd4j/graph/ValueAxisSetting.java
new file mode 100644
index 0000000000..53fdcef9f6
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/ValueAxisSetting.java
@@ -0,0 +1,11 @@
+package org.rrd4j.graph;
+
+class ValueAxisSetting {
+ final double gridStep;
+ final int labelFactor;
+
+ ValueAxisSetting(double gridStep, int labelFactor) {
+ this.gridStep = gridStep;
+ this.labelFactor = labelFactor;
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/ValueScaler.java b/apps/jrobin/java/src/org/rrd4j/graph/ValueScaler.java
new file mode 100644
index 0000000000..1068365d9d
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/ValueScaler.java
@@ -0,0 +1,70 @@
+package org.rrd4j.graph;
+
+class ValueScaler {
+ static final String UNIT_UNKNOWN = "?";
+ static final String UNIT_SYMBOLS[] = {
+ "a", "f", "p", "n", "u", "m", " ", "k", "M", "G", "T", "P", "E"
+ };
+ static final int SYMB_CENTER = 6;
+
+ private final double base;
+ private double magfact = -1; // nothing scaled before, rescale
+ private String unit;
+
+ ValueScaler(double base) {
+ this.base = base;
+ }
+
+ Scaled scale(double value, boolean mustRescale) {
+ Scaled scaled;
+ if (mustRescale) {
+ scaled = rescale(value);
+ }
+ else if (magfact >= 0) {
+ // already scaled, need not rescale
+ scaled = new Scaled(value / magfact, unit);
+ }
+ else {
+ // scaling not requested, but never scaled before - must rescale anyway
+ scaled = rescale(value);
+ // if zero, scale again on the next try
+ if (scaled.value == 0.0 || Double.isNaN(scaled.value)) {
+ magfact = -1.0;
+ }
+ }
+ return scaled;
+ }
+
+ private Scaled rescale(double value) {
+ int sindex;
+ if (value == 0.0 || Double.isNaN(value)) {
+ sindex = 0;
+ magfact = 1.0;
+ }
+ else {
+ sindex = (int) (Math.floor(Math.log(Math.abs(value)) / Math.log(base)));
+ magfact = Math.pow(base, sindex);
+ }
+ if (sindex <= SYMB_CENTER && sindex >= -SYMB_CENTER) {
+ unit = UNIT_SYMBOLS[sindex + SYMB_CENTER];
+ }
+ else {
+ unit = UNIT_UNKNOWN;
+ }
+ return new Scaled(value / magfact, unit);
+ }
+
+ static class Scaled {
+ double value;
+ String unit;
+
+ public Scaled(double value, String unit) {
+ this.value = value;
+ this.unit = unit;
+ }
+
+ void dump() {
+ System.out.println("[" + value + unit + "]");
+ }
+ }
+}
diff --git a/apps/jrobin/java/src/org/rrd4j/graph/package-info.java b/apps/jrobin/java/src/org/rrd4j/graph/package-info.java
new file mode 100644
index 0000000000..3174ae2571
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/graph/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * RRD4J graph capabilities.
+ */
+package org.rrd4j.graph;
diff --git a/apps/jrobin/java/src/org/rrd4j/package-info.java b/apps/jrobin/java/src/org/rrd4j/package-info.java
new file mode 100644
index 0000000000..6ed9a52845
--- /dev/null
+++ b/apps/jrobin/java/src/org/rrd4j/package-info.java
@@ -0,0 +1,22 @@
+/**
+ * RRD4J is a high performance data logging and graphing system for time series data, implementing
+ * RRDTool's functionality in Java. It follows much of the same logic and uses the same data sources,
+ * archive types and definitions as RRDTool does.
+ *