Code

frontend: Added 'FETCH <name>' query command.
authorSebastian Harl <sh@tokkee.org>
Mon, 31 Mar 2014 21:17:34 +0000 (23:17 +0200)
committerSebastian Harl <sh@tokkee.org>
Mon, 31 Mar 2014 21:17:34 +0000 (23:17 +0200)
For now, <name> may only be a simple identifier.

src/frontend/connection-private.h
src/frontend/grammar.y
src/frontend/query.c
src/frontend/scanner.l
src/include/frontend/connection.h
src/include/frontend/proto.h

index 82cece90f00cdae17c59557f5f651979fb1c6013..534d3cbd3978d3ca43707aba0a071ad9bdd9281d 100644 (file)
@@ -41,6 +41,8 @@
 #include <inttypes.h>
 #include <arpa/inet.h>
 
+#include <stdlib.h>
+
 #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
index 551d1714d7a12cf86b64aea6834b4e4dd782dd89..004a5effa1537a29473066103757cd169867c37a 100644 (file)
@@ -37,6 +37,7 @@
 #include "utils/llist.h"
 
 #include <stdio.h>
+#include <string.h>
 
 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 <str> IDENTIFIER
-%token <node> LIST
+%token <node> FETCH LIST
 
 %type <list> statements
 %type <node> 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
                {
index ffec03aef40bc406a2619cc1972f9630dc5a8505..96c46d28db6f2b3425d90cd1079a363882779983 100644 (file)
@@ -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)
 {
index 87367f6e4324886fa0e2b0aa93a457c918326b68..c279a4876d11a66672fb54e209c81213608ed55b 100644 (file)
@@ -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;
index dc93db6c782ed46ddb03bfae613445dc78815973..bf902ddc1761b78c5b56f7b3c4903c8614639c3d 100644 (file)
@@ -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.
index 76d1997be470b33c592f5f93aa5837656515f5c5..132e10c17058d972f4b893ec37cbb6a972c011aa 100644 (file)
@@ -49,6 +49,8 @@ typedef enum {
 
        /* querying */
        CONNECTION_QUERY,
+       /* query commands */
+       CONNECTION_FETCH,
        CONNECTION_LIST,
 
        /* command elements */