Code

frontend: Added simple 'LOOKUP <type> WHERE <expression>' query.
authorSebastian Harl <sh@tokkee.org>
Tue, 1 Apr 2014 20:45:19 +0000 (22:45 +0200)
committerSebastian Harl <sh@tokkee.org>
Tue, 1 Apr 2014 20:45:19 +0000 (22:45 +0200)
This query command may be used to retrieve a list of detailed host information
for each host matching the specified expression. For now, querying hosts is
supported only.

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 534d3cbd3978d3ca43707aba0a071ad9bdd9281d..f2d85f2ccdfd177e461032421a90eb181f870fdc 100644 (file)
@@ -87,6 +87,12 @@ typedef struct {
 } conn_node_matcher_t;
 #define CONN_MATCHER(obj) ((conn_node_matcher_t *)(obj))
 
+typedef struct {
+       sdb_conn_node_t super;
+       conn_node_matcher_t *matcher;
+} conn_lookup_t;
+#define CONN_LOOKUP(obj) ((conn_lookup_t *)(obj))
+
 /*
  * type helper functions
  */
@@ -97,6 +103,13 @@ conn_fetch_destroy(sdb_object_t *obj)
                free(CONN_FETCH(obj)->name);
 } /* conn_fetch_destroy */
 
+static void __attribute__((unused))
+conn_lookup_destroy(sdb_object_t *obj)
+{
+       if (CONN_LOOKUP(obj)->matcher)
+               sdb_object_deref(SDB_OBJ(CONN_LOOKUP(obj)->matcher));
+} /* conn_fetch_destroy */
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index 3802c9c97de1aa70c8d387acd99df728c70ed0bb..50bb00e7f632fa35abb283ca7025b0c02a80a908 100644 (file)
@@ -75,13 +75,16 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg);
 
 %token SCANNER_ERROR
 
+%token WHERE
+
 %token <str> IDENTIFIER STRING
-%token <node> FETCH LIST
+%token <node> FETCH LIST LOOKUP
 
 %type <list> statements
 %type <node> statement
        fetch_statement
        list_statement
+       lookup_statement
        expression
 
 %%
@@ -141,6 +144,8 @@ statement:
        |
        list_statement
        |
+       lookup_statement
+       |
        /* empty */
                {
                        $$ = NULL;
@@ -178,6 +183,32 @@ list_statement:
                }
        ;
 
+/*
+ * LOOKUP <type> WHERE <expression>;
+ *
+ * Returns detailed information about <type> matching expression.
+ */
+lookup_statement:
+       LOOKUP IDENTIFIER WHERE expression
+               {
+                       /* TODO: support other types as well */
+                       if (strcasecmp($2, "hosts")) {
+                               char errmsg[strlen($2) + 32];
+                               snprintf(errmsg, sizeof(errmsg),
+                                               YY_("unknown table %s"), $2);
+                               sdb_fe_yyerror(&yylloc, scanner, errmsg);
+                               YYABORT;
+                       }
+
+                       $$ = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL,
+                                               conn_lookup_t, conn_lookup_destroy));
+                       CONN_LOOKUP($$)->matcher = CONN_MATCHER($4);
+                       $$->cmd = CONNECTION_LOOKUP;
+                       free($2);
+                       $2 = NULL;
+               }
+       ;
+
 expression:
        STRING
                {
index 96c46d28db6f2b3425d90cd1079a363882779983..759b9c9795ebbe86da1c9ab4308c0c641f7e10aa 100644 (file)
 
 #include <errno.h>
 
+/*
+ * private helper functions
+ */
+
+static int
+lookup_tojson(sdb_store_base_t *obj, void *user_data)
+{
+       sdb_strbuf_t *buf = user_data;
+       if (sdb_strbuf_len(buf) > 1)
+               sdb_strbuf_append(buf, ",");
+       return sdb_store_host_tojson(obj, buf, /* flags = */ 0);
+} /* lookup_tojson */
+
 /*
  * public API
  */
@@ -49,6 +62,8 @@ sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node)
                        return sdb_fe_fetch(conn, CONN_FETCH(node)->name);
                case CONNECTION_LIST:
                        return sdb_fe_list(conn);
+               case CONNECTION_LOOKUP:
+                       return sdb_fe_lookup(conn, CONN_LOOKUP(node)->matcher->matcher);
 
                default:
                        sdb_log(SDB_LOG_ERR, "frontend: Unknown command %i", node->cmd);
@@ -132,5 +147,39 @@ sdb_fe_list(sdb_conn_t *conn)
        return 0;
 } /* sdb_fe_list */
 
+int
+sdb_fe_lookup(sdb_conn_t *conn, sdb_store_matcher_t *m)
+{
+       sdb_strbuf_t *buf;
+
+       buf = sdb_strbuf_create(1024);
+       if (! buf) {
+               char errbuf[1024];
+               sdb_log(SDB_LOG_ERR, "frontend: Failed to create "
+                               "buffer to handle LOOKUP command: %s",
+                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
+
+               sdb_strbuf_sprintf(conn->errbuf, "Out of memory");
+               sdb_strbuf_destroy(buf);
+               return -1;
+       }
+
+       sdb_strbuf_append(buf, "[");
+
+       if (sdb_store_lookup(m, lookup_tojson, buf)) {
+               sdb_log(SDB_LOG_ERR, "frontend: Failed to lookup hosts");
+               sdb_strbuf_sprintf(conn->errbuf, "Failed to lookup hosts");
+               sdb_strbuf_destroy(buf);
+               return -1;
+       }
+
+       sdb_strbuf_append(buf, "]");
+
+       sdb_connection_send(conn, CONNECTION_OK,
+                       (uint32_t)sdb_strbuf_len(buf), sdb_strbuf_string(buf));
+       sdb_strbuf_destroy(buf);
+       return 0;
+} /* sdb_fe_lookup */
+
 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */
 
index c0d167c00c0df1da371d8762098acd57c7ce5abc..61f1743fa60560c69f2cf5835f9c49827e760b17 100644 (file)
@@ -91,11 +91,15 @@ string              ('[^']*')
        }
 
 {identifier} {
-               /* XXX */
-               if (! strcasecmp(yytext, "LIST"))
-                       return LIST;
-               else if (! strcasecmp(yytext, "FETCH"))
+               /* XXX: simplify handling of reserved words */
+               if (! strcasecmp(yytext, "FETCH"))
                        return FETCH;
+               else if (! strcasecmp(yytext, "LIST"))
+                       return LIST;
+               else if (! strcasecmp(yytext, "LOOKUP"))
+                       return LOOKUP;
+               else if (! strcasecmp(yytext, "WHERE"))
+                       return WHERE;
 
                yylval->str = strdup(yytext);
                return IDENTIFIER;
index bf902ddc1761b78c5b56f7b3c4903c8614639c3d..4791a5e4523c61f1d76d56f88c113d1c4ae26382 100644 (file)
@@ -29,6 +29,7 @@
 #define SDB_FRONTEND_CONNECTION_H 1
 
 #include "frontend/proto.h"
+#include "core/store.h"
 #include "utils/llist.h"
 #include "utils/strbuf.h"
 
@@ -186,6 +187,17 @@ sdb_fe_fetch(sdb_conn_t *conn, const char *name);
 int
 sdb_fe_list(sdb_conn_t *conn);
 
+/*
+ * sdb_fe_lookup:
+ * Send a list of hosts matching 'm', serialized as JSON, to the client.
+ *
+ * Returns:
+ *  - 0 on success
+ *  - a negative value else
+ */
+int
+sdb_fe_lookup(sdb_conn_t *conn, sdb_store_matcher_t *m);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index 132e10c17058d972f4b893ec37cbb6a972c011aa..0f55a7c71d13b5ec80b2d57d5c98db6b2c8af154 100644 (file)
@@ -52,6 +52,7 @@ typedef enum {
        /* query commands */
        CONNECTION_FETCH,
        CONNECTION_LIST,
+       CONNECTION_LOOKUP,
 
        /* command elements */
        CONNECTION_EXPR,