Code

store: Added child matchers.
authorSebastian Harl <sh@tokkee.org>
Tue, 14 Oct 2014 21:44:19 +0000 (23:44 +0200)
committerSebastian Harl <sh@tokkee.org>
Tue, 14 Oct 2014 21:44:19 +0000 (23:44 +0200)
A child matcher matches an object's children of a certain type. It applies
another matcher to all children and matches if any of the children matches.

src/core/store-private.h
src/core/store_lookup.c
src/include/core/store.h

index 4f9b9b59f71d4d103540020ed2dba04cc09a7a5a..b8f27e25e20ff0f7af2c34f7a98ba9df93f4728c 100644 (file)
@@ -143,6 +143,9 @@ enum {
        MATCHER_NOT,
        MATCHER_NAME,
        MATCHER_ATTR,
+       MATCHER_SERVICE,
+       MATCHER_METRIC,
+       MATCHER_ATTRIBUTE,
        MATCHER_LT,
        MATCHER_LE,
        MATCHER_EQ,
@@ -162,6 +165,9 @@ enum {
                : ((t) == MATCHER_NOT) ? "NOT" \
                : ((t) == MATCHER_NAME) ? "NAME" \
                : ((t) == MATCHER_ATTR) ? "ATTR" \
+               : ((t) == MATCHER_SERVICE) ? "SERVICE" \
+               : ((t) == MATCHER_METRIC) ? "METRIC" \
+               : ((t) == MATCHER_ATTRIBUTE) ? "ATTRIBUTE" \
                : ((t) == MATCHER_LT) ? "<" \
                : ((t) == MATCHER_LE) ? "<=" \
                : ((t) == MATCHER_EQ) ? "=" \
@@ -203,6 +209,13 @@ typedef struct {
 } uop_matcher_t;
 #define UOP_M(m) ((uop_matcher_t *)(m))
 
+/* child matcher */
+typedef struct {
+       sdb_store_matcher_t super;
+       sdb_store_matcher_t *m;
+} child_matcher_t;
+#define CHILD_M(m) ((child_matcher_t *)(m))
+
 /* compare operator matcher */
 typedef struct {
        sdb_store_matcher_t super;
index 4e777d863f2dbed1a2433da46bf27bd8e62c55e9..9968aba468eab75c8dfc8b4da86c915504c1c3e9 100644 (file)
@@ -286,6 +286,43 @@ match_attr(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
        return 0;
 } /* match_attr */
 
+static int
+match_child(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
+               sdb_store_matcher_t *filter)
+{
+       sdb_avltree_iter_t *iter = NULL;
+       int status = 0;
+
+       assert((m->type == MATCHER_SERVICE)
+                       || (m->type == MATCHER_METRIC)
+                       || (m->type == MATCHER_ATTRIBUTE));
+
+       /* TODO: support all object types */
+       if (obj->type != SDB_HOST)
+               return 0;
+
+       if (m->type == MATCHER_SERVICE)
+               iter = sdb_avltree_get_iter(HOST(obj)->services);
+       else if (m->type == MATCHER_METRIC)
+               iter = sdb_avltree_get_iter(HOST(obj)->metrics);
+       else if (m->type == SDB_ATTRIBUTE)
+               iter = sdb_avltree_get_iter(HOST(obj)->attributes);
+
+       while (sdb_avltree_iter_has_next(iter)) {
+               sdb_object_t *child = sdb_avltree_iter_get_next(iter);
+               if (filter && (! sdb_store_matcher_matches(filter,
+                                               STORE_OBJ(child), NULL)))
+                       continue;
+
+               if (sdb_store_matcher_matches(CHILD_M(m)->m, obj, filter)) {
+                       status = 1;
+                       break;
+               }
+       }
+       sdb_avltree_iter_destroy(iter);
+       return status;
+} /* match_child */
+
 static int
 match_lt(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
                sdb_store_matcher_t *filter)
@@ -440,6 +477,9 @@ matchers[] = {
        match_unary,
        match_name,
        match_attr,
+       match_child,
+       match_child,
+       match_child,
        match_lt,
        match_le,
        match_eq,
@@ -731,6 +771,35 @@ op_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
        return buf;
 } /* op_tostring */
 
+static int
+child_matcher_init(sdb_object_t *obj, va_list ap)
+{
+       M(obj)->type = va_arg(ap, int);
+       CHILD_M(obj)->m = va_arg(ap, sdb_store_matcher_t *);
+
+       if (! CHILD_M(obj)->m)
+               return -1;
+
+       sdb_object_ref(SDB_OBJ(CHILD_M(obj)->m));
+       return 0;
+} /* child_matcher_init */
+
+static void
+child_matcher_destroy(sdb_object_t *obj)
+{
+       sdb_object_deref(SDB_OBJ(CHILD_M(obj)->m));
+} /* child_matcher_destroy */
+
+static char *
+child_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
+{
+       snprintf(buf, buflen, "%s:", MATCHER_SYM(m->type));
+       buf[buflen - 1] = '\0';
+       sdb_store_matcher_tostring(CHILD_M(m)->m,
+                       buf + strlen(buf), buflen - strlen(buf));
+       return buf;
+} /* child_tostring */
+
 static int
 cmp_matcher_init(sdb_object_t *obj, va_list ap)
 {
@@ -869,6 +938,12 @@ static sdb_type_t uop_type = {
        /* destroy = */ uop_matcher_destroy,
 };
 
+static sdb_type_t child_type = {
+       /* size = */ sizeof(child_matcher_t),
+       /* init = */ child_matcher_init,
+       /* destroy = */ child_matcher_destroy,
+};
+
 static sdb_type_t cmp_type = {
        /* size = */ sizeof(cmp_matcher_t),
        /* init = */ cmp_matcher_init,
@@ -892,6 +967,9 @@ matchers_tostring[] = {
        uop_tostring,
        name_tostring,
        attr_tostring,
+       child_tostring,
+       child_tostring,
+       child_tostring,
        cond_tostring,
        cond_tostring,
        cond_tostring,
@@ -957,6 +1035,20 @@ sdb_store_attr_matcher(const char *name, const char *value, _Bool re)
        return m;
 } /* sdb_store_attr_matcher */
 
+sdb_store_matcher_t *
+sdb_store_child_matcher(int type, sdb_store_matcher_t *m)
+{
+       if (type == SDB_SERVICE)
+               type = MATCHER_SERVICE;
+       else if (type == SDB_METRIC)
+               type = MATCHER_METRIC;
+       else if (type == SDB_ATTRIBUTE)
+               type = MATCHER_ATTRIBUTE;
+       else
+               return NULL;
+       return M(sdb_object_create("any-matcher", child_type, type, m));
+} /* sdb_store_child_matcher */
+
 sdb_store_matcher_t *
 sdb_store_lt_matcher(sdb_store_cond_t *cond)
 {
index e3b3387151ef38b66ec7f32f745304abaff10391..9304acfa79e1f7761928a76dad17e161d02db09f 100644 (file)
@@ -411,6 +411,14 @@ sdb_store_attr_matcher(const char *name, const char *value, _Bool re);
 sdb_store_matcher_t *
 sdb_store_isnull_matcher(const char *attr_name);
 
+/*
+ * sdb_store_child_matcher:
+ * Creates a matcher matching an object's children of the specified type. It
+ * matches if *any* of those children match 'm'.
+ */
+sdb_store_matcher_t *
+sdb_store_child_matcher(int type, sdb_store_matcher_t *m);
+
 /*
  * sdb_store_lt_matcher, sdb_store_le_matcher, sdb_store_eq_matcher,
  * sdb_store_ge_matcher, sdb_store_gt_matcher: