Fawkes API Fawkes Development Version
rrd_descriptions.cpp
1
2/***************************************************************************
3 * rrd_descriptions.cpp - Fawkes RRD descriptions
4 *
5 * Created: Sat Dec 18 11:41:32 2010
6 * Copyright 2006-2011 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version. A runtime exception applies to
14 * this software (see LICENSE.GPL_WRE file mentioned below for details).
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22 */
23
24#include <core/exceptions/software.h>
25#include <core/exceptions/system.h>
26#include <plugins/rrd/aspect/rrd_descriptions.h>
27#include <plugins/rrd/aspect/rrd_manager.h>
28#include <utils/misc/string_conversions.h>
29
30#include <cfloat>
31#include <cstdio>
32#include <cstdlib>
33#include <cstring>
34
35namespace fawkes {
36
37/** @class RRDDataSource <plugins/rrd/aspect/rrd_descriptions.h>
38 * Class to represent a RRD data source.
39 * @author Tim Niemueller
40 */
41
42/** Use for unknown min or max values */
43const float RRDDataSource::UNKNOWN = FLT_MIN;
44
45/** Constructor for regular data source.
46 * @param name name of the data source
47 * @param type type of the data source, may not be COMPUTE.
48 * @param heartbeat Number of seconds after which a new value must be received
49 * before the value is considered to be unknown.
50 * @param min minimum value, use UNKNOWN constant if not known
51 * @param max maximum value, use UNKNOWN constant if not known
52 */
54 Type type,
55 unsigned int heartbeat,
56 float min,
57 float max)
58: name_(strdup(name)),
59 type_(type),
60 heartbeat_(heartbeat),
61 min_(min),
62 max_(max),
63 rpn_expression_(NULL),
64 string_(NULL)
65{
66 if (type_ == COMPUTE) {
67 throw IllegalArgumentException("Non-compute data source ctor used with "
68 "COMPUTE type for DS %s",
69 name);
70 }
71}
72
73/** Constructor for expression RRDs.
74 * @param name name of the data source
75 * @param rpn_expression RPN expression
76 */
77RRDDataSource::RRDDataSource(const char *name, const char *rpn_expression)
78: name_(strdup(name)),
79 type_(COMPUTE),
80 heartbeat_(300),
81 min_(UNKNOWN),
82 max_(UNKNOWN),
83 rpn_expression_(strdup(rpn_expression)),
84 string_(NULL)
85{
86}
87
88/** Copy constructor.
89 * @param other other instance to copy
90 */
92: name_(strdup(other.name_)),
93 type_(other.type_),
94 heartbeat_(other.heartbeat_),
95 min_(other.min_),
96 max_(other.max_),
97 rpn_expression_(other.rpn_expression_ ? strdup(other.rpn_expression_) : 0),
98 string_(NULL)
99{
100}
101
102/** Destructor. */
104{
105 if (string_)
106 free(string_);
107 if (name_)
108 free(name_);
109 if (rpn_expression_)
110 free(rpn_expression_);
111}
112
113/** Assignment operator.
114 * @param other Instance to copy data from.
115 * @return reference to this instance
116 */
119{
120 if (string_)
121 free(string_);
122 if (name_)
123 free(name_);
124 if (rpn_expression_)
125 free(rpn_expression_);
126 string_ = NULL;
127 rpn_expression_ = NULL;
128 name_ = strdup(other.name_);
129 type_ = other.type_;
130 heartbeat_ = other.heartbeat_;
131 min_ = other.min_;
132 max_ = other.max_;
133 if (other.rpn_expression_)
134 rpn_expression_ = strdup(other.rpn_expression_);
135
136 return *this;
137}
138
139/** Get string reprensetation.
140 * @return string representation suitable to be bassed to rrd_create().
141 */
142const char *
144{
145 if (!string_) {
146 if (type_ == COMPUTE) {
147 if (asprintf(&string_, "DS:%s:COMPUTE:%s", name_, rpn_expression_) == -1) {
148 throw OutOfMemoryException("Failed to create DS string for %s", name_);
149 }
150 } else {
151 const char *type_string;
152 switch (type_) {
153 case COUNTER: type_string = "COUNTER"; break;
154 case DERIVE: type_string = "DERIVE"; break;
155 case ABSOLUTE: type_string = "ABSOLUTE"; break;
156 default: type_string = "GAUGE"; break;
157 }
158 char min_s[32];
159 char max_s[32];
160 if (min_ == UNKNOWN) {
161 strcpy(min_s, "U");
162 } else {
163 snprintf(min_s, 32, "%f", min_);
164 }
165 if (max_ == UNKNOWN) {
166 strcpy(max_s, "U");
167 } else {
168 snprintf(max_s, 32, "%f", max_);
169 }
170 if (asprintf(&string_, "DS:%s:%s:%u:%s:%s", name_, type_string, heartbeat_, min_s, max_s)
171 == -1) {
172 throw OutOfMemoryException("Failed to create DS string for %s", name_);
173 }
174 }
175 }
176
177 return string_;
178}
179
180/** @class RRDArchive <plugins/rrd/aspect/rrd_descriptions.h>
181 * RRD Archive description.
182 * @author Tim Niemueller
183 */
184
185/** Constructor.
186 * @param cf consolidation function
187 * @param xff The xfiles factor defines what part of a consolidation interval
188 * may be made up from *UNKNOWN* data while the consolidated value is still
189 * regarded as known. It is given as the ratio of allowed *UNKNOWN* PDPs to
190 * the number of PDPs in the interval. Thus, it ranges from 0 to 1 (exclusive).
191 * @param steps defines how many of these primary data points are used to build
192 * a consolidated data point which then goes into the archive.
193 * @param rows defines how many generations of data values are kept in an RRA.
194 * Obviously, this has to be greater than zero.
195 */
196RRDArchive::RRDArchive(ConsolidationFunction cf, float xff, unsigned int steps, unsigned int rows)
197: cf_(cf), xff_(xff), steps_(steps), rows_(rows), string_(NULL)
198{
199}
200
201/** Copy constructor.
202 * @param rra instance to copy
203 */
205: cf_(rra.cf_), xff_(rra.xff_), steps_(rra.steps_), rows_(rra.rows_), string_(NULL)
206{
207}
208
209/** Destructor. */
211{
212 if (string_)
213 free(string_);
214}
215
216/** Assignment operator.
217 * @param rra instance to copy from
218 * @return reference to this instance
219 */
222{
223 if (string_)
224 free(string_);
225 string_ = NULL;
226 cf_ = rra.cf_;
227 xff_ = rra.xff_;
228 steps_ = rra.steps_;
229 rows_ = rra.rows_;
230 return *this;
231}
232
233/** Get string representation.
234 * @return string representation suitable to be passed to rrd_create().
235 */
236const char *
238{
239 if (!string_) {
240 const char *cf_string;
241 switch (cf_) {
242 case MIN: cf_string = "MIN"; break;
243 case MAX: cf_string = "MAX"; break;
244 case LAST: cf_string = "LAST"; break;
245 default: cf_string = "AVERAGE"; break;
246 }
247 if (asprintf(&string_, "RRA:%s:%f:%u:%u", cf_string, xff_, steps_, rows_) == -1) {
248 throw OutOfMemoryException("Failed to create RRA string");
249 }
250 }
251
252 return string_;
253}
254
255/** Convert consolidation function type to string.
256 * @param cf consolidation function type
257 * @return string representation of @p cf, suitable for RRA lines.
258 */
259const char *
261{
262 switch (cf) {
263 case RRDArchive::MIN: return "MIN"; break;
264 case RRDArchive::MAX: return "MAX"; break;
265 case RRDArchive::LAST: return "LAST"; break;
266 default: return "AVERAGE"; break;
267 }
268}
269
270/** @class RRDDefinition <plugins/rrd/aspect/rrd_descriptions.h>
271 * RRD Definition.
272 * This class describes everything required to create an RRD file.
273 * It does not represent all the options rrdtool provides, but a reasonable
274 * subset.
275 * @author Tim Niemueller
276 */
277
278/** Constructor with default RRAs.
279 * This creates the RRD definition with the default RRAs produced by
280 * get_default_rra().
281 * @param name RRD name
282 * @param ds data sources
283 * @param step_sec Specifies the base interval in seconds with which data
284 * will be fed into the RRD.
285 * @param recreate if true existing RRD files will be overwritten, otherwise
286 * data is appended.
287 */
289 std::vector<RRDDataSource> &ds,
290 unsigned int step_sec,
291 bool recreate)
292: name_(strdup(name)),
293 step_sec_(step_sec),
294 recreate_(recreate),
295 ds_(ds),
296 rra_(get_default_rra()),
297 filename_(NULL),
298 rrd_manager_(NULL)
299{
300}
301
302/** Constructor.
303 * @param name RRD name
304 * @param ds data sources
305 * @param rra RRAs for this RRD.
306 * @param step_sec Specifies the base interval in seconds with which data
307 * will be fed into the RRD.
308 * @param recreate if true existing RRD files will be overwritten, otherwise
309 * data is appended.
310 */
312 std::vector<RRDDataSource> &ds,
313 std::vector<RRDArchive> & rra,
314 unsigned int step_sec,
315 bool recreate)
316: name_(strdup(name)),
317 step_sec_(step_sec),
318 recreate_(recreate),
319 ds_(ds),
320 rra_(rra),
321 filename_(NULL),
322 rrd_manager_(NULL)
323{
324}
325
326/** Copy constructor.
327 * @param other instance to clone
328 */
330: name_(strdup(other.name_)),
331 step_sec_(other.step_sec_),
332 recreate_(other.recreate_),
333 ds_(other.ds_),
334 rra_(other.rra_),
335 filename_(other.filename_ ? strdup(other.filename_) : 0),
336 rrd_manager_(NULL)
337{
338}
339
340/** Assignment operator.
341 * @param other other instance to copy from
342 * @return reference to this instance.
343 */
346{
347 if (name_)
348 free(name_);
349 if (filename_)
350 free(filename_);
351 if (rrd_manager_)
352 rrd_manager_->remove_rrd(this);
353 filename_ = NULL;
354 rrd_manager_ = NULL;
355 name_ = strdup(other.name_);
356 step_sec_ = other.step_sec_;
357 recreate_ = other.recreate_;
358 ds_ = other.ds_;
359 rra_ = other.rra_;
360 if (other.filename_)
361 filename_ = strdup(other.filename_);
362 return *this;
363}
364
365/** Destructor. */
367{
368 if (rrd_manager_)
369 rrd_manager_->remove_rrd(this);
370
371 if (name_)
372 free(name_);
373 if (filename_)
374 free(filename_);
375}
376
377/** Get default RRAs. They correspond to the following and assume a
378 * 10 second step size.
379 * @code
380 * "RRA:AVERAGE:0.5:1:720" # 2 hours of 10 sec averages
381 * "RRA:AVERAGE:0.5:3:1680" # 12 hours of 30 sec averages
382 * "RRA:AVERAGE:0.5:30:456" # 1 day of 5 min averages
383 * "RRA:AVERAGE:0.5:180:412" # 7 days of 30 min averages
384 * "RRA:AVERAGE:0.5:720:439" # 4 weeks of 2 hour averages
385 * "RRA:AVERAGE:0.5:8640:402" # 1 year of 1 day averages
386 * "RRA:MIN:0.5:1:720"
387 * "RRA:MIN:0.5:3:1680"
388 * "RRA:MIN:0.5:30:456"
389 * "RRA:MIN:0.5:180:412"
390 * "RRA:MIN:0.5:720:439"
391 * "RRA:MIN:0.5:8640:402"
392 * "RRA:MAX:0.5:1:720"
393 * "RRA:MAX:0.5:3:1680"
394 * "RRA:MAX:0.5:30:456"
395 * "RRA:MAX:0.5:180:412"
396 * "RRA:MAX:0.5:720:439"
397 * "RRA:MAX:0.5:8640:402"
398 * @endcode
399 * @return vector of RRDArchive representing the described RRAs.
400 */
401const std::vector<RRDArchive>
403{
404 std::vector<RRDArchive> rv;
405 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 1, 720));
406 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 3, 1680));
407 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 30, 456));
408 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 180, 412));
409 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 720, 439));
410 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 8640, 402));
411 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 1, 720));
412 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 3, 1680));
413 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 30, 456));
414 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 180, 412));
415 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 720, 439));
416 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 8640, 402));
417 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 1, 720));
418 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 3, 1680));
419 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 30, 456));
420 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 180, 412));
421 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 720, 439));
422 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 8640, 402));
423 return rv;
424}
425
426/** Find data source index.
427 * @param ds_name name of the data source
428 * @return index of found data source
429 * @exception Exception thrown if the data source could not be found
430 */
431size_t
432RRDDefinition::find_ds_index(const char *ds_name) const
433{
434 for (size_t i = 0; i < ds_.size(); ++i) {
435 if (strcmp(ds_[i].get_name(), ds_name) == 0)
436 return i;
437 }
438
439 throw Exception("Data source name %s not found", ds_name);
440}
441
442/** Set filename.
443 * This can be done only once. Do not do this manually, rather let the RRDManager
444 * handle this!
445 * @param filename new filename, should be absolute, otherwise considered
446 * relative to current working directory.
447 */
448void
449RRDDefinition::set_filename(const char *filename)
450{
451 if (filename_) {
452 throw Exception("Graph definition %s: filename has already been set!", name_);
453 }
454 filename_ = strdup(filename);
455}
456
457/** Set RRD manager.
458 * This can be done only once. Do not do this manually, rather let the RRDManager
459 * handle this! The RRD manager is used to unregister this RRD if it is deleted.
460 * This is a precaution to avoid dangling RRDs.
461 * @param rrd_manager RRD manager to use
462 */
463void
465{
466 if (rrd_manager_) {
467 throw Exception("RRD definition %s: RRD manager has already been set", name_);
468 }
469 rrd_manager_ = rrd_manager;
470}
471
472/** @class RRDGraphDataDefinition <plugins/rrd/aspect/rrd_descriptions.h>
473 * Represent data definition in graph arguments.
474 * @author Tim Niemueller
475 * Currently supports only DEF and CDEF definitions.
476 */
477
478/** DEF constructor.
479 * @param name name of the graph data source
480 * @param cf consolidation function to apply if needed
481 * @param rrd_def RRD definition to use
482 * @param ds_name data source name in RRD, @p rrd_def will be queried for the
483 * data source. If ds_name is NULL, @p name will be used as the data source name.
484 */
487 const RRDDefinition * rrd_def,
488 const char * ds_name)
489: name_(strdup(name)),
490 rrd_def_(rrd_def),
491 ds_name_(ds_name ? strdup(ds_name) : strdup(name)),
492 rpn_expression_(NULL),
493 cf_(cf),
494 string_(NULL)
495{
496}
497
498/** CDEF constructor.
499 * @param name name of the graph data source
500 * @param rpn_expression RPN expression
501 */
502RRDGraphDataDefinition::RRDGraphDataDefinition(const char *name, const char *rpn_expression)
503: name_(strdup(name)),
504 rrd_def_(0),
505 ds_name_(NULL),
506 rpn_expression_(strdup(rpn_expression)),
507 cf_(RRDArchive::AVERAGE),
508 string_(NULL)
509{
510}
511
512/** Copy constructor.
513 * @param other instance to clone
514 */
516: name_(strdup(other.name_)),
517 rrd_def_(other.rrd_def_),
518 ds_name_(other.ds_name_ ? strdup(other.ds_name_) : NULL),
519 rpn_expression_(other.rpn_expression_ ? strdup(other.rpn_expression_) : 0),
520 cf_(other.cf_),
521 string_(NULL)
522{
523}
524
525/** Destructor. */
527{
528 if (name_)
529 free(name_);
530 if (ds_name_)
531 free(ds_name_);
532 if (rpn_expression_)
533 free(rpn_expression_);
534 if (string_)
535 free(string_);
536}
537
538/** Assignment operator.
539 * @param other instance to copy from
540 * @return reference to this instance
541 */
544{
545 if (string_)
546 free(string_);
547 if (ds_name_)
548 free(ds_name_);
549 if (name_)
550 free(name_);
551 if (rpn_expression_)
552 free(rpn_expression_);
553
554 string_ = NULL;
555 rpn_expression_ = NULL;
556 name_ = strdup(other.name_);
557 rrd_def_ = other.rrd_def_;
558 if (other.ds_name_)
559 ds_name_ = strdup(other.ds_name_);
560 if (other.rpn_expression_)
561 rpn_expression_ = other.rpn_expression_;
562 cf_ = other.cf_;
563
564 return *this;
565}
566
567/** Create string representation.
568 * @return string representation suitable for rrd_graph_v().
569 */
570const char *
572{
573 if (!string_) {
574 if (rpn_expression_) {
575 if (asprintf(&string_, "CDEF:%s=%s", name_, rpn_expression_) == -1) {
576 throw OutOfMemoryException("Failed to create RRA string");
577 }
578 } else {
579 size_t ds_index = rrd_def_->find_ds_index(ds_name_);
580
581 if (asprintf(&string_,
582 "DEF:%s=%s:%s:%s",
583 name_,
584 rrd_def_->get_filename(),
585 rrd_def_->get_ds(ds_index).get_name(),
587 == -1) {
588 throw OutOfMemoryException("Failed to create RRA string");
589 }
590 }
591 }
592
593 return string_;
594}
595
596/** @class RRDGraphElement <plugins/rrd/aspect/rrd_descriptions.h>
597 * Interface for graph elements.
598 * This super class provides the general interface for the different
599 * existing graph elements.
600 * @author Tim Niemueller
601 *
602 * @fn RRDGraphElement * RRDGraphElement::clone() const
603 * Clone this element.
604 * The clone function is needed to copy an object without knowing its type and
605 * therefore without calling its copy constructor.
606 * @return new copied instance
607 */
608
609/** Create string representation.
610 * @return string suitable for rrd_graph_v().
611 */
612const char *
614{
615 throw NotImplementedException("Invalid graph element");
616}
617
618/** @class RRDGraphGPrint <plugins/rrd/aspect/rrd_descriptions.h>
619 * Print string inside graph.
620 * @author Tim Niemueller
621 */
622
623/** Constructor.
624 * @param def_name Data definition for this graph element.
625 * @param cf consolidation function to use
626 * @param format Format string, cf. man rrdgraph_graph(1).
627 */
628RRDGraphGPrint::RRDGraphGPrint(const char * def_name,
630 const char * format)
631: def_name_(strdup(def_name)), cf_(cf), format_(strdup(format)), string_(NULL)
632{
633}
634
635/** Copy constructor.
636 * @param other instance to copy
637 */
639: def_name_(strdup(other.def_name_)), cf_(other.cf_), format_(strdup(other.format_)), string_(NULL)
640{
641}
642
643/** Destructor. */
645{
646 if (def_name_)
647 free(def_name_);
648 if (format_)
649 free(format_);
650 if (string_)
651 free(string_);
652}
653
654/** Assignment operator.
655 * @param g matching graph element to assign
656 * @return reference to this instance
657 */
660{
661 if (def_name_)
662 free(def_name_);
663 if (format_)
664 free(format_);
665 if (string_)
666 free(string_);
667
668 string_ = NULL;
669 def_name_ = strdup(g.def_name_);
670 cf_ = g.cf_;
671 format_ = strdup(g.format_);
672
673 return *this;
674}
675
676const char *
678{
679 if (!string_) {
680 if (asprintf(&string_, "GPRINT:%s:%s:%s", def_name_, RRDArchive::cf_to_string(cf_), format_)
681 == -1) {
682 throw OutOfMemoryException("Failed to create RRD graph GPRINT string");
683 }
684 }
685
686 return string_;
687}
688
689/** @class RRDGraphLine <plugins/rrd/aspect/rrd_descriptions.h>
690 * Print graph line.
691 * @author Tim Niemueller
692 */
693
694/** Constructor.
695 * @param def_name Data definition for this graph element.
696 * @param width line width
697 * @param color color hash string (HTML style, e.g. FF0000)
698 * @param legend legend string
699 * @param stacked true to stack on previous graph element
700 */
701RRDGraphLine::RRDGraphLine(const char *def_name,
702 float width,
703 const char *color,
704 const char *legend,
705 bool stacked)
706: def_name_(strdup(def_name)),
707 width_(width),
708 color_(strdup(color)),
709 legend_(strdup(legend)),
710 stacked_(stacked),
711 string_(NULL)
712{
713}
714
715/** Copy ctor.
716 * @param other instance to copy
717 */
719: def_name_(strdup(other.def_name_)),
720 width_(other.width_),
721 color_(strdup(other.color_)),
722 legend_(strdup(other.legend_)),
723 stacked_(other.stacked_),
724 string_(NULL)
725{
726}
727
728/** Destructor. */
730{
731 if (def_name_)
732 free(def_name_);
733 if (color_)
734 free(color_);
735 if (legend_)
736 free(legend_);
737 if (string_)
738 free(string_);
739}
740
741/** Assignment operator.
742 * @param g matching graph element to assign
743 * @return reference to this instance
744 */
747{
748 if (def_name_)
749 free(def_name_);
750 if (color_)
751 free(color_);
752 if (legend_)
753 free(legend_);
754 if (string_)
755 free(string_);
756
757 string_ = NULL;
758 def_name_ = strdup(g.def_name_);
759 width_ = g.width_;
760 color_ = strdup(g.color_);
761 legend_ = strdup(g.legend_);
762 stacked_ = g.stacked_;
763
764 return *this;
765}
766
767const char *
769{
770 if (!string_) {
771 if (asprintf(&string_,
772 "LINE%f:%s#%s:%s%s",
773 width_,
774 def_name_,
775 color_,
776 legend_,
777 stacked_ ? ":STACK" : "")
778 == -1) {
779 throw OutOfMemoryException("Failed to create RRD graph LINE string");
780 }
781 }
782
783 return string_;
784}
785
786/** @class RRDGraphArea <plugins/rrd/aspect/rrd_descriptions.h>
787 * Print graph area.
788 * @author Tim Niemueller
789 */
790
791/** Constructor.
792 * @param def_name Data definition for this graph element.
793 * @param color color hash string (HTML style, e.g. FF0000)
794 * @param legend legend string
795 * @param stacked true to stack on previous graph element
796 */
797RRDGraphArea::RRDGraphArea(const char *def_name,
798 const char *color,
799 const char *legend,
800 bool stacked)
801: def_name_(strdup(def_name)),
802 color_(strdup(color)),
803 legend_(strdup(legend)),
804 stacked_(stacked),
805 string_(NULL)
806{
807}
808
809/** Copy ctor.
810 * @param other instance to copy
811 */
813: def_name_(strdup(other.def_name_)),
814 color_(strdup(other.color_)),
815 legend_(strdup(other.legend_)),
816 stacked_(other.stacked_),
817 string_(NULL)
818{
819}
820
821/** Destructor. */
823{
824 if (def_name_)
825 free(def_name_);
826 if (color_)
827 free(color_);
828 if (legend_)
829 free(legend_);
830 if (string_)
831 free(string_);
832}
833
834/** Assignment operator.
835 * @param g matching graph element to assign
836 * @return reference to this instance
837 */
840{
841 if (def_name_)
842 free(def_name_);
843 if (color_)
844 free(color_);
845 if (legend_)
846 free(legend_);
847 if (string_)
848 free(string_);
849
850 string_ = NULL;
851 def_name_ = strdup(g.def_name_);
852 color_ = strdup(g.color_);
853 legend_ = strdup(g.legend_);
854 stacked_ = g.stacked_;
855
856 return *this;
857}
858
859const char *
861{
862 if (!string_) {
863 if (asprintf(&string_, "AREA:%s#%s:%s%s", def_name_, color_, legend_, stacked_ ? ":STACK" : "")
864 == -1) {
865 throw OutOfMemoryException("Failed to create RRD graph AREA string");
866 }
867 }
868
869 return string_;
870}
871
872/** @class RRDGraphDefinition <plugins/rrd/aspect/rrd_descriptions.h>
873 * Class representing a graph definition.
874 * This graph definition is used to generate all required parameters to create
875 * a graph from an RRD.
876 * @author Tim Niemueller
877 */
878
879/** Constructor.
880 * @param name name of this graph definition, used internally, name must be
881 * unique among all registered graphs.
882 * @param rrd_def pointer to definition of the RRD to graph
883 * @param start time from where to start graphing. Maybe an absolute time or
884 * a negative number for relative times, e.g. "-300" for 5 minutes back from now.
885 * @param end time where to end graphing. Maybe an absolute time or a negative
886 * number for relative times, e.g. "-300" for 5 minutes back from now.
887 * @param step step size in seconds
888 * @param title Graph title to print on top of graph
889 * @param vertical_label string printed rotated by 90° counter-clockwise besides
890 * the vertical axis. Usually should carry description of the Y axis units.
891 * @param update_interval The interval at which the graph should be generated.
892 * @param slope_mode true to enable slope mode when graphing
893 * @param def data definitions for the graph
894 * @param elements elements to print in the graph. This graph definition takes
895 * ownership of the graph elemenets and will delete them in its dtor.
896 */
898 RRDDefinition * rrd_def,
899 const char * title,
900 const char * vertical_label,
901 std::vector<RRDGraphDataDefinition> &def,
902 std::vector<RRDGraphElement *> & elements,
903 time_t start,
904 time_t end,
905 unsigned int step,
906 unsigned int update_interval,
907 bool slope_mode)
908: name_(strdup(name)),
909 rrd_def_(rrd_def),
910 start_(start),
911 end_(end),
912 step_(step),
913 title_(strdup(title)),
914 vertical_label_(strdup(vertical_label)),
915 update_interval_(update_interval),
916 slope_mode_(slope_mode),
917 defs_(def),
918 elements_(elements)
919{
920 filename_ = NULL;
921 argv_ = NULL;
922 argc_ = 0;
923 fonts_.push_back("LEGEND:10:");
924 fonts_.push_back("UNIT:8:");
925 fonts_.push_back("TITLE:12:");
926 fonts_.push_back("AXIS:8:");
927 width_ = 560;
928 width_s_ = strdup(StringConversions::to_string(width_).c_str());
929 start_s_ = strdup(StringConversions::to_string(start_).c_str());
930 end_s_ = strdup(StringConversions::to_string(end_).c_str());
931 step_s_ = strdup(StringConversions::to_string(step_).c_str());
932}
933
934/** Copy constructor.
935 * @param other instance to copy
936 */
938: name_(strdup(other.name_)),
939 rrd_def_(other.rrd_def_),
940 start_(other.start_),
941 end_(other.end_),
942 step_(other.step_),
943 title_(strdup(other.title_)),
944 vertical_label_(strdup(other.vertical_label_)),
945 update_interval_(other.update_interval_),
946 slope_mode_(other.slope_mode_),
947 defs_(other.defs_),
948 width_(other.width_),
949 fonts_(other.fonts_),
950 filename_(strdup(other.filename_))
951{
952 std::vector<RRDGraphElement *>::const_iterator i;
953 for (i = other.elements_.begin(); i != other.elements_.end(); ++i) {
954 elements_.push_back((*i)->clone());
955 }
956
957 argv_ = NULL;
958 argc_ = 0;
959 width_s_ = strdup(StringConversions::to_string(width_).c_str());
960 start_s_ = strdup(StringConversions::to_string(start_).c_str());
961 end_s_ = strdup(StringConversions::to_string(end_).c_str());
962 step_s_ = strdup(StringConversions::to_string(step_).c_str());
963}
964
965/** Destructor. */
967{
968 if (filename_)
969 free(filename_);
970 if (argv_)
971 free(argv_);
972 if (name_)
973 free(name_);
974 if (title_)
975 free(title_);
976 if (vertical_label_)
977 free(vertical_label_);
978
979 free(width_s_);
980 free(start_s_);
981 free(end_s_);
982 free(step_s_);
983
984 std::vector<RRDGraphElement *>::iterator i;
985 for (i = elements_.begin(); i != elements_.end(); ++i) {
986 delete *i;
987 }
988}
989
990/** Set filename.
991 * This can be done only once. Do not do this manually, rather let the RRDManager
992 * handle this!
993 * @param filename new filename, should be absolute, otherwise considered
994 * relative to current working directory.
995 */
996void
998{
999 if (filename_) {
1000 throw Exception("Graph definition for RRD %s: filename has already been set!",
1001 rrd_def_->get_name());
1002 }
1003 filename_ = strdup(filename);
1004}
1005
1006/** Get argument array and size.
1007 * @param argc upon completion contains the number of arguments in the
1008 * return value.
1009 * @return argument array suitable for rrd_create_v().
1010 */
1011const char **
1013{
1014 if (argv_ == NULL) {
1015 // "graph" filename --disable-rrdtool-tag --width ... --start ... --end ...
1016 // [fonts] --title ... --vertical-label ... [--slope-mode] DEFS... ELEMS...
1017 argc_ = 16 + fonts_.size() * 2 + defs_.size() + elements_.size();
1018 argv_ = (const char **)malloc(argc_ * sizeof(char *));
1019 size_t i = 0;
1020 argv_[i++] = "graph";
1021 argv_[i++] = filename_;
1022 argv_[i++] = "--disable-rrdtool-tag";
1023 argv_[i++] = "--width";
1024 argv_[i++] = width_s_;
1025 argv_[i++] = "--start";
1026 argv_[i++] = start_s_;
1027 argv_[i++] = "--end";
1028 argv_[i++] = end_s_;
1029 argv_[i++] = "--step";
1030 argv_[i++] = step_s_;
1031 argv_[i++] = "--title";
1032 argv_[i++] = title_;
1033 argv_[i++] = "--vertical-label";
1034
1035 if (strcmp(vertical_label_, "") == 0) {
1036 argv_[i++] = " ";
1037 } else {
1038 argv_[i++] = vertical_label_;
1039 }
1040
1041 if (slope_mode_)
1042 argv_[i++] = "--slope-mode";
1043
1044 std::vector<const char *>::const_iterator f;
1045 for (f = fonts_.begin(); f != fonts_.end(); ++f) {
1046 argv_[i++] = "--font";
1047 argv_[i++] = *f;
1048 }
1049
1050 std::vector<RRDGraphDataDefinition>::const_iterator d;
1051 for (d = defs_.begin(); d != defs_.end(); ++d) {
1052 argv_[i++] = d->to_string();
1053 }
1054
1055 std::vector<RRDGraphElement *>::const_iterator e;
1056 for (e = elements_.begin(); e != elements_.end(); ++e) {
1057 argv_[i++] = (*e)->to_string();
1058 }
1059
1060 argc_ = i;
1061 }
1062
1063 argc = argc_;
1064 return argv_;
1065}
1066
1067} // end namespace fawkes
Base class for exceptions in Fawkes.
Definition: exception.h:36
Expected parameter is missing.
Definition: software.h:80
Called method has not been implemented.
Definition: software.h:105
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
RRD Archive description.
RRDArchive(ConsolidationFunction cf, float xff, unsigned int steps, unsigned int rows)
Constructor.
const char * to_string() const
Get string representation.
ConsolidationFunction
Consolidation function type.
@ MAX
Maximum consolidation function.
@ MIN
Minimum consolidation function.
@ LAST
Last value consolidation function.
@ AVERAGE
Averaging consolidation function.
static const char * cf_to_string(ConsolidationFunction cf)
Convert consolidation function type to string.
RRDArchive & operator=(const RRDArchive &rra)
Assignment operator.
Class to represent a RRD data source.
Type
Data source type.
@ DERIVE
Derived value.
@ COMPUTE
Computed value.
@ ABSOLUTE
Absolute value.
@ COUNTER
Counter value.
const char * to_string() const
Get string reprensetation.
RRDDataSource & operator=(const RRDDataSource &other)
Assignment operator.
static const float UNKNOWN
Use for unknown min or max values.
RRDDataSource(const char *name, Type type, unsigned int heartbeat=30, float min=0, float max=UNKNOWN)
Constructor for regular data source.
void set_rrd_manager(RRDManager *rrd_manager)
Set RRD manager.
const char * get_filename() const
Get file name.
void set_filename(const char *filename)
Set filename.
RRDDefinition(const char *name, std::vector< RRDDataSource > &ds, unsigned int step_sec=10, bool recreate=false)
Constructor with default RRAs.
RRDDefinition & operator=(const RRDDefinition &other)
Assignment operator.
const char * get_name() const
Get name.
size_t find_ds_index(const char *ds_name) const
Find data source index.
static const std::vector< RRDArchive > get_default_rra()
Get default RRAs.
const std::vector< RRDDataSource > & get_ds() const
Get data sources.
Print graph area.
virtual const char * to_string() const
Create string representation.
RRDGraphArea(const char *def_name, const char *color, const char *legend, bool stacked=false)
Constructor.
virtual ~RRDGraphArea()
Destructor.
RRDGraphArea & operator=(const RRDGraphArea &g)
Assignment operator.
Represent data definition in graph arguments.
RRDGraphDataDefinition(const char *name, RRDArchive::ConsolidationFunction cf, const RRDDefinition *rrd_def, const char *ds_name=NULL)
DEF constructor.
RRDGraphDataDefinition & operator=(const RRDGraphDataDefinition &rra)
Assignment operator.
const char * to_string() const
Create string representation.
Class representing a graph definition.
RRDGraphDefinition(const char *name, RRDDefinition *rrd_def, const char *title, const char *vertical_label, std::vector< RRDGraphDataDefinition > &def, std::vector< RRDGraphElement * > &elements, time_t start=-600, time_t end=-10, unsigned int step=10, unsigned int update_interval=10, bool slope_mode=false)
Constructor.
const char ** get_argv(size_t &argc) const
Get argument array and size.
void set_filename(const char *filename)
Set filename.
virtual const char * to_string() const
Create string representation.
Print string inside graph.
RRDGraphGPrint & operator=(const RRDGraphGPrint &g)
Assignment operator.
RRDGraphGPrint(const char *def_name, RRDArchive::ConsolidationFunction cf, const char *format)
Constructor.
virtual ~RRDGraphGPrint()
Destructor.
virtual const char * to_string() const
Create string representation.
Print graph line.
virtual const char * to_string() const
Create string representation.
RRDGraphLine & operator=(const RRDGraphLine &g)
Assignment operator.
virtual ~RRDGraphLine()
Destructor.
RRDGraphLine(const char *def_name, float width, const char *color, const char *legend, bool stacked=false)
Constructor.
Interface for a RRD connection creator.
Definition: rrd_manager.h:37
virtual void remove_rrd(RRDDefinition *rrd_def)=0
Remove RRD.
static std::string to_string(unsigned int i)
Convert unsigned int value to a string.
Fawkes library namespace.