From 2a60a9b22492baeeec4f573fbfe8c6394b8ad9e9 Mon Sep 17 00:00:00 2001 From: Lubos Stanek Date: Fri, 17 Nov 2006 20:54:16 +0100 Subject: [PATCH] Improve and generalize the ignorelist functionality. --- configure.in | 35 ++++- src/Makefile.am | 3 +- src/config_list.c | 390 ++++++++++++++++++++++++++++++++++++++++++++++ src/config_list.h | 82 ++++++++++ src/sensors.c | 56 ++----- 5 files changed, 519 insertions(+), 47 deletions(-) create mode 100644 src/config_list.c create mode 100644 src/config_list.h diff --git a/configure.in b/configure.in index 6d3698eb..e76d8111 100644 --- a/configure.in +++ b/configure.in @@ -841,7 +841,39 @@ then AC_DEFINE_UNQUOTED(COLLECTD_HEARTBEAT, "$collectd_heartbeat", [Interval in which plugins are queried.]) fi -# +dnl Check for regex +AC_ARG_WITH(regex, [AS_HELP_STRING([--with-regex], [Use POSIX regular expression in config.])], +[ + if test "x$withval" != "xno" && test "x$withval" != "xyes" + then + with_regex="yes" + fi +], +[ + with_regex="no" +]) +if test "x$with_regex" = "xyes" +then + AC_CHECK_FUNCS([regcomp regexec], + [with_regfuncs="yes"], + [with_regfuncs="no (regcomp & regexec not found)"]) +fi +if test "x$with_regex" = "xyes" +then + AC_CHECK_HEADERS(regex.h, + [with_regexh="yes"], + [with_regexh="no (regex.h not found)"]) +fi +if test "x$with_regex" = "xyes" -a "x$with_regfuncs" = "xyes" -a "x$with_regexh" = "xyes" +then + collect_regex=1 +else + collect_regex=0 +fi +AC_DEFINE_UNQUOTED(COLLECT_REGEX, [$collect_regex], + [Wether or not to use regular expressions]) +AM_CONDITIONAL(BUILD_WITH_REGEX, test "x$with_regex" = "xyes") + # Check for enabled/disabled features # @@ -954,6 +986,7 @@ Configuration: libstatgrab . . . . $with_libstatgrab libkstat . . . . . $with_kstat libmysql . . . . . $with_libmysql + regex . . . . . . . $with_regex Features: debug . . . . . . . $enable_debug diff --git a/src/Makefile.am b/src/Makefile.am index 5538f641..35b92f84 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,8 @@ collectd_SOURCES = collectd.c collectd.h \ common.c common.h \ network.c network.h \ plugin.c plugin.h \ - configfile.c configfile.h + configfile.c configfile.h \ + config_list.c config_list.h collectd_CPPFLAGS = $(LTDLINCL) collectd_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"' collectd_CPPFLAGS += -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"' diff --git a/src/config_list.c b/src/config_list.c new file mode 100644 index 00000000..fa9294ad --- /dev/null +++ b/src/config_list.c @@ -0,0 +1,390 @@ +/** + * collectd - src/config_list.c + * Copyright (C) 2006 Lubos Stanek + * + * 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 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. + * + * 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. + * + * Authors: + * Lubos Stanek + **/ +/** + * configlist handles plugin's list of configured collectable + * entries with global ignore action + **/ +/** + * Usage: + * + * Define plugin's global variable of type configlist_t: + * configlist_t *myconfig_ignore; + * If you know the state of global ignore (IgnoreSelected), + * allocate the variable with: + * myconfig_ignore = configlist_create (YourKnownIgnore); + * If you do not know the state of the global ignore (IgnoreSelected), + * initialize the global variable and set the ignore flag later: + * myconfig_ignore = configlist_init (); + * Append single entries in your cf_register'ed callback function: + * configlist_add (myconfig_ignore, newentry); + * When you hit the IgnoreSelected config option, + * offer it to the list: + * configlist_ignore (myconfig_ignore, instantly_got_value_of_ignore); + * That ia all for the configlist initialization. + * Later during read and write (plugin's registered functions) get + * the information whether this entry would be collected or not: + * if (configlist_ignored (myconfig_ignore, thisentry)) + * return; + **/ + +#include "common.h" +#include "utils_debug.h" +#include "config_list.h" + +#define BUFSIZE 512 + +/* private prototypes */ + +struct configentry_s; +typedef struct configentry_s configentry_t; + +struct configlist_s { + int ignore; /* ignore entries */ + int num; /* number of entries */ + configentry_t *next; /* pointer to the first entry */ +}; + +struct configentry_s { +#if HAVE_REGEX_H + regex_t *rmatch; /* regular expression entry identification */ +#endif + char *smatch; /* string entry identification */ + configentry_t *next; +}; + + +/* *** *** *** ********************************************* *** *** *** */ +/* *** *** *** *** *** *** private functions *** *** *** *** *** *** */ +/* *** *** *** ********************************************* *** *** *** */ + +#if HAVE_REGEX_H +static int configlist_regappend(configlist_t *conflist, const char *entry) +{ + int rcompile; + regex_t *regtemp; + char regerr[BUFSIZE]; + configentry_t *new; + + /* create buffer */ + if ((regtemp = malloc(sizeof(regex_t))) == NULL) + { + syslog (LOG_ERR, "cannot allocate new config entry"); + regfree (regtemp); + return (0); + } + memset (regtemp, '\0', sizeof(regex_t)); + + /* compile regex */ + if ((rcompile = regcomp (regtemp, entry, REG_EXTENDED)) != 0) + { + if (regerror(rcompile, regtemp, regerr, sizeof(regerr))) + syslog (LOG_ERR, "cannot compile regex %s: %i/%s", + entry, rcompile, regerr); + else + syslog (LOG_ERR, "cannot compile regex %s: %i", + entry, rcompile); + regfree (regtemp); + return (0); + } + DBG("regex compiled: %s - %i", entry, rcompile); + + /* create new entry */ + if ((new = malloc(sizeof(configentry_t))) == NULL) + { + syslog (LOG_ERR, "cannot allocate new config entry"); + regfree (regtemp); + return (0); + } + memset (new, '\0', sizeof(configentry_t)); + new->rmatch = regtemp; +#if COLLECTD_DEBUG + new->smatch = sstrdup(entry); +#endif + /* append new entry */ + if (conflist->next == NULL) + { + conflist->next=new; + } + else + { + new->next=conflist->next; + conflist->next=new; + } + conflist->num++; + return (1); +} /* int configlist_regappend(configlist_t *conflist, const char *entry) */ +#endif + +static int configlist_strappend(configlist_t *conflist, const char *entry) +{ + configentry_t *new; + + /* create new entry */ + if ((new = malloc(sizeof(configentry_t))) == NULL ) + { + syslog (LOG_ERR, "cannot allocate new entry"); + return (0); + } + memset (new, '\0', sizeof(configentry_t)); + new->smatch = sstrdup(entry); + + /* append new entry */ + if (conflist->next == NULL) + { + conflist->next=new; + } + else + { + new->next=conflist->next; + conflist->next=new; + } + conflist->num++; + return (1); +} /* int configlist_strappend(configlist_t *conflist, const char *entry) */ + +#if HAVE_REGEX_H +/* + * check list for entry regex match + * return 1 if found + */ +static int configentry_rmatch (configentry_t *confentry, const char *entry) +{ + if (confentry == NULL) + return (0); + + if (strlen (entry) == 0) + return (0); + + if (confentry->rmatch == NULL) + return (0); + + /* match regex */ + if (regexec (confentry->rmatch, entry, 0, NULL, 0) == 0) + return (1); + + return (0); +} /* int configentry_rmatch (configentry_t *confentry, const char *entry) */ +#endif + +/* + * check list for entry string match + * return 1 if found + */ +static int configentry_smatch (configentry_t *confentry, const char *entry) +{ + if (confentry == NULL) + return (0); + + if (strlen (entry) == 0) + return (0); + + if ((confentry->smatch != NULL && strcmp (entry, confentry->smatch) == 0)) + return (1); + + return (0); +} /* int configentry_smatch (configentry_t *confentry, const char *entry) */ + + +/* *** *** *** ******************************************** *** *** *** */ +/* *** *** *** *** *** *** public functions *** *** *** *** *** *** */ +/* *** *** *** ******************************************** *** *** *** */ + +/* + * create the configlist_t with known ignore state + * return pointer to configlist_t + */ +configlist_t *configlist_create (int ignore) +{ + configlist_t *conflist; + + if ((conflist = smalloc (sizeof (configlist_t))) == NULL) + { + syslog(LOG_ERR, "not enough memory to allocate configlist"); + return (NULL); + } + DBG("configlist created 0x%p, ignore %i", (void *) conflist, ignore); + memset (conflist, '\0', sizeof (configlist_t)); + + if (ignore) + conflist->ignore = ignore; + + return (conflist); +} /* configlist_t *configlist_create (int ignore) */ + +/* + * create configlist_t and initialize the ignore state to 0 + * return pointer to configlist_t + */ +configlist_t *configlist_init (void) +{ + return (configlist_create (0)); +} /* configlist_t *configlist_init (void) */ + + +/* + * free memory used by configlist_t + */ +void configlist_free (configlist_t *conflist) +{ + configentry_t *this; + configentry_t *next; + + DBG ("(conflist = 0x%p)", (void *) conflist); + + if (conflist == NULL) + return; + + for (this = conflist->next; this != NULL; this = next) + { + DBG ("free - confentry = 0x%p, numlist %i", (void *) this, conflist->num); + next = this->next; + conflist->num--; +#if HAVE_REGEX_H + if (this->rmatch != NULL) + { + regfree (this->rmatch); + this->rmatch = NULL; + } +#endif + if (this->smatch != NULL) + { + sfree (this->smatch); + this->smatch = NULL; + } + sfree (this); + } +#if COLLECTD_DEBUG + if (conflist->num != 0) + DBG ("after free numlist: %i", conflist->num); +#endif + conflist->num = 0; + sfree (conflist); + conflist = NULL; +} /* void configlist_destroy (configlist_t *conflist) */ + +/* + * set ignore state of the configlist_t + */ +void configlist_ignore (configlist_t *conflist, int ignore) +{ + if (conflist == NULL) + { + DBG("ignore call with configlist_t == NULL"); + return; + } + + conflist->ignore = ignore; +} /* void configlist_ignore (configlist_t *conflist, int ignore) */ + +/* + * get number of entries in the configlist_t + * return int number + */ +int configlist_num (configlist_t *conflist) +{ + if (conflist == NULL) + { + DBG("get num called with configlist_t == NULL"); + return (0); + } + + return (conflist->num); +} /* int configlist_num (configlist_t *conflist) */ + +/* + * append entry into configlist_t + * return 1 for success + */ +int configlist_add (configlist_t *conflist, const char *entry) +{ +#if HAVE_REGEX_H + char *entrytemp; +#endif + int restemp; + + if (conflist == NULL) + { + DBG("add called with configlist_t == NULL"); + return (0); + } + + /* append nothing, report success */ + if (strlen(entry) == 0) + { + DBG("not appending: empty entry"); + return (1); + } + +#if HAVE_REGEX_H + /* regex string is enclosed in "|...|" */ + if (entry[0] == '|' && strlen(entry) > 2 && entry[strlen(entry) - 1] == '|') + { + entrytemp = smalloc(strlen(entry) - 2); + sstrncpy(entrytemp, &entry[1], strlen(entry) - 1); + DBG("to add regex entry: %s", entrytemp); + restemp = configlist_regappend(conflist, entrytemp); + sfree (entrytemp); + } + else +#endif + { + DBG("to add entry: %s", entry); + restemp = configlist_strappend(conflist, entry); + } + return (restemp); +} /* int configlist_add (configlist_t *conflist, const char *entry) */ + +/* + * check list for entry + * return 1 for ignored entry + */ +int configlist_ignored (configlist_t *conflist, const char *entry) +{ + configentry_t *traverse; + + /* if no entries, collect all */ + if (configlist_num(conflist) == 0) + return (0); + + /* traverse list and check entries */ + traverse = conflist->next; + while (traverse != NULL) + { +#if HAVE_REGEX_H + if (traverse->rmatch != NULL) + { + if (configentry_rmatch (traverse, entry)) + return (conflist->ignore); + } + else +#endif + { + if (configentry_smatch (traverse, entry)) + return (conflist->ignore); + } + traverse = traverse->next; + } + + return (1 - conflist->ignore); +} /* int configlist_ignored (configlist_t *conflist, const char *entry) */ + diff --git a/src/config_list.h b/src/config_list.h new file mode 100644 index 00000000..dd434a56 --- /dev/null +++ b/src/config_list.h @@ -0,0 +1,82 @@ +/** + * collectd - src/config_list.h + * Copyright (C) 2006 Lubos Stanek + * + * 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 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. + * + * 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. + * + * Authors: + * Lubos Stanek + **/ +/** + * configlist handles plugin's list of configured collectable + * entries with global ignore action + **/ + +#if !CONFIG_LIST_H +#define CONFIG_LIST_H 1 + +#include "common.h" + +#if HAVE_REGEX_H +# include +#endif + +/* public prototypes */ + +struct configlist_s; +typedef struct configlist_s configlist_t; + +/* + * create the configlist_t with known ignore state + * return pointer to configlist_t + */ +configlist_t *configlist_create (int ignore); + +/* + * create configlist_t and initialize the ignore state to 0 + * return pointer to configlist_t + */ +configlist_t *configlist_init (void); + +/* + * free memory used by configlist_t + */ +void configlist_free (configlist_t *conflist); + +/* + * set ignore state of the configlist_t + */ +void configlist_ignore (configlist_t *conflist, int ignore); +/* + * get number of entries in the configlist_t + * return int number + */ +int configlist_num (configlist_t *conflist); + +/* + * append entry to configlist_t + * return 1 for success + */ +int configlist_add (configlist_t *conflist, const char *entry); + +/* + * check list for entry + * return 1 for ignored entry + */ +int configlist_ignored (configlist_t *conflist, const char *entry); + +#endif /* !CONFIG_LIST_H */ + diff --git a/src/sensors.c b/src/sensors.c index 4dd826e2..c60f2914 100644 --- a/src/sensors.c +++ b/src/sensors.c @@ -33,6 +33,7 @@ #include "common.h" #include "plugin.h" #include "configfile.h" +#include "config_list.h" #include "utils_debug.h" #define MODULE_NAME "sensors" @@ -164,14 +165,8 @@ static char *config_keys[] = }; static int config_keys_num = 3; -static char **sensor_list = NULL; -static int sensor_list_num = 0; -/* - * sensor_list_action: - * 0 => default is to collect selected sensors - * 1 => ignore selected sensors - */ -static int sensor_list_action = 0; +static configlist_t *sensor_list; + /* * sensor_extended_naming: * 0 => default is to create chip-feature @@ -193,33 +188,23 @@ featurelist_t *first_feature = NULL; static int sensors_config (char *key, char *value) { - char **temp; + if (sensor_list == NULL) + sensor_list = configlist_init(); if (strcasecmp (key, "Sensor") == 0) { - temp = (char **) realloc (sensor_list, (sensor_list_num + 1) * sizeof (char *)); - if (temp == NULL) - { - syslog (LOG_EMERG, "Cannot allocate more memory."); - return (1); - } - sensor_list = temp; - - if ((sensor_list[sensor_list_num] = strdup (value)) == NULL) + if (!configlist_add (sensor_list, value)) { - syslog (LOG_EMERG, "Cannot allocate memory."); + syslog (LOG_EMERG, "Cannot add value."); return (1); } - sensor_list_num++; } else if (strcasecmp (key, "IgnoreSelected") == 0) { if ((strcasecmp (value, "True") == 0) || (strcasecmp (value, "Yes") == 0) || (strcasecmp (value, "On") == 0)) - sensor_list_action = 1; - else - sensor_list_action = 0; + configlist_ignore (sensor_list, 1); } else if (strcasecmp (key, "ExtendedSensorNaming") == 0) { @@ -238,25 +223,6 @@ static int sensors_config (char *key, char *value) return (0); } -/* - * Check if this feature should be ignored. This is called from - * both, `submit' and `write' to give client and server - * the ability to ignore certain stuff... - */ -static int config_get_ignored (const char *inst) -{ - int i; - - /* If no ignored are given collect all features. */ - if (sensor_list_num < 1) - return (0); - - for (i = 0; i < sensor_list_num; i++) - if (strcasecmp (inst, sensor_list[i]) == 0) - return (sensor_list_action); - return (1 - sensor_list_action); -} - static void collectd_sensors_init (void) { #ifdef HAVE_LIBSENSORS @@ -370,7 +336,7 @@ static void sensors_voltage_write (char *host, char *inst, char *val) int status; /* skip ignored in our config */ - if (config_get_ignored (inst)) + if (configlist_ignored (sensor_list, inst)) return; /* extended sensor naming */ @@ -391,7 +357,7 @@ static void sensors_write (char *host, char *inst, char *val) int status; /* skip ignored in our config */ - if (config_get_ignored (inst)) + if (configlist_ignored (sensor_list, inst)) return; /* extended sensor naming */ @@ -418,7 +384,7 @@ static void sensors_submit (const char *feat_name, return; /* skip ignored in our config */ - if (config_get_ignored (inst)) + if (configlist_ignored (sensor_list, inst)) return; if (snprintf (buf, BUFSIZE, "%u:%.3f", (unsigned int) curtime, -- 2.30.2