Code

store: Let the JSON formatter know about arrays at top level.
authorSebastian Harl <sh@tokkee.org>
Sun, 2 Nov 2014 17:02:25 +0000 (18:02 +0100)
committerSebastian Harl <sh@tokkee.org>
Sun, 2 Nov 2014 17:05:02 +0000 (18:05 +0100)
There's no reason to require this to be handled separately.

src/core/store_json.c
src/frontend/query.c
src/include/core/store.h
t/unit/core/store_json_test.c

index d9fc37c4b30d498b3340fce1b238b177f57ad95d..b4b7b6a8af4b1becfb02431e43188325355f29b4 100644 (file)
@@ -52,6 +52,8 @@ struct sdb_store_json_formatter {
         * the path pointing to the current object */
        int context[8];
        size_t current;
+
+       int flags;
 };
 
 /*
@@ -105,7 +107,7 @@ json_emit(sdb_store_json_formatter_t *f, sdb_store_obj_t *obj)
  */
 
 sdb_store_json_formatter_t *
-sdb_store_json_formatter(sdb_strbuf_t *buf)
+sdb_store_json_formatter(sdb_strbuf_t *buf, int flags)
 {
        sdb_store_json_formatter_t *f;
 
@@ -119,6 +121,7 @@ sdb_store_json_formatter(sdb_strbuf_t *buf)
        f->buf = buf;
        f->context[0] = 0;
        f->current = 0;
+       f->flags = flags;
        return f;
 } /* sdb_store_json_formatter */
 
@@ -130,6 +133,8 @@ sdb_store_json_emit(sdb_store_json_formatter_t *f, sdb_store_obj_t *obj)
 
        /* first host */
        if (! f->context[0]) {
+               if (f->flags & SDB_WANT_ARRAY)
+                       sdb_strbuf_append(f->buf, "[");
                assert(f->current == 0);
                f->context[0] = SDB_HOST;
                return json_emit(f, obj);
@@ -228,12 +233,21 @@ sdb_store_json_finish(sdb_store_json_formatter_t *f)
        if (! f)
                return -1;
 
+       if (! f->context[0]) {
+               /* no content */
+               if (f->flags & SDB_WANT_ARRAY)
+                       sdb_strbuf_append(f->buf, "[]");
+               return 0;
+       }
+
        while (f->current > 0) {
                sdb_strbuf_append(f->buf, "}]");
                --f->current;
        }
-       if (f->context[0])
-               sdb_strbuf_append(f->buf, "}");
+
+       sdb_strbuf_append(f->buf, "}");
+       if (f->flags & SDB_WANT_ARRAY)
+               sdb_strbuf_append(f->buf, "]");
        return 0;
 } /* sdb_store_json_finish */
 
index dddf8424ad0d89fc5c9a4b10be757c353b669aa0..1ef36b351de41d9e3bf392075de68f375927f1dc 100644 (file)
@@ -390,7 +390,7 @@ sdb_fe_exec_lookup(sdb_conn_t *conn, int type,
                sdb_strbuf_sprintf(conn->errbuf, "Out of memory");
                return -1;
        }
-       f = sdb_store_json_formatter(buf);
+       f = sdb_store_json_formatter(buf, SDB_WANT_ARRAY);
        if (! f) {
                char errbuf[1024];
                sdb_log(SDB_LOG_ERR, "frontend: Failed to create "
@@ -403,7 +403,6 @@ sdb_fe_exec_lookup(sdb_conn_t *conn, int type,
        }
 
        sdb_strbuf_memcpy(buf, &res_type, sizeof(uint32_t));
-       sdb_strbuf_append(buf, "[");
 
        if (sdb_store_scan(SDB_HOST, m, filter, lookup_tojson, f)) {
                sdb_log(SDB_LOG_ERR, "frontend: Failed to lookup hosts");
@@ -414,8 +413,6 @@ sdb_fe_exec_lookup(sdb_conn_t *conn, int type,
        }
        sdb_store_json_finish(f);
 
-       sdb_strbuf_append(buf, "]");
-
        sdb_connection_send(conn, CONNECTION_DATA,
                        (uint32_t)sdb_strbuf_len(buf), sdb_strbuf_string(buf));
        sdb_strbuf_destroy(buf);
index 6dd7d1ade1ca98b952a4ce05a8b1a4f6bc21fa49..df959eab25396d03e67e8ab24f075a9086be77f1 100644 (file)
@@ -89,7 +89,7 @@ typedef struct sdb_store_matcher sdb_store_matcher_t;
 #define SDB_STORE_MATCHER(obj) ((sdb_store_matcher_t *)(obj))
 
 /*
- * A JSON formatter converts a stored object into the JSON format.
+ * A JSON formatter converts stored objects into the JSON format.
  * See http://www.ietf.org/rfc/rfc4627.txt
  */
 struct sdb_store_json_formatter;
@@ -577,6 +577,8 @@ sdb_store_scan(int type, sdb_store_matcher_t *m, sdb_store_matcher_t *filter,
  * out. The SKIP_EMPTY flags may be used to skip host objects entirely.
  */
 enum {
+       SDB_WANT_ARRAY              = 1 << 0,
+
        SDB_SKIP_ATTRIBUTES         = 1 << 0,
        SDB_SKIP_SERVICES           = 1 << 1,
        SDB_SKIP_METRICS            = 1 << 2,
@@ -624,7 +626,7 @@ sdb_store_host_tojson(sdb_store_obj_t *host, sdb_strbuf_t *buf,
  * Create a JSON formatter writing to the specified buffer.
  */
 sdb_store_json_formatter_t *
-sdb_store_json_formatter(sdb_strbuf_t *buf);
+sdb_store_json_formatter(sdb_strbuf_t *buf, int flags);
 
 /*
  * sdb_store_json_emit:
index ee0db2fa15469bd9f8abe09f3007167fc8851131..c544633e3e4e1b189ebcd180687957fcfeaf2f17 100644 (file)
@@ -236,6 +236,9 @@ START_TEST(test_store_tojson)
                                "{\"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,
+                       "[]" },
        };
 
        buf = sdb_strbuf_create(0);
@@ -269,17 +272,15 @@ START_TEST(test_store_tojson)
                }
 
                sdb_strbuf_clear(buf);
-               f = sdb_store_json_formatter(buf);
+               f = sdb_store_json_formatter(buf, SDB_WANT_ARRAY);
                assert(f);
 
-               sdb_strbuf_append(buf, "[");
                status = sdb_store_scan(SDB_HOST, /* m = */ NULL, filter,
                                golden_data[i].f, f);
                fail_unless(status == 0,
                                "sdb_store_scan(HOST, ..., tojson) = %d; expected: 0",
                                status);
                sdb_store_json_finish(f);
-               sdb_strbuf_append(buf, "]");
 
                verify_json_output(buf, golden_data[i].expected);
                free(f);