X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Frrdtool.c;h=cb8ad593cbe51d4f9a36f22734fc273c8f724810;hb=fbb822b876e877c69be066ceca693769d4a9618a;hp=c63f883afea9b86d8138472230b0f7fa3d1e8999;hpb=1e4db580e37d235755de0c4a4c08ba7a6ac7bb4c;p=collectd.git diff --git a/src/rrdtool.c b/src/rrdtool.c index c63f883a..cb8ad593 100644 --- a/src/rrdtool.c +++ b/src/rrdtool.c @@ -1,6 +1,8 @@ /** * collectd - src/rrdtool.c * Copyright (C) 2006-2008 Florian octo Forster + * Copyright (C) 2008-2008 Sebastian Harl + * Copyright (C) 2009 Mariusz Gronczewski * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -17,6 +19,8 @@ * * Authors: * Florian octo Forster + * Sebastian Harl + * Mariusz Gronczewski **/ #include "collectd.h" @@ -40,6 +44,7 @@ struct rrd_cache_s char **values; time_t first_value; time_t last_value; + int random_variation; enum { FLAG_NONE = 0x00, @@ -76,7 +81,8 @@ static const char *config_keys[] = "RRARows", "RRATimespan", "XFF", - "WritesPerSecond" + "WritesPerSecond", + "RandomTimeout" }; static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); @@ -103,6 +109,7 @@ static rrdcreate_config_t rrdcreate_config = * ALWAYS lock `cache_lock' first! */ static int cache_timeout = 0; static int cache_flush_timeout = 0; +static int random_timeout = 1; static time_t cache_flush_last; static c_avl_tree_t *cache = NULL; static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; @@ -296,7 +303,7 @@ static void *rrd_queue_thread (void __attribute__((unused)) *data) pthread_mutex_lock (&queue_lock); /* Wait for values to arrive */ - while (true) + while (42) { struct timespec ts_wait; @@ -335,7 +342,7 @@ static void *rrd_queue_thread (void __attribute__((unused)) *data) &ts_wait); if (status == ETIMEDOUT) break; - } /* while (true) */ + } /* while (42) */ /* XXX: If you need to lock both, cache_lock and queue_lock, at * the same time, ALWAYS lock `cache_lock' first! */ @@ -425,11 +432,6 @@ static void *rrd_queue_thread (void __attribute__((unused)) *data) sfree (queue_entry); } /* while (42) */ - pthread_mutex_lock (&cache_lock); - c_avl_destroy (cache); - cache = NULL; - pthread_mutex_unlock (&cache_lock); - pthread_exit ((void *) 0); return ((void *) 0); } /* void *rrd_queue_thread */ @@ -669,6 +671,7 @@ static int rrd_cache_insert (const char *filename, rc->values = NULL; rc->first_value = 0; rc->last_value = 0; + rc->random_variation = 0; rc->flags = FLAG_NONE; new_rc = 1; } @@ -676,7 +679,7 @@ static int rrd_cache_insert (const char *filename, if (rc->last_value >= value_time) { pthread_mutex_unlock (&cache_lock); - WARNING ("rrdtool plugin: (rc->last_value = %u) >= (value_time = %u)", + DEBUG ("rrdtool plugin: (rc->last_value = %u) >= (value_time = %u)", (unsigned int) rc->last_value, (unsigned int) value_time); return (-1); @@ -739,7 +742,7 @@ static int rrd_cache_insert (const char *filename, filename, rc->values_num, (unsigned long)(rc->last_value - rc->first_value)); - if ((rc->last_value - rc->first_value) >= cache_timeout) + if ((rc->last_value + rc->random_variation - rc->first_value) >= cache_timeout) { /* XXX: If you need to lock both, cache_lock and queue_lock, at * the same time, ALWAYS lock `cache_lock' first! */ @@ -750,6 +753,18 @@ static int rrd_cache_insert (const char *filename, status = rrd_queue_enqueue (filename, &queue_head, &queue_tail); if (status == 0) rc->flags = FLAG_QUEUED; + + /* Update the jitter value. Negative values are + * slightly preferred. */ + if (random_timeout > 0) + { + rc->random_variation = (rand () % (2 * random_timeout)) + - random_timeout; + } + else + { + rc->random_variation = 0; + } } else { @@ -766,6 +781,59 @@ static int rrd_cache_insert (const char *filename, return (0); } /* int rrd_cache_insert */ +static int rrd_cache_destroy (void) /* {{{ */ +{ + void *key = NULL; + void *value = NULL; + + int non_empty = 0; + + pthread_mutex_lock (&cache_lock); + + if (cache == NULL) + { + pthread_mutex_unlock (&cache_lock); + return (0); + } + + while (c_avl_pick (cache, &key, &value) == 0) + { + rrd_cache_t *rc; + int i; + + sfree (key); + key = NULL; + + rc = value; + value = NULL; + + if (rc->values_num > 0) + non_empty++; + + for (i = 0; i < rc->values_num; i++) + sfree (rc->values[i]); + sfree (rc->values); + sfree (rc); + } + + c_avl_destroy (cache); + cache = NULL; + + if (non_empty > 0) + { + INFO ("rrdtool plugin: %i cache %s had values when destroying the cache.", + non_empty, (non_empty == 1) ? "entry" : "entries"); + } + else + { + DEBUG ("rrdtool plugin: No values have been lost " + "when destroying the cache."); + } + + pthread_mutex_unlock (&cache_lock); + return (0); +} /* }}} int rrd_cache_destroy */ + static int rrd_compare_numeric (const void *a_ptr, const void *b_ptr) { int a = *((int *) a_ptr); @@ -787,6 +855,9 @@ static int rrd_write (const data_set_t *ds, const value_list_t *vl, char values[512]; int status; + if (do_shutdown) + return (0); + if (0 != strcmp (ds->type, vl->type)) { ERROR ("rrdtool plugin: DS type does not match value list type"); return -1; @@ -988,6 +1059,23 @@ static int rrd_config (const char *key, const char *value) write_rate = 1.0 / wps; } } + else if (strcasecmp ("RandomTimeout", key) == 0) + { + int tmp; + + tmp = atoi (value); + if (tmp < 0) + { + fprintf (stderr, "rrdtool: `RandomTimeout' must " + "be greater than or equal to zero.\n"); + ERROR ("rrdtool: `RandomTimeout' must " + "be greater then or equal to zero."); + } + else + { + random_timeout = tmp; + } + } else { return (-1); @@ -1026,7 +1114,7 @@ static int rrd_shutdown (void) DEBUG ("rrdtool plugin: queue_thread exited."); } - /* TODO: Maybe it'd be a good idea to free the cache here.. */ + rrd_cache_destroy (); return (0); } /* int rrd_shutdown */