X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fcommon.c;h=bcdf59aafdbd8a52a36579073f49ff2bf9b6c8f8;hb=44e4d530c8db2e078cd73ab254d1be41a5f2812c;hp=fd1fbd402194ee9c67fd886d60dc33d1a13a1b1d;hpb=3a4405009e53f578c26c22073920cc5b4ffa6eca;p=collectd.git diff --git a/src/common.c b/src/common.c index fd1fbd40..bcdf59aa 100644 --- a/src/common.c +++ b/src/common.c @@ -1,21 +1,19 @@ /** * collectd - src/common.c - * Copyright (C) 2005,2006 Florian octo Forster + * Copyright (C) 2005-2007 Florian octo Forster * - * This program is free software; you can redistribute it and/ - * or modify it under the terms of the GNU General Public Li- - * cence as published by the Free Software Foundation; either - * version 2 of the Licence, or any later version. + * 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 use- - * ful, but WITHOUT ANY WARRANTY; without even the implied war- - * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public Licence for more details. + * 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 - * Licence along with this program; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, - * USA. + * 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 @@ -27,60 +25,21 @@ #endif #include "common.h" -#include "utils_debug.h" +#include "plugin.h" #ifdef HAVE_MATH_H # include #endif -extern int operating_mode; +/* for ntohl and htonl */ +#if HAVE_ARPA_INET_H +# include +#endif #ifdef HAVE_LIBKSTAT extern kstat_ctl_t *kc; #endif -#ifdef HAVE_LIBRRD -#if 0 -static char *rra_def[] = -{ - "RRA:AVERAGE:0.0:1:1500", - "RRA:AVERAGE:0.2:6:1500", - "RRA:AVERAGE:0.1:180:1680", - "RRA:AVERAGE:0.1:2160:1520", - "RRA:MIN:0.0:1:1500", - "RRA:MIN:0.2:6:1500", - "RRA:MIN:0.1:180:1680", - "RRA:MIN:0.1:2160:1520", - "RRA:MAX:0.0:1:1500", - "RRA:MAX:0.2:6:1500", - "RRA:MAX:0.1:180:1680", - "RRA:MAX:0.1:2160:1520", - NULL -}; -static int rra_num = 12; -#endif - -static int rra_timespans[] = -{ - 3600, - 86400, - 604800, - 2678400, - 31622400, - 0 -}; -static int rra_timespans_num = 5; - -static char *rra_types[] = -{ - "AVERAGE", - "MIN", - "MAX", - NULL -}; -static int rra_types_num = 3; -#endif /* HAVE_LIBRRD */ - void sstrncpy (char *d, const char *s, int len) { strncpy (d, s, len); @@ -96,20 +55,29 @@ char *sstrdup (const char *s) if((r = strdup (s)) == NULL) { - DBG ("Not enough memory."); + DEBUG ("Not enough memory."); exit(3); } return (r); } +/* Don't use the return value of `strerror_r', because the GNU-people got + * inventive there.. -octo */ +char *sstrerror (int errnum, char *buf, size_t buflen) +{ + buf[0] = '\0'; + strerror_r (errnum, buf, buflen); + return (buf); +} /* char *sstrerror */ + void *smalloc (size_t size) { void *r; if ((r = malloc (size)) == NULL) { - DBG("Not enough memory."); + DEBUG("Not enough memory."); exit(3); } @@ -150,7 +118,7 @@ ssize_t sread (int fd, void *buf, size_t count) if (status == 0) { - DBG ("Received EOF from fd %i. " + DEBUG ("Received EOF from fd %i. " "Closing fd and returning error.", fd); close (fd); @@ -197,10 +165,12 @@ int strsplit (char *string, char **fields, size_t size) { size_t i; char *ptr; + char *saveptr; i = 0; ptr = string; - while ((fields[i] = strtok (ptr, " \t")) != NULL) + saveptr = NULL; + while ((fields[i] = strtok_r (ptr, " \t", &saveptr)) != NULL) { ptr = NULL; i++; @@ -324,7 +294,7 @@ int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct times return (0); } -static int check_create_dir (const char *file_orig) +int check_create_dir (const char *file_orig) { struct stat statbuf; @@ -334,7 +304,9 @@ static int check_create_dir (const char *file_orig) char *fields[16]; int fields_num; char *ptr; + char *saveptr; int last_is_file = 1; + int path_is_absolute = 0; int len; int i; @@ -355,9 +327,11 @@ static int check_create_dir (const char *file_orig) */ if (file_orig[len - 1] == '/') last_is_file = 0; + if (file_orig[0] == '/') + path_is_absolute = 1; /* - * Create a copy for `strtok' to destroy + * Create a copy for `strtok_r' to destroy */ strncpy (file_copy, file_orig, 512); file_copy[511] = '\0'; @@ -367,8 +341,9 @@ static int check_create_dir (const char *file_orig) * remove leading and trailing slashes.. */ ptr = file_copy; + saveptr = NULL; fields_num = 0; - while ((fields[fields_num] = strtok (ptr, "/")) != NULL) + while ((fields[fields_num] = strtok_r (ptr, "/", &saveptr)) != NULL) { ptr = NULL; fields_num++; @@ -389,16 +364,18 @@ static int check_create_dir (const char *file_orig) */ if (fields[i][0] == '.') { - syslog (LOG_ERR, "Cowardly refusing to create a directory that begins with a `.' (dot): `%s'", file_orig); + ERROR ("Cowardly refusing to create a directory that begins with a `.' (dot): `%s'", file_orig); return (-2); } /* * Join the components together again */ - if (strjoin (dir, dir_len, fields, i + 1, "/") < 0) + dir[0] = '/'; + if (strjoin (dir + path_is_absolute, dir_len - path_is_absolute, + fields, i + 1, "/") < 0) { - syslog (LOG_ERR, "strjoin failed: `%s', component #%i", file_orig, i); + ERROR ("strjoin failed: `%s', component #%i", file_orig, i); return (-1); } @@ -408,19 +385,25 @@ static int check_create_dir (const char *file_orig) { if (mkdir (dir, 0755) == -1) { - syslog (LOG_ERR, "mkdir (%s): %s", dir, strerror (errno)); + char errbuf[1024]; + ERROR ("mkdir (%s): %s", dir, + sstrerror (errno, + errbuf, sizeof (errbuf))); return (-1); } } else { - syslog (LOG_ERR, "stat (%s): %s", dir, strerror (errno)); + char errbuf[1024]; + ERROR ("stat (%s): %s", dir, + sstrerror (errno, errbuf, + sizeof (errbuf))); return (-1); } } else if (!S_ISDIR (statbuf.st_mode)) { - syslog (LOG_ERR, "stat (%s): Not a directory!", dir); + ERROR ("stat (%s): Not a directory!", dir); return (-1); } } @@ -428,338 +411,6 @@ static int check_create_dir (const char *file_orig) return (0); } -/* * * * * - * Magic * - * * * * */ -#if HAVE_LIBRRD -static int rra_get (char ***ret) -{ - static char **rra_def = NULL; - static int rra_num = 0; - - int rra_max = rra_timespans_num * rra_types_num; - - int step; - int rows; - int span; - - int cdp_num; - int cdp_len; - int i, j; - - char buffer[64]; - - if ((rra_num != 0) && (rra_def != NULL)) - { - *ret = rra_def; - return (rra_num); - } - - if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL) - return (-1); - memset (rra_def, '\0', (rra_max + 1) * sizeof (char *)); - - step = atoi (COLLECTD_STEP); - rows = atoi (COLLECTD_ROWS); - - if ((step <= 0) || (rows <= 0)) - { - *ret = NULL; - return (-1); - } - - cdp_len = 0; - for (i = 0; i < rra_timespans_num; i++) - { - span = rra_timespans[i]; - - if ((span / step) < rows) - continue; - - if (cdp_len == 0) - cdp_len = 1; - else - cdp_len = (int) floor (((double) span) / ((double) (rows * step))); - - cdp_num = (int) ceil (((double) span) / ((double) (cdp_len * step))); - - for (j = 0; j < rra_types_num; j++) - { - if (rra_num >= rra_max) - break; - - if (snprintf (buffer, sizeof(buffer), "RRA:%s:%3.1f:%u:%u", - rra_types[j], COLLECTD_XFF, - cdp_len, cdp_num) >= sizeof (buffer)) - { - syslog (LOG_ERR, "rra_get: Buffer would have been truncated."); - continue; - } - - rra_def[rra_num++] = sstrdup (buffer); - } - } - -#if COLLECT_DEBUG - DBG ("rra_num = %i", rra_num); - for (i = 0; i < rra_num; i++) - DBG (" %s", rra_def[i]); -#endif - - *ret = rra_def; - return (rra_num); -} -#endif /* HAVE_LIBRRD */ - -static int log_create_file (char *filename, char **ds_def, int ds_num) -{ - FILE *log; - int i; - - if (check_create_dir (filename)) - return (-1); - - log = fopen (filename, "w"); - if (log == NULL) - { - syslog (LOG_WARNING, "Failed to create %s: %s", filename, - strerror(errno)); - return (-1); - } - - fprintf (log, "epoch"); - for (i = 0; i < ds_num; i++) - { - char *name; - char *tmp; - - name = strchr (ds_def[i], ':'); - if (name == NULL) - { - syslog (LOG_WARNING, "Invalid DS definition '%s' for %s", - ds_def[i], filename); - fclose(log); - remove(filename); - return (-1); - } - - name += 1; - tmp = strchr (name, ':'); - if (tmp == NULL) - { - syslog (LOG_WARNING, "Invalid DS definition '%s' for %s", - ds_def[i], filename); - fclose(log); - remove(filename); - return (-1); - } - - /* The `%.*s' is needed because there is no null-byte behind - * the name. */ - fprintf(log, ",%.*s", (int) (tmp - name), name); - } - fprintf(log, "\n"); - fclose(log); - - return 0; -} - -static int log_update_file (char *host, char *file, char *values, - char **ds_def, int ds_num) -{ - char *tmp; - FILE *fp; - struct stat statbuf; - char full_file[1024]; - - /* Cook the values a bit: Substitute colons with commas */ - strsubstitute (values, ':', ','); - - /* host == NULL => local mode */ - if (host != NULL) - { - if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024) - return (-1); - } - else - { - if (snprintf (full_file, 1024, "%s", file) >= 1024) - return (-1); - } - - strncpy (full_file, file, 1024); - - tmp = full_file + strlen (full_file) - 4; - assert ((tmp != NULL) && (tmp > full_file)); - - /* Change the filename for logfiles. */ - if (strncmp (tmp, ".rrd", 4) == 0) - { - time_t now; - struct tm *tm; - - /* TODO: Find a way to minimize the calls to `localtime', since - * they are pretty expensive.. */ - now = time (NULL); - tm = localtime (&now); - - strftime (tmp, 1024 - (tmp - full_file), "-%Y-%m-%d", tm); - - /* `localtime(3)' returns a pointer to static data, - * therefore the pointer may not be free'd. */ - } - else - DBG ("The filename ends with `%s' which is unexpected.", tmp); - - if (stat (full_file, &statbuf) == -1) - { - if (errno == ENOENT) - { - if (log_create_file (full_file, ds_def, ds_num)) - return (-1); - } - else - { - syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno)); - return (-1); - } - } - else if (!S_ISREG (statbuf.st_mode)) - { - syslog (LOG_ERR, "stat %s: Not a regular file!", full_file); - return (-1); - } - - - fp = fopen (full_file, "a"); - if (fp == NULL) - { - syslog (LOG_WARNING, "Failed to append to %s: %s", full_file, - strerror(errno)); - return (-1); - } - fprintf(fp, "%s\n", values); - fclose(fp); - - return (0); -} /* int log_update_file */ - -#if HAVE_LIBRRD -static int rrd_create_file (char *filename, char **ds_def, int ds_num) -{ - char **argv; - int argc; - char **rra_def; - int rra_num; - int i, j; - int status = 0; - - if (check_create_dir (filename)) - return (-1); - - if ((rra_num = rra_get (&rra_def)) < 1) - { - syslog (LOG_ERR, "rra_create failed: Could not calculate RRAs"); - return (-1); - } - - argc = ds_num + rra_num + 4; - - if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL) - { - syslog (LOG_ERR, "rrd_create failed: %s", strerror (errno)); - return (-1); - } - - argv[0] = "create"; - argv[1] = filename; - argv[2] = "-s"; - argv[3] = COLLECTD_STEP; - - j = 4; - for (i = 0; i < ds_num; i++) - argv[j++] = ds_def[i]; - for (i = 0; i < rra_num; i++) - argv[j++] = rra_def[i]; - argv[j] = NULL; - - optind = 0; /* bug in librrd? */ - rrd_clear_error (); - if (rrd_create (argc, argv) == -1) - { - syslog (LOG_ERR, "rrd_create failed: %s: %s", filename, rrd_get_error ()); - status = -1; - } - - free (argv); - - return (status); -} -#endif /* HAVE_LIBRRD */ - -int rrd_update_file (char *host, char *file, char *values, - char **ds_def, int ds_num) -{ -#if HAVE_LIBRRD - struct stat statbuf; - char full_file[1024]; - char *argv[4] = { "update", full_file, values, NULL }; -#endif /* HAVE_LIBRRD */ - - /* I'd rather have a function `common_update_file' to make this - * decission, but for that we'd need to touch all plugins.. */ - if (operating_mode == MODE_LOG) - return (log_update_file (host, file, values, - ds_def, ds_num)); - -#if HAVE_LIBRRD - /* host == NULL => local mode */ - if (host != NULL) - { - if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024) - return (-1); - } - else - { - if (snprintf (full_file, 1024, "%s", file) >= 1024) - return (-1); - } - - if (stat (full_file, &statbuf) == -1) - { - if (errno == ENOENT) - { - if (rrd_create_file (full_file, ds_def, ds_num)) - return (-1); - } - else - { - syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno)); - return (-1); - } - } - else if (!S_ISREG (statbuf.st_mode)) - { - syslog (LOG_ERR, "stat %s: Not a regular file!", full_file); - return (-1); - } - - optind = 0; /* bug in librrd? */ - rrd_clear_error (); - if (rrd_update (3, argv) == -1) - { - syslog (LOG_WARNING, "rrd_update failed: %s: %s", full_file, rrd_get_error ()); - return (-1); - } - return (0); -/* #endif HAVE_LIBRRD */ - -#else - syslog (LOG_ERR, "`rrd_update_file' was called, but collectd isn't linked against librrd!"); - return (-1); -#endif -} - #ifdef HAVE_LIBKSTAT int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name) { @@ -775,13 +426,13 @@ int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name) { if ((*ksp_ptr = kstat_lookup (kc, module, instance, name)) == NULL) { - syslog (LOG_ERR, "Cound not find kstat %s", ident); + ERROR ("Cound not find kstat %s", ident); return (-1); } if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) { - syslog (LOG_WARNING, "kstat %s has wrong type", ident); + WARNING ("kstat %s has wrong type", ident); *ksp_ptr = NULL; return (-1); } @@ -794,13 +445,13 @@ int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name) if (kstat_read (kc, *ksp_ptr, NULL) == -1) { - syslog (LOG_WARNING, "kstat %s could not be read", ident); + WARNING ("kstat %s could not be read", ident); return (-1); } if ((*ksp_ptr)->ks_type != KSTAT_TYPE_NAMED) { - syslog (LOG_WARNING, "kstat %s has wrong type", ident); + WARNING ("kstat %s has wrong type", ident); return (-1); } @@ -840,8 +491,63 @@ long long get_kstat_value (kstat_t *ksp, char *name) else if (kn->data_type == KSTAT_DATA_UINT64) retval = (long long) kn->value.ui64; /* XXX: Might overflow! */ else - syslog (LOG_WARNING, "get_kstat_value: Not a numeric value: %s", name); + WARNING ("get_kstat_value: Not a numeric value: %s", name); return (retval); } #endif /* HAVE_LIBKSTAT */ + +unsigned long long ntohll (unsigned long long n) +{ +#if __BYTE_ORDER == __BIG_ENDIAN + return (n); +#else + return (((unsigned long long) ntohl (n)) << 32) + ntohl (n >> 32); +#endif +} /* unsigned long long ntohll */ + +unsigned long long htonll (unsigned long long n) +{ +#if __BYTE_ORDER == __BIG_ENDIAN + return (n); +#else + return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32); +#endif +} /* unsigned long long htonll */ + +int format_name (char *ret, int ret_len, + const char *hostname, + const char *plugin, const char *plugin_instance, + const char *type, const char *type_instance) +{ + int status; + + assert (plugin != NULL); + assert (type != NULL); + + if ((plugin_instance == NULL) || (strlen (plugin_instance) == 0)) + { + if ((type_instance == NULL) || (strlen (type_instance) == 0)) + status = snprintf (ret, ret_len, "%s/%s/%s", + hostname, plugin, type); + else + status = snprintf (ret, ret_len, "%s/%s/%s-%s", + hostname, plugin, type, + type_instance); + } + else + { + if ((type_instance == NULL) || (strlen (type_instance) == 0)) + status = snprintf (ret, ret_len, "%s/%s-%s/%s", + hostname, plugin, plugin_instance, + type); + else + status = snprintf (ret, ret_len, "%s/%s-%s/%s-%s", + hostname, plugin, plugin_instance, + type, type_instance); + } + + if ((status < 1) || (status >= ret_len)) + return (-1); + return (0); +} /* int format_name */