summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 0f3d90a)
raw | patch | inline | side by side (parent: 0f3d90a)
author | Sebastian Harl <sh@tokkee.org> | |
Thu, 19 Jun 2014 12:22:52 +0000 (14:22 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Thu, 19 Jun 2014 12:22:52 +0000 (14:22 +0200) |
This is a generic matcher applied to hosts (or their services or attributes)
and matches based on the respective object name.
Subsequently, this will replace the more complex host/service/attribute
matchers. Instead, more basic matchers will be available which can then be
combined arbitrarily using the existing logical matchers.
and matches based on the respective object name.
Subsequently, this will replace the more complex host/service/attribute
matchers. Instead, more basic matchers will be available which can then be
combined arbitrarily using the existing logical matchers.
index 823cd18feea6731da32660130149df1d24588df5..cda98357cadaa114e0af20f956f9927dc7e9cf49 100644 (file)
--- a/src/core/store-private.h
+++ b/src/core/store-private.h
#define SDB_STORE_OBJ(obj) ((sdb_store_obj_t *)(obj))
#define SDB_CONST_STORE_OBJ(obj) ((const sdb_store_obj_t *)(obj))
-enum {
- SDB_HOST = 1,
- SDB_SERVICE,
- SDB_ATTRIBUTE,
-};
-#define TYPE_TO_NAME(t) \
- (((t) == SDB_HOST) ? "host" \
- : ((t) == SDB_SERVICE) ? "service" \
- : ((t) == SDB_ATTRIBUTE) ? "attribute" : "unknown")
-
/* shortcuts for accessing the sdb_store_obj_t attributes
* of inheriting objects */
#define _last_update super.last_update
* matchers
*/
-/* when adding to this, also update 'matchers' in store_lookup.c */
+/* when adding to this, also update 'matchers' and 'matchers_tostring'
+ * in store_lookup.c */
enum {
MATCHER_OR,
MATCHER_AND,
MATCHER_NOT,
+ MATCHER_NAME,
MATCHER_ATTR,
MATCHER_SERVICE,
MATCHER_HOST,
} uop_matcher_t;
#define UOP_M(m) ((uop_matcher_t *)(m))
-/* match any type of object by it's base information */
+/* match any type of object by it's name */
typedef struct {
sdb_store_matcher_t super;
+ int obj_type;
+
/* match by the name of the object */
name_matcher_t name;
} obj_matcher_t;
diff --git a/src/core/store.c b/src/core/store.c
index 6d9c971702b4e696ca14991eb2ea4f4e4716413c..df8c02fb152a87135c4f44464476d8d8096d5361 100644 (file)
--- a/src/core/store.c
+++ b/src/core/store.c
parent = store_lookup(parent_type, parent_name);
if (! parent) {
sdb_log(SDB_LOG_ERR, "store: Failed to store %s '%s' - "
- "parent %s '%s' not found", TYPE_TO_NAME(type), name,
- TYPE_TO_NAME(parent_type), parent_name);
+ "parent %s '%s' not found", SDB_STORE_TYPE_TO_NAME(type),
+ name, SDB_STORE_TYPE_TO_NAME(parent_type), parent_name);
free(parent_cname);
free(cname);
return -1;
if (old->last_update > last_update) {
sdb_log(SDB_LOG_DEBUG, "store: Cannot update %s '%s' - "
"value too old (%"PRIscTIME" < %"PRIscTIME")",
- TYPE_TO_NAME(type), name, last_update, old->last_update);
+ SDB_STORE_TYPE_TO_NAME(type), name,
+ last_update, old->last_update);
/* don't report an error; the object may be updated by multiple
* backends */
status = 1;
if (! new) {
char errbuf[1024];
sdb_log(SDB_LOG_ERR, "store: Failed to create %s '%s': %s",
- TYPE_TO_NAME(type), name,
+ SDB_STORE_TYPE_TO_NAME(type), name,
sdb_strerror(errno, errbuf, sizeof(errbuf)));
free(parent_cname);
free(cname);
if (! iter) {
char errbuf[1024];
sdb_log(SDB_LOG_ERR, "store: Failed to retrieve %ss: %s\n",
- TYPE_TO_NAME(type),
+ SDB_STORE_TYPE_TO_NAME(type),
sdb_strerror(errno, errbuf, sizeof(errbuf)));
sdb_strbuf_append(buf, "{\"error\": \"failed to retrieve %ss: %s\"}",
- TYPE_TO_NAME(type), errbuf);
+ SDB_STORE_TYPE_TO_NAME(type), errbuf);
}
/* has_next returns false if the iterator is NULL */
index 2affaa986f869e3c7514761857653203c291fefa..8bdb40e63c41f9ff8bd487390663614ede8082d2 100644 (file)
--- a/src/core/store_lookup.c
+++ b/src/core/store_lookup.c
/* specific matchers */
static int
-match_name(name_matcher_t *m, const char *name)
+match_obj_name(name_matcher_t *m, const char *name)
{
assert(m);
/* matches */ 0, NULL, /* flags = */ 0))
return 0;
return 1;
-} /* match_name */
+} /* match_obj_name */
static char *
-name_tostring(name_matcher_t *m, char *buf, size_t buflen)
+obj_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 */
+} /* obj_name_tostring */
static char *
logical_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
return buf;
} /* unary_tostring */
+static char *
+name_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
+{
+ char name[buflen + 1];
+ assert(m->type == MATCHER_NAME);
+ snprintf(buf, buflen, "OBJ[%s]{ NAME%s }",
+ SDB_STORE_TYPE_TO_NAME(OBJ_M(m)->obj_type),
+ obj_name_tostring(&OBJ_M(m)->name, name, sizeof(name)));
+ return buf;
+} /* name_tostring */
+
static char *
attr_tostring(sdb_store_matcher_t *m, char *buf, size_t buflen)
{
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)));
+ obj_name_tostring(&OBJ_M(m)->name, name, sizeof(name)),
+ obj_name_tostring(&ATTR_M(m)->value, value, sizeof(value)));
return buf;
} /* attr_tostring */
assert(m->type == MATCHER_SERVICE);
snprintf(buf, buflen, "SERVICE{ NAME%s, %s }",
- name_tostring(&OBJ_M(m)->name, name, sizeof(name)),
+ obj_name_tostring(&OBJ_M(m)->name, name, sizeof(name)),
attr_tostring(SDB_STORE_MATCHER(SERVICE_M(m)->attr),
attr, sizeof(attr)));
return buf;
assert(m->type == MATCHER_HOST);
snprintf(buf, buflen, "HOST{ NAME%s, %s, %s }",
- name_tostring(&OBJ_M(m)->name, name, sizeof(name)),
+ obj_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),
return buf;
} /* host_tostring */
+static int
+match_name(sdb_store_matcher_t *m, sdb_store_base_t *obj)
+{
+ sdb_llist_iter_t *iter = NULL;
+ int status = 0;
+
+ assert(m && obj);
+
+ if (obj->type != SDB_HOST)
+ return 0;
+
+ switch (OBJ_M(m)->obj_type) {
+ case SDB_HOST:
+ return match_obj_name(&OBJ_M(m)->name, obj->super.name);
+ break;
+ case SDB_SERVICE:
+ iter = sdb_llist_get_iter(SDB_STORE_OBJ(obj)->children);
+ break;
+ case SDB_ATTRIBUTE:
+ iter = sdb_llist_get_iter(SDB_STORE_OBJ(obj)->attributes);
+ break;
+ }
+
+ while (sdb_llist_iter_has_next(iter)) {
+ sdb_store_base_t *child = STORE_BASE(sdb_llist_iter_get_next(iter));
+ if (match_obj_name(&OBJ_M(m)->name, child->super.name)) {
+ status = 1;
+ break;
+ }
+ }
+ sdb_llist_iter_destroy(iter);
+ return status;
+} /* match_name */
+
/* match attribute specific values;
* always call this function through match_obj() */
static int
if (sdb_data_format(&attr->value, buf, sizeof(buf), SDB_UNQUOTED) <= 0)
return 0;
- return match_name(&m->value, buf);
+ return match_obj_name(&m->value, buf);
}
} /* match_attr */
match_logical,
match_logical,
match_unary,
+ match_name,
match_obj,
match_obj,
match_obj,
logical_tostring,
logical_tostring,
unary_tostring,
+ name_tostring,
attr_tostring,
service_tostring,
host_tostring,
assert(m && obj);
- status = match_name(&OBJ_M(m)->name, obj->super.name);
+ status = match_obj_name(&OBJ_M(m)->name, obj->super.name);
if (! status)
return status;
case MATCHER_HOST:
return match_host(HOST_M(m), obj);
break;
+ default:
+ assert(m->type != m->type);
+ break;
}
return 0;
} /* match_obj */
obj_matcher_init(sdb_object_t *obj, va_list ap)
{
obj_matcher_t *m = OBJ_M(obj);
+ M(obj)->type = MATCHER_NAME;
return name_matcher_init(&m->name, ap);
} /* obj_matcher_init */
attr_matcher_t *attr = ATTR_M(obj);
int status;
- M(obj)->type = MATCHER_ATTR;
-
status = obj_matcher_init(obj, ap);
if (! status)
status = name_matcher_init(&attr->value, ap);
+
+ M(obj)->type = MATCHER_ATTR;
return status;
} /* attr_matcher_init */
attr_matcher_t *attr;
int status;
- M(obj)->type = MATCHER_SERVICE;
-
status = obj_matcher_init(obj, ap);
if (status)
return status;
sdb_object_ref(SDB_OBJ(attr));
SERVICE_M(obj)->attr = attr;
+
+ M(obj)->type = MATCHER_SERVICE;
return 0;
} /* service_matcher_init */
attr_matcher_t *attr;
int status;
- M(obj)->type = MATCHER_HOST;
-
status = obj_matcher_init(obj, ap);
if (status)
return status;
HOST_M(obj)->service = service;
sdb_object_ref(SDB_OBJ(attr));
HOST_M(obj)->attr = attr;
+
+ M(obj)->type = MATCHER_HOST;
return 0;
} /* host_matcher_init */
sdb_object_deref(SDB_OBJ(UOP_M(obj)->op));
} /* uop_matcher_destroy */
+static sdb_type_t name_type = {
+ /* size = */ sizeof(obj_matcher_t),
+ /* init = */ obj_matcher_init,
+ /* destroy = */ obj_matcher_destroy,
+};
+
static sdb_type_t attr_type = {
/* size = */ sizeof(attr_matcher_t),
/* init = */ attr_matcher_init,
* public API
*/
+sdb_store_matcher_t *
+sdb_store_name_matcher(int type, const char *name, _Bool re)
+{
+ sdb_store_matcher_t *m;
+
+ if (re)
+ m = M(sdb_object_create("name-matcher", name_type,
+ NULL, name));
+ else
+ m = M(sdb_object_create("name-matcher", name_type,
+ name, NULL));
+
+ if (! m)
+ return NULL;
+
+ OBJ_M(m)->obj_type = type;
+ return m;
+} /* sdb_store_name_matcher */
+
sdb_store_matcher_t *
sdb_store_attr_matcher(const char *attr_name, const char *attr_name_re,
const char *attr_value, const char *attr_value_re)
index 6106b3fdbe2490629a6b1e42d02ee85184d134dc..68ee3aa1aae42e73212610a49eb48658b8343e9e 100644 (file)
--- a/src/include/core/store.h
+++ b/src/include/core/store.h
extern "C" {
#endif
+/*
+ * Store object types.
+ */
+enum {
+ SDB_HOST = 1,
+ SDB_SERVICE,
+ SDB_ATTRIBUTE,
+};
+#define SDB_STORE_TYPE_TO_NAME(t) \
+ (((t) == SDB_HOST) ? "host" \
+ : ((t) == SDB_SERVICE) ? "service" \
+ : ((t) == SDB_ATTRIBUTE) ? "attribute" : "unknown")
+
+
/*
* sdb_store_base_t represents the super-class of any object stored in the
* database. It inherits from sdb_object_t and may safely be cast to a generic
sdb_time_t last_update);
/*
- * Store matchers may be used to lookup objects from the host based on their
- * various attributes. Each type of matcher evaluates attributes of the
- * respective object type.
+ * 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.
*
* For each matcher object, *all* specified attributes have to match.
*
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
+ * true, the specified name is treated as a POSIX extended regular expression.
+ * Else, the exact name has to match.
+ */
+sdb_store_matcher_t *
+sdb_store_name_matcher(int type, const char *name, _Bool re);
+
/*
* sdb_store_attr_matcher:
* Creates a matcher matching attributes based on their name or value. Either
index 56315196caf4155f22d43fc81694b15ac76b8916..c143a8aacc2dca51d291cb5485e34cb26454fc56 100644 (file)
}
END_TEST
+START_TEST(test_store_match_name)
+{
+ sdb_store_base_t *obj;
+
+ struct {
+ int type;
+ const char *name;
+ _Bool re;
+
+ int expected;
+ } golden_data[] = {
+ { SDB_HOST, NULL, 0, 1 },
+ { SDB_HOST, NULL, 1, 1 },
+ { SDB_HOST, "a", 0, 1 },
+ { SDB_HOST, "a", 1, 1 },
+ { SDB_HOST, "b", 0, 0 },
+ { SDB_HOST, "b", 1, 0 },
+ { SDB_HOST, "^a$", 1, 1 },
+ { SDB_HOST, "^b$", 1, 0 },
+ { SDB_HOST, "^a$", 0, 0 },
+ { SDB_HOST, "^b$", 0, 0 },
+ { SDB_SERVICE, NULL, 0, 1 },
+ { SDB_SERVICE, NULL, 1, 1 },
+ { SDB_SERVICE, "s1", 0, 1 },
+ { SDB_SERVICE, "s2", 0, 1 },
+ { SDB_SERVICE, "s3", 0, 0 },
+ { SDB_SERVICE, "s4", 0, 0 },
+ { SDB_SERVICE, "^s1$", 1, 1 },
+ { SDB_SERVICE, "^s1$", 0, 0 },
+ { SDB_SERVICE, "x1", 0, 0 },
+ { SDB_SERVICE, "x1", 1, 0 },
+ { SDB_SERVICE, "x", 1, 0 },
+ { SDB_ATTRIBUTE, NULL, 0, 1 },
+ { SDB_ATTRIBUTE, NULL, 1, 1 },
+ { SDB_ATTRIBUTE, "k1", 0, 1 },
+ { SDB_ATTRIBUTE, "k2", 0, 0 },
+ { SDB_ATTRIBUTE, "k3", 0, 0 },
+ { SDB_ATTRIBUTE, "k", 1, 1 },
+ { SDB_ATTRIBUTE, "1", 1, 1 },
+ { SDB_ATTRIBUTE, "2", 1, 0 },
+ };
+
+ size_t i;
+
+ obj = sdb_store_get_host("a");
+ fail_unless(obj != NULL,
+ "sdb_store_get_host(a) = NULL; expected: <host>");
+
+ for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+ sdb_store_matcher_t *m, *n;
+ char buf[1024];
+ int status;
+
+ m = sdb_store_name_matcher(golden_data[i].type,
+ golden_data[i].name, golden_data[i].re);
+ fail_unless(m != NULL,
+ "sdb_store_service_matcher(%d, %s, %d) = NULL; expected: <matcher>",
+ golden_data[i].type, golden_data[i].name, golden_data[i].re);
+
+ status = sdb_store_matcher_matches(m, obj);
+ fail_unless(status == golden_data[i].expected,
+ "sdb_store_matcher_matches(%s, <host a>) = %d; expected: %d",
+ sdb_store_matcher_tostring(m, buf, sizeof(buf)),
+ status, golden_data[i].expected);
+
+ n = sdb_store_inv_matcher(m);
+ fail_unless(n != NULL,
+ "sdb_store_inv_matcher() = NULL; expected: <matcher>");
+ sdb_object_deref(SDB_OBJ(m));
+
+ /* now match the inverted set of objects */
+ status = sdb_store_matcher_matches(n, obj);
+ fail_unless(status == !golden_data[i].expected,
+ "sdb_store_matcher_matches(%s, <host a>) = %d; expected: %d",
+ sdb_store_matcher_tostring(n, buf, sizeof(buf)),
+ status, golden_data[i].expected);
+
+ sdb_object_deref(SDB_OBJ(n));
+ }
+
+ sdb_object_deref(SDB_OBJ(obj));
+}
+END_TEST
+
START_TEST(test_store_match_op)
{
sdb_store_base_t *obj;
tc = tcase_create("core");
tcase_add_checked_fixture(tc, populate, sdb_store_clear);
tcase_add_test(tc, test_store_match);
+ tcase_add_test(tc, test_store_match_name);
tcase_add_test(tc, test_store_match_op);
tcase_add_test(tc, test_parse_cmp);
tcase_add_test(tc, test_lookup);