/**
* collectd - src/utils_cache.c
* Copyright (C) 2007-2010 Florian octo Forster
+ * Copyright (C) 2016 Sebastian tokkee Harl
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
*
* Authors:
* Florian octo Forster <octo at collectd.org>
+ * Sebastian tokkee Harl <sh at tokkee.org>
**/
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
#include "utils_avltree.h"
#include "meta_data.h"
#include <assert.h>
-#include <pthread.h>
typedef struct cache_entry_s
{
char name[6 * DATA_MAX_NAME_LEN];
- int values_num;
+ size_t values_num;
gauge_t *values_gauge;
value_t *values_raw;
/* Time contained in the package
* (for purging old entries) */
cdtime_t last_update;
/* Interval in which the data is collected
- * (for purding old entries) */
+ * (for purging old entries) */
cdtime_t interval;
int state;
int hits;
meta_data_t *meta;
} cache_entry_t;
+struct uc_iter_s {
+ c_avl_iterator_t *iter;
+
+ char *name;
+ cache_entry_t *entry;
+};
+
static c_avl_tree_t *cache_tree = NULL;
static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
return (strcmp (a->name, b->name));
} /* int cache_compare */
-static cache_entry_t *cache_alloc (int values_num)
+static cache_entry_t *cache_alloc (size_t values_num)
{
cache_entry_t *ce;
- ce = (cache_entry_t *) malloc (sizeof (cache_entry_t));
+ ce = calloc (1, sizeof (*ce));
if (ce == NULL)
{
- ERROR ("utils_cache: cache_alloc: malloc failed.");
+ ERROR ("utils_cache: cache_alloc: calloc failed.");
return (NULL);
}
- memset (ce, '\0', sizeof (cache_entry_t));
ce->values_num = values_num;
ce->values_gauge = calloc (values_num, sizeof (*ce->values_gauge));
static void uc_check_range (const data_set_t *ds, cache_entry_t *ce)
{
- int i;
-
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
if (isnan (ce->values_gauge[i]))
continue;
static int uc_insert (const data_set_t *ds, const value_list_t *vl,
const char *key)
{
- int i;
char *key_copy;
cache_entry_t *ce;
if (ce == NULL)
{
sfree (key_copy);
- ERROR ("uc_insert: cache_alloc (%i) failed.", ds->ds_num);
+ ERROR ("uc_insert: cache_alloc (%zu) failed.", ds->ds_num);
return (-1);
}
sstrncpy (ce->name, key, sizeof (ce->name));
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
switch (ds->ds[i].type)
{
c_avl_iterator_t *iter;
int status;
- int i;
-
+
pthread_mutex_lock (&cache_lock);
now = cdtime ();
continue;
/* If entry has not been updated, add to `keys' array */
- tmp = (char **) realloc ((void *) keys,
+ tmp = realloc ((void *) keys,
(keys_len + 1) * sizeof (char *));
if (tmp == NULL)
{
* including plugin specific meta data, rates, history, …. This must be done
* without holding the lock, otherwise we will run into a deadlock if a
* plugin calls the cache interface. */
- for (i = 0; i < keys_len; i++)
+ for (int i = 0; i < keys_len; i++)
{
value_list_t vl = VALUE_LIST_INIT;
* the timestamp again, so in theory it is possible we remove a value after
* it is updated here. */
pthread_mutex_lock (&cache_lock);
- for (i = 0; i < keys_len; i++)
+ for (int i = 0; i < keys_len; i++)
{
key = NULL;
ce = NULL;
char name[6 * DATA_MAX_NAME_LEN];
cache_entry_t *ce = NULL;
int status;
- int i;
if (FORMAT_VL (name, sizeof (name), vl) != 0)
{
return (-1);
}
- for (i = 0; i < ds->ds_num; i++)
+ for (size_t i = 0; i < ds->ds_num; i++)
{
switch (ds->ds[i].type)
{
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;
- }
-
+ counter_t diff = counter_diff (ce->values_raw[i].counter, vl->values[i].counter);
ce->values_gauge[i] = ((double) diff)
/ (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
ce->values_raw[i].counter = vl->values[i].counter;
case DS_TYPE_DERIVE:
{
- derive_t diff;
-
- diff = vl->values[i].derive - ce->values_raw[i].derive;
+ derive_t diff = vl->values[i].derive - ce->values_raw[i].derive;
ce->values_gauge[i] = ((double) diff)
/ (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time));
return (-1);
} /* switch (ds->ds[i].type) */
- DEBUG ("uc_update: %s: ds[%i] = %lf", name, i, ce->values_gauge[i]);
+ DEBUG ("uc_update: %s: ds[%zu] = %lf", name, i, ce->values_gauge[i]);
} /* for (i) */
/* Update the history if it exists. */
if (ce->history != NULL)
{
assert (ce->history_index < ce->history_length);
- for (i = 0; i < ce->values_num; i++)
+ for (size_t i = 0; i < ce->values_num; i++)
{
size_t hist_idx = (ce->values_num * ce->history_index) + i;
ce->history[hist_idx] = ce->values_gauge[i];
else
{
ret_num = ce->values_num;
- ret = (gauge_t *) malloc (ret_num * sizeof (gauge_t));
+ ret = malloc (ret_num * sizeof (*ret));
if (ret == NULL)
{
ERROR ("utils_cache: uc_get_rate_by_name: malloc failed.");
* values are returned. */
if (ret_num != (size_t) ds->ds_num)
{
- ERROR ("utils_cache: uc_get_rate: ds[%s] has %i values, "
+ ERROR ("utils_cache: uc_get_rate: ds[%s] has %zu values, "
"but uc_get_rate_by_name returned %zu.",
ds->type, ds->ds_num, ret_num);
sfree (ret);
if (status != 0)
{
- size_t i;
-
- for (i = 0; i < number; i++)
+ for (size_t i = 0; i < number; i++)
{
sfree (names[i]);
}
if (FORMAT_VL (name, sizeof (name), vl) != 0)
{
- ERROR ("uc_get_state: FORMAT_VL failed.");
+ ERROR ("uc_set_state: FORMAT_VL failed.");
return (STATE_ERROR);
}
gauge_t *ret_history, size_t num_steps, size_t num_ds)
{
cache_entry_t *ce = NULL;
- size_t i;
int status = 0;
pthread_mutex_lock (&cache_lock);
return (-ENOMEM);
}
- for (i = ce->history_length * ce->values_num;
+ for (size_t i = ce->history_length * ce->values_num;
i < (num_steps * ce->values_num);
i++)
tmp[i] = NAN;
} /* if (ce->history_length < num_steps) */
/* Copy the values to the output buffer. */
- for (i = 0; i < num_steps; i++)
+ for (size_t i = 0; i < num_steps; i++)
{
size_t src_index;
size_t dst_index;
if (FORMAT_VL (name, sizeof (name), vl) != 0)
{
- ERROR ("uc_get_state: FORMAT_VL failed.");
+ ERROR ("uc_get_hits: FORMAT_VL failed.");
return (STATE_ERROR);
}
if (FORMAT_VL (name, sizeof (name), vl) != 0)
{
- ERROR ("uc_get_state: FORMAT_VL failed.");
+ ERROR ("uc_set_hits: FORMAT_VL failed.");
return (STATE_ERROR);
}
if (FORMAT_VL (name, sizeof (name), vl) != 0)
{
- ERROR ("uc_get_state: FORMAT_VL failed.");
+ ERROR ("uc_inc_hits: FORMAT_VL failed.");
return (STATE_ERROR);
}
} /* int uc_inc_hits */
/*
+ * Iterator interface
+ */
+uc_iter_t *uc_get_iterator (void)
+{
+ uc_iter_t *iter;
+
+ iter = (uc_iter_t *) calloc(1, sizeof (*iter));
+ if (iter == NULL)
+ return (NULL);
+
+ pthread_mutex_lock (&cache_lock);
+
+ iter->iter = c_avl_get_iterator (cache_tree);
+ if (iter->iter == NULL)
+ {
+ free (iter);
+ return (NULL);
+ }
+
+ return (iter);
+} /* uc_iter_t *uc_get_iterator */
+
+int uc_iterator_next (uc_iter_t *iter, char **ret_name)
+{
+ int status;
+
+ if (iter == NULL)
+ return (-1);
+
+ while ((status = c_avl_iterator_next (iter->iter,
+ (void *) &iter->name, (void *) &iter->entry)) == 0)
+ {
+ if (iter->entry->state == STATE_MISSING)
+ continue;
+
+ break;
+ }
+ if (status != 0) {
+ iter->name = NULL;
+ iter->entry = NULL;
+ return (-1);
+ }
+
+ if (ret_name != NULL)
+ *ret_name = iter->name;
+
+ return (0);
+} /* int uc_iterator_next */
+
+void uc_iterator_destroy (uc_iter_t *iter)
+{
+ if (iter == NULL)
+ return;
+
+ c_avl_iterator_destroy (iter->iter);
+ pthread_mutex_unlock (&cache_lock);
+
+ free (iter);
+} /* void uc_iterator_destroy */
+
+int uc_iterator_get_time (uc_iter_t *iter, cdtime_t *ret_time)
+{
+ if ((iter == NULL) || (iter->entry == NULL) || (ret_time == NULL))
+ return (-1);
+
+ *ret_time = iter->entry->last_time;
+ return (0);
+} /* int uc_iterator_get_name */
+
+int uc_iterator_get_values (uc_iter_t *iter, value_t **ret_values, size_t *ret_num)
+{
+ if ((iter == NULL) || (iter->entry == NULL)
+ || (ret_values == NULL) || (ret_num == NULL))
+ return (-1);
+
+ *ret_values = calloc (iter->entry->values_num, sizeof(*iter->entry->values_raw));
+ if (*ret_values == NULL)
+ return (-1);
+ for (size_t i = 0; i < iter->entry->values_num; ++i)
+ *ret_values[i] = iter->entry->values_raw[i];
+
+ *ret_num = iter->entry->values_num;
+
+ return (0);
+} /* int uc_iterator_get_values */
+
+int uc_iterator_get_interval (uc_iter_t *iter, cdtime_t *ret_interval)
+{
+ if ((iter == NULL) || (iter->entry == NULL) || (ret_interval == NULL))
+ return (-1);
+
+ *ret_interval = iter->entry->interval;
+ return (0);
+} /* int uc_iterator_get_name */
+
+/*
* Meta data interface
*/
/* XXX: This function will acquire `cache_lock' but will not free it! */