summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 61c35f1)
raw | patch | inline | side by side (parent: 61c35f1)
author | Sebastian Harl <sh@tokkee.org> | |
Sun, 18 Dec 2016 13:47:41 +0000 (14:47 +0100) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Sun, 18 Dec 2016 13:47:41 +0000 (14:47 +0100) |
JSON is really not what users wanna see, even if it's pretty-printed ;-)
Instead, use a simple key/value style output.
Instead, use a simple key/value style output.
src/include/core/store.h | patch | blob | history | |
src/tools/sysdb/command.c | patch | blob | history | |
src/tools/sysdb/json.c | patch | blob | history | |
src/tools/sysdb/json.h | patch | blob | history |
index f0fc0c7d779cf4504eb67f316c6846c8f7e99303..5e8a2a77be0a6257eda63f2196c250027612b491 100644 (file)
--- a/src/include/core/store.h
+++ b/src/include/core/store.h
SDB_METRIC,
SDB_ATTRIBUTE = 1 << 4,
+ SDB_TIMESERIES = 1 << 6,
/*
* Queryable fields of a stored object.
: ((t) == (SDB_ATTRIBUTE | SDB_HOST)) ? "host attribute" \
: ((t) == (SDB_ATTRIBUTE | SDB_SERVICE)) ? "service attribute" \
: ((t) == (SDB_ATTRIBUTE | SDB_METRIC)) ? "metric attribute" \
+ : ((t) == SDB_TIMESERIES) ? "timeseries" \
: "unknown")
#define SDB_FIELD_TO_NAME(f) \
index dd8b2980c7ca6efb784bd7c6e8a889618d207596..61960be83505ca167e4045f6a225854b9aeb0946 100644 (file)
data_printer(sdb_input_t __attribute__((unused)) *input, sdb_strbuf_t *buf)
{
size_t len = sdb_strbuf_len(buf);
+ uint32_t type = 0;
if ((! len) || (len == sizeof(uint32_t))) {
/* empty command or empty reply */
return;
}
- /* At the moment, we don't care about the result type. We simply print the
- * result without further parsing it. */
+ sdb_proto_unmarshal_int32(SDB_STRBUF_STR(buf), &type);
sdb_strbuf_skip(buf, 0, sizeof(uint32_t));
- if (sdb_json_print(input, buf))
+ if (sdb_json_print(input, (int)type, buf))
sdb_log(SDB_LOG_ERR, "Failed to print result");
printf("\n");
} /* data_printer */
diff --git a/src/tools/sysdb/json.c b/src/tools/sysdb/json.c
index 4f36179b02c823161487c6c0351c9c841351824c..1bd8080970b831fe5a00c1dd586e887ee616e8e5 100644 (file)
--- a/src/tools/sysdb/json.c
+++ b/src/tools/sysdb/json.c
#include "sysdb.h"
+#include "core/store.h"
+#include "frontend/proto.h"
#include "utils/error.h"
#include "utils/strbuf.h"
#include "tools/sysdb/json.h"
#ifdef HAVE_LIBYAJL
# include <yajl/yajl_parse.h>
-# include <yajl/yajl_gen.h>
#endif
-#include <unistd.h>
+#include <stdbool.h>
#include <stdio.h>
+#include <string.h>
#ifdef HAVE_LIBYAJL
/*
- * YAJL callbacks
+ * formatter
*/
-#define GEN(obj) ((yajl_gen)(obj))
-#define OK(cb) ((cb) == yajl_gen_status_ok)
+typedef struct {
+ /* The context describes the state of the formatter along with the
+ * respective parent contexts. */
+ int context[8];
+ ssize_t array_indices[8];
+ size_t current;
+ int next_context;
+
+ bool have_output;
+} formatter_t;
+#define F(obj) ((formatter_t *)(obj))
+#define F_INIT { { 0 }, { -1, -1, -1, -1, -1, -1, -1, -1 }, 0, 0, false }
static int
-gen_null(void *ctx) { return OK(yajl_gen_null(GEN(ctx))); }
+push(formatter_t *f, int type)
+{
+ f->current++;
+ if (f->current >= SDB_STATIC_ARRAY_LEN(f->context)) {
+ sdb_log(SDB_LOG_ERR, "Nesting level too deep");
+ return false;
+ }
+ f->context[f->current] = type;
+ return true;
+} /* push */
+
+static void
+pop(formatter_t *f)
+{
+ if (f->current == 0)
+ return;
+
+ f->next_context = f->context[f->current];
+ f->current--;
+} /* pop */
+
+static void
+print(formatter_t *f, const char *s, ssize_t l)
+{
+ if (l >= 0) {
+ /* 's' may point into a larger buffer and not be null-terminated */
+ char buf[l + 1];
+ strncpy(buf, s, l);
+ buf[l] = '\0';
+ printf("%s", buf);
+ }
+ else
+ printf("%s", s);
+
+ f->have_output = true;
+} /* print */
+
+static void
+indent(formatter_t *f)
+{
+ size_t i;
+ for (i = 0; i < f->current - 1; i++)
+ print(f, "\t", -1);
+}
+
+static void
+format(formatter_t *f, const char *s, ssize_t l)
+{
+ if (f->array_indices[f->current] >= 0) {
+ if (f->array_indices[f->current] != 0)
+ print(f, ", ", -1);
+ f->array_indices[f->current]++;
+ }
+
+ print(f, s, l);
+ return;
+} /* format */
static int
-gen_boolean(void *ctx, int v) { return OK(yajl_gen_bool(GEN(ctx), v)); }
+format_key(formatter_t *f, const char *k, ssize_t l)
+{
+ int type = 0;
+
+ if (! strncasecmp("services", k, l))
+ type = SDB_SERVICE;
+ else if (! strncasecmp("metrics", k, l))
+ type = SDB_METRIC;
+ else if (! strncasecmp("attributes", k, l))
+ type = SDB_ATTRIBUTE;
+
+ if (f->have_output)
+ print(f, "\n", -1);
+ indent(f);
+ print(f, k, l);
+ print(f, ": ", -1);
+
+ f->next_context = type;
+ return true;
+} /* format_key */
+
+/*
+ * YAJL callbacks
+ */
static int
-gen_number(void *ctx, const char *v, size_t l)
+fmt_null(void *ctx) {
+ formatter_t *f = F(ctx);
+ format(f, "NULL", -1);
+ return true;
+}
+
+static int
+fmt_boolean(void *ctx, int v) {
+ formatter_t *f = F(ctx);
+ if (v)
+ format(f, "true", -1);
+ else
+ format(f, "false", -1);
+ return true;
+}
+
+static int
+fmt_number(void *ctx, const char *v, size_t l)
{
- return OK(yajl_gen_number(GEN(ctx), v, l));
+ formatter_t *f = F(ctx);
+ format(f, v, l);
+ return true;
}
static int
-gen_string(void *ctx, const unsigned char *v, size_t l)
+fmt_string(void *ctx, const unsigned char *v, size_t l)
{
- return OK(yajl_gen_string(GEN(ctx), v, l));
+ formatter_t *f = F(ctx);
+ format(f, (const char *)v, l);
+ return true;
+}
+
+static int
+fmt_start_map(void *ctx) {
+ formatter_t *f = F(ctx);
+ const char *name;
+
+ if (!push(f, f->next_context))
+ return false;
+
+ if (f->have_output)
+ print(f, "\n", -1);
+
+ name = SDB_STORE_TYPE_TO_NAME(f->context[f->current]);
+ if (strcmp(name, "unknown")) {
+ if (f->have_output)
+ print(f, "\n", -1);
+ indent(f);
+ format(f, name, -1);
+ }
+ return true;
}
static int
-gen_start_map(void *ctx) { return OK(yajl_gen_map_open(GEN(ctx))); }
+fmt_map_key(void *ctx, const unsigned char *v, size_t l)
+{
+ formatter_t *f = F(ctx);
+ return format_key(f, (const char *)v, l);
+}
static int
-gen_end_map(void *ctx) { return OK(yajl_gen_map_close(GEN(ctx))); }
+fmt_end_map(void *ctx) {
+ formatter_t *f = F(ctx);
+ pop(f);
+ return true;
+}
static int
-gen_start_array(void *ctx) { return OK(yajl_gen_array_open(GEN(ctx))); }
+fmt_start_array(void *ctx) {
+ formatter_t *f = F(ctx);
+ f->array_indices[f->current] = 0;
+ return true;
+}
static int
-gen_end_array(void *ctx) { return OK(yajl_gen_array_close(GEN(ctx))); }
-
-static yajl_callbacks reformatters = {
- gen_null,
- gen_boolean,
- NULL, /* gen_integer; */
- NULL, /* gen_doube; both default to gen_number */
- gen_number,
- gen_string,
- gen_start_map,
- gen_string,
- gen_end_map,
- gen_start_array,
- gen_end_array,
-};
+fmt_end_array(void *ctx) {
+ formatter_t *f = F(ctx);
+ f->array_indices[f->current] = -1;
+ return true;
+}
-static void
-printer(void __attribute__((unused)) *ctx, const char *str, size_t len)
-{
- write(1, str, len);
-} /* printer */
+static yajl_callbacks fmts = {
+ fmt_null,
+ fmt_boolean,
+ NULL, /* fmt_integer; */
+ NULL, /* fmt_double; both default to fmt_number */
+ fmt_number,
+ fmt_string,
+ fmt_start_map,
+ fmt_map_key,
+ fmt_end_map,
+ fmt_start_array,
+ fmt_end_array,
+};
#endif /* HAVE_LIBYAJL */
*/
int
-sdb_json_print(sdb_input_t *input, sdb_strbuf_t *buf)
+sdb_json_print(sdb_input_t *input, int type, sdb_strbuf_t *buf)
{
#ifdef HAVE_LIBYAJL
const unsigned char *json;
size_t json_len;
yajl_handle h;
- yajl_gen gen;
yajl_status status;
+ formatter_t f = F_INIT;
int ret = 0;
return 0;
}
- gen = yajl_gen_alloc(/* alloc_funcs */ NULL);
- if (! gen)
- return -1;
-
- yajl_gen_config(gen, yajl_gen_beautify, 1);
- yajl_gen_config(gen, yajl_gen_validate_utf8, 1);
- yajl_gen_config(gen, yajl_gen_print_callback, printer, NULL);
+ /* Store lookups always return hosts at the top-level. */
+ f.context[0] = SDB_HOST;
+ switch (type) {
+ case SDB_CONNECTION_LIST:
+ case SDB_CONNECTION_LOOKUP:
+ /* Array types */
+ f.array_indices[0] = 0;
+ break;
+ case SDB_CONNECTION_TIMESERIES:
+ f.context[0] = SDB_TIMESERIES;
+ break;
+ }
+ f.next_context = f.context[0];
- h = yajl_alloc(&reformatters, /* alloc_funcs */ NULL, (void *)gen);
- if (! h) {
- yajl_gen_free(gen);
+ h = yajl_alloc(&fmts, /* alloc_funcs */ NULL, &f);
+ if (! h)
return -1;
- }
json = (const unsigned char *)sdb_strbuf_string(buf);
json_len = sdb_strbuf_len(buf);
ret = -1;
}
- yajl_gen_free(gen);
yajl_free(h);
return ret;
#else /* HAVE_LIBYAJL */
(void)input;
+ (void)type;
printf("%s\n", sdb_strbuf_string(buf));
return 0;
#endif /* HAVE_LIBYAJL */
diff --git a/src/tools/sysdb/json.h b/src/tools/sysdb/json.h
index 08def61f726e361b94bf028b8098722740196066..b276eff82b62b64732a42258b7d98bfaa66eda66 100644 (file)
--- a/src/tools/sysdb/json.h
+++ b/src/tools/sysdb/json.h
/*
* sdb_json_print:
- * Format the JSON string stored in the specified buffer. The output is
- * printed to the standard output channel.
+ * Format the JSON object of the specified type. The raw JSON is read from the
+ * specified buffer. The output is printed to the standard output channel.
*/
int
-sdb_json_print(sdb_input_t *input, sdb_strbuf_t *buf);
+sdb_json_print(sdb_input_t *input, int type, sdb_strbuf_t *buf);
#endif /* SYSDB_JSON_H */