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 
35 namespace 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 */
43 const 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  */
53 RRDDataSource::RRDDataSource(const char * name,
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  */
77 RRDDataSource::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  */
142 const 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  */
196 RRDArchive::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  */
220 RRDArchive &
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  */
236 const 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  */
259 const 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  */
401 const 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  */
431 size_t
432 RRDDefinition::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  */
448 void
449 RRDDefinition::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  */
463 void
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  */
502 RRDGraphDataDefinition::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  */
570 const 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  */
612 const 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  */
628 RRDGraphGPrint::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 
676 const 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  */
701 RRDGraphLine::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  */
745 RRDGraphLine &
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 
767 const 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  */
797 RRDGraphArea::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  */
838 RRDGraphArea &
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 
859 const 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  */
996 void
997 RRDGraphDefinition::set_filename(const char *filename)
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  */
1011 const char **
1012 RRDGraphDefinition::get_argv(size_t &argc) const
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
fawkes::RRDDefinition::find_ds_index
size_t find_ds_index(const char *ds_name) const
Find data source index.
Definition: rrd_descriptions.cpp:432
fawkes::IllegalArgumentException
Expected parameter is missing.
Definition: software.h:80
fawkes::RRDDefinition::set_filename
void set_filename(const char *filename)
Set filename.
Definition: rrd_descriptions.cpp:449
fawkes::RRDDataSource::DERIVE
@ DERIVE
Derived value.
Definition: rrd_descriptions.h:41
fawkes::RRDGraphDefinition
Class representing a graph definition.
Definition: rrd_descriptions.h:465
fawkes::RRDGraphGPrint::RRDGraphGPrint
RRDGraphGPrint(const char *def_name, RRDArchive::ConsolidationFunction cf, const char *format)
Constructor.
Definition: rrd_descriptions.cpp:628
fawkes::RRDGraphDefinition::~RRDGraphDefinition
~RRDGraphDefinition()
Destructor.
Definition: rrd_descriptions.cpp:966
fawkes::RRDArchive::MIN
@ MIN
Minimum consolidation function.
Definition: rrd_descriptions.h:114
fawkes::RRDDataSource::RRDDataSource
RRDDataSource(const char *name, Type type, unsigned int heartbeat=30, float min=0, float max=UNKNOWN)
Constructor for regular data source.
Definition: rrd_descriptions.cpp:53
fawkes::RRDGraphGPrint
Print string inside graph.
Definition: rrd_descriptions.h:308
fawkes::RRDGraphLine::~RRDGraphLine
virtual ~RRDGraphLine()
Destructor.
Definition: rrd_descriptions.cpp:729
fawkes::RRDArchive::MAX
@ MAX
Maximum consolidation function.
Definition: rrd_descriptions.h:115
fawkes::RRDArchive::cf_to_string
static const char * cf_to_string(ConsolidationFunction cf)
Convert consolidation function type to string.
Definition: rrd_descriptions.cpp:260
fawkes::RRDGraphLine::to_string
virtual const char * to_string() const
Create string representation.
Definition: rrd_descriptions.cpp:768
fawkes::RRDDataSource
Class to represent a RRD data source.
Definition: rrd_descriptions.h:35
fawkes::RRDArchive::operator=
RRDArchive & operator=(const RRDArchive &rra)
Assignment operator.
Definition: rrd_descriptions.cpp:221
fawkes::RRDDataSource::Type
Type
Data source type.
Definition: rrd_descriptions.h:38
fawkes::RRDGraphLine::RRDGraphLine
RRDGraphLine(const char *def_name, float width, const char *color, const char *legend, bool stacked=false)
Constructor.
Definition: rrd_descriptions.cpp:701
fawkes::RRDGraphElement::to_string
virtual const char * to_string() const
Create string representation.
Definition: rrd_descriptions.cpp:613
fawkes::RRDGraphGPrint::to_string
virtual const char * to_string() const
Create string representation.
Definition: rrd_descriptions.cpp:677
fawkes::RRDDataSource::to_string
const char * to_string() const
Get string reprensetation.
Definition: rrd_descriptions.cpp:143
fawkes::RRDDefinition::RRDDefinition
RRDDefinition(const char *name, std::vector< RRDDataSource > &ds, unsigned int step_sec=10, bool recreate=false)
Constructor with default RRAs.
Definition: rrd_descriptions.cpp:288
fawkes::RRDManager::remove_rrd
virtual void remove_rrd(RRDDefinition *rrd_def)=0
Remove RRD.
fawkes::RRDArchive::to_string
const char * to_string() const
Get string representation.
Definition: rrd_descriptions.cpp:237
fawkes::RRDGraphDefinition::get_argv
const char ** get_argv(size_t &argc) const
Get argument array and size.
Definition: rrd_descriptions.cpp:1012
fawkes::RRDArchive::ConsolidationFunction
ConsolidationFunction
Consolidation function type.
Definition: rrd_descriptions.h:112
fawkes::StringConversions::to_string
static std::string to_string(unsigned int i)
Convert unsigned int value to a string.
Definition: string_conversions.cpp:73
fawkes::RRDGraphDataDefinition::to_string
const char * to_string() const
Create string representation.
Definition: rrd_descriptions.cpp:571
fawkes::RRDDefinition::get_ds
const std::vector< RRDDataSource > & get_ds() const
Get data sources.
Definition: rrd_descriptions.h:204
fawkes::RRDGraphDataDefinition
Represent data definition in graph arguments.
Definition: rrd_descriptions.h:243
fawkes::RRDDataSource::operator=
RRDDataSource & operator=(const RRDDataSource &other)
Assignment operator.
Definition: rrd_descriptions.cpp:118
fawkes::RRDDataSource::COUNTER
@ COUNTER
Counter value.
Definition: rrd_descriptions.h:40
fawkes::RRDDefinition::get_filename
const char * get_filename() const
Get file name.
Definition: rrd_descriptions.h:224
fawkes
Fawkes library namespace.
fawkes::RRDGraphGPrint::operator=
RRDGraphGPrint & operator=(const RRDGraphGPrint &g)
Assignment operator.
Definition: rrd_descriptions.cpp:659
fawkes::RRDGraphArea::~RRDGraphArea
virtual ~RRDGraphArea()
Destructor.
Definition: rrd_descriptions.cpp:822
fawkes::RRDDefinition::get_name
const char * get_name() const
Get name.
Definition: rrd_descriptions.h:185
fawkes::RRDGraphLine::operator=
RRDGraphLine & operator=(const RRDGraphLine &g)
Assignment operator.
Definition: rrd_descriptions.cpp:746
fawkes::RRDDefinition::operator=
RRDDefinition & operator=(const RRDDefinition &other)
Assignment operator.
Definition: rrd_descriptions.cpp:345
fawkes::RRDGraphDataDefinition::~RRDGraphDataDefinition
~RRDGraphDataDefinition()
Destructor.
Definition: rrd_descriptions.cpp:526
fawkes::RRDManager
Interface for a RRD connection creator.
Definition: rrd_manager.h:37
fawkes::RRDGraphArea
Print graph area.
Definition: rrd_descriptions.h:414
fawkes::RRDDataSource::COMPUTE
@ COMPUTE
Computed value.
Definition: rrd_descriptions.h:43
fawkes::RRDArchive::RRDArchive
RRDArchive(ConsolidationFunction cf, float xff, unsigned int steps, unsigned int rows)
Constructor.
Definition: rrd_descriptions.cpp:196
fawkes::NotImplementedException
Called method has not been implemented.
Definition: software.h:105
fawkes::RRDDefinition::~RRDDefinition
~RRDDefinition()
Destructor.
Definition: rrd_descriptions.cpp:366
fawkes::RRDDefinition
RRD Definition.
Definition: rrd_descriptions.h:163
fawkes::RRDDefinition::get_default_rra
static const std::vector< RRDArchive > get_default_rra()
Get default RRAs.
Definition: rrd_descriptions.cpp:402
fawkes::RRDDataSource::~RRDDataSource
~RRDDataSource()
Destructor.
Definition: rrd_descriptions.cpp:103
fawkes::RRDDefinition::set_rrd_manager
void set_rrd_manager(RRDManager *rrd_manager)
Set RRD manager.
Definition: rrd_descriptions.cpp:464
fawkes::RRDArchive::AVERAGE
@ AVERAGE
Averaging consolidation function.
Definition: rrd_descriptions.h:113
fawkes::RRDGraphArea::RRDGraphArea
RRDGraphArea(const char *def_name, const char *color, const char *legend, bool stacked=false)
Constructor.
Definition: rrd_descriptions.cpp:797
fawkes::RRDGraphGPrint::~RRDGraphGPrint
virtual ~RRDGraphGPrint()
Destructor.
Definition: rrd_descriptions.cpp:644
fawkes::RRDGraphDataDefinition::operator=
RRDGraphDataDefinition & operator=(const RRDGraphDataDefinition &rra)
Assignment operator.
Definition: rrd_descriptions.cpp:543
fawkes::OutOfMemoryException
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
fawkes::RRDGraphArea::to_string
virtual const char * to_string() const
Create string representation.
Definition: rrd_descriptions.cpp:860
fawkes::RRDArchive
RRD Archive description.
Definition: rrd_descriptions.h:109
fawkes::RRDDataSource::UNKNOWN
static const float UNKNOWN
Use for unknown min or max values.
Definition: rrd_descriptions.h:46
fawkes::RRDArchive::LAST
@ LAST
Last value consolidation function.
Definition: rrd_descriptions.h:116
fawkes::RRDGraphDefinition::RRDGraphDefinition
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.
Definition: rrd_descriptions.cpp:897
fawkes::RRDGraphDefinition::set_filename
void set_filename(const char *filename)
Set filename.
Definition: rrd_descriptions.cpp:997
fawkes::RRDGraphArea::operator=
RRDGraphArea & operator=(const RRDGraphArea &g)
Assignment operator.
Definition: rrd_descriptions.cpp:839
fawkes::RRDDataSource::ABSOLUTE
@ ABSOLUTE
Absolute value.
Definition: rrd_descriptions.h:42
fawkes::RRDGraphLine
Print graph line.
Definition: rrd_descriptions.h:352
fawkes::RRDArchive::~RRDArchive
~RRDArchive()
Destructor.
Definition: rrd_descriptions.cpp:210
fawkes::RRDGraphDataDefinition::RRDGraphDataDefinition
RRDGraphDataDefinition(const char *name, RRDArchive::ConsolidationFunction cf, const RRDDefinition *rrd_def, const char *ds_name=NULL)
DEF constructor.
Definition: rrd_descriptions.cpp:485
fawkes::Exception
Base class for exceptions in Fawkes.
Definition: exception.h:36