Code

Let the network protocol and SysQL support last_update for metric stores.
authorSebastian Harl <sh@tokkee.org>
Mon, 5 Sep 2016 01:18:00 +0000 (21:18 -0400)
committerSebastian Harl <sh@tokkee.org>
Mon, 5 Sep 2016 01:18:00 +0000 (21:18 -0400)
doc/sysdbql.7.txt
src/frontend/query.c
src/include/parser/ast.h
src/include/utils/proto.h
src/parser/ast.c
src/parser/grammar.y
src/plugins/store/network.c
src/utils/proto.c
t/unit/core/store_test.c
t/unit/parser/parser_test.c
t/unit/utils/proto_test.c

index ceb58347a2cf64ac4ea37c93da806370197c265b..587cd6cc72bee0fe71d2f046480bea47aa9f59de 100644 (file)
@@ -263,7 +263,7 @@ storing the different data types:
        provided as well. If omitted, the current time on the server will be used
        instead.
 
-*STORE* metric '<hostname>'.'<name>' STORE '<type>' '<id>' [*LAST UPDATE* '<datetime>']::
+*STORE* metric '<hostname>'.'<name>' STORE '<type>' '<id>' ['<datetime>'] [*LAST UPDATE* '<datetime>']::
        Store a metric and provide information about the metric store associated
        with it. A metric store describes how to access a metric's data and can be
        used to retrieve time-series information associated with the metric. See
index 5d00636dd99e77219303c645bdf019f8ac59bfeb..3f33a9914b7bfd342727f73e4ae74134ef9c1b11 100644 (file)
@@ -158,7 +158,7 @@ exec_store(sdb_ast_store_t *st, sdb_strbuf_t *buf, sdb_strbuf_t *errbuf)
                snprintf(name, sizeof(name), "%s.%s", st->hostname, st->name);
                metric_store.type = st->store_type;
                metric_store.id = st->store_id;
-               metric_store.last_update = st->last_update;
+               metric_store.last_update = st->store_last_update;
                status = sdb_plugin_store_metric(st->hostname, st->name,
                                &metric_store, st->last_update);
                break;
@@ -510,7 +510,7 @@ sdb_conn_store(sdb_conn_t *conn)
                        }
                        ast = sdb_ast_store_create(SDB_HOST, /* host */ NULL,
                                        /* parent */ 0, NULL, sstrdup(host.name), host.last_update,
-                                       /* metric store */ NULL, NULL, SDB_DATA_NULL);
+                                       /* metric store */ NULL, NULL, 0, SDB_DATA_NULL);
                }
                break;
 
@@ -524,7 +524,7 @@ sdb_conn_store(sdb_conn_t *conn)
                        }
                        ast = sdb_ast_store_create(SDB_SERVICE, sstrdup(svc.hostname),
                                        /* parent */ 0, NULL, sstrdup(svc.name), svc.last_update,
-                                       /* metric store */ NULL, NULL, SDB_DATA_NULL);
+                                       /* metric store */ NULL, NULL, 0, SDB_DATA_NULL);
                }
                break;
 
@@ -539,7 +539,7 @@ sdb_conn_store(sdb_conn_t *conn)
                        ast = sdb_ast_store_create(SDB_METRIC, sstrdup(metric.hostname),
                                        /* parent */ 0, NULL, sstrdup(metric.name), metric.last_update,
                                        sstrdup(metric.store_type), sstrdup(metric.store_id),
-                                       SDB_DATA_NULL);
+                                       metric.store_last_update, SDB_DATA_NULL);
                }
                break;
        }
@@ -565,7 +565,7 @@ sdb_conn_store(sdb_conn_t *conn)
                }
                ast = sdb_ast_store_create(SDB_ATTRIBUTE, sstrdup(hostname),
                                parent_type, sstrdup(parent), sstrdup(attr.key),
-                               attr.last_update, /* metric store */ NULL, NULL,
+                               attr.last_update, /* metric store */ NULL, NULL, 0,
                                attr.value);
        }
 
index 01446abbd84b86e4b0395e2715f700fbad04a9dd..4272ec04f1285e71f0493b7d216d1be717ecaa66 100644 (file)
@@ -309,6 +309,7 @@ typedef struct {
        /* metric specific */
        char *store_type;
        char *store_id;
+       sdb_time_t store_last_update;
 
        /* attribute specific */
        sdb_data_t value;
@@ -316,7 +317,7 @@ typedef struct {
 #define SDB_AST_STORE(obj) ((sdb_ast_store_t *)(obj))
 #define SDB_AST_STORE_INIT \
        { { SDB_OBJECT_INIT, SDB_AST_TYPE_STORE, -1 }, \
-               -1, NULL, -1, NULL, NULL, 0, NULL, NULL, SDB_DATA_INIT }
+               -1, NULL, -1, NULL, NULL, 0, NULL, NULL, 0, SDB_DATA_INIT }
 
 /*
  * sdb_ast_timeseries_t represents a TIMESERIES command.
@@ -418,7 +419,8 @@ sdb_ast_lookup_create(int obj_type, sdb_ast_node_t *matcher,
 sdb_ast_node_t *
 sdb_ast_store_create(int obj_type, char *hostname,
                int parent_type, char *parent, char *name, sdb_time_t last_update,
-               char *store_type, char *store_id, sdb_data_t value);
+               char *store_type, char *store_id, sdb_time_t store_last_update,
+               sdb_data_t value);
 
 /*
  * sdb_ast_timeseries_create:
index 56715630524594a71e524932def3f1a01a9f7670..a9ea1e321d4368fb61ae87fda233056e561b7cf2 100644 (file)
@@ -61,8 +61,9 @@ typedef struct {
        const char *name;
        const char *store_type; /* optional */
        const char *store_id;   /* optional */
+       sdb_time_t store_last_update; /* optional */
 } sdb_proto_metric_t;
-#define SDB_PROTO_METRIC_INIT { 0, NULL, NULL, NULL, NULL }
+#define SDB_PROTO_METRIC_INIT { 0, NULL, NULL, NULL, NULL, 0 }
 
 typedef struct {
        sdb_time_t last_update;
index dcfe7862bd0b73c891ea017796a28cc626cf0589..96c05ffa612ab22fb4e28658912b98b48c65bc1a 100644 (file)
@@ -347,7 +347,8 @@ sdb_ast_lookup_create(int obj_type, sdb_ast_node_t *matcher,
 sdb_ast_node_t *
 sdb_ast_store_create(int obj_type, char *hostname,
                int parent_type, char *parent, char *name, sdb_time_t last_update,
-               char *store_type, char *store_id, sdb_data_t value)
+               char *store_type, char *store_id, sdb_time_t store_last_update,
+               sdb_data_t value)
 {
        sdb_ast_store_t *store;
        store = SDB_AST_STORE(sdb_object_create("STORE", st_type));
@@ -364,6 +365,7 @@ sdb_ast_store_create(int obj_type, char *hostname,
        store->last_update = last_update;
        store->store_type = store_type;
        store->store_id = store_id;
+       store->store_last_update = store_last_update;
        store->value = value;
        return SDB_AST_NODE(store);
 } /* sdb_ast_store_create */
index c350d54365a03c5d9d8cb9faaf00234064f4ace5..6654780c185ddcd88ad3d3d8517fc48c1e566813 100644 (file)
@@ -104,7 +104,7 @@ sdb_parser_yyerrorf(YYLTYPE *lval, sdb_parser_yyscan_t scanner, const char *fmt,
        sdb_llist_t    *list;
        sdb_ast_node_t *node;
 
-       struct { char *type; char *id; } metric_store;
+       struct { char *type; char *id; sdb_time_t last_update; } metric_store;
 }
 
 %start statements
@@ -339,42 +339,42 @@ store_statement:
        STORE HOST_T STRING last_update_clause
                {
                        $$ = sdb_ast_store_create(SDB_HOST, NULL, 0, NULL,
-                                       $3, $4, NULL, NULL, SDB_DATA_NULL);
+                                       $3, $4, NULL, NULL, 0, SDB_DATA_NULL);
                        CK_OOM($$);
                }
        |
        STORE SERVICE_T STRING '.' STRING last_update_clause
                {
                        $$ = sdb_ast_store_create(SDB_SERVICE, $3, 0, NULL,
-                                       $5, $6, NULL, NULL, SDB_DATA_NULL);
+                                       $5, $6, NULL, NULL, 0, SDB_DATA_NULL);
                        CK_OOM($$);
                }
        |
        STORE METRIC_T STRING '.' STRING metric_store_clause last_update_clause
                {
                        $$ = sdb_ast_store_create(SDB_METRIC, $3, 0, NULL,
-                                       $5, $7, $6.type, $6.id, SDB_DATA_NULL);
+                                       $5, $7, $6.type, $6.id, $6.last_update, SDB_DATA_NULL);
                        CK_OOM($$);
                }
        |
        STORE HOST_T ATTRIBUTE_T STRING '.' STRING data last_update_clause
                {
                        $$ = sdb_ast_store_create(SDB_ATTRIBUTE, $4, 0, NULL,
-                                       $6, $8, NULL, NULL, $7);
+                                       $6, $8, NULL, NULL, 0, $7);
                        CK_OOM($$);
                }
        |
        STORE SERVICE_T ATTRIBUTE_T STRING '.' STRING '.' STRING data last_update_clause
                {
                        $$ = sdb_ast_store_create(SDB_ATTRIBUTE, $4, SDB_SERVICE, $6,
-                                       $8, $10, NULL, NULL, $9);
+                                       $8, $10, NULL, NULL, 0, $9);
                        CK_OOM($$);
                }
        |
        STORE METRIC_T ATTRIBUTE_T STRING '.' STRING '.' STRING data last_update_clause
                {
                        $$ = sdb_ast_store_create(SDB_ATTRIBUTE, $4, SDB_METRIC, $6,
-                                       $8, $10, NULL, NULL, $9);
+                                       $8, $10, NULL, NULL, 0, $9);
                        CK_OOM($$);
                }
        ;
@@ -385,9 +385,11 @@ last_update_clause:
        /* empty */ { $$ = sdb_gettime(); }
 
 metric_store_clause:
-       STORE STRING STRING { $$.type = $2; $$.id = $3; }
+       STORE STRING STRING datetime { $$.type = $2; $$.id = $3; $$.last_update = $4; }
        |
-       /* empty */ { $$.type = $$.id = NULL; }
+       STORE STRING STRING { $$.type = $2; $$.id = $3; $$.last_update = 0; }
+       |
+       /* empty */ { $$.type = $$.id = NULL; $$.last_update = 0; }
 
 /*
  * TIMESERIES <host>.<metric> [START <datetime>] [END <datetime>];
index 8223d389a496f1ed85995ce8f2f318a8a16a9940..77012b95bf9cab931c6a02e7f06685cd57e0c68d 100644 (file)
@@ -149,7 +149,7 @@ store_metric(sdb_store_metric_t *metric, sdb_object_t *user_data)
 {
        sdb_proto_metric_t m = {
                metric->last_update, metric->hostname, metric->name,
-               metric->store.type, metric->store.id,
+               metric->store.type, metric->store.id, metric->store.last_update,
        };
        size_t len = sdb_proto_marshal_metric(NULL, 0, &m);
        char buf[len];
index f8265d6861da71335da53a88d3c932b713c718e6..61676266ead9cc14a49049cc85a5f5dbe1a96031 100644 (file)
@@ -466,8 +466,11 @@ sdb_proto_marshal_metric(char *buf, size_t buf_len,
                return -1;
 
        len = OBJ_HEADER_LEN + strlen(metric->hostname) + strlen(metric->name) + 2;
-       if (metric->store_type && metric->store_id)
+       if (metric->store_type && metric->store_id) {
                len += strlen(metric->store_type) + strlen(metric->store_id) + 2;
+               if (metric->store_last_update > 0)
+                       len += sizeof(sdb_time_t);
+       }
        if (buf_len < len)
                return len;
 
@@ -480,7 +483,12 @@ sdb_proto_marshal_metric(char *buf, size_t buf_len,
        if (metric->store_type && metric->store_id) {
                n = marshal_string(buf, buf_len, metric->store_type);
                buf += n; buf_len -= n;
-               marshal_string(buf, buf_len, metric->store_id);
+               n = marshal_string(buf, buf_len, metric->store_id);
+               buf += n; buf_len -= n;
+               if (metric->store_last_update > 0) {
+                       n = marshal_datetime(buf, buf_len, metric->store_last_update);
+                       buf += n; buf_len -= n;
+               }
        }
        return len;
 } /* sdb_proto_marshal_metric */
@@ -771,6 +779,8 @@ sdb_proto_unmarshal_metric(const char *buf, size_t len,
        buf += n; len -= n; l += n;
        if ((n = unmarshal_string(buf, len, metric ? &metric->name : NULL)) < 0)
                return n;
+
+       metric->store_last_update = 0;
        if (len > (size_t)n) {
                buf += n; len -= n; l += n;
                if ((n = unmarshal_string(buf, len,
@@ -780,6 +790,12 @@ sdb_proto_unmarshal_metric(const char *buf, size_t len,
                if ((n = unmarshal_string(buf, len,
                                                metric ? &metric->store_id : NULL)) < 0)
                        return n;
+               if (len >= sizeof(sdb_time_t)) {
+                       buf += n; len -= n; l += n;
+                       if ((n = unmarshal_datetime(buf, len,
+                                                       metric ? &metric->store_last_update : NULL)) < 0)
+                               return n;
+               }
        }
        else if (metric) {
                metric->store_type = NULL;
index 96ac0c1d67356eabbb59d885a75d2be6f1b48398..d6a44e09f13ab01e095ecae6a64db3246e74e083 100644 (file)
@@ -280,16 +280,6 @@ START_TEST(test_store_metric)
                                golden_data[i].host, golden_data[i].metric,
                                golden_data[i].store, golden_data[i].last_update,
                                status, golden_data[i].expected);
-
-               if (status < 0)
-                       continue;
-
-               if (golden_data[i].store != NULL)
-                       fail_unless(golden_data[i].store->last_update > 0,
-                                       "sdb_memstore_metric(%s, %s, %p, %d, 0) did not update "
-                                       "store->last_update",
-                                       golden_data[i].host, golden_data[i].metric,
-                                       golden_data[i].store, golden_data[i].last_update);
        }
 }
 END_TEST
index f6601f164ed2f34cdfa652a0b23dbc5f667a8447..14977ff820f91e63dfc69b822fdcf98f2ebc5c38 100644 (file)
@@ -220,6 +220,11 @@ struct {
          "STORE 'typ' 'id' "
          "LAST UPDATE "
          "2015-02-01",          -1,  1, SDB_AST_TYPE_STORE, SDB_METRIC },
+       { "STORE metric "
+         "'host'.'metric' "
+         "STORE 'typ' 'id' 2015-02-01 13:37 "
+         "LAST UPDATE "
+         "2015-02-01",          -1,  1, SDB_AST_TYPE_STORE, SDB_METRIC },
        { "STORE metric attribute "
          "'host'.'metric'.'key' "
          "123",                 -1,  1, SDB_AST_TYPE_STORE, SDB_ATTRIBUTE },
index 7e2e9b9b3cab209cfefde542c50bfcfe35fbade0..bc5f910d117bcf599497538a4202e0c447964263 100644 (file)
@@ -376,28 +376,36 @@ START_TEST(test_marshal_metric)
                char *expected;
        } golden_data[] = {
                {
-                       { 4711, "hostA", "metricX", NULL, NULL },
+                       { 4711, "hostA", "metricX", NULL, NULL, 0 },
                        26, METRIC_TYPE "\0\0\0\0\0\0\x12\x67" "hostA\0metricX\0"
                },
                {
-                       { 0, "hostA", "metricX", NULL, NULL },
+                       { 0, "hostA", "metricX", NULL, NULL, 0 },
                        26, METRIC_TYPE "\0\0\0\0\0\0\0\0" "hostA\0metricX\0"
                },
                {
-                       { 0, "hostA", "metricX", "type", NULL },
+                       { 0, "hostA", "metricX", "type", NULL, 0 },
                        26, METRIC_TYPE "\0\0\0\0\0\0\0\0" "hostA\0metricX\0"
                },
                {
-                       { 0, "hostA", "metricX", NULL, "id" },
+                       { 0, "hostA", "metricX", NULL, "id", 0 },
                        26, METRIC_TYPE "\0\0\0\0\0\0\0\0" "hostA\0metricX\0"
                },
                {
-                       { 4711, "hostA", "metricX", "type", "id" },
+                       { 0, "hostA", "metricX", NULL, NULL, 4711 },
+                       26, METRIC_TYPE "\0\0\0\0\0\0\0\0" "hostA\0metricX\0"
+               },
+               {
+                       { 4711, "hostA", "metricX", "type", "id", 0 },
                        34, METRIC_TYPE "\0\0\0\0\0\0\x12\x67" "hostA\0metricX\0type\0id\0"
                },
-               { { 4711, "hostA", NULL, NULL, NULL }, -1, NULL },
-               { { 4711, NULL, "metricX", NULL, NULL }, -1, NULL },
-               { { 4711, NULL, NULL, NULL, NULL }, -1, NULL },
+               {
+                       { 4711, "hostA", "metricX", "type", "id", 4711 },
+                       42, METRIC_TYPE "\0\0\0\0\0\0\x12\x67" "hostA\0metricX\0type\0id\0" "\0\0\0\0\0\0\x12\x67"
+               },
+               { { 4711, "hostA", NULL, NULL, NULL, 0 }, -1, NULL },
+               { { 4711, NULL, "metricX", NULL, NULL, 0 }, -1, NULL },
+               { { 4711, NULL, NULL, NULL, NULL, 0 }, -1, NULL },
        };
 
        size_t i;
@@ -434,9 +442,10 @@ START_TEST(test_marshal_metric)
 
                if ((! golden_data[i].metric.store_type)
                                || (! golden_data[i].metric.store_id)) {
-                       /* if any of these is NULL, we expect both to be NULL */
+                       /* if any of these is NULL, we expect all to be NULL */
                        golden_data[i].metric.store_type = NULL;
                        golden_data[i].metric.store_id = NULL;
+                       golden_data[i].metric.store_last_update = 0;
                }
 
                check = sdb_proto_unmarshal_metric(buf, len, &metric);
@@ -447,15 +456,18 @@ START_TEST(test_marshal_metric)
                                && streq(metric.hostname, golden_data[i].metric.hostname)
                                && streq(metric.name, golden_data[i].metric.name)
                                && streq(metric.store_type, golden_data[i].metric.store_type)
-                               && streq(metric.store_id, golden_data[i].metric.store_id),
+                               && streq(metric.store_id, golden_data[i].metric.store_id)
+                               && metric.store_last_update == golden_data[i].metric.store_last_update,
                                "<%zu> sdb_proto_unmarshal_metric(buf<%s>) = "
-                               "{ %"PRIsdbTIME", %s, %s, %s, %s }; expected: "
-                               "{ %"PRIsdbTIME", %s, %s, %s, %s }", i, golden_data[i].metric.name,
+                               "{ %"PRIsdbTIME", %s, %s, %s, %s, %"PRIsdbTIME" }; expected: "
+                               "{ %"PRIsdbTIME", %s, %s, %s, %s, %"PRIsdbTIME" }",
+                               i, golden_data[i].metric.name,
                                metric.last_update, metric.hostname, metric.name,
-                               metric.store_type, metric.store_id,
+                               metric.store_type, metric.store_id, metric.store_last_update,
                                golden_data[i].metric.last_update,
                                golden_data[i].metric.hostname, golden_data[i].metric.name,
-                               golden_data[i].metric.store_type, golden_data[i].metric.store_id);
+                               golden_data[i].metric.store_type, golden_data[i].metric.store_id,
+                               golden_data[i].metric.store_last_update);
        }
 }
 END_TEST