From 9ae83505d8025ab32a8bdf7904ff4df8f9e661bf Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Mon, 31 Mar 2014 23:17:34 +0200 Subject: [PATCH] frontend: Added 'FETCH ' query command. For now, may only be a simple identifier. --- src/frontend/connection-private.h | 18 ++++++++++++ src/frontend/grammar.y | 16 ++++++++++- src/frontend/query.c | 46 +++++++++++++++++++++++++++++++ src/frontend/scanner.l | 2 ++ src/include/frontend/connection.h | 11 ++++++++ src/include/frontend/proto.h | 2 ++ 6 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/frontend/connection-private.h b/src/frontend/connection-private.h index 82cece9..534d3cb 100644 --- a/src/frontend/connection-private.h +++ b/src/frontend/connection-private.h @@ -41,6 +41,8 @@ #include #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -73,12 +75,28 @@ struct sdb_conn { * node types */ +typedef struct { + sdb_conn_node_t super; + char *name; +} conn_fetch_t; +#define CONN_FETCH(obj) ((conn_fetch_t *)(obj)) + typedef struct { sdb_conn_node_t super; sdb_store_matcher_t *matcher; } conn_node_matcher_t; #define CONN_MATCHER(obj) ((conn_node_matcher_t *)(obj)) +/* + * type helper functions + */ +static void __attribute__((unused)) +conn_fetch_destroy(sdb_object_t *obj) +{ + if (CONN_FETCH(obj)->name) + free(CONN_FETCH(obj)->name); +} /* conn_fetch_destroy */ + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 551d171..004a5ef 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -37,6 +37,7 @@ #include "utils/llist.h" #include +#include int sdb_fe_yylex(YYSTYPE *yylval, YYLTYPE *yylloc, sdb_fe_yyscan_t yyscanner); @@ -75,10 +76,11 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); %token SCANNER_ERROR %token IDENTIFIER -%token LIST +%token FETCH LIST %type statements %type statement + fetch_statement list_statement expression @@ -135,6 +137,8 @@ statements: ; statement: + fetch_statement + | list_statement | /* empty */ @@ -143,6 +147,16 @@ statement: } ; +fetch_statement: + FETCH IDENTIFIER + { + $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_fetch_t, conn_fetch_destroy)); + CONN_FETCH($$)->name = strdup($2); + $$->cmd = CONNECTION_FETCH; + } + ; + list_statement: LIST { diff --git a/src/frontend/query.c b/src/frontend/query.c index ffec03a..96c46d2 100644 --- a/src/frontend/query.c +++ b/src/frontend/query.c @@ -45,6 +45,8 @@ sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node) return -1; switch (node->cmd) { + case CONNECTION_FETCH: + return sdb_fe_fetch(conn, CONN_FETCH(node)->name); case CONNECTION_LIST: return sdb_fe_list(conn); @@ -55,6 +57,50 @@ sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node) return -1; } /* sdb_fe_exec */ +int +sdb_fe_fetch(sdb_conn_t *conn, const char *name) +{ + sdb_strbuf_t *buf; + sdb_store_base_t *host; + + host = sdb_store_get_host(name); + if (! host) { + sdb_log(SDB_LOG_DEBUG, "frontend: Failed to fetch host '%s': " + "not found", name); + + sdb_strbuf_sprintf(conn->errbuf, "Host %s not found", name); + return -1; + } + + buf = sdb_strbuf_create(1024); + if (! buf) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "frontend: Failed to create " + "buffer to handle FETCH command: %s", + sdb_strerror(errno, errbuf, sizeof(errbuf))); + + sdb_strbuf_sprintf(conn->errbuf, "Out of memory"); + sdb_strbuf_destroy(buf); + sdb_object_deref(SDB_OBJ(host)); + return -1; + } + + if (sdb_store_host_tojson(host, buf, /* flags = */ 0)) { + sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize " + "host '%s' to JSON", name); + sdb_strbuf_sprintf(conn->errbuf, "Out of memory"); + sdb_strbuf_destroy(buf); + sdb_object_deref(SDB_OBJ(host)); + return -1; + } + + sdb_connection_send(conn, CONNECTION_OK, + (uint32_t)sdb_strbuf_len(buf), sdb_strbuf_string(buf)); + sdb_strbuf_destroy(buf); + sdb_object_deref(SDB_OBJ(host)); + return 0; +} /* sdb_fe_fetch */ + int sdb_fe_list(sdb_conn_t *conn) { diff --git a/src/frontend/scanner.l b/src/frontend/scanner.l index 87367f6..c279a48 100644 --- a/src/frontend/scanner.l +++ b/src/frontend/scanner.l @@ -92,6 +92,8 @@ identifier ([A-Za-z_][A-Za-z_0-9$]*) /* XXX */ if (! strcasecmp(yytext, "LIST")) return LIST; + else if (! strcasecmp(yytext, "FETCH")) + return FETCH; yylval->str = strdup(yytext); return IDENTIFIER; diff --git a/src/include/frontend/connection.h b/src/include/frontend/connection.h index dc93db6..bf902dd 100644 --- a/src/include/frontend/connection.h +++ b/src/include/frontend/connection.h @@ -164,6 +164,17 @@ sdb_fe_session_start(sdb_conn_t *conn); * store access */ +/* + * sdb_fe_fetch: + * Send the named host, serialized as JSON, to the client. + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_fe_fetch(sdb_conn_t *conn, const char *name); + /* * sdb_fe_list: * Send a complete listing of the store, serialized as JSON, to the client. diff --git a/src/include/frontend/proto.h b/src/include/frontend/proto.h index 76d1997..132e10c 100644 --- a/src/include/frontend/proto.h +++ b/src/include/frontend/proto.h @@ -49,6 +49,8 @@ typedef enum { /* querying */ CONNECTION_QUERY, + /* query commands */ + CONNECTION_FETCH, CONNECTION_LIST, /* command elements */ -- 2.30.2