From ae719038f60b9639f600333474b596e48e497e51 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sun, 5 Oct 2014 16:25:36 +0200 Subject: [PATCH] frontend, proto: Include object type in FETCH and LOOKUP messages. The respective commands only support hosts at the moment but this change prepares the wire-format to support other types as well. --- src/frontend/connection-private.h | 2 + src/frontend/grammar.y | 2 + src/frontend/query.c | 75 +++++++++++++++++++++++++------ src/include/frontend/connection.h | 18 ++++---- src/include/frontend/proto.h | 13 ++++-- 5 files changed, 83 insertions(+), 27 deletions(-) diff --git a/src/frontend/connection-private.h b/src/frontend/connection-private.h index dd4bcce..85f278c 100644 --- a/src/frontend/connection-private.h +++ b/src/frontend/connection-private.h @@ -96,6 +96,7 @@ typedef struct { typedef struct { sdb_conn_node_t super; + int type; char *name; conn_matcher_t *filter; } conn_fetch_t; @@ -103,6 +104,7 @@ typedef struct { typedef struct { sdb_conn_node_t super; + int type; conn_matcher_t *matcher; conn_matcher_t *filter; } conn_lookup_t; diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 129b461..f13bbad 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -234,6 +234,7 @@ fetch_statement: $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, conn_fetch_t, conn_fetch_destroy)); + CONN_FETCH($$)->type = SDB_HOST; CONN_FETCH($$)->name = $3; CONN_FETCH($$)->filter = CONN_MATCHER($4); $$->cmd = CONNECTION_FETCH; @@ -291,6 +292,7 @@ lookup_statement: $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, conn_lookup_t, conn_lookup_destroy)); + CONN_LOOKUP($$)->type = SDB_HOST; CONN_LOOKUP($$)->matcher = CONN_MATCHER($3); CONN_LOOKUP($$)->filter = CONN_MATCHER($4); $$->cmd = CONNECTION_LOOKUP; diff --git a/src/frontend/query.c b/src/frontend/query.c index 1751ba5..39b5d53 100644 --- a/src/frontend/query.c +++ b/src/frontend/query.c @@ -125,12 +125,25 @@ sdb_fe_query(sdb_conn_t *conn) int sdb_fe_fetch(sdb_conn_t *conn) { - char hostname[conn->cmd_len + 1]; + char name[conn->cmd_len + 1]; + int type; + if ((! conn) || (conn->cmd != CONNECTION_FETCH)) return -1; - strncpy(hostname, sdb_strbuf_string(conn->buf), conn->cmd_len); - hostname[sizeof(hostname) - 1] = '\0'; - return sdb_fe_exec_fetch(conn, hostname, /* filter = */ NULL); + + if (conn->cmd_len < sizeof(type)) { + sdb_log(SDB_LOG_ERR, "frontend: Invalid command length %d for " + "FETCH command", conn->cmd_len); + sdb_strbuf_sprintf(conn->errbuf, "FETCH: Invalid command length %d", + conn->cmd_len); + return -1; + } + + type = sdb_proto_get_int(conn->buf, 0); + strncpy(name, sdb_strbuf_string(conn->buf) + sizeof(type), + conn->cmd_len - sizeof(type)); + name[sizeof(name) - 1] = '\0'; + return sdb_fe_exec_fetch(conn, type, name, /* filter = */ NULL); } /* sdb_fe_fetch */ int @@ -157,23 +170,37 @@ int sdb_fe_lookup(sdb_conn_t *conn) { sdb_store_matcher_t *m; + const char *matcher; + size_t matcher_len; + + uint32_t type; int status; if ((! conn) || (conn->cmd != CONNECTION_LOOKUP)) return -1; - m = sdb_fe_parse_matcher(sdb_strbuf_string(conn->buf), - (int)conn->cmd_len); + if (conn->cmd_len < sizeof(type)) { + sdb_log(SDB_LOG_ERR, "frontend: Invalid command length %d for " + "LOOKUP command", conn->cmd_len); + sdb_strbuf_sprintf(conn->errbuf, "LOOKUP: Invalid command length %d", + conn->cmd_len); + return -1; + } + type = sdb_proto_get_int(conn->buf, 0); + + matcher = sdb_strbuf_string(conn->buf) + sizeof(type); + matcher_len = conn->cmd_len - sizeof(type); + m = sdb_fe_parse_matcher(matcher, (int)matcher_len); if (! m) { - char expr[conn->cmd_len + 1]; - strncpy(expr, sdb_strbuf_string(conn->buf), conn->cmd_len); + char expr[matcher_len + 1]; + strncpy(expr, matcher, sizeof(expr)); expr[sizeof(expr) - 1] = '\0'; sdb_log(SDB_LOG_ERR, "frontend: Failed to parse " "lookup condition '%s'", expr); return -1; } - status = sdb_fe_exec_lookup(conn, m, /* filter = */ NULL); + status = sdb_fe_exec_lookup(conn, type, m, /* filter = */ NULL); sdb_object_deref(SDB_OBJ(m)); return status; } /* sdb_fe_lookup */ @@ -190,7 +217,8 @@ sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node) case CONNECTION_FETCH: if (CONN_FETCH(node)->filter) filter = CONN_FETCH(node)->filter->matcher; - return sdb_fe_exec_fetch(conn, CONN_FETCH(node)->name, filter); + return sdb_fe_exec_fetch(conn, CONN_FETCH(node)->type, + CONN_FETCH(node)->name, filter); case CONNECTION_LIST: if (CONN_LIST(node)->filter) filter = CONN_LIST(node)->filter->matcher; @@ -200,7 +228,8 @@ sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node) m = CONN_LOOKUP(node)->matcher->matcher; if (CONN_LOOKUP(node)->filter) filter = CONN_LOOKUP(node)->filter->matcher; - return sdb_fe_exec_lookup(conn, m, filter); + return sdb_fe_exec_lookup(conn, + CONN_LOOKUP(node)->type, m, filter); case CONNECTION_TIMESERIES: return sdb_fe_exec_timeseries(conn, CONN_TS(node)->hostname, CONN_TS(node)->metric, @@ -214,13 +243,22 @@ sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node) } /* sdb_fe_exec */ int -sdb_fe_exec_fetch(sdb_conn_t *conn, const char *name, +sdb_fe_exec_fetch(sdb_conn_t *conn, int type, const char *name, sdb_store_matcher_t *filter) { sdb_strbuf_t *buf; sdb_store_obj_t *host; uint32_t res_type = htonl(CONNECTION_FETCH); + /* XXX: support other types */ + if (type != SDB_HOST) { + sdb_log(SDB_LOG_ERR, "frontend: Invalid object type %d " + "in FETCH command", type); + sdb_strbuf_sprintf(conn->errbuf, + "FETCH: Invalid object type %d", type); + return -1; + } + host = sdb_store_get_host(name); if (! host) { sdb_log(SDB_LOG_DEBUG, "frontend: Failed to fetch host '%s': " @@ -312,12 +350,21 @@ sdb_fe_exec_list(sdb_conn_t *conn, int type, sdb_store_matcher_t *filter) } /* sdb_fe_exec_list */ int -sdb_fe_exec_lookup(sdb_conn_t *conn, sdb_store_matcher_t *m, - sdb_store_matcher_t *filter) +sdb_fe_exec_lookup(sdb_conn_t *conn, int type, + sdb_store_matcher_t *m, sdb_store_matcher_t *filter) { tojson_data_t data = { NULL, filter, 0 }; uint32_t res_type = htonl(CONNECTION_LOOKUP); + /* XXX: support other types */ + if (type != SDB_HOST) { + sdb_log(SDB_LOG_ERR, "frontend: Invalid object type %d " + "in LOOKUP command", type); + sdb_strbuf_sprintf(conn->errbuf, + "LOOKUP: Invalid object type %d", type); + return -1; + } + data.buf = sdb_strbuf_create(1024); if (! data.buf) { char errbuf[1024]; diff --git a/src/include/frontend/connection.h b/src/include/frontend/connection.h index 8189470..a890bd0 100644 --- a/src/include/frontend/connection.h +++ b/src/include/frontend/connection.h @@ -186,16 +186,16 @@ sdb_fe_lookup(sdb_conn_t *conn); /* * sdb_fe_exec_fetch: - * Execute the 'FETCH' command. Send the named host, serialized as JSON, to - * the client. If specified, only objects matching the filter will be - * included. See sdb_store_tojson for details. + * Execute the 'FETCH' command. Send the named object of the specified type, + * serialized as JSON, to the client. If specified, only objects matching the + * filter will be included. See sdb_store_tojson for details. * * Returns: * - 0 on success * - a negative value else */ int -sdb_fe_exec_fetch(sdb_conn_t *conn, const char *name, +sdb_fe_exec_fetch(sdb_conn_t *conn, int type, const char *name, sdb_store_matcher_t *filter); /* @@ -214,17 +214,17 @@ sdb_fe_exec_list(sdb_conn_t *conn, int type, sdb_store_matcher_t *filter); /* * sdb_fe_exec_lookup: - * Execute the 'LOOKUP' command. Send a list of hosts matching 'm', serialized - * as JSON, to the client. If specified, only objects matching the filter will - * be included. See sdb_store_tojson for details. + * Execute the 'LOOKUP' command. Send a list of objects of the specified type + * matching 'm', serialized as JSON, to the client. If specified, only objects + * matching the filter will be included. See sdb_store_tojson for details. * * Returns: * - 0 on success * - a negative value else */ int -sdb_fe_exec_lookup(sdb_conn_t *conn, sdb_store_matcher_t *m, - sdb_store_matcher_t *filter); +sdb_fe_exec_lookup(sdb_conn_t *conn, int type, + sdb_store_matcher_t *m, sdb_store_matcher_t *filter); /* * sdb_fe_exec_timeseries: diff --git a/src/include/frontend/proto.h b/src/include/frontend/proto.h index de45f73..e9001cb 100644 --- a/src/include/frontend/proto.h +++ b/src/include/frontend/proto.h @@ -171,22 +171,27 @@ typedef enum { /* * CONNECTION_FETCH: * Execute the 'FETCH' command in the server. The message body shall - * include the hostname of the host to be retrieved. + * include the type and the identifier of the object to be retrieved. + * Hosts are identified by their name. Other types are not supported yet. + * The type is encoded as a 32bit integer in network byte-order. */ CONNECTION_FETCH, /* * CONNECTION_LIST: * Execute the 'LIST' command in the server. The message body may include - * the type of the objects to be included in addition to all hosts, - * encoded as a 32bit integer in network byte-order. + * the type of the objects to be listed, encoded as a 32bit integer in + * network byte-order. The response includes all hosts and the respective + * child objects. By default, all hosts are listed. */ CONNECTION_LIST, /* * CONNECTION_LOOKUP: * Execute the 'LOOKUP' command in the server. The message body shall - * include the conditional expression of the 'MATCHING' clause. + * include the type of the objects to look up and a string representing + * the conditional expression of the 'MATCHING' clause. The type is + * encoded as a 32bit integer in network byte-order. */ CONNECTION_LOOKUP, -- 2.30.2