From 39077d366e960a11eb30d89918c24c383352e04a Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Fri, 1 Jun 2012 14:23:58 +0200 Subject: [PATCH] src/common.[ch]: Add rate_to_value(). --- src/common.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/common.h | 17 +++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/src/common.c b/src/common.c index 459c7024..4ca58d55 100644 --- a/src/common.c +++ b/src/common.c @@ -1230,7 +1230,101 @@ counter_t counter_diff (counter_t old_value, counter_t new_value) } return (diff); -} /* counter_t counter_to_gauge */ +} /* counter_t counter_diff */ + +int rate_to_value (value_t *ret_value, gauge_t rate, /* {{{ */ + rate_to_value_state_t *state, + int ds_type, cdtime_t t) +{ + derive_t delta_gauge; + cdtime_t delta_t; + + if (ds_type == DS_TYPE_GAUGE) + { + state->last_value.gauge = rate; + state->last_time = t; + + *ret_value = state->last_value; + return (0); + } + + /* Counter and absolute can't handle negative rates. Reset "last time" + * to zero, so that the next valid rate will re-initialize the + * structure. */ + if ((rate < 0.0) + && ((ds_type == DS_TYPE_COUNTER) + || (ds_type == DS_TYPE_ABSOLUTE))) + { + memset (state, 0, sizeof (*state)); + return (EINVAL); + } + + /* Another invalid state: The time is not increasing. */ + if (t <= state->last_time) + { + memset (state, 0, sizeof (*state)); + return (EINVAL); + } + + delta_t = t - state->last_time; + delta_gauge = (rate * CDTIME_T_TO_DOUBLE (delta_t)) + state->residual; + + /* Previous value is invalid. */ + if (state->last_time == 0) /* {{{ */ + { + if (ds_type == DS_TYPE_DERIVE) + { + state->last_value.derive = (derive_t) rate; + state->residual = rate - ((gauge_t) state->last_value.derive); + } + else if (ds_type == DS_TYPE_COUNTER) + { + state->last_value.counter = (counter_t) rate; + state->residual = rate - ((gauge_t) state->last_value.counter); + } + else if (ds_type == DS_TYPE_ABSOLUTE) + { + state->last_value.absolute = (absolute_t) rate; + state->residual = rate - ((gauge_t) state->last_value.absolute); + } + else + { + assert (23 == 42); + } + + state->last_time = t; + return (EAGAIN); + } /* }}} */ + + if (ds_type == DS_TYPE_DERIVE) + { + derive_t delta_derive = (derive_t) delta_gauge; + + state->last_value.derive += delta_derive; + state->residual = delta_gauge - ((gauge_t) delta_derive); + } + else if (ds_type == DS_TYPE_COUNTER) + { + counter_t delta_counter = (counter_t) delta_gauge; + + state->last_value.counter += delta_counter; + state->residual = delta_gauge - ((gauge_t) delta_counter); + } + else if (ds_type == DS_TYPE_ABSOLUTE) + { + absolute_t delta_absolute = (absolute_t) delta_gauge; + + state->last_value.absolute = delta_absolute; + state->residual = delta_gauge - ((gauge_t) delta_absolute); + } + else + { + assert (23 == 42); + } + + *ret_value = state->last_value; + return (0); +} /* }}} value_t rate_to_value */ int service_name_to_port_number (const char *service_name) { diff --git a/src/common.h b/src/common.h index 6b11b538..8a7d9865 100644 --- a/src/common.h +++ b/src/common.h @@ -47,6 +47,14 @@ || (strcasecmp ("no", (s)) == 0) \ || (strcasecmp ("off", (s)) == 0)) +struct rate_to_value_state_s +{ + value_t last_value; + cdtime_t last_time; + gauge_t residual; +}; +typedef struct rate_to_value_state_s rate_to_value_state_t; + char *sstrncpy (char *dest, const char *src, size_t n); int ssnprintf (char *dest, size_t n, const char *format, ...); char *sstrdup(const char *s); @@ -292,6 +300,15 @@ int read_file_contents (const char *filename, char *buf, int bufsize); counter_t counter_diff (counter_t old_value, counter_t new_value); +/* Convert a rate back to a value_t. When converting to a derive_t, counter_t + * or absoltue_t, take fractional residuals into account. This is important + * when scaling counters, for example. + * Returns zero on success. Returns EAGAIN when called for the first time; in + * this case the value_t is invalid and the next call should succeed. Other + * return values indicate an error. */ +int rate_to_value (value_t *ret_value, gauge_t rate, + rate_to_value_state_t *state, int ds_type, cdtime_t t); + /* Converts a service name (a string) to a port number * (in the range [1-65535]). Returns less than zero on error. */ int service_name_to_port_number (const char *service_name); -- 2.11.0