KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jrobin > core > RrdDef


1 /* ============================================================
2  * JRobin : Pure java implementation of RRDTool's functionality
3  * ============================================================
4  *
5  * Project Info: http://www.jrobin.org
6  * Project Lead: Sasa Markovic (saxon@jrobin.org);
7  *
8  * (C) Copyright 2003, by Sasa Markovic.
9  *
10  * Developers: Sasa Markovic (saxon@jrobin.org)
11  * Arne Vandamme (cobralord@jrobin.org)
12  *
13  * This library is free software; you can redistribute it and/or modify it under the terms
14  * of the GNU Lesser General Public License as published by the Free Software Foundation;
15  * either version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  * See the GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License along with this
22  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */

25
26 package org.jrobin.core;
27
28 import java.util.ArrayList JavaDoc;
29 import java.util.Date JavaDoc;
30 import java.util.GregorianCalendar JavaDoc;
31 import java.util.StringTokenizer JavaDoc;
32 import java.io.*;
33
34 /**
35  * <p>Class to represent definition of new Round Robin Database (RRD).
36  * Object of this class is used to create
37  * new RRD from scratch - pass its reference as a <code>RrdDb</code> constructor
38  * argument (see documentation for {@link org.jrobin.core.RrdDb RrdDb} class). <code>RrdDef</code>
39  * object <b>does not</b> actually create new RRD. It just holds all necessary
40  * information which will be used during the actual creation process</p>
41  *
42  * <p>RRD definition (RrdDef object) consists of the following elements:</p>
43  *
44  * <ul>
45  * <li> path to RRD that will be created
46  * <li> starting timestamp
47  * <li> step
48  * <li> one or more datasource definitions
49  * <li> one or more archive definitions
50  * </ul>
51  * <p>RrdDef provides API to set all these elements. For the complete explanation of all
52  * RRD definition parameters, see RRDTool's
53  * <a HREF="../../../../man/rrdcreate.html" target="man">rrdcreate man page</a>.</p>
54  *
55  * @author <a HREF="mailto:saxon@jrobin.org">Sasa Markovic</a>
56  */

57 public class RrdDef {
58     /** default RRD step to be used if not specified in constructor (300 seconds) */
59     public static final long DEFAULT_STEP = 300L;
60     /** if not specified in constructor, starting timestamp will be set to the
61      * current timestamp plus DEFAULT_INITIAL_SHIFT seconds (-10) */

62     public static final long DEFAULT_INITIAL_SHIFT = -10L;
63
64     private String JavaDoc path;
65     private long startTime = Util.getTime() + DEFAULT_INITIAL_SHIFT;
66     private long step = DEFAULT_STEP;
67     private ArrayList JavaDoc dsDefs = new ArrayList JavaDoc(), arcDefs = new ArrayList JavaDoc();
68
69     /**
70      * <p>Creates new RRD definition object with the given path.
71      * When this object is passed to
72      * <code>RrdDb</code> constructor, new RRD will be created using the
73      * specified path. </p>
74      * @param path Path to new RRD.
75      * @throws RrdException Thrown if name is invalid (null or empty).
76      */

77     public RrdDef(String JavaDoc path) throws RrdException {
78         if(path == null || path.length() == 0) {
79             throw new RrdException("No path specified");
80         }
81         this.path = path;
82     }
83
84     /**
85      * <p>Creates new RRD definition object with the given path and step.</p>
86      * @param path Path to new RRD.
87      * @param step RRD step.
88      * @throws RrdException Thrown if supplied parameters are invalid.
89      */

90     public RrdDef(String JavaDoc path, long step) throws RrdException {
91         this(path);
92         if(step <= 0) {
93             throw new RrdException("Invalid RRD step specified: " + step);
94         }
95         this.step = step;
96     }
97
98     /**
99      * <p>Creates new RRD definition object with the given path, starting timestamp
100      * and step.</p>
101      * @param path Path to new RRD.
102      * @param startTime RRD starting timestamp.
103      * @param step RRD step.
104      * @throws RrdException Thrown if supplied parameters are invalid.
105      */

106     public RrdDef(String JavaDoc path, long startTime, long step) throws RrdException {
107         this(path, step);
108         if(startTime < 0) {
109             throw new RrdException("Invalid RRD start time specified: " + startTime);
110         }
111         this.startTime = startTime;
112     }
113
114     /**
115      * Returns path for the new RRD
116      * @return path to the new RRD which should be created
117      */

118     public String JavaDoc getPath() {
119         return path;
120     }
121
122     /**
123      * Returns starting timestamp for the RRD that should be created.
124      * @return RRD starting timestamp
125      */

126     public long getStartTime() {
127         return startTime;
128     }
129
130     /**
131      * Returns time step for the RRD that will be created.
132      * @return RRD step
133      */

134     public long getStep() {
135         return step;
136     }
137
138     /**
139      * Sets path to RRD.
140      * @param path to new RRD.
141      */

142     public void setPath(String JavaDoc path) {
143         this.path = path;
144     }
145
146     /**
147      * Sets RRD's starting timestamp.
148      * @param startTime starting timestamp.
149      */

150     public void setStartTime(long startTime) {
151         this.startTime = startTime;
152     }
153
154     /**
155      * Sets RRD's starting timestamp.
156      * @param date starting date
157      */

158     public void setStartTime(Date JavaDoc date) {
159         this.startTime = Util.getTimestamp(date);
160     }
161
162     /**
163      * Sets RRD's starting timestamp.
164      * @param gc starting date
165      */

166     public void setStartTime(GregorianCalendar JavaDoc gc) {
167         this.startTime = Util.getTimestamp(gc);
168     }
169
170     /**
171      * Sets RRD's time step.
172      * @param step RRD time step.
173      */

174     public void setStep(long step) {
175         this.step = step;
176     }
177
178     /**
179      * Adds single datasource definition represented with object of class <code>DsDef</code>.
180      * @param dsDef Datasource definition.
181      * @throws RrdException Thrown if new datasource definition uses already used data
182      * source name.
183      */

184     public void addDatasource(DsDef dsDef) throws RrdException {
185         if(dsDefs.contains(dsDef)) {
186             throw new RrdException("Datasource already defined: " + dsDef.dump());
187         }
188         dsDefs.add(dsDef);
189     }
190
191     /**
192      * Adds single datasource to RRD definition by specifying its data source name, source type,
193      * heartbeat, minimal and maximal value. For the complete explanation of all data
194      * source definition parameters see RRDTool's
195      * <a HREF="../../../../man/rrdcreate.html" target="man">rrdcreate man page</a>.</p>
196      *
197      * @param dsName Data source name.
198      * @param dsType Data source type. Valid types are "COUNTER",
199      * "GAUGE", "DERIVE" and "ABSOLUTE".
200      * @param heartbeat Data source heartbeat.
201      * @param minValue Minimal acceptable value. Use <code>Double.NaN</code> if unknown.
202      * @param maxValue Maximal acceptable value. Use <code>Double.NaN</code> if unknown.
203      * @throws RrdException Thrown if new datasource definition uses already used data
204      * source name.
205      */

206     public void addDatasource(String JavaDoc dsName, String JavaDoc dsType, long heartbeat,
207         double minValue, double maxValue) throws RrdException {
208         addDatasource(new DsDef(dsName, dsType, heartbeat, minValue, maxValue));
209     }
210
211     /**
212      * Adds single datasource to RRD definition from a RRDTool-like
213      * datasource definition string. The string must have six elements separated with colons
214      * (:) in the following order:<p>
215      * <pre>
216      * DS:name:type:heartbeat:minValue:maxValue
217      * </pre>
218      * For example:</p>
219      * <pre>
220      * DS:input:COUNTER:600:0:U
221      * </pre>
222      * For more information on datasource definition parameters see <code>rrdcreate</code>
223      * man page.<p>
224      * @param rrdToolDsDef Datasource definition string with the syntax borrowed from RRDTool.
225      * @throws RrdException Thrown if invalid string is supplied.
226      */

227     public void addDatasource(String JavaDoc rrdToolDsDef) throws RrdException {
228         RrdException rrdException = new RrdException(
229             "Wrong rrdtool-like datasource definition: " + rrdToolDsDef);
230         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(rrdToolDsDef, ":");
231         if (tokenizer.countTokens() != 6) {
232             throw rrdException;
233         }
234         String JavaDoc[] tokens = new String JavaDoc[6];
235         for (int curTok = 0; tokenizer.hasMoreTokens(); curTok++) {
236             tokens[curTok] = tokenizer.nextToken();
237         }
238         if (!tokens[0].equalsIgnoreCase("DS")) {
239             throw rrdException;
240         }
241         String JavaDoc dsName = tokens[1];
242         String JavaDoc dsType = tokens[2];
243         long dsHeartbeat;
244         try {
245             dsHeartbeat = Long.parseLong(tokens[3]);
246         }
247         catch(NumberFormatException JavaDoc nfe) {
248             throw rrdException;
249         }
250         double minValue = Double.NaN;
251         if(!tokens[4].equalsIgnoreCase("U")) {
252             try {
253                 minValue = Double.parseDouble(tokens[4]);
254             }
255             catch(NumberFormatException JavaDoc nfe) {
256                 throw rrdException;
257             }
258         }
259         double maxValue = Double.NaN;
260         if(!tokens[5].equalsIgnoreCase("U")) {
261             try {
262                 maxValue = Double.parseDouble(tokens[5]);
263             }
264             catch(NumberFormatException JavaDoc nfe) {
265                 throw rrdException;
266             }
267         }
268         addDatasource(new DsDef(dsName, dsType, dsHeartbeat, minValue, maxValue));
269     }
270
271     /**
272      * Adds data source definitions to RRD definition in bulk.
273      * @param dsDefs Array of data source definition objects.
274      * @throws RrdException Thrown if duplicate data source name is used.
275      */

276     public void addDatasource(DsDef[] dsDefs) throws RrdException {
277         for(int i = 0; i < dsDefs.length; i++) {
278             addDatasource(dsDefs[i]);
279         }
280     }
281
282     /**
283      * Adds single archive definition represented with object of class <code>ArcDef</code>.
284      * @param arcDef Archive definition.
285      * @throws RrdException Thrown if archive with the same consolidation function
286      * and the same number of steps is already added.
287      */

288     public void addArchive(ArcDef arcDef) throws RrdException {
289         if(arcDefs.contains(arcDef)) {
290             throw new RrdException("Archive already defined: " + arcDef.dump());
291         }
292         arcDefs.add(arcDef);
293     }
294
295     /**
296      * Adds archive definitions to RRD definition in bulk.
297      * @param arcDefs Array of archive definition objects
298      * @throws RrdException Thrown if RRD definition already contains archive with
299      * the same consolidation function and the same number of steps.
300      */

301     public void addArchive(ArcDef[] arcDefs) throws RrdException {
302         for(int i = 0; i < arcDefs.length; i++) {
303             addArchive(arcDefs[i]);
304         }
305     }
306
307     /**
308      * Adds single archive definition by specifying its consolidation function, X-files factor,
309      * number of steps and rows. For the complete explanation of all archive
310      * definition parameters see RRDTool's
311      * <a HREF="../../../../man/rrdcreate.html" target="man">rrdcreate man page</a>.</p>
312      * @param consolFun Consolidation function. Valid values are "AVERAGE",
313      * "MIN", "MAX" and "LAST"
314      * @param xff X-files factor. Valid values are between 0 and 1.
315      * @param steps Number of archive steps
316      * @param rows Number of archive rows
317      * @throws RrdException Thrown if archive with the same consolidation function
318      * and the same number of steps is already added.
319      */

320     public void addArchive(String JavaDoc consolFun, double xff, int steps, int rows)
321         throws RrdException {
322         addArchive(new ArcDef(consolFun, xff, steps, rows));
323     }
324
325     /**
326      * Adds single archive to RRD definition from a RRDTool-like
327      * archive definition string. The string must have five elements separated with colons
328      * (:) in the following order:<p>
329      * <pre>
330      * RRA:consolidationFunction:XFilesFactor:steps:rows
331      * </pre>
332      * For example:</p>
333      * <pre>
334      * RRA:AVERAGE:0.5:10:1000
335      * </pre>
336      * For more information on archive definition parameters see <code>rrdcreate</code>
337      * man page.<p>
338      * @param rrdToolArcDef Archive definition string with the syntax borrowed from RRDTool.
339      * @throws RrdException Thrown if invalid string is supplied.
340      */

341     public void addArchive(String JavaDoc rrdToolArcDef) throws RrdException {
342         RrdException rrdException = new RrdException(
343             "Wrong rrdtool-like archive definition: " + rrdToolArcDef);
344         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(rrdToolArcDef, ":");
345         if (tokenizer.countTokens() != 5) {
346             throw rrdException;
347         }
348         String JavaDoc[] tokens = new String JavaDoc[5];
349         for (int curTok = 0; tokenizer.hasMoreTokens(); curTok++) {
350             tokens[curTok] = tokenizer.nextToken();
351         }
352         if (!tokens[0].equalsIgnoreCase("RRA")) {
353             throw rrdException;
354         }
355         String JavaDoc consolFun = tokens[1];
356         double xff;
357         try {
358             xff = Double.parseDouble(tokens[2]);
359         }
360         catch(NumberFormatException JavaDoc nfe) {
361             throw rrdException;
362         }
363         int steps;
364         try {
365             steps = Integer.parseInt(tokens[3]);
366         }
367         catch(NumberFormatException JavaDoc nfe) {
368             throw rrdException;
369         }
370         int rows;
371         try {
372             rows = Integer.parseInt(tokens[4]);
373         }
374         catch(NumberFormatException JavaDoc nfe) {
375             throw rrdException;
376         }
377         addArchive(new ArcDef(consolFun, xff, steps, rows));
378     }
379
380     void validate() throws RrdException {
381         if(dsDefs.size() == 0) {
382             throw new RrdException("No RRD datasource specified. At least one is needed.");
383         }
384         if(arcDefs.size() == 0) {
385             throw new RrdException("No RRD archive specified. At least one is needed.");
386         }
387     }
388
389     /**
390      * Returns all data source definition objects specified so far.
391      * @return Array of data source definition objects
392      */

393     public DsDef[] getDsDefs() {
394         return (DsDef[]) dsDefs.toArray(new DsDef[0]);
395     }
396
397     /**
398      * Returns all archive definition objects specified so far.
399      * @return Array of archive definition objects.
400      */

401     public ArcDef[] getArcDefs() {
402         return (ArcDef[]) arcDefs.toArray(new ArcDef[0]);
403     }
404
405     /**
406      * Returns number of defined datasources.
407      * @return Number of defined datasources.
408      */

409     public int getDsCount() {
410         return dsDefs.size();
411     }
412
413     /**
414      * Returns number of defined archives.
415      * @return Number of defined archives.
416      */

417     public int getArcCount() {
418         return arcDefs.size();
419     }
420
421     /**
422      * Returns string that represents all specified RRD creation parameters. Returned string
423      * has the syntax of RRDTool's <code>create</code> command.
424      * @return Dumped content of <code>RrdDb</code> object.
425      */

426     public String JavaDoc dump() {
427         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc("create \"");
428         buffer.append(path + "\"");
429         buffer.append(" --start " + getStartTime());
430         buffer.append(" --step " + getStep() + " ");
431         for(int i = 0; i < dsDefs.size(); i++) {
432             DsDef dsDef = (DsDef) dsDefs.get(i);
433             buffer.append(dsDef.dump() + " ");
434         }
435         for(int i = 0; i < arcDefs.size(); i++) {
436             ArcDef arcDef = (ArcDef) arcDefs.get(i);
437             buffer.append(arcDef.dump() + " ");
438         }
439         return buffer.toString().trim();
440     }
441
442     String JavaDoc getRrdToolCommand() {
443         return dump();
444     }
445
446     void removeDatasource(String JavaDoc dsName) throws RrdException {
447         for(int i = 0; i < dsDefs.size(); i++) {
448             DsDef dsDef = (DsDef) dsDefs.get(i);
449             if(dsDef.getDsName().equals(dsName)) {
450                 dsDefs.remove(i);
451                 return;
452             }
453         }
454         throw new RrdException("Could not find datasource named '" + dsName + "'");
455     }
456
457     void removeArchive(String JavaDoc consolFun, int steps) throws RrdException {
458         ArcDef arcDef = findArchive(consolFun, steps);
459         if(!arcDefs.remove(arcDef)) {
460             throw new RrdException("Could not remove archive " + consolFun + "/" + steps);
461         }
462     }
463
464     ArcDef findArchive(String JavaDoc consolFun, int steps) throws RrdException {
465         for(int i = 0; i < arcDefs.size(); i++) {
466             ArcDef arcDef = (ArcDef) arcDefs.get(i);
467             if(arcDef.getConsolFun().equals(consolFun) && arcDef.getSteps() == steps) {
468                 return arcDef;
469             }
470         }
471         throw new RrdException("Could not find archive " + consolFun + "/" + steps);
472     }
473
474     /**
475      * Exports RrdDef object to output stream in XML format. Generated XML code can be parsed
476      * with {@link RrdDefTemplate} class.
477      * @param out Output stream
478      */

479     public void exportXmlTemplate(OutputStream out) {
480         XmlWriter xml = new XmlWriter(out);
481         xml.startTag("rrd_def");
482         xml.writeTag("path", getPath());
483         xml.writeTag("step", getStep());
484         xml.writeTag("start", getStartTime());
485         // datasources
486
DsDef[] dsDefs = getDsDefs();
487         for(int i = 0; i < dsDefs.length; i++) {
488             xml.startTag("datasource");
489             xml.writeTag("name", dsDefs[i].getDsName());
490             xml.writeTag("type", dsDefs[i].getDsType());
491             xml.writeTag("heartbeat", dsDefs[i].getHeartbeat());
492             xml.writeTag("min", dsDefs[i].getMinValue(), "U");
493             xml.writeTag("max", dsDefs[i].getMaxValue(), "U");
494             xml.closeTag(); // datasource
495
}
496         ArcDef[] arcDefs = getArcDefs();
497         for(int i = 0; i < arcDefs.length; i++) {
498             xml.startTag("archive");
499             xml.writeTag("cf", arcDefs[i].getConsolFun());
500             xml.writeTag("xff", arcDefs[i].getXff());
501             xml.writeTag("steps", arcDefs[i].getSteps());
502             xml.writeTag("rows", arcDefs[i].getRows());
503             xml.closeTag(); // archive
504
}
505         xml.closeTag(); // rrd_def
506
xml.flush();
507     }
508
509     /**
510      * Exports RrdDef object to string in XML format. Generated XML string can be parsed
511      * with {@link RrdDefTemplate} class.
512      * @return XML formatted string representing this RrdDef object
513      */

514     public String JavaDoc exportXmlTemplate() {
515         ByteArrayOutputStream out = new ByteArrayOutputStream();
516         exportXmlTemplate(out);
517         return out.toString();
518     }
519
520     /**
521      * Exports RrdDef object to a file in XML format. Generated XML code can be parsed
522      * with {@link RrdDefTemplate} class.
523      * @param filePath Path to the file
524      */

525     public void exportXmlTemplate(String JavaDoc filePath) throws IOException {
526         FileOutputStream out = new FileOutputStream(filePath, false);
527         exportXmlTemplate(out);
528         out.close();
529     }
530
531     /**
532      * Returns the number of storage bytes required to create RRD from this
533      * RrdDef object.
534      * @return Estimated byte count of the underlying RRD storage.
535      */

536     public long getEstimatedSize() {
537         int dsCount = dsDefs.size();
538         int arcCount = arcDefs.size();
539         int rowsCount = 0;
540         for(int i = 0; i < arcDefs.size(); i++) {
541             ArcDef arcDef = (ArcDef) arcDefs.get(i);
542             rowsCount += arcDef.getRows();
543         }
544         return calculateSize(dsCount, arcCount, rowsCount);
545     }
546
547     static long calculateSize(int dsCount, int arcCount, int rowsCount) {
548         return 64L + 128L * dsCount + 56L * arcCount +
549             20L * dsCount * arcCount + 8L * dsCount * rowsCount;
550     }
551
552     /**
553      * Compares the current RrdDef with another. RrdDefs are considered equal if:<p>
554      *<ul>
555      * <li>RRD steps match
556      * <li>all datasources have exactly the same definition in both RrdDef objects (datasource names,
557      * types, heartbeat, min and max values must match)
558      * <li>all archives have exactly the same definition in both RrdDef objects (archive consolidation
559      * functions, X-file factors, step and row counts must match)
560      * </ul>
561      * @param obj The second RrdDef object
562      * @return true if RrdDefs match exactly, false otherwise
563      */

564     public boolean equals(Object JavaDoc obj) {
565         if(obj == null || !(obj instanceof RrdDef)) {
566             return false;
567         }
568         RrdDef rrdDef2 = (RrdDef) obj;
569         // check primary RRD step
570
if(step != rrdDef2.step) {
571             return false;
572         }
573         // check datasources
574
DsDef[] dsDefs = getDsDefs(), dsDefs2 = rrdDef2.getDsDefs();
575         if(dsDefs.length != dsDefs2.length) {
576             return false;
577         }
578         for(int i = 0; i < dsDefs.length; i++) {
579             boolean matched = false;
580             for(int j = 0; j < dsDefs2.length; j++) {
581                 if(dsDefs[i].exactlyEqual(dsDefs2[j])) {
582                     matched = true;
583                     break;
584                 }
585             }
586             // this datasource could not be matched
587
if(!matched) {
588                 return false;
589             }
590         }
591         // check archives
592
ArcDef[] arcDefs = getArcDefs(), arcDefs2 = rrdDef2.getArcDefs();
593         if(arcDefs.length != arcDefs2.length) {
594             return false;
595         }
596         for(int i = 0; i < arcDefs.length; i++) {
597             boolean matched = false;
598             for(int j = 0; j < arcDefs2.length; j++) {
599                 if(arcDefs[i].exactlyEqual(arcDefs2[j])) {
600                     matched = true;
601                     break;
602                 }
603             }
604             // this archive could not be matched
605
if(!matched) {
606                 return false;
607             }
608         }
609         // everything matches
610
return true;
611     }
612 }
613
Popular Tags