Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * rrd_descriptions.cpp - Fawkes RRD descriptions 00004 * 00005 * Created: Sat Dec 18 11:41:32 2010 00006 * Copyright 2006-2011 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <plugins/rrd/aspect/rrd_descriptions.h> 00025 #include <plugins/rrd/aspect/rrd_manager.h> 00026 #include <core/exceptions/software.h> 00027 #include <core/exceptions/system.h> 00028 #include <utils/misc/string_conversions.h> 00029 00030 #include <cstring> 00031 #include <cstdlib> 00032 #include <cstdio> 00033 #include <cfloat> 00034 00035 namespace fawkes { 00036 #if 0 /* just to make Emacs auto-indent happy */ 00037 } 00038 #endif 00039 00040 /** @class RRDDataSource <plugins/rrd/aspect/rrd_descriptions.h> 00041 * Class to represent a RRD data source. 00042 * @author Tim Niemueller 00043 */ 00044 00045 /** Use for unknown min or max values */ 00046 const float RRDDataSource::UNKNOWN = FLT_MIN; 00047 00048 /** Constructor for regular data source. 00049 * @param name name of the data source 00050 * @param type type of the data source, may not be COMPUTE. 00051 * @param heartbeat Number of seconds after which a new value must be received 00052 * before the value is considered to be unknown. 00053 * @param min minimum value, use UNKNOWN constant if not known 00054 * @param max maximum value, use UNKNOWN constant if not known 00055 */ 00056 RRDDataSource::RRDDataSource(const char *name, Type type, unsigned int heartbeat, 00057 float min, float max) 00058 : __name(strdup(name)), __type(type), __heartbeat(heartbeat), 00059 __min(min), __max(max), __rpn_expression(NULL), __string(NULL) 00060 { 00061 if (__type == COMPUTE) { 00062 throw IllegalArgumentException("Non-compute data source ctor used with " 00063 "COMPUTE type for DS %s", name); 00064 } 00065 } 00066 00067 00068 /** Constructor for expression RRDs. 00069 * @param name name of the data source 00070 * @param rpn_expression RPN expression 00071 */ 00072 RRDDataSource::RRDDataSource(const char *name, const char *rpn_expression) 00073 : __name(strdup(name)), __type(COMPUTE), __heartbeat(300), __min(UNKNOWN), 00074 __max(UNKNOWN), __rpn_expression(strdup(rpn_expression)), __string(NULL) 00075 { 00076 } 00077 00078 /** Copy constructor. 00079 * @param other other instance to copy 00080 */ 00081 RRDDataSource::RRDDataSource(const RRDDataSource &other) 00082 : __name(strdup(other.__name)), __type(other.__type), 00083 __heartbeat(other.__heartbeat), 00084 __min(other.__min), __max(other.__max), 00085 __rpn_expression(other.__rpn_expression ? strdup(other.__rpn_expression) : 0), 00086 __string(NULL) 00087 { 00088 } 00089 00090 /** Destructor. */ 00091 RRDDataSource::~RRDDataSource() 00092 { 00093 if (__string) free(__string); 00094 if (__name) free(__name); 00095 if (__rpn_expression) free(__rpn_expression); 00096 } 00097 00098 /** Assignment operator. 00099 * @param other Instance to copy data from. 00100 * @return reference to this instance 00101 */ 00102 RRDDataSource & 00103 RRDDataSource::operator=(const RRDDataSource &other) 00104 { 00105 if (__string) free(__string); 00106 if (__name) free(__name); 00107 if (__rpn_expression) free(__rpn_expression); 00108 __string = NULL; 00109 __rpn_expression = NULL; 00110 __name = strdup(other.__name); 00111 __type = other.__type; 00112 __heartbeat = other.__heartbeat; 00113 __min = other.__min; 00114 __max = other.__max; 00115 if (other.__rpn_expression) __rpn_expression = strdup(other.__rpn_expression); 00116 00117 return *this; 00118 } 00119 00120 00121 /** Get string reprensetation. 00122 * @return string representation suitable to be bassed to rrd_create(). 00123 */ 00124 const char * 00125 RRDDataSource::to_string() const 00126 { 00127 if (! __string) { 00128 if (__type == COMPUTE) { 00129 if (asprintf(&__string, "DS:%s:COMPUTE:%s", __name, __rpn_expression) == -1) { 00130 throw OutOfMemoryException("Failed to create DS string for %s", __name); 00131 } 00132 } else { 00133 const char *type_string; 00134 switch (__type) { 00135 case COUNTER: type_string = "COUNTER"; break; 00136 case DERIVE: type_string = "DERIVE"; break; 00137 case ABSOLUTE: type_string = "ABSOLUTE"; break; 00138 default: type_string = "GAUGE"; break; 00139 } 00140 char min_s[32]; 00141 char max_s[32]; 00142 if (__min == UNKNOWN) { 00143 strcpy(min_s, "U"); 00144 } else { 00145 snprintf(min_s, 32, "%f", __min); 00146 } 00147 if (__max == UNKNOWN) { 00148 strcpy(max_s, "U"); 00149 } else { 00150 snprintf(max_s, 32, "%f", __max); 00151 } 00152 if (asprintf(&__string, "DS:%s:%s:%u:%s:%s", __name, type_string, 00153 __heartbeat, min_s, max_s) == -1) { 00154 throw OutOfMemoryException("Failed to create DS string for %s", __name); 00155 } 00156 } 00157 } 00158 00159 return __string; 00160 } 00161 00162 00163 /** @class RRDArchive <plugins/rrd/aspect/rrd_descriptions.h> 00164 * RRD Archive description. 00165 * @author Tim Niemueller 00166 */ 00167 00168 /** Constructor. 00169 * @param cf consolidation function 00170 * @param xff The xfiles factor defines what part of a consolidation interval 00171 * may be made up from *UNKNOWN* data while the consolidated value is still 00172 * regarded as known. It is given as the ratio of allowed *UNKNOWN* PDPs to 00173 * the number of PDPs in the interval. Thus, it ranges from 0 to 1 (exclusive). 00174 * @param steps defines how many of these primary data points are used to build 00175 * a consolidated data point which then goes into the archive. 00176 * @param rows defines how many generations of data values are kept in an RRA. 00177 * Obviously, this has to be greater than zero. 00178 */ 00179 RRDArchive::RRDArchive(ConsolidationFunction cf, float xff, 00180 unsigned int steps, unsigned int rows) 00181 : __cf(cf), __xff(xff), __steps(steps), __rows(rows), __string(NULL) 00182 { 00183 } 00184 00185 00186 /** Copy constructor. 00187 * @param rra instance to copy 00188 */ 00189 RRDArchive::RRDArchive(const RRDArchive &rra) 00190 : __cf(rra.__cf), __xff(rra.__xff), __steps(rra.__steps), __rows(rra.__rows), 00191 __string(NULL) 00192 { 00193 } 00194 00195 00196 /** Destructor. */ 00197 RRDArchive::~RRDArchive() 00198 { 00199 if (__string) free(__string); 00200 } 00201 00202 /** Assignment operator. 00203 * @param rra instance to copy from 00204 * @return reference to this instance 00205 */ 00206 RRDArchive & 00207 RRDArchive::operator=(const RRDArchive &rra) 00208 { 00209 if (__string) free(__string); 00210 __string = NULL; 00211 __cf = rra.__cf; 00212 __xff = rra.__xff; 00213 __steps = rra.__steps; 00214 __rows = rra.__rows; 00215 return *this; 00216 } 00217 00218 /** Get string representation. 00219 * @return string representation suitable to be passed to rrd_create(). 00220 */ 00221 const char * 00222 RRDArchive::to_string() const 00223 { 00224 if (! __string) { 00225 const char *cf_string; 00226 switch (__cf) { 00227 case MIN: cf_string = "MIN"; break; 00228 case MAX: cf_string = "MAX"; break; 00229 case LAST: cf_string = "LAST"; break; 00230 default: cf_string = "AVERAGE"; break; 00231 } 00232 if (asprintf(&__string, "RRA:%s:%f:%u:%u", cf_string, 00233 __xff, __steps, __rows) == -1) { 00234 throw OutOfMemoryException("Failed to create RRA string"); 00235 } 00236 } 00237 00238 return __string; 00239 } 00240 00241 /** Convert consolidation function type to string. 00242 * @param cf consolidation function type 00243 * @return string representation of @p cf, suitable for RRA lines. 00244 */ 00245 const char * 00246 RRDArchive::cf_to_string(ConsolidationFunction cf) 00247 { 00248 switch (cf) { 00249 case RRDArchive::MIN: return "MIN"; break; 00250 case RRDArchive::MAX: return "MAX"; break; 00251 case RRDArchive::LAST: return "LAST"; break; 00252 default: return "AVERAGE"; break; 00253 } 00254 } 00255 00256 /** @class RRDDefinition <plugins/rrd/aspect/rrd_descriptions.h> 00257 * RRD Definition. 00258 * This class describes everything required to create an RRD file. 00259 * It does not represent all the options rrdtool provides, but a reasonable 00260 * subset. 00261 * @author Tim Niemueller 00262 */ 00263 00264 /** Constructor with default RRAs. 00265 * This creates the RRD definition with the default RRAs produced by 00266 * get_default_rra(). 00267 * @param name RRD name 00268 * @param ds data sources 00269 * @param step_sec Specifies the base interval in seconds with which data 00270 * will be fed into the RRD. 00271 * @param recreate if true existing RRD files will be overwritten, otherwise 00272 * data is appended. 00273 */ 00274 RRDDefinition::RRDDefinition(const char *name, std::vector<RRDDataSource> &ds, 00275 unsigned int step_sec, bool recreate) 00276 : __name(strdup(name)), __step_sec(step_sec), __recreate(recreate), 00277 __ds(ds), __rra(get_default_rra()), __filename(NULL), __rrd_manager(NULL) 00278 { 00279 } 00280 00281 /** Constructor. 00282 * @param name RRD name 00283 * @param ds data sources 00284 * @param rra RRAs for this RRD. 00285 * @param step_sec Specifies the base interval in seconds with which data 00286 * will be fed into the RRD. 00287 * @param recreate if true existing RRD files will be overwritten, otherwise 00288 * data is appended. 00289 */ 00290 RRDDefinition::RRDDefinition(const char *name, 00291 std::vector<RRDDataSource> &ds, 00292 std::vector<RRDArchive> &rra, 00293 unsigned int step_sec, bool recreate) 00294 : __name(strdup(name)), __step_sec(step_sec), __recreate(recreate), __ds(ds), 00295 __rra(rra), __filename(NULL), __rrd_manager(NULL) 00296 { 00297 } 00298 00299 00300 /** Copy constructor. 00301 * @param other instance to clone 00302 */ 00303 RRDDefinition::RRDDefinition(const RRDDefinition &other) 00304 : __name(strdup(other.__name)), __step_sec(other.__step_sec), 00305 __recreate(other.__recreate), __ds(other.__ds), __rra(other.__rra), 00306 __filename(other.__filename ? strdup(other.__filename) : 0), 00307 __rrd_manager(NULL) 00308 { 00309 } 00310 00311 /** Assignment operator. 00312 * @param other other instance to copy from 00313 * @return reference to this instance. 00314 */ 00315 RRDDefinition & 00316 RRDDefinition::operator=(const RRDDefinition &other) 00317 { 00318 if (__name) free(__name); 00319 if (__filename) free(__filename); 00320 if (__rrd_manager) __rrd_manager->remove_rrd(this); 00321 __filename = NULL; 00322 __rrd_manager = NULL; 00323 __name = strdup(other.__name); 00324 __step_sec = other.__step_sec; 00325 __recreate = other.__recreate; 00326 __ds = other.__ds; 00327 __rra = other.__rra; 00328 if (other.__filename) __filename=strdup(other.__filename); 00329 return *this; 00330 } 00331 00332 /** Destructor. */ 00333 RRDDefinition::~RRDDefinition() 00334 { 00335 if (__rrd_manager) __rrd_manager->remove_rrd(this); 00336 00337 if (__name) free(__name); 00338 if (__filename) free(__filename); 00339 } 00340 00341 /** Get default RRAs. They correspond to the following and assume a 00342 * 10 second step size. 00343 * @code 00344 * "RRA:AVERAGE:0.5:1:720" # 2 hours of 10 sec averages 00345 * "RRA:AVERAGE:0.5:3:1680" # 12 hours of 30 sec averages 00346 * "RRA:AVERAGE:0.5:30:456" # 1 day of 5 min averages 00347 * "RRA:AVERAGE:0.5:180:412" # 7 days of 30 min averages 00348 * "RRA:AVERAGE:0.5:720:439" # 4 weeks of 2 hour averages 00349 * "RRA:AVERAGE:0.5:8640:402" # 1 year of 1 day averages 00350 * "RRA:MIN:0.5:1:720" 00351 * "RRA:MIN:0.5:3:1680" 00352 * "RRA:MIN:0.5:30:456" 00353 * "RRA:MIN:0.5:180:412" 00354 * "RRA:MIN:0.5:720:439" 00355 * "RRA:MIN:0.5:8640:402" 00356 * "RRA:MAX:0.5:1:720" 00357 * "RRA:MAX:0.5:3:1680" 00358 * "RRA:MAX:0.5:30:456" 00359 * "RRA:MAX:0.5:180:412" 00360 * "RRA:MAX:0.5:720:439" 00361 * "RRA:MAX:0.5:8640:402" 00362 * @endcode 00363 * @return vector of RRDArchive representing the described RRAs. 00364 */ 00365 const std::vector<RRDArchive> 00366 RRDDefinition::get_default_rra() 00367 { 00368 std::vector<RRDArchive> rv; 00369 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 1, 720)); 00370 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 3, 1680)); 00371 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 30, 456)); 00372 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 180, 412)); 00373 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 720, 439)); 00374 rv.push_back(RRDArchive(RRDArchive::AVERAGE, 0.5, 8640, 402)); 00375 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 1, 720)); 00376 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 3, 1680)); 00377 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 30, 456)); 00378 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 180, 412)); 00379 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 720, 439)); 00380 rv.push_back(RRDArchive(RRDArchive::MIN, 0.5, 8640, 402)); 00381 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 1, 720)); 00382 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 3, 1680)); 00383 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 30, 456)); 00384 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 180, 412)); 00385 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 720, 439)); 00386 rv.push_back(RRDArchive(RRDArchive::MAX, 0.5, 8640, 402)); 00387 return rv; 00388 } 00389 00390 00391 /** Find data source index. 00392 * @param ds_name name of the data source 00393 * @return index of found data source 00394 * @exception Exception thrown if the data source could not be found 00395 */ 00396 size_t 00397 RRDDefinition::find_ds_index(const char *ds_name) const 00398 { 00399 for (size_t i = 0; i < __ds.size(); ++i) { 00400 if (strcmp(__ds[i].get_name(), ds_name) == 0) return i; 00401 } 00402 00403 throw Exception("Data source name %s not found", ds_name); 00404 } 00405 00406 /** Set filename. 00407 * This can be done only once. Do not do this manually, rather let the RRDManager 00408 * handle this! 00409 * @param filename new filename, should be absolute, otherwise considered 00410 * relative to current working directory. 00411 */ 00412 void 00413 RRDDefinition::set_filename(const char *filename) 00414 { 00415 if (__filename) { 00416 throw Exception("Graph definition %s: filename has already been set!", __name); 00417 } 00418 __filename = strdup(filename); 00419 } 00420 00421 00422 /** Set RRD manager. 00423 * This can be done only once. Do not do this manually, rather let the RRDManager 00424 * handle this! The RRD manager is used to unregister this RRD if it is deleted. 00425 * This is a precaution to avoid dangling RRDs. 00426 * @param rrd_manager RRD manager to use 00427 */ 00428 void 00429 RRDDefinition::set_rrd_manager(RRDManager *rrd_manager) 00430 { 00431 if (__rrd_manager) { 00432 throw Exception("RRD definition %s: RRD manager has already been set", __name); 00433 } 00434 __rrd_manager = rrd_manager; 00435 } 00436 00437 00438 00439 /** @class RRDGraphDataDefinition <plugins/rrd/aspect/rrd_descriptions.h> 00440 * Represent data definition in graph arguments. 00441 * @author Tim Niemueller 00442 * Currently supports only DEF and CDEF definitions. 00443 */ 00444 00445 /** DEF constructor. 00446 * @param name name of the graph data source 00447 * @param cf consolidation function to apply if needed 00448 * @param rrd_def RRD definition to use 00449 * @param ds_name data source name in RRD, @p rrd_def will be queried for the 00450 * data source. If ds_name is NULL, @p name will be used as the data source name. 00451 */ 00452 RRDGraphDataDefinition::RRDGraphDataDefinition(const char *name, 00453 RRDArchive::ConsolidationFunction cf, 00454 const RRDDefinition *rrd_def, 00455 const char *ds_name) 00456 : __name(strdup(name)), __rrd_def(rrd_def), 00457 __ds_name(ds_name ? strdup(ds_name) : strdup(name)), 00458 __rpn_expression(NULL), __cf(cf), __string(NULL) 00459 { 00460 } 00461 00462 00463 /** CDEF constructor. 00464 * @param name name of the graph data source 00465 * @param rpn_expression RPN expression 00466 */ 00467 RRDGraphDataDefinition::RRDGraphDataDefinition(const char *name, 00468 const char *rpn_expression) 00469 : __name(strdup(name)), __rrd_def(0), __ds_name(NULL), 00470 __rpn_expression(strdup(rpn_expression)), 00471 __cf(RRDArchive::AVERAGE), __string(NULL) 00472 { 00473 } 00474 00475 00476 /** Copy constructor. 00477 * @param other instance to clone 00478 */ 00479 RRDGraphDataDefinition::RRDGraphDataDefinition(const RRDGraphDataDefinition &other) 00480 : __name(strdup(other.__name)), __rrd_def(other.__rrd_def), 00481 __ds_name(other.__ds_name ? strdup(other.__ds_name) : NULL), 00482 __rpn_expression(other.__rpn_expression ? strdup(other.__rpn_expression) : 0), 00483 __cf(other.__cf), __string(NULL) 00484 { 00485 } 00486 00487 00488 /** Destructor. */ 00489 RRDGraphDataDefinition::~RRDGraphDataDefinition() 00490 { 00491 if (__name) free(__name); 00492 if (__ds_name) free(__ds_name); 00493 if (__rpn_expression) free(__rpn_expression); 00494 if (__string) free(__string); 00495 } 00496 00497 /** Assignment operator. 00498 * @param other instance to copy from 00499 * @return reference to this instance 00500 */ 00501 RRDGraphDataDefinition & 00502 RRDGraphDataDefinition::operator=(const RRDGraphDataDefinition &other) 00503 { 00504 if (__string) free(__string); 00505 if (__ds_name) free(__ds_name); 00506 if (__name) free(__name); 00507 if (__rpn_expression) free(__rpn_expression); 00508 00509 __string = NULL; 00510 __rpn_expression = NULL; 00511 __name = strdup(other.__name); 00512 __rrd_def = other.__rrd_def; 00513 if (other.__ds_name) __ds_name = strdup(other.__ds_name); 00514 if (other.__rpn_expression) __rpn_expression = other.__rpn_expression; 00515 __cf = other.__cf; 00516 00517 return *this; 00518 } 00519 00520 00521 /** Create string representation. 00522 * @return string representation suitable for rrd_graph_v(). 00523 */ 00524 const char * 00525 RRDGraphDataDefinition::to_string() const 00526 { 00527 if (! __string) { 00528 if (__rpn_expression) { 00529 if (asprintf(&__string, "CDEF:%s=%s", __name, __rpn_expression) == -1) { 00530 throw OutOfMemoryException("Failed to create RRA string"); 00531 } 00532 } else { 00533 size_t ds_index = __rrd_def->find_ds_index(__ds_name); 00534 00535 if (asprintf(&__string, "DEF:%s=%s:%s:%s", __name, __rrd_def->get_filename(), 00536 __rrd_def->get_ds(ds_index).get_name(), 00537 RRDArchive::cf_to_string(__cf)) == -1) { 00538 throw OutOfMemoryException("Failed to create RRA string"); 00539 } 00540 } 00541 } 00542 00543 return __string; 00544 } 00545 00546 /** @class RRDGraphElement <plugins/rrd/aspect/rrd_descriptions.h> 00547 * Interface for graph elements. 00548 * This super class provides the general interface for the different 00549 * existing graph elements. 00550 * @author Tim Niemueller 00551 * 00552 * @fn RRDGraphElement * RRDGraphElement::clone() const 00553 * Clone this element. 00554 * The clone function is needed to copy an object without knowing its type and 00555 * therefore without calling its copy constructor. 00556 * @return new copied instance 00557 */ 00558 00559 /** Create string representation. 00560 * @return string suitable for rrd_graph_v(). 00561 */ 00562 const char * 00563 RRDGraphElement::to_string() const 00564 { 00565 throw NotImplementedException("Invalid graph element"); 00566 } 00567 00568 00569 00570 /** @class RRDGraphGPrint <plugins/rrd/aspect/rrd_descriptions.h> 00571 * Print string inside graph. 00572 * @author Tim Niemueller 00573 */ 00574 00575 /** Constructor. 00576 * @param def_name Data definition for this graph element. 00577 * @param cf consolidation function to use 00578 * @param format Format string, cf. man rrdgraph_graph(1). 00579 */ 00580 RRDGraphGPrint::RRDGraphGPrint(const char *def_name, 00581 RRDArchive::ConsolidationFunction cf, 00582 const char *format) 00583 : __def_name(strdup(def_name)), __cf(cf), __format(strdup(format)), 00584 __string(NULL) 00585 { 00586 } 00587 00588 /** Copy constructor. 00589 * @param other instance to copy 00590 */ 00591 RRDGraphGPrint::RRDGraphGPrint(const RRDGraphGPrint &other) 00592 : __def_name(strdup(other.__def_name)), __cf(other.__cf), 00593 __format(strdup(other.__format)), __string(NULL) 00594 { 00595 } 00596 00597 00598 /** Destructor. */ 00599 RRDGraphGPrint::~RRDGraphGPrint() 00600 { 00601 if (__def_name) free(__def_name); 00602 if (__format) free(__format); 00603 if (__string) free(__string); 00604 } 00605 00606 /** Assignment operator. 00607 * @param g matching graph element to assign 00608 * @return reference to this instance 00609 */ 00610 RRDGraphGPrint & 00611 RRDGraphGPrint::operator=(const RRDGraphGPrint &g) 00612 { 00613 if (__def_name) free(__def_name); 00614 if (__format) free(__format); 00615 if (__string) free(__string); 00616 00617 __string = NULL; 00618 __def_name = strdup(g.__def_name); 00619 __cf = g.__cf; 00620 __format = strdup(g.__format); 00621 00622 return *this; 00623 } 00624 00625 00626 const char * 00627 RRDGraphGPrint::to_string() const 00628 { 00629 if (! __string) { 00630 if (asprintf(&__string, "GPRINT:%s:%s:%s", __def_name, 00631 RRDArchive::cf_to_string(__cf), __format) == -1) { 00632 throw OutOfMemoryException("Failed to create RRD graph GPRINT string"); 00633 } 00634 } 00635 00636 return __string; 00637 } 00638 00639 00640 /** @class RRDGraphLine <plugins/rrd/aspect/rrd_descriptions.h> 00641 * Print graph line. 00642 * @author Tim Niemueller 00643 */ 00644 00645 /** Constructor. 00646 * @param def_name Data definition for this graph element. 00647 * @param width line width 00648 * @param color color hash string (HTML style, e.g. FF0000) 00649 * @param legend legend string 00650 * @param stacked true to stack on previous graph element 00651 */ 00652 RRDGraphLine::RRDGraphLine(const char *def_name, float width, const char *color, 00653 const char *legend, bool stacked) 00654 : __def_name(strdup(def_name)), __width(width), __color(strdup(color)), 00655 __legend(strdup(legend)), __stacked(stacked), __string(NULL) 00656 { 00657 } 00658 00659 /** Copy ctor. 00660 * @param other instance to copy 00661 */ 00662 RRDGraphLine::RRDGraphLine(const RRDGraphLine &other) 00663 : __def_name(strdup(other.__def_name)), __width(other.__width), 00664 __color(strdup(other.__color)), 00665 __legend(strdup(other.__legend)), __stacked(other.__stacked), __string(NULL) 00666 { 00667 } 00668 00669 00670 /** Destructor. */ 00671 RRDGraphLine::~RRDGraphLine() 00672 { 00673 if (__def_name) free(__def_name); 00674 if (__color) free(__color); 00675 if (__legend) free(__legend); 00676 if (__string) free(__string); 00677 } 00678 00679 00680 /** Assignment operator. 00681 * @param g matching graph element to assign 00682 * @return reference to this instance 00683 */ 00684 RRDGraphLine & 00685 RRDGraphLine::operator=(const RRDGraphLine &g) 00686 { 00687 if (__def_name) free(__def_name); 00688 if (__color) free(__color); 00689 if (__legend) free(__legend); 00690 if (__string) free(__string); 00691 00692 __string = NULL; 00693 __def_name = strdup(g.__def_name); 00694 __width = g.__width; 00695 __color = strdup(g.__color); 00696 __legend = strdup(g.__legend); 00697 __stacked = g.__stacked; 00698 00699 return *this; 00700 } 00701 00702 00703 const char * 00704 RRDGraphLine::to_string() const 00705 { 00706 if (! __string) { 00707 if (asprintf(&__string, "LINE%f:%s#%s:%s%s", __width, __def_name, __color, 00708 __legend, __stacked ? ":STACK" : "") == -1) { 00709 throw OutOfMemoryException("Failed to create RRD graph LINE string"); 00710 } 00711 } 00712 00713 return __string; 00714 } 00715 00716 00717 /** @class RRDGraphArea <plugins/rrd/aspect/rrd_descriptions.h> 00718 * Print graph area. 00719 * @author Tim Niemueller 00720 */ 00721 00722 /** Constructor. 00723 * @param def_name Data definition for this graph element. 00724 * @param color color hash string (HTML style, e.g. FF0000) 00725 * @param legend legend string 00726 * @param stacked true to stack on previous graph element 00727 */ 00728 RRDGraphArea::RRDGraphArea(const char *def_name,const char *color, 00729 const char *legend, bool stacked) 00730 : __def_name(strdup(def_name)), __color(strdup(color)), 00731 __legend(strdup(legend)), __stacked(stacked), __string(NULL) 00732 { 00733 } 00734 00735 00736 /** Copy ctor. 00737 * @param other instance to copy 00738 */ 00739 RRDGraphArea::RRDGraphArea(const RRDGraphArea &other) 00740 : __def_name(strdup(other.__def_name)), __color(strdup(other.__color)), 00741 __legend(strdup(other.__legend)), __stacked(other.__stacked), __string(NULL) 00742 { 00743 } 00744 00745 00746 /** Destructor. */ 00747 RRDGraphArea::~RRDGraphArea() 00748 { 00749 if (__def_name) free(__def_name); 00750 if (__color) free(__color); 00751 if (__legend) free(__legend); 00752 if (__string) free(__string); 00753 } 00754 00755 00756 /** Assignment operator. 00757 * @param g matching graph element to assign 00758 * @return reference to this instance 00759 */ 00760 RRDGraphArea & 00761 RRDGraphArea::operator=(const RRDGraphArea &g) 00762 { 00763 if (__def_name) free(__def_name); 00764 if (__color) free(__color); 00765 if (__legend) free(__legend); 00766 if (__string) free(__string); 00767 00768 __string = NULL; 00769 __def_name = strdup(g.__def_name); 00770 __color = strdup(g.__color); 00771 __legend = strdup(g.__legend); 00772 __stacked = g.__stacked; 00773 00774 return *this; 00775 } 00776 00777 00778 const char * 00779 RRDGraphArea::to_string() const 00780 { 00781 if (! __string) { 00782 if (asprintf(&__string, "AREA:%s#%s:%s%s", __def_name, __color, __legend, 00783 __stacked ? ":STACK" : "") == -1) { 00784 throw OutOfMemoryException("Failed to create RRD graph AREA string"); 00785 } 00786 } 00787 00788 return __string; 00789 } 00790 00791 00792 /** @class RRDGraphDefinition <plugins/rrd/aspect/rrd_descriptions.h> 00793 * Class representing a graph definition. 00794 * This graph definition is used to generate all required parameters to create 00795 * a graph from an RRD. 00796 * @author Tim Niemueller 00797 */ 00798 00799 /** Constructor. 00800 * @param name name of this graph definition, used internally, name must be 00801 * unique among all registered graphs. 00802 * @param rrd_def pointer to definition of the RRD to graph 00803 * @param start time from where to start graphing. Maybe an absolute time or 00804 * a negative number for relative times, e.g. "-300" for 5 minutes back from now. 00805 * @param end time where to end graphing. Maybe an absolute time or a negative 00806 * number for relative times, e.g. "-300" for 5 minutes back from now. 00807 * @param step step size in seconds 00808 * @param title Graph title to print on top of graph 00809 * @param vertical_label string printed rotated by 90° counter-clockwise besides 00810 * the vertical axis. Usually should carry description of the Y axis units. 00811 * @param update_interval The interval at which the graph should be generated. 00812 * @param slope_mode true to enable slope mode when graphing 00813 * @param def data definitions for the graph 00814 * @param elements elements to print in the graph. This graph definition takes 00815 * ownership of the graph elemenets and will delete them in its dtor. 00816 */ 00817 RRDGraphDefinition::RRDGraphDefinition(const char *name, RRDDefinition *rrd_def, 00818 const char *title, 00819 const char *vertical_label, 00820 std::vector<RRDGraphDataDefinition> &def, 00821 std::vector<RRDGraphElement *> &elements, 00822 time_t start, time_t end, unsigned int step, 00823 unsigned int update_interval, 00824 bool slope_mode) 00825 : __name(strdup(name)), __rrd_def(rrd_def), 00826 __start(start), __end(end), __step(step), 00827 __title(strdup(title)), __vertical_label(strdup(vertical_label)), 00828 __update_interval(update_interval), __slope_mode(slope_mode), 00829 __defs(def), __elements(elements) 00830 { 00831 __filename = NULL; 00832 __argv = NULL; 00833 __argc = 0; 00834 __fonts.push_back("LEGEND:10:"); 00835 __fonts.push_back("UNIT:8:"); 00836 __fonts.push_back("TITLE:12:"); 00837 __fonts.push_back("AXIS:8:"); 00838 __width = 560; 00839 __width_s = strdup(StringConversions::to_string(__width).c_str()); 00840 __start_s = strdup(StringConversions::to_string(__start).c_str()); 00841 __end_s = strdup(StringConversions::to_string(__end).c_str()); 00842 __step_s = strdup(StringConversions::to_string(__step).c_str()); 00843 } 00844 00845 /** Copy constructor. 00846 * @param other instance to copy 00847 */ 00848 RRDGraphDefinition::RRDGraphDefinition(const RRDGraphDefinition &other) 00849 : __name(strdup(other.__name)), __rrd_def(other.__rrd_def), 00850 __start(other.__start), __end(other.__end), __step(other.__step), 00851 __title(strdup(other.__title)), 00852 __vertical_label(strdup(other.__vertical_label)), 00853 __update_interval(other.__update_interval), 00854 __slope_mode(other.__slope_mode), __defs(other.__defs), 00855 __width(other.__width), __fonts(other.__fonts), 00856 __filename(strdup(other.__filename)) 00857 { 00858 std::vector<RRDGraphElement *>::const_iterator i; 00859 for (i = other.__elements.begin(); i != other.__elements.end(); ++i) { 00860 __elements.push_back((*i)->clone()); 00861 } 00862 00863 __argv = NULL; 00864 __argc = 0; 00865 __width_s = strdup(StringConversions::to_string(__width).c_str()); 00866 __start_s = strdup(StringConversions::to_string(__start).c_str()); 00867 __end_s = strdup(StringConversions::to_string(__end).c_str()); 00868 __step_s = strdup(StringConversions::to_string(__step).c_str()); 00869 } 00870 00871 00872 /** Destructor. */ 00873 RRDGraphDefinition::~RRDGraphDefinition() 00874 { 00875 if (__filename) free(__filename); 00876 if (__argv) free(__argv); 00877 if (__name) free(__name); 00878 if (__title) free(__title); 00879 if (__vertical_label) free(__vertical_label); 00880 00881 free(__width_s); 00882 free(__start_s); 00883 free(__end_s); 00884 free(__step_s); 00885 00886 std::vector<RRDGraphElement *>::iterator i; 00887 for (i = __elements.begin(); i != __elements.end(); ++i) { 00888 delete *i; 00889 } 00890 } 00891 00892 /** Set filename. 00893 * This can be done only once. Do not do this manually, rather let the RRDManager 00894 * handle this! 00895 * @param filename new filename, should be absolute, otherwise considered 00896 * relative to current working directory. 00897 */ 00898 void 00899 RRDGraphDefinition::set_filename(const char *filename) 00900 { 00901 if (__filename) { 00902 throw Exception("Graph definition for RRD %s: filename has already been set!", 00903 __rrd_def->get_name()); 00904 } 00905 __filename = strdup(filename); 00906 } 00907 00908 /** Get argument array and size. 00909 * @param argc upon completion contains the number of arguments in the 00910 * return value. 00911 * @return argument array suitable for rrd_create_v(). 00912 */ 00913 const char ** 00914 RRDGraphDefinition::get_argv(size_t &argc) const 00915 { 00916 if (__argv == NULL) { 00917 // "graph" filename --disable-rrdtool-tag --width ... --start ... --end ... 00918 // [fonts] --title ... --vertical-label ... [--slope-mode] DEFS... ELEMS... 00919 __argc = 16 + __fonts.size() * 2 + __defs.size() + __elements.size(); 00920 __argv = (const char **)malloc(__argc * sizeof(char *)); 00921 size_t i = 0; 00922 __argv[i++] = "graph"; 00923 __argv[i++] = __filename; 00924 __argv[i++] = "--disable-rrdtool-tag"; 00925 __argv[i++] = "--width"; 00926 __argv[i++] = __width_s; 00927 __argv[i++] = "--start"; 00928 __argv[i++] = __start_s; 00929 __argv[i++] = "--end"; 00930 __argv[i++] = __end_s; 00931 __argv[i++] = "--step"; 00932 __argv[i++] = __step_s; 00933 __argv[i++] = "--title"; 00934 __argv[i++] = __title; 00935 __argv[i++] = "--vertical-label"; 00936 00937 if (strcmp(__vertical_label, "") == 0) { 00938 __argv[i++] = " "; 00939 } else { 00940 __argv[i++] = __vertical_label; 00941 } 00942 00943 if (__slope_mode) __argv[i++] = "--slope-mode"; 00944 00945 std::vector<const char *>::const_iterator f; 00946 for (f = __fonts.begin(); f != __fonts.end(); ++f) { 00947 __argv[i++] = "--font"; 00948 __argv[i++] = *f; 00949 } 00950 00951 std::vector<RRDGraphDataDefinition>::const_iterator d; 00952 for (d = __defs.begin(); d != __defs.end(); ++d) { 00953 __argv[i++] = d->to_string(); 00954 } 00955 00956 std::vector<RRDGraphElement *>::const_iterator e; 00957 for (e = __elements.begin(); e != __elements.end(); ++e) { 00958 __argv[i++] = (*e)->to_string(); 00959 } 00960 00961 __argc = i; 00962 } 00963 00964 argc = __argc; 00965 return __argv; 00966 } 00967 00968 00969 } // end namespace fawkes