From: Florian Forster Date: Wed, 17 Nov 2010 14:18:03 +0000 (+0100) Subject: Merge branch 'ff/highres' X-Git-Tag: collectd-5.0.0-beta0~19 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=83077c18c3e78739c2d2d18debf99875944eaa72;hp=053bea810096f410d3b03ade7ef761da05565a45;p=collectd.git Merge branch 'ff/highres' Conflicts: src/netapp.c --- diff --git a/bindings/java/org/collectd/api/CollectdFlushInterface.java b/bindings/java/org/collectd/api/CollectdFlushInterface.java index 3e492ddf..410c61c6 100644 --- a/bindings/java/org/collectd/api/CollectdFlushInterface.java +++ b/bindings/java/org/collectd/api/CollectdFlushInterface.java @@ -29,5 +29,5 @@ package org.collectd.api; */ public interface CollectdFlushInterface { - public int flush (int timeout, String identifier); + public int flush (Number timeout, String identifier); } diff --git a/bindings/java/org/collectd/api/ValueList.java b/bindings/java/org/collectd/api/ValueList.java index 1baeff24..b8d6f40f 100644 --- a/bindings/java/org/collectd/api/ValueList.java +++ b/bindings/java/org/collectd/api/ValueList.java @@ -87,10 +87,16 @@ public class ValueList extends PluginData { _ds = new DataSet (_type, dsrc); } + /** + * Returns the interval (in milliseconds) of the value list. + */ public long getInterval() { return _interval; } + /** + * Sets the interval (in milliseconds) of the value list. + */ public void setInterval(long interval) { _interval = interval; } diff --git a/configure.in b/configure.in index 5d82c47c..fd6a2570 100644 --- a/configure.in +++ b/configure.in @@ -572,6 +572,16 @@ socket_needs_socket="no" AC_CHECK_FUNCS(socket, [], AC_CHECK_LIB(socket, socket, [socket_needs_socket="yes"], AC_MSG_ERROR(cannot find socket))) AM_CONDITIONAL(BUILD_WITH_LIBSOCKET, test "x$socket_needs_socket" = "xyes") +clock_gettime_needs_rt="no" +clock_gettime_needs_posix4="no" +AC_CHECK_FUNCS(clock_gettime, + [], + AC_CHECK_LIB(rt, clock_gettime, + [clock_gettime_needs_rt="yes"], + AC_CHECK_LIB(posix4, clock_gettime, + [clock_gettime_needs_posix4="yes"], + AC_MSG_ERROR(cannot find clock_gettime)))) + nanosleep_needs_rt="no" nanosleep_needs_posix4="no" AC_CHECK_FUNCS(nanosleep, @@ -581,8 +591,9 @@ AC_CHECK_FUNCS(nanosleep, AC_CHECK_LIB(posix4, nanosleep, [nanosleep_needs_posix4="yes"], AC_MSG_ERROR(cannot find nanosleep)))) -AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$nanosleep_needs_rt" = "xyes") -AM_CONDITIONAL(BUILD_WITH_LIBPOSIX4, test "x$nanosleep_needs_posix4" = "xyes") + +AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$clock_gettime_needs_rt" = "xyes" || test "x$nanosleep_needs_rt" = "xyes") +AM_CONDITIONAL(BUILD_WITH_LIBPOSIX4, test "x$clock_gettime_needs_posix4" = "xyes" || test "x$nanosleep_needs_posix4" = "xyes") AC_CHECK_FUNCS(sysctl, [have_sysctl="yes"], [have_sysctl="no"]) AC_CHECK_FUNCS(sysctlbyname, [have_sysctlbyname="yes"], [have_sysctlbyname="no"]) diff --git a/src/Makefile.am b/src/Makefile.am index 247892bb..1a7ba5b1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,6 +41,7 @@ collectd_SOURCES = collectd.c collectd.h \ utils_subst.c utils_subst.h \ utils_tail.c utils_tail.h \ utils_threshold.c utils_threshold.h \ + utils_time.c utils_time.h \ types_list.c types_list.h collectd_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL) diff --git a/src/bind.c b/src/bind.c index 6e0b907f..47215c74 100644 --- a/src/bind.c +++ b/src/bind.c @@ -241,7 +241,7 @@ static void submit (time_t ts, const char *plugin_instance, /* {{{ */ vl.values = values; vl.values_len = 1; - vl.time = ts; + vl.time = TIME_T_TO_CDTIME_T (ts); sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "bind", sizeof(vl.plugin)); if (plugin_instance) { diff --git a/src/collectd.c b/src/collectd.c index 277d3b0d..d33d1d66 100644 --- a/src/collectd.c +++ b/src/collectd.c @@ -40,7 +40,7 @@ * Global variables */ char hostname_g[DATA_MAX_NAME_LEN]; -int interval_g; +cdtime_t interval_g; int timeout_g; #if HAVE_LIBKSTAT kstat_ctl_t *kc; @@ -51,7 +51,9 @@ static int loop = 0; static void *do_flush (void __attribute__((unused)) *arg) { INFO ("Flushing all data."); - plugin_flush (NULL, -1, NULL); + plugin_flush (/* plugin = */ NULL, + /* timeout = */ 0, + /* ident = */ NULL); INFO ("Finished flushing all data."); pthread_exit (NULL); return NULL; @@ -139,15 +141,25 @@ static int init_global_variables (void) str = global_option_get ("Interval"); if (str == NULL) - str = "10"; - interval_g = atoi (str); - if (interval_g <= 0) { - fprintf (stderr, "Cannot set the interval to a correct value.\n" - "Please check your settings.\n"); - return (-1); + interval_g = TIME_T_TO_CDTIME_T (10); + } + else + { + double tmp; + + tmp = atof (str); + if (tmp <= 0.0) + { + fprintf (stderr, "Cannot set the interval to a " + "correct value.\n" + "Please check your settings.\n"); + return (-1); + } + + interval_g = DOUBLE_TO_CDTIME_T (tmp); } - DEBUG ("interval_g = %i;", interval_g); + DEBUG ("interval_g = %.3f;", CDTIME_T_TO_DOUBLE (interval_g)); str = global_option_get ("Timeout"); if (str == NULL) @@ -311,22 +323,14 @@ static int do_init (void) static int do_loop (void) { - struct timeval tv_now; - struct timeval tv_next; - struct timeval tv_wait; - struct timespec ts_wait; + cdtime_t wait_until; + + wait_until = cdtime () + interval_g; while (loop == 0) { - if (gettimeofday (&tv_next, NULL) < 0) - { - char errbuf[1024]; - ERROR ("gettimeofday failed: %s", - sstrerror (errno, errbuf, - sizeof (errbuf))); - return (-1); - } - tv_next.tv_sec += interval_g; + struct timespec ts_wait = { 0, 0 }; + cdtime_t now; #if HAVE_LIBKSTAT update_kstat (); @@ -335,27 +339,20 @@ static int do_loop (void) /* Issue all plugins */ plugin_read_all (); - if (gettimeofday (&tv_now, NULL) < 0) - { - char errbuf[1024]; - ERROR ("gettimeofday failed: %s", - sstrerror (errno, errbuf, - sizeof (errbuf))); - return (-1); - } - - if (timeval_cmp (tv_next, tv_now, &tv_wait) <= 0) + now = cdtime (); + if (now >= wait_until) { WARNING ("Not sleeping because the next interval is " - "%i.%06i seconds in the past!", - (int) tv_wait.tv_sec, (int) tv_wait.tv_usec); + "%.3f seconds in the past!", + CDTIME_T_TO_DOUBLE (now - wait_until)); + wait_until = now + interval_g; continue; } - ts_wait.tv_sec = tv_wait.tv_sec; - ts_wait.tv_nsec = (long) (1000 * tv_wait.tv_usec); + CDTIME_T_TO_TIMESPEC (wait_until - now, &ts_wait); + wait_until = wait_until + interval_g; - while ((loop == 0) && (nanosleep (&ts_wait, &ts_wait) == -1)) + while ((loop == 0) && (nanosleep (&ts_wait, &ts_wait) != 0)) { if (errno != EINTR) { @@ -368,7 +365,6 @@ static int do_loop (void) } } /* while (loop == 0) */ - DEBUG ("return (0);"); return (0); } /* int do_loop */ diff --git a/src/collectd.h b/src/collectd.h index 93d356e3..8dd0f426 100644 --- a/src/collectd.h +++ b/src/collectd.h @@ -279,8 +279,11 @@ # endif #endif -extern char hostname_g[]; -extern int interval_g; -extern int timeout_g; +/* Type for time as used by "utils_time.h" */ +typedef uint64_t cdtime_t; + +extern char hostname_g[]; +extern cdtime_t interval_g; +extern int timeout_g; #endif /* COLLECTD_H */ diff --git a/src/common.c b/src/common.c index 08653dcd..87d7bf08 100644 --- a/src/common.c +++ b/src/common.c @@ -833,7 +833,7 @@ int format_values (char *ret, size_t ret_len, /* {{{ */ offset += ((size_t) status); \ } while (0) - BUFFER_ADD ("%lu", (unsigned long) vl->time); + BUFFER_ADD ("%.3f", CDTIME_T_TO_DOUBLE (vl->time)); for (i = 0; i < ds->ds_num; i++) { @@ -979,9 +979,22 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds) if (i == -1) { if (strcmp ("N", ptr) == 0) - vl->time = time (NULL); + vl->time = cdtime (); else - vl->time = (time_t) atoi (ptr); + { + char *endptr = NULL; + double tmp; + + errno = 0; + tmp = strtod (ptr, &endptr); + if ((errno != 0) /* Overflow */ + || (endptr == ptr) /* Invalid string */ + || (endptr == NULL) /* This should not happen */ + || (*endptr != 0)) /* Trailing chars */ + return (-1); + + vl->time = DOUBLE_TO_CDTIME_T (tmp); + } } else { diff --git a/src/configfile.c b/src/configfile.c index 99dded93..e162dd99 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -1059,3 +1059,28 @@ int cf_util_get_port_number (const oconfig_item_t *ci) /* {{{ */ return (service_name_to_port_number (ci->values[0].value.string)); } /* }}} int cf_util_get_port_number */ + +int cf_util_get_cdtime (const oconfig_item_t *ci, cdtime_t *ret_value) /* {{{ */ +{ + if ((ci == NULL) || (ret_value == NULL)) + return (EINVAL); + + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) + { + ERROR ("cf_util_get_cdtime: The %s option requires " + "exactly one numeric argument.", ci->key); + return (-1); + } + + if (ci->values[0].value.number < 0.0) + { + ERROR ("cf_util_get_cdtime: The numeric argument of the %s " + "option must not be negative.", ci->key); + return (-1); + } + + *ret_value = DOUBLE_TO_CDTIME_T (ci->values[0].value.number); + + return (0); +} /* }}} int cf_util_get_cdtime */ + diff --git a/src/configfile.h b/src/configfile.h index 519a6ff8..65b1efcd 100644 --- a/src/configfile.h +++ b/src/configfile.h @@ -23,6 +23,7 @@ **/ #include "collectd.h" +#include "utils_time.h" #include "liboconfig/oconfig.h" /* @@ -113,4 +114,6 @@ int cf_util_get_flag (const oconfig_item_t *ci, * port number in the range [1-65535] or less than zero upon failure. */ int cf_util_get_port_number (const oconfig_item_t *ci); +int cf_util_get_cdtime (const oconfig_item_t *ci, cdtime_t *ret_value); + #endif /* defined(CONFIGFILE_H) */ diff --git a/src/cpu.c b/src/cpu.c index 7aa6361b..3dbe80ee 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -163,7 +163,7 @@ static int init (void) DEBUG ("host_processors returned %i %s", (int) cpu_list_len, cpu_list_len == 1 ? "processor" : "processors"); INFO ("cpu plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s"); - cpu_temp_retry_max = 86400 / interval_g; + cpu_temp_retry_max = 86400 / CDTIME_T_TO_TIME_T (interval_g); /* #endif PROCESSOR_CPU_LOAD_INFO */ #elif defined(HAVE_LIBKSTAT) diff --git a/src/cpython.h b/src/cpython.h index 46e2301a..4b8aa721 100644 --- a/src/cpython.h +++ b/src/cpython.h @@ -188,7 +188,7 @@ typedef struct { PluginData data; PyObject *values; /* Sequence */ PyObject *meta; /* dict */ - int interval; + double interval; } Values; PyTypeObject ValuesType; #define Values_New() PyObject_CallFunctionObjArgs((PyObject *) &ValuesType, (void *) 0) diff --git a/src/csv.c b/src/csv.c index 96c1e3e7..87a7b4e3 100644 --- a/src/csv.c +++ b/src/csv.c @@ -53,7 +53,8 @@ static int value_list_to_string (char *buffer, int buffer_len, memset (buffer, '\0', buffer_len); - status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) vl->time); + status = ssnprintf (buffer, buffer_len, "%.3f", + CDTIME_T_TO_DOUBLE (vl->time)); if ((status < 1) || (status >= buffer_len)) return (-1); offset = status; @@ -298,8 +299,10 @@ static int csv_write (const data_set_t *ds, const value_list_t *vl, } fprintf (use_stdio == 1 ? stdout : stderr, - "PUTVAL %s interval=%i %s\n", - filename, vl->interval, values); + "PUTVAL %s interval=%.3f %s\n", + filename, + CDTIME_T_TO_DOUBLE (vl->interval), + values); return (0); } diff --git a/src/dbi.c b/src/dbi.c index cd9240a6..caa41ef6 100644 --- a/src/dbi.c +++ b/src/dbi.c @@ -566,7 +566,7 @@ static int cdbi_read_database_query (cdbi_database_t *db, /* {{{ */ udb_query_prepare_result (q, prep_area, hostname_g, /* plugin = */ "dbi", db->name, - column_names, column_num, /* interval = */ -1); + column_names, column_num, /* interval = */ 0); /* 0 = error; 1 = success; */ status = dbi_result_first_row (res); /* {{{ */ diff --git a/src/dns.c b/src/dns.c index 6e63fe44..47da4e94 100644 --- a/src/dns.c +++ b/src/dns.c @@ -226,7 +226,7 @@ static void *dns_child_loop (void __attribute__((unused)) *dummy) pcap_obj = pcap_open_live ((pcap_device != NULL) ? pcap_device : "any", PCAP_SNAPLEN, 0 /* Not promiscuous */, - interval_g, + (int) CDTIME_T_TO_MS (interval_g / 2), pcap_error); if (pcap_obj == NULL) { diff --git a/src/exec.c b/src/exec.c index 9aabe9fc..8d5ae9c3 100644 --- a/src/exec.c +++ b/src/exec.c @@ -270,13 +270,14 @@ static void set_environment (void) /* {{{ */ char buffer[1024]; #ifdef HAVE_SETENV - ssnprintf (buffer, sizeof (buffer), "%i", interval_g); + ssnprintf (buffer, sizeof (buffer), "%.3f", CDTIME_T_TO_DOUBLE (interval_g)); setenv ("COLLECTD_INTERVAL", buffer, /* overwrite = */ 1); ssnprintf (buffer, sizeof (buffer), "%s", hostname_g); setenv ("COLLECTD_HOSTNAME", buffer, /* overwrite = */ 1); #else - ssnprintf (buffer, sizeof (buffer), "COLLECTD_INTERVAL=%i", interval_g); + ssnprintf (buffer, sizeof (buffer), "COLLECTD_INTERVAL=%.3f", + CDTIME_T_TO_DOUBLE (interval_g)); putenv (buffer); ssnprintf (buffer, sizeof (buffer), "COLLECTD_HOSTNAME=%s", hostname_g); diff --git a/src/gmond.c b/src/gmond.c index 2ffc42a5..8c774e53 100644 --- a/src/gmond.c +++ b/src/gmond.c @@ -719,7 +719,7 @@ static int mc_handle_metadata_msg (Ganglia_metadata_msg *msg) /* {{{ */ map->type, map->type_instance, ds->ds_num); if (se != NULL) - se->vl.interval = (int) msg_meta.metric.tmax; + se->vl.interval = TIME_T_TO_CDTIME_T (msg_meta.metric.tmax); pthread_mutex_unlock (&staging_lock); if (se == NULL) diff --git a/src/ipmi.c b/src/ipmi.c index 95b3dbf5..f341320d 100644 --- a/src/ipmi.c +++ b/src/ipmi.c @@ -136,7 +136,7 @@ static void sensor_read_handler (ipmi_sensor_t *sensor, if (c_ipmi_nofiy_notpresent) { - notification_t n = { NOTIF_WARNING, time(NULL), "", "", "ipmi", + notification_t n = { NOTIF_WARNING, cdtime (), "", "", "ipmi", "", "", "", NULL }; sstrncpy (n.host, hostname_g, sizeof (n.host)); @@ -190,7 +190,7 @@ static void sensor_read_handler (ipmi_sensor_t *sensor, if (c_ipmi_nofiy_notpresent) { - notification_t n = { NOTIF_OKAY, time(NULL), "", "", "ipmi", + notification_t n = { NOTIF_OKAY, cdtime (), "", "", "ipmi", "", "", "", NULL }; sstrncpy (n.host, hostname_g, sizeof (n.host)); @@ -363,7 +363,7 @@ static int sensor_list_add (ipmi_sensor_t *sensor) if (c_ipmi_nofiy_add && (c_ipmi_init_in_progress == 0)) { - notification_t n = { NOTIF_OKAY, time(NULL), "", "", "ipmi", + notification_t n = { NOTIF_OKAY, cdtime (), "", "", "ipmi", "", "", "", NULL }; sstrncpy (n.host, hostname_g, sizeof (n.host)); @@ -417,7 +417,7 @@ static int sensor_list_remove (ipmi_sensor_t *sensor) if (c_ipmi_nofiy_remove && c_ipmi_active) { - notification_t n = { NOTIF_WARNING, time(NULL), "", "", + notification_t n = { NOTIF_WARNING, cdtime (), "", "", "ipmi", "", "", "", NULL }; sstrncpy (n.host, hostname_g, sizeof (n.host)); @@ -664,7 +664,8 @@ static int c_ipmi_init (void) int status; /* Don't send `ADD' notifications during startup (~ 1 minute) */ - c_ipmi_init_in_progress = 1 + (60 / interval_g); + time_t iv = CDTIME_T_TO_TIME_T (interval_g); + c_ipmi_init_in_progress = 1 + (60 / iv); c_ipmi_active = 1; diff --git a/src/ipvs.c b/src/ipvs.c index 87eee108..f3a583b9 100644 --- a/src/ipvs.c +++ b/src/ipvs.c @@ -235,8 +235,6 @@ static void cipvs_submit_connections (char *pi, char *ti, counter_t value) vl.values = values; vl.values_len = 1; - vl.interval = interval_g; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "ipvs", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, pi, sizeof (vl.plugin_instance)); @@ -260,8 +258,6 @@ static void cipvs_submit_if (char *pi, char *t, char *ti, vl.values = values; vl.values_len = 2; - vl.interval = interval_g; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "ipvs", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, pi, sizeof (vl.plugin_instance)); diff --git a/src/java.c b/src/java.c index 528ec9c4..3089a533 100644 --- a/src/java.c +++ b/src/java.c @@ -109,7 +109,7 @@ static int cjni_callback_register (JNIEnv *jvm_env, jobject o_name, static int cjni_read (user_data_t *user_data); static int cjni_write (const data_set_t *ds, const value_list_t *vl, user_data_t *ud); -static int cjni_flush (int timeout, const char *identifier, user_data_t *ud); +static int cjni_flush (cdtime_t timeout, const char *identifier, user_data_t *ud); static void cjni_log (int severity, const char *message, user_data_t *ud); static int cjni_notification (const notification_t *n, user_data_t *ud); @@ -809,7 +809,7 @@ static jobject ctoj_value_list (JNIEnv *jvm_env, /* {{{ */ #undef SET_STRING /* Set the `time' member. Java stores time in milliseconds. */ - status = ctoj_long (jvm_env, ((jlong) vl->time) * ((jlong) 1000), + status = ctoj_long (jvm_env, (jlong) CDTIME_T_TO_MS (vl->time), c_valuelist, o_valuelist, "setTime"); if (status != 0) { @@ -819,7 +819,8 @@ static jobject ctoj_value_list (JNIEnv *jvm_env, /* {{{ */ } /* Set the `interval' member.. */ - status = ctoj_long (jvm_env, (jlong) vl->interval, + status = ctoj_long (jvm_env, + (jlong) CDTIME_T_TO_MS (vl->interval), c_valuelist, o_valuelist, "setInterval"); if (status != 0) { @@ -914,7 +915,7 @@ static jobject ctoj_notification (JNIEnv *jvm_env, /* {{{ */ return (NULL); } - /* Set the `interval' member.. */ + /* Set the `severity' member.. */ status = ctoj_int (jvm_env, (jint) n->severity, c_notification, o_notification, "setSeverity"); if (status != 0) @@ -1242,7 +1243,7 @@ static int jtoc_value_list (JNIEnv *jvm_env, value_list_t *vl, /* {{{ */ return (-1); } /* Java measures time in milliseconds. */ - vl->time = (time_t) (tmp_long / ((jlong) 1000)); + vl->time = MS_TO_CDTIME_T (tmp_long); status = jtoc_long (jvm_env, &tmp_long, class_ptr, object_ptr, "getInterval"); @@ -1251,7 +1252,7 @@ static int jtoc_value_list (JNIEnv *jvm_env, value_list_t *vl, /* {{{ */ ERROR ("java plugin: jtoc_value_list: jtoc_long (getInterval) failed."); return (-1); } - vl->interval = (int) tmp_long; + vl->interval = MS_TO_CDTIME_T (tmp_long); status = jtoc_values_array (jvm_env, ds, vl, class_ptr, object_ptr); if (status != 0) @@ -1729,7 +1730,7 @@ static cjni_callback_info_t *cjni_callback_info_create (JNIEnv *jvm_env, /* {{{ case CB_TYPE_FLUSH: method_name = "flush"; - method_signature = "(ILjava/lang/String;)I"; + method_signature = "(Ljava/lang/Number;Ljava/lang/String;)I"; break; case CB_TYPE_SHUTDOWN: @@ -2551,11 +2552,12 @@ static int cjni_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */ } /* }}} int cjni_write */ /* Call the CB_TYPE_FLUSH callback pointed to by the `user_data_t' pointer. */ -static int cjni_flush (int timeout, const char *identifier, /* {{{ */ +static int cjni_flush (cdtime_t timeout, const char *identifier, /* {{{ */ user_data_t *ud) { JNIEnv *jvm_env; cjni_callback_info_t *cbi; + jobject o_timeout; jobject o_identifier; int status; int ret_status; @@ -2578,21 +2580,32 @@ static int cjni_flush (int timeout, const char *identifier, /* {{{ */ cbi = (cjni_callback_info_t *) ud->data; + o_timeout = ctoj_jdouble_to_number (jvm_env, + (jdouble) CDTIME_T_TO_DOUBLE (timeout)); + if (o_timeout == NULL) + { + ERROR ("java plugin: cjni_flush: Converting double " + "to Number object failed."); + return (-1); + } + o_identifier = NULL; if (identifier != NULL) { o_identifier = (*jvm_env)->NewStringUTF (jvm_env, identifier); if (o_identifier == NULL) { + (*jvm_env)->DeleteLocalRef (jvm_env, o_timeout); ERROR ("java plugin: cjni_flush: NewStringUTF failed."); return (-1); } } ret_status = (*jvm_env)->CallIntMethod (jvm_env, - cbi->object, cbi->method, (jint) timeout, o_identifier); + cbi->object, cbi->method, o_timeout, o_identifier); (*jvm_env)->DeleteLocalRef (jvm_env, o_identifier); + (*jvm_env)->DeleteLocalRef (jvm_env, o_timeout); status = cjni_thread_detach (); if (status != 0) diff --git a/src/libvirt.c b/src/libvirt.c index 44f38320..5d9d84b6 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -125,17 +125,6 @@ static time_t last_refresh = (time_t) 0; static int refresh_lists (void); -/* Submit functions. */ -static void cpu_submit (unsigned long long cpu_time, - time_t t, - virDomainPtr dom, const char *type); -static void vcpu_submit (unsigned long long cpu_time, - time_t t, - virDomainPtr dom, int vcpu_nr, const char *type); -static void submit_counter2 (const char *type, counter_t v0, counter_t v1, - time_t t, - virDomainPtr dom, const char *devname); - /* ERROR(...) macro for virterrors. */ #define VIRT_ERROR(conn,s) do { \ virErrorPtr err; \ @@ -143,6 +132,113 @@ static void submit_counter2 (const char *type, counter_t v0, counter_t v1, if (err) ERROR ("%s: %s", (s), err->message); \ } while(0) +static void +init_value_list (value_list_t *vl, virDomainPtr dom) +{ + int i, n; + const char *name; + char uuid[VIR_UUID_STRING_BUFLEN]; + char *host_ptr; + size_t host_len; + + vl->interval = interval_g; + + sstrncpy (vl->plugin, "libvirt", sizeof (vl->plugin)); + + vl->host[0] = '\0'; + host_ptr = vl->host; + host_len = sizeof (vl->host); + + /* Construct the hostname field according to HostnameFormat. */ + for (i = 0; i < HF_MAX_FIELDS; ++i) { + if (hostname_format[i] == hf_none) + continue; + + n = DATA_MAX_NAME_LEN - strlen (vl->host) - 2; + + if (i > 0 && n >= 1) { + strncat (vl->host, ":", 1); + n--; + } + + switch (hostname_format[i]) { + case hf_none: break; + case hf_hostname: + strncat (vl->host, hostname_g, n); + break; + case hf_name: + name = virDomainGetName (dom); + if (name) + strncat (vl->host, name, n); + break; + case hf_uuid: + if (virDomainGetUUIDString (dom, uuid) == 0) + strncat (vl->host, uuid, n); + break; + } + } + + vl->host[sizeof (vl->host) - 1] = '\0'; +} /* void init_value_list */ + +static void +cpu_submit (unsigned long long cpu_time, + virDomainPtr dom, const char *type) +{ + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + init_value_list (&vl, dom); + + values[0].counter = cpu_time; + + vl.values = values; + vl.values_len = 1; + + sstrncpy (vl.type, type, sizeof (vl.type)); + + plugin_dispatch_values (&vl); +} + +static void +vcpu_submit (counter_t cpu_time, + virDomainPtr dom, int vcpu_nr, const char *type) +{ + value_t values[1]; + value_list_t vl = VALUE_LIST_INIT; + + init_value_list (&vl, dom); + + values[0].counter = cpu_time; + vl.values = values; + vl.values_len = 1; + + sstrncpy (vl.type, type, sizeof (vl.type)); + ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr); + + plugin_dispatch_values (&vl); +} + +static void +submit_counter2 (const char *type, counter_t v0, counter_t v1, + virDomainPtr dom, const char *devname) +{ + value_t values[2]; + value_list_t vl = VALUE_LIST_INIT; + + init_value_list (&vl, dom); + + values[0].counter = v0; + values[1].counter = v1; + vl.values = values; + vl.values_len = 2; + + sstrncpy (vl.type, type, sizeof (vl.type)); + sstrncpy (vl.type_instance, devname, sizeof (vl.type_instance)); + + plugin_dispatch_values (&vl); +} /* void submit_counter2 */ + static int lv_init (void) { @@ -322,7 +418,7 @@ lv_read (void) if (virDomainGetInfo (domains[i], &info) != 0) continue; - cpu_submit (info.cpuTime, t, domains[i], "virt_cpu_total"); + cpu_submit (info.cpuTime, domains[i], "virt_cpu_total"); vinfo = malloc (info.nrVirtCpu * sizeof vinfo[0]); if (vinfo == NULL) { @@ -338,7 +434,7 @@ lv_read (void) for (j = 0; j < info.nrVirtCpu; ++j) vcpu_submit (vinfo[j].cpuTime, - t, domains[i], vinfo[j].number, "virt_vcpu"); + domains[i], vinfo[j].number, "virt_vcpu"); sfree (vinfo); } @@ -354,12 +450,12 @@ lv_read (void) if ((stats.rd_req != -1) && (stats.wr_req != -1)) submit_counter2 ("disk_ops", (counter_t) stats.rd_req, (counter_t) stats.wr_req, - t, block_devices[i].dom, block_devices[i].path); + block_devices[i].dom, block_devices[i].path); if ((stats.rd_bytes != -1) && (stats.wr_bytes != -1)) submit_counter2 ("disk_octets", (counter_t) stats.rd_bytes, (counter_t) stats.wr_bytes, - t, block_devices[i].dom, block_devices[i].path); + block_devices[i].dom, block_devices[i].path); } /* for (nr_block_devices) */ /* Get interface stats for each domain. */ @@ -378,22 +474,22 @@ lv_read (void) if ((stats.rx_bytes != -1) && (stats.tx_bytes != -1)) submit_counter2 ("if_octets", (counter_t) stats.rx_bytes, (counter_t) stats.tx_bytes, - t, interface_devices[i].dom, display_name); + interface_devices[i].dom, display_name); if ((stats.rx_packets != -1) && (stats.tx_packets != -1)) submit_counter2 ("if_packets", (counter_t) stats.rx_packets, (counter_t) stats.tx_packets, - t, interface_devices[i].dom, display_name); + interface_devices[i].dom, display_name); if ((stats.rx_errs != -1) && (stats.tx_errs != -1)) submit_counter2 ("if_errors", (counter_t) stats.rx_errs, (counter_t) stats.tx_errs, - t, interface_devices[i].dom, display_name); + interface_devices[i].dom, display_name); if ((stats.rx_drop != -1) && (stats.tx_drop != -1)) submit_counter2 ("if_dropped", (counter_t) stats.rx_drop, (counter_t) stats.tx_drop, - t, interface_devices[i].dom, display_name); + interface_devices[i].dom, display_name); } /* for (nr_interface_devices) */ return 0; @@ -698,117 +794,6 @@ ignore_device_match (ignorelist_t *il, const char *domname, const char *devpath) return r; } -static void -init_value_list (value_list_t *vl, time_t t, virDomainPtr dom) -{ - int i, n; - const char *name; - char uuid[VIR_UUID_STRING_BUFLEN]; - char *host_ptr; - size_t host_len; - - vl->time = t; - vl->interval = interval_g; - - sstrncpy (vl->plugin, "libvirt", sizeof (vl->plugin)); - - vl->host[0] = '\0'; - host_ptr = vl->host; - host_len = sizeof (vl->host); - - /* Construct the hostname field according to HostnameFormat. */ - for (i = 0; i < HF_MAX_FIELDS; ++i) { - if (hostname_format[i] == hf_none) - continue; - - n = DATA_MAX_NAME_LEN - strlen (vl->host) - 2; - - if (i > 0 && n >= 1) { - strncat (vl->host, ":", 1); - n--; - } - - switch (hostname_format[i]) { - case hf_none: break; - case hf_hostname: - strncat (vl->host, hostname_g, n); - break; - case hf_name: - name = virDomainGetName (dom); - if (name) - strncat (vl->host, name, n); - break; - case hf_uuid: - if (virDomainGetUUIDString (dom, uuid) == 0) - strncat (vl->host, uuid, n); - break; - } - } - - vl->host[sizeof (vl->host) - 1] = '\0'; -} /* void init_value_list */ - -static void -cpu_submit (unsigned long long cpu_time, - time_t t, - virDomainPtr dom, const char *type) -{ - value_t values[1]; - value_list_t vl = VALUE_LIST_INIT; - - init_value_list (&vl, t, dom); - - values[0].counter = cpu_time; - - vl.values = values; - vl.values_len = 1; - - sstrncpy (vl.type, type, sizeof (vl.type)); - - plugin_dispatch_values (&vl); -} - -static void -vcpu_submit (counter_t cpu_time, - time_t t, - virDomainPtr dom, int vcpu_nr, const char *type) -{ - value_t values[1]; - value_list_t vl = VALUE_LIST_INIT; - - init_value_list (&vl, t, dom); - - values[0].counter = cpu_time; - vl.values = values; - vl.values_len = 1; - - sstrncpy (vl.type, type, sizeof (vl.type)); - ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr); - - plugin_dispatch_values (&vl); -} - -static void -submit_counter2 (const char *type, counter_t v0, counter_t v1, - time_t t, - virDomainPtr dom, const char *devname) -{ - value_t values[2]; - value_list_t vl = VALUE_LIST_INIT; - - init_value_list (&vl, t, dom); - - values[0].counter = v0; - values[1].counter = v1; - vl.values = values; - vl.values_len = 2; - - sstrncpy (vl.type, type, sizeof (vl.type)); - sstrncpy (vl.type_instance, devname, sizeof (vl.type_instance)); - - plugin_dispatch_values (&vl); -} /* void submit_counter2 */ - static int lv_shutdown (void) { diff --git a/src/logfile.c b/src/logfile.c index 6d0f6e07..60fb5d92 100644 --- a/src/logfile.c +++ b/src/logfile.c @@ -92,7 +92,8 @@ static int logfile_config (const char *key, const char *value) return 0; } /* int logfile_config (const char *, const char *) */ -static void logfile_print (const char *msg, int severity, time_t timestamp_time) +static void logfile_print (const char *msg, int severity, + cdtime_t timestamp_time) { FILE *fh; int do_close = 0; @@ -126,7 +127,8 @@ static void logfile_print (const char *msg, int severity, time_t timestamp_time) if (print_timestamp) { - localtime_r (×tamp_time, ×tamp_tm); + time_t tt = CDTIME_T_TO_TIME_T (timestamp_time); + localtime_r (&tt, ×tamp_tm); strftime (timestamp_str, sizeof (timestamp_str), "%Y-%m-%d %H:%M:%S", ×tamp_tm); @@ -179,7 +181,7 @@ static void logfile_log (int severity, const char *msg, if (severity > log_level) return; - logfile_print (msg, severity, time (NULL)); + logfile_print (msg, severity, cdtime ()); } /* void logfile_log (int, const char *) */ static int logfile_notification (const notification_t *n, @@ -218,7 +220,7 @@ static int logfile_notification (const notification_t *n, buf[sizeof (buf) - 1] = '\0'; logfile_print (buf, LOG_INFO, - (n->time > 0) ? n->time : time (NULL)); + (n->time != 0) ? n->time : cdtime ()); return (0); } /* int logfile_notification */ diff --git a/src/match_timediff.c b/src/match_timediff.c index 4ac944af..2e274155 100644 --- a/src/match_timediff.c +++ b/src/match_timediff.c @@ -34,29 +34,13 @@ struct mt_match_s; typedef struct mt_match_s mt_match_t; struct mt_match_s { - time_t future; - time_t past; + cdtime_t future; + cdtime_t past; }; /* * internal helper functions */ -static int mt_config_add_time_t (time_t *ret_value, /* {{{ */ - oconfig_item_t *ci) -{ - - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) - { - ERROR ("timediff match: `%s' needs exactly one numeric argument.", - ci->key); - return (-1); - } - - *ret_value = (time_t) ci->values[0].value.number; - - return (0); -} /* }}} int mt_config_add_time_t */ - static int mt_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ { mt_match_t *m; @@ -80,9 +64,9 @@ static int mt_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ oconfig_item_t *child = ci->children + i; if (strcasecmp ("Future", child->key) == 0) - status = mt_config_add_time_t (&m->future, child); + status = cf_util_get_cdtime (child, &m->future); else if (strcasecmp ("Past", child->key) == 0) - status = mt_config_add_time_t (&m->past, child); + status = cf_util_get_cdtime (child, &m->past); else { ERROR ("timediff match: The `%s' configuration option is not " @@ -132,13 +116,13 @@ static int mt_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */ notification_meta_t __attribute__((unused)) **meta, void **user_data) { mt_match_t *m; - time_t now; + cdtime_t now; if ((user_data == NULL) || (*user_data == NULL)) return (-1); m = *user_data; - now = time (NULL); + now = cdtime (); if (m->future != 0) { diff --git a/src/memcached.c b/src/memcached.c index 8490bf66..8b4a8fc1 100644 --- a/src/memcached.c +++ b/src/memcached.c @@ -176,12 +176,14 @@ static int memcached_query_daemon (char *buffer, int buffer_size) /* {{{ */ p.events = POLLIN | POLLERR | POLLHUP; p.revents = 0; - status = poll (&p, /* nfds = */ 1, /* timeout = */ 1000 * interval_g); + status = poll (&p, /* nfds = */ 1, + /* timeout = */ CDTIME_T_TO_MS (interval_g)); if (status <= 0) { if (status == 0) { - ERROR ("memcached: poll(2) timed out after %i seconds.", interval_g); + ERROR ("memcached: poll(2) timed out after %.3f seconds.", + CDTIME_T_TO_DOUBLE (interval_g)); } else { diff --git a/src/modbus.c b/src/modbus.c index adab0d0f..3824097c 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -94,7 +94,7 @@ struct mb_host_s /* {{{ */ char node[NI_MAXHOST]; /* char service[NI_MAXSERV]; */ int port; - int interval; + cdtime_t interval; mb_slave_t *slaves; size_t slaves_num; @@ -771,7 +771,7 @@ static int mb_config_add_host (oconfig_item_t *ci) /* {{{ */ status = -1; } else if (strcasecmp ("Interval", child->key) == 0) - status = cf_util_get_int (child, &host->interval); + status = cf_util_get_cdtime (child, &host->interval); else if (strcasecmp ("Slave", child->key) == 0) /* Don't set status: Gracefully continue if a slave fails. */ mb_config_add_slave (host, child); @@ -797,21 +797,19 @@ static int mb_config_add_host (oconfig_item_t *ci) /* {{{ */ { user_data_t ud; char name[1024]; - struct timespec interval; + struct timespec interval = { 0, 0 }; ud.data = host; ud.free_func = host_free; ssnprintf (name, sizeof (name), "modbus-%s", host->host); - interval.tv_nsec = 0; - if (host->interval > 0) - interval.tv_sec = host->interval; - else - interval.tv_sec = 0; + CDTIME_T_TO_TIMESPEC (host->interval, &interval); plugin_register_complex_read (/* group = */ NULL, name, - mb_read, (interval.tv_sec > 0) ? &interval : NULL, &ud); + /* callback = */ mb_read, + /* interval = */ (host->interval > 0) ? &interval : NULL, + &ud); } else { diff --git a/src/mysql.c b/src/mysql.c index a01bbe40..1ca3b484 100644 --- a/src/mysql.c +++ b/src/mysql.c @@ -485,7 +485,7 @@ static int mysql_read_slave_stats (mysql_database_t *db, MYSQL *con) if (db->slave_notif) { - notification_t n = { 0, time (NULL), "", "", + notification_t n = { 0, cdtime (), "", "", "mysql", "", "time_offset", "", NULL }; char *io, *sql; diff --git a/src/netapp.c b/src/netapp.c index c50b3dbd..5c4b6e73 100644 --- a/src/netapp.c +++ b/src/netapp.c @@ -38,8 +38,8 @@ typedef void service_handler_t(host_config_t *host, na_elem_t *result, void *dat struct cna_interval_s { - time_t interval; - time_t last_read; + cdtime_t interval; + cdtime_t last_read; }; typedef struct cna_interval_s cna_interval_t; @@ -79,7 +79,7 @@ typedef struct { cna_interval_t interval; na_elem_t *query; - time_t timestamp; + cdtime_t timestamp; uint64_t name_cache_hit; uint64_t name_cache_miss; uint64_t find_dir_hit; @@ -104,7 +104,7 @@ typedef struct { typedef struct disk_s { char *name; uint32_t flags; - time_t timestamp; + cdtime_t timestamp; uint64_t disk_busy; uint64_t base_for_disk_busy; double disk_busy_percent; @@ -153,7 +153,7 @@ typedef struct data_volume_perf_s data_volume_perf_t; struct data_volume_perf_s { char *name; uint32_t flags; - time_t timestamp; + cdtime_t timestamp; uint64_t read_bytes; uint64_t write_bytes; @@ -242,7 +242,7 @@ struct host_config_s { int port; char *username; char *password; - int interval; + cdtime_t interval; na_server_t *srv; cfg_wafl_t *cfg_wafl; @@ -566,7 +566,7 @@ static int submit_values (const char *host, /* {{{ */ const char *plugin_inst, const char *type, const char *type_inst, value_t *values, int values_len, - time_t timestamp, int interval) + cdtime_t timestamp, cdtime_t interval) { value_list_t vl = VALUE_LIST_INIT; @@ -595,7 +595,7 @@ static int submit_values (const char *host, /* {{{ */ static int submit_two_counters (const char *host, const char *plugin_inst, /* {{{ */ const char *type, const char *type_inst, counter_t val0, counter_t val1, - time_t timestamp, int interval) + cdtime_t timestamp, cdtime_t interval) { value_t values[2]; @@ -607,7 +607,8 @@ static int submit_two_counters (const char *host, const char *plugin_inst, /* {{ } /* }}} int submit_two_counters */ static int submit_counter (const char *host, const char *plugin_inst, /* {{{ */ - const char *type, const char *type_inst, counter_t counter, time_t timestamp, int interval) + const char *type, const char *type_inst, counter_t counter, + cdtime_t timestamp, cdtime_t interval) { value_t v; @@ -619,7 +620,7 @@ static int submit_counter (const char *host, const char *plugin_inst, /* {{{ */ static int submit_two_gauge (const char *host, const char *plugin_inst, /* {{{ */ const char *type, const char *type_inst, gauge_t val0, gauge_t val1, - time_t timestamp, int interval) + cdtime_t timestamp, cdtime_t interval) { value_t values[2]; @@ -631,7 +632,8 @@ static int submit_two_gauge (const char *host, const char *plugin_inst, /* {{{ * } /* }}} int submit_two_gauge */ static int submit_double (const char *host, const char *plugin_inst, /* {{{ */ - const char *type, const char *type_inst, double d, time_t timestamp, int interval) + const char *type, const char *type_inst, double d, + cdtime_t timestamp, cdtime_t interval) { value_t v; @@ -650,8 +652,8 @@ static int submit_cache_ratio (const char *host, /* {{{ */ uint64_t new_misses, uint64_t old_hits, uint64_t old_misses, - time_t timestamp, - int interval) + cdtime_t timestamp, + cdtime_t interval) { value_t v; @@ -816,6 +818,16 @@ static int submit_volume_perf_data (const char *hostname, /* {{{ */ return (0); } /* }}} int submit_volume_perf_data */ +static cdtime_t cna_child_get_cdtime (na_elem_t *data) /* {{{ */ +{ + time_t t; + + t = (time_t) na_child_get_uint64 (data, "timestamp", /* default = */ 0); + + return (TIME_T_TO_CDTIME_T (t)); +} /* }}} cdtime_t cna_child_get_cdtime */ + + /* * Query functions * @@ -835,7 +847,7 @@ static int cna_handle_wafl_data (const char *hostname, cfg_wafl_t *cfg_wafl, /* memset (&perf_data, 0, sizeof (perf_data)); - perf_data.timestamp = (time_t) na_child_get_uint64 (data, "timestamp", 0); + perf_data.timestamp = cna_child_get_cdtime (data); instances = na_elem_child(na_elem_child (data, "instances"), "instance-data"); if (instances == NULL) @@ -950,7 +962,7 @@ static int cna_query_wafl (host_config_t *host) /* {{{ */ { na_elem_t *data; int status; - time_t now; + cdtime_t now; if (host == NULL) return (EINVAL); @@ -959,7 +971,7 @@ static int cna_query_wafl (host_config_t *host) /* {{{ */ if (host->cfg_wafl == NULL) return (0); - now = time (NULL); + now = cdtime (); if ((host->cfg_wafl->interval.interval + host->cfg_wafl->interval.last_read) > now) return (0); @@ -988,9 +1000,9 @@ static int cna_query_wafl (host_config_t *host) /* {{{ */ /* Data corresponding to */ static int cna_handle_disk_data (const char *hostname, /* {{{ */ - cfg_disk_t *cfg_disk, na_elem_t *data, int interval) + cfg_disk_t *cfg_disk, na_elem_t *data, cdtime_t interval) { - time_t timestamp; + cdtime_t timestamp; na_elem_t *instances; na_elem_t *instance; na_elem_iter_t instance_iter; @@ -999,7 +1011,7 @@ static int cna_handle_disk_data (const char *hostname, /* {{{ */ if ((cfg_disk == NULL) || (data == NULL)) return (EINVAL); - timestamp = (time_t) na_child_get_uint64(data, "timestamp", 0); + timestamp = cna_child_get_cdtime (data); instances = na_elem_child (data, "instances"); if (instances == NULL) @@ -1144,7 +1156,7 @@ static int cna_query_disk (host_config_t *host) /* {{{ */ { na_elem_t *data; int status; - time_t now; + cdtime_t now; if (host == NULL) return (EINVAL); @@ -1154,7 +1166,7 @@ static int cna_query_disk (host_config_t *host) /* {{{ */ if (host->cfg_disk == NULL) return (0); - now = time (NULL); + now = cdtime (); if ((host->cfg_disk->interval.interval + host->cfg_disk->interval.last_read) > now) return (0); @@ -1183,14 +1195,14 @@ static int cna_query_disk (host_config_t *host) /* {{{ */ /* Data corresponding to */ static int cna_handle_volume_perf_data (const char *hostname, /* {{{ */ - cfg_volume_perf_t *cvp, na_elem_t *data, int interval) + cfg_volume_perf_t *cvp, na_elem_t *data, cdtime_t interval) { - time_t timestamp; + cdtime_t timestamp; na_elem_t *elem_instances; na_elem_iter_t iter_instances; na_elem_t *elem_instance; - timestamp = (time_t) na_child_get_uint64(data, "timestamp", 0); + timestamp = cna_child_get_cdtime (data); elem_instances = na_elem_child(data, "instances"); if (elem_instances == NULL) @@ -1315,7 +1327,7 @@ static int cna_query_volume_perf (host_config_t *host) /* {{{ */ { na_elem_t *data; int status; - time_t now; + cdtime_t now; if (host == NULL) return (EINVAL); @@ -1325,7 +1337,7 @@ static int cna_query_volume_perf (host_config_t *host) /* {{{ */ if (host->cfg_volume_perf == NULL) return (0); - now = time (NULL); + now = cdtime (); if ((host->cfg_volume_perf->interval.interval + host->cfg_volume_perf->interval.last_read) > now) return (0); @@ -1444,7 +1456,7 @@ static int cna_change_volume_status (const char *hostname, /* {{{ */ notification_t n; memset (&n, 0, sizeof (&n)); - n.time = time (NULL); + n.time = cdtime (); sstrncpy (n.host, hostname, sizeof (n.host)); sstrncpy (n.plugin, "netapp", sizeof (n.plugin)); sstrncpy (n.plugin_instance, v->name, sizeof (n.plugin_instance)); @@ -1679,7 +1691,7 @@ static int cna_query_volume_usage (host_config_t *host) /* {{{ */ { na_elem_t *data; int status; - time_t now; + cdtime_t now; if (host == NULL) return (EINVAL); @@ -1689,7 +1701,7 @@ static int cna_query_volume_usage (host_config_t *host) /* {{{ */ if (host->cfg_volume_usage == NULL) return (0); - now = time (NULL); + now = cdtime (); if ((host->cfg_volume_usage->interval.interval + host->cfg_volume_usage->interval.last_read) > now) return (0); @@ -1730,9 +1742,9 @@ static int cna_handle_system_data (const char *hostname, /* {{{ */ uint32_t counter_flags = 0; const char *instance; - time_t timestamp; + cdtime_t timestamp; - timestamp = (time_t) na_child_get_uint64 (data, "timestamp", 0); + timestamp = cna_child_get_cdtime (data); instances = na_elem_child(na_elem_child (data, "instances"), "instance-data"); if (instances == NULL) @@ -1839,7 +1851,7 @@ static int cna_query_system (host_config_t *host) /* {{{ */ { na_elem_t *data; int status; - time_t now; + cdtime_t now; if (host == NULL) return (EINVAL); @@ -1848,7 +1860,7 @@ static int cna_query_system (host_config_t *host) /* {{{ */ if (host->cfg_system == NULL) return (0); - now = time (NULL); + now = cdtime (); if ((host->cfg_system->interval.interval + host->cfg_system->interval.last_read) > now) return (0); @@ -1905,23 +1917,12 @@ static int cna_config_bool_to_flag (const oconfig_item_t *ci, /* {{{ */ static int cna_config_get_interval (const oconfig_item_t *ci, /* {{{ */ cna_interval_t *out_interval) { - time_t tmp; - - if ((ci == NULL) || (out_interval == NULL)) - return (EINVAL); - - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) - { - WARNING ("netapp plugin: The `Interval' option needs exactly one numeric argument."); - return (-1); - } + cdtime_t tmp = 0; + int status; - tmp = (time_t) (ci->values[0].value.number + .5); - if (tmp < 1) - { - WARNING ("netapp plugin: The `Interval' option needs a positive integer argument."); - return (-1); - } + status = cf_util_get_cdtime (ci, &tmp); + if (status != 0) + return (status); out_interval->interval = tmp; out_interval->last_read = 0; @@ -2421,11 +2422,7 @@ static host_config_t *cna_config_host (const oconfig_item_t *ci) /* {{{ */ } else if (!strcasecmp(item->key, "Password")) { status = cf_util_get_string (item, &host->password); } else if (!strcasecmp(item->key, "Interval")) { - if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_NUMBER || item->values[0].value.number != (int) item->values[0].value.number || item->values[0].value.number < 2) { - WARNING("netapp plugin: \"Interval\" of host %s needs exactly one integer argument.", ci->values[0].value.string); - continue; - } - host->interval = item->values[0].value.number; + status = cf_util_get_cdtime (item, &host->interval); } else if (!strcasecmp(item->key, "WAFL")) { cna_config_wafl(host, item); } else if (!strcasecmp(item->key, "Disks")) { @@ -2556,8 +2553,7 @@ static int cna_config (oconfig_item_t *ci) { /* {{{ */ ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name); - memset (&interval, 0, sizeof (interval)); - interval.tv_sec = host->interval; + CDTIME_T_TO_TIMESPEC (host->interval, &interval); memset (&ud, 0, sizeof (ud)); ud.data = host; diff --git a/src/network.c b/src/network.c index 3ad11778..7a1fcf7f 100644 --- a/src/network.c +++ b/src/network.c @@ -1381,8 +1381,19 @@ static int parse_packet (sockent_t *se, /* {{{ */ &tmp); if (status == 0) { - vl.time = (time_t) tmp; - n.time = (time_t) tmp; + vl.time = TIME_T_TO_CDTIME_T (tmp); + n.time = TIME_T_TO_CDTIME_T (tmp); + } + } + else if (pkg_type == TYPE_TIME_HR) + { + uint64_t tmp = 0; + status = parse_part_number (&buffer, &buffer_size, + &tmp); + if (status == 0) + { + vl.time = (cdtime_t) tmp; + n.time = (cdtime_t) tmp; } } else if (pkg_type == TYPE_INTERVAL) @@ -1391,7 +1402,15 @@ static int parse_packet (sockent_t *se, /* {{{ */ status = parse_part_number (&buffer, &buffer_size, &tmp); if (status == 0) - vl.interval = (int) tmp; + vl.interval = TIME_T_TO_CDTIME_T (tmp); + } + else if (pkg_type == TYPE_INTERVAL_HR) + { + uint64_t tmp = 0; + status = parse_part_number (&buffer, &buffer_size, + &tmp); + if (status == 0) + vl.interval = (cdtime_t) tmp; } else if (pkg_type == TYPE_HOST) { @@ -2587,7 +2606,7 @@ static int add_to_buffer (char *buffer, int buffer_size, /* {{{ */ if (vl_def->time != vl->time) { - if (write_part_number (&buffer, &buffer_size, TYPE_TIME, + if (write_part_number (&buffer, &buffer_size, TYPE_TIME_HR, (uint64_t) vl->time)) return (-1); vl_def->time = vl->time; @@ -2595,7 +2614,7 @@ static int add_to_buffer (char *buffer, int buffer_size, /* {{{ */ if (vl_def->interval != vl->interval) { - if (write_part_number (&buffer, &buffer_size, TYPE_INTERVAL, + if (write_part_number (&buffer, &buffer_size, TYPE_INTERVAL_HR, (uint64_t) vl->interval)) return (-1); vl_def->interval = vl->interval; @@ -3077,8 +3096,7 @@ static int network_notification (const notification_t *n, memset (buffer, '\0', sizeof (buffer)); - - status = write_part_number (&buffer_ptr, &buffer_free, TYPE_TIME, + status = write_part_number (&buffer_ptr, &buffer_free, TYPE_TIME_HR, (uint64_t) n->time); if (status != 0) return (-1); @@ -3352,9 +3370,9 @@ static int network_init (void) * just send the buffer if `flush' is called - if the requested value was in * there, good. If not, well, then there is nothing to flush.. -octo */ -static int network_flush (int timeout, - const char __attribute__((unused)) *identifier, - user_data_t __attribute__((unused)) *user_data) +static int network_flush (__attribute__((unused)) cdtime_t timeout, + __attribute__((unused)) const char *identifier, + __attribute__((unused)) user_data_t *user_data) { pthread_mutex_lock (&send_buffer_lock); diff --git a/src/network.h b/src/network.h index 777616c4..1b354561 100644 --- a/src/network.h +++ b/src/network.h @@ -56,12 +56,14 @@ #define TYPE_HOST 0x0000 #define TYPE_TIME 0x0001 +#define TYPE_TIME_HR 0x0008 #define TYPE_PLUGIN 0x0002 #define TYPE_PLUGIN_INSTANCE 0x0003 #define TYPE_TYPE 0x0004 #define TYPE_TYPE_INSTANCE 0x0005 #define TYPE_VALUES 0x0006 #define TYPE_INTERVAL 0x0007 +#define TYPE_INTERVAL_HR 0x0009 /* Types to transmit notifications */ #define TYPE_MESSAGE 0x0100 diff --git a/src/notify_email.c b/src/notify_email.c index 0aed27f1..da6894a3 100644 --- a/src/notify_email.c +++ b/src/notify_email.c @@ -230,6 +230,7 @@ static int notify_email_notification (const notification_t *n, { smtp_recipient_t recipient; + time_t tt; struct tm timestamp_tm; char timestamp_str[64]; @@ -249,7 +250,8 @@ static int notify_email_notification (const notification_t *n, (email_subject == NULL) ? DEFAULT_SMTP_SUBJECT : email_subject, severity, n->host); - localtime_r (&n->time, ×tamp_tm); + tt = CDTIME_T_TO_TIME_T (n->time); + localtime_r (&tt, ×tamp_tm); strftime (timestamp_str, sizeof (timestamp_str), "%Y-%m-%d %H:%M:%S", ×tamp_tm); timestamp_str[sizeof (timestamp_str) - 1] = '\0'; diff --git a/src/onewire.c b/src/onewire.c index 462458c7..09a6bf09 100644 --- a/src/onewire.c +++ b/src/onewire.c @@ -59,7 +59,7 @@ static ow_family_features_t ow_family_features[] = static int ow_family_features_num = STATIC_ARRAY_SIZE (ow_family_features); static char *device_g = NULL; -static int ow_interval = 0; +static cdtime_t ow_interval = 0; static const char *config_keys[] = { @@ -106,10 +106,10 @@ static int cow_load_config (const char *key, const char *value) } else if (strcasecmp ("Interval", key) == 0) { - int tmp; - tmp = atoi (value); - if (tmp > 0) - ow_interval = tmp; + double tmp; + tmp = atof (value); + if (tmp > 0.0) + ow_interval = DOUBLE_TO_CDTIME_T (tmp); else ERROR ("onewire plugin: Invalid `Interval' setting: %s", value); } @@ -306,12 +306,11 @@ static int cow_init (void) return (1); } - memset (&cb_interval, 0, sizeof (cb_interval)); - if (ow_interval > 0) - cb_interval.tv_sec = (time_t) ow_interval; + CDTIME_T_TO_TIMESPEC (ow_interval, &cb_interval); plugin_register_complex_read (/* group = */ NULL, "onewire", cow_read, - &cb_interval, /* user data = */ NULL); + (ow_interval != 0) ? &cb_interval : NULL, + /* user data = */ NULL); plugin_register_shutdown ("onewire", cow_shutdown); return (0); diff --git a/src/oracle.c b/src/oracle.c index 2f218519..03567494 100644 --- a/src/oracle.c +++ b/src/oracle.c @@ -586,7 +586,7 @@ static int o_read_database_query (o_database_t *db, /* {{{ */ status = udb_query_prepare_result (q, prep_area, hostname_g, /* plugin = */ "oracle", db->name, column_names, column_num, - /* interval = */ -1); + /* interval = */ 0); if (status != 0) { ERROR ("oracle plugin: o_read_database_query (%s, %s): " diff --git a/src/perl.c b/src/perl.c index 72605804..f8a48227 100644 --- a/src/perl.c +++ b/src/perl.c @@ -235,15 +235,6 @@ struct { { "", NULL } }; -struct { - char name[64]; - int *var; -} g_integers[] = -{ - { "Collectd::interval_g", &interval_g }, - { "", NULL } -}; - /* * Helper functions for data type conversion. */ @@ -397,10 +388,16 @@ static int hv2value_list (pTHX_ HV *hash, value_list_t *vl) } if (NULL != (tmp = hv_fetch (hash, "time", 4, 0))) - vl->time = (time_t)SvIV (*tmp); + { + double t = SvNV (*tmp); + vl->time = DOUBLE_TO_CDTIME_T (t); + } if (NULL != (tmp = hv_fetch (hash, "interval", 8, 0))) - vl->interval = SvIV (*tmp); + { + double t = SvNV (*tmp); + vl->interval = DOUBLE_TO_CDTIME_T (t); + } if (NULL != (tmp = hv_fetch (hash, "host", 4, 0))) sstrncpy (vl->host, SvPV_nolen (*tmp), sizeof (vl->host)); @@ -552,9 +549,12 @@ static int hv2notification (pTHX_ HV *hash, notification_t *n) n->severity = NOTIF_FAILURE; if (NULL != (tmp = hv_fetch (hash, "time", 4, 0))) - n->time = (time_t)SvIV (*tmp); + { + double t = SvNV (*tmp); + n->time = DOUBLE_TO_CDTIME_T (t); + } else - n->time = time (NULL); + n->time = cdtime (); if (NULL != (tmp = hv_fetch (hash, "message", 7, 0))) sstrncpy (n->message, SvPV_nolen (*tmp), sizeof (n->message)); @@ -672,11 +672,17 @@ static int value_list2hv (pTHX_ value_list_t *vl, data_set_t *ds, HV *hash) return -1; if (0 != vl->time) - if (NULL == hv_store (hash, "time", 4, newSViv (vl->time), 0)) + { + double t = CDTIME_T_TO_DOUBLE (vl->time); + if (NULL == hv_store (hash, "time", 4, newSVnv (t), 0)) return -1; + } - if (NULL == hv_store (hash, "interval", 8, newSViv (vl->interval), 0)) - return -1; + { + double t = CDTIME_T_TO_DOUBLE (vl->interval); + if (NULL == hv_store (hash, "interval", 8, newSVnv (t), 0)) + return -1; + } if ('\0' != vl->host[0]) if (NULL == hv_store (hash, "host", 4, newSVpv (vl->host, 0), 0)) @@ -754,8 +760,11 @@ static int notification2hv (pTHX_ notification_t *n, HV *hash) return -1; if (0 != n->time) - if (NULL == hv_store (hash, "time", 4, newSViv (n->time), 0)) + { + double t = CDTIME_T_TO_DOUBLE (n->time); + if (NULL == hv_store (hash, "time", 4, newSVnv (t), 0)) return -1; + } if ('\0' != *n->message) if (NULL == hv_store (hash, "message", 7, newSVpv (n->message, 0), 0)) @@ -1106,11 +1115,15 @@ static int pplugin_call_all (pTHX_ int type, ...) XPUSHs (sv_2mortal (newRV_noinc ((SV *)notif))); } else if (PLUGIN_FLUSH == type) { + cdtime_t timeout; + /* * $_[0] = $timeout; * $_[1] = $identifier; */ - XPUSHs (sv_2mortal (newSViv (va_arg (ap, int)))); + timeout = va_arg (ap, cdtime_t); + + XPUSHs (sv_2mortal (newSVnv (CDTIME_T_TO_DOUBLE (timeout)))); XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0))); } @@ -1986,7 +1999,7 @@ static int perl_notify (const notification_t *notif, return pplugin_call_all (aTHX_ PLUGIN_NOTIF, notif); } /* static int perl_notify (const notification_t *) */ -static int perl_flush (int timeout, const char *identifier, +static int perl_flush (cdtime_t timeout, const char *identifier, user_data_t __attribute__((unused)) *user_data) { dTHX; @@ -2088,19 +2101,27 @@ static int g_pv_set (pTHX_ SV *var, MAGIC *mg) return 0; } /* static int g_pv_set (pTHX_ SV *, MAGIC *) */ -static int g_iv_get (pTHX_ SV *var, MAGIC *mg) +static int g_interval_get (pTHX_ SV *var, MAGIC *mg) { - int *iv = (int *)mg->mg_ptr; - sv_setiv (var, *iv); + cdtime_t *interval = (cdtime_t *)mg->mg_ptr; + double nv; + + nv = CDTIME_T_TO_DOUBLE (*interval); + + sv_setnv (var, nv); return 0; -} /* static int g_iv_get (pTHX_ SV *, MAGIC *) */ +} /* static int g_interval_get (pTHX_ SV *, MAGIC *) */ -static int g_iv_set (pTHX_ SV *var, MAGIC *mg) +static int g_interval_set (pTHX_ SV *var, MAGIC *mg) { - int *iv = (int *)mg->mg_ptr; - *iv = (int)SvIV (var); + cdtime_t *interval = (cdtime_t *)mg->mg_ptr; + double nv; + + nv = (double)SvNV (var); + + *interval = DOUBLE_TO_CDTIME_T (nv); return 0; -} /* static int g_iv_set (pTHX_ SV *, MAGIC *) */ +} /* static int g_interval_set (pTHX_ SV *, MAGIC *) */ static MGVTBL g_pv_vtbl = { g_pv_get, g_pv_set, NULL, NULL, NULL, NULL, NULL @@ -2108,8 +2129,8 @@ static MGVTBL g_pv_vtbl = { , NULL #endif }; -static MGVTBL g_iv_vtbl = { - g_iv_get, g_iv_set, NULL, NULL, NULL, NULL, NULL +static MGVTBL g_interval_vtbl = { + g_interval_get, g_interval_set, NULL, NULL, NULL, NULL, NULL #if HAVE_PERL_STRUCT_MGVTBL_SVT_LOCAL , NULL #endif @@ -2151,12 +2172,11 @@ static void xs_init (pTHX) g_strings[i].var, 0); } - /* global integers */ - for (i = 0; '\0' != g_integers[i].name[0]; ++i) { - tmp = get_sv (g_integers[i].name, 1); - sv_magicext (tmp, NULL, PERL_MAGIC_ext, &g_iv_vtbl, - (char *)g_integers[i].var, 0); - } + tmp = get_sv ("Collectd::interval_g", /* create = */ 1); + sv_magicext (tmp, NULL, /* how = */ PERL_MAGIC_ext, + /* vtbl = */ &g_interval_vtbl, + /* name = */ (char *) &interval_g, /* namelen = */ 0); + return; } /* static void xs_init (pTHX) */ diff --git a/src/plugin.c b/src/plugin.c index 65d3875e..f6bc506c 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -336,7 +336,7 @@ static void *plugin_read_thread (void __attribute__((unused)) *args) while (read_loop != 0) { read_func_t *rf; - struct timeval now; + cdtime_t now; int status; int rf_type; int rc; @@ -347,10 +347,9 @@ static void *plugin_read_thread (void __attribute__((unused)) *args) { struct timespec abstime; - gettimeofday (&now, /* timezone = */ NULL); + now = cdtime (); - abstime.tv_sec = now.tv_sec + interval_g; - abstime.tv_nsec = 1000 * now.tv_usec; + CDTIME_T_TO_TIMESPEC (now + interval_g, &abstime); pthread_mutex_lock (&read_lock); pthread_cond_timedwait (&read_cond, &read_lock, @@ -361,15 +360,13 @@ static void *plugin_read_thread (void __attribute__((unused)) *args) if ((rf->rf_interval.tv_sec == 0) && (rf->rf_interval.tv_nsec == 0)) { - gettimeofday (&now, /* timezone = */ NULL); + now = cdtime (); - rf->rf_interval.tv_sec = interval_g; - rf->rf_interval.tv_nsec = 0; + CDTIME_T_TO_TIMESPEC (interval_g, &rf->rf_interval); rf->rf_effective_interval = rf->rf_interval; - rf->rf_next_read.tv_sec = now.tv_sec; - rf->rf_next_read.tv_nsec = 1000 * now.tv_usec; + CDTIME_T_TO_TIMESPEC (now, &rf->rf_next_read); } /* sleep until this entry is due, @@ -459,7 +456,7 @@ static void *plugin_read_thread (void __attribute__((unused)) *args) } /* update the ``next read due'' field */ - gettimeofday (&now, /* timezone = */ NULL); + now = cdtime (); DEBUG ("plugin_read_thread: Effective interval of the " "%s plugin is %i.%09i.", @@ -476,15 +473,12 @@ static void *plugin_read_thread (void __attribute__((unused)) *args) NORMALIZE_TIMESPEC (rf->rf_next_read); /* Check, if `rf_next_read' is in the past. */ - if ((rf->rf_next_read.tv_sec < now.tv_sec) - || ((rf->rf_next_read.tv_sec == now.tv_sec) - && (rf->rf_next_read.tv_nsec < (1000 * now.tv_usec)))) + if (TIMESPEC_TO_CDTIME_T (&rf->rf_next_read) < now) { /* `rf_next_read' is in the past. Insert `now' * so this value doesn't trail off into the * past too much. */ - rf->rf_next_read.tv_sec = now.tv_sec; - rf->rf_next_read.tv_nsec = 1000 * now.tv_usec; + CDTIME_T_TO_TIMESPEC (now, &rf->rf_next_read); } DEBUG ("plugin_read_thread: Next read of the %s plugin at %i.%09i.", @@ -1251,7 +1245,7 @@ int plugin_write (const char *plugin, /* {{{ */ return (status); } /* }}} int plugin_write */ -int plugin_flush (const char *plugin, int timeout, const char *identifier) +int plugin_flush (const char *plugin, cdtime_t timeout, const char *identifier) { llentry_t *le; @@ -1296,7 +1290,8 @@ void plugin_shutdown_all (void) destroy_read_heap (); - plugin_flush (/* plugin = */ NULL, /* timeout = */ -1, + plugin_flush (/* plugin = */ NULL, + /* timeout = */ 0, /* identifier = */ NULL); le = NULL; @@ -1384,16 +1379,17 @@ int plugin_dispatch_values (value_list_t *vl) } if (vl->time == 0) - vl->time = time (NULL); + vl->time = cdtime (); if (vl->interval <= 0) vl->interval = interval_g; - DEBUG ("plugin_dispatch_values: time = %u; interval = %i; " + DEBUG ("plugin_dispatch_values: time = %.3f; interval = %.3f; " "host = %s; " "plugin = %s; plugin_instance = %s; " "type = %s; type_instance = %s;", - (unsigned int) vl->time, vl->interval, + CDTIME_T_TO_DOUBLE (vl->time), + CDTIME_T_TO_DOUBLE (vl->interval), vl->host, vl->plugin, vl->plugin_instance, vl->type, vl->type_instance); @@ -1518,9 +1514,9 @@ int plugin_dispatch_notification (const notification_t *notif) /* Possible TODO: Add flap detection here */ DEBUG ("plugin_dispatch_notification: severity = %i; message = %s; " - "time = %u; host = %s;", + "time = %.3f; host = %s;", notif->severity, notif->message, - (unsigned int) notif->time, notif->host); + CDTIME_T_TO_DOUBLE (notif->time), notif->host); /* Nobody cares for notifications */ if (list_notification == NULL) diff --git a/src/plugin.h b/src/plugin.h index d78aa4f8..490aed03 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -25,6 +25,7 @@ #include "collectd.h" #include "configfile.h" #include "meta_data.h" +#include "utils_time.h" #define PLUGIN_FLAGS_GLOBAL 0x0001 @@ -85,8 +86,8 @@ struct value_list_s { value_t *values; int values_len; - time_t time; - int interval; + cdtime_t time; + cdtime_t interval; char host[DATA_MAX_NAME_LEN]; char plugin[DATA_MAX_NAME_LEN]; char plugin_instance[DATA_MAX_NAME_LEN]; @@ -143,7 +144,7 @@ typedef struct notification_meta_s typedef struct notification_s { int severity; - time_t time; + cdtime_t time; char message[NOTIF_MAX_MSG_LEN]; char host[DATA_MAX_NAME_LEN]; char plugin[DATA_MAX_NAME_LEN]; @@ -167,7 +168,7 @@ typedef int (*plugin_init_cb) (void); typedef int (*plugin_read_cb) (user_data_t *); typedef int (*plugin_write_cb) (const data_set_t *, const value_list_t *, user_data_t *); -typedef int (*plugin_flush_cb) (int timeout, const char *identifier, +typedef int (*plugin_flush_cb) (cdtime_t timeout, const char *identifier, user_data_t *); typedef void (*plugin_log_cb) (int severity, const char *message, user_data_t *); @@ -248,7 +249,7 @@ void plugin_shutdown_all (void); int plugin_write (const char *plugin, const data_set_t *ds, const value_list_t *vl); -int plugin_flush (const char *plugin, int timeout, const char *identifier); +int plugin_flush (const char *plugin, cdtime_t timeout, const char *identifier); /* * The `plugin_register_*' functions are used to make `config', `init', diff --git a/src/postgresql.c b/src/postgresql.c index 175cc095..a8812e21 100644 --- a/src/postgresql.c +++ b/src/postgresql.c @@ -117,7 +117,7 @@ typedef struct { udb_query_t **queries; size_t queries_num; - int interval; + cdtime_t interval; char *host; char *port; @@ -335,8 +335,9 @@ static PGresult *c_psql_exec_query_params (c_psql_database_t *db, params[i] = db->user; break; case C_PSQL_PARAM_INTERVAL: - ssnprintf (interval, sizeof (interval), "%i", - db->interval > 0 ? db->interval : interval_g); + ssnprintf (interval, sizeof (interval), "%.3f", + (db->interval > 0) + ? CDTIME_T_TO_DOUBLE (db->interval) : interval_g); params[i] = interval; break; default: @@ -535,28 +536,6 @@ static int config_set_s (char *name, char **var, const oconfig_item_t *ci) return 0; } /* config_set_s */ -static int config_set_i (char *name, int *var, - const oconfig_item_t *ci, int min) -{ - int value; - - if ((0 != ci->children_num) || (1 != ci->values_num) - || (OCONFIG_TYPE_NUMBER != ci->values[0].type)) { - log_err ("%s expects a single number argument.", name); - return 1; - } - - value = (int)ci->values[0].value.number; - - if (value < min) { - log_err ("%s expects a number greater or equal to %i.", name, min); - return 1; - } - - *var = value; - return 0; -} /* config_set_s */ - static int config_query_param_add (udb_query_t *q, oconfig_item_t *ci) { c_psql_user_data_t *data; @@ -618,7 +597,7 @@ static int c_psql_config_database (oconfig_item_t *ci) c_psql_database_t *db; char cb_name[DATA_MAX_NAME_LEN]; - struct timespec cb_interval; + struct timespec cb_interval = { 0, 0 }; user_data_t ud; int i; @@ -656,7 +635,7 @@ static int c_psql_config_database (oconfig_item_t *ci) udb_query_pick_from_list (c, queries, queries_num, &db->queries, &db->queries_num); else if (0 == strcasecmp (c->key, "Interval")) - config_set_i ("Interval", &db->interval, c, /* min = */ 1); + cf_util_get_cdtime (c, &db->interval); else log_warn ("Ignoring unknown config key \"%s\".", c->key); } @@ -701,12 +680,11 @@ static int c_psql_config_database (oconfig_item_t *ci) ssnprintf (cb_name, sizeof (cb_name), "postgresql-%s", db->database); - memset (&cb_interval, 0, sizeof (cb_interval)); - if (db->interval > 0) - cb_interval.tv_sec = (time_t)db->interval; + CDTIME_T_TO_TIMESPEC (db->interval, &cb_interval); plugin_register_complex_read ("postgresql", cb_name, c_psql_read, - /* interval = */ &cb_interval, &ud); + /* interval = */ (db->interval > 0) ? &cb_interval : NULL, + &ud); return 0; } /* c_psql_config_database */ diff --git a/src/powerdns.c b/src/powerdns.c index 29f6bca5..a1b23555 100644 --- a/src/powerdns.c +++ b/src/powerdns.c @@ -321,6 +321,9 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */ struct sockaddr_un sa_unix; + struct timeval stv_timeout; + cdtime_t cdt_timeout; + sd = socket (PF_UNIX, item->socktype, 0); if (sd < 0) { @@ -361,12 +364,13 @@ static int powerdns_get_data_dgram (list_item_t *item, /* {{{ */ break; } - struct timeval timeout; - timeout.tv_sec=2; - if (timeout.tv_sec < interval_g * 3 / 4) - timeout.tv_sec = interval_g * 3 / 4; - timeout.tv_usec=0; - status = setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof (timeout)); + cdt_timeout = interval_g * 3 / 4; + if (cdt_timeout < TIME_T_TO_CDTIME_T (2)) + cdt_timeout = TIME_T_TO_CDTIME_T (2); + + CDTIME_T_TO_TIMEVAL (cdt_timeout, &stv_timeout); + + status = setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, &stv_timeout, sizeof (stv_timeout)); if (status != 0) { FUNC_ERROR ("setsockopt"); diff --git a/src/python.c b/src/python.c index c056b5bf..eed0591d 100644 --- a/src/python.c +++ b/src/python.c @@ -435,8 +435,8 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li sstrncpy(v->data.type_instance, value_list->type_instance, sizeof(v->data.type_instance)); sstrncpy(v->data.plugin, value_list->plugin, sizeof(v->data.plugin)); sstrncpy(v->data.plugin_instance, value_list->plugin_instance, sizeof(v->data.plugin_instance)); - v->data.time = value_list->time; - v->interval = value_list->interval; + v->data.time = CDTIME_T_TO_DOUBLE(value_list->time); + v->interval = CDTIME_T_TO_DOUBLE(value_list->interval); Py_CLEAR(v->values); v->values = list; Py_CLEAR(v->meta); @@ -465,7 +465,7 @@ static int cpy_notification_callback(const notification_t *notification, user_da sstrncpy(n->data.type_instance, notification->type_instance, sizeof(n->data.type_instance)); sstrncpy(n->data.plugin, notification->plugin, sizeof(n->data.plugin)); sstrncpy(n->data.plugin_instance, notification->plugin_instance, sizeof(n->data.plugin_instance)); - n->data.time = notification->time; + n->data.time = CDTIME_T_TO_DOUBLE(notification->time); sstrncpy(n->message, notification->message, sizeof(n->message)); n->severity = notification->severity; ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data, (void *) 0); /* New reference. */ diff --git a/src/pyvalues.c b/src/pyvalues.c index cc7e296c..36a717e9 100644 --- a/src/pyvalues.c +++ b/src/pyvalues.c @@ -91,7 +91,7 @@ static PyObject *cpy_common_repr(PyObject *s) { if (self->time != 0) { CPY_STRCAT(&ret, l_time); - tmp = PyInt_FromLong(self->time); + tmp = PyFloat_FromDouble(self->time); CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp); CPY_STRCAT_AND_DEL(&ret, tmp); } @@ -351,14 +351,13 @@ static PyObject *Values_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) { Values *self = (Values *) s; - int interval = 0; - double time = 0; + double interval = 0, time = 0; PyObject *values = NULL, *meta = NULL, *tmp; const char *type = "", *plugin_instance = "", *type_instance = "", *plugin = "", *host = ""; static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance", "plugin", "host", "time", "interval", "meta", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdiO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist, NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance, NULL, &plugin, NULL, &host, &time, &interval, &meta)) return -1; @@ -485,8 +484,7 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) { value_t *value; value_list_t value_list = VALUE_LIST_INIT; PyObject *values = self->values, *meta = self->meta; - double time = self->data.time; - int interval = self->interval; + double time = self->data.time, interval = self->interval; const char *host = self->data.host; const char *plugin = self->data.plugin; const char *plugin_instance = self->data.plugin_instance; @@ -495,7 +493,7 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance", "plugin", "host", "time", "interval", "meta", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdiO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist, NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance, NULL, &plugin, NULL, &host, &time, &interval, &meta)) return NULL; @@ -559,8 +557,8 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) { value_list.values = value; value_list.meta = cpy_build_meta(meta); value_list.values_len = size; - value_list.time = time; - value_list.interval = interval; + value_list.time = DOUBLE_TO_CDTIME_T(time); + value_list.interval = DOUBLE_TO_CDTIME_T(interval); sstrncpy(value_list.host, host, sizeof(value_list.host)); sstrncpy(value_list.plugin, plugin, sizeof(value_list.plugin)); sstrncpy(value_list.plugin_instance, plugin_instance, sizeof(value_list.plugin_instance)); @@ -588,8 +586,7 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) { value_t *value; value_list_t value_list = VALUE_LIST_INIT; PyObject *values = self->values, *meta = self->meta; - double time = self->data.time; - int interval = self->interval; + double time = self->data.time, interval = self->interval; const char *host = self->data.host; const char *plugin = self->data.plugin; const char *plugin_instance = self->data.plugin_instance; @@ -599,7 +596,7 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"destination", "type", "values", "plugin_instance", "type_instance", "plugin", "host", "time", "interval", "meta", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdiO", kwlist, + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist, NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance, NULL, &plugin, NULL, &host, &time, &interval, &meta)) return NULL; @@ -658,8 +655,8 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) { } value_list.values = value; value_list.values_len = size; - value_list.time = time; - value_list.interval = interval; + value_list.time = DOUBLE_TO_CDTIME_T(time); + value_list.interval = DOUBLE_TO_CDTIME_T(interval); sstrncpy(value_list.host, host, sizeof(value_list.host)); sstrncpy(value_list.plugin, plugin, sizeof(value_list.plugin)); sstrncpy(value_list.plugin_instance, plugin_instance, sizeof(value_list.plugin_instance)); @@ -701,7 +698,7 @@ static PyObject *Values_repr(PyObject *s) { ret = cpy_common_repr(s); if (self->interval != 0) { CPY_STRCAT(&ret, l_interval); - tmp = PyInt_FromLong(self->interval); + tmp = PyFloat_FromDouble(self->interval); CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp); CPY_STRCAT_AND_DEL(&ret, tmp); } @@ -864,7 +861,7 @@ static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObj return NULL; } - notification.time = t; + notification.time = DOUBLE_TO_CDTIME_T(t); notification.severity = severity; sstrncpy(notification.message, message, sizeof(notification.message)); sstrncpy(notification.host, host, sizeof(notification.host)); @@ -873,8 +870,8 @@ static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObj sstrncpy(notification.type, type, sizeof(notification.type)); sstrncpy(notification.type_instance, type_instance, sizeof(notification.type_instance)); notification.meta = NULL; - if (notification.time < 1) - notification.time = time(0); + if (notification.time == 0) + notification.time = cdtime(); if (notification.host[0] == 0) sstrncpy(notification.host, hostname_g, sizeof(notification.host)); if (notification.plugin[0] == 0) diff --git a/src/rrdcached.c b/src/rrdcached.c index 34e860ba..fb7eb79e 100644 --- a/src/rrdcached.c +++ b/src/rrdcached.c @@ -64,12 +64,14 @@ static int value_list_to_string (char *buffer, int buffer_len, int offset; int status; int i; + time_t t; assert (0 == strcmp (ds->type, vl->type)); memset (buffer, '\0', buffer_len); - status = ssnprintf (buffer, buffer_len, "%u", (unsigned int) vl->time); + t = CDTIME_T_TO_TIME_T (vl->time); + status = ssnprintf (buffer, buffer_len, "%lu", (unsigned long) t); if ((status < 1) || (status >= buffer_len)) return (-1); offset = status; diff --git a/src/rrdtool.c b/src/rrdtool.c index cb8ad593..b366a9c6 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; @@ -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) { @@ -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); @@ -1134,12 +1167,12 @@ static int rrd_init (void) 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 +1187,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) diff --git a/src/snmp.c b/src/snmp.c index 1c2828c1..54bcf672 100644 --- a/src/snmp.c +++ b/src/snmp.c @@ -69,7 +69,7 @@ struct host_definition_s int version; void *sess_handle; c_complain_t complaint; - uint32_t interval; + cdtime_t interval; data_definition_t **data_list; int data_list_len; }; @@ -159,7 +159,6 @@ static void csnmp_host_definition_destroy (void *arg) /* {{{ */ * +-> csnmp_config_add_host_community * +-> csnmp_config_add_host_version * +-> csnmp_config_add_host_collect - * +-> csnmp_config_add_host_interval */ static void call_snmp_init_once (void) { @@ -543,22 +542,6 @@ static int csnmp_config_add_host_collect (host_definition_t *host, return (0); } /* int csnmp_config_add_host_collect */ -static int csnmp_config_add_host_interval (host_definition_t *hd, oconfig_item_t *ci) -{ - if ((ci->values_num != 1) - || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) - { - WARNING ("snmp plugin: The `Interval' config option needs exactly one number argument."); - return (-1); - } - - hd->interval = ci->values[0].value.number >= 0 - ? (uint32_t) ci->values[0].value.number - : 0; - - return (0); -} /* int csnmp_config_add_host_interval */ - static int csnmp_config_add_host (oconfig_item_t *ci) { host_definition_t *hd; @@ -607,7 +590,7 @@ static int csnmp_config_add_host (oconfig_item_t *ci) else if (strcasecmp ("Collect", option->key) == 0) csnmp_config_add_host_collect (hd, option); else if (strcasecmp ("Interval", option->key) == 0) - csnmp_config_add_host_interval (hd, option); + cf_util_get_cdtime (option, &hd->interval); else { WARNING ("snmp plugin: csnmp_config_add_host: Option `%s' not allowed here.", option->key); @@ -651,9 +634,7 @@ static int csnmp_config_add_host (oconfig_item_t *ci) cb_data.data = hd; cb_data.free_func = csnmp_host_definition_destroy; - memset (&cb_interval, 0, sizeof (cb_interval)); - if (hd->interval != 0) - cb_interval.tv_sec = (time_t) hd->interval; + CDTIME_T_TO_TIMESPEC (hd->interval, &cb_interval); status = plugin_register_complex_read (/* group = */ NULL, cb_name, csnmp_read_host, /* interval = */ &cb_interval, @@ -1529,8 +1510,8 @@ static int csnmp_read_value (host_definition_t *host, data_definition_t *data) static int csnmp_read_host (user_data_t *ud) { host_definition_t *host; - time_t time_start; - time_t time_end; + cdtime_t time_start; + cdtime_t time_end; int status; int success; int i; @@ -1540,9 +1521,7 @@ static int csnmp_read_host (user_data_t *ud) if (host->interval == 0) host->interval = interval_g; - time_start = time (NULL); - DEBUG ("snmp plugin: csnmp_read_host (%s) started at %u;", host->name, - (unsigned int) time_start); + time_start = cdtime (); if (host->sess_handle == NULL) csnmp_host_open_session (host); @@ -1564,14 +1543,14 @@ static int csnmp_read_host (user_data_t *ud) success++; } - time_end = time (NULL); - DEBUG ("snmp plugin: csnmp_read_host (%s) finished at %u;", host->name, - (unsigned int) time_end); - if ((uint32_t) (time_end - time_start) > host->interval) + time_end = cdtime (); + if ((time_end - time_start) > host->interval) { - WARNING ("snmp plugin: Host `%s' should be queried every %"PRIu32 - " seconds, but reading all values takes %u seconds.", - host->name, host->interval, (unsigned int) (time_end - time_start)); + WARNING ("snmp plugin: Host `%s' should be queried every %.3f " + "seconds, but reading all values takes %.3f seconds.", + host->name, + CDTIME_T_TO_DOUBLE (host->interval), + CDTIME_T_TO_DOUBLE (time_end - time_start)); } if (success == 0) diff --git a/src/target_notification.c b/src/target_notification.c index 96598afd..cb68048b 100644 --- a/src/target_notification.c +++ b/src/target_notification.c @@ -209,7 +209,7 @@ static int tn_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */ /* Initialize the structure. */ memset (&n, 0, sizeof (n)); n.severity = data->severity; - n.time = time (NULL); + n.time = cdtime (); sstrncpy (n.message, data->message, sizeof (n.message)); sstrncpy (n.host, vl->host, sizeof (n.host)); sstrncpy (n.plugin, vl->plugin, sizeof (n.plugin)); diff --git a/src/target_scale.c b/src/target_scale.c index 29fecdfd..af224f10 100644 --- a/src/target_scale.c +++ b/src/target_scale.c @@ -96,7 +96,7 @@ static int ts_invoke_counter (const data_set_t *ds, value_list_t *vl, /* {{{ */ { difference = curr_counter - prev_counter; } - rate = ((double) difference) / ((double) vl->interval); + rate = ((double) difference) / CDTIME_T_TO_DOUBLE (vl->interval); /* Modify the rate. */ if (!isnan (data->factor)) @@ -105,7 +105,7 @@ static int ts_invoke_counter (const data_set_t *ds, value_list_t *vl, /* {{{ */ rate += data->offset; /* Calculate the internal counter. */ - int_fraction += (rate * ((double) vl->interval)); + int_fraction += (rate * CDTIME_T_TO_DOUBLE (vl->interval)); difference = (uint64_t) int_fraction; int_fraction -= ((double) difference); int_counter += difference; @@ -199,7 +199,7 @@ static int ts_invoke_derive (const data_set_t *ds, value_list_t *vl, /* {{{ */ /* Calcualte the rate */ difference = curr_derive - prev_derive; - rate = ((double) difference) / ((double) vl->interval); + rate = ((double) difference) / CDTIME_T_TO_DOUBLE (vl->interval); /* Modify the rate. */ if (!isnan (data->factor)) @@ -208,7 +208,7 @@ static int ts_invoke_derive (const data_set_t *ds, value_list_t *vl, /* {{{ */ rate += data->offset; /* Calculate the internal derive. */ - int_fraction += (rate * ((double) vl->interval)); + int_fraction += (rate * CDTIME_T_TO_DOUBLE (vl->interval)); if (int_fraction < 0.0) /* handle negative integer rounding correctly */ difference = ((int64_t) int_fraction) - 1; else @@ -263,7 +263,7 @@ static int ts_invoke_absolute (const data_set_t *ds, value_list_t *vl, /* {{{ */ if (status != 0) int_fraction = 0.0; - rate = ((double) curr_absolute) / ((double) vl->interval); + rate = ((double) curr_absolute) / CDTIME_T_TO_DOUBLE (vl->interval); /* Modify the rate. */ if (!isnan (data->factor)) @@ -272,7 +272,7 @@ static int ts_invoke_absolute (const data_set_t *ds, value_list_t *vl, /* {{{ */ rate += data->offset; /* Calculate the new absolute. */ - int_fraction += (rate * ((double) vl->interval)); + int_fraction += (rate * CDTIME_T_TO_DOUBLE (vl->interval)); curr_absolute = (uint64_t) int_fraction; int_fraction -= ((double) curr_absolute); diff --git a/src/thermal.c b/src/thermal.c index b9d07bf5..0ad0d90a 100644 --- a/src/thermal.c +++ b/src/thermal.c @@ -29,13 +29,17 @@ # error "This module is for Linux only." #endif +static const char *config_keys[] = { + "Device", + "IgnoreSelected", + "ForceUseProcfs" +}; + const char *const dirname_sysfs = "/sys/class/thermal"; const char *const dirname_procfs = "/proc/acpi/thermal_zone"; -static char force_procfs = 0; +static _Bool force_procfs = 0; static ignorelist_t *device_list; -static value_list_t vl_temp_template = VALUE_LIST_STATIC; -static value_list_t vl_state_template = VALUE_LIST_STATIC; enum dev_type { TEMP = 0, @@ -45,16 +49,18 @@ enum dev_type { static void thermal_submit (const char *plugin_instance, enum dev_type dt, gauge_t value) { - value_list_t vl = (dt == TEMP) ? vl_temp_template : vl_state_template; - value_t vt; + value_list_t vl = VALUE_LIST_INIT; + value_t v; - vt.gauge = value; + v.gauge = value; + vl.values = &v; - vl.values = &vt; sstrncpy (vl.plugin, "thermal", sizeof(vl.plugin)); - sstrncpy (vl.plugin_instance, plugin_instance, - sizeof(vl.plugin_instance)); - sstrncpy (vl.type, (dt == TEMP) ? "temperature" : "gauge", + if (plugin_instance != NULL) + sstrncpy (vl.plugin_instance, plugin_instance, + sizeof (vl.plugin_instance)); + sstrncpy (vl.type, + (dt == TEMP) ? "temperature" : "gauge", sizeof (vl.type)); plugin_dispatch_values (&vl); @@ -66,7 +72,7 @@ static int thermal_sysfs_device_read (const char __attribute__((unused)) *dir, char filename[256]; char data[1024]; int len; - int ok = 0; + _Bool success = 0; if (device_list && ignorelist_match (device_list, name)) return -1; @@ -87,7 +93,7 @@ static int thermal_sysfs_device_read (const char __attribute__((unused)) *dir, if (endptr == data + len && errno == 0) { thermal_submit(name, TEMP, temp); - ++ok; + success = 1; } } @@ -107,11 +113,11 @@ static int thermal_sysfs_device_read (const char __attribute__((unused)) *dir, if (endptr == data + len && errno == 0) { thermal_submit(name, COOLING_DEV, state); - ++ok; + success = 1; } } - return ok ? 0 : -1; + return (success ? 0 : -1); } static int thermal_procfs_device_read (const char __attribute__((unused)) *dir, @@ -141,17 +147,17 @@ static int thermal_procfs_device_read (const char __attribute__((unused)) *dir, && (! strncmp(data, str_temp, sizeof(str_temp)-1))) { char *endptr = NULL; double temp; - double celsius, add; + double factor, add; if (data[--len] == 'C') { add = 0; - celsius = 1; + factor = 1.0; } else if (data[len] == 'F') { add = -32; - celsius = 5/9; + factor = 5.0/9.0; } else if (data[len] == 'K') { add = -273.15; - celsius = 1; + factor = 1.0; } else return -1; @@ -164,7 +170,7 @@ static int thermal_procfs_device_read (const char __attribute__((unused)) *dir, ++len; errno = 0; - temp = (strtod (data + len, &endptr) + add) * celsius; + temp = (strtod (data + len, &endptr) + add) * factor; if (endptr != data + len && errno == 0) { thermal_submit(name, TEMP, temp); @@ -175,12 +181,6 @@ static int thermal_procfs_device_read (const char __attribute__((unused)) *dir, return -1; } -static const char *config_keys[] = { - "Device", - "IgnoreSelected", - "ForceUseProcfs" -}; - static int thermal_config (const char *key, const char *value) { if (device_list == NULL) @@ -237,21 +237,6 @@ static int thermal_init (void) ret = plugin_register_read ("thermal", thermal_procfs_read); } - if (!ret) { - vl_temp_template.values_len = 1; - vl_temp_template.interval = interval_g; - sstrncpy (vl_temp_template.host, hostname_g, - sizeof(vl_temp_template.host)); - sstrncpy (vl_temp_template.plugin, "thermal", - sizeof(vl_temp_template.plugin)); - sstrncpy (vl_temp_template.type_instance, "temperature", - sizeof(vl_temp_template.type_instance)); - - vl_state_template = vl_temp_template; - sstrncpy (vl_state_template.type_instance, "cooling_state", - sizeof(vl_state_template.type_instance)); - } - return ret; } diff --git a/src/utils_cache.c b/src/utils_cache.c index aeb662d5..20b12375 100644 --- a/src/utils_cache.c +++ b/src/utils_cache.c @@ -38,13 +38,13 @@ typedef struct cache_entry_s value_t *values_raw; /* Time contained in the package * (for calculating rates) */ - time_t last_time; + cdtime_t last_time; /* Time according to the local clock * (for purging old entries) */ - time_t last_update; + cdtime_t last_update; /* Interval in which the data is collected * (for purding old entries) */ - int interval; + cdtime_t interval; int state; int hits; @@ -164,7 +164,7 @@ static int uc_send_notification (const char *name) * acquiring the lock takes and we will use this time later to decide * whether or not the state is OKAY. */ - n.time = time (NULL); + n.time = cdtime (); status = c_avl_get (cache_tree, name, (void *) &ce); if (status != 0) @@ -184,8 +184,8 @@ static int uc_send_notification (const char *name) } ssnprintf (n.message, sizeof (n.message), - "%s has not been updated for %i seconds.", name, - (int) (n.time - ce->last_update)); + "%s has not been updated for %.3f seconds.", name, + CDTIME_T_TO_DOUBLE (n.time - ce->last_update)); pthread_mutex_unlock (&cache_lock); @@ -258,7 +258,7 @@ static int uc_insert (const data_set_t *ds, const value_list_t *vl, ce->values_gauge[i] = NAN; if (vl->interval > 0) ce->values_gauge[i] = ((double) vl->values[i].absolute) - / ((double) vl->interval); + / CDTIME_T_TO_DOUBLE (vl->interval); ce->values_raw[i].absolute = vl->values[i].absolute; break; @@ -274,7 +274,7 @@ static int uc_insert (const data_set_t *ds, const value_list_t *vl, uc_check_range (ds, ce); ce->last_time = vl->time; - ce->last_update = time (NULL); + ce->last_update = cdtime (); ce->interval = vl->interval; ce->state = STATE_OKAY; @@ -300,7 +300,7 @@ int uc_init (void) int uc_check_timeout (void) { - time_t now; + cdtime_t now; cache_entry_t *ce; char **keys = NULL; @@ -312,14 +312,14 @@ int uc_check_timeout (void) pthread_mutex_lock (&cache_lock); - now = time (NULL); + now = cdtime (); /* Build a list of entries to be flushed */ iter = c_avl_get_iterator (cache_tree); while (c_avl_iterator_next (iter, (void *) &key, (void *) &ce) == 0) { /* If entry has not been updated, add to `keys' array */ - if ((now - ce->last_update) >= (timeout_g * ce->interval)) + if ((now - ce->last_update) >= (ce->interval * timeout_g)) { char **tmp; @@ -448,7 +448,7 @@ int uc_update (const data_set_t *ds, const value_list_t *vl) char name[6 * DATA_MAX_NAME_LEN]; cache_entry_t *ce = NULL; int send_okay_notification = 0; - time_t update_delay = 0; + cdtime_t update_delay = 0; notification_t n; int status; int i; @@ -475,9 +475,11 @@ int uc_update (const data_set_t *ds, const value_list_t *vl) if (ce->last_time >= vl->time) { pthread_mutex_unlock (&cache_lock); - NOTICE ("uc_update: Value too old: name = %s; value time = %u; " - "last cache update = %u;", - name, (unsigned int) vl->time, (unsigned int) ce->last_time); + NOTICE ("uc_update: Value too old: name = %s; value time = %.3f; " + "last cache update = %.3f;", + name, + CDTIME_T_TO_DOUBLE (vl->time), + CDTIME_T_TO_DOUBLE (ce->last_time)); return (-1); } @@ -487,7 +489,7 @@ int uc_update (const data_set_t *ds, const value_list_t *vl) { send_okay_notification = 1; ce->state = STATE_OKAY; - update_delay = time (NULL) - ce->last_update; + update_delay = cdtime () - ce->last_update; } for (i = 0; i < ds->ds_num; i++) @@ -514,7 +516,7 @@ int uc_update (const data_set_t *ds, const value_list_t *vl) } ce->values_gauge[i] = ((double) diff) - / ((double) (vl->time - ce->last_time)); + / (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time)); ce->values_raw[i].counter = vl->values[i].counter; } break; @@ -531,14 +533,14 @@ int uc_update (const data_set_t *ds, const value_list_t *vl) diff = vl->values[i].derive - ce->values_raw[i].derive; ce->values_gauge[i] = ((double) diff) - / ((double) (vl->time - ce->last_time)); + / (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time)); ce->values_raw[i].derive = vl->values[i].derive; } break; case DS_TYPE_ABSOLUTE: ce->values_gauge[i] = ((double) vl->values[i].absolute) - / ((double) (vl->time - ce->last_time)); + / (CDTIME_T_TO_DOUBLE (vl->time - ce->last_time)); ce->values_raw[i].absolute = vl->values[i].absolute; break; @@ -571,7 +573,7 @@ int uc_update (const data_set_t *ds, const value_list_t *vl) uc_check_range (ds, ce); ce->last_time = vl->time; - ce->last_update = time (NULL); + ce->last_update = cdtime (); ce->interval = vl->interval; pthread_mutex_unlock (&cache_lock); @@ -682,14 +684,14 @@ gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl) return (ret); } /* gauge_t *uc_get_rate */ -int uc_get_names (char ***ret_names, time_t **ret_times, size_t *ret_number) +int uc_get_names (char ***ret_names, cdtime_t **ret_times, size_t *ret_number) { c_avl_iterator_t *iter; char *key; cache_entry_t *value; char **names = NULL; - time_t *times = NULL; + cdtime_t *times = NULL; size_t number = 0; int status = 0; @@ -710,9 +712,9 @@ int uc_get_names (char ***ret_names, time_t **ret_times, size_t *ret_number) if (ret_times != NULL) { - time_t *tmp_times; + cdtime_t *tmp_times; - tmp_times = (time_t *) realloc (times, sizeof (time_t) * (number + 1)); + tmp_times = (cdtime_t *) realloc (times, sizeof (cdtime_t) * (number + 1)); if (tmp_times == NULL) { status = -1; diff --git a/src/utils_cache.h b/src/utils_cache.h index f8059eca..87f93c0e 100644 --- a/src/utils_cache.h +++ b/src/utils_cache.h @@ -35,7 +35,7 @@ int uc_update (const data_set_t *ds, const value_list_t *vl); int uc_get_rate_by_name (const char *name, gauge_t **ret_values, size_t *ret_values_num); gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl); -int uc_get_names (char ***ret_names, time_t **ret_times, size_t *ret_number); +int uc_get_names (char ***ret_names, cdtime_t **ret_times, size_t *ret_number); int uc_get_state (const data_set_t *ds, const value_list_t *vl); int uc_set_state (const data_set_t *ds, const value_list_t *vl, int state); diff --git a/src/utils_cmd_flush.c b/src/utils_cmd_flush.c index 0e7b350f..3584f3b7 100644 --- a/src/utils_cmd_flush.c +++ b/src/utils_cmd_flush.c @@ -54,7 +54,7 @@ int handle_flush (FILE *fh, char *buffer) int success = 0; int error = 0; - int timeout = -1; + double timeout = 0.0; char **plugins = NULL; int plugins_num = 0; char **identifiers = NULL; @@ -106,9 +106,9 @@ int handle_flush (FILE *fh, char *buffer) errno = 0; endptr = NULL; - timeout = strtol (opt_value, &endptr, 0); + timeout = strtod (opt_value, &endptr); - if ((endptr == opt_value) || (errno != 0)) + if ((endptr == opt_value) || (errno != 0) || (!isfinite (timeout))) { print_to_socket (fh, "-1 Invalid value for option `timeout': " "%s\n", opt_value); @@ -116,8 +116,10 @@ int handle_flush (FILE *fh, char *buffer) sfree (identifiers); return (-1); } - else if (timeout <= 0) - timeout = -1; + else if (timeout < 0.0) + { + timeout = 0.0; + } } else { @@ -149,7 +151,9 @@ int handle_flush (FILE *fh, char *buffer) int status; identifier = identifiers[j]; - status = plugin_flush (plugin, timeout, identifier); + status = plugin_flush (plugin, + DOUBLE_TO_CDTIME_T (timeout), + identifier); if (status == 0) success++; else diff --git a/src/utils_cmd_listval.c b/src/utils_cmd_listval.c index 4ca9646d..ef66af56 100644 --- a/src/utils_cmd_listval.c +++ b/src/utils_cmd_listval.c @@ -50,7 +50,7 @@ int handle_listval (FILE *fh, char *buffer) { char *command; char **names = NULL; - time_t *times = NULL; + cdtime_t *times = NULL; size_t number = 0; size_t i; int status; @@ -90,7 +90,8 @@ int handle_listval (FILE *fh, char *buffer) print_to_socket (fh, "%i Value%s found\n", (int) number, (number == 1) ? "" : "s"); for (i = 0; i < number; i++) - print_to_socket (fh, "%u %s\n", (unsigned int) times[i], names[i]); + print_to_socket (fh, "%.3f %s\n", CDTIME_T_TO_DOUBLE (times[i]), + names[i]); free_everything_and_return (0); } /* int handle_listval */ diff --git a/src/utils_cmd_putval.c b/src/utils_cmd_putval.c index 15cd939b..dd43337e 100644 --- a/src/utils_cmd_putval.c +++ b/src/utils_cmd_putval.c @@ -56,16 +56,16 @@ static int set_option (value_list_t *vl, const char *key, const char *value) if (strcasecmp ("interval", key) == 0) { - int tmp; + double tmp; char *endptr; endptr = NULL; errno = 0; - tmp = strtol (value, &endptr, 0); + tmp = strtod (value, &endptr); if ((errno == 0) && (endptr != NULL) - && (endptr != value) && (tmp > 0)) - vl->interval = tmp; + && (endptr != value) && (tmp > 0.0)) + vl->interval = DOUBLE_TO_CDTIME_T (tmp); } else return (1); @@ -246,9 +246,11 @@ int create_putval (char *ret, size_t ret_len, /* {{{ */ escape_string (buffer_values, sizeof (buffer_values)); ssnprintf (ret, ret_len, - "PUTVAL %s interval=%i %s", + "PUTVAL %s interval=%.3f %s", buffer_ident, - (vl->interval > 0) ? vl->interval : interval_g, + (vl->interval > 0) + ? CDTIME_T_TO_DOUBLE (vl->interval) + : CDTIME_T_TO_DOUBLE (interval_g), buffer_values); return (0); diff --git a/src/utils_db_query.c b/src/utils_db_query.c index 78c8052e..dcac8076 100644 --- a/src/utils_db_query.c +++ b/src/utils_db_query.c @@ -73,7 +73,7 @@ struct udb_query_preparation_area_s /* {{{ */ char *plugin; char *db_name; - int interval; + cdtime_t interval; udb_result_preparation_area_t *result_prep_areas; }; /* }}} */ @@ -839,7 +839,7 @@ void udb_query_finish_result (const udb_query_t const *q, /* {{{ */ sfree (prep_area->plugin); sfree (prep_area->db_name); - prep_area->interval = -1; + prep_area->interval = 0; for (r = q->results, r_area = prep_area->result_prep_areas; r != NULL; r = r->next, r_area = r_area->next) @@ -907,7 +907,7 @@ int udb_query_handle_result (const udb_query_t const *q, /* {{{ */ int udb_query_prepare_result (const udb_query_t const *q, /* {{{ */ udb_query_preparation_area_t *prep_area, const char *host, const char *plugin, const char *db_name, - char **column_names, size_t column_num, int interval) + char **column_names, size_t column_num, cdtime_t interval) { udb_result_preparation_area_t *r_area; udb_result_t *r; diff --git a/src/utils_db_query.h b/src/utils_db_query.h index 846f81c2..727be036 100644 --- a/src/utils_db_query.h +++ b/src/utils_db_query.h @@ -68,7 +68,7 @@ int udb_query_check_version (udb_query_t *q, unsigned int version); int udb_query_prepare_result (const udb_query_t const *q, udb_query_preparation_area_t *prep_area, const char *host, const char *plugin, const char *db_name, - char **column_names, size_t column_num, int interval); + char **column_names, size_t column_num, cdtime_t interval); int udb_query_handle_result (const udb_query_t const *q, udb_query_preparation_area_t *prep_area, char **column_values); void udb_query_finish_result (const udb_query_t const *q, diff --git a/src/utils_format_json.c b/src/utils_format_json.c index ac88c0fa..65c886b6 100644 --- a/src/utils_format_json.c +++ b/src/utils_format_json.c @@ -265,7 +265,7 @@ static int value_list_to_json (char *buffer, size_t buffer_size, /* {{{ */ BUFFER_ADD (",\"dsnames\":%s", temp); BUFFER_ADD (",\"time\":%lu", (unsigned long) vl->time); - BUFFER_ADD (",\"interval\":%i", vl->interval); + BUFFER_ADD (",\"interval\":%.3f", CDTIME_T_TO_DOUBLE (vl->interval)); #define BUFFER_ADD_KEYVAL(key, value) do { \ status = escape_string (temp, sizeof (temp), (value)); \ diff --git a/src/utils_rrdcreate.c b/src/utils_rrdcreate.c index 4ecec59d..7a389f26 100644 --- a/src/utils_rrdcreate.c +++ b/src/utils_rrdcreate.c @@ -103,7 +103,10 @@ static int rra_get (char ***ret, const value_list_t *vl, /* {{{ */ return (-1); } - ss = (cfg->stepsize > 0) ? cfg->stepsize : vl->interval; + if (cfg->stepsize > 0) + ss = cfg->stepsize; + else + ss = (int) CDTIME_T_TO_TIME_T (vl->interval); if (ss <= 0) { *ret = NULL; @@ -241,7 +244,9 @@ static int ds_get (char ***ret, /* {{{ */ status = ssnprintf (buffer, sizeof (buffer), "DS:%s:%s:%i:%s:%s", d->name, type, - (cfg->heartbeat > 0) ? cfg->heartbeat : (2 * vl->interval), + (cfg->heartbeat > 0) + ? cfg->heartbeat + : (int) CDTIME_T_TO_TIME_T (2 * vl->interval), min, max); if ((status < 1) || ((size_t) status >= sizeof (buffer))) break; @@ -323,7 +328,7 @@ static int srrd_create (const char *filename, /* {{{ */ last_up = time (NULL) - 10; ssnprintf (pdp_step_str, sizeof (pdp_step_str), "%lu", pdp_step); - ssnprintf (last_up_str, sizeof (last_up_str), "%u", (unsigned int) last_up); + ssnprintf (last_up_str, sizeof (last_up_str), "%lu", (unsigned long) last_up); new_argv[0] = "create"; new_argv[1] = (void *) filename; @@ -368,6 +373,8 @@ int cu_rrd_create_file (const char *filename, /* {{{ */ char **ds_def; int ds_num; int status = 0; + time_t last_up; + int stepsize; if (check_create_dir (filename)) return (-1); @@ -398,10 +405,19 @@ int cu_rrd_create_file (const char *filename, /* {{{ */ memcpy (argv + ds_num, rra_def, rra_num * sizeof (char *)); argv[ds_num + rra_num] = NULL; + if (vl->time == 0) + last_up = time (NULL) - 10; + else + last_up = CDTIME_T_TO_TIME_T (vl->time) - 10; + + if (cfg->stepsize > 0) + stepsize = cfg->stepsize; + else + stepsize = (int) CDTIME_T_TO_TIME_T (vl->interval); + assert (vl->time > 10); status = srrd_create (filename, - (cfg->stepsize > 0) ? cfg->stepsize : vl->interval, - vl->time - 10, + stepsize, last_up, argc, (const char **) argv); free (argv); diff --git a/src/utils_time.c b/src/utils_time.c new file mode 100644 index 00000000..420b425c --- /dev/null +++ b/src/utils_time.c @@ -0,0 +1,44 @@ +/** + * collectd - src/utils_time.h + * Copyright (C) 2010 Florian octo Forster + * + * 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 + * Free Software Foundation; only version 2 of the License is applicable. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian octo Forster + **/ + +#include "collectd.h" +#include "utils_time.h" +#include "plugin.h" +#include "common.h" + +cdtime_t cdtime (void) /* {{{ */ +{ + int status; + struct timespec ts = { 0, 0 }; + + status = clock_gettime (CLOCK_REALTIME, &ts); + if (status != 0) + { + char errbuf[1024]; + ERROR ("cdtime: clock_gettime failed: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (0); + } + + return (TIMESPEC_TO_CDTIME_T (&ts)); +} /* }}} cdtime_t cdtime */ + +/* vim: set sw=2 sts=2 et fdm=marker : */ diff --git a/src/utils_time.h b/src/utils_time.h new file mode 100644 index 00000000..da73492c --- /dev/null +++ b/src/utils_time.h @@ -0,0 +1,70 @@ +/** + * collectd - src/utils_time.h + * Copyright (C) 2010 Florian octo Forster + * + * 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 + * Free Software Foundation; only version 2 of the License is applicable. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian octo Forster + **/ + +#ifndef UTILS_TIME_H +#define UTILS_TIME_H 1 + +#include "collectd.h" + +/* + * "cdtime_t" is a 64bit unsigned integer. The time is stored at a 2^-30 second + * resolution, i.e. the most significant 34 bit are used to store the time in + * seconds, the least significant bits store the sub-second part in something + * very close to nanoseconds. *The* big advantage of storing time in this + * manner is that comparing times and calculating differences is as simple as + * it is with "time_t", i.e. a simple integer comparison / subtraction works. + */ +/* + * cdtime_t is defined in "collectd.h" */ +/* typedef uint64_t cdtime_t; */ + +/* 2^30 = 1073741824 */ +#define TIME_T_TO_CDTIME_T(t) (((cdtime_t) (t)) * 1073741824) +#define CDTIME_T_TO_TIME_T(t) ((time_t) ((t) / 1073741824)) + +#define CDTIME_T_TO_DOUBLE(t) (((double) (t)) / 1073741824.0) +#define DOUBLE_TO_CDTIME_T(d) ((cdtime_t) ((d) * 1073741824.0)) + +#define MS_TO_CDTIME_T(ms) ((cdtime_t) (((double) (ms)) * 1073741.824)) +#define CDTIME_T_TO_MS(t) ((long) (((double) (t)) / 1073741.824)) +#define US_TO_CDTIME_T(us) ((cdtime_t) (((double) (us)) * 1073.741824)) +#define CDTIME_T_TO_US(t) ((suseconds_t) (((double) (t)) / 1073.741824)) +#define NS_TO_CDTIME_T(ns) ((cdtime_t) (((double) (ns)) * 1.073741824)) +#define CDTIME_T_TO_NS(t) ((long) (((double) (t)) / 1.073741824)) + +#define CDTIME_T_TO_TIMEVAL(cdt,tvp) do { \ + (tvp)->tv_sec = CDTIME_T_TO_TIME_T (cdt); \ + (tvp)->tv_usec = CDTIME_T_TO_US ((cdt) % 1073741824); \ +} while (0) +#define TIMEVAL_TO_CDTIME_T(tv) (TIME_T_TO_CDTIME_T ((tv).tv_sec) \ + + US_TO_CDTIME_T ((tv).tv_usec)) + +#define CDTIME_T_TO_TIMESPEC(cdt,tsp) do { \ + (tsp)->tv_sec = CDTIME_T_TO_TIME_T (cdt); \ + (tsp)->tv_nsec = CDTIME_T_TO_NS ((cdt) % 1073741824); \ +} while (0) +#define TIMESPEC_TO_CDTIME_T(ts) (TIME_T_TO_CDTIME_T ((ts)->tv_sec) \ + + NS_TO_CDTIME_T ((ts)->tv_nsec)) + +cdtime_t cdtime (void); + +#endif /* UTILS_TIME_H */ +/* vim: set sw=2 sts=2 et : */ diff --git a/src/write_http.c b/src/write_http.c index bac8e986..1a0e4ef0 100644 --- a/src/write_http.c +++ b/src/write_http.c @@ -61,7 +61,7 @@ struct wh_callback_s char send_buffer[4096]; size_t send_buffer_free; size_t send_buffer_fill; - time_t send_buffer_init_time; + cdtime_t send_buffer_init_time; pthread_mutex_t send_lock; }; @@ -72,7 +72,7 @@ static void wh_reset_buffer (wh_callback_t *cb) /* {{{ */ memset (cb->send_buffer, 0, sizeof (cb->send_buffer)); cb->send_buffer_free = sizeof (cb->send_buffer); cb->send_buffer_fill = 0; - cb->send_buffer_init_time = time (NULL); + cb->send_buffer_init_time = cdtime (); if (cb->format == WH_FORMAT_JSON) { @@ -157,19 +157,21 @@ static int wh_callback_init (wh_callback_t *cb) /* {{{ */ return (0); } /* }}} int wh_callback_init */ -static int wh_flush_nolock (int timeout, wh_callback_t *cb) /* {{{ */ +static int wh_flush_nolock (cdtime_t timeout, wh_callback_t *cb) /* {{{ */ { int status; - DEBUG ("write_http plugin: wh_flush_nolock: timeout = %i; " + DEBUG ("write_http plugin: wh_flush_nolock: timeout = %.3f; " "send_buffer_fill = %zu;", - timeout, cb->send_buffer_fill); + CDTIME_T_TO_DOUBLE (timeout), + cb->send_buffer_fill); + /* timeout == 0 => flush unconditionally */ if (timeout > 0) { - time_t now; + cdtime_t now; - now = time (NULL); + now = cdtime (); if ((cb->send_buffer_init_time + timeout) > now) return (0); } @@ -178,7 +180,7 @@ static int wh_flush_nolock (int timeout, wh_callback_t *cb) /* {{{ */ { if (cb->send_buffer_fill <= 0) { - cb->send_buffer_init_time = time (NULL); + cb->send_buffer_init_time = cdtime (); return (0); } @@ -189,7 +191,7 @@ static int wh_flush_nolock (int timeout, wh_callback_t *cb) /* {{{ */ { if (cb->send_buffer_fill <= 2) { - cb->send_buffer_init_time = time (NULL); + cb->send_buffer_init_time = cdtime (); return (0); } @@ -218,7 +220,7 @@ static int wh_flush_nolock (int timeout, wh_callback_t *cb) /* {{{ */ return (status); } /* }}} wh_flush_nolock */ -static int wh_flush (int timeout, /* {{{ */ +static int wh_flush (cdtime_t timeout, /* {{{ */ const char *identifier __attribute__((unused)), user_data_t *user_data) { @@ -258,7 +260,7 @@ static void wh_callback_free (void *data) /* {{{ */ cb = data; - wh_flush_nolock (/* timeout = */ -1, cb); + wh_flush_nolock (/* timeout = */ 0, cb); curl_easy_cleanup (cb->curl); sfree (cb->location); @@ -304,8 +306,10 @@ static int wh_write_command (const data_set_t *ds, const value_list_t *vl, /* {{ } command_len = (size_t) ssnprintf (command, sizeof (command), - "PUTVAL %s interval=%i %s\r\n", - key, vl->interval, values); + "PUTVAL %s interval=%.3f %s\r\n", + key, + CDTIME_T_TO_DOUBLE (vl->interval), + values); if (command_len >= sizeof (command)) { ERROR ("write_http plugin: Command buffer too small: " "Need %zu bytes.", command_len + 1); @@ -327,7 +331,7 @@ static int wh_write_command (const data_set_t *ds, const value_list_t *vl, /* {{ if (command_len >= cb->send_buffer_free) { - status = wh_flush_nolock (/* timeout = */ -1, cb); + status = wh_flush_nolock (/* timeout = */ 0, cb); if (status != 0) { pthread_mutex_unlock (&cb->send_lock); @@ -379,7 +383,7 @@ static int wh_write_json (const data_set_t *ds, const value_list_t *vl, /* {{{ * ds, vl, cb->store_rates); if (status == (-ENOMEM)) { - status = wh_flush_nolock (/* timeout = */ -1, cb); + status = wh_flush_nolock (/* timeout = */ 0, cb); if (status != 0) { wh_reset_buffer (cb);