X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fmatch_regex.c;h=ed1e3295902f9297e90f917712b74cbebb1b28b1;hp=9c708982b562e1a77ed0dab8159082611d57e18b;hb=d486225f89ea52d8ed2b4242eba2ad94c409f837;hpb=2079ee1517e34de372f58e7e2267ad5c71a8a41f diff --git a/src/match_regex.c b/src/match_regex.c index 9c708982..ed1e3295 100644 --- a/src/match_regex.c +++ b/src/match_regex.c @@ -33,7 +33,10 @@ #include "collectd.h" +#include "common.h" #include "filter_chain.h" +#include "meta_data.h" +#include "utils_llist.h" #include #include @@ -62,7 +65,8 @@ struct mr_match_s { mr_regex_t *plugin_instance; mr_regex_t *type; mr_regex_t *type_instance; - _Bool invert; + llist_t *meta; /* Maps each meta key into mr_regex_t* */ + bool invert; }; /* @@ -75,7 +79,7 @@ static void mr_free_regex(mr_regex_t *r) /* {{{ */ regfree(&r->re); memset(&r->re, 0, sizeof(r->re)); - free(r->re_str); + sfree(r->re_str); if (r->next != NULL) mr_free_regex(r->next); @@ -91,14 +95,19 @@ static void mr_free_match(mr_match_t *m) /* {{{ */ mr_free_regex(m->plugin_instance); mr_free_regex(m->type); mr_free_regex(m->type_instance); + for (llentry_t *e = llist_head(m->meta); e != NULL; e = e->next) { + sfree(e->key); + mr_free_regex((mr_regex_t *)e->value); + } + llist_destroy(m->meta); - free(m); + sfree(m); } /* }}} void mr_free_match */ static int mr_match_regexen(mr_regex_t *re_head, /* {{{ */ const char *string) { if (re_head == NULL) - return (FC_MATCH_MATCHES); + return FC_MATCH_MATCHES; for (mr_regex_t *re = re_head; re != NULL; re = re->next) { int status; @@ -112,35 +121,30 @@ static int mr_match_regexen(mr_regex_t *re_head, /* {{{ */ } else { DEBUG("regex match: Regular expression `%s' does not match `%s'.", re->re_str, string); - return (FC_MATCH_NO_MATCH); + return FC_MATCH_NO_MATCH; } } - return (FC_MATCH_MATCHES); + return FC_MATCH_MATCHES; } /* }}} int mr_match_regexen */ -static int mr_config_add_regex(mr_regex_t **re_head, /* {{{ */ - oconfig_item_t *ci) { +static int mr_add_regex(mr_regex_t **re_head, const char *re_str, /* {{{ */ + const char *option) { mr_regex_t *re; int status; - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - log_warn("`%s' needs exactly one string argument.", ci->key); - return (-1); - } - re = calloc(1, sizeof(*re)); if (re == NULL) { - log_err("mr_config_add_regex: calloc failed."); - return (-1); + log_err("mr_add_regex: calloc failed."); + return -1; } re->next = NULL; - re->re_str = strdup(ci->values[0].value.string); + re->re_str = strdup(re_str); if (re->re_str == NULL) { - free(re); - log_err("mr_config_add_regex: strdup failed."); - return (-1); + sfree(re); + log_err("mr_add_regex: strdup failed."); + return -1; } status = regcomp(&re->re, re->re_str, REG_EXTENDED | REG_NOSUB); @@ -148,11 +152,11 @@ static int mr_config_add_regex(mr_regex_t **re_head, /* {{{ */ char errmsg[1024]; regerror(status, &re->re, errmsg, sizeof(errmsg)); errmsg[sizeof(errmsg) - 1] = 0; - log_err("Compiling regex `%s' for `%s' failed: %s.", re->re_str, ci->key, + log_err("Compiling regex `%s' for `%s' failed: %s.", re->re_str, option, errmsg); - free(re->re_str); - free(re); - return (-1); + sfree(re->re_str); + sfree(re); + return -1; } if (*re_head == NULL) { @@ -167,9 +171,69 @@ static int mr_config_add_regex(mr_regex_t **re_head, /* {{{ */ ptr->next = re; } - return (0); + return 0; +} /* }}} int mr_add_regex */ + +static int mr_config_add_regex(mr_regex_t **re_head, /* {{{ */ + oconfig_item_t *ci) { + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { + log_warn("`%s' needs exactly one string argument.", ci->key); + return -1; + } + + return mr_add_regex(re_head, ci->values[0].value.string, ci->key); } /* }}} int mr_config_add_regex */ +static int mr_config_add_meta_regex(llist_t **meta, /* {{{ */ + oconfig_item_t *ci) { + char *meta_key; + llentry_t *entry; + mr_regex_t *re_head; + int status; + char buffer[1024]; + + if ((ci->values_num != 2) || (ci->values[0].type != OCONFIG_TYPE_STRING) || + (ci->values[1].type != OCONFIG_TYPE_STRING)) { + log_warn("`%s' needs exactly two string arguments.", ci->key); + return -1; + } + + if (*meta == NULL) { + *meta = llist_create(); + if (*meta == NULL) { + log_err("mr_config_add_meta_regex: llist_create failed."); + return -1; + } + } + + meta_key = ci->values[0].value.string; + entry = llist_search(*meta, meta_key); + if (entry == NULL) { + meta_key = strdup(meta_key); + if (meta_key == NULL) { + log_err("mr_config_add_meta_regex: strdup failed."); + return -1; + } + entry = llentry_create(meta_key, NULL); + if (entry == NULL) { + log_err("mr_config_add_meta_regex: llentry_create failed."); + sfree(meta_key); + return -1; + } + /* meta_key and entry will now be freed by mr_free_match(). */ + llist_append(*meta, entry); + } + + snprintf(buffer, sizeof(buffer), "%s `%s'", ci->key, meta_key); + /* Can't pass &entry->value into mr_add_regex, so copy in/out. */ + re_head = entry->value; + status = mr_add_regex(&re_head, ci->values[1].value.string, buffer); + if (status == 0) { + entry->value = re_head; + } + return status; +} /* }}} int mr_config_add_meta_regex */ + static int mr_create(const oconfig_item_t *ci, void **user_data) /* {{{ */ { mr_match_t *m; @@ -178,10 +242,10 @@ static int mr_create(const oconfig_item_t *ci, void **user_data) /* {{{ */ m = calloc(1, sizeof(*m)); if (m == NULL) { log_err("mr_create: calloc failed."); - return (-ENOMEM); + return -ENOMEM; } - m->invert = 0; + m->invert = false; status = 0; for (int i = 0; i < ci->children_num; i++) { @@ -198,6 +262,8 @@ static int mr_create(const oconfig_item_t *ci, void **user_data) /* {{{ */ status = mr_config_add_regex(&m->type, child); else if (strcasecmp("TypeInstance", child->key) == 0) status = mr_config_add_regex(&m->type_instance, child); + else if (strcasecmp("MetaData", child->key) == 0) + status = mr_config_add_meta_regex(&m->meta, child); else if (strcasecmp("Invert", child->key) == 0) status = cf_util_get_boolean(child, &m->invert); else { @@ -215,7 +281,7 @@ static int mr_create(const oconfig_item_t *ci, void **user_data) /* {{{ */ while (status == 0) { if ((m->host == NULL) && (m->plugin == NULL) && (m->plugin_instance == NULL) && (m->type == NULL) && - (m->type_instance == NULL)) { + (m->type_instance == NULL) && (m->meta == NULL)) { log_err("No (valid) regular expressions have been configured. " "This match will be ignored."); status = -1; @@ -226,18 +292,18 @@ static int mr_create(const oconfig_item_t *ci, void **user_data) /* {{{ */ if (status != 0) { mr_free_match(m); - return (status); + return status; } *user_data = m; - return (0); + return 0; } /* }}} int mr_create */ static int mr_destroy(void **user_data) /* {{{ */ { if ((user_data != NULL) && (*user_data != NULL)) mr_free_match(*user_data); - return (0); + return 0; } /* }}} int mr_destroy */ static int mr_match(const data_set_t __attribute__((unused)) * ds, /* {{{ */ @@ -249,7 +315,7 @@ static int mr_match(const data_set_t __attribute__((unused)) * ds, /* {{{ */ int nomatch_value = FC_MATCH_NO_MATCH; if ((user_data == NULL) || (*user_data == NULL)) - return (-1); + return -1; m = *user_data; @@ -259,19 +325,35 @@ static int mr_match(const data_set_t __attribute__((unused)) * ds, /* {{{ */ } if (mr_match_regexen(m->host, vl->host) == FC_MATCH_NO_MATCH) - return (nomatch_value); + return nomatch_value; if (mr_match_regexen(m->plugin, vl->plugin) == FC_MATCH_NO_MATCH) - return (nomatch_value); + return nomatch_value; if (mr_match_regexen(m->plugin_instance, vl->plugin_instance) == FC_MATCH_NO_MATCH) - return (nomatch_value); + return nomatch_value; if (mr_match_regexen(m->type, vl->type) == FC_MATCH_NO_MATCH) - return (nomatch_value); + return nomatch_value; if (mr_match_regexen(m->type_instance, vl->type_instance) == FC_MATCH_NO_MATCH) - return (nomatch_value); + return nomatch_value; + if (vl->meta != NULL) { + for (llentry_t *e = llist_head(m->meta); e != NULL; e = e->next) { + mr_regex_t *meta_re = (mr_regex_t *)e->value; + char *value; + int status = meta_data_get_string(vl->meta, e->key, &value); + if (status == (-ENOENT)) /* key is not present */ + return nomatch_value; + if (status != 0) /* some other problem */ + continue; /* error will have already been printed. */ + if (mr_match_regexen(meta_re, value) == FC_MATCH_NO_MATCH) { + sfree(value); + return nomatch_value; + } + sfree(value); + } + } - return (match_value); + return match_value; } /* }}} int mr_match */ void module_register(void) { @@ -282,5 +364,3 @@ void module_register(void) { mproc.match = mr_match; fc_register_match("regex", mproc); } /* module_register */ - -/* vim: set sw=4 ts=4 tw=78 noexpandtab fdm=marker : */