X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Frrdtool.c;h=e5f964e5bdc4fe01084267ee0b821e298fd42650;hp=2b384d09d7690b113aeadd5b4fec588f72b9b4ba;hb=b4c8f3f762d666742c774ab3b45815e5a416e5da;hpb=77f03c91b3074b5abd3e602002b7fc7ce28ea612 diff --git a/src/rrdtool.c b/src/rrdtool.c index 2b384d09..e5f964e5 100644 --- a/src/rrdtool.c +++ b/src/rrdtool.c @@ -40,11 +40,11 @@ */ struct rrd_cache_s { - int values_num; - char **values; - time_t first_value; - time_t last_value; - int random_variation; + int values_num; + char **values; + cdtime_t first_value; + cdtime_t last_value; + int64_t random_variation; enum { FLAG_NONE = 0x00, @@ -107,10 +107,10 @@ static rrdcreate_config_t rrdcreate_config = /* XXX: If you need to lock both, cache_lock and queue_lock, at the same time, * 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 cdtime_t cache_timeout = 0; +static cdtime_t cache_flush_timeout = 0; +static cdtime_t random_timeout = TIME_T_TO_CDTIME_T (1); +static cdtime_t cache_flush_last; static c_avl_tree_t *cache = NULL; static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; @@ -199,11 +199,13 @@ static int value_list_to_string (char *buffer, int buffer_len, { int offset; int status; + time_t tt; int i; memset (buffer, '\0', buffer_len); - status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) vl->time); + tt = CDTIME_T_TO_TIME_T (vl->time); + status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) tt); if ((status < 1) || (status >= buffer_len)) return (-1); offset = status; @@ -303,7 +305,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; @@ -342,7 +344,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! */ @@ -510,10 +512,11 @@ static int rrd_queue_dequeue (const char *filename, return (0); } /* int rrd_queue_dequeue */ -static void rrd_cache_flush (int timeout) +/* XXX: You must hold "cache_lock" when calling this function! */ +static void rrd_cache_flush (cdtime_t timeout) { rrd_cache_t *rc; - time_t now; + cdtime_t now; char **keys = NULL; int keys_num = 0; @@ -522,9 +525,11 @@ static void rrd_cache_flush (int timeout) c_avl_iterator_t *iter; int i; - DEBUG ("rrdtool plugin: Flushing cache, timeout = %i", timeout); + DEBUG ("rrdtool plugin: Flushing cache, timeout = %.3f", + CDTIME_T_TO_DOUBLE (timeout)); - now = time (NULL); + now = cdtime (); + timeout = TIME_T_TO_CDTIME_T (timeout); /* Build a list of entries to be flushed */ iter = c_avl_get_iterator (cache); @@ -532,7 +537,9 @@ static void rrd_cache_flush (int timeout) { if (rc->flags != FLAG_NONE) continue; - else if ((now - rc->first_value) < timeout) + /* timeout == 0 => flush everything */ + else if ((timeout != 0) + && ((now - rc->first_value) < timeout)) continue; else if (rc->values_num > 0) { @@ -585,10 +592,11 @@ static void rrd_cache_flush (int timeout) cache_flush_last = now; } /* void rrd_cache_flush */ -static int rrd_cache_flush_identifier (int timeout, const char *identifier) +static int rrd_cache_flush_identifier (cdtime_t timeout, + const char *identifier) { rrd_cache_t *rc; - time_t now; + cdtime_t now; int status; char key[2048]; @@ -598,7 +606,7 @@ static int rrd_cache_flush_identifier (int timeout, const char *identifier) return (0); } - now = time (NULL); + now = cdtime (); if (datadir == NULL) snprintf (key, sizeof (key), "%s.rrd", @@ -642,8 +650,43 @@ static int rrd_cache_flush_identifier (int timeout, const char *identifier) return (status); } /* int rrd_cache_flush_identifier */ +static int64_t rrd_get_random_variation (void) +{ + double dbl_timeout; + cdtime_t ctm_timeout; + double rand_fact; + _Bool negative; + int64_t ret; + + if (random_timeout <= 0) + return (0); + + /* Assure that "cache_timeout + random_variation" is never negative. */ + if (random_timeout > cache_timeout) + { + INFO ("rrdtool plugin: Adjusting \"RandomTimeout\" to %.3f seconds.", + CDTIME_T_TO_DOUBLE (cache_timeout)); + random_timeout = cache_timeout; + } + + /* This seems a bit complicated, but "random_timeout" is likely larger than + * RAND_MAX, so we can't simply use modulo here. */ + dbl_timeout = CDTIME_T_TO_DOUBLE (random_timeout); + rand_fact = ((double) random ()) + / ((double) RAND_MAX); + negative = (_Bool) (random () % 2); + + ctm_timeout = DOUBLE_TO_CDTIME_T (dbl_timeout * rand_fact); + + ret = (int64_t) ctm_timeout; + if (negative) + ret *= -1; + + return (ret); +} /* int64_t rrd_get_random_variation */ + static int rrd_cache_insert (const char *filename, - const char *value, time_t value_time) + const char *value, cdtime_t value_time) { rrd_cache_t *rc = NULL; int new_rc = 0; @@ -664,14 +707,14 @@ static int rrd_cache_insert (const char *filename, if (rc == NULL) { - rc = (rrd_cache_t *) malloc (sizeof (rrd_cache_t)); + rc = malloc (sizeof (*rc)); if (rc == NULL) return (-1); rc->values_num = 0; rc->values = NULL; rc->first_value = 0; rc->last_value = 0; - rc->random_variation = 0; + rc->random_variation = rrd_get_random_variation (); rc->flags = FLAG_NONE; new_rc = 1; } @@ -679,9 +722,9 @@ static int rrd_cache_insert (const char *filename, if (rc->last_value >= value_time) { pthread_mutex_unlock (&cache_lock); - DEBUG ("rrdtool plugin: (rc->last_value = %u) >= (value_time = %u)", - (unsigned int) rc->last_value, - (unsigned int) value_time); + DEBUG ("rrdtool plugin: (rc->last_value = %"PRIu64") " + ">= (value_time = %"PRIu64")", + rc->last_value, value_time); return (-1); } @@ -738,11 +781,11 @@ static int rrd_cache_insert (const char *filename, } DEBUG ("rrdtool plugin: rrd_cache_insert: file = %s; " - "values_num = %i; age = %lu;", + "values_num = %i; age = %.3f;", filename, rc->values_num, - (unsigned long)(rc->last_value - rc->first_value)); + CDTIME_T_TO_DOUBLE (rc->last_value - rc->first_value)); - if ((rc->last_value + rc->random_variation - rc->first_value) >= cache_timeout) + if ((rc->last_value - rc->first_value) >= (cache_timeout + rc->random_variation)) { /* XXX: If you need to lock both, cache_lock and queue_lock, at * the same time, ALWAYS lock `cache_lock' first! */ @@ -754,17 +797,7 @@ static int rrd_cache_insert (const char *filename, 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; - } + rc->random_variation = rrd_get_random_variation (); } else { @@ -773,7 +806,7 @@ static int rrd_cache_insert (const char *filename, } if ((cache_timeout > 0) && - ((time (NULL) - cache_flush_last) > cache_flush_timeout)) + ((cdtime () - cache_flush_last) > cache_flush_timeout)) rrd_cache_flush (cache_flush_timeout); pthread_mutex_unlock (&cache_lock); @@ -899,8 +932,8 @@ static int rrd_write (const data_set_t *ds, const value_list_t *vl, return (status); } /* int rrd_write */ -static int rrd_flush (int timeout, const char *identifier, - user_data_t __attribute__((unused)) *user_data) +static int rrd_flush (cdtime_t timeout, const char *identifier, + __attribute__((unused)) user_data_t *user_data) { pthread_mutex_lock (&cache_lock); @@ -919,7 +952,7 @@ static int rrd_config (const char *key, const char *value) { if (strcasecmp ("CacheTimeout", key) == 0) { - int tmp = atoi (value); + double tmp = atof (value); if (tmp < 0) { fprintf (stderr, "rrdtool: `CacheTimeout' must " @@ -928,7 +961,7 @@ static int rrd_config (const char *key, const char *value) "be greater than 0.\n"); return (1); } - cache_timeout = tmp; + cache_timeout = DOUBLE_TO_CDTIME_T (tmp); } else if (strcasecmp ("CacheFlush", key) == 0) { @@ -965,7 +998,7 @@ static int rrd_config (const char *key, const char *value) } else if (strcasecmp ("StepSize", key) == 0) { - int temp = atoi (value); + unsigned long temp = strtoul (value, NULL, 0); if (temp > 0) rrdcreate_config.stepsize = temp; } @@ -1061,10 +1094,10 @@ static int rrd_config (const char *key, const char *value) } else if (strcasecmp ("RandomTimeout", key) == 0) { - int tmp; + double tmp; - tmp = atoi (value); - if (tmp < 0) + tmp = atof (value); + if (tmp < 0.0) { fprintf (stderr, "rrdtool: `RandomTimeout' must " "be greater than or equal to zero.\n"); @@ -1073,7 +1106,7 @@ static int rrd_config (const char *key, const char *value) } else { - random_timeout = tmp; + random_timeout = DOUBLE_TO_CDTIME_T (tmp); } } else @@ -1086,7 +1119,7 @@ static int rrd_config (const char *key, const char *value) static int rrd_shutdown (void) { pthread_mutex_lock (&cache_lock); - rrd_cache_flush (-1); + rrd_cache_flush (0); pthread_mutex_unlock (&cache_lock); pthread_mutex_lock (&queue_lock); @@ -1128,18 +1161,16 @@ static int rrd_init (void) return (0); init_once = 1; - if (rrdcreate_config.stepsize < 0) - rrdcreate_config.stepsize = 0; if (rrdcreate_config.heartbeat <= 0) rrdcreate_config.heartbeat = 2 * rrdcreate_config.stepsize; if ((rrdcreate_config.heartbeat > 0) - && (rrdcreate_config.heartbeat < interval_g)) + && (rrdcreate_config.heartbeat < CDTIME_T_TO_TIME_T (interval_g))) WARNING ("rrdtool plugin: Your `heartbeat' is " "smaller than your `interval'. This will " "likely cause problems."); else if ((rrdcreate_config.stepsize > 0) - && (rrdcreate_config.stepsize < interval_g)) + && (rrdcreate_config.stepsize < CDTIME_T_TO_TIME_T (interval_g))) WARNING ("rrdtool plugin: Your `stepsize' is " "smaller than your `interval'. This will " "create needlessly big RRD-files."); @@ -1154,10 +1185,9 @@ static int rrd_init (void) return (-1); } - cache_flush_last = time (NULL); - if (cache_timeout < 2) + cache_flush_last = cdtime (); + if (cache_timeout == 0) { - cache_timeout = 0; cache_flush_timeout = 0; } else if (cache_flush_timeout < cache_timeout) @@ -1174,7 +1204,7 @@ static int rrd_init (void) } queue_thread_running = 1; - DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %i;" + DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %lu;" " heartbeat = %i; rrarows = %i; xff = %lf;", (datadir == NULL) ? "(null)" : datadir, rrdcreate_config.stepsize,