summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: b75718e)
raw | patch | inline | side by side (parent: b75718e)
author | Sebastian Harl <sh@tokkee.org> | |
Mon, 28 Sep 2015 07:54:15 +0000 (09:54 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Mon, 28 Sep 2015 07:54:15 +0000 (09:54 +0200) |
This makes the JSON module more generic by removing a special case of the
memory store. The caller may now emit arbitrary objects and the formatter will
do the right thing as long as parent-child relationships are right.
memory store. The caller may now emit arbitrary objects and the formatter will
do the right thing as long as parent-child relationships are right.
src/core/store_exec.c | patch | blob | history | |
src/core/store_json.c | patch | blob | history | |
t/unit/core/store_json_test.c | patch | blob | history |
diff --git a/src/core/store_exec.c b/src/core/store_exec.c
index ee1f8d046f47ad49768c4aa2a2b89a0bff9bbd80..c377129b825e8c6e42a2a690e6953f3a21749337 100644 (file)
--- a/src/core/store_exec.c
+++ b/src/core/store_exec.c
* private helper functions
*/
+typedef struct {
+ sdb_store_json_formatter_t *f;
+ sdb_store_obj_t *current_host;
+} iter_t;
+
+static int
+maybe_emit_host(iter_t *iter, sdb_store_obj_t *obj)
+{
+ if ((obj->type == SDB_HOST) || (obj->type == SDB_ATTRIBUTE))
+ return 0;
+ if (iter->current_host == obj->parent)
+ return 0;
+ iter->current_host = obj->parent;
+ return sdb_store_json_emit(iter->f, obj->parent);
+} /* maybe_emit_host */
+
static int
list_tojson(sdb_store_obj_t *obj,
sdb_store_matcher_t __attribute__((unused)) *filter,
void *user_data)
{
- sdb_store_json_formatter_t *f = user_data;
- return sdb_store_json_emit(f, obj);
+ iter_t *iter = user_data;
+ maybe_emit_host(iter, obj);
+ return sdb_store_json_emit(iter->f, obj);
} /* list_tojson */
static int
lookup_tojson(sdb_store_obj_t *obj, sdb_store_matcher_t *filter,
void *user_data)
{
- sdb_store_json_formatter_t *f = user_data;
- return sdb_store_json_emit_full(f, obj, filter);
+ iter_t *iter = user_data;
+ maybe_emit_host(iter, obj);
+ return sdb_store_json_emit_full(iter->f, obj, filter);
} /* lookup_tojson */
/*
sdb_store_obj_t *obj;
sdb_store_json_formatter_t *f;
+ int status = 0;
if ((! name) || ((type == SDB_HOST) && hostname)
|| ((type != SDB_HOST) && (! hostname))) {
}
sdb_strbuf_memcpy(buf, &res_type, sizeof(uint32_t));
- if (sdb_store_json_emit_full(f, obj, filter)) {
+ if (type != SDB_HOST)
+ status = sdb_store_json_emit(f, obj->parent);
+ if (status || sdb_store_json_emit_full(f, obj, filter)) {
sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize "
"%s %s.%s to JSON", SDB_STORE_TYPE_TO_NAME(type),
hostname, name);
int type, sdb_store_matcher_t *filter)
{
uint32_t res_type = htonl(SDB_CONNECTION_LIST);
- sdb_store_json_formatter_t *f;
+ iter_t iter = { NULL, NULL };
- f = sdb_store_json_formatter(buf, type, SDB_WANT_ARRAY);
- if (! f) {
+ iter.f = sdb_store_json_formatter(buf, type, SDB_WANT_ARRAY);
+ if (! iter.f) {
char err[1024];
sdb_log(SDB_LOG_ERR, "frontend: Failed to create "
"JSON formatter to handle LIST command: %s",
}
sdb_strbuf_memcpy(buf, &res_type, sizeof(uint32_t));
- if (sdb_store_scan(store, type, /* m = */ NULL, filter, list_tojson, f)) {
+ if (sdb_store_scan(store, type, /* m = */ NULL, filter, list_tojson, &iter)) {
sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize "
"store to JSON");
sdb_strbuf_sprintf(errbuf, "Out of memory");
- sdb_object_deref(SDB_OBJ(f));
+ sdb_object_deref(SDB_OBJ(iter.f));
return -1;
}
- sdb_store_json_finish(f);
- sdb_object_deref(SDB_OBJ(f));
+ sdb_store_json_finish(iter.f);
+ sdb_object_deref(SDB_OBJ(iter.f));
return SDB_CONNECTION_DATA;
} /* exec_list */
int type, sdb_store_matcher_t *m, sdb_store_matcher_t *filter)
{
uint32_t res_type = htonl(SDB_CONNECTION_LOOKUP);
- sdb_store_json_formatter_t *f;
+ iter_t iter = { NULL, NULL };
- f = sdb_store_json_formatter(buf, type, SDB_WANT_ARRAY);
- if (! f) {
+ iter.f = sdb_store_json_formatter(buf, type, SDB_WANT_ARRAY);
+ if (! iter.f) {
char err[1024];
sdb_log(SDB_LOG_ERR, "frontend: Failed to create "
"JSON formatter to handle LOOKUP command: %s",
sdb_strbuf_memcpy(buf, &res_type, sizeof(uint32_t));
- if (sdb_store_scan(store, type, m, filter, lookup_tojson, f)) {
+ if (sdb_store_scan(store, type, m, filter, lookup_tojson, &iter)) {
sdb_log(SDB_LOG_ERR, "frontend: Failed to lookup %ss",
SDB_STORE_TYPE_TO_NAME(type));
sdb_strbuf_sprintf(errbuf, "Failed to lookup %ss",
SDB_STORE_TYPE_TO_NAME(type));
- sdb_object_deref(SDB_OBJ(f));
+ sdb_object_deref(SDB_OBJ(iter.f));
return -1;
}
- sdb_store_json_finish(f);
- sdb_object_deref(SDB_OBJ(f));
+ sdb_store_json_finish(iter.f);
+ sdb_object_deref(SDB_OBJ(iter.f));
return SDB_CONNECTION_DATA;
} /* exec_lookup */
diff --git a/src/core/store_json.c b/src/core/store_json.c
index 878cc4fe265886653c754a60a83ef23889af1668..639c9534aa8485fc9afce4e5e25ecf33058057eb 100644 (file)
--- a/src/core/store_json.c
+++ b/src/core/store_json.c
/*
* SysDB - src/core/store_json.c
- * Copyright (C) 2013-2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * Copyright (C) 2013-2015 Sebastian 'tokkee' Harl <sh@tokkee.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
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;
};
f->context[0] = 0;
f->current = 0;
-
- f->current_host = NULL;
return 0;
} /* formatter_init */
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;
- }
- }
-
escape_string(SDB_OBJ(obj)->name, name);
sdb_strbuf_append(f->buf, "{\"name\": %s, ", name);
if (obj->type == SDB_ATTRIBUTE) {
if ((! f) || (! obj))
return -1;
- 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) {
+ if ((obj->type != f->type) && (obj->type != SDB_HOST)) {
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),
if (f->flags & SDB_WANT_ARRAY)
sdb_strbuf_append(f->buf, "[");
assert(f->current == 0);
- 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;
+ else {
+ 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, "},");
- }
- else if ((f->context[f->current] == SDB_HOST)
- || (obj->type == SDB_ATTRIBUTE)) {
- assert(obj->type != SDB_HOST);
- /* all object types may be children of a host;
- * attributes may be children of any type */
- sdb_strbuf_append(f->buf, ", \"%ss\": [",
- SDB_STORE_TYPE_TO_NAME(obj->type));
- ++f->current;
- }
- else {
- sdb_log(SDB_LOG_ERR, "store: Unexpected object of type %s "
- "on level %zu during JSON serialization",
- SDB_STORE_TYPE_TO_NAME(obj->type), f->current);
- return -1;
+ if (obj->type == f->context[f->current]) {
+ /* new entry of the same type */
+ sdb_strbuf_append(f->buf, "},");
+ }
+ else if ((f->context[f->current] == SDB_HOST)
+ || (obj->type == SDB_ATTRIBUTE)) {
+ assert(obj->type != SDB_HOST);
+ /* all object types may be children of a host;
+ * attributes may be children of any type */
+ sdb_strbuf_append(f->buf, ", \"%ss\": [",
+ SDB_STORE_TYPE_TO_NAME(obj->type));
+ ++f->current;
+ }
+ else {
+ sdb_log(SDB_LOG_ERR, "store: Unexpected object of type %s "
+ "on level %zu during JSON serialization",
+ SDB_STORE_TYPE_TO_NAME(obj->type), f->current);
+ return -1;
+ }
}
json_emit(f, obj);
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, "]");
index f8ebac913633fe025df01344c2e2ecab521874cc..4173831f824833b821e68b03183c024460e0ad2c 100644 (file)
{ { NULL, 0, SDB_DATA_INIT },
SDB_SERVICE, scan_tojson_full,
"["
- "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
+ "{\"name\": \"s1\", "
+ "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "{\"name\": \"s2\", "
+ "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
"\"update_interval\": \"0s\", \"backends\": [], "
- "\"services\": ["
- "{\"name\": \"s1\", "
- "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []},"
- "{\"name\": \"s2\", "
+ "\"attributes\": ["
+ "{\"name\": \"k1\", \"value\": 123, "
"\"last_update\": \"1970-01-01 00:00:02 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": [], "
- "\"attributes\": ["
- "{\"name\": \"k1\", \"value\": 123, "
- "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []},"
- "{\"name\": \"k2\", \"value\": 4711, "
- "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []}"
- "]}"
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "{\"name\": \"k2\", \"value\": 4711, "
+ "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []}"
"]}"
"]" },
{ { NULL, 0, SDB_DATA_INIT },
SDB_SERVICE, scan_tojson,
"["
- "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": [], "
- "\"services\": ["
- "{\"name\": \"s1\", "
- "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []},"
- "{\"name\": \"s2\", "
- "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []}"
- "]}"
+ "{\"name\": \"s1\", "
+ "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "{\"name\": \"s2\", "
+ "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []}"
"]" },
{ { sdb_store_gt_matcher, SDB_FIELD_LAST_UPDATE,
{ SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } },
SDB_SERVICE, scan_tojson_full,
"["
- "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
+ "{\"name\": \"s2\", "
+ "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
"\"update_interval\": \"0s\", \"backends\": [], "
- "\"services\": ["
- "{\"name\": \"s2\", "
+ "\"attributes\": ["
+ "{\"name\": \"k1\", \"value\": 123, "
"\"last_update\": \"1970-01-01 00:00:02 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": [], "
- "\"attributes\": ["
- "{\"name\": \"k1\", \"value\": 123, "
- "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []}"
- "]}"
+ "\"update_interval\": \"0s\", \"backends\": []}"
"]}"
"]" },
{ { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
{ { NULL, 0, SDB_DATA_INIT },
SDB_METRIC, scan_tojson_full,
"["
- "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
+ "{\"name\": \"m1\", "
+ "\"timeseries\": false, "
+ "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
"\"update_interval\": \"0s\", \"backends\": [], "
- "\"metrics\": ["
- "{\"name\": \"m1\", "
- "\"timeseries\": false, "
+ "\"attributes\": ["
+ "{\"name\": \"k3\", \"value\": 42, "
"\"last_update\": \"1970-01-01 00:00:02 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": [], "
- "\"attributes\": ["
- "{\"name\": \"k3\", \"value\": 42, "
- "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []}"
- "]},"
- "{\"name\": \"m2\", "
- "\"timeseries\": false, "
- "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
"\"update_interval\": \"0s\", \"backends\": []}"
"]},"
- "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": [], "
- "\"metrics\": ["
- "{\"name\": \"m1\", "
- "\"timeseries\": false, "
- "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []}"
- "]}"
+ "{\"name\": \"m2\", "
+ "\"timeseries\": false, "
+ "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "{\"name\": \"m1\", "
+ "\"timeseries\": false, "
+ "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []}"
"]" },
{ { NULL, 0, SDB_DATA_INIT },
SDB_METRIC, scan_tojson,
"["
- "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": [], "
- "\"metrics\": ["
- "{\"name\": \"m1\", "
- "\"timeseries\": false, "
- "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []},"
- "{\"name\": \"m2\", "
- "\"timeseries\": false, "
- "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []}"
- "]},"
- "{\"name\": \"h2\", \"last_update\": \"1970-01-01 00:00:03 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": [], "
- "\"metrics\": ["
- "{\"name\": \"m1\", "
- "\"timeseries\": false, "
- "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []}"
- "]}"
+ "{\"name\": \"m1\", "
+ "\"timeseries\": false, "
+ "\"last_update\": \"1970-01-01 00:00:02 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "{\"name\": \"m2\", "
+ "\"timeseries\": false, "
+ "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []},"
+ "{\"name\": \"m1\", "
+ "\"timeseries\": false, "
+ "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []}"
"]" },
{ { sdb_store_le_matcher, SDB_FIELD_LAST_UPDATE,
{ SDB_TYPE_DATETIME, { .datetime = 1 * SDB_INTERVAL_SECOND } } },
SDB_METRIC, scan_tojson_full,
"["
- "{\"name\": \"h1\", \"last_update\": \"1970-01-01 00:00:01 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": [], "
- "\"metrics\": ["
- "{\"name\": \"m2\", "
- "\"timeseries\": false, "
- "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
- "\"update_interval\": \"0s\", \"backends\": []}"
- "]}"
+ "{\"name\": \"m2\", "
+ "\"timeseries\": false, "
+ "\"last_update\": \"1970-01-01 00:00:01 +0000\", "
+ "\"update_interval\": \"0s\", \"backends\": []}"
"]" },
{ { sdb_store_lt_matcher, SDB_FIELD_LAST_UPDATE,
{ SDB_TYPE_DATETIME, { .datetime = 0 } } },