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 <plugins/rrd/aspect/rrd_descriptions.h>
25 #include <plugins/rrd/aspect/rrd_manager.h>
26 #include <core/exceptions/software.h>
27 #include <core/exceptions/system.h>
28 #include <utils/misc/string_conversions.h>
29 
30 #include <cstring>
31 #include <cstdlib>
32 #include <cstdio>
33 #include <cfloat>
34 
35 namespace fawkes {
36 #if 0 /* just to make Emacs auto-indent happy */
37 }
38 #endif
39 
40 /** @class RRDDataSource <plugins/rrd/aspect/rrd_descriptions.h>
41  * Class to represent a RRD data source.
42  * @author Tim Niemueller
43  */
44 
45 /** Use for unknown min or max values */
46 const float RRDDataSource::UNKNOWN = FLT_MIN;
47 
48 /** Constructor for regular data source.
49  * @param name name of the data source
50  * @param type type of the data source, may not be COMPUTE.
51  * @param heartbeat Number of seconds after which a new value must be received
52  * before the value is considered to be unknown.
53  * @param min minimum value, use UNKNOWN constant if not known
54  * @param max maximum value, use UNKNOWN constant if not known
55  */
56 RRDDataSource::RRDDataSource(const char *name, Type type, unsigned int heartbeat,
57  float min, float max)
58  : __name(strdup(name)), __type(type), __heartbeat(heartbeat),
59  __min(min), __max(max), __rpn_expression(NULL), __string(NULL)
60 {
61  if (__type == COMPUTE) {
62  throw IllegalArgumentException("Non-compute data source ctor used with "
63  "COMPUTE type for DS %s", name);
64  }
65 }
66 
67 
68 /** Constructor for expression RRDs.
69  * @param name name of the data source
70  * @param rpn_expression RPN expression
71  */
72 RRDDataSource::RRDDataSource(const char *name, const char *rpn_expression)
73  : __name(strdup(name)), __type(COMPUTE), __heartbeat(300), __min(UNKNOWN),
74  __max(UNKNOWN), __rpn_expression(strdup(rpn_expression)), __string(NULL)
75 {
76 }
77 
78 /** Copy constructor.
79  * @param other other instance to copy
80  */
82  : __name(strdup(other.__name)), __type(other.__type),
83  __heartbeat(other.__heartbeat),
84  __min(other.__min), __max(other.__max),
85  __rpn_expression(other.__rpn_expression ? strdup(other.__rpn_expression) : 0),
86  __string(NULL)
87 {
88 }
89 
90 /** Destructor. */
92 {
93  if (__string) free(__string);
94  if (__name) free(__name);
95  if (__rpn_expression) free(__rpn_expression);
96 }
97 
98 /** Assignment operator.
99  * @param other Instance to copy data from.
100  * @return reference to this instance
101  */
104 {
105  if (__string) free(__string);
106  if (__name) free(__name);
107  if (__rpn_expression) free(__rpn_expression);
108  __string = NULL;
109  __rpn_expression = NULL;
110  __name = strdup(other.__name);
111  __type = other.__type;
112  __heartbeat = other.__heartbeat;
113  __min = other.__min;
114  __max = other.__max;
115  if (other.__rpn_expression) __rpn_expression = strdup(other.__rpn_expression);
116 
117  return *this;
118 }
119 
120 
121 /** Get string reprensetation.
122  * @return string representation suitable to be bassed to rrd_create().
123  */
124 const char *
126 {
127  if (! __string) {
128  if (__type == COMPUTE) {
129  if (asprintf(&__string, "DS:%s:COMPUTE:%s", __name, __rpn_expression) == -1) {
130  throw OutOfMemoryException("Failed to create DS string for %s", __name);
131  }
132  } else {
133  const char *type_string;
134  switch (__type) {
135  case COUNTER: type_string = "COUNTER"; break;
136  case DERIVE: type_string = "DERIVE"; break;
137  case ABSOLUTE: type_string = "ABSOLUTE"; break;
138  default: type_string = "GAUGE"; break;
139  }
140  char min_s[32];
141  char max_s[32];
142  if (__min == UNKNOWN) {
143  strcpy(min_s, "U");
144  } else {
145  snprintf(min_s, 32, "%f", __min);
146  }
147  if (__max == UNKNOWN) {
148  strcpy(max_s, "U");
149  } else {
150  snprintf(max_s, 32, "%f", __max);
151  }
152  if (asprintf(&__string, "DS:%s:%s:%u:%s:%s", __name, type_string,
153  __heartbeat, min_s, max_s) == -1) {
154  throw OutOfMemoryException("Failed to create DS string for %s", __name);
155  }
156  }
157  }
158 
159  return __string;
160 }
161 
162 
163 /** @class RRDArchive <plugins/rrd/aspect/rrd_descriptions.h>
164  * RRD Archive description.
165  * @author Tim Niemueller
166  */
167 
168 /** Constructor.
169  * @param cf consolidation function
170  * @param xff The xfiles factor defines what part of a consolidation interval
171  * may be made up from *UNKNOWN* data while the consolidated value is still
172  * regarded as known. It is given as the ratio of allowed *UNKNOWN* PDPs to
173  * the number of PDPs in the interval. Thus, it ranges from 0 to 1 (exclusive).
174  * @param steps defines how many of these primary data points are used to build
175  * a consolidated data point which then goes into the archive.
176  * @param rows defines how many generations of data values are kept in an RRA.
177  * Obviously, this has to be greater than zero.
178  */
180  unsigned int steps, unsigned int rows)
181  : __cf(cf), __xff(xff), __steps(steps), __rows(rows), __string(NULL)
182 {
183 }
184 
185 
186 /** Copy constructor.
187  * @param rra instance to copy
188  */
190  : __cf(rra.__cf), __xff(rra.__xff), __steps(rra.__steps), __rows(rra.__rows),
191  __string(NULL)
192 {
193 }
194 
195 
196 /** Destructor. */
198 {
199  if (__string) free(__string);
200 }
201 
202 /** Assignment operator.
203  * @param rra instance to copy from
204  * @return reference to this instance
205  */
206 RRDArchive &
208 {
209  if (__string) free(__string);
210  __string = NULL;
211  __cf = rra.__cf;
212  __xff = rra.__xff;
213  __steps = rra.__steps;
214  __rows = rra.__rows;
215  return *this;
216 }
217 
218 /** Get string representation.
219  * @return string representation suitable to be passed to rrd_create().
220  */
221 const char *
223 {
224  if (! __string) {
225  const char *cf_string;
226  switch (__cf) {
227  case MIN: cf_string = "MIN"; break;
228  case MAX: cf_string = "MAX"; break;
229  case LAST: cf_string = "LAST"; break;
230  default: cf_string = "AVERAGE"; break;
231  }
232  if (asprintf(&__string, "RRA:%s:%f:%u:%u", cf_string,
233  __xff, __steps, __rows) == -1) {
234  throw OutOfMemoryException("Failed to create RRA string");
235  }
236  }
237 
238  return __string;
239 }
240 
241 /** Convert consolidation function type to string.
242  * @param cf consolidation function type
243  * @return string representation of @p cf, suitable for RRA lines.
244  */
245 const char *
247 {
248  switch (cf) {
249  case RRDArchive::MIN: return "MIN"; break;
250  case RRDArchive::MAX: return "MAX"; break;
251  case RRDArchive::LAST: return "LAST"; break;
252  default: return "AVERAGE"; break;
253  }
254 }
255 
256 /** @class RRDDefinition <plugins/rrd/aspect/rrd_descriptions.h>
257  * RRD Definition.
258  * This class describes everything required to create an RRD file.
259  * It does not represent all the options rrdtool provides, but a reasonable
260  * subset.
261  * @author Tim Niemueller
262  */
263 
264 /** Constructor with default RRAs.
265  * This creates the RRD definition with the default RRAs produced by
266  * get_default_rra().
267  * @param name RRD name
268  * @param ds data sources
269  * @param step_sec Specifies the base interval in seconds with which data
270  * will be fed into the RRD.
271  * @param recreate if true existing RRD files will be overwritten, otherwise
272  * data is appended.
273  */
274 RRDDefinition::RRDDefinition(const char *name, std::vector<RRDDataSource> &ds,
275  unsigned int step_sec, bool recreate)
276  : __name(strdup(name)), __step_sec(step_sec), __recreate(recreate),
277  __ds(ds), __rra(get_default_rra()), __filename(NULL), __rrd_manager(NULL)
278 {
279 }
280 
281 /** Constructor.
282  * @param name RRD name
283  * @param ds data sources
284  * @param rra RRAs for this RRD.
285  * @param step_sec Specifies the base interval in seconds with which data
286  * will be fed into the RRD.
287  * @param recreate if true existing RRD files will be overwritten, otherwise
288  * data is appended.
289  */
291  std::vector<RRDDataSource> &ds,
292  std::vector<RRDArchive> &rra,
293  unsigned int step_sec, bool recreate)
294  : __name(strdup(name)), __step_sec(step_sec), __recreate(recreate), __ds(ds),
295  __rra(rra), __filename(NULL), __rrd_manager(NULL)
296 {
297 }
298 
299 
300 /** Copy constructor.
301  * @param other instance to clone
302  */
304  : __name(strdup(other.__name)), __step_sec(other.__step_sec),
305  __recreate(other.__recreate), __ds(other.__ds), __rra(other.__rra),
306  __filename(other.__filename ? strdup(other.__filename) : 0),
307  __rrd_manager(NULL)
308 {
309 }
310 
311 /** Assignment operator.
312  * @param other other instance to copy from
313  * @return reference to this instance.
314  */
317 {
318  if (__name) free(__name);
319  if (__filename) free(__filename);
320  if (__rrd_manager) __rrd_manager->remove_rrd(this);
321  __filename = NULL;
322  __rrd_manager = NULL;
323  __name = strdup(other.__name);
324  __step_sec = other.__step_sec;
325  __recreate = other.__recreate;
326  __ds = other.__ds;
327  __rra = other.__rra;
328  if (other.__filename) __filename=strdup(other.__filename);
329  return *this;
330 }
331 
332 /** Destructor. */
334 {
335  if (__rrd_manager) __rrd_manager->remove_rrd(this);
336 
337  if (__name) free(__name);
338  if (__filename) free(__filename);
339 }
340 
341 /** Get default RRAs. They correspond to the following and assume a
342  * 10 second step size.
343  * @code
344  * "RRA:AVERAGE:0.5:1:720" # 2 hours of 10 sec averages
345  * "RRA:AVERAGE:0.5:3:1680" # 12 hours of 30 sec averages
346  * "RRA:AVERAGE:0.5:30:456" # 1 day of 5 min averages
347  * "RRA:AVERAGE:0.5:180:412" # 7 days of 30 min averages
348  * "RRA:AVERAGE:0.5:720:439" # 4 weeks of 2 hour averages
349  * "RRA:AVERAGE:0.5:8640:402" # 1 year of 1 day averages
350  * "RRA:MIN:0.5:1:720"
351  * "RRA:MIN:0.5:3:1680"
352  * "RRA:MIN:0.5:30:456"
353  * "RRA:MIN:0.5:180:412"
354  * "RRA:MIN:0.5:720:439"
355  * "RRA:MIN:0.5:8640:402"
356  * "RRA:MAX:0.5:1:720"
357  * "RRA:MAX:0.5:3:1680"
358  * "RRA:MAX:0.5:30:456"
359  * "RRA:MAX:0.5:180:412"
360  * "RRA:MAX:0.5:720:439"
361  * "RRA:MAX:0.5:8640:402"
362  * @endcode
363  * @return vector of RRDArchive representing the described RRAs.
364  */
365 const std::vector<RRDArchive>
367 {
368  std::vector<RRDArchive> rv;
369  rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 1, 720));
370  rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 3, 1680));
371  rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 30, 456));
372  rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 180, 412));
373  rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 720, 439));
374  rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 8640, 402));
375  rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 1, 720));
376  rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 3, 1680));
377  rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 30, 456));
378  rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 180, 412));
379  rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 720, 439));
380  rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 8640, 402));
381  rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 1, 720));
382  rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 3, 1680));
383  rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 30, 456));
384  rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 180, 412));
385  rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 720, 439));
386  rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 8640, 402));
387  return rv;
388 }
389 
390 
391 /** Find data source index.
392  * @param ds_name name of the data source
393  * @return index of found data source
394  * @exception Exception thrown if the data source could not be found
395  */
396 size_t
397 RRDDefinition::find_ds_index(const char *ds_name) const
398 {
399  for (size_t i = 0; i < __ds.size(); ++i) {
400  if (strcmp(__ds[i].get_name(), ds_name) == 0) return i;
401  }
402 
403  throw Exception("Data source name %s not found", ds_name);
404 }
405 
406 /** Set filename.
407  * This can be done only once. Do not do this manually, rather let the RRDManager
408  * handle this!
409  * @param filename new filename, should be absolute, otherwise considered
410  * relative to current working directory.
411  */
412 void
413 RRDDefinition::set_filename(const char *filename)
414 {
415  if (__filename) {
416  throw Exception("Graph definition %s: filename has already been set!", __name);
417  }
418  __filename = strdup(filename);
419 }
420 
421 
422 /** Set RRD manager.
423  * This can be done only once. Do not do this manually, rather let the RRDManager
424  * handle this! The RRD manager is used to unregister this RRD if it is deleted.
425  * This is a precaution to avoid dangling RRDs.
426  * @param rrd_manager RRD manager to use
427  */
428 void
430 {
431  if (__rrd_manager) {
432  throw Exception("RRD definition %s: RRD manager has already been set", __name);
433  }
434  __rrd_manager = rrd_manager;
435 }
436 
437 
438 
439 /** @class RRDGraphDataDefinition <plugins/rrd/aspect/rrd_descriptions.h>
440  * Represent data definition in graph arguments.
441  * @author Tim Niemueller
442  * Currently supports only DEF and CDEF definitions.
443  */
444 
445 /** DEF constructor.
446  * @param name name of the graph data source
447  * @param cf consolidation function to apply if needed
448  * @param rrd_def RRD definition to use
449  * @param ds_name data source name in RRD, @p rrd_def will be queried for the
450  * data source. If ds_name is NULL, @p name will be used as the data source name.
451  */
454  const RRDDefinition *rrd_def,
455  const char *ds_name)
456  : __name(strdup(name)), __rrd_def(rrd_def),
457  __ds_name(ds_name ? strdup(ds_name) : strdup(name)),
458  __rpn_expression(NULL), __cf(cf), __string(NULL)
459 {
460 }
461 
462 
463 /** CDEF constructor.
464  * @param name name of the graph data source
465  * @param rpn_expression RPN expression
466  */
468  const char *rpn_expression)
469  : __name(strdup(name)), __rrd_def(0), __ds_name(NULL),
470  __rpn_expression(strdup(rpn_expression)),
471  __cf(RRDArchive::AVERAGE), __string(NULL)
472 {
473 }
474 
475 
476 /** Copy constructor.
477  * @param other instance to clone
478  */
480  : __name(strdup(other.__name)), __rrd_def(other.__rrd_def),
481  __ds_name(other.__ds_name ? strdup(other.__ds_name) : NULL),
482  __rpn_expression(other.__rpn_expression ? strdup(other.__rpn_expression) : 0),
483  __cf(other.__cf), __string(NULL)
484 {
485 }
486 
487 
488 /** Destructor. */
490 {
491  if (__name) free(__name);
492  if (__ds_name) free(__ds_name);
493  if (__rpn_expression) free(__rpn_expression);
494  if (__string) free(__string);
495 }
496 
497 /** Assignment operator.
498  * @param other instance to copy from
499  * @return reference to this instance
500  */
503 {
504  if (__string) free(__string);
505  if (__ds_name) free(__ds_name);
506  if (__name) free(__name);
507  if (__rpn_expression) free(__rpn_expression);
508 
509  __string = NULL;
510  __rpn_expression = NULL;
511  __name = strdup(other.__name);
512  __rrd_def = other.__rrd_def;
513  if (other.__ds_name) __ds_name = strdup(other.__ds_name);
514  if (other.__rpn_expression) __rpn_expression = other.__rpn_expression;
515  __cf = other.__cf;
516 
517  return *this;
518 }
519 
520 
521 /** Create string representation.
522  * @return string representation suitable for rrd_graph_v().
523  */
524 const char *
526 {
527  if (! __string) {
528  if (__rpn_expression) {
529  if (asprintf(&__string, "CDEF:%s=%s", __name, __rpn_expression) == -1) {
530  throw OutOfMemoryException("Failed to create RRA string");
531  }
532  } else {
533  size_t ds_index = __rrd_def->find_ds_index(__ds_name);
534 
535  if (asprintf(&__string, "DEF:%s=%s:%s:%s", __name, __rrd_def->get_filename(),
536  __rrd_def->get_ds(ds_index).get_name(),
537  RRDArchive::cf_to_string(__cf)) == -1) {
538  throw OutOfMemoryException("Failed to create RRA string");
539  }
540  }
541  }
542 
543  return __string;
544 }
545 
546 /** @class RRDGraphElement <plugins/rrd/aspect/rrd_descriptions.h>
547  * Interface for graph elements.
548  * This super class provides the general interface for the different
549  * existing graph elements.
550  * @author Tim Niemueller
551  *
552  * @fn RRDGraphElement * RRDGraphElement::clone() const
553  * Clone this element.
554  * The clone function is needed to copy an object without knowing its type and
555  * therefore without calling its copy constructor.
556  * @return new copied instance
557  */
558 
559 /** Create string representation.
560  * @return string suitable for rrd_graph_v().
561  */
562 const char *
564 {
565  throw NotImplementedException("Invalid graph element");
566 }
567 
568 
569 
570 /** @class RRDGraphGPrint <plugins/rrd/aspect/rrd_descriptions.h>
571  * Print string inside graph.
572  * @author Tim Niemueller
573  */
574 
575 /** Constructor.
576  * @param def_name Data definition for this graph element.
577  * @param cf consolidation function to use
578  * @param format Format string, cf. man rrdgraph_graph(1).
579  */
580 RRDGraphGPrint::RRDGraphGPrint(const char *def_name,
582  const char *format)
583  : __def_name(strdup(def_name)), __cf(cf), __format(strdup(format)),
584  __string(NULL)
585 {
586 }
587 
588 /** Copy constructor.
589  * @param other instance to copy
590  */
592  : __def_name(strdup(other.__def_name)), __cf(other.__cf),
593  __format(strdup(other.__format)), __string(NULL)
594 {
595 }
596 
597 
598 /** Destructor. */
600 {
601  if (__def_name) free(__def_name);
602  if (__format) free(__format);
603  if (__string) free(__string);
604 }
605 
606 /** Assignment operator.
607  * @param g matching graph element to assign
608  * @return reference to this instance
609  */
612 {
613  if (__def_name) free(__def_name);
614  if (__format) free(__format);
615  if (__string) free(__string);
616 
617  __string = NULL;
618  __def_name = strdup(g.__def_name);
619  __cf = g.__cf;
620  __format = strdup(g.__format);
621 
622  return *this;
623 }
624 
625 
626 const char *
628 {
629  if (! __string) {
630  if (asprintf(&__string, "GPRINT:%s:%s:%s", __def_name,
631  RRDArchive::cf_to_string(__cf), __format) == -1) {
632  throw OutOfMemoryException("Failed to create RRD graph GPRINT string");
633  }
634  }
635 
636  return __string;
637 }
638 
639 
640 /** @class RRDGraphLine <plugins/rrd/aspect/rrd_descriptions.h>
641  * Print graph line.
642  * @author Tim Niemueller
643  */
644 
645 /** Constructor.
646  * @param def_name Data definition for this graph element.
647  * @param width line width
648  * @param color color hash string (HTML style, e.g. FF0000)
649  * @param legend legend string
650  * @param stacked true to stack on previous graph element
651  */
652 RRDGraphLine::RRDGraphLine(const char *def_name, float width, const char *color,
653  const char *legend, bool stacked)
654  : __def_name(strdup(def_name)), __width(width), __color(strdup(color)),
655  __legend(strdup(legend)), __stacked(stacked), __string(NULL)
656 {
657 }
658 
659 /** Copy ctor.
660  * @param other instance to copy
661  */
663  : __def_name(strdup(other.__def_name)), __width(other.__width),
664  __color(strdup(other.__color)),
665  __legend(strdup(other.__legend)), __stacked(other.__stacked), __string(NULL)
666 {
667 }
668 
669 
670 /** Destructor. */
672 {
673  if (__def_name) free(__def_name);
674  if (__color) free(__color);
675  if (__legend) free(__legend);
676  if (__string) free(__string);
677 }
678 
679 
680 /** Assignment operator.
681  * @param g matching graph element to assign
682  * @return reference to this instance
683  */
684 RRDGraphLine &
686 {
687  if (__def_name) free(__def_name);
688  if (__color) free(__color);
689  if (__legend) free(__legend);
690  if (__string) free(__string);
691 
692  __string = NULL;
693  __def_name = strdup(g.__def_name);
694  __width = g.__width;
695  __color = strdup(g.__color);
696  __legend = strdup(g.__legend);
697  __stacked = g.__stacked;
698 
699  return *this;
700 }
701 
702 
703 const char *
705 {
706  if (! __string) {
707  if (asprintf(&__string, "LINE%f:%s#%s:%s%s", __width, __def_name, __color,
708  __legend, __stacked ? ":STACK" : "") == -1) {
709  throw OutOfMemoryException("Failed to create RRD graph LINE string");
710  }
711  }
712 
713  return __string;
714 }
715 
716 
717 /** @class RRDGraphArea <plugins/rrd/aspect/rrd_descriptions.h>
718  * Print graph area.
719  * @author Tim Niemueller
720  */
721 
722 /** Constructor.
723  * @param def_name Data definition for this graph element.
724  * @param color color hash string (HTML style, e.g. FF0000)
725  * @param legend legend string
726  * @param stacked true to stack on previous graph element
727  */
728 RRDGraphArea::RRDGraphArea(const char *def_name,const char *color,
729  const char *legend, bool stacked)
730  : __def_name(strdup(def_name)), __color(strdup(color)),
731  __legend(strdup(legend)), __stacked(stacked), __string(NULL)
732 {
733 }
734 
735 
736 /** Copy ctor.
737  * @param other instance to copy
738  */
740  : __def_name(strdup(other.__def_name)), __color(strdup(other.__color)),
741  __legend(strdup(other.__legend)), __stacked(other.__stacked), __string(NULL)
742 {
743 }
744 
745 
746 /** Destructor. */
748 {
749  if (__def_name) free(__def_name);
750  if (__color) free(__color);
751  if (__legend) free(__legend);
752  if (__string) free(__string);
753 }
754 
755 
756 /** Assignment operator.
757  * @param g matching graph element to assign
758  * @return reference to this instance
759  */
760 RRDGraphArea &
762 {
763  if (__def_name) free(__def_name);
764  if (__color) free(__color);
765  if (__legend) free(__legend);
766  if (__string) free(__string);
767 
768  __string = NULL;
769  __def_name = strdup(g.__def_name);
770  __color = strdup(g.__color);
771  __legend = strdup(g.__legend);
772  __stacked = g.__stacked;
773 
774  return *this;
775 }
776 
777 
778 const char *
780 {
781  if (! __string) {
782  if (asprintf(&__string, "AREA:%s#%s:%s%s", __def_name, __color, __legend,
783  __stacked ? ":STACK" : "") == -1) {
784  throw OutOfMemoryException("Failed to create RRD graph AREA string");
785  }
786  }
787 
788  return __string;
789 }
790 
791 
792 /** @class RRDGraphDefinition <plugins/rrd/aspect/rrd_descriptions.h>
793  * Class representing a graph definition.
794  * This graph definition is used to generate all required parameters to create
795  * a graph from an RRD.
796  * @author Tim Niemueller
797  */
798 
799 /** Constructor.
800  * @param name name of this graph definition, used internally, name must be
801  * unique among all registered graphs.
802  * @param rrd_def pointer to definition of the RRD to graph
803  * @param start time from where to start graphing. Maybe an absolute time or
804  * a negative number for relative times, e.g. "-300" for 5 minutes back from now.
805  * @param end time where to end graphing. Maybe an absolute time or a negative
806  * number for relative times, e.g. "-300" for 5 minutes back from now.
807  * @param step step size in seconds
808  * @param title Graph title to print on top of graph
809  * @param vertical_label string printed rotated by 90° counter-clockwise besides
810  * the vertical axis. Usually should carry description of the Y axis units.
811  * @param update_interval The interval at which the graph should be generated.
812  * @param slope_mode true to enable slope mode when graphing
813  * @param def data definitions for the graph
814  * @param elements elements to print in the graph. This graph definition takes
815  * ownership of the graph elemenets and will delete them in its dtor.
816  */
818  const char *title,
819  const char *vertical_label,
820  std::vector<RRDGraphDataDefinition> &def,
821  std::vector<RRDGraphElement *> &elements,
822  time_t start, time_t end, unsigned int step,
823  unsigned int update_interval,
824  bool slope_mode)
825  : __name(strdup(name)), __rrd_def(rrd_def),
826  __start(start), __end(end), __step(step),
827  __title(strdup(title)), __vertical_label(strdup(vertical_label)),
828  __update_interval(update_interval), __slope_mode(slope_mode),
829  __defs(def), __elements(elements)
830 {
831  __filename = NULL;
832  __argv = NULL;
833  __argc = 0;
834  __fonts.push_back("LEGEND:10:");
835  __fonts.push_back("UNIT:8:");
836  __fonts.push_back("TITLE:12:");
837  __fonts.push_back("AXIS:8:");
838  __width = 560;
839  __width_s = strdup(StringConversions::to_string(__width).c_str());
840  __start_s = strdup(StringConversions::to_string(__start).c_str());
841  __end_s = strdup(StringConversions::to_string(__end).c_str());
842  __step_s = strdup(StringConversions::to_string(__step).c_str());
843 }
844 
845 /** Copy constructor.
846  * @param other instance to copy
847  */
849  : __name(strdup(other.__name)), __rrd_def(other.__rrd_def),
850  __start(other.__start), __end(other.__end), __step(other.__step),
851  __title(strdup(other.__title)),
852  __vertical_label(strdup(other.__vertical_label)),
853  __update_interval(other.__update_interval),
854  __slope_mode(other.__slope_mode), __defs(other.__defs),
855  __width(other.__width), __fonts(other.__fonts),
856  __filename(strdup(other.__filename))
857 {
858  std::vector<RRDGraphElement *>::const_iterator i;
859  for (i = other.__elements.begin(); i != other.__elements.end(); ++i) {
860  __elements.push_back((*i)->clone());
861  }
862 
863  __argv = NULL;
864  __argc = 0;
865  __width_s = strdup(StringConversions::to_string(__width).c_str());
866  __start_s = strdup(StringConversions::to_string(__start).c_str());
867  __end_s = strdup(StringConversions::to_string(__end).c_str());
868  __step_s = strdup(StringConversions::to_string(__step).c_str());
869 }
870 
871 
872 /** Destructor. */
874 {
875  if (__filename) free(__filename);
876  if (__argv) free(__argv);
877  if (__name) free(__name);
878  if (__title) free(__title);
879  if (__vertical_label) free(__vertical_label);
880 
881  free(__width_s);
882  free(__start_s);
883  free(__end_s);
884  free(__step_s);
885 
886  std::vector<RRDGraphElement *>::iterator i;
887  for (i = __elements.begin(); i != __elements.end(); ++i) {
888  delete *i;
889  }
890 }
891 
892 /** Set filename.
893  * This can be done only once. Do not do this manually, rather let the RRDManager
894  * handle this!
895  * @param filename new filename, should be absolute, otherwise considered
896  * relative to current working directory.
897  */
898 void
899 RRDGraphDefinition::set_filename(const char *filename)
900 {
901  if (__filename) {
902  throw Exception("Graph definition for RRD %s: filename has already been set!",
903  __rrd_def->get_name());
904  }
905  __filename = strdup(filename);
906 }
907 
908 /** Get argument array and size.
909  * @param argc upon completion contains the number of arguments in the
910  * return value.
911  * @return argument array suitable for rrd_create_v().
912  */
913 const char **
914 RRDGraphDefinition::get_argv(size_t &argc) const
915 {
916  if (__argv == NULL) {
917  // "graph" filename --disable-rrdtool-tag --width ... --start ... --end ...
918  // [fonts] --title ... --vertical-label ... [--slope-mode] DEFS... ELEMS...
919  __argc = 16 + __fonts.size() * 2 + __defs.size() + __elements.size();
920  __argv = (const char **)malloc(__argc * sizeof(char *));
921  size_t i = 0;
922  __argv[i++] = "graph";
923  __argv[i++] = __filename;
924  __argv[i++] = "--disable-rrdtool-tag";
925  __argv[i++] = "--width";
926  __argv[i++] = __width_s;
927  __argv[i++] = "--start";
928  __argv[i++] = __start_s;
929  __argv[i++] = "--end";
930  __argv[i++] = __end_s;
931  __argv[i++] = "--step";
932  __argv[i++] = __step_s;
933  __argv[i++] = "--title";
934  __argv[i++] = __title;
935  __argv[i++] = "--vertical-label";
936 
937  if (strcmp(__vertical_label, "") == 0) {
938  __argv[i++] = " ";
939  } else {
940  __argv[i++] = __vertical_label;
941  }
942 
943  if (__slope_mode) __argv[i++] = "--slope-mode";
944 
945  std::vector<const char *>::const_iterator f;
946  for (f = __fonts.begin(); f != __fonts.end(); ++f) {
947  __argv[i++] = "--font";
948  __argv[i++] = *f;
949  }
950 
951  std::vector<RRDGraphDataDefinition>::const_iterator d;
952  for (d = __defs.begin(); d != __defs.end(); ++d) {
953  __argv[i++] = d->to_string();
954  }
955 
956  std::vector<RRDGraphElement *>::const_iterator e;
957  for (e = __elements.begin(); e != __elements.end(); ++e) {
958  __argv[i++] = (*e)->to_string();
959  }
960 
961  __argc = i;
962  }
963 
964  argc = __argc;
965  return __argv;
966 }
967 
968 
969 } // end namespace fawkes
static const float UNKNOWN
Use for unknown min or max values.
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.
virtual const char * to_string() const
Create string representation.
virtual const char * to_string() const
Create string representation.
Interface for a RRD connection creator.
Definition: rrd_manager.h:40
Type
Data source type.
Print graph area.
RRDGraphLine & operator=(const RRDGraphLine &g)
Assignment operator.
Fawkes library namespace.
const char * to_string() const
Get string reprensetation.
Called method has not been implemented.
Definition: software.h:107
const char * to_string() const
Get string representation.
Maximum consolidation function.
RRDDataSource(const char *name, Type type, unsigned int heartbeat=30, float min=0, float max=UNKNOWN)
Constructor for regular data source.
RRDGraphArea & operator=(const RRDGraphArea &g)
Assignment operator.
void set_filename(const char *filename)
Set filename.
const std::vector< RRDDataSource > & get_ds() const
Get data sources.
static const char * cf_to_string(ConsolidationFunction cf)
Convert consolidation function type to string.
RRD Archive description.
RRDGraphGPrint(const char *def_name, RRDArchive::ConsolidationFunction cf, const char *format)
Constructor.
RRDGraphArea(const char *def_name, const char *color, const char *legend, bool stacked=false)
Constructor.
ConsolidationFunction
Consolidation function type.
Print graph line.
Represent data definition in graph arguments.
Base class for exceptions in Fawkes.
Definition: exception.h:36
Class representing a graph definition.
void set_filename(const char *filename)
Set filename.
RRDDataSource & operator=(const RRDDataSource &other)
Assignment operator.
Class to represent a RRD data source.
virtual const char * to_string() const
Create string representation.
const char * to_string() const
Create string representation.
RRDGraphDataDefinition(const char *name, RRDArchive::ConsolidationFunction cf, const RRDDefinition *rrd_def, const char *ds_name=NULL)
DEF constructor.
RRDDefinition(const char *name, std::vector< RRDDataSource > &ds, unsigned int step_sec=10, bool recreate=false)
Constructor with default RRAs.
virtual ~RRDGraphLine()
Destructor.
virtual void remove_rrd(RRDDefinition *rrd_def)=0
Remove RRD.
RRDArchive & operator=(const RRDArchive &rra)
Assignment operator.
const char ** get_argv(size_t &argc) const
Get argument array and size.
virtual const char * to_string() const
Create string representation.
~RRDArchive()
Destructor.
size_t find_ds_index(const char *ds_name) const
Find data source index.
const char * get_name() const
Get name.
const char * get_filename() const
Get file name.
RRDArchive(ConsolidationFunction cf, float xff, unsigned int steps, unsigned int rows)
Constructor.
Print string inside graph.
~RRDDataSource()
Destructor.
RRDGraphGPrint & operator=(const RRDGraphGPrint &g)
Assignment operator.
RRDDefinition & operator=(const RRDDefinition &other)
Assignment operator.
Expected parameter is missing.
Definition: software.h:82
virtual ~RRDGraphArea()
Destructor.
Last value consolidation function.
Minimum consolidation function.
RRDGraphLine(const char *def_name, float width, const char *color, const char *legend, bool stacked=false)
Constructor.
static std::string to_string(unsigned int i)
Convert unsigned int value to a string.
static const std::vector< RRDArchive > get_default_rra()
Get default RRAs.
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
RRDGraphDataDefinition & operator=(const RRDGraphDataDefinition &rra)
Assignment operator.
void set_rrd_manager(RRDManager *rrd_manager)
Set RRD manager.
Averaging consolidation function.
virtual ~RRDGraphGPrint()
Destructor.