HOME | Library | JRobin API | Utilities | Support | About Us | Forum

Welcome to JRobin
JRobin 1.4.0 released!
Download JRobin
Live demo
Gallery
License
Site map

# JRobin 1.4.0 released!

## What's new in JRobin 1.4.0?

### Backends

The core package was completely redesigned. High level JRobin classes implementing the whole RRD logic are now clearly separated from the I/O backend (low level classes implementing actual I/O operations).

Default backend shipped with 1.4.0 is based on extremely fast java.nio.* library. It's true that it takes more memory (borrowed from the OS directly), but it runs almost four times faster than before. Backends are also "switchable": with a single line of code you can force JRobin to use the an improved and faster version of the I/O engine found in 1.3.1 release.

And that's not all: your RRD data can be maintained in memory, you don't have to use files. For those who want to create their own, custom RRD backends (RDBMS based, for example), there is a simple skeleton for it. Please refer to the backend page to for the whole explanation.

### Speed, more speed

Just run the StressTest from the main JRobin library. It should perform more than 2.500 RRD updates per second on a modest PC (this is at least 2-3 times faster than before).

### RrdGraphDef: new setResolution() option

This sets the resolution with which to fetch values from the RRD datasources. This is the equivalent to RRDtool's --step option.

### RrdGraphDef: RrdBackendFactory specification with datasource

The RrdBackendFactory is an entirely new core feature that's being introduced with JRobin 1.4.0. It allows for far better control over RRD datasources, and can offer tremendous performance enhancement. It basically comes down to the fact that you can now also use RRD datasources by storing them purely in memory, or on disk but using the new - high performance - Java NIO package. Both NIO and MEMORY are many times faster than the traditional FILE access. Please refer to the backends page for more information on the RrdBackendFactory.

It is possible to specify the backend in a RrdGraphDefTemplate or RrdExportDefTemplate by adding a <backend>BACKEND_NAME</backend> tag to a RRD def.

### RrdGraphDef: NewsetLowerLimit() option

Grid range specification has been altered so you can specify only lower or upper limit values, while leaving the other limit for auto-scaling. Because of the common use, a separate method setLowerLimit(value) has been added to allow easier specification of the lower limit. The setLowerLimit(value) is the equivalent of setGridRange(value, Double.NaN, false).

The XML template equivalents are:

    <options>
      <!-- Both options have the same effect -->
      <lower_limit>0</lower_limit>
      <grid_range>
        <lower>0</lower>
        <upper>U</upper>
        <rigid>false</rigid>
      </grid_range>
    </options>

### RrdGraph: New render option with Graphics2D passing

A new method was added to RrdGraph allowing you to render a JRobin graph onto a Graphics2D object you pass yourself. The method is of the form renderImage(Graphics2D, width, height). Additionally an extra method was added to retrieve a JRobin graph directly as its underlying BufferedImage: getBufferedImage(width, height). In both cases auto-sizing of the graph is done by specifying a width and height of 0.

Live example is available:

    java -cp jrobin-demo-1.4.0.jar org.jrobin.demo.graph.SwingDemo

### RrdGraphDef: new setLazy() option

Like with Rrdtool, the lazy option can be used to make sure images only get generated if they are outdated. In other words, if the RRD datasources have a last update time that is after the last graph generation time. The last graph generation time is determined by the 'last modified' timestamp of the file.

Live example is available:

    java -cp jrobin-demo-1.4.0.jar org.jrobin.demo.graph.LazyDemo

In a windowless environment be sure to specify `-Djava.awt.headless=true` option.

### RrdGraphDef: Zero value for the end timestamp

If you put 0 (zero) as the end timestamp of a RrdGraphDef time period, the graph will be generated until the last completed sample (in time! not value!). This is almost the same as graphing until the current time, only the graph will automatically adjust the range so it shows the last completed sample. If the last sample is correct, you will no longer see NaN values at the very end of the graph.

The StressTest demo contains a sample use of this feature.

### RrdGraphDef: New datasource type (Sdef) in graph definitions

JRobin now offers an entirely new datasource, internally called Sdef. This datasource represents the result of a consolidation function applied to another datasource, much like the gprint() method does. A specified Sdef datasource can be used in any Cdef datasource with RPN calculation, and can be derived from any other datasource. It can also be used in the normal way for plotting or drawing comments. Example code:

    graphDef.datasource( "in", RRD_FILE, "input", "AVERAGE" );
    graphDef.datasource( "avgIn", "in", "AVERAGE" ); // Sdef
    graphDef.datasource( "deviation", "in,avgIn,-" );
    graphDef.area( "deviation", Color.BLUE, "Deviation from average" );
    graphDef.line( "avgIn", Color.RED, "Average incoming" );

and the corrseponding code in the XML template would be:

    <datasources>
      ...
      <def>
        <name>avgIn</name>
        <datasource>in</datasource>
        <cf>AVERAGE</cf>
      </def>
      ...
    </datasources>

Live example is available in the SwingDemo application (already mentioned on this page)

### RrdGraphDef: added time() method

You can now plot a timestamp with a specified format on a JRobin graph. You can either specify the timestamp in several ways, or you can omit the timestamp, in which case the 'current time' will be plotted. The current time in this case would be the time when the graph generation encounters the Time command. The format of the text is like normal comment, only it should contain a @t marker to specficy where the timestamp should be. The timestamp will then be printed according to the provided pattern. The pattern can be a pattern string for a SimpleDateFormat object, or it can be any DateFormat object you created:

    // Specific time
    rrdGraphDef.time("First day of the year: @t@l", "dd-MM-yyyy",
        new GregorianCalendar(2004, Calendar.JANUARY, 1));
    // Current time
    rrdGraphDef.time( "@lGenerated: @t@c", "HH:mm:ss");

There is a set of corresponding XML tags for the RrdGraphDef template. If the value tag is omitted, the current time will be used. Otherwise, the value tag can be specified like the start and end time of the graph: as an absolute time in seconds since the epoch, or as an ISO timestamp of the form: `yyyy-MM-dd HH:mm:ss`.

    <!-- This would print out the current time -->
    <time>
        <format>Current time: @t</format>
        <pattern>MMM dd, yyyy   HH:mm:ss</pattern>
    </time>

    <!-- This would print out: january 2004 (in your locale) -->
    <time>
        <format>Month: @t</format>
        <pattern>MMMM yyyy</pattern>
        <value>2004-01-01 12:00:00</value>
    </time></graph>

Live example is available in the SwingDemo application (already mentioned on this page):

### Added RRD export functionality like RRDtool XPORT command

JRobin now supports data export functionality, much like the original RRDtool does, with a few extra touches ofcourse.

Since 1.4.0 export has been introduced in the form of RrdExport, RrdExportDef and ExportData classes. It works very much like graphing does, here's a quick example:

    // Create a def for export specification
    RrdExportDef def = new RrdExportDef( startTime, endTime );
    def.datasource( "ds", "test.rrd", "datasource", "AVERAGE" );
    def.export( "ds", "A single datasource" );

    // Pass the def to the exporter, fetch the export data, but no more than 50 rows
    // If you don't specify the maximum number of rows to retrieve, 400 will be used
    RrdExport export = new RrdExport( def );
    ExportData data = export.fetch( 50 );

    // Dump the exported data to XML in a file
    data.exportXml( "export-data.xml" );

    // Or request a value directly from the exported data
    double value = data.getAggregate( "ds", "MAX" );

    // We can also request the value as a string, much like with GPRINT
    System.out.println( data.print( "ds", "MAX", "Maximum: @5.2" ) );

The ExportData class corresponds to the public RrdDataSet interface, as does the FetchData class (the result of a direct fetch on an RRD). The RrdDataSet interface gives you a number of useful methods that can be used to retrieve and calculate data or for example pass it on to an external graphing or charting library.

UNLIKE with RRDtool, it is not necessary to specify what data to export, by default all datasources requested will be exported. However, as soon you specify a datasource to export, using the export() construct, by default the system will revert to the so called 'strict' export like RRDtool, and only export the datasources you explicitly specified. You can override this behaviour by calling setStrictExport(boolean) method manually. If you disable strict export, you can set legends for only a few datasources, but still have all datasources in the ExportData set.

The RrdExportDef is a subset of the RrdGraphDef and introduces a new XML Template very much alike. An example:

    <rrd_export_def>
      <span>
        <start>${start}</start>
        <end>${end}</end>
      </span>
      <datasources>
        <def>
          <name>bytesIn</name>
          <rrd>${rrd}</rrd>
          <source>ifInOctets</source>
          <cf>AVERAGE</cf>
        </def>
        <def>
          <name>bitsIn</name>
          <rpn>bytesIn,8,*</rpn>
        </def>
      </datasources>
      <exports>
        <export>
          <datasource>bitsIn</datasource>
          <legend>Bits Incoming</legend>
        </export>
        <export>
          <datasource>bytesIn</datasource>
          <legend>Bytes Incoming</legend>
         </export>
      </exports>
    </rrd_export_def>

An ExportData object can directly be recreated from an export XML file, like:

    ExportData data = new ExportData( new File("export-data.xml"), true );

The second parameter determines if the legends in the export XML should be used to name the datasources. If set to false, the datasources will get named sequentially of the form 'd1', 'd2'... unless you specify a different prefix in the ExportData constructor, like in:

    ExportData data = new ExportData( new File("export-data.xml"), "mydata");
    // The imported datasources will be named 'mydata1', 'mydata2' ...

Because of the XML import functionality, you can easily import regular RRDtool XPORT xml data into a JRobin ExportData set. Furthermore, ExportData can be set as a datasource in a normal RrdGraphDef, allowing you to generate graphs directly from RRDtool exported data. Simply add a number of ExportData objects to a RrdGraphDef:

    RrdGraphDef graphDef = new RrdGraphDef();
    ...
    graphDef.addExportData( exportData1 );
    graphDef.addExportData( exportData2 );
    ...

And there is the RrdGraphDefTemplate XML variation:

    <datasources>
      ...
      <export_data>
        <file>/export_data/exportdata1.xml</file>
        <ds_name_prefix>traffic</ds_name_prefix>
      </export_data>

      <export_data>
        <file>/export_data/exportdata2.xml</file>
        <use_legend_names>true</use_legend_names>
      </export_data>

      <export_data>
        <file>/export_data/exportdata3.xml</file>
      </export_data>
      ...
    </datasources>

Every RrdGraphDef is also a RrdExportDef. This means you can pass a RrdGraphDef directly to an RrdExport, you can generate the ExportData from the corresponding graph. However, if you are interested in both generating the graph and retrieving the ExportData, it is better to use the export functionality of RrdGraph, in order to generate the data only once. A simple example:

    RrdGraphDef graphDef = new RrdGraphDef( startTime, endTime );
    ...
    RrdGraph graph = new RrdGraph( graphDef );

    // Save the graph image
    graph.saveAsPNG( graphFile );

    // Get the export data
    ExportData data = graph.getExportData();

    // Do something with the exported data
    // Store max values in a relational database for example.

Note: RrdGraph also contains two fetchExportData methods. These will calculate the ExportData again based on the passed RrdGraphDef. Use the getExportData() method after creating the image to save a calculation roundtrip, it can save you many CPU cycles, use fetchExportData() if you want to retrieve the export data without generating the graph, or if you want to re-generate it after changing the graphDef or with a lower maxRows limit.

The workings of JRobin export are demonstrated in the combined ExportDemo. The ExportDemo is actually two different apps: ExportExportDemo, that exports data from two rrd files and dumps the result in some XML files:

    java -cp jrobin-demo-1.4.0.jar org.jrobin.demo.graph.ExportExportDemo

...and the ExportImportDemo that reads in the output from ExportExportDemo and generates a graph from it:

    java -cp jrobin-demo-1.4.0.jar org.jrobin.demo.graph.ExportImportDemo

### New demo utilities: GraphTemplate and ExportTemplate

JRobin 1.4.0 comes with two new demo applications: GraphTemplate and ExportTemplate. These are command-line utilities that allow you to generate output (a graph or export data) based on a template XML file (RrdGraphDefTemplate or RrdExportDefTemplate). The programs are very similar, and if they detect parameters in the template XML (${param}), they will ask for the values of these parameters interactively.

    java -cp jrobin-demo-1.4.0.jar \
        org.jrobin.demo.graph.GraphTemplate \
        [-img (png|gif|jpg)] [-w width] [-h height] [-q jpegQuality] \
        <template_file> <image_name>

Command parameters are:

- -img Specifies the image format of the target graph
- -width Width in pixels of the target graph
- -height Height in pixels of the target graph
- -q If JPEG is used as image format, specify the quality as float
- <template_file> File containing XML RrdGraphDef template
- <image_name> Name the image should be saved as

    java -cp jrobin-demo-1.4.0.jar \
        org.jrobin.demo.graph.ExportTemplate \
        [-m maxRows] [-f <dump_file>] \
        <template_file>

Command parameters are:

- -m Maximum number of rows to have in the exported data (similar to RRDtool XPORT -m)
- -f File where to dump the exported data in XML format, if not specified, the export XML is printed on stdout
- <template_file> File containing XML RrdExportDef template

### Improved LinearInterpolator class

There is a new interpolation method in the LinearInterpolator class. It is now possible to interpolate data points in a (time, value) plane with a single best-fit line. The slope of the line will be calculated so that the total square distance of real data points from from the best-fit line is at minimum.

### Rich PlottableDemo

Many users asked how to create those fancy-looking gradient-filled graphs. All those tricks are now included in the PlottableDemo.

### New FetchSourceList class and setDatasources() option

It often happens you want to generate a different batch of graphs, but using the same set of datasources. Use of aFetchSourceList combined with the new RrdGraphDef.setDatasources() method allows you to manage the graph datasources separately, and passing them on to a RrdGraphDef in one go. Please note, FetchSourceList only touches on the subject of RrdDb datasources, not combined, static or plottable definitions.

When generating multiple graphs with the lazy flag set, using the same datasources, the use of a single FetchSourceList (with the persistent option set) can offer serious performance enhancement:

    FetchSourceList list = new FetchSourceList( 2, true, new RrdOpener(true, true) );
    list.add( "in", RRD_FILE, "in", "AVERAGE" );
    list.add( "out", RRD_FILE, "out", "AVERAGE" );
    ...
    list.openAll();                   // Retrieve all RrdDb instances
    ...                               // Create basic GraphDef
    graphDef.setDatasources( list );  // Set the datasources
    ...                               // Generate graph (one or more)
    list.releaseAll();                // Release all RrdDb instances

### New RrdOpener class

The RrdOpener class represents a wrapper object to be used for opening and closing RrdDb instances. A FetchSourceList requires an RrdOpener to access the RrdDb objects related to the datasources. The RrdGraph object used to generate the graphs is itself a child class of RrdOpener, and is the default opener used for graph datasources. You can override this behaviour, by providing the datasources as a persistent FetchSourceList, with its own RrdOpener. Be aware you must manually control releasing or closing all RrdDbs when finished with them.

The use of RrdOpener is in creating child classes that override the general retrieve and release methods, allowing central management of the RrdDb instances. This could for example easily be used to count how many times a RdbDb is retrieved, or to map the name of the RrdDb to say a database record.

Live example is available in LazyDemo (already mentioned on this page).

### Restructured web site

At least, it looks better now.

### Importan release notes

- JRobin 1.4.0 switched to java.nio.* package in order to perform low level I/O operations many times faster than before. However, if you ever become suspicios that the new I/O engine has problems never encountered before, it is easy to force JRobin to perform I/O operations in an old-fashioned way (like in 1.3.1 version). Just put the following line of code somewhere early in your application:

      RrdDb.setDefaultFactory("FILE");

- RrdFile class is gone, forever. It was tightly related to RandomAccessFile class and does not fit well in the new frontend/backend concept. Chances are that you never used this class in your code, but if you still need it take a look at ist counterpart, the RrdBackend class.
- Some methods from the core package classes will now throw IOExceptions. This might force you to recompile your code. If I had to put some money on it, I would rather say that 'no compilation is required' than 'recompilation is mandatory'. Important constructors and methods, like update() or fetchData(), preserved their original signature.
- FetchSourceList and RrdOpener are advanced features that are still in development, even though they are in the heart of the stable 1.4.0 release. As such, both FetchSourceList and RrdOpener are subject to serious API changes in the next release(s).

Older releases and news

Back to the top

Copyright © 2003, 2004 Sasa Markovic & Arne Vandamme. All Rights Reserved.