summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: fa16153)
raw | patch | inline | side by side (parent: fa16153)
author | Sebastian Harl <sh@tokkee.org> | |
Sun, 2 Nov 2014 18:04:42 +0000 (19:04 +0100) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Sun, 2 Nov 2014 18:04:42 +0000 (19:04 +0100) |
When formatting services or metrics, expect those objects to be emitted on the
highest level and then create the host object for them first (once for a
series of objects belonging to the same host).
highest level and then create the host object for them first (once for a
series of objects belonging to the same host).
src/core/store_json.c | patch | blob | history | |
src/frontend/query.c | patch | blob | history | |
src/include/core/store.h | patch | blob | history | |
t/unit/core/store_json_test.c | patch | blob | history |
diff --git a/src/core/store_json.c b/src/core/store_json.c
index b4b7b6a8af4b1becfb02431e43188325355f29b4..493ac9f377c9072d54fdf76488ab242e76cc6ec6 100644 (file)
--- a/src/core/store_json.c
+++ b/src/core/store_json.c
int context[8];
size_t current;
+ /* The current host context when processing non-host objects */
+ sdb_store_obj_t *current_host;
+
+ int type;
int flags;
};
assert(f && obj);
+ if ((f->type != SDB_HOST) && (f->type == obj->type)) {
+ /* create the host for the current entry first */
+ assert(obj->parent && (obj->parent->type == SDB_HOST));
+ if (f->current_host != obj->parent) {
+ json_emit(f, obj->parent);
+ sdb_strbuf_append(f->buf, ", \"%ss\": [",
+ SDB_STORE_TYPE_TO_NAME(obj->type));
+ f->current_host = obj->parent;
+ }
+ }
+
sdb_strbuf_append(f->buf, "{\"name\": \"%s\", ", SDB_OBJ(obj)->name);
if (obj->type == SDB_ATTRIBUTE) {
char tmp[sdb_data_strlen(&ATTR(obj)->value) + 1];
*/
sdb_store_json_formatter_t *
-sdb_store_json_formatter(sdb_strbuf_t *buf, int flags)
+sdb_store_json_formatter(sdb_strbuf_t *buf, int type, int flags)
{
sdb_store_json_formatter_t *f;
if (! buf)
return NULL;
+ if ((type != SDB_HOST) && (type != SDB_SERVICE) && (type != SDB_METRIC))
+ return NULL;
+
f = calloc(1, sizeof(*f));
if (! f)
return NULL;
f->buf = buf;
f->context[0] = 0;
f->current = 0;
+
+ f->current_host = NULL;
+
+ f->type = type;
f->flags = flags;
return f;
} /* sdb_store_json_formatter */
if ((! f) || (! obj))
return -1;
- /* first host */
+ if ((f->type != SDB_HOST) && (obj->type == SDB_HOST)) {
+ sdb_log(SDB_LOG_ERR, "store: Unexpected object of type host "
+ "during %s JSON serialization",
+ SDB_STORE_TYPE_TO_NAME(f->type));
+ return -1;
+ }
+
+ /* first top-level object */
if (! f->context[0]) {
+ if (obj->type != f->type) {
+ sdb_log(SDB_LOG_ERR, "store: Unexpected object of type %s "
+ "as the first element during %s JSON serialization",
+ SDB_STORE_TYPE_TO_NAME(obj->type),
+ SDB_STORE_TYPE_TO_NAME(f->type));
+ return -1;
+ }
if (f->flags & SDB_WANT_ARRAY)
sdb_strbuf_append(f->buf, "[");
assert(f->current == 0);
- f->context[0] = SDB_HOST;
+ f->context[0] = obj->type;
return json_emit(f, obj);
}
+ if ((f->current >= 1) && (obj->type != SDB_ATTRIBUTE)) {
+ /* new entry of a previous type or a new type on the same level;
+ * rewind to the right state */
+ while (f->current > 0) {
+ if (f->context[f->current] == obj->type)
+ break;
+ sdb_strbuf_append(f->buf, "}]");
+ --f->current;
+ }
+ }
+ if ((obj->type == f->type) && (f->type != SDB_HOST))
+ if (obj->parent != f->current_host)
+ sdb_strbuf_append(f->buf, "}]");
+
if (obj->type == f->context[f->current]) {
/* new entry of the same type */
sdb_strbuf_append(f->buf, "},");
SDB_STORE_TYPE_TO_NAME(obj->type));
++f->current;
}
- else if (f->current >= 1) {
- /* new entry of a previous type or a new type on the same level
- * -> rewind to the right state and then handle the new object */
- assert(obj->type != SDB_ATTRIBUTE);
- while (f->current > 0) {
- if (f->context[f->current] == obj->type)
- break;
- assert(f->context[f->current] != SDB_HOST);
- sdb_strbuf_append(f->buf, "}]");
- --f->current;
- }
- return sdb_store_json_emit(f, obj);
- }
else {
sdb_log(SDB_LOG_ERR, "store: Unexpected object of type %s "
"on level %zu during JSON serialization",
sdb_strbuf_append(f->buf, "}]");
--f->current;
}
+ if (f->context[0] != SDB_HOST) {
+ assert(f->type != SDB_HOST);
+ sdb_strbuf_append(f->buf, "}]}");
+ }
+ else
+ sdb_strbuf_append(f->buf, "}");
- sdb_strbuf_append(f->buf, "}");
if (f->flags & SDB_WANT_ARRAY)
sdb_strbuf_append(f->buf, "]");
return 0;
diff --git a/src/frontend/query.c b/src/frontend/query.c
index 1ef36b351de41d9e3bf392075de68f375927f1dc..1cb32dd307098f1290f011f3f83104bf97a5604b 100644 (file)
--- a/src/frontend/query.c
+++ b/src/frontend/query.c
sdb_strbuf_sprintf(conn->errbuf, "Out of memory");
return -1;
}
- f = sdb_store_json_formatter(buf, SDB_WANT_ARRAY);
+ f = sdb_store_json_formatter(buf, type, SDB_WANT_ARRAY);
if (! f) {
char errbuf[1024];
sdb_log(SDB_LOG_ERR, "frontend: Failed to create "
index df959eab25396d03e67e8ab24f075a9086be77f1..c25c278a327f5904ec8252cdee65ac9dc3da15d8 100644 (file)
--- a/src/include/core/store.h
+++ b/src/include/core/store.h
/*
* sdb_store_json_formatter:
- * Create a JSON formatter writing to the specified buffer.
+ * Create a JSON formatter for the specified object types writing to the
+ * specified buffer.
*/
sdb_store_json_formatter_t *
-sdb_store_json_formatter(sdb_strbuf_t *buf, int flags);
+sdb_store_json_formatter(sdb_strbuf_t *buf, int type, int flags);
/*
* sdb_store_json_emit:
index c544633e3e4e1b189ebcd180687957fcfeaf2f17..d7fad58c8d9793567f476810bd763c5a4516f413 100644 (file)
int field;
sdb_data_t value;
} filter;
+ int type;
int (*f)(sdb_store_obj_t *, sdb_store_matcher_t *, void *);
const char *expected;
} golden_data[] = {
- { { NULL, 0, SDB_DATA_INIT }, scan_tojson_full,
+ { { NULL, 0, SDB_DATA_INIT },
+ SDB_HOST, scan_tojson_full,
"["
"{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
"\"update_interval\": \"0s\", \"backends\": [], "
"]}"
"]}"
"]" },
- { { NULL, 0, SDB_DATA_INIT }, scan_tojson,
+ { { NULL, 0, SDB_DATA_INIT },
+ SDB_HOST, scan_tojson,
"["
"{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
"\"update_interval\": \"0s\", \"backends\": []},"
"\"update_interval\": \"0s\", \"backends\": []}"
"]" },
{ { sdb_store_eq_matcher, SDB_FIELD_NAME,
- { SDB_TYPE_STRING, { .string = "h1" } } }, scan_tojson_full,
+ { SDB_TYPE_STRING, { .string = "h1" } } },
+ SDB_HOST, scan_tojson_full,
"["
"{\"name\": \"h1\", \"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 } } }, scan_tojson_full,
+ { SDB_TYPE_DATETIME, { .datetime = 1 } } },
+ SDB_HOST, scan_tojson_full,
"["
"{\"name\": \"h2\", \"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 } } }, scan_tojson_full,
+ { SDB_TYPE_DATETIME, { .datetime = 1 } } },
+ SDB_HOST, scan_tojson_full,
"["
"{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
"\"update_interval\": \"0s\", \"backends\": [], "
"]}"
"]" },
{ { sdb_store_ge_matcher, SDB_FIELD_LAST_UPDATE,
- { SDB_TYPE_DATETIME, { .datetime = 3 } } }, scan_tojson_full,
+ { SDB_TYPE_DATETIME, { .datetime = 3 } } },
+ SDB_HOST, scan_tojson_full,
"["
"{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
"\"update_interval\": \"0s\", \"backends\": []}"
"]" },
{ { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
- { SDB_TYPE_DATETIME, { .datetime = 0 } } }, scan_tojson_full,
+ { SDB_TYPE_DATETIME, { .datetime = 0 } } },
+ SDB_HOST, scan_tojson_full,
+ "[]" },
+
+ { { NULL, 0, SDB_DATA_INIT },
+ SDB_SERVICE, scan_tojson_full,
+ "["
+ "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"services\": ["
+ "{\"name\": \"s1\", "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "{\"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\": []},"
+ "{\"name\": \"k2\", \"value\": 4711, "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []}"
+ "]}"
+ "]}"
+ "]" },
+ { { NULL, 0, SDB_DATA_INIT },
+ SDB_SERVICE, scan_tojson,
+ "["
+ "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"services\": ["
+ "{\"name\": \"s1\", "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "{\"name\": \"s2\", "
+ "\"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 } } },
+ SDB_SERVICE, scan_tojson_full,
+ "["
+ "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"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_lt_matcher, SDB_FIELD_LAST_UPDATE,
+ { SDB_TYPE_DATETIME, { .datetime = 0 } } },
+ SDB_SERVICE, scan_tojson_full,
+ "[]" },
+ { { NULL, 0, SDB_DATA_INIT },
+ SDB_METRIC, scan_tojson_full,
+ "["
+ "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"metrics\": ["
+ "{\"name\": \"m1\", "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"attributes\": ["
+ "{\"name\": \"k3\", \"value\": 42, "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []}"
+ "]},"
+ "{\"name\": \"m2\", "
+ "\"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\": [], "
+ "\"metrics\": ["
+ "{\"name\": \"m1\", "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []}"
+ "]}"
+ "]" },
+ { { NULL, 0, SDB_DATA_INIT },
+ SDB_METRIC, scan_tojson,
+ "["
+ "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"metrics\": ["
+ "{\"name\": \"m1\", "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "{\"name\": \"m2\", "
+ "\"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\": [], "
+ "\"metrics\": ["
+ "{\"name\": \"m1\", "
+ "\"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 } } },
+ SDB_METRIC, scan_tojson_full,
+ "["
+ "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": [], "
+ "\"metrics\": ["
+ "{\"name\": \"m2\", "
+ "\"last_update\": \"1970-01-01 00:00:00 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []}"
+ "]}"
+ "]" },
+ { { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
+ { SDB_TYPE_DATETIME, { .datetime = 0 } } },
+ SDB_METRIC, scan_tojson_full,
"[]" },
};
}
sdb_strbuf_clear(buf);
- f = sdb_store_json_formatter(buf, SDB_WANT_ARRAY);
+ f = sdb_store_json_formatter(buf,
+ golden_data[i].type, SDB_WANT_ARRAY);
assert(f);
- status = sdb_store_scan(SDB_HOST, /* m = */ NULL, filter,
+ status = sdb_store_scan(golden_data[i].type, /* m = */ NULL, filter,
golden_data[i].f, f);
fail_unless(status == 0,
"sdb_store_scan(HOST, ..., tojson) = %d; expected: 0",