📄 rrddb.java
字号:
/* ============================================================
* 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.*;
import java.util.Date;
/**
* <p>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).</p>
* <p/>
* <p>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).</p>
* <p/>
* <p>Note that JRobin uses binary format different from RRDTool's format. You cannot
* use this class to manipulate RRD files created with RRDTool. <b>However, if you perform
* the same sequence of create, update and fetch operations, you will get exactly the same
* results from JRobin and RRDTool.</b><p>
* <p/>
* <p/>
* You will not be able to use JRobin API if you are not familiar with
* basic RRDTool concepts. Good place to start is the
* <a href="http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/tutorial/rrdtutorial.html">official RRD tutorial</a>
* and relevant RRDTool man pages: <a href="../../../../man/rrdcreate.html" target="man">rrdcreate</a>,
* <a href="../../../../man/rrdupdate.html" target="man">rrdupdate</a>,
* <a href="../../../../man/rrdfetch.html" target="man">rrdfetch</a> and
* <a href="../../../../man/rrdgraph.html" target="man">rrdgraph</a>.
* For RRDTool's advanced graphing capabilities (RPN extensions), also supported in JRobin,
* there is an excellent
* <a href="http://people.ee.ethz.ch/~oetiker/webtools/rrdtool/tutorial/cdeftutorial.html" target="man">CDEF tutorial</a>.
* </p>
*
* @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;
/**
* <p>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.</p>
* <p/>
* <p>New RRD file structure is specified with an object of class
* {@link org.jrobin.core.RrdDef <b>RrdDef</b>}. The underlying RRD storage is created as soon
* as the constructor returns.</p>
* <p/>
* <p>Typical scenario:</p>
* <p/>
* <pre>
* // 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);
* <p/>
* // RRD definition is now completed, create the database!
* RrdDb rrd = new RrdDb(def);
* // new RRD file has been created on your disk
* </pre>
*
* @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());
}
/**
* <p>Constructor used to create new RRD object from the definition object but with a storage
* (backend) different from default.</p>
* <p/>
* <p>JRobin uses <i>factories</i> to create RRD backend objecs. There are three different
* backend factories supplied with JRobin, and each factory has its unique name:</p>
* <p/>
* <ul>
* <li><b>FILE</b>: backends created from this factory will store RRD data to files by using
* java.io.* classes and methods
* <li><b>NIO</b>: backends created from this factory will store RRD data to files by using
* java.nio.* classes and methods
* <li><b>MEMORY</b>: backends created from this factory will store RRD data in memory. This might
* be useful in runtime environments which prohibit disk utilization, or for storing temporary,
* non-critical data (it gets lost as soon as JVM exits).
* </ul>
* <p/>
* <p>For example, to create RRD in memory, use the following code</p>
* <pre>
* RrdBackendFactory factory = RrdBackendFactory.getFactory("MEMORY");
* RrdDb rrdDb = new RrdDb(rrdDef, factory);
* rrdDb.close();
* </pre>
* <p/>
* <p>New RRD file structure is specified with an object of class
* {@link org.jrobin.core.RrdDef <b>RrdDef</b>}. The underlying RRD storage is created as soon
* as the constructor returns.</p>
*
* @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;
}
}
/**
* <p>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.</p>
*
* @param path Path to existing RRD.
* @param readOnly Should be set to <code>false</code> if you want to update
* the underlying RRD. If you want just to fetch data from the RRD file
* (read-only access), specify <code>true</code>. If you try to update RRD file
* open in read-only mode (<code>readOnly</code> set to <code>true</code>),
* <code>IOException</code> 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());
}
/**
* <p>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.</p>
*
* @param path Path to existing RRD.
* @param readOnly Should be set to <code>false</code> if you want to update
* the underlying RRD. If you want just to fetch data from the RRD file
* (read-only access), specify <code>true</code>. If you try to update RRD file
* open in read-only mode (<code>readOnly</code> set to <code>true</code>),
* <code>IOException</code> 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;
}
}
/**
* <p>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);
}
/**
* <p>Constructor used to open already existing RRD in R/W mode with a storage (backend) type
* different from default.</p>
*
* @param path Path to existing RRD.
* @param factory Backend factory used to create 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 path, RrdBackendFactory factory) throws IOException, RrdException {
this(path, false, factory);
}
/**
* <p>Constructor used to create RRD files from external file sources.
* Supported external file sources are:</p>
* <p/>
* <ul>
* <li>RRDTool/JRobin XML file dumps (i.e files created with <code>rrdtool dump</code> command).
* <li>RRDTool binary files.
* </ul>
* <p/>
* <p>Newly created RRD will be backed with a default storage (backend) type
* (file on the disk).</p>
* <p/>
* <p>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):</p>
* <p/>
* <pre>
* rrdtool dump original.rrd > original.xml
* </pre>
* <p/>
* <p>Than, use the file <code>original.xml</code> to create JRobin RRD file named
* <code>copy.rrd</code>:</p>
* <p/>
* <pre>
* RrdDb rrd = new RrdDb("copy.rrd", "original.xml");
* </pre>
* <p/>
* <p>or:</p>
* <p/>
* <pre>
* RrdDb rrd = new RrdDb("copy.rrd", "xml:/original.xml");
* </pre>
* <p/>
* <p>See documentation for {@link #dumpXml(java.lang.String) dumpXml()} method
* to see how to convert JRobin files to RRDTool's format.</p>
* <p/>
* <p>To read RRDTool files directly, specify <code>rrdtool:/</code> prefix in the
* <code>externalPath</code> argument. For example, to create JRobin compatible file named
* <code>copy.rrd</code> from the file <code>original.rrd</code> created with RRDTool, use
* the following code:</p>
* <p/>
* <pre>
* RrdDb rrd = new RrdDb("copy.rrd", "rrdtool:/original.rrd");
* </pre>
* <p/>
* <p>Note that the prefix <code>xml:/</code> or <code>rrdtool:/</code> is necessary to distinguish
* between XML and RRDTool's binary sources. If no prefix is supplied, XML format is assumed</p>
*
* @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
* <code>xml:/</code> or <code>rrdtool:/</code> 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 {
this(rrdPath, externalPath, RrdBackendFactory.getDefaultFactory());
}
/**
* <p>Constructor used to create RRD files from external file sources with a backend type
* different from default. Supported external file sources are:</p>
* <p/>
* <ul>
* <li>RRDTool/JRobin XML file dumps (i.e files created with <code>rrdtool dump</code> command).
* <li>RRDTool binary files.
* </ul>
* <p/>
* <p>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):</p>
* <p/>
* <pre>
* rrdtool dump original.rrd > original.xml
* </pre>
* <p/>
* <p>Than, use the file <code>original.xml</code> to create JRobin RRD file named
* <code>copy.rrd</code>:</p>
* <p/>
* <pre>
* RrdDb rrd = new RrdDb("copy.rrd", "original.xml");
* </pre>
* <p/>
* <p>or:</p>
* <p/>
* <pre>
* RrdDb rrd = new RrdDb("copy.rrd", "xml:/original.xml");
* </pre>
* <p/>
* <p>See documentation for {@link #dumpXml(java.lang.String) dumpXml()} method
* to see how to convert JRobin files to RRDTool's format.</p>
* <p/>
* <p>To read RRDTool files directly, specify <code>rrdtool:/</code> prefix in the
* <code>externalPath</code> argument. For example, to create JRobin compatible file named
* <code>copy.rrd</code> from the file <code>original.rrd</code> created with RRDTool, use
* the following code:</p>
* <p/>
* <pre>
* RrdDb rrd = new RrdDb("copy.rrd", "rrdtool:/original.rrd");
* </pre>
* <p/>
* <p>Note that the prefix <code>xml:/</code> or <code>rrdtool:/</code> is necessary to distinguish
* between XML and RRDTool's binary sources. If no prefix is supplied, XML format is assumed</p>
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -