summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: a075de6)
raw | patch | inline | side by side (parent: a075de6)
author | Sebastian Harl <sh@tokkee.org> | |
Tue, 29 Jul 2014 20:18:14 +0000 (22:18 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Tue, 29 Jul 2014 20:18:14 +0000 (22:18 +0200) |
Only objects covered by the specified filter will be included in the JSON
output.
output.
src/core/store.c | patch | blob | history | |
src/frontend/query.c | patch | blob | history | |
src/include/core/store.h | patch | blob | history | |
t/unit/core/store_test.c | patch | blob | history |
diff --git a/src/core/store.c b/src/core/store.c
index 800059cf62112f0b3615258b731d728595805553..bb6cb96a45bb4b91d934705324e06b179b4742b4 100644 (file)
--- a/src/core/store.c
+++ b/src/core/store.c
* of the serialized data.
*/
static void
-store_obj_tojson(sdb_avltree_t *tree, int type, sdb_strbuf_t *buf, int flags)
+store_obj_tojson(sdb_avltree_t *tree, int type, sdb_strbuf_t *buf,
+ sdb_store_matcher_t *filter, int flags)
{
sdb_avltree_iter_t *iter;
assert(sobj);
assert(sobj->type == type);
+ if (filter && (! sdb_store_matcher_matches(filter, sobj, NULL)))
+ continue;
+
sdb_strbuf_append(buf, "{\"name\": \"%s\", ", SDB_OBJ(sobj)->name);
if (sobj->type == SDB_ATTRIBUTE) {
char tmp[sdb_data_strlen(&ATTR(sobj)->value) + 1];
&& (! (flags & SDB_SKIP_ATTRIBUTES))) {
sdb_strbuf_append(buf, ", \"attributes\": ");
store_obj_tojson(SVC(sobj)->attributes, SDB_ATTRIBUTE,
- buf, flags);
+ buf, filter, flags);
}
sdb_strbuf_append(buf, "}");
} /* sdb_store_service_attr */
int
-sdb_store_host_tojson(sdb_store_obj_t *h, sdb_strbuf_t *buf, int flags)
+sdb_store_host_tojson(sdb_store_obj_t *h, sdb_strbuf_t *buf,
+ sdb_store_matcher_t *filter, int flags)
{
- sdb_host_t *host;
+ sdb_host_t *host = HOST(h);
if ((! h) || (h->type != SDB_HOST) || (! buf))
return -1;
- host = HOST(h);
+ if (filter && (! sdb_store_matcher_matches(filter, h, NULL)))
+ return 0;
sdb_strbuf_append(buf, "{\"name\": \"%s\", ", SDB_OBJ(host)->name);
store_common_tojson(h, buf);
if (! (flags & SDB_SKIP_ATTRIBUTES)) {
sdb_strbuf_append(buf, ", \"attributes\": ");
- store_obj_tojson(host->attributes, SDB_ATTRIBUTE, buf, flags);
+ store_obj_tojson(host->attributes, SDB_ATTRIBUTE, buf, filter, flags);
}
if (! (flags & SDB_SKIP_SERVICES)) {
sdb_strbuf_append(buf, ", \"services\": ");
- store_obj_tojson(host->services, SDB_SERVICE, buf, flags);
+ store_obj_tojson(host->services, SDB_SERVICE, buf, filter, flags);
}
sdb_strbuf_append(buf, "}");
} /* sdb_store_host_tojson */
int
-sdb_store_tojson(sdb_strbuf_t *buf, int flags)
+sdb_store_tojson(sdb_strbuf_t *buf, sdb_store_matcher_t *filter, int flags)
{
sdb_avltree_iter_t *host_iter;
while (sdb_avltree_iter_has_next(host_iter)) {
sdb_store_obj_t *host;
+ size_t len = sdb_strbuf_len(buf);
host = STORE_OBJ(sdb_avltree_iter_get_next(host_iter));
assert(host);
- if (sdb_store_host_tojson(host, buf, flags))
+ if (sdb_store_host_tojson(host, buf, filter, flags))
return -1;
- if (sdb_avltree_iter_has_next(host_iter))
+ /* sdb_store_host_tojson may leave the buffer unmodified */
+ if ((sdb_avltree_iter_has_next(host_iter))
+ && (sdb_strbuf_len(buf) != len))
sdb_strbuf_append(buf, ",");
}
diff --git a/src/frontend/query.c b/src/frontend/query.c
index 675b3960a48c7680a75a1a0ef1c34d808635144d..53ba81aac38b03dd24bc07922b146a1dc6d23c4c 100644 (file)
--- a/src/frontend/query.c
+++ b/src/frontend/query.c
sdb_strbuf_t *buf = user_data;
if (sdb_strbuf_len(buf) > 1)
sdb_strbuf_append(buf, ",");
- return sdb_store_host_tojson(obj, buf, /* flags = */ 0);
+ return sdb_store_host_tojson(obj, buf,
+ /* filter = */ NULL, /* flags = */ 0);
} /* lookup_tojson */
/*
return -1;
}
- if (sdb_store_host_tojson(host, buf, /* flags = */ 0)) {
+ if (sdb_store_host_tojson(host, buf,
+ /* filter = */ NULL, /* flags = */ 0)) {
sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize "
"host '%s' to JSON", name);
sdb_strbuf_sprintf(conn->errbuf, "Out of memory");
return -1;
}
- if (sdb_store_tojson(buf, /* flags = */ SDB_SKIP_ALL)) {
+ if (sdb_store_tojson(buf,
+ /* filter = */ NULL, /* flags = */ SDB_SKIP_ALL)) {
sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize "
"store to JSON");
sdb_strbuf_sprintf(conn->errbuf, "Out of memory");
index a9788f44bb5b59ac7b166b46667bdb0acc9a70f1..494f8d648c241834100c56a29560b6d58fd5ca6f 100644 (file)
--- a/src/include/core/store.h
+++ b/src/include/core/store.h
/*
* sdb_store_tojson:
* Serialize the entire store to JSON and append the result to the specified
- * buffer.
+ * buffer. If specified, only objects matching the filter will be included in
+ * the result (see sdb_store_host_tojson for details).
*
* Returns:
* - 0 on success
* - a negative value on error
*/
int
-sdb_store_tojson(sdb_strbuf_t *buf, int flags);
+sdb_store_tojson(sdb_strbuf_t *buf, sdb_store_matcher_t *filter, int flags);
/*
* sdb_store_host_tojson:
* Serialize a host object to JSON and append the result to the specified
- * buffer.
+ * buffer. If specified, only objects matching the filter will be included in
+ * the result. The filter is applied to each object individually and, thus,
+ * should not be of any object-type specific kind. If the filter rejects the
+ * host object, the function returns success but leaves the buffer unmodified.
*
* Returns:
* - 0 on success
* - a negative value on error
*/
int
-sdb_store_host_tojson(sdb_store_obj_t *host, sdb_strbuf_t *buf, int flags);
+sdb_store_host_tojson(sdb_store_obj_t *host, sdb_strbuf_t *buf,
+ sdb_store_matcher_t *filter, int flags);
/*
* sdb_store_iter_cb:
index 0d0c56bce6df859074e64590cf910eea3bfa67f5..bc2066a208b98afabc1921efb6c8b8dd683370f5 100644 (file)
--- a/t/unit/core/store_test.c
+++ b/t/unit/core/store_test.c
sdb_data_t datum;
sdb_store_host("h1", 1);
- sdb_store_host("h2", 1);
+ sdb_store_host("h2", 3);
datum.type = SDB_TYPE_STRING;
datum.data.string = "v1";
sdb_store_attribute("h1", "k3", &datum, 2);
sdb_store_service("h2", "s1", 1);
- sdb_store_service("h2", "s2", 1);
+ sdb_store_service("h2", "s2", 2);
datum.type = SDB_TYPE_INTEGER;
datum.data.integer = 123;
sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
+ datum.data.integer = 4711;
+ sdb_store_service_attr("h2", "s2", "k2", &datum, 1);
- /* don't overwrite */
+ /* don't overwrite k1 */
datum.data.integer = 666;
sdb_store_service_attr("h2", "s2", "k1", &datum, 2);
} /* populate */
size_t i;
struct {
+ struct {
+ sdb_store_matcher_t *(*m)(sdb_store_cond_t *);
+ int field;
+ sdb_data_t value;
+ } filter;
int flags;
const char *expected;
} golden_data[] = {
- { 0, "{\"hosts\":["
+ { { NULL, 0, SDB_DATA_INIT }, 0,
+ "{\"hosts\":["
"{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
"\"update_interval\": \"0s\", \"backends\": [], "
"\"attributes\": ["
"\"update_interval\": \"0s\", \"backends\": [], "
"\"attributes\": ["
"{\"name\": \"k1\", \"value\": 123, "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "{\"name\": \"k2\", \"value\": 4711, "
"\"last_update\": \"1970-01-01 00:00:00 +0000\", "
"\"update_interval\": \"0s\", \"backends\": []}"
"]}"
"]}"
"]}" },
- { SDB_SKIP_SERVICES,
+ { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_SERVICES,
"{\"hosts\":["
"{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
"\"update_interval\": \"0s\", \"backends\": [], "
"\"update_interval\": \"0s\", \"backends\": [], "
"\"attributes\": []}"
"]}" },
- { SDB_SKIP_ATTRIBUTES,
+ { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_ATTRIBUTES,
"{\"hosts\":["
"{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
"\"update_interval\": \"0s\", \"backends\": [], "
"\"update_interval\": \"0s\", \"backends\": []}"
"]}"
"]}" },
- { SDB_SKIP_SERVICES | SDB_SKIP_ATTRIBUTES,
+ { { NULL, 0, SDB_DATA_INIT }, SDB_SKIP_SERVICES | SDB_SKIP_ATTRIBUTES,
"{\"hosts\":["
"{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
"\"update_interval\": \"0s\", \"backends\": []},"
"{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
"\"update_interval\": \"0s\", \"backends\": []}"
"]}" },
+ { { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
+ { SDB_TYPE_DATETIME, { .datetime = 1 } } }, 0,
+ "{\"hosts\":["
+ "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"attributes\": [], "
+ "\"services\": ["
+ "{\"name\": \"s2\", "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"attributes\": ["
+ "{\"name\": \"k1\", \"value\": 123, "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "]}"
+ "]}"
+ "]}" },
+ { { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
+ { SDB_TYPE_DATETIME, { .datetime = 1 } } }, 0,
+ "{\"hosts\":["
+ "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"attributes\": ["
+ "{\"name\": \"k1\", \"value\": \"v1\", "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "], "
+ "\"services\": []},"
+ "]}" },
+ { { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE,
+ { SDB_TYPE_DATETIME, { .datetime = 3 } } }, 0,
+ "{\"hosts\":["
+ "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"attributes\": [], "
+ "\"services\": []}"
+ "]}" },
};
buf = sdb_strbuf_create(0);
populate();
for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+ sdb_store_matcher_t *filter = NULL;
int status;
sdb_strbuf_clear(buf);
- status = sdb_store_tojson(buf, golden_data[i].flags);
+ if (golden_data[i].filter.m) {
+ sdb_store_expr_t *expr;
+ sdb_store_cond_t *c = NULL;
+
+ expr = sdb_store_expr_constvalue(&golden_data[i].filter.value);
+ fail_unless(expr != NULL,
+ "INTERNAL ERROR: sdb_store_expr_constvalue() = NULL");
+ c = sdb_store_obj_cond(golden_data[i].filter.field, expr);
+ sdb_object_deref(SDB_OBJ(expr));
+ fail_unless(c != NULL,
+ "INTERNAL ERROR: sdb_store_obj_cond() = NULL");
+ filter = golden_data[i].filter.m(c);
+ sdb_object_deref(SDB_OBJ(c));
+ fail_unless(filter != NULL,
+ "INTERNAL ERROR: sdb_store_*_matcher() = NULL");
+ }
+
+ status = sdb_store_tojson(buf, filter, golden_data[i].flags);
fail_unless(status == 0,
"sdb_store_tojson(%x) = %d; expected: 0",
golden_data[i].flags, status);
verify_json_output(buf, golden_data[i].expected, golden_data[i].flags);
+ sdb_object_deref(SDB_OBJ(filter));
}
sdb_strbuf_destroy(buf);
}