From 22aa3b95ef9e01872eb7bd645c8dfea723b9c9d2 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Tue, 14 Oct 2014 22:45:07 +0200 Subject: [PATCH] store: Apply filters when evaluating attribute values or expressions. --- src/core/store.c | 7 ++++- src/core/store_expr.c | 11 +++++--- src/core/store_lookup.c | 12 ++++---- src/include/core/store.h | 60 +++++++++++++++++++++------------------- 4 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/core/store.c b/src/core/store.c index db8a9d9..81aedfb 100644 --- a/src/core/store.c +++ b/src/core/store.c @@ -932,7 +932,8 @@ sdb_store_get_field(sdb_store_obj_t *obj, int field, sdb_data_t *res) } /* sdb_store_get_field */ int -sdb_store_get_attr(sdb_store_obj_t *obj, const char *name, sdb_data_t *res) +sdb_store_get_attr(sdb_store_obj_t *obj, const char *name, sdb_data_t *res, + sdb_store_matcher_t *filter) { sdb_avltree_t *tree = NULL; sdb_avltree_iter_t *iter = NULL; @@ -957,6 +958,10 @@ sdb_store_get_attr(sdb_store_obj_t *obj, const char *name, sdb_data_t *res) if (strcasecmp(SDB_OBJ(attr)->name, name)) continue; + if (filter&& (! sdb_store_matcher_matches(filter, + STORE_OBJ(attr), NULL))) + break; /* found it but it's filtered */ + assert(STORE_OBJ(attr)->type == SDB_ATTRIBUTE); if (res) sdb_data_copy(res, &ATTR(attr)->value); diff --git a/src/core/store_expr.c b/src/core/store_expr.c index ca7b72b..4e8bae7 100644 --- a/src/core/store_expr.c +++ b/src/core/store_expr.c @@ -182,7 +182,7 @@ sdb_store_expr_constvalue(const sdb_data_t *value) int sdb_store_expr_eval(sdb_store_expr_t *expr, sdb_store_obj_t *obj, - sdb_data_t *res) + sdb_data_t *res, sdb_store_matcher_t *filter) { sdb_data_t v1 = SDB_DATA_INIT, v2 = SDB_DATA_INIT; int status = 0; @@ -190,16 +190,19 @@ sdb_store_expr_eval(sdb_store_expr_t *expr, sdb_store_obj_t *obj, if ((! expr) || (! res)) return -1; + if (filter && obj && (! sdb_store_matcher_matches(filter, obj, NULL))) + obj = NULL; /* this object does not exist */ + if (! expr->type) return sdb_data_copy(res, &expr->data); else if (expr->type == FIELD_VALUE) return sdb_store_get_field(obj, (int)expr->data.data.integer, res); else if (expr->type == ATTR_VALUE) - return sdb_store_get_attr(obj, expr->data.data.string, res); + return sdb_store_get_attr(obj, expr->data.data.string, res, filter); - if (sdb_store_expr_eval(expr->left, obj, &v1)) + if (sdb_store_expr_eval(expr->left, obj, &v1, filter)) return -1; - if (sdb_store_expr_eval(expr->right, obj, &v2)) { + if (sdb_store_expr_eval(expr->right, obj, &v2, filter)) { sdb_data_free_datum(&v1); return -1; } diff --git a/src/core/store_lookup.c b/src/core/store_lookup.c index 0c9d361..dc3e499 100644 --- a/src/core/store_lookup.c +++ b/src/core/store_lookup.c @@ -114,7 +114,7 @@ attr_cmp(sdb_store_obj_t *obj, sdb_store_cond_t *cond, if (obj->type != SDB_HOST) return INT_MAX; - if (sdb_store_expr_eval(ATTR_C(cond)->expr, obj, &value)) + if (sdb_store_expr_eval(ATTR_C(cond)->expr, obj, &value, filter)) return INT_MAX; attr = attr_get(HOST(obj), ATTR_C(cond)->name, filter); @@ -130,13 +130,13 @@ attr_cmp(sdb_store_obj_t *obj, sdb_store_cond_t *cond, static int obj_cmp(sdb_store_obj_t *obj, sdb_store_cond_t *cond, - sdb_store_matcher_t __attribute__((unused)) *filter) + sdb_store_matcher_t *filter) { sdb_data_t obj_value = SDB_DATA_INIT; sdb_data_t value = SDB_DATA_INIT; int status; - if (sdb_store_expr_eval(OBJ_C(cond)->expr, obj, &value)) + if (sdb_store_expr_eval(OBJ_C(cond)->expr, obj, &value, filter)) return INT_MAX; if (OBJ_C(cond)->field == SDB_FIELD_BACKEND) { @@ -588,7 +588,7 @@ cond_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen) return buf; } - if (sdb_store_expr_eval(expr, NULL, &value)) + if (sdb_store_expr_eval(expr, /* obj */ NULL, &value, /* filter */ NULL)) snprintf(value_str, sizeof(value_str), "ERR"); else if (sdb_data_format(&value, value_str, sizeof(value_str), SDB_SINGLE_QUOTED) < 0) @@ -1007,8 +1007,8 @@ sdb_store_matcher_parse_cmp(const char *obj_type, const char *attr, if (! expr) return NULL; - if (sdb_store_expr_eval(expr, NULL, &value) || - (value.type != SDB_TYPE_STRING)) { + if (sdb_store_expr_eval(expr, /* obj */ NULL, &value, /* filter */ NULL) + || (value.type != SDB_TYPE_STRING)) { sdb_data_free_datum(&value); if (type != SDB_ATTRIBUTE) return NULL; diff --git a/src/include/core/store.h b/src/include/core/store.h index b9a8d08..c0a9849 100644 --- a/src/include/core/store.h +++ b/src/include/core/store.h @@ -64,6 +64,30 @@ enum { struct sdb_store_obj; typedef struct sdb_store_obj sdb_store_obj_t; +/* + * Expressions represent arithmetic expressions based on stored objects and + * their various attributes. + * + * An expression object inherits from sdb_object_t and, thus, may safely be + * cast to a generic object. + */ +struct sdb_store_expr; +typedef struct sdb_store_expr sdb_store_expr_t; +#define SDB_STORE_EXPR(obj) ((sdb_store_expr_t *)(obj)) + +/* + * Store matchers may be used to lookup hosts from the store based on their + * various attributes. Service and attribute matchers are applied to a host's + * services and attributes and evaluate to true if *any* service or attribute + * matches. + * + * A store matcher object inherits from sdb_object_t and, thus, may safely be + * cast to a generic object. + */ +struct sdb_store_matcher; +typedef struct sdb_store_matcher sdb_store_matcher_t; +#define SDB_STORE_MATCHER(obj) ((sdb_store_matcher_t *)(obj)) + /* * Queryable fields of a stored object. */ @@ -257,25 +281,17 @@ sdb_store_get_field(sdb_store_obj_t *obj, int field, sdb_data_t *res); * sdb_store_get_attr: * Get the value of a stored object's attribute. The caller is responsible for * freeing any dynamically allocated memory possibly stored in the returned - * value.If 'res' is NULL, the function will return whether the attribute - * exists. + * value. If 'res' is NULL, the function will return whether the attribute + * exists. If specified, only attributes matching the filter will be + * considered. * * Returns: * - 0 if the attribute exists * - a negative value else */ int -sdb_store_get_attr(sdb_store_obj_t *obj, const char *name, sdb_data_t *res); - -/* - * Expressions specify arithmetic expressions. - * - * A expression object inherits from sdb_object_t and, thus, may safely be - * cast to a generic object. - */ -struct sdb_store_expr; -typedef struct sdb_store_expr sdb_store_expr_t; -#define SDB_STORE_EXPR(obj) ((sdb_store_expr_t *)(obj)) +sdb_store_get_attr(sdb_store_obj_t *obj, const char *name, sdb_data_t *res, + sdb_store_matcher_t *filter); /* * sdb_store_expr_create: @@ -330,7 +346,8 @@ sdb_store_expr_constvalue(const sdb_data_t *value); * result in 'res'. The result's value will be allocated dynamically if * necessary and, thus, should be free'd by the caller (e.g. using * sdb_data_free_datum). The object may be NULL, in which case the expression - * needs to evaluate to a constant value. + * needs to evaluate to a constant value. If specified, only objects matching + * the filter will be used during the evaluation. * * Returns: * - 0 on success @@ -338,7 +355,7 @@ sdb_store_expr_constvalue(const sdb_data_t *value); */ int sdb_store_expr_eval(sdb_store_expr_t *expr, sdb_store_obj_t *obj, - sdb_data_t *res); + sdb_data_t *res, sdb_store_matcher_t *filter); /* * Conditionals may be used to lookup hosts from the store based on a @@ -369,19 +386,6 @@ sdb_store_attr_cond(const char *name, sdb_store_expr_t *expr); sdb_store_cond_t * sdb_store_obj_cond(int field, sdb_store_expr_t *expr); -/* - * Store matchers may be used to lookup hosts from the store based on their - * various attributes. Service and attribute matchers are applied to a host's - * services and attributes and evaluate to true if *any* service or attribute - * matches. - * - * A store matcher object inherits from sdb_object_t and, thus, may safely be - * cast to a generic object. - */ -struct sdb_store_matcher; -typedef struct sdb_store_matcher sdb_store_matcher_t; -#define SDB_STORE_MATCHER(obj) ((sdb_store_matcher_t *)(obj)) - /* * sdb_store_name_matcher: * Creates a matcher matching by the specified object type's name. If 're' is -- 2.30.2