char name[6 * DATA_MAX_NAME_LEN];
int values_num;
gauge_t *values_gauge;
- counter_t *values_counter;
+ value_t *values_raw;
/* Time contained in the package
* (for calculating rates) */
time_t last_time;
memset (ce, '\0', sizeof (cache_entry_t));
ce->values_num = values_num;
- ce->values_gauge = (gauge_t *) calloc (values_num, sizeof (gauge_t));
- ce->values_counter = (counter_t *) calloc (values_num, sizeof (counter_t));
- if ((ce->values_gauge == NULL) || (ce->values_counter == NULL))
+ ce->values_gauge = calloc (values_num, sizeof (*ce->values_gauge));
+ ce->values_raw = calloc (values_num, sizeof (*ce->values_raw));
+ if ((ce->values_gauge == NULL) || (ce->values_raw == NULL))
{
sfree (ce->values_gauge);
- sfree (ce->values_counter);
+ sfree (ce->values_raw);
sfree (ce);
ERROR ("utils_cache: cache_alloc: calloc failed.");
return (NULL);
return;
sfree (ce->values_gauge);
- sfree (ce->values_counter);
+ sfree (ce->values_raw);
sfree (ce);
} /* void cache_free */
return (0);
} /* int uc_send_notification */
+static void uc_check_range (const data_set_t *ds, cache_entry_t *ce)
+{
+ int i;
+
+ for (i = 0; i < ds->ds_num; i++)
+ {
+ if (isnan (ce->values_gauge[i]))
+ continue;
+ else if (ce->values_gauge[i] < ds->ds[i].min)
+ ce->values_gauge[i] = NAN;
+ else if (ce->values_gauge[i] > ds->ds[i].max)
+ ce->values_gauge[i] = NAN;
+ }
+} /* void uc_check_range */
+
static int uc_insert (const data_set_t *ds, const value_list_t *vl,
const char *key)
{
ce = cache_alloc (ds->ds_num);
if (ce == NULL)
{
+ sfree (key_copy);
ERROR ("uc_insert: cache_alloc (%i) failed.", ds->ds_num);
return (-1);
}
for (i = 0; i < ds->ds_num; i++)
{
- if (ds->ds[i].type == DS_TYPE_COUNTER)
+ switch (ds->ds[i].type)
{
- ce->values_gauge[i] = NAN;
- ce->values_counter[i] = vl->values[i].counter;
- }
- else /* if (ds->ds[i].type == DS_TYPE_GAUGE) */
- {
- ce->values_gauge[i] = vl->values[i].gauge;
- }
+ case DS_TYPE_COUNTER:
+ ce->values_gauge[i] = NAN;
+ ce->values_raw[i].counter = vl->values[i].counter;
+ break;
+
+ case DS_TYPE_GAUGE:
+ ce->values_gauge[i] = vl->values[i].gauge;
+ ce->values_raw[i].gauge = vl->values[i].gauge;
+ break;
+
+ case DS_TYPE_DERIVE:
+ ce->values_gauge[i] = NAN;
+ ce->values_raw[i].derive = vl->values[i].derive;
+ break;
+
+ case DS_TYPE_ABSOLUTE:
+ ce->values_gauge[i] = NAN;
+ if (vl->interval > 0)
+ ce->values_gauge[i] = ((double) vl->values[i].absolute)
+ / ((double) vl->interval);
+ ce->values_raw[i].absolute = vl->values[i].absolute;
+ break;
+
+ default:
+ /* This shouldn't happen. */
+ ERROR ("uc_insert: Don't know how to handle data source type %i.",
+ ds->ds[i].type);
+ return (-1);
+ } /* switch (ds->ds[i].type) */
} /* for (i) */
+ /* Prune invalid gauge data */
+ uc_check_range (ds, ce);
+
ce->last_time = vl->time;
ce->last_update = time (NULL);
ce->interval = vl->interval;
{
ERROR ("uc_purge: realloc failed.");
c_avl_iterator_destroy (iter);
+ pthread_mutex_unlock (&cache_lock);
return (-1);
}
ERROR ("uc_check_timeout: c_avl_remove (%s) failed.", keys[i]);
}
sfree (keys[i]);
+ sfree (key);
cache_free (ce);
}
- else if (status == 1) /* persist */
+ else if (status == 2) /* persist */
{
DEBUG ("uc_check_timeout: %s is missing, sending notification.",
keys[i]);
ce->state = STATE_MISSING;
}
- else if (status == 2) /* do not persist */
+ else if (status == 1) /* do not persist */
{
if (ce->state == STATE_MISSING)
{
}
else
{
- WARNING ("uc_check_timeout: ut_check_interesting (%s) returned ",
+ WARNING ("uc_check_timeout: ut_check_interesting (%s) returned "
"invalid status %i.",
keys[i], status);
}
for (i = 0; i < ds->ds_num; i++)
{
- if (ds->ds[i].type == DS_TYPE_COUNTER)
+ switch (ds->ds[i].type)
{
- counter_t diff;
+ case DS_TYPE_COUNTER:
+ {
+ counter_t diff;
+
+ /* check if the counter has wrapped around */
+ if (vl->values[i].counter < ce->values_raw[i].counter)
+ {
+ if (ce->values_raw[i].counter <= 4294967295U)
+ diff = (4294967295U - ce->values_raw[i].counter)
+ + vl->values[i].counter;
+ else
+ diff = (18446744073709551615ULL - ce->values_raw[i].counter)
+ + vl->values[i].counter;
+ }
+ else /* counter has NOT wrapped around */
+ {
+ diff = vl->values[i].counter - ce->values_raw[i].counter;
+ }
+
+ ce->values_gauge[i] = ((double) diff)
+ / ((double) (vl->time - ce->last_time));
+ ce->values_raw[i].counter = vl->values[i].counter;
+ }
+ break;
- /* check if the counter has wrapped around */
- if (vl->values[i].counter < ce->values_counter[i])
- {
- if (ce->values_counter[i] <= 4294967295U)
- diff = (4294967295U - ce->values_counter[i])
- + vl->values[i].counter;
- else
- diff = (18446744073709551615ULL - ce->values_counter[i])
- + vl->values[i].counter;
- }
- else /* counter has NOT wrapped around */
- {
- diff = vl->values[i].counter - ce->values_counter[i];
- }
+ case DS_TYPE_GAUGE:
+ ce->values_raw[i].gauge = vl->values[i].gauge;
+ ce->values_gauge[i] = vl->values[i].gauge;
+ break;
+
+ case DS_TYPE_DERIVE:
+ {
+ derive_t diff;
+
+ diff = vl->values[i].derive - ce->values_raw[i].derive;
+
+ ce->values_gauge[i] = ((double) diff)
+ / ((double) (vl->time - ce->last_time));
+ ce->values_raw[i].derive = vl->values[i].derive;
+ }
+ break;
+
+ case DS_TYPE_ABSOLUTE:
+ ce->values_gauge[i] = ((double) vl->values[i].absolute)
+ / ((double) (vl->time - ce->last_time));
+ ce->values_raw[i].absolute = vl->values[i].absolute;
+ break;
+
+ default:
+ /* This shouldn't happen. */
+ pthread_mutex_unlock (&cache_lock);
+ ERROR ("uc_update: Don't know how to handle data source type %i.",
+ ds->ds[i].type);
+ return (-1);
+ } /* switch (ds->ds[i].type) */
- ce->values_gauge[i] = ((double) diff)
- / ((double) (vl->time - ce->last_time));
- ce->values_counter[i] = vl->values[i].counter;
- }
- else /* if (ds->ds[i].type == DS_TYPE_GAUGE) */
- {
- ce->values_gauge[i] = vl->values[i].gauge;
- }
DEBUG ("uc_update: %s: ds[%i] = %lf", name, i, ce->values_gauge[i]);
} /* for (i) */
+ /* Prune invalid gauge data */
+ uc_check_range (ds, ce);
+
ce->last_time = vl->time;
ce->last_update = time (NULL);
ce->interval = vl->interval;
if (FORMAT_VL (name, sizeof (name), vl, ds) != 0)
{
- ERROR ("uc_insert: FORMAT_VL failed.");
+ ERROR ("utils_cache: uc_get_rate: FORMAT_VL failed.");
return (NULL);
}
/* This is important - the caller has no other way of knowing how many
* values are returned. */
- if (ret_num != ds->ds_num)
+ if (ret_num != (size_t) ds->ds_num)
{
ERROR ("utils_cache: uc_get_rate: ds[%s] has %i values, "
- "but uc_get_rate_by_name returned %i.",
+ "but uc_get_rate_by_name returned %zu.",
ds->type, ds->ds_num, ret_num);
sfree (ret);
return (NULL);