Code

frontend: Let the 'fetch' command support other types besides hosts.
authorSebastian Harl <sh@tokkee.org>
Tue, 4 Nov 2014 07:26:57 +0000 (08:26 +0100)
committerSebastian Harl <sh@tokkee.org>
Tue, 4 Nov 2014 07:26:57 +0000 (08:26 +0100)
src/frontend/connection-private.h
src/frontend/grammar.y
src/frontend/query.c
src/include/frontend/connection.h

index 4ff4e51bb4ab44f9203ca12b49ab3f8501b64265..042091a997044a712c4de1d4c45fe734b1406348 100644 (file)
@@ -103,7 +103,8 @@ typedef struct {
 typedef struct {
        sdb_conn_node_t super;
        int type;
-       char *name;
+       char *host;
+       char *name; /* NULL for type == SDB_HOST */
        conn_matcher_t *filter;
 } conn_fetch_t;
 #define CONN_FETCH(obj) ((conn_fetch_t *)(obj))
@@ -149,6 +150,8 @@ conn_list_destroy(sdb_object_t *obj)
 static void __attribute__((unused))
 conn_fetch_destroy(sdb_object_t *obj)
 {
+       if (CONN_FETCH(obj)->host)
+               free(CONN_FETCH(obj)->host);
        if (CONN_FETCH(obj)->name)
                free(CONN_FETCH(obj)->name);
        sdb_object_deref(SDB_OBJ(CONN_FETCH(obj)->filter));
index 4702562e992ebcb7ae9058360a4e94c17f3205e7..b400f9acc51736fc43ebed4cb7a02ea6b03036af 100644 (file)
@@ -288,7 +288,8 @@ 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($$)->host = $3;
+                       CONN_FETCH($$)->name = NULL;
                        CONN_FETCH($$)->filter = CONN_MATCHER($4);
                        $$->cmd = CONNECTION_FETCH;
                }
index 057d5b8e4a3b1ec07b2456de8afbeb06b157c96c..b806dcd52c2489dc4d74bae90ac80f582bf2cf61 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * SysDB - src/frontend/query.c
- * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * Copyright (C) 2013-2014 Sebastian 'tokkee' Harl <sh@tokkee.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -145,7 +145,8 @@ sdb_fe_fetch(sdb_conn_t *conn)
        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);
+       /* TODO: support other types besides hosts */
+       return sdb_fe_exec_fetch(conn, type, name, NULL, /* filter = */ NULL);
 } /* sdb_fe_fetch */
 
 int
@@ -240,7 +241,7 @@ sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node)
                        if (CONN_FETCH(node)->filter)
                                filter = CONN_FETCH(node)->filter->matcher;
                        return sdb_fe_exec_fetch(conn, CONN_FETCH(node)->type,
-                                       CONN_FETCH(node)->name, filter);
+                                       CONN_FETCH(node)->host, CONN_FETCH(node)->name, filter);
                case CONNECTION_LIST:
                        if (CONN_LIST(node)->filter)
                                filter = CONN_LIST(node)->filter->matcher;
@@ -265,33 +266,48 @@ sdb_fe_exec(sdb_conn_t *conn, sdb_conn_node_t *node)
 } /* sdb_fe_exec */
 
 int
-sdb_fe_exec_fetch(sdb_conn_t *conn, int type, const char *name,
-               sdb_store_matcher_t *filter)
+sdb_fe_exec_fetch(sdb_conn_t *conn, int type,
+               const char *hostname, const char *name, sdb_store_matcher_t *filter)
 {
-       sdb_store_obj_t *host;
        uint32_t res_type = htonl(CONNECTION_FETCH);
 
+       sdb_store_obj_t *host;
+       sdb_store_obj_t *obj;
+
        sdb_store_json_formatter_t *f;
        sdb_strbuf_t *buf;
 
-       /* 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);
+       if ((! hostname) || ((type == SDB_HOST) && name)
+                       || ((type != SDB_HOST) && (! name))) {
+               /* This is a programming error, not something the client did wrong */
+               sdb_strbuf_sprintf(conn->errbuf, "INTERNAL ERROR: invalid "
+                               "arguments to sdb_fe_exec_fetch(%s, %s, %s)",
+                               SDB_STORE_TYPE_TO_NAME(type), hostname, name);
                return -1;
        }
 
-       host = sdb_store_get_host(name);
+       host = sdb_store_get_host(hostname);
        if ((! host) || (filter
                                && (! sdb_store_matcher_matches(filter, host, NULL)))) {
-               sdb_log(SDB_LOG_DEBUG, "frontend: Failed to fetch host '%s': "
-                               "not found", name);
-
-               sdb_strbuf_sprintf(conn->errbuf, "Host %s not found", name);
+               sdb_strbuf_sprintf(conn->errbuf, "Failed to fetch %s %s: "
+                               "host %s not found", SDB_STORE_TYPE_TO_NAME(type),
+                               name, hostname);
                return -1;
        }
+       if (type == SDB_HOST) {
+               obj = host;
+       }
+       else {
+               obj = sdb_store_get_child(host, type, name);
+               if ((! obj) || (filter
+                                       && (! sdb_store_matcher_matches(filter, obj, NULL)))) {
+                       sdb_strbuf_sprintf(conn->errbuf, "Failed to fetch %s %s.%s: "
+                                       "%s not found", SDB_STORE_TYPE_TO_NAME(type),
+                                       hostname, name, name);
+                       return -1;
+               }
+               sdb_object_deref(SDB_OBJ(host));
+       }
 
        buf = sdb_strbuf_create(1024);
        if (! buf) {
@@ -302,7 +318,7 @@ sdb_fe_exec_fetch(sdb_conn_t *conn, int type, const char *name,
 
                sdb_strbuf_sprintf(conn->errbuf, "Out of memory");
                sdb_strbuf_destroy(buf);
-               sdb_object_deref(SDB_OBJ(host));
+               sdb_object_deref(SDB_OBJ(obj));
                return -1;
        }
        f = sdb_store_json_formatter(buf, type, /* flags = */ 0);
@@ -314,18 +330,19 @@ sdb_fe_exec_fetch(sdb_conn_t *conn, int type, const char *name,
 
                sdb_strbuf_sprintf(conn->errbuf, "Out of memory");
                sdb_strbuf_destroy(buf);
-               sdb_object_deref(SDB_OBJ(host));
+               sdb_object_deref(SDB_OBJ(obj));
                return -1;
        }
 
        sdb_strbuf_memcpy(buf, &res_type, sizeof(uint32_t));
-       if (sdb_store_json_emit_full(f, host, filter)) {
+       if (sdb_store_json_emit_full(f, obj, filter)) {
                sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize "
-                               "host '%s' to JSON", name);
+                               "%s %s.%s to JSON", SDB_STORE_TYPE_TO_NAME(type),
+                               hostname, name);
                sdb_strbuf_sprintf(conn->errbuf, "Out of memory");
                sdb_strbuf_destroy(buf);
                free(f);
-               sdb_object_deref(SDB_OBJ(host));
+               sdb_object_deref(SDB_OBJ(obj));
                return -1;
        }
        sdb_store_json_finish(f);
@@ -334,7 +351,7 @@ sdb_fe_exec_fetch(sdb_conn_t *conn, int type, const char *name,
                        (uint32_t)sdb_strbuf_len(buf), sdb_strbuf_string(buf));
        sdb_strbuf_destroy(buf);
        free(f);
-       sdb_object_deref(SDB_OBJ(host));
+       sdb_object_deref(SDB_OBJ(obj));
        return 0;
 } /* sdb_fe_exec_fetch */
 
index efa8ba437278ab5aaa85ee72f9fdceaf883bf374..cbaa43ef459d1810a2bd2f84822a41487c7c33e7 100644 (file)
@@ -195,8 +195,8 @@ sdb_fe_lookup(sdb_conn_t *conn);
  *  - a negative value else
  */
 int
-sdb_fe_exec_fetch(sdb_conn_t *conn, int type, const char *name,
-               sdb_store_matcher_t *filter);
+sdb_fe_exec_fetch(sdb_conn_t *conn, int type,
+               const char *hostname, const char *name, sdb_store_matcher_t *filter);
 
 /*
  * sdb_fe_exec_list: