*/
public interface CollectdFlushInterface
{
- public int flush (int timeout, String identifier);
+ public int flush (Number timeout, String identifier);
}
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,
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"])
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)
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) {
# endif
#endif
+/* Type for time as used by "utils_time.h" */
+typedef uint64_t cdtime_t;
+
extern char hostname_g[];
extern int interval_g;
extern int timeout_g;
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++)
{
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
{
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 */
+
**/
#include "collectd.h"
+#include "utils_time.h"
#include "liboconfig/oconfig.h"
/*
* 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) */
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;
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));
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));
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));
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));
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));
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));
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);
#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)
{
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:
} /* }}} 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;
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)
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; \
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)
{
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) {
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);
}
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. */
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;
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)
{
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;
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);
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,
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 */
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;
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 "
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)
{
if (db->slave_notif)
{
- notification_t n = { 0, time (NULL), "", "",
+ notification_t n = { 0, cdtime (), "", "",
"mysql", "", "time_offset", "", NULL };
char *io, *sql;
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;
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;
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;
struct data_volume_perf_s {
char *name;
uint32_t flags;
- time_t timestamp;
+ cdtime_t timestamp;
uint64_t read_bytes;
uint64_t write_bytes;
int port;
char *username;
char *password;
- int interval;
+ cdtime_t interval;
na_server_t *srv;
cfg_wafl_t *cfg_wafl;
const char *plugin_inst,
const char *type, const char *type_inst,
value_t *values, int values_len,
- time_t timestamp)
+ cdtime_t timestamp)
{
value_list_t vl = VALUE_LIST_INIT;
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)
+ cdtime_t timestamp)
{
value_t values[2];
} /* }}} 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)
+ const char *type, const char *type_inst, counter_t counter, cdtime_t timestamp)
{
value_t v;
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)
+ cdtime_t timestamp)
{
value_t values[2];
} /* }}} 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)
+ const char *type, const char *type_inst, double d, cdtime_t timestamp)
{
value_t v;
uint64_t new_misses,
uint64_t old_hits,
uint64_t old_misses,
- time_t timestamp)
+ cdtime_t timestamp)
{
value_t v;
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
*
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)
{
na_elem_t *data;
int status;
- time_t now;
+ cdtime_t now;
if (host == NULL)
return (EINVAL);
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);
static int cna_handle_disk_data (const char *hostname, /* {{{ */
cfg_disk_t *cfg_disk, na_elem_t *data)
{
- time_t timestamp;
+ cdtime_t timestamp;
na_elem_t *instances;
na_elem_t *instance;
na_elem_iter_t instance_iter;
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)
{
na_elem_t *data;
int status;
- time_t now;
+ cdtime_t now;
if (host == NULL)
return (EINVAL);
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);
static int cna_handle_volume_perf_data (const char *hostname, /* {{{ */
cfg_volume_perf_t *cvp, na_elem_t *data)
{
- 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)
{
na_elem_t *data;
int status;
- time_t now;
+ cdtime_t now;
if (host == NULL)
return (EINVAL);
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);
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));
{
na_elem_t *data;
int status;
- time_t now;
+ cdtime_t now;
if (host == NULL)
return (EINVAL);
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);
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)
{
na_elem_t *data;
int status;
- time_t now;
+ cdtime_t now;
if (host == NULL)
return (EINVAL);
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);
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;
} 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")) {
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;
&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_INTERVAL)
if (vl_def->time != vl->time)
{
+ time_t tmp = CDTIME_T_TO_TIME_T (vl->time);
if (write_part_number (&buffer, &buffer_size, TYPE_TIME,
- (uint64_t) vl->time))
+ (uint64_t) tmp))
return (-1);
vl_def->time = vl->time;
}
char *buffer_ptr = buffer;
int buffer_free = sizeof (buffer);
int status;
+ time_t tmp;
memset (buffer, '\0', sizeof (buffer));
+ tmp = CDTIME_T_TO_TIME_T (n->time);
status = write_part_number (&buffer_ptr, &buffer_free, TYPE_TIME,
- (uint64_t) n->time);
+ (uint64_t) tmp);
if (status != 0)
return (-1);
* 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);
{
smtp_recipient_t recipient;
+ time_t tt;
struct tm timestamp_tm;
char timestamp_str[64];
(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';
}
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);
}
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);
}
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);
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));
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;
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))
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)));
}
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;
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;
}
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 = %i; "
"host = %s; "
"plugin = %s; plugin_instance = %s; "
"type = %s; type_instance = %s;",
- (unsigned int) vl->time, vl->interval,
+ CDTIME_T_TO_DOUBLE (vl->time), vl->interval,
vl->host,
vl->plugin, vl->plugin_instance,
vl->type, vl->type_instance);
/* 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)
#include "collectd.h"
#include "configfile.h"
#include "meta_data.h"
+#include "utils_time.h"
#define PLUGIN_FLAGS_GLOBAL 0x0001
{
value_t *values;
int values_len;
- time_t time;
+ cdtime_t time;
int interval;
char host[DATA_MAX_NAME_LEN];
char plugin[DATA_MAX_NAME_LEN];
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];
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 *);
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',
struct sockaddr_un sa_unix;
+ struct timeval stv_timeout;
+ cdtime_t cdt_timeout;
+
sd = socket (PF_UNIX, item->socktype, 0);
if (sd < 0)
{
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));
+ /* TODO: Remove the macro once interval_g is of type cdtime_t. */
+ cdt_timeout = TIME_T_TO_CDTIME_T (interval_g);
+ cdt_timeout = cdt_timeout * 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");
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;
*/
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,
/* 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;
{
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;
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;
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);
{
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)
{
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];
return (0);
}
- now = time (NULL);
+ now = cdtime ();
if (datadir == NULL)
snprintf (key, sizeof (key), "%s.rrd",
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);
+
+ /* 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;
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;
}
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);
}
}
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! */
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
{
}
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);
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);
{
if (strcasecmp ("CacheTimeout", key) == 0)
{
- int tmp = atoi (value);
+ double tmp = atof (value);
if (tmp < 0)
{
fprintf (stderr, "rrdtool: `CacheTimeout' must "
"be greater than 0.\n");
return (1);
}
- cache_timeout = tmp;
+ cache_timeout = DOUBLE_TO_CDTIME_T (tmp);
}
else if (strcasecmp ("CacheFlush", key) == 0)
{
}
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");
}
else
{
- random_timeout = tmp;
+ random_timeout = DOUBLE_TO_CDTIME_T (tmp);
}
}
else
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);
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)
int version;
void *sess_handle;
c_complain_t complaint;
- uint32_t interval;
+ cdtime_t interval;
data_definition_t **data_list;
int data_list_len;
};
* +-> 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)
{
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;
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);
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,
sstrncpy (vl.host, host->name, sizeof (vl.host));
sstrncpy (vl.plugin, "snmp", sizeof (vl.plugin));
- vl.interval = host->interval;
+ vl.interval = (int) CDTIME_T_TO_TIME_T (host->interval);
subid = 0;
have_more = 1;
sstrncpy (vl.type, data->type, sizeof (vl.type));
sstrncpy (vl.type_instance, data->instance.string, sizeof (vl.type_instance));
- vl.interval = host->interval;
+ vl.interval = (int) CDTIME_T_TO_TIME_T (host->interval);
req = snmp_pdu_create (SNMP_MSG_GET);
if (req == NULL)
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;
host = ud->data;
+ /* FIXME: Convert "interval_g" to cdtime_t, too. */
if (host->interval == 0)
- host->interval = interval_g;
+ host->interval = TIME_T_TO_CDTIME_T (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);
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)
/* 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));
# 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,
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);
char filename[256];
char data[1024];
int len;
- int ok = 0;
+ _Bool success = 0;
if (device_list && ignorelist_match (device_list, name))
return -1;
if (endptr == data + len && errno == 0) {
thermal_submit(name, TEMP, temp);
- ++ok;
+ success = 1;
}
}
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,
&& (! 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;
++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);
return -1;
}
-static const char *config_keys[] = {
- "Device",
- "IgnoreSelected",
- "ForceUseProcfs"
-};
-
static int thermal_config (const char *key, const char *value)
{
if (device_list == NULL)
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;
}
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;
* 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)
}
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);
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;
int uc_check_timeout (void)
{
- time_t now;
+ cdtime_t now;
cache_entry_t *ce;
char **keys = NULL;
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))
+ /* FIXME: Remove macro once "ce->interval" is of type cdtime_t. */
+ if ((now - ce->last_update) >= TIME_T_TO_CDTIME_T (timeout_g * ce->interval))
{
char **tmp;
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;
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);
}
{
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++)
}
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;
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;
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);
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;
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;
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);
{
char *command;
char **names = NULL;
- time_t *times = NULL;
+ cdtime_t *times = NULL;
size_t number = 0;
size_t i;
int status;
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 */
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;
char **ds_def;
int ds_num;
int status = 0;
+ time_t last_up;
if (check_create_dir (filename))
return (-1);
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;
+
assert (vl->time > 10);
status = srrd_create (filename,
(cfg->stepsize > 0) ? cfg->stepsize : vl->interval,
- vl->time - 10,
+ last_up,
argc, (const char **) argv);
free (argv);
--- /dev/null
+/**
+ * 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 <ff at octo.it>
+ **/
+
+#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 : */
--- /dev/null
+/**
+ * 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 <ff at octo.it>
+ **/
+
+#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 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 : */
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;
};
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)
{
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);
}
{
if (cb->send_buffer_fill <= 0)
{
- cb->send_buffer_init_time = time (NULL);
+ cb->send_buffer_init_time = cdtime ();
return (0);
}
{
if (cb->send_buffer_fill <= 2)
{
- cb->send_buffer_init_time = time (NULL);
+ cb->send_buffer_init_time = cdtime ();
return (0);
}
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)
{
cb = data;
- wh_flush_nolock (/* timeout = */ -1, cb);
+ wh_flush_nolock (/* timeout = */ 0, cb);
curl_easy_cleanup (cb->curl);
sfree (cb->location);
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);
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);