#include "collectd.h"
#include "plugin.h"
#include "common.h"
-#include "utils_llist.h"
+#include "utils_avltree.h"
#include "utils_debug.h"
/*
static const char *config_keys[] =
{
"CacheTimeout",
+ "CacheFlush",
"DataDir",
NULL
};
-static int config_keys_num = 2;
+static int config_keys_num = 3;
static char *datadir = NULL;
-static int cache_timeout = 0;
-static time_t cache_flush;
-static llist_t *cache = NULL;
+static int cache_timeout = 0;
+static int cache_flush_timeout = 0;
+static time_t cache_flush_last;
+static avl_tree_t *cache = NULL;
/* * * * * * * * * *
* WARNING: Magic *
const char *value)
{
rrd_cache_t *rc = NULL;
- llentry_t *le = NULL;
if (cache != NULL)
- {
- le = llist_search (cache, filename);
- if (le != NULL)
- rc = (rrd_cache_t *) le->value;
- }
+ avl_get (cache, filename, (void *) &rc);
if (rc == NULL)
{
{
syslog (LOG_ERR, "rrdtool plugin: realloc failed: %s",
strerror (errno));
- free (rc);
- if (le != NULL)
+ if (cache != NULL)
{
- llist_remove (cache, le);
- llentry_destroy (le);
+ void *cache_key = NULL;
+ avl_remove (cache, filename, &cache_key, NULL);
+ sfree (cache_key);
}
+ free (rc);
return (NULL);
}
if (rc->values_num == 1)
rc->first_value = time (NULL);
- if ((cache != NULL) && (le == NULL))
+ /* Insert if this is the first value */
+ if ((cache != NULL) && (rc->values_num == 1))
{
- le = llentry_create (filename, (void *) rc);
- if (le != NULL)
- llist_prepend (cache, le);
+ void *cache_key = strdup (filename);
+
+ if (cache_key == NULL)
+ {
+ syslog (LOG_ERR, "rrdtool plugin: strdup failed: %s",
+ strerror (errno));
+ sfree (rc->values);
+ sfree (rc);
+ return (NULL);
+ }
+
+ avl_insert (cache, cache_key, rc);
}
DBG ("rrd_cache_insert (%s, %s) = %p", filename, value, (void *) rc);
static void rrd_cache_flush (int timeout)
{
- llentry_t *le;
rrd_cache_t *rc;
time_t now;
+ char **keys = NULL;
+ int keys_num = 0;
+
+ char *key;
+ avl_iterator_t *iter;
+ int i;
+
if (cache == NULL)
return;
now = time (NULL);
- /* Remove empty entries */
- le = llist_head (cache);
- while (le != NULL)
+ /* Build a list of entries to be flushed */
+ iter = avl_get_iterator (cache);
+ while (avl_iterator_next (iter, (void *) &key, (void *) &rc) == 0)
{
- llentry_t *next = le->next;
- rc = (rrd_cache_t *) le->value;
- if (rc->values_num == 0)
+ DBG ("key = %s; age = %i;", key, now - rc->first_value);
+ if ((now - rc->first_value) >= timeout)
{
- DBG ("Removing cache entry for `%s'", le->key);
- free (rc->values);
- free (rc);
- llist_remove (cache, le);
+ keys = (char **) realloc ((void *) keys,
+ (keys_num + 1) * sizeof (char *));
+ if (keys == NULL)
+ {
+ DBG ("realloc failed: %s", strerror (errno));
+ syslog (LOG_ERR, "rrdtool plugin: "
+ "realloc failed: %s",
+ strerror (errno));
+ avl_iterator_destroy (iter);
+ return;
+ }
+ keys[keys_num] = key;
+ keys_num++;
}
- le = next;
- }
-
- /* Write timed out entries */
- le = llist_head (cache);
- while (le != NULL)
+ } /* while (avl_iterator_next) */
+ avl_iterator_destroy (iter);
+
+ for (i = 0; i < keys_num; i++)
{
- rc = (rrd_cache_t *) le->value;
- if ((now - rc->first_value) >= timeout)
- rrd_write_cache_entry (le->key, rc);
+ if (avl_remove (cache, keys[i], NULL, (void *) &rc) != 0)
+ {
+ DBG ("avl_remove (%s) failed.", keys[i]);
+ continue;
+ }
- le = le->next;
- }
+ rrd_write_cache_entry (keys[i], rc);
+ sfree (keys[i]); keys[i] = NULL;
+ sfree (rc->values);
+ sfree (rc);
+ } /* for (i = 0..keys_num) */
- cache_flush = now;
+ free (keys);
+ DBG ("Flushed %i value(s)", keys_num);
+
+ cache_flush_last = now;
} /* void rrd_cache_flush */
static int rrd_write (const data_set_t *ds, const value_list_t *vl)
if ((now - rc->first_value) >= cache_timeout)
rrd_write_cache_entry (filename, rc);
- if ((time (NULL) - cache_flush) >= cache_timeout)
+ if ((now - cache_flush_last) >= cache_flush_timeout)
{
- rrd_cache_flush (cache_timeout);
+ rrd_cache_flush (cache_flush_timeout);
}
return (0);
-} /* int rrd_dispatch */
+} /* int rrd_write */
static int rrd_config (const char *key, const char *val)
{
}
cache_timeout = tmp;
}
+ else if (strcasecmp ("CacheFlush", key) == 0)
+ {
+ int tmp = atoi (val);
+ if (tmp < 0)
+ {
+ fprintf (stderr, "rrdtool: `CacheFlush' must "
+ "be greater than 0.\n");
+ return (1);
+ }
+ cache_flush_timeout = tmp;
+ }
else if (strcasecmp ("DataDir", key) == 0)
{
if (datadir != NULL)
if (cache_timeout < 2)
{
cache_timeout = 0;
+ cache_flush_timeout = 0;
}
else
{
- cache = llist_create ();
- cache_flush = time (NULL);
+ if (cache_flush_timeout < cache_timeout)
+ cache_flush_timeout = 10 * cache_timeout;
+
+ cache = avl_create ((int (*) (const void *, const void *)) strcmp);
+ cache_flush_last = time (NULL);
plugin_register_shutdown ("rrdtool", rrd_shutdown);
}
return (0);