From: Sebastian Harl Date: Mon, 28 Jul 2014 21:36:05 +0000 (+0200) Subject: store: Make matchers more generic and applicable to non-hosts as well. X-Git-Tag: sysdb-0.3.0~21 X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=commitdiff_plain;h=3da6e0cdfaba4755f5d272100e95528d33aae322 store: Make matchers more generic and applicable to non-hosts as well. Most of the matchers are actually not specific to hosts and may be re-used for different purposes (e.g. filters). Make them applicable to arbitrary object types (again) and only check for the right object type when actually needed. Added simple unit-tests covering filters applied to all types of objects. --- diff --git a/src/core/store-private.h b/src/core/store-private.h index 703bc55..0df3c7b 100644 --- a/src/core/store-private.h +++ b/src/core/store-private.h @@ -95,9 +95,9 @@ typedef struct { * conditionals */ -/* compares a host using the specified conditional and taking the specified +/* compares an object using the specified conditional and taking the specified * filter into account */ -typedef int (*cmp_cb)(sdb_host_t *, sdb_store_cond_t *, +typedef int (*cmp_cb)(sdb_store_obj_t *, sdb_store_cond_t *, sdb_store_matcher_t *); struct sdb_store_cond { diff --git a/src/core/store_lookup.c b/src/core/store_lookup.c index ac0f2e8..ed58591 100644 --- a/src/core/store_lookup.c +++ b/src/core/store_lookup.c @@ -104,17 +104,20 @@ attr_get(sdb_host_t *host, const char *name, sdb_store_matcher_t *filter) */ static int -attr_cmp(sdb_host_t *host, sdb_store_cond_t *cond, +attr_cmp(sdb_store_obj_t *obj, sdb_store_cond_t *cond, sdb_store_matcher_t *filter) { sdb_attribute_t *attr; sdb_data_t value = SDB_DATA_INIT; int status; + if (obj->type != SDB_HOST) + return INT_MAX; + if (sdb_store_expr_eval(ATTR_C(cond)->expr, &value)) return INT_MAX; - attr = attr_get(host, ATTR_C(cond)->name, filter); + attr = attr_get(HOST(obj), ATTR_C(cond)->name, filter); if (! attr) status = INT_MAX; else if (attr->value.type != value.type) @@ -147,7 +150,7 @@ match_string(string_matcher_t *m, const char *name) } /* match_string */ static int -match_logical(sdb_store_matcher_t *m, sdb_host_t *host, +match_logical(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { int status; @@ -155,8 +158,7 @@ match_logical(sdb_store_matcher_t *m, sdb_host_t *host, assert((m->type == MATCHER_AND) || (m->type == MATCHER_OR)); assert(OP_M(m)->left && OP_M(m)->right); - status = sdb_store_matcher_matches(OP_M(m)->left, STORE_OBJ(host), - filter); + status = sdb_store_matcher_matches(OP_M(m)->left, obj, filter); /* lazy evaluation */ if ((! status) && (m->type == MATCHER_AND)) @@ -164,21 +166,21 @@ match_logical(sdb_store_matcher_t *m, sdb_host_t *host, else if (status && (m->type == MATCHER_OR)) return status; - return sdb_store_matcher_matches(OP_M(m)->right, STORE_OBJ(host), filter); + return sdb_store_matcher_matches(OP_M(m)->right, obj, filter); } /* match_logical */ static int -match_unary(sdb_store_matcher_t *m, sdb_host_t *host, +match_unary(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { assert(m->type == MATCHER_NOT); assert(UOP_M(m)->op); - return !sdb_store_matcher_matches(UOP_M(m)->op, STORE_OBJ(host), filter); + return !sdb_store_matcher_matches(UOP_M(m)->op, obj, filter); } /* match_unary */ static int -match_name(sdb_store_matcher_t *m, sdb_host_t *host, +match_name(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { sdb_avltree_iter_t *iter = NULL; @@ -186,15 +188,17 @@ match_name(sdb_store_matcher_t *m, sdb_host_t *host, assert(m->type == MATCHER_NAME); + if (obj->type == NAME_M(m)->obj_type) + return match_string(&NAME_M(m)->name, SDB_OBJ(obj)->name); + else if (obj->type != SDB_HOST) + return 0; + switch (NAME_M(m)->obj_type) { - case SDB_HOST: - return match_string(&NAME_M(m)->name, SDB_OBJ(host)->name); - break; case SDB_SERVICE: - iter = sdb_avltree_get_iter(host->services); + iter = sdb_avltree_get_iter(HOST(obj)->services); break; case SDB_ATTRIBUTE: - iter = sdb_avltree_get_iter(host->attributes); + iter = sdb_avltree_get_iter(HOST(obj)->attributes); break; } @@ -213,7 +217,7 @@ match_name(sdb_store_matcher_t *m, sdb_host_t *host, } /* match_name */ static int -match_attr(sdb_store_matcher_t *m, sdb_host_t *host, +match_attr(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { sdb_attribute_t *attr; @@ -221,7 +225,10 @@ match_attr(sdb_store_matcher_t *m, sdb_host_t *host, assert(m->type == MATCHER_ATTR); assert(ATTR_M(m)->name); - attr = attr_get(host, ATTR_M(m)->name, filter); + if (obj->type != SDB_HOST) + return 0; + + attr = attr_get(HOST(obj), ATTR_M(m)->name, filter); if (attr) { char buf[sdb_data_strlen(&attr->value) + 1]; if (sdb_data_format(&attr->value, buf, sizeof(buf), SDB_UNQUOTED) <= 0) @@ -233,64 +240,66 @@ match_attr(sdb_store_matcher_t *m, sdb_host_t *host, } /* match_attr */ static int -match_lt(sdb_store_matcher_t *m, sdb_host_t *host, +match_lt(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { int status; assert(m->type == MATCHER_LT); - status = COND_M(m)->cond->cmp(host, COND_M(m)->cond, filter); + status = COND_M(m)->cond->cmp(obj, COND_M(m)->cond, filter); return (status != INT_MAX) && (status < 0); } /* match_lt */ static int -match_le(sdb_store_matcher_t *m, sdb_host_t *host, +match_le(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { int status; assert(m->type == MATCHER_LE); - status = COND_M(m)->cond->cmp(host, COND_M(m)->cond, filter); + status = COND_M(m)->cond->cmp(obj, COND_M(m)->cond, filter); return (status != INT_MAX) && (status <= 0); } /* match_le */ static int -match_eq(sdb_store_matcher_t *m, sdb_host_t *host, +match_eq(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { int status; assert(m->type == MATCHER_EQ); - status = COND_M(m)->cond->cmp(host, COND_M(m)->cond, filter); + status = COND_M(m)->cond->cmp(obj, COND_M(m)->cond, filter); return (status != INT_MAX) && (! status); } /* match_eq */ static int -match_ge(sdb_store_matcher_t *m, sdb_host_t *host, +match_ge(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { int status; assert(m->type == MATCHER_GE); - status = COND_M(m)->cond->cmp(host, COND_M(m)->cond, filter); + status = COND_M(m)->cond->cmp(obj, COND_M(m)->cond, filter); return (status != INT_MAX) && (status >= 0); } /* match_ge */ static int -match_gt(sdb_store_matcher_t *m, sdb_host_t *host, +match_gt(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { int status; assert(m->type == MATCHER_GT); - status = COND_M(m)->cond->cmp(host, COND_M(m)->cond, filter); + status = COND_M(m)->cond->cmp(obj, COND_M(m)->cond, filter); return (status != INT_MAX) && (status > 0); } /* match_gt */ static int -match_isnull(sdb_store_matcher_t *m, sdb_host_t *host, +match_isnull(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { assert(m->type == MATCHER_ISNULL); - return attr_get(host, ISNULL_M(m)->attr_name, filter) == NULL; + if (obj->type != SDB_HOST) + return 0; + return attr_get(HOST(obj), ISNULL_M(m)->attr_name, filter) == NULL; } /* match_isnull */ -typedef int (*matcher_cb)(sdb_store_matcher_t *, sdb_host_t *, +typedef int (*matcher_cb)(sdb_store_matcher_t *, sdb_store_obj_t *, sdb_store_matcher_t *); /* this array needs to be indexable by the matcher types; @@ -910,9 +919,6 @@ int sdb_store_matcher_matches(sdb_store_matcher_t *m, sdb_store_obj_t *obj, sdb_store_matcher_t *filter) { - if (obj->type != SDB_HOST) - return 0; - if (filter && (! sdb_store_matcher_matches(filter, obj, NULL))) return 0; @@ -923,7 +929,7 @@ sdb_store_matcher_matches(sdb_store_matcher_t *m, sdb_store_obj_t *obj, if ((m->type < 0) || ((size_t)m->type >= SDB_STATIC_ARRAY_LEN(matchers))) return 0; - return matchers[m->type](m, HOST(obj), filter); + return matchers[m->type](m, obj, filter); } /* sdb_store_matcher_matches */ char * diff --git a/t/unit/core/store_lookup_test.c b/t/unit/core/store_lookup_test.c index c6eeb6b..1adece5 100644 --- a/t/unit/core/store_lookup_test.c +++ b/t/unit/core/store_lookup_test.c @@ -539,10 +539,10 @@ START_TEST(test_scan) } golden_data[] = { { "host = 'a'", NULL, 1, "OBJ\\[host\\]\\{ NAME\\{ 'a', \\(nil\\) \\} \\}" }, - { "host = 'a'", "host = 'b'", 0, + { "host = 'a'", "host = 'x'", 0, /* filter never matches */ "OBJ\\[host\\]\\{ NAME\\{ 'a', \\(nil\\) \\} \\}" }, { "host = 'a'", - "attribute.x IS NULL", 1, + "NOT attribute.x = ''", 1, /* filter always matches */ "OBJ\\[host\\]\\{ NAME\\{ 'a', \\(nil\\) \\} \\}" }, { "host =~ 'a|b'", NULL, 2, "OBJ\\[host\\]\\{ NAME\\{ NULL, "PTR_RE" \\} \\}" }, @@ -552,12 +552,22 @@ START_TEST(test_scan) "OBJ\\[host\\]\\{ NAME\\{ NULL, "PTR_RE" \\} \\}" }, { "service = 's1'", NULL, 2, "OBJ\\[service\\]\\{ NAME\\{ 's1', \\(nil\\) } \\}" }, + { "service = 's1'", "host = 'x'", 0, /* filter never matches */ + "OBJ\\[service\\]\\{ NAME\\{ 's1', \\(nil\\) } \\}" }, + { "service = 's1'", + "NOT attribute.x = ''", 2, /* filter always matches */ + "OBJ\\[service\\]\\{ NAME\\{ 's1', \\(nil\\) } \\}" }, { "service =~ 's'", NULL, 2, "OBJ\\[service\\]\\{ NAME\\{ NULL, "PTR_RE" } \\}" }, { "service !~ 's'", NULL, 1, "\\(NOT, OBJ\\[service\\]\\{ NAME\\{ NULL, "PTR_RE" } \\}\\)" }, { "attribute = 'k1'", NULL, 1, "OBJ\\[attribute\\]\\{ NAME\\{ 'k1', \\(nil\\) \\} " }, + { "attribute = 'k1'", "host = 'x'", 0, /* filter never matches */ + "OBJ\\[attribute\\]\\{ NAME\\{ 'k1', \\(nil\\) \\} " }, + { "attribute = 'k1'", + "NOT attribute.x = ''", 1, /* filter always matches */ + "OBJ\\[attribute\\]\\{ NAME\\{ 'k1', \\(nil\\) \\} " }, { "attribute = 'x'", NULL, 0, "OBJ\\[attribute\\]\\{ NAME\\{ 'x', \\(nil\\) \\}" }, { "attribute.k1 = 'v1'", NULL, 1, @@ -630,9 +640,9 @@ START_TEST(test_scan) n = 0; sdb_store_scan(m, filter, scan_cb, &n); fail_unless(n == golden_data[i].expected, - "sdb_store_scan(matcher{%s}, filter{NULL}) found %d hosts; " - "expected: %d", golden_data[i].query, n, - golden_data[i].expected); + "sdb_store_scan(matcher{%s}, filter{%s}) found %d hosts; " + "expected: %d", golden_data[i].query, golden_data[i].filter, + n, golden_data[i].expected); sdb_object_deref(SDB_OBJ(filter)); sdb_object_deref(SDB_OBJ(m)); }