X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Frrdtool.c;h=cd275dadc622bd92c18943edecf7da245e10d247;hp=e29d637d9233b172808fef04938eab8cd1f845b5;hb=ba1015262cdc912f9d01ab5a76037e65033c54c5;hpb=42b8d7550d029ed9aef6f25e3eb2009c1f18b144 diff --git a/src/rrdtool.c b/src/rrdtool.c index e29d637d..cd275dad 100644 --- a/src/rrdtool.c +++ b/src/rrdtool.c @@ -36,15 +36,14 @@ /* * Private types */ -struct rrd_cache_s { +typedef struct rrd_cache_s { int values_num; char **values; cdtime_t first_value; cdtime_t last_value; int64_t random_variation; enum { FLAG_NONE = 0x00, FLAG_QUEUED = 0x01, FLAG_FLUSHQ = 0x02 } flags; -}; -typedef struct rrd_cache_s rrd_cache_t; +} rrd_cache_t; enum rrd_queue_dir_e { QUEUE_INSERT_FRONT, QUEUE_INSERT_BACK }; typedef enum rrd_queue_dir_e rrd_queue_dir_t; @@ -87,7 +86,7 @@ static rrdcreate_config_t rrdcreate_config = { * ALWAYS lock `cache_lock' first! */ static cdtime_t cache_timeout = 0; static cdtime_t cache_flush_timeout = 0; -static cdtime_t random_timeout = TIME_T_TO_CDTIME_T_STATIC(1); +static cdtime_t random_timeout = 0; static cdtime_t cache_flush_last; static c_avl_tree_t *cache = NULL; static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; @@ -110,19 +109,16 @@ static int do_shutdown = 0; #if HAVE_THREADSAFE_LIBRRD static int srrd_update(char *filename, char *template, int argc, const char **argv) { - int status; - optind = 0; /* bug in librrd? */ rrd_clear_error(); - status = rrd_update_r(filename, template, argc, (void *)argv); - + int status = rrd_update_r(filename, template, argc, (void *)argv); if (status != 0) { WARNING("rrdtool plugin: rrd_update_r (%s) failed: %s", filename, rrd_get_error()); } - return (status); + return status; } /* int srrd_update */ /* #endif HAVE_THREADSAFE_LIBRRD */ @@ -140,7 +136,7 @@ static int srrd_update(char *filename, char *template, int argc, new_argv = malloc((new_argc + 1) * sizeof(*new_argv)); if (new_argv == NULL) { ERROR("rrdtool plugin: malloc failed."); - return (-1); + return -1; } new_argv[0] = "update"; @@ -163,7 +159,7 @@ static int srrd_update(char *filename, char *template, int argc, sfree(new_argv); - return (status); + return status; } /* int srrd_update */ #endif /* !HAVE_THREADSAFE_LIBRRD */ @@ -177,9 +173,9 @@ static int value_list_to_string_multiple(char *buffer, int buffer_len, memset(buffer, '\0', buffer_len); tt = CDTIME_T_TO_TIME_T(vl->time); - status = ssnprintf(buffer, buffer_len, "%u", (unsigned int)tt); + status = snprintf(buffer, buffer_len, "%u", (unsigned int)tt); if ((status < 1) || (status >= buffer_len)) - return (-1); + return -1; offset = status; for (size_t i = 0; i < ds->ds_num; i++) { @@ -187,28 +183,28 @@ static int value_list_to_string_multiple(char *buffer, int buffer_len, (ds->ds[i].type != DS_TYPE_GAUGE) && (ds->ds[i].type != DS_TYPE_DERIVE) && (ds->ds[i].type != DS_TYPE_ABSOLUTE)) - return (-1); + return -1; if (ds->ds[i].type == DS_TYPE_COUNTER) - status = ssnprintf(buffer + offset, buffer_len - offset, ":%llu", - vl->values[i].counter); + status = snprintf(buffer + offset, buffer_len - offset, ":%llu", + vl->values[i].counter); else if (ds->ds[i].type == DS_TYPE_GAUGE) - status = ssnprintf(buffer + offset, buffer_len - offset, ":" GAUGE_FORMAT, - vl->values[i].gauge); + status = snprintf(buffer + offset, buffer_len - offset, ":" GAUGE_FORMAT, + vl->values[i].gauge); else if (ds->ds[i].type == DS_TYPE_DERIVE) - status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIi64, - vl->values[i].derive); + status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIi64, + vl->values[i].derive); else /*if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */ - status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIu64, - vl->values[i].absolute); + status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIu64, + vl->values[i].absolute); if ((status < 1) || (status >= (buffer_len - offset))) - return (-1); + return -1; offset += status; } /* for ds->ds_num */ - return (0); + return 0; } /* int value_list_to_string_multiple */ static int value_list_to_string(char *buffer, int buffer_len, @@ -217,34 +213,34 @@ static int value_list_to_string(char *buffer, int buffer_len, time_t tt; if (ds->ds_num != 1) - return (value_list_to_string_multiple(buffer, buffer_len, ds, vl)); + return value_list_to_string_multiple(buffer, buffer_len, ds, vl); tt = CDTIME_T_TO_TIME_T(vl->time); switch (ds->ds[0].type) { case DS_TYPE_DERIVE: - status = ssnprintf(buffer, buffer_len, "%u:%" PRIi64, (unsigned)tt, - vl->values[0].derive); + status = snprintf(buffer, buffer_len, "%u:%" PRIi64, (unsigned)tt, + vl->values[0].derive); break; case DS_TYPE_GAUGE: - status = ssnprintf(buffer, buffer_len, "%u:" GAUGE_FORMAT, (unsigned)tt, - vl->values[0].gauge); + status = snprintf(buffer, buffer_len, "%u:" GAUGE_FORMAT, (unsigned)tt, + vl->values[0].gauge); break; case DS_TYPE_COUNTER: - status = ssnprintf(buffer, buffer_len, "%u:%llu", (unsigned)tt, - vl->values[0].counter); + status = snprintf(buffer, buffer_len, "%u:%llu", (unsigned)tt, + vl->values[0].counter); break; case DS_TYPE_ABSOLUTE: - status = ssnprintf(buffer, buffer_len, "%u:%" PRIu64, (unsigned)tt, - vl->values[0].absolute); + status = snprintf(buffer, buffer_len, "%u:%" PRIu64, (unsigned)tt, + vl->values[0].absolute); break; default: - return (EINVAL); + return EINVAL; } if ((status < 1) || (status >= buffer_len)) - return (ENOMEM); + return ENOMEM; - return (0); + return 0; } /* int value_list_to_string */ static int value_list_to_filename(char *buffer, size_t buffer_size, @@ -257,7 +253,7 @@ static int value_list_to_filename(char *buffer, size_t buffer_size, size_t datadir_len = strlen(datadir) + 1; if (datadir_len >= buffer_size) - return (ENOMEM); + return ENOMEM; sstrncpy(buffer, datadir, buffer_size); buffer[datadir_len - 1] = '/'; @@ -269,7 +265,7 @@ static int value_list_to_filename(char *buffer, size_t buffer_size, status = FORMAT_VL(buffer, buffer_size, vl); if (status != 0) - return (status); + return status; len = strlen(buffer); assert(len < buffer_size); @@ -277,10 +273,10 @@ static int value_list_to_filename(char *buffer, size_t buffer_size, buffer_size -= len; if (buffer_size <= sizeof(suffix)) - return (ENOMEM); + return ENOMEM; memcpy(buffer, suffix, sizeof(suffix)); - return (0); + return 0; } /* int value_list_to_filename */ static void *rrd_queue_thread(void __attribute__((unused)) * data) { @@ -418,7 +414,7 @@ static void *rrd_queue_thread(void __attribute__((unused)) * data) { } /* while (42) */ pthread_exit((void *)0); - return ((void *)0); + return (void *)0; } /* void *rrd_queue_thread */ static int rrd_queue_enqueue(const char *filename, rrd_queue_t **head, @@ -427,12 +423,12 @@ static int rrd_queue_enqueue(const char *filename, rrd_queue_t **head, queue_entry = malloc(sizeof(*queue_entry)); if (queue_entry == NULL) - return (-1); + return -1; queue_entry->filename = strdup(filename); if (queue_entry->filename == NULL) { free(queue_entry); - return (-1); + return -1; } queue_entry->next = NULL; @@ -448,7 +444,7 @@ static int rrd_queue_enqueue(const char *filename, rrd_queue_t **head, pthread_cond_signal(&queue_cond); pthread_mutex_unlock(&queue_lock); - return (0); + return 0; } /* int rrd_queue_enqueue */ static int rrd_queue_dequeue(const char *filename, rrd_queue_t **head, @@ -471,7 +467,7 @@ static int rrd_queue_dequeue(const char *filename, rrd_queue_t **head, if (this == NULL) { pthread_mutex_unlock(&queue_lock); - return (-1); + return -1; } if (prev == NULL) @@ -487,7 +483,7 @@ static int rrd_queue_dequeue(const char *filename, rrd_queue_t **head, sfree(this->filename); sfree(this); - return (0); + return 0; } /* int rrd_queue_dequeue */ /* XXX: You must hold "cache_lock" when calling this function! */ @@ -505,7 +501,6 @@ static void rrd_cache_flush(cdtime_t timeout) { CDTIME_T_TO_DOUBLE(timeout)); now = cdtime(); - timeout = TIME_T_TO_CDTIME_T(timeout); /* Build a list of entries to be flushed */ iter = c_avl_get_iterator(cache); @@ -568,7 +563,7 @@ static int rrd_cache_flush_identifier(cdtime_t timeout, if (identifier == NULL) { rrd_cache_flush(timeout); - return (0); + return 0; } now = cdtime(); @@ -584,7 +579,7 @@ static int rrd_cache_flush_identifier(cdtime_t timeout, INFO("rrdtool plugin: rrd_cache_flush_identifier: " "c_avl_get (%s) failed. Does that file really exist?", key); - return (status); + return status; } if (rc->flags == FLAG_FLUSHQ) { @@ -602,27 +597,14 @@ static int rrd_cache_flush_identifier(cdtime_t timeout, rc->flags = FLAG_FLUSHQ; } - return (status); + return status; } /* int rrd_cache_flush_identifier */ static int64_t rrd_get_random_variation(void) { - long min; - long max; - 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; - } + return 0; - max = (long)(random_timeout / 2); - min = max - ((long)random_timeout); - - return ((int64_t)cdrand_range(min, max)); + return (int64_t)cdrand_range(-random_timeout, random_timeout); } /* int64_t rrd_get_random_variation */ static int rrd_cache_insert(const char *filename, const char *value, @@ -638,16 +620,15 @@ static int rrd_cache_insert(const char *filename, const char *value, if (cache == NULL) { pthread_mutex_unlock(&cache_lock); WARNING("rrdtool plugin: cache == NULL."); - return (-1); + return -1; } - c_avl_get(cache, filename, (void *)&rc); - - if (rc == NULL) { + int status = c_avl_get(cache, filename, (void *)&rc); + if ((status != 0) || (rc == NULL)) { rc = malloc(sizeof(*rc)); if (rc == NULL) { pthread_mutex_unlock(&cache_lock); - return (-1); + return -1; } rc->values_num = 0; rc->values = NULL; @@ -664,7 +645,7 @@ static int rrd_cache_insert(const char *filename, const char *value, DEBUG("rrdtool plugin: (rc->last_value = %" PRIu64 ") " ">= (value_time = %" PRIu64 ")", rc->last_value, value_time); - return (-1); + return -1; } values_new = @@ -683,7 +664,7 @@ static int rrd_cache_insert(const char *filename, const char *value, sfree(cache_key); sfree(rc->values); sfree(rc); - return (-1); + return -1; } rc->values = values_new; @@ -710,7 +691,7 @@ static int rrd_cache_insert(const char *filename, const char *value, sfree(rc->values[0]); sfree(rc->values); sfree(rc); - return (-1); + return -1; } c_avl_insert(cache, cache_key, rc); @@ -740,11 +721,11 @@ static int rrd_cache_insert(const char *filename, const char *value, if ((cache_timeout > 0) && ((cdtime() - cache_flush_last) > cache_flush_timeout)) - rrd_cache_flush(cache_flush_timeout); + rrd_cache_flush(cache_timeout + random_timeout); pthread_mutex_unlock(&cache_lock); - return (0); + return 0; } /* int rrd_cache_insert */ static int rrd_cache_destroy(void) /* {{{ */ @@ -758,7 +739,7 @@ static int rrd_cache_destroy(void) /* {{{ */ if (cache == NULL) { pthread_mutex_unlock(&cache_lock); - return (0); + return 0; } while (c_avl_pick(cache, &key, &value) == 0) { @@ -791,7 +772,7 @@ static int rrd_cache_destroy(void) /* {{{ */ } pthread_mutex_unlock(&cache_lock); - return (0); + return 0; } /* }}} int rrd_cache_destroy */ static int rrd_compare_numeric(const void *a_ptr, const void *b_ptr) { @@ -799,55 +780,52 @@ static int rrd_compare_numeric(const void *a_ptr, const void *b_ptr) { int b = *((int *)b_ptr); if (a < b) - return (-1); + return -1; else if (a > b) - return (1); + return 1; else - return (0); + return 0; } /* int rrd_compare_numeric */ static int rrd_write(const data_set_t *ds, const value_list_t *vl, user_data_t __attribute__((unused)) * user_data) { - struct stat statbuf; - char filename[512]; - char values[512]; - int status; if (do_shutdown) - return (0); + return 0; if (0 != strcmp(ds->type, vl->type)) { ERROR("rrdtool plugin: DS type does not match value list type"); return -1; } + char filename[PATH_MAX]; if (value_list_to_filename(filename, sizeof(filename), vl) != 0) - return (-1); + return -1; + char values[32 * (ds->ds_num + 1)]; if (value_list_to_string(values, sizeof(values), ds, vl) != 0) - return (-1); + return -1; + struct stat statbuf = {0}; if (stat(filename, &statbuf) == -1) { if (errno == ENOENT) { - status = cu_rrd_create_file(filename, ds, vl, &rrdcreate_config); - if (status != 0) - return (-1); - else if (rrdcreate_config.async) - return (0); + if (cu_rrd_create_file(filename, ds, vl, &rrdcreate_config) != 0) { + return -1; + } else if (rrdcreate_config.async) { + return 0; + } } else { char errbuf[1024]; - ERROR("stat(%s) failed: %s", filename, + ERROR("rrdtool plugin: stat(%s) failed: %s", filename, sstrerror(errno, errbuf, sizeof(errbuf))); - return (-1); + return -1; } } else if (!S_ISREG(statbuf.st_mode)) { - ERROR("stat(%s): Not a regular file!", filename); - return (-1); + ERROR("rrdtool plugin: stat(%s): Not a regular file!", filename); + return -1; } - status = rrd_cache_insert(filename, values, vl->time); - - return (status); + return rrd_cache_insert(filename, values, vl->time); } /* int rrd_write */ static int rrd_flush(cdtime_t timeout, const char *identifier, @@ -856,13 +834,13 @@ static int rrd_flush(cdtime_t timeout, const char *identifier, if (cache == NULL) { pthread_mutex_unlock(&cache_lock); - return (0); + return 0; } rrd_cache_flush_identifier(timeout, identifier); pthread_mutex_unlock(&cache_lock); - return (0); + return 0; } /* int rrd_flush */ static int rrd_config(const char *key, const char *value) { @@ -873,19 +851,19 @@ static int rrd_config(const char *key, const char *value) { "be greater than 0.\n"); ERROR("rrdtool: `CacheTimeout' must " "be greater than 0.\n"); - return (1); + return 1; } cache_timeout = DOUBLE_TO_CDTIME_T(tmp); } else if (strcasecmp("CacheFlush", key) == 0) { - int tmp = atoi(value); + double tmp = atof(value); if (tmp < 0) { fprintf(stderr, "rrdtool: `CacheFlush' must " "be greater than 0.\n"); ERROR("rrdtool: `CacheFlush' must " "be greater than 0.\n"); - return (1); + return 1; } - cache_flush_timeout = tmp; + cache_flush_timeout = DOUBLE_TO_CDTIME_T(tmp); } else if (strcasecmp("DataDir", key) == 0) { char *tmp; size_t len; @@ -893,7 +871,7 @@ static int rrd_config(const char *key, const char *value) { tmp = strdup(value); if (tmp == NULL) { ERROR("rrdtool plugin: strdup failed."); - return (1); + return 1; } len = strlen(tmp); @@ -905,7 +883,7 @@ static int rrd_config(const char *key, const char *value) { if (len == 0) { ERROR("rrdtool plugin: Invalid \"DataDir\" option."); sfree(tmp); - return (1); + return 1; } if (datadir != NULL) { @@ -933,7 +911,7 @@ static int rrd_config(const char *key, const char *value) { "be greater than 0.\n"); ERROR("rrdtool: `RRARows' must " "be greater than 0.\n"); - return (1); + return 1; } rrdcreate_config.rrarows = tmp; } else if (strcasecmp("RRATimespan", key) == 0) { @@ -945,7 +923,7 @@ static int rrd_config(const char *key, const char *value) { value_copy = strdup(value); if (value_copy == NULL) - return (1); + return 1; dummy = value_copy; while ((ptr = strtok_r(dummy, ", \t", &saveptr)) != NULL) { @@ -957,7 +935,7 @@ static int rrd_config(const char *key, const char *value) { fprintf(stderr, "rrdtool: realloc failed.\n"); ERROR("rrdtool: realloc failed.\n"); free(value_copy); - return (1); + return 1; } rrdcreate_config.timespans = tmp_alloc; rrdcreate_config.timespans[rrdcreate_config.timespans_num] = atoi(ptr); @@ -978,7 +956,7 @@ static int rrd_config(const char *key, const char *value) { "be in the range 0 to 1 (exclusive)."); ERROR("rrdtool: `XFF' must " "be in the range 0 to 1 (exclusive)."); - return (1); + return 1; } rrdcreate_config.xff = tmp; } else if (strcasecmp("WritesPerSecond", key) == 0) { @@ -987,7 +965,7 @@ static int rrd_config(const char *key, const char *value) { if (wps < 0.0) { fprintf(stderr, "rrdtool: `WritesPerSecond' must be " "greater than or equal to zero."); - return (1); + return 1; } else if (wps == 0.0) { write_rate = 0.0; } else { @@ -1006,9 +984,9 @@ static int rrd_config(const char *key, const char *value) { random_timeout = DOUBLE_TO_CDTIME_T(tmp); } } else { - return (-1); + return -1; } - return (0); + return 0; } /* int rrd_config */ static int rrd_shutdown(void) { @@ -1039,15 +1017,14 @@ static int rrd_shutdown(void) { rrd_cache_destroy(); - return (0); + return 0; } /* int rrd_shutdown */ static int rrd_init(void) { static int init_once = 0; - int status; if (init_once != 0) - return (0); + return 0; init_once = 1; if (rrdcreate_config.heartbeat <= 0) @@ -1060,23 +1037,37 @@ static int rrd_init(void) { if (cache == NULL) { pthread_mutex_unlock(&cache_lock); ERROR("rrdtool plugin: c_avl_create failed."); - return (-1); + return -1; } cache_flush_last = cdtime(); if (cache_timeout == 0) { + random_timeout = 0; cache_flush_timeout = 0; - } else if (cache_flush_timeout < cache_timeout) + } else if (cache_flush_timeout < cache_timeout) { + INFO("rrdtool plugin: \"CacheFlush %.3f\" is less than \"CacheTimeout " + "%.3f\". Adjusting \"CacheFlush\" to %.3f seconds.", + CDTIME_T_TO_DOUBLE(cache_flush_timeout), + CDTIME_T_TO_DOUBLE(cache_timeout), + CDTIME_T_TO_DOUBLE(cache_timeout * 10)); cache_flush_timeout = 10 * cache_timeout; + } + + /* 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; + } pthread_mutex_unlock(&cache_lock); - status = + int status = plugin_thread_create(&queue_thread, /* attr = */ NULL, rrd_queue_thread, /* args = */ NULL, "rrdtool queue"); if (status != 0) { ERROR("rrdtool plugin: Cannot create queue-thread."); - return (-1); + return -1; } queue_thread_running = 1; @@ -1086,7 +1077,7 @@ static int rrd_init(void) { rrdcreate_config.heartbeat, rrdcreate_config.rrarows, rrdcreate_config.xff); - return (0); + return 0; } /* int rrd_init */ void module_register(void) {