📄 rrddb.java
字号:
* @param rrdPath Path to RRD 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.
* @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;
}
}
/**
* 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];
}
/**
* <p>Returns an array of datasource names defined in RRD.</p>
*
* @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;
}
/**
* <p>Creates new sample with the given timestamp and all datasource values set to
* 'unknown'. Use returned <code>Sample</code> 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.</p>
* <p/>
* <p>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.</p>
*
* @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);
}
/**
* <p>Creates new sample with the current timestamp and all data source values set to
* 'unknown'. Use returned <code>Sample</code> 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.</p>
* <p/>
* <p>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.</p>
*
* @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());
}
/**
* <p>Prepares fetch request to be executed on this RRD. Use returned
* <code>FetchRequest</code> object and its {@link org.jrobin.core.FetchRequest#fetchData() fetchData()}
* method to actually fetch data from the RRD file.</p>
*
* @param consolFun Consolidation function to be used in fetch request. Allowed values are
* "AVERAGE", "MIN", "MAX" and "LAST" (these constants are conveniently defined in the
* {@link ConsolFuns} class).
* @param fetchStart Starting timestamp for fetch request.
* @param fetchEnd Ending timestamp for fetch request.
* @param resolution Fetch resolution (see RRDTool's
* <a href="../../../../man/rrdfetch.html" target="man">rrdfetch man page</a> for an
* explanation of this parameter.
* @return Request object that should be used to actually fetch data from RRD.
* @throws RrdException In case of JRobin related error (invalid consolidation function or
* invalid time span).
*/
public FetchRequest createFetchRequest(String consolFun, long fetchStart, long fetchEnd,
long resolution) throws RrdException {
return new FetchRequest(this, consolFun, fetchStart, fetchEnd, resolution);
}
/**
* <p>Prepares fetch request to be executed on this RRD. Use returned
* <code>FetchRequest</code> 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
* <a href="../../../../man/rrdfetch.html" target="man">rrdfetch man page</a>
* for the explanation of the resolution parameter).</p>
*
* @param consolFun Consolidation function to be used in fetch request. Allowed values are
* "AVERAGE", "MIN", "MAX" and "LAST" (these constants are conveniently defined in the
* {@link ConsolFuns} class).
* @param fetchStart Starting timestamp for fetch request.
* @param fetchEnd Ending timestamp for fetch request.
* @return Request object that should be used to actually fetch data from RRD.
* @throws RrdException In case of JRobin related error (invalid consolidation function or
* invalid time span).
*/
public FetchRequest createFetchRequest(String consolFun, long fetchStart, long fetchEnd)
throws RrdException {
return createFetchRequest(consolFun, fetchStart, fetchEnd, 1);
}
synchronized void store(Sample sample) throws IOException, RrdException {
if (closed) {
throw new RrdException("RRD already closed, cannot store this sample");
}
long newTime = sample.getTime();
long lastTime = header.getLastUpdateTime();
if (lastTime >= newTime) {
throw new RrdException("Bad sample timestamp " + newTime +
". Last update time was " + lastTime + ", at least one second step is required");
}
double[] newValues = sample.getValues();
for (int i = 0; i < datasources.length; i++) {
double newValue = newValues[i];
datasources[i].process(newTime, newValue);
}
header.setLastUpdateTime(newTime);
}
synchronized FetchData fetchData(FetchRequest request) throws IOException, RrdException {
if (closed) {
throw new RrdException("RRD already closed, cannot fetch data");
}
Archive archive = findMatchingArchive(request);
return archive.fetchData(request);
}
public Archive findMatchingArchive(FetchRequest request) throws RrdException, IOException {
String consolFun = request.getConsolFun();
long fetchStart = request.getFetchStart();
long fetchEnd = request.getFetchEnd();
long resolution = request.getResolution();
Archive bestFullMatch = null, bestPartialMatch = null;
long bestStepDiff = 0, bestMatch = 0;
for (Archive archive : archives) {
if (archive.getConsolFun().equals(consolFun)) {
long arcStep = archive.getArcStep();
long arcStart = archive.getStartTime() - arcStep;
long arcEnd = archive.getEndTime();
long fullMatch = fetchEnd - fetchStart;
if (arcEnd >= fetchEnd && arcStart <= fetchStart) {
long tmpStepDiff = Math.abs(archive.getArcStep() - resolution);
if (tmpStepDiff < bestStepDiff || bestFullMatch == null) {
bestStepDiff = tmpStepDiff;
bestFullMatch = archive;
}
}
else {
long tmpMatch = fullMatch;
if (arcStart > fetchStart) {
tmpMatch -= (arcStart - fetchStart);
}
if (arcEnd < fetchEnd) {
tmpMatch -= (fetchEnd - arcEnd);
}
if (bestPartialMatch == null || bestMatch < tmpMatch) {
bestPartialMatch = archive;
bestMatch = tmpMatch;
}
}
}
}
if (bestFullMatch != null) {
return bestFullMatch;
}
else if (bestPartialMatch != null) {
return bestPartialMatch;
}
else {
throw new RrdException("RRD file does not contain RRA:" + consolFun + " archive");
}
}
/**
* Finds the archive that best matches to the start time (time period being start-time until now)
* and requested resolution.
*
* @param consolFun Consolidation function of the datasource.
* @param startTime Start time of the time period in seconds.
* @param resolution Requested fetch resolution.
* @return Reference to the best matching archive.
* @throws IOException Thrown in case of I/O related error.
*/
public Archive findStartMatchArchive(String consolFun, long startTime, long resolution) throws IOException {
long arcStep, diff;
int fallBackIndex = 0;
int arcIndex = -1;
long minDiff = Long.MAX_VALUE;
long fallBackDiff = Long.MAX_VALUE;
for (int i = 0; i < archives.length; i++) {
if (archives[i].getConsolFun().equals(consolFun)) {
arcStep = archives[i].getArcStep();
diff = Math.abs(resolution - arcStep);
// Now compare start time, see if this archive encompasses the requested interval
if (startTime >= archives[i].getStartTime()) {
if (diff == 0) // Best possible match either way
{
return archives[i];
}
else if (diff < minDiff) {
minDiff = diff;
arcIndex = i;
}
}
else if (diff < fallBackDiff) {
fallBackDiff = diff;
fallBackIndex = i;
}
}
}
return (arcIndex >= 0 ? archives[arcIndex] : archives[fallBackIndex]);
}
/**
* <p>Returns string representing complete internal RRD state. The returned
* string can be printed to <code>stdout</code> and/or used for debugging purposes.</p>
*
* @return String representing internal RRD state.
* @throws IOException Thrown in case of I/O related error.
*/
public synchronized String dump() throws IOException {
StringBuffer buffer = new StringBuffer();
buffer.append(header.dump());
for (Datasource datasource : datasources) {
buffer.append(datasource.dump());
}
for (Archive archive : archives) {
buffer.append(archive.dump());
}
return buffer.toString();
}
void archive(Datasource datasource, double value, long numUpdates)
throws IOException, RrdException {
int dsIndex = getDsIndex(datasource.getDsName());
for (Archive archive : archives) {
archive.archive(dsIndex, value, numUpdates);
}
}
/**
* <p>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.</p>
*
* @param dsName Data source name.
* @return Internal index of the given data source name in this RRD.
* @throws RrdException Thrown in case of JRobin related error (invalid data source name,
* for example)
* @throws IOException Thrown in case of I/O error.
*/
public int getDsIndex(String dsName) throws RrdException, IOException {
for (int i = 0; i < datasources.length; i++) {
if (datasources[i].getDsName().equals(dsName)) {
return i;
}
}
throw new RrdException("Unknown datasource name: " + dsName);
}
/**
* Checks presence of a specific datasource.
*
* @param dsName Datasource name to check
* @return <code>true</code> if datasource is present in this RRD, <code>false</code> 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;
}
/**
* <p>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.</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -