From cd9116c6aad5517b0232c3ae357c6dd81b56024f Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sat, 10 Jan 2015 14:02:31 +0100 Subject: [PATCH] frontend/grammar: Added 'STORE host|service|metric [attribute]' commands. This implements the STORE command in SysQL. --- src/frontend/analyzer.c | 14 ++++- src/frontend/connection-private.h | 91 +++++++++++++++++++++++++++ src/frontend/grammar.y | 101 +++++++++++++++++++++++++++++- src/frontend/query.c | 30 +++++++++ src/frontend/scanner.l | 3 + src/include/frontend/proto.h | 6 ++ 6 files changed, 242 insertions(+), 3 deletions(-) diff --git a/src/frontend/analyzer.c b/src/frontend/analyzer.c index 8d228c4..894cc22 100644 --- a/src/frontend/analyzer.c +++ b/src/frontend/analyzer.c @@ -322,10 +322,20 @@ sdb_fe_analyze(sdb_conn_node_t *node, sdb_strbuf_t *errbuf) filter = CONN_LOOKUP(node)->filter->matcher; context = CONN_LOOKUP(node)->type; } - else if (node->cmd == SDB_CONNECTION_TIMESERIES) + else if ((node->cmd == SDB_CONNECTION_STORE_HOST) + || (node->cmd == SDB_CONNECTION_STORE_SERVICE) + || (node->cmd == SDB_CONNECTION_STORE_METRIC) + || (node->cmd == SDB_CONNECTION_STORE_ATTRIBUTE)) { return 0; - else + } + else if (node->cmd == SDB_CONNECTION_TIMESERIES) { + return 0; + } + else { + sdb_strbuf_sprintf(errbuf, + "Don't know how to analyze command %#x", node->cmd); return -1; + } if (analyze_matcher(context, m, errbuf)) status = -1; diff --git a/src/frontend/connection-private.h b/src/frontend/connection-private.h index 1e5e9e5..361af16 100644 --- a/src/frontend/connection-private.h +++ b/src/frontend/connection-private.h @@ -117,6 +117,42 @@ typedef struct { } conn_lookup_t; #define CONN_LOOKUP(obj) ((conn_lookup_t *)(obj)) +typedef struct { + sdb_conn_node_t super; + char *name; + sdb_time_t last_update; +} conn_store_host_t; +#define CONN_STORE_HOST(obj) ((conn_store_host_t *)(obj)) + +typedef struct { + sdb_conn_node_t super; + char *hostname; + char *name; + sdb_time_t last_update; +} conn_store_svc_t; +#define CONN_STORE_SVC(obj) ((conn_store_svc_t *)(obj)) + +typedef struct { + sdb_conn_node_t super; + char *hostname; + char *name; + char *store_type; /* optional */ + char *store_id; /* optional */ + sdb_time_t last_update; +} conn_store_metric_t; +#define CONN_STORE_METRIC(obj) ((conn_store_metric_t *)(obj)) + +typedef struct { + sdb_conn_node_t super; + int parent_type; + char *hostname; /* optional */ + char *parent; + char *key; + sdb_data_t value; + sdb_time_t last_update; +} conn_store_attr_t; +#define CONN_STORE_ATTR(obj) ((conn_store_attr_t *)(obj)) + typedef struct { sdb_conn_node_t super; char *hostname; @@ -164,6 +200,61 @@ conn_lookup_destroy(sdb_object_t *obj) sdb_object_deref(SDB_OBJ(CONN_LOOKUP(obj)->filter)); } /* conn_lookup_destroy */ +static void __attribute__((unused)) +conn_store_host_destroy(sdb_object_t *obj) +{ + conn_store_host_t *host = CONN_STORE_HOST(obj); + if (host->name) + free((void *)host->name); + host->name = NULL; +} /* conn_store_host_destroy */ + +static void __attribute__((unused)) +conn_store_svc_destroy(sdb_object_t *obj) +{ + conn_store_svc_t *svc = CONN_STORE_SVC(obj); + if (svc->hostname) + free((void *)svc->hostname); + svc->hostname = NULL; + if (svc->name) + free((void *)svc->name); + svc->name = NULL; +} /* conn_store_svc_destroy */ + +static void __attribute__((unused)) +conn_store_metric_destroy(sdb_object_t *obj) +{ + conn_store_metric_t *metric = CONN_STORE_METRIC(obj); + if (metric->hostname) + free((void *)metric->hostname); + metric->hostname = NULL; + if (metric->name) + free((void *)metric->name); + metric->name = NULL; + if (metric->store_type) + free((void *)metric->store_type); + metric->store_type = NULL; + if (metric->store_id) + free((void *)metric->store_id); + metric->store_id = NULL; +} /* conn_store_metric_destroy */ + +static void __attribute__((unused)) +conn_store_attr_destroy(sdb_object_t *obj) +{ + conn_store_attr_t *attr = CONN_STORE_ATTR(obj); + if (attr->hostname) + free((void *)attr->hostname); + attr->hostname = NULL; + if (attr->parent) + free((void *)attr->parent); + attr->parent = NULL; + if (attr->key) + free((void *)attr->key); + attr->key = NULL; + sdb_data_free_datum(&attr->value); +} /* conn_store_attr_destroy */ + static void __attribute__((unused)) conn_ts_destroy(sdb_object_t *obj) { diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 187f359..87184a4 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -104,6 +104,8 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...); sdb_store_matcher_t *m; sdb_store_expr_t *expr; + + sdb_metric_store_t metric_store; } %start statements @@ -119,12 +121,14 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...); %token ATTRIBUTE_T ATTRIBUTES_T %token NAME_T LAST_UPDATE_T AGE_T INTERVAL_T BACKEND_T +%token LAST UPDATE + %token START END /* NULL token */ %token NULL_T -%token FETCH LIST LOOKUP TIMESERIES +%token FETCH LIST LOOKUP STORE TIMESERIES %token IDENTIFIER STRING @@ -153,6 +157,7 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...); fetch_statement list_statement lookup_statement + store_statement timeseries_statement matching_clause filter_clause @@ -175,6 +180,9 @@ sdb_fe_yyerrorf(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *fmt, ...); %type datetime start_clause end_clause + last_update_clause + +%type metric_store_clause %destructor { free($$); } %destructor { sdb_object_deref(SDB_OBJ($$)); } @@ -265,6 +273,8 @@ statement: | lookup_statement | + store_statement + | timeseries_statement | /* empty */ @@ -345,6 +355,95 @@ filter_clause: | /* empty */ { $$ = NULL; } +/* + * STORE |. [LAST UPDATE ]; + * STORE METRIC . STORE [LAST UPDATE ]; + * STORE ATTRIBUTE . [LAST UPDATE ]; + * + * Store or update an object in the database. + */ +store_statement: + STORE HOST_T STRING last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_host_t, conn_store_host_destroy)); + CONN_STORE_HOST($$)->name = $3; + CONN_STORE_HOST($$)->last_update = $4; + $$->cmd = SDB_CONNECTION_STORE_HOST; + } + | + STORE SERVICE_T STRING '.' STRING last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_svc_t, conn_store_svc_destroy)); + CONN_STORE_SVC($$)->hostname = $3; + CONN_STORE_SVC($$)->name = $5; + CONN_STORE_SVC($$)->last_update = $6; + $$->cmd = SDB_CONNECTION_STORE_SERVICE; + } + | + STORE METRIC_T STRING '.' STRING metric_store_clause last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_metric_t, conn_store_metric_destroy)); + CONN_STORE_METRIC($$)->hostname = $3; + CONN_STORE_METRIC($$)->name = $5; + CONN_STORE_METRIC($$)->store_type = $6.type; + CONN_STORE_METRIC($$)->store_id = $6.id; + CONN_STORE_METRIC($$)->last_update = $7; + $$->cmd = SDB_CONNECTION_STORE_METRIC; + } + | + STORE HOST_T ATTRIBUTE_T STRING '.' STRING data last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_attr_t, conn_store_attr_destroy)); + CONN_STORE_ATTR($$)->parent_type = SDB_HOST; + CONN_STORE_ATTR($$)->hostname = NULL; + CONN_STORE_ATTR($$)->parent = $4; + CONN_STORE_ATTR($$)->key = $6; + CONN_STORE_ATTR($$)->value = $7; + CONN_STORE_ATTR($$)->last_update = $8; + $$->cmd = SDB_CONNECTION_STORE_ATTRIBUTE; + } + | + STORE SERVICE_T ATTRIBUTE_T STRING '.' STRING '.' STRING data last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_attr_t, conn_store_attr_destroy)); + CONN_STORE_ATTR($$)->parent_type = SDB_SERVICE; + CONN_STORE_ATTR($$)->hostname = $4; + CONN_STORE_ATTR($$)->parent = $6; + CONN_STORE_ATTR($$)->key = $8; + CONN_STORE_ATTR($$)->value = $9; + CONN_STORE_ATTR($$)->last_update = $10; + $$->cmd = SDB_CONNECTION_STORE_ATTRIBUTE; + } + | + STORE METRIC_T ATTRIBUTE_T STRING '.' STRING '.' STRING data last_update_clause + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_store_attr_t, conn_store_attr_destroy)); + CONN_STORE_ATTR($$)->parent_type = SDB_METRIC; + CONN_STORE_ATTR($$)->hostname = $4; + CONN_STORE_ATTR($$)->parent = $6; + CONN_STORE_ATTR($$)->key = $8; + CONN_STORE_ATTR($$)->value = $9; + CONN_STORE_ATTR($$)->last_update = $10; + $$->cmd = SDB_CONNECTION_STORE_ATTRIBUTE; + } + ; + +last_update_clause: + LAST UPDATE datetime { $$ = $3; } + | + /* empty */ { $$ = sdb_gettime(); } + +metric_store_clause: + STORE STRING STRING { $$.type = $2; $$.id = $3; } + | + /* empty */ { $$.type = $$.id = NULL; } + /* * TIMESERIES . [START ] [END ]; * diff --git a/src/frontend/query.c b/src/frontend/query.c index 63ec226..cc107c6 100644 --- a/src/frontend/query.c +++ b/src/frontend/query.c @@ -250,6 +250,36 @@ sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node) filter = CONN_LOOKUP(node)->filter->matcher; return sdb_fe_exec_lookup(conn, CONN_LOOKUP(node)->type, m, filter); + case SDB_CONNECTION_STORE_HOST: + { + conn_store_host_t *n = CONN_STORE_HOST(node); + sdb_proto_host_t host = { n->last_update, n->name }; + return sdb_fe_store_host(conn, &host); + } + case SDB_CONNECTION_STORE_SERVICE: + { + conn_store_svc_t *n = CONN_STORE_SVC(node); + sdb_proto_service_t svc = { n->last_update, n->hostname, n->name }; + return sdb_fe_store_service(conn, &svc); + } + case SDB_CONNECTION_STORE_METRIC: + { + conn_store_metric_t *n = CONN_STORE_METRIC(node); + sdb_proto_metric_t metric = { + n->last_update, n->hostname, n->name, + n->store_type, n->store_id + }; + return sdb_fe_store_metric(conn, &metric); + } + case SDB_CONNECTION_STORE_ATTRIBUTE: + { + conn_store_attr_t *n = CONN_STORE_ATTR(node); + sdb_proto_attribute_t attr = { + n->last_update, n->parent_type, n->hostname, n->parent, + n->key, n->value + }; + return sdb_fe_store_attribute(conn, &attr); + } case SDB_CONNECTION_TIMESERIES: return sdb_fe_exec_timeseries(conn, CONN_TS(node)->hostname, CONN_TS(node)->metric, diff --git a/src/frontend/scanner.l b/src/frontend/scanner.l index 6781122..3985bf8 100644 --- a/src/frontend/scanner.l +++ b/src/frontend/scanner.l @@ -59,6 +59,7 @@ static struct { { "FILTER", FILTER }, { "IN", IN }, { "IS", IS }, + { "LAST", LAST }, { "LIST", LIST }, { "LOOKUP", LOOKUP }, { "MATCHING", MATCHING }, @@ -66,7 +67,9 @@ static struct { { "NULL", NULL_T }, { "OR", OR }, { "START", START }, + { "STORE", STORE }, { "TIMESERIES", TIMESERIES }, + { "UPDATE", UPDATE }, /* object types */ { "host", HOST_T }, diff --git a/src/include/frontend/proto.h b/src/include/frontend/proto.h index 99e2a8d..52b50d1 100644 --- a/src/include/frontend/proto.h +++ b/src/include/frontend/proto.h @@ -277,6 +277,12 @@ typedef enum { */ SDB_CONNECTION_STORE = 50, + /* Only used internally: */ + SDB_CONNECTION_STORE_HOST, + SDB_CONNECTION_STORE_SERVICE, + SDB_CONNECTION_STORE_METRIC, + SDB_CONNECTION_STORE_ATTRIBUTE, + /* * Command subcomponents. */ -- 2.30.2