X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fcommon.c;h=1c80e8f1b8cd6d2f85dfebd482e30caf88cdf6d0;hb=8eb9e6285f394569d7fe6ad43a0f4e5f9bca454f;hp=8f6cad20d7f9bc4a86579f0da97b54a11bde925a;hpb=eb4aab6b6d5af827b5c1fb2f7d2550b7de22fa90;p=collectd.git diff --git a/src/common.c b/src/common.c index 8f6cad20..1c80e8f1 100644 --- a/src/common.c +++ b/src/common.c @@ -1,6 +1,6 @@ /** * collectd - src/common.c - * Copyright (C) 2005-2008 Florian octo Forster + * Copyright (C) 2005-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 @@ -16,7 +16,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: - * Florian octo Forster + * Florian octo Forster * Niki W. Waibel * Sebastian Harl * Michał Mirosław @@ -29,6 +29,7 @@ #include "collectd.h" #include "common.h" #include "plugin.h" +#include "utils_cache.h" #if HAVE_PTHREAD_H # include @@ -43,6 +44,15 @@ # include #endif +/* for getaddrinfo */ +#include +#include +#include + +#if HAVE_NETINET_IN_H +# include +#endif + #ifdef HAVE_LIBKSTAT extern kstat_ctl_t *kc; #endif @@ -659,6 +669,7 @@ long long get_kstat_value (kstat_t *ksp, char *name) } #endif /* HAVE_LIBKSTAT */ +#ifndef HAVE_HTONLL unsigned long long ntohll (unsigned long long n) { #if BYTE_ORDER == BIG_ENDIAN @@ -676,6 +687,7 @@ unsigned long long htonll (unsigned long long n) return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32); #endif } /* unsigned long long htonll */ +#endif /* HAVE_HTONLL */ #if FP_LAYOUT_NEED_NOTHING /* Well, we need nothing.. */ @@ -791,6 +803,75 @@ int format_name (char *ret, int ret_len, return (0); } /* int format_name */ +int format_values (char *ret, size_t ret_len, /* {{{ */ + const data_set_t *ds, const value_list_t *vl, + _Bool store_rates) +{ + size_t offset = 0; + int status; + int i; + gauge_t *rates = NULL; + + assert (0 == strcmp (ds->type, vl->type)); + + memset (ret, 0, ret_len); + +#define BUFFER_ADD(...) do { \ + status = ssnprintf (ret + offset, ret_len - offset, \ + __VA_ARGS__); \ + if (status < 1) \ + { \ + sfree (rates); \ + return (-1); \ + } \ + else if (((size_t) status) >= (ret_len - offset)) \ + { \ + sfree (rates); \ + return (-1); \ + } \ + else \ + offset += ((size_t) status); \ +} while (0) + + BUFFER_ADD ("%.3f", CDTIME_T_TO_DOUBLE (vl->time)); + + for (i = 0; i < ds->ds_num; i++) + { + if (ds->ds[i].type == DS_TYPE_GAUGE) + BUFFER_ADD (":%f", vl->values[i].gauge); + else if (store_rates) + { + if (rates == NULL) + rates = uc_get_rate (ds, vl); + if (rates == NULL) + { + WARNING ("format_values: " + "uc_get_rate failed."); + return (-1); + } + BUFFER_ADD (":%g", rates[i]); + } + else if (ds->ds[i].type == DS_TYPE_COUNTER) + BUFFER_ADD (":%llu", vl->values[i].counter); + else if (ds->ds[i].type == DS_TYPE_DERIVE) + BUFFER_ADD (":%"PRIi64, vl->values[i].derive); + else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) + BUFFER_ADD (":%"PRIu64, vl->values[i].absolute); + else + { + ERROR ("format_values plugin: Unknown data source type: %i", + ds->ds[i].type); + sfree (rates); + return (-1); + } + } /* for ds->ds_num */ + +#undef BUFFER_ADD + + sfree (rates); + return (0); +} /* }}} int format_values */ + int parse_identifier (char *str, char **ret_host, char **ret_plugin, char **ret_plugin_instance, char **ret_type, char **ret_type_instance) @@ -837,28 +918,71 @@ int parse_identifier (char *str, char **ret_host, return (0); } /* int parse_identifier */ -int parse_value (const char *value, value_t *ret_value, const data_source_t ds) +int parse_identifier_vl (const char *str, value_list_t *vl) /* {{{ */ { - char *endptr = NULL; - - if (DS_TYPE_COUNTER == ds.type) - ret_value->counter = (counter_t)strtoll (value, &endptr, 0); - else if (DS_TYPE_GAUGE == ds.type) - ret_value->gauge = (gauge_t)strtod (value, &endptr); - else { - ERROR ("parse_value: Invalid data source \"%s\" " - "(type = %i).", ds.name, ds.type); - return -1; - } + char str_copy[6 * DATA_MAX_NAME_LEN]; + char *host = NULL; + char *plugin = NULL; + char *plugin_instance = NULL; + char *type = NULL; + char *type_instance = NULL; + int status; - if (value == endptr) { - ERROR ("parse_value: Failed to parse string as number: %s.", value); - return -1; - } - else if ((NULL != endptr) && ('\0' != *endptr)) - WARNING ("parse_value: Ignoring trailing garbage after number: %s.", - endptr); - return 0; + if ((str == NULL) || (vl == NULL)) + return (EINVAL); + + sstrncpy (str_copy, str, sizeof (str_copy)); + + status = parse_identifier (str_copy, &host, + &plugin, &plugin_instance, + &type, &type_instance); + if (status != 0) + return (status); + + sstrncpy (vl->host, host, sizeof (host)); + sstrncpy (vl->plugin, plugin, sizeof (plugin)); + sstrncpy (vl->plugin_instance, plugin_instance, sizeof (plugin_instance)); + sstrncpy (vl->type, type, sizeof (type)); + sstrncpy (vl->type_instance, type_instance, sizeof (type_instance)); + + return (0); +} /* }}} int parse_identifier_vl */ + +int parse_value (const char *value, value_t *ret_value, int ds_type) +{ + char *endptr = NULL; + + switch (ds_type) + { + case DS_TYPE_COUNTER: + ret_value->counter = (counter_t) strtoull (value, &endptr, 0); + break; + + case DS_TYPE_GAUGE: + ret_value->gauge = (gauge_t) strtod (value, &endptr); + break; + + case DS_TYPE_DERIVE: + ret_value->counter = (derive_t) strtoll (value, &endptr, 0); + break; + + case DS_TYPE_ABSOLUTE: + ret_value->counter = (absolute_t) strtoull (value, &endptr, 0); + break; + + default: + ERROR ("parse_value: Invalid data source type: %i.", ds_type); + return -1; + } + + if (value == endptr) { + ERROR ("parse_value: Failed to parse string as number: %s.", value); + return -1; + } + else if ((NULL != endptr) && ('\0' != *endptr)) + WARNING ("parse_value: Ignoring trailing garbage after number: %s.", + endptr); + return 0; } /* int parse_value */ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds) @@ -885,15 +1009,28 @@ 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 { if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE)) vl->values[i].gauge = NAN; - else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i])) + else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type)) return -1; } @@ -986,7 +1123,7 @@ int notification_init (notification_t *n, int severity, const char *message, } /* int notification_init */ int walk_directory (const char *dir, dirwalk_callback_f callback, - void *user_data) + void *user_data, int include_hidden) { struct dirent *ent; DIR *dh; @@ -1007,9 +1144,18 @@ int walk_directory (const char *dir, dirwalk_callback_f callback, while ((ent = readdir (dh)) != NULL) { int status; - - if (ent->d_name[0] == '.') - continue; + + if (include_hidden) + { + if ((strcmp (".", ent->d_name) == 0) + || (strcmp ("..", ent->d_name) == 0)) + continue; + } + else /* if (!include_hidden) */ + { + if (ent->d_name[0]=='.') + continue; + } status = (*callback) (dir, ent->d_name, user_data); if (status != 0) @@ -1058,3 +1204,74 @@ counter_t counter_diff (counter_t old_value, counter_t new_value) return (diff); } /* counter_t counter_to_gauge */ + +int service_name_to_port_number (const char *service_name) +{ + struct addrinfo *ai_list; + struct addrinfo *ai_ptr; + struct addrinfo ai_hints; + int status; + int service_number; + + if (service_name == NULL) + return (-1); + + ai_list = NULL; + memset (&ai_hints, 0, sizeof (ai_hints)); + ai_hints.ai_family = AF_UNSPEC; + + status = getaddrinfo (/* node = */ NULL, service_name, + &ai_hints, &ai_list); + if (status != 0) + { + ERROR ("service_name_to_port_number: getaddrinfo failed: %s", + gai_strerror (status)); + return (-1); + } + + service_number = -1; + for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) + { + if (ai_ptr->ai_family == AF_INET) + { + struct sockaddr_in *sa; + + sa = (void *) ai_ptr->ai_addr; + service_number = (int) ntohs (sa->sin_port); + } + else if (ai_ptr->ai_family == AF_INET6) + { + struct sockaddr_in6 *sa; + + sa = (void *) ai_ptr->ai_addr; + service_number = (int) ntohs (sa->sin6_port); + } + + if ((service_number > 0) && (service_number <= 65535)) + break; + } + + freeaddrinfo (ai_list); + + if ((service_number > 0) && (service_number <= 65535)) + return (service_number); + return (-1); +} /* int service_name_to_port_number */ + +int strtoderive (const char *string, derive_t *ret_value) /* {{{ */ +{ + derive_t tmp; + char *endptr; + + if ((string == NULL) || (ret_value == NULL)) + return (EINVAL); + + errno = 0; + endptr = NULL; + tmp = (derive_t) strtoll (string, &endptr, /* base = */ 0); + if ((endptr == string) || (errno != 0)) + return (-1); + + *ret_value = tmp; + return (0); +} /* }}} int strtoderive */