1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 public class RrdDef {
58
59
60
61 public static final long DEFAULT_STEP = 300L;
62
63
64
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
76
77
78
79
80
81
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
92
93
94
95
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
107
108
109
110
111
112
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
124
125
126
127 public String getPath() {
128 return path;
129 }
130
131
132
133
134
135
136 public long getStartTime() {
137 return startTime;
138 }
139
140
141
142
143
144
145 public long getStep() {
146 return step;
147 }
148
149
150
151
152
153
154 public void setPath(String path) {
155 this.path = path;
156 }
157
158
159
160
161
162
163 public void setStartTime(long startTime) {
164 this.startTime = startTime;
165 }
166
167
168
169
170
171
172 public void setStartTime(Date date) {
173 this.startTime = Util.getTimestamp(date);
174 }
175
176
177
178
179
180
181 public void setStartTime(Calendar gc) {
182 this.startTime = Util.getTimestamp(gc);
183 }
184
185
186
187
188
189
190 public void setStep(long step) {
191 this.step = step;
192 }
193
194
195
196
197
198
199
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
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
296
297
298
299
300 public void addDatasource(DsDef[] dsDefs) throws RrdException {
301 for (DsDef dsDef : dsDefs) {
302 addDatasource(dsDef);
303 }
304 }
305
306
307
308
309
310
311
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
322
323
324
325
326
327 public void addArchive(ArcDef[] arcDefs) throws RrdException {
328 for (ArcDef arcDef : arcDefs) {
329 addArchive(arcDef);
330 }
331 }
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
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
355
356
357
358
359
360
361
362
363
364
365
366
367
368
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
420
421
422
423 public DsDef[] getDsDefs() {
424 return dsDefs.toArray(new DsDef[0]);
425 }
426
427
428
429
430
431
432 public ArcDef[] getArcDefs() {
433 return arcDefs.toArray(new ArcDef[0]);
434 }
435
436
437
438
439
440
441 public int getDsCount() {
442 return dsDefs.size();
443 }
444
445
446
447
448
449
450 public int getArcCount() {
451 return arcDefs.size();
452 }
453
454
455
456
457
458
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
517
518
519
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
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();
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();
546 }
547 xml.closeTag();
548 xml.flush();
549 }
550
551
552
553
554
555
556
557 public String exportXmlTemplate() {
558 ByteArrayOutputStream out = new ByteArrayOutputStream();
559 exportXmlTemplate(out);
560 return out.toString();
561 }
562
563
564
565
566
567
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
577
578
579
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
593
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
601
602
603
604
605
606
607
608
609
610
611
612 public boolean equals(Object obj) {
613 if (obj == null || !(obj instanceof RrdDef)) {
614 return false;
615 }
616 RrdDef rrdDef2 = (RrdDef) obj;
617
618 if (step != rrdDef2.step) {
619 return false;
620 }
621
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
635 if (!matched) {
636 return false;
637 }
638 }
639
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
653 if (!matched) {
654 return false;
655 }
656 }
657
658 return true;
659 }
660
661
662
663
664 public void removeDatasources() {
665 dsDefs.clear();
666 }
667
668
669
670
671 public void removeArchives() {
672 arcDefs.clear();
673 }
674 }