Code

store: Added not-equal and not-regex matchers.
[sysdb.git] / src / core / store_lookup.c
index 4e777d863f2dbed1a2433da46bf27bd8e62c55e9..cb3629c89eff652d34721e33bac763415a208bf0 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)
@@ -398,6 +435,16 @@ match_cmp_eq(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
        return (status != INT_MAX) && (! status);
 } /* match_cmp_eq */
 
+static int
+match_cmp_ne(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
+               sdb_store_matcher_t *filter)
+{
+       int status;
+       assert(m->type == MATCHER_CMP_NE);
+       status = cmp_expr(CMP_M(m)->left, CMP_M(m)->right, obj, filter);
+       return (status != INT_MAX) && status;
+} /* match_cmp_ne */
+
 static int
 match_cmp_ge(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
                sdb_store_matcher_t *filter)
@@ -418,6 +465,65 @@ match_cmp_gt(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
        return (status != INT_MAX) && (status > 0);
 } /* match_cmp_gt */
 
+static int
+match_regex(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
+               sdb_store_matcher_t *filter)
+{
+       sdb_data_t v = SDB_DATA_INIT;
+       int status = 0;
+
+       regex_t regex;
+       _Bool free_regex = 0;
+
+       assert((m->type == MATCHER_REGEX)
+                       || (m->type == MATCHER_NREGEX));
+
+       if (! CMP_M(m)->right->type) {
+               assert(CMP_M(m)->right->data.type == SDB_TYPE_REGEX);
+               regex = CMP_M(m)->right->data.data.re.regex;
+       }
+       else {
+               sdb_data_t tmp = SDB_DATA_INIT;
+               char *raw;
+
+               if (sdb_store_expr_eval(CMP_M(m)->right, obj, &tmp, filter))
+                       return 0;
+
+               if (tmp.type != SDB_TYPE_STRING) {
+                       sdb_data_free_datum(&tmp);
+                       return 0;
+               }
+
+               raw = tmp.data.string;
+               if (sdb_data_parse(raw, SDB_TYPE_REGEX, &tmp)) {
+                       free(raw);
+                       return 0;
+               }
+
+               regex = tmp.data.re.regex;
+               free_regex = 1;
+               free(tmp.data.re.raw);
+               free(raw);
+       }
+
+       if (sdb_store_expr_eval(CMP_M(m)->left, obj, &v, filter))
+               status = 0;
+       else {
+               char value[sdb_data_strlen(&v) + 1];
+               if (sdb_data_format(&v, value, sizeof(value), SDB_UNQUOTED) < 0)
+                       status = 0;
+               else if (! regexec(&regex, value, 0, NULL, 0))
+                       status = 1;
+       }
+
+       if (free_regex)
+               regfree(&regex);
+       sdb_data_free_datum(&v);
+       if (m->type == MATCHER_NREGEX)
+               return !status;
+       return status;
+} /* match_regex */
+
 static int
 match_isnull(sdb_store_matcher_t *m, sdb_store_obj_t *obj,
                sdb_store_matcher_t *filter)
@@ -440,6 +546,9 @@ matchers[] = {
        match_unary,
        match_name,
        match_attr,
+       match_child,
+       match_child,
+       match_child,
        match_lt,
        match_le,
        match_eq,
@@ -448,8 +557,11 @@ matchers[] = {
        match_cmp_lt,
        match_cmp_le,
        match_cmp_eq,
+       match_cmp_ne,
        match_cmp_ge,
        match_cmp_gt,
+       match_regex,
+       match_regex,
        match_isnull,
 };
 
@@ -731,6 +843,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 +1010,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 +1039,9 @@ matchers_tostring[] = {
        uop_tostring,
        name_tostring,
        attr_tostring,
+       child_tostring,
+       child_tostring,
+       child_tostring,
        cond_tostring,
        cond_tostring,
        cond_tostring,
@@ -902,6 +1052,9 @@ matchers_tostring[] = {
        cmp_tostring,
        cmp_tostring,
        cmp_tostring,
+       cmp_tostring,
+       cmp_tostring,
+       cmp_tostring,
        isnull_tostring,
 };
 
@@ -957,6 +1110,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)
 {
@@ -1018,6 +1185,13 @@ sdb_store_cmp_eq(sdb_store_expr_t *left, sdb_store_expr_t *right)
                                MATCHER_CMP_EQ, left, right));
 } /* sdb_store_cmp_eq */
 
+sdb_store_matcher_t *
+sdb_store_cmp_ne(sdb_store_expr_t *left, sdb_store_expr_t *right)
+{
+       return M(sdb_object_create("ne-matcher", cmp_type,
+                               MATCHER_CMP_NE, left, right));
+} /* sdb_store_cmp_ne */
+
 sdb_store_matcher_t *
 sdb_store_cmp_ge(sdb_store_expr_t *left, sdb_store_expr_t *right)
 {
@@ -1032,6 +1206,35 @@ sdb_store_cmp_gt(sdb_store_expr_t *left, sdb_store_expr_t *right)
                                MATCHER_CMP_GT, left, right));
 } /* sdb_store_cmp_gt */
 
+sdb_store_matcher_t *
+sdb_store_regex_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right)
+{
+       if (! right->type) {
+               if ((right->data.type != SDB_TYPE_STRING)
+                               && (right->data.type != SDB_TYPE_REGEX))
+                       return NULL;
+
+               if (right->data.type == SDB_TYPE_STRING) {
+                       char *raw = right->data.data.string;
+                       if (sdb_data_parse(raw, SDB_TYPE_REGEX, &right->data))
+                               return NULL;
+                       free(raw);
+               }
+       }
+       return M(sdb_object_create("regex-matcher", cmp_type,
+                               MATCHER_REGEX, left, right));
+} /* sdb_store_regex_matcher */
+
+sdb_store_matcher_t *
+sdb_store_nregex_matcher(sdb_store_expr_t *left, sdb_store_expr_t *right)
+{
+       sdb_store_matcher_t *m = sdb_store_regex_matcher(left, right);
+       if (! m)
+               return NULL;
+       m->type = MATCHER_NREGEX;
+       return m;
+} /* sdb_store_nregex_matcher */
+
 sdb_store_matcher_t *
 sdb_store_isnull_matcher(const char *attr_name)
 {