Code

core: Don't leak memory when shutting down the collector loop.
[sysdb.git] / src / core / store_lookup.c
index d43b9e32c764c10e0a372dabd71a79d3d30668f2..2affaa986f869e3c7514761857653203c291fefa 100644 (file)
@@ -103,6 +103,106 @@ match_name(name_matcher_t *m, const char *name)
        return 1;
 } /* match_name */
 
+static char *
+name_tostring(name_matcher_t *m, char *buf, size_t buflen)
+{
+       snprintf(buf, buflen, "{ %s%s%s, %p }",
+                       m->name ? "'" : "", m->name ? m->name : "NULL", m->name ? "'" : "",
+                       m->name_re);
+       return buf;
+} /* name_tostring */
+
+static char *
+logical_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
+{
+       char left[buflen + 1], right[buflen + 1];
+
+       if (! m) {
+               /* this should not happen */
+               snprintf(buf, buflen, "()");
+               return buf;
+       }
+
+       assert((m->type == MATCHER_OR) || (m->type == MATCHER_AND));
+       snprintf(buf, buflen, "(%s, %s, %s)",
+                       m->type == MATCHER_OR ? "OR" : "AND",
+                       sdb_store_matcher_tostring(OP_M(m)->left, left, sizeof(left)),
+                       sdb_store_matcher_tostring(OP_M(m)->right, right, sizeof(right)));
+       return buf;
+} /* logical_tostring */
+
+static char *
+unary_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
+{
+       char op[buflen + 1];
+
+       if (! m) {
+               /* this should not happen */
+               snprintf(buf, buflen, "()");
+               return buf;
+       }
+
+       assert(m->type == MATCHER_NOT);
+       snprintf(buf, buflen, "(NOT, %s)",
+                       sdb_store_matcher_tostring(UOP_M(m)->op, op, sizeof(op)));
+       return buf;
+} /* unary_tostring */
+
+static char *
+attr_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
+{
+       char name[buflen + 1], value[buflen + 1];
+
+       if (! m) {
+               snprintf(buf, buflen, "ATTR{}");
+               return buf;
+       }
+
+       assert(m->type == MATCHER_ATTR);
+       snprintf(buf, buflen, "ATTR{ NAME%s, VALUE%s }",
+                       name_tostring(&OBJ_M(m)->name, name, sizeof(name)),
+                       name_tostring(&ATTR_M(m)->value, value, sizeof(value)));
+       return buf;
+} /* attr_tostring */
+
+static char *
+service_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
+{
+       char name[buflen + 1], attr[buflen + 1];
+
+       if (! m) {
+               snprintf(buf, buflen, "SERVICE{}");
+               return buf;
+       }
+
+       assert(m->type == MATCHER_SERVICE);
+       snprintf(buf, buflen, "SERVICE{ NAME%s, %s }",
+                       name_tostring(&OBJ_M(m)->name, name, sizeof(name)),
+                       attr_tostring(SDB_STORE_MATCHER(SERVICE_M(m)->attr),
+                               attr, sizeof(attr)));
+       return buf;
+} /* service_tostring */
+
+static char *
+host_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
+{
+       char name[buflen + 1], service[buflen + 1], attr[buflen + 1];
+
+       if (! m) {
+               snprintf(buf, buflen, "HOST{}");
+               return buf;
+       }
+
+       assert(m->type == MATCHER_HOST);
+       snprintf(buf, buflen, "HOST{ NAME%s, %s, %s }",
+                       name_tostring(&OBJ_M(m)->name, name, sizeof(name)),
+                       service_tostring(SDB_STORE_MATCHER(HOST_M(m)->service),
+                               service, sizeof(service)),
+                       attr_tostring(SDB_STORE_MATCHER(HOST_M(m)->attr),
+                               attr, sizeof(attr)));
+       return buf;
+} /* host_tostring */
+
 /* match attribute specific values;
  * always call this function through match_obj() */
 static int
@@ -218,6 +318,17 @@ static matcher_cb matchers[] = {
        match_obj,
 };
 
+typedef char *(*matcher_tostring_cb)(sdb_store_matcher_t *, char *, size_t);
+
+static matcher_tostring_cb matchers_tostring[] = {
+       logical_tostring,
+       logical_tostring,
+       unary_tostring,
+       attr_tostring,
+       service_tostring,
+       host_tostring,
+};
+
 static int
 match_logical(sdb_store_matcher_t *m, sdb_store_base_t *obj)
 {
@@ -514,6 +625,9 @@ sdb_store_matcher_parse_cmp(const char *obj_type, const char *attr,
                const char *op, const char *value)
 {
        int typ = -1;
+       int inv = 0;
+
+       sdb_store_matcher_t *m = NULL;
 
        const char *matcher = NULL;
        const char *matcher_re = NULL;
@@ -526,10 +640,20 @@ sdb_store_matcher_parse_cmp(const char *obj_type, const char *attr,
                typ = SDB_ATTRIBUTE;
 
        /* TODO: support other operators */
-       if (! strcasecmp(op, "="))
+       if (! strcasecmp(op, "=")) {
                matcher = value;
-       else if (! strcasecmp(op, "=~"))
+       }
+       else if (! strcasecmp(op, "!=")) {
+               matcher = value;
+               inv = 1;
+       }
+       else if (! strcasecmp(op, "=~")) {
                matcher_re = value;
+       }
+       else if (! strcasecmp(op, "!~")) {
+               matcher_re = value;
+               inv = 1;
+       }
        else
                return NULL;
 
@@ -537,17 +661,41 @@ sdb_store_matcher_parse_cmp(const char *obj_type, const char *attr,
                /* accept */
        }
        else if (typ == SDB_ATTRIBUTE)
-               return sdb_store_attr_matcher(attr, NULL, matcher, matcher_re);
+               m = sdb_store_host_matcher(/* name = */ NULL, NULL,
+                               /* service = */ NULL,
+                               sdb_store_attr_matcher(attr, NULL, matcher, matcher_re));
        else
                return NULL;
 
-       if (typ == SDB_HOST)
-               return sdb_store_host_matcher(matcher, matcher_re, NULL, NULL);
+       if (m) {
+               /* accept the attribute value matcher */
+       }
+       else if (typ == SDB_HOST)
+               m = sdb_store_host_matcher(matcher, matcher_re, NULL, NULL);
        else if (typ == SDB_SERVICE)
-               return sdb_store_service_matcher(matcher, matcher_re, NULL);
+               m = sdb_store_host_matcher(/* name = */ NULL, NULL,
+                               sdb_store_service_matcher(matcher, matcher_re, NULL),
+                               /* attr = */ NULL);
        else if (typ == SDB_ATTRIBUTE)
-               return sdb_store_attr_matcher(matcher, matcher_re, NULL, NULL);
-       return NULL;
+               m = sdb_store_host_matcher(/* name = */ NULL, NULL,
+                               /* service = */ NULL,
+                               sdb_store_attr_matcher(matcher, matcher_re, NULL, NULL));
+
+       if (! m)
+               return NULL;
+
+       /* pass ownership to the host matcher */
+       sdb_object_deref(SDB_OBJ(HOST_M(m)->service));
+       sdb_object_deref(SDB_OBJ(HOST_M(m)->attr));
+
+       if (inv) {
+               sdb_store_matcher_t *tmp;
+               tmp = sdb_store_inv_matcher(m);
+               /* pass ownership to the inverse matcher */
+               sdb_object_deref(SDB_OBJ(m));
+               m = tmp;
+       }
+       return m;
 } /* sdb_store_matcher_parse_cmp */
 
 sdb_store_matcher_t *
@@ -583,6 +731,18 @@ sdb_store_matcher_matches(sdb_store_matcher_t *m, sdb_store_base_t *obj)
        return matchers[m->type](m, obj);
 } /* sdb_store_matcher_matches */
 
+char *
+sdb_store_matcher_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
+{
+       if (! m)
+               return NULL;
+
+       if ((m->type < 0)
+                       || (((size_t)m->type >= SDB_STATIC_ARRAY_LEN(matchers_tostring))))
+               return NULL;
+       return matchers_tostring[m->type](m, buf, buflen);
+} /* sdb_store_matcher_tostring */
+
 int
 sdb_store_lookup(sdb_store_matcher_t *m, sdb_store_lookup_cb cb,
                void *user_data)