View Javadoc

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-2005, by Sasa Markovic.
9    *
10   * Developers:    Sasa Markovic (saxon@jrobin.org)
11   *
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.io.ByteArrayOutputStream;
29  import java.io.FileOutputStream;
30  import java.io.IOException;
31  import java.io.OutputStream;
32  import java.util.*;
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 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   * <p/>
42   * <p>RRD definition (RrdDef object) consists of the following elements:</p>
43   * <p/>
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  	/**
59  	 * default RRD step to be used if not specified in constructor (300 seconds)
60  	 */
61  	public static final long DEFAULT_STEP = 300L;
62  	/**
63  	 * if not specified in constructor, starting timestamp will be set to the
64  	 * current timestamp plus DEFAULT_INITIAL_SHIFT seconds (-10)
65  	 */
66  	public static final long DEFAULT_INITIAL_SHIFT = -10L;
67  
68  	private String path;
69  	private long startTime = Util.getTime() + DEFAULT_INITIAL_SHIFT;
70  	private long step = DEFAULT_STEP;
71  	private ArrayList<DsDef> dsDefs = new ArrayList<DsDef>();
72  	private ArrayList<ArcDef> arcDefs = new ArrayList<ArcDef>();
73  
74  	/**
75  	 * <p>Creates new RRD definition object with the given path.
76  	 * When this object is passed to
77  	 * <code>RrdDb</code> constructor, new RRD will be created using the
78  	 * specified path. </p>
79  	 *
80  	 * @param path Path to new RRD.
81  	 * @throws RrdException Thrown if name is invalid (null or empty).
82  	 */
83  	public RrdDef(String path) throws RrdException {
84  		if (path == null || path.length() == 0) {
85  			throw new RrdException("No path specified");
86  		}
87  		this.path = path;
88  	}
89  
90  	/**
91  	 * <p>Creates new RRD definition object with the given path and step.</p>
92  	 *
93  	 * @param path Path to new RRD.
94  	 * @param step RRD step.
95  	 * @throws RrdException Thrown if supplied parameters are invalid.
96  	 */
97  	public RrdDef(String path, long step) throws RrdException {
98  		this(path);
99  		if (step <= 0) {
100 			throw new RrdException("Invalid RRD step specified: " + step);
101 		}
102 		this.step = step;
103 	}
104 
105 	/**
106 	 * <p>Creates new RRD definition object with the given path, starting timestamp
107 	 * and step.</p>
108 	 *
109 	 * @param path	  Path to new RRD.
110 	 * @param startTime RRD starting timestamp.
111 	 * @param step	  RRD step.
112 	 * @throws RrdException Thrown if supplied parameters are invalid.
113 	 */
114 	public RrdDef(String path, long startTime, long step) throws RrdException {
115 		this(path, step);
116 		if (startTime < 0) {
117 			throw new RrdException("Invalid RRD start time specified: " + startTime);
118 		}
119 		this.startTime = startTime;
120 	}
121 
122 	/**
123 	 * Returns path for the new RRD
124 	 *
125 	 * @return path to the new RRD which should be created
126 	 */
127 	public String getPath() {
128 		return path;
129 	}
130 
131 	/**
132 	 * Returns starting timestamp for the RRD that should be created.
133 	 *
134 	 * @return RRD starting timestamp
135 	 */
136 	public long getStartTime() {
137 		return startTime;
138 	}
139 
140 	/**
141 	 * Returns time step for the RRD that will be created.
142 	 *
143 	 * @return RRD step
144 	 */
145 	public long getStep() {
146 		return step;
147 	}
148 
149 	/**
150 	 * Sets path to RRD.
151 	 *
152 	 * @param path to new RRD.
153 	 */
154 	public void setPath(String path) {
155 		this.path = path;
156 	}
157 
158 	/**
159 	 * Sets RRD's starting timestamp.
160 	 *
161 	 * @param startTime starting timestamp.
162 	 */
163 	public void setStartTime(long startTime) {
164 		this.startTime = startTime;
165 	}
166 
167 	/**
168 	 * Sets RRD's starting timestamp.
169 	 *
170 	 * @param date starting date
171 	 */
172 	public void setStartTime(Date date) {
173 		this.startTime = Util.getTimestamp(date);
174 	}
175 
176 	/**
177 	 * Sets RRD's starting timestamp.
178 	 *
179 	 * @param gc starting date
180 	 */
181 	public void setStartTime(Calendar gc) {
182 		this.startTime = Util.getTimestamp(gc);
183 	}
184 
185 	/**
186 	 * Sets RRD's time step.
187 	 *
188 	 * @param step RRD time step.
189 	 */
190 	public void setStep(long step) {
191 		this.step = step;
192 	}
193 
194 	/**
195 	 * Adds single datasource definition represented with object of class <code>DsDef</code>.
196 	 *
197 	 * @param dsDef Datasource definition.
198 	 * @throws RrdException Thrown if new datasource definition uses already used data
199 	 *                      source name.
200 	 */
201 	public void addDatasource(DsDef dsDef) throws RrdException {
202 		if (dsDefs.contains(dsDef)) {
203 			throw new RrdException("Datasource already defined: " + dsDef.dump());
204 		}
205 		dsDefs.add(dsDef);
206 	}
207 
208 	/**
209 	 * <p>Adds single datasource to RRD definition by specifying its data source name, source type,
210 	 * heartbeat, minimal and maximal value. For the complete explanation of all data
211 	 * source definition parameters see RRDTool's
212 	 * <a href="../../../../man/rrdcreate.html" target="man">rrdcreate man page</a>.</p>
213 	 * <p/>
214 	 * <p><b>IMPORTANT NOTE:</b> If datasource name ends with '!', corresponding archives will never
215 	 * store NaNs as datasource values. In that case, NaN datasource values will be silently
216 	 * replaced with zeros by the framework.</p>
217 	 *
218 	 * @param dsName	Data source name.
219 	 * @param dsType	Data source type. Valid types are "COUNTER",
220 	 *                  "GAUGE", "DERIVE" and "ABSOLUTE" (these string constants are conveniently defined in
221 	 *                  the {@link DsTypes} class).
222 	 * @param heartbeat Data source heartbeat.
223 	 * @param minValue  Minimal acceptable value. Use <code>Double.NaN</code> if unknown.
224 	 * @param maxValue  Maximal acceptable value. Use <code>Double.NaN</code> if unknown.
225 	 * @throws RrdException Thrown if new datasource definition uses already used data
226 	 *                      source name.
227 	 */
228 	public void addDatasource(String dsName, String dsType, long heartbeat,
229 							  double minValue, double maxValue) throws RrdException {
230 		addDatasource(new DsDef(dsName, dsType, heartbeat, minValue, maxValue));
231 	}
232 
233 	/**
234 	 * Adds single datasource to RRD definition from a RRDTool-like
235 	 * datasource definition string. The string must have six elements separated with colons
236 	 * (:) in the following order:<p>
237 	 * <pre>
238 	 * DS:name:type:heartbeat:minValue:maxValue
239 	 * </pre>
240 	 * For example:</p>
241 	 * <pre>
242 	 * DS:input:COUNTER:600:0:U
243 	 * </pre>
244 	 * For more information on datasource definition parameters see <code>rrdcreate</code>
245 	 * man page.<p>
246 	 *
247 	 * @param rrdToolDsDef Datasource definition string with the syntax borrowed from RRDTool.
248 	 * @throws RrdException Thrown if invalid string is supplied.
249 	 */
250 	public void addDatasource(String rrdToolDsDef) throws RrdException {
251 		RrdException rrdException = new RrdException(
252 				"Wrong rrdtool-like datasource definition: " + rrdToolDsDef);
253 		StringTokenizer tokenizer = new StringTokenizer(rrdToolDsDef, ":");
254 		if (tokenizer.countTokens() != 6) {
255 			throw rrdException;
256 		}
257 		String[] tokens = new String[6];
258 		for (int curTok = 0; tokenizer.hasMoreTokens(); curTok++) {
259 			tokens[curTok] = tokenizer.nextToken();
260 		}
261 		if (!tokens[0].equalsIgnoreCase("DS")) {
262 			throw rrdException;
263 		}
264 		String dsName = tokens[1];
265 		String dsType = tokens[2];
266 		long dsHeartbeat;
267 		try {
268 			dsHeartbeat = Long.parseLong(tokens[3]);
269 		}
270 		catch (NumberFormatException nfe) {
271 			throw rrdException;
272 		}
273 		double minValue = Double.NaN;
274 		if (!tokens[4].equalsIgnoreCase("U")) {
275 			try {
276 				minValue = Double.parseDouble(tokens[4]);
277 			}
278 			catch (NumberFormatException nfe) {
279 				throw rrdException;
280 			}
281 		}
282 		double maxValue = Double.NaN;
283 		if (!tokens[5].equalsIgnoreCase("U")) {
284 			try {
285 				maxValue = Double.parseDouble(tokens[5]);
286 			}
287 			catch (NumberFormatException nfe) {
288 				throw rrdException;
289 			}
290 		}
291 		addDatasource(new DsDef(dsName, dsType, dsHeartbeat, minValue, maxValue));
292 	}
293 
294 	/**
295 	 * Adds data source definitions to RRD definition in bulk.
296 	 *
297 	 * @param dsDefs Array of data source definition objects.
298 	 * @throws RrdException Thrown if duplicate data source name is used.
299 	 */
300 	public void addDatasource(DsDef[] dsDefs) throws RrdException {
301 		for (DsDef dsDef : dsDefs) {
302 			addDatasource(dsDef);
303 		}
304 	}
305 
306 	/**
307 	 * Adds single archive definition represented with object of class <code>ArcDef</code>.
308 	 *
309 	 * @param arcDef Archive definition.
310 	 * @throws RrdException Thrown if archive with the same consolidation function
311 	 *                      and the same number of steps is already added.
312 	 */
313 	public void addArchive(ArcDef arcDef) throws RrdException {
314 		if (arcDefs.contains(arcDef)) {
315 			throw new RrdException("Archive already defined: " + arcDef.dump());
316 		}
317 		arcDefs.add(arcDef);
318 	}
319 
320 	/**
321 	 * Adds archive definitions to RRD definition in bulk.
322 	 *
323 	 * @param arcDefs Array of archive definition objects
324 	 * @throws RrdException Thrown if RRD definition already contains archive with
325 	 *                      the same consolidation function and the same number of steps.
326 	 */
327 	public void addArchive(ArcDef[] arcDefs) throws RrdException {
328 		for (ArcDef arcDef : arcDefs) {
329 			addArchive(arcDef);
330 		}
331 	}
332 
333 	/**
334 	 * Adds single archive definition by specifying its consolidation function, X-files factor,
335 	 * number of steps and rows. For the complete explanation of all archive
336 	 * definition parameters see RRDTool's
337 	 * <a href="../../../../man/rrdcreate.html" target="man">rrdcreate man page</a>.</p>
338 	 *
339 	 * @param consolFun Consolidation function. Valid values are "AVERAGE",
340 	 *                  "MIN", "MAX" and "LAST" (these constants are conveniently defined in the
341 	 *                  {@link ConsolFuns} class)
342 	 * @param xff	   X-files factor. Valid values are between 0 and 1.
343 	 * @param steps	 Number of archive steps
344 	 * @param rows	  Number of archive rows
345 	 * @throws RrdException Thrown if archive with the same consolidation function
346 	 *                      and the same number of steps is already added.
347 	 */
348 	public void addArchive(String consolFun, double xff, int steps, int rows)
349 			throws RrdException {
350 		addArchive(new ArcDef(consolFun, xff, steps, rows));
351 	}
352 
353 	/**
354 	 * Adds single archive to RRD definition from a RRDTool-like
355 	 * archive definition string. The string must have five elements separated with colons
356 	 * (:) in the following order:<p>
357 	 * <pre>
358 	 * RRA:consolidationFunction:XFilesFactor:steps:rows
359 	 * </pre>
360 	 * For example:</p>
361 	 * <pre>
362 	 * RRA:AVERAGE:0.5:10:1000
363 	 * </pre>
364 	 * For more information on archive definition parameters see <code>rrdcreate</code>
365 	 * man page.<p>
366 	 *
367 	 * @param rrdToolArcDef Archive definition string with the syntax borrowed from RRDTool.
368 	 * @throws RrdException Thrown if invalid string is supplied.
369 	 */
370 	public void addArchive(String rrdToolArcDef) throws RrdException {
371 		RrdException rrdException = new RrdException(
372 				"Wrong rrdtool-like archive definition: " + rrdToolArcDef);
373 		StringTokenizer tokenizer = new StringTokenizer(rrdToolArcDef, ":");
374 		if (tokenizer.countTokens() != 5) {
375 			throw rrdException;
376 		}
377 		String[] tokens = new String[5];
378 		for (int curTok = 0; tokenizer.hasMoreTokens(); curTok++) {
379 			tokens[curTok] = tokenizer.nextToken();
380 		}
381 		if (!tokens[0].equalsIgnoreCase("RRA")) {
382 			throw rrdException;
383 		}
384 		String consolFun = tokens[1];
385 		double xff;
386 		try {
387 			xff = Double.parseDouble(tokens[2]);
388 		}
389 		catch (NumberFormatException nfe) {
390 			throw rrdException;
391 		}
392 		int steps;
393 		try {
394 			steps = Integer.parseInt(tokens[3]);
395 		}
396 		catch (NumberFormatException nfe) {
397 			throw rrdException;
398 		}
399 		int rows;
400 		try {
401 			rows = Integer.parseInt(tokens[4]);
402 		}
403 		catch (NumberFormatException nfe) {
404 			throw rrdException;
405 		}
406 		addArchive(new ArcDef(consolFun, xff, steps, rows));
407 	}
408 
409 	void validate() throws RrdException {
410 		if (dsDefs.size() == 0) {
411 			throw new RrdException("No RRD datasource specified. At least one is needed.");
412 		}
413 		if (arcDefs.size() == 0) {
414 			throw new RrdException("No RRD archive specified. At least one is needed.");
415 		}
416 	}
417 
418 	/**
419 	 * Returns all data source definition objects specified so far.
420 	 *
421 	 * @return Array of data source definition objects
422 	 */
423 	public DsDef[] getDsDefs() {
424 		return dsDefs.toArray(new DsDef[0]);
425 	}
426 
427 	/**
428 	 * Returns all archive definition objects specified so far.
429 	 *
430 	 * @return Array of archive definition objects.
431 	 */
432 	public ArcDef[] getArcDefs() {
433 		return arcDefs.toArray(new ArcDef[0]);
434 	}
435 
436 	/**
437 	 * Returns number of defined datasources.
438 	 *
439 	 * @return Number of defined datasources.
440 	 */
441 	public int getDsCount() {
442 		return dsDefs.size();
443 	}
444 
445 	/**
446 	 * Returns number of defined archives.
447 	 *
448 	 * @return Number of defined archives.
449 	 */
450 	public int getArcCount() {
451 		return arcDefs.size();
452 	}
453 
454 	/**
455 	 * Returns string that represents all specified RRD creation parameters. Returned string
456 	 * has the syntax of RRDTool's <code>create</code> command.
457 	 *
458 	 * @return Dumped content of <code>RrdDb</code> object.
459 	 */
460 	public String dump() {
461 		StringBuffer buffer = new StringBuffer("create \"");
462 		buffer.append(path).append("\"");
463 		buffer.append(" --start ").append(getStartTime());
464 		buffer.append(" --step ").append(getStep()).append(" ");
465 		for (DsDef dsDef : dsDefs) {
466 			buffer.append(dsDef.dump()).append(" ");
467 		}
468 		for (ArcDef arcDef : arcDefs) {
469 			buffer.append(arcDef.dump()).append(" ");
470 		}
471 		return buffer.toString().trim();
472 	}
473 
474 	String getRrdToolCommand() {
475 		return dump();
476 	}
477 
478 	void removeDatasource(String dsName) throws RrdException {
479 		for (int i = 0; i < dsDefs.size(); i++) {
480 			DsDef dsDef = dsDefs.get(i);
481 			if (dsDef.getDsName().equals(dsName)) {
482 				dsDefs.remove(i);
483 				return;
484 			}
485 		}
486 		throw new RrdException("Could not find datasource named '" + dsName + "'");
487 	}
488 
489 	void saveSingleDatasource(String dsName) {
490 		Iterator<DsDef> it = dsDefs.iterator();
491 		while (it.hasNext()) {
492 			DsDef dsDef = it.next();
493 			if (!dsDef.getDsName().equals(dsName)) {
494 				it.remove();
495 			}
496 		}
497 	}
498 
499 	void removeArchive(String consolFun, int steps) throws RrdException {
500 		ArcDef arcDef = findArchive(consolFun, steps);
501 		if (!arcDefs.remove(arcDef)) {
502 			throw new RrdException("Could not remove archive " + consolFun + "/" + steps);
503 		}
504 	}
505 
506 	ArcDef findArchive(String consolFun, int steps) throws RrdException {
507 		for (ArcDef arcDef : arcDefs) {
508 			if (arcDef.getConsolFun().equals(consolFun) && arcDef.getSteps() == steps) {
509 				return arcDef;
510 			}
511 		}
512 		throw new RrdException("Could not find archive " + consolFun + "/" + steps);
513 	}
514 
515 	/**
516 	 * Exports RrdDef object to output stream in XML format. Generated XML code can be parsed
517 	 * with {@link RrdDefTemplate} class.
518 	 *
519 	 * @param out Output stream
520 	 */
521 	public void exportXmlTemplate(OutputStream out) {
522 		XmlWriter xml = new XmlWriter(out);
523 		xml.startTag("rrd_def");
524 		xml.writeTag("path", getPath());
525 		xml.writeTag("step", getStep());
526 		xml.writeTag("start", getStartTime());
527 		// datasources
528 		DsDef[] dsDefs = getDsDefs();
529 		for (DsDef dsDef : dsDefs) {
530 			xml.startTag("datasource");
531 			xml.writeTag("name", dsDef.getDsName());
532 			xml.writeTag("type", dsDef.getDsType());
533 			xml.writeTag("heartbeat", dsDef.getHeartbeat());
534 			xml.writeTag("min", dsDef.getMinValue(), "U");
535 			xml.writeTag("max", dsDef.getMaxValue(), "U");
536 			xml.closeTag(); // datasource
537 		}
538 		ArcDef[] arcDefs = getArcDefs();
539 		for (ArcDef arcDef : arcDefs) {
540 			xml.startTag("archive");
541 			xml.writeTag("cf", arcDef.getConsolFun());
542 			xml.writeTag("xff", arcDef.getXff());
543 			xml.writeTag("steps", arcDef.getSteps());
544 			xml.writeTag("rows", arcDef.getRows());
545 			xml.closeTag(); // archive
546 		}
547 		xml.closeTag(); // rrd_def
548 		xml.flush();
549 	}
550 
551 	/**
552 	 * Exports RrdDef object to string in XML format. Generated XML string can be parsed
553 	 * with {@link RrdDefTemplate} class.
554 	 *
555 	 * @return XML formatted string representing this RrdDef object
556 	 */
557 	public String exportXmlTemplate() {
558 		ByteArrayOutputStream out = new ByteArrayOutputStream();
559 		exportXmlTemplate(out);
560 		return out.toString();
561 	}
562 
563 	/**
564 	 * Exports RrdDef object to a file in XML format. Generated XML code can be parsed
565 	 * with {@link RrdDefTemplate} class.
566 	 *
567 	 * @param filePath Path to the file
568 	 */
569 	public void exportXmlTemplate(String filePath) throws IOException {
570 		FileOutputStream out = new FileOutputStream(filePath, false);
571 		exportXmlTemplate(out);
572 		out.close();
573 	}
574 
575 	/**
576 	 * Returns the number of storage bytes required to create RRD from this
577 	 * RrdDef object.
578 	 *
579 	 * @return Estimated byte count of the underlying RRD storage.
580 	 */
581 	public long getEstimatedSize() {
582 		int dsCount = dsDefs.size();
583 		int arcCount = arcDefs.size();
584 		int rowsCount = 0;
585 		for (ArcDef arcDef : arcDefs) {
586 			rowsCount += arcDef.getRows();
587 		}
588 		return calculateSize(dsCount, arcCount, rowsCount);
589 	}
590 
591 	static long calculateSize(int dsCount, int arcCount, int rowsCount) {
592 		// return 64L + 128L * dsCount + 56L * arcCount +
593 		//	20L * dsCount * arcCount + 8L * dsCount * rowsCount;
594 		return (24L + 48L * dsCount + 16L * arcCount +
595 				20L * dsCount * arcCount + 8L * dsCount * rowsCount) +
596 				(1L + 2L * dsCount + arcCount) * 2L * RrdPrimitive.STRING_LENGTH;
597 	}
598 
599 	/**
600 	 * Compares the current RrdDef with another. RrdDefs are considered equal if:<p>
601 	 * <ul>
602 	 * <li>RRD steps match
603 	 * <li>all datasources have exactly the same definition in both RrdDef objects (datasource names,
604 	 * types, heartbeat, min and max values must match)
605 	 * <li>all archives have exactly the same definition in both RrdDef objects (archive consolidation
606 	 * functions, X-file factors, step and row counts must match)
607 	 * </ul>
608 	 *
609 	 * @param obj The second RrdDef object
610 	 * @return true if RrdDefs match exactly, false otherwise
611 	 */
612 	public boolean equals(Object obj) {
613 		if (obj == null || !(obj instanceof RrdDef)) {
614 			return false;
615 		}
616 		RrdDef rrdDef2 = (RrdDef) obj;
617 		// check primary RRD step
618 		if (step != rrdDef2.step) {
619 			return false;
620 		}
621 		// check datasources
622 		DsDef[] dsDefs = getDsDefs(), dsDefs2 = rrdDef2.getDsDefs();
623 		if (dsDefs.length != dsDefs2.length) {
624 			return false;
625 		}
626 		for (DsDef dsDef : dsDefs) {
627 			boolean matched = false;
628 			for (DsDef dsDef2 : dsDefs2) {
629 				if (dsDef.exactlyEqual(dsDef2)) {
630 					matched = true;
631 					break;
632 				}
633 			}
634 			// this datasource could not be matched
635 			if (!matched) {
636 				return false;
637 			}
638 		}
639 		// check archives
640 		ArcDef[] arcDefs = getArcDefs(), arcDefs2 = rrdDef2.getArcDefs();
641 		if (arcDefs.length != arcDefs2.length) {
642 			return false;
643 		}
644 		for (ArcDef arcDef : arcDefs) {
645 			boolean matched = false;
646 			for (ArcDef arcDef2 : arcDefs2) {
647 				if (arcDef.exactlyEqual(arcDef2)) {
648 					matched = true;
649 					break;
650 				}
651 			}
652 			// this archive could not be matched
653 			if (!matched) {
654 				return false;
655 			}
656 		}
657 		// everything matches
658 		return true;
659 	}
660 
661 	/**
662 	 * Removes all datasource definitions.
663 	 */
664 	public void removeDatasources() {
665 		dsDefs.clear();
666 	}
667 
668 	/**
669 	 * Removes all RRA archive definitions.
670 	 */
671 	public void removeArchives() {
672 		arcDefs.clear();
673 	}
674 }