Code

frontend, proto: Include the response data type in query replies.
authorSebastian Harl <sh@tokkee.org>
Sun, 14 Sep 2014 10:14:48 +0000 (12:14 +0200)
committerSebastian Harl <sh@tokkee.org>
Sun, 14 Sep 2014 10:14:48 +0000 (12:14 +0200)
For that purpose, use the newly added CONNECTION_DATA status instead of
CONNECTION_OK for query replies and include the data type as the first field
in the message body. The type is the same as the respective command type.

src/frontend/query.c
src/include/frontend/proto.h
src/tools/sysdb/command.c
src/tools/sysdb/main.c

index bbf98530afedcb106abc34174e9c61e9dc8a55ae..52d27ec3c47ba7e7dc940ba552e76b43cf0b38a2 100644 (file)
@@ -205,6 +205,7 @@ sdb_fe_exec_fetch(sdb_conn_t *conn, const char *name,
 {
        sdb_strbuf_t *buf;
        sdb_store_obj_t *host;
+       uint32_t type = htonl(CONNECTION_FETCH);
 
        host = sdb_store_get_host(name);
        if (! host) {
@@ -228,6 +229,7 @@ sdb_fe_exec_fetch(sdb_conn_t *conn, const char *name,
                return -1;
        }
 
+       sdb_strbuf_memcpy(buf, &type, sizeof(uint32_t));
        if (sdb_store_host_tojson(host, buf, filter, /* flags = */ 0)) {
                sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize "
                                "host '%s' to JSON", name);
@@ -237,7 +239,7 @@ sdb_fe_exec_fetch(sdb_conn_t *conn, const char *name,
                return -1;
        }
 
-       sdb_connection_send(conn, CONNECTION_OK,
+       sdb_connection_send(conn, CONNECTION_DATA,
                        (uint32_t)sdb_strbuf_len(buf), sdb_strbuf_string(buf));
        sdb_strbuf_destroy(buf);
        sdb_object_deref(SDB_OBJ(host));
@@ -248,6 +250,7 @@ int
 sdb_fe_exec_list(sdb_conn_t *conn, sdb_store_matcher_t *filter)
 {
        sdb_strbuf_t *buf;
+       uint32_t type = htonl(CONNECTION_LIST);
 
        buf = sdb_strbuf_create(1024);
        if (! buf) {
@@ -261,6 +264,7 @@ sdb_fe_exec_list(sdb_conn_t *conn, sdb_store_matcher_t *filter)
                return -1;
        }
 
+       sdb_strbuf_memcpy(buf, &type, sizeof(uint32_t));
        if (sdb_store_tojson(buf, filter, /* flags = */ SDB_SKIP_ALL)) {
                sdb_log(SDB_LOG_ERR, "frontend: Failed to serialize "
                                "store to JSON");
@@ -269,7 +273,7 @@ sdb_fe_exec_list(sdb_conn_t *conn, sdb_store_matcher_t *filter)
                return -1;
        }
 
-       sdb_connection_send(conn, CONNECTION_OK,
+       sdb_connection_send(conn, CONNECTION_DATA,
                        (uint32_t)sdb_strbuf_len(buf), sdb_strbuf_string(buf));
        sdb_strbuf_destroy(buf);
        return 0;
@@ -280,6 +284,7 @@ sdb_fe_exec_lookup(sdb_conn_t *conn, sdb_store_matcher_t *m,
                sdb_store_matcher_t *filter)
 {
        tojson_data_t data = { NULL, filter, 0 };
+       uint32_t type = htonl(CONNECTION_LOOKUP);
 
        data.buf = sdb_strbuf_create(1024);
        if (! data.buf) {
@@ -293,6 +298,7 @@ sdb_fe_exec_lookup(sdb_conn_t *conn, sdb_store_matcher_t *m,
                return -1;
        }
 
+       sdb_strbuf_memcpy(data.buf, &type, sizeof(uint32_t));
        sdb_strbuf_append(data.buf, "[");
 
        /* Let the JSON serializer handle the filter instead of the scanner. Else,
@@ -308,7 +314,7 @@ sdb_fe_exec_lookup(sdb_conn_t *conn, sdb_store_matcher_t *m,
 
        sdb_strbuf_append(data.buf, "]");
 
-       sdb_connection_send(conn, CONNECTION_OK,
+       sdb_connection_send(conn, CONNECTION_DATA,
                        (uint32_t)sdb_strbuf_len(data.buf), sdb_strbuf_string(data.buf));
        sdb_strbuf_destroy(data.buf);
        return 0;
@@ -320,6 +326,7 @@ sdb_fe_exec_timeseries(sdb_conn_t *conn,
                sdb_timeseries_opts_t *opts)
 {
        sdb_strbuf_t *buf;
+       uint32_t type = htonl(CONNECTION_TIMESERIES);
 
        buf = sdb_strbuf_create(1024);
        if (! buf) {
@@ -332,6 +339,7 @@ sdb_fe_exec_timeseries(sdb_conn_t *conn,
                return -1;
        }
 
+       sdb_strbuf_memcpy(buf, &type, sizeof(uint32_t));
        if (sdb_store_fetch_timeseries(hostname, metric, opts, buf)) {
                sdb_log(SDB_LOG_ERR, "frontend: Failed to fetch time-series");
                sdb_strbuf_sprintf(conn->errbuf, "Failed to fetch time-series");
@@ -339,7 +347,7 @@ sdb_fe_exec_timeseries(sdb_conn_t *conn,
                return -1;
        }
 
-       sdb_connection_send(conn, CONNECTION_OK,
+       sdb_connection_send(conn, CONNECTION_DATA,
                        (uint32_t)sdb_strbuf_len(buf), sdb_strbuf_string(buf));
        sdb_strbuf_destroy(buf);
        return 0;
index 9e02400e13ea597d9201d0a0577c47e9daefa11e..c006c49afef15284c98d7da909b5654c8217952b 100644 (file)
@@ -53,15 +53,46 @@ extern "C" {
 typedef enum {
        /*
         * CONNECTION_OK:
-        * Indicates that a command was successful. The message body will contain
-        * the result of the command (if any) encoded as a JSON string.
+        * Indicates that a command was successful. The message body will usually
+        * be empty but may contain a string providing unformatted information
+        * providing more details.
+        *
+        * 0               32              64
+        * +---------------+---------------+
+        * | message type  | length        |
+        * +---------------+---------------+
+        * | optional status message ...   |
         */
        CONNECTION_OK = 0,
 
+       /*
+        * CONNECTION_DATA:
+        * Indicates that a data query was successful. The message body will
+        * contain the type of the data and the result encoded as a JSON string.
+        * The type is the same as the command code of the respective command (see
+        * below) and is stored as an unsigned 32bit integer in network
+        * byte-order. The result may be empty (but the type is still included).
+        *
+        * 0               32              64
+        * +---------------+---------------+
+        * | message type  | length        |
+        * +---------------+---------------+
+        * | result type   | result ...    |
+        * +---------------+               |
+        * | ...                           |
+        */
+       CONNECTION_DATA,
+
        /*
         * CONNECTION_ERROR:
         * Indicates that a command has failed. The message body will contain a
         * string describing the error.
+        *
+        * 0               32              64
+        * +---------------+---------------+
+        * | message type  | length        |
+        * +---------------+---------------+
+        * | error message ...             |
         */
        CONNECTION_ERROR,
 
@@ -70,6 +101,12 @@ typedef enum {
         * Indicates an asynchronous log message. The message body will contain
         * the message string providing informational or warning logs. Log
         * messages may be sent to the client any time.
+        *
+        * 0               32              64
+        * +---------------+---------------+
+        * | message type  | length        |
+        * +---------------+---------------+
+        * | log message ...               |
         */
        CONNECTION_LOG,
 } sdb_conn_status_t;
@@ -103,7 +140,12 @@ typedef enum {
        CONNECTION_STARTUP,
 
        /*
-        * Querying the server.
+        * Querying the server. On success, the server replies with
+        * CONNECTION_DATA.
+        *
+        * The command codes listed here are used, both, for sending a query to
+        * the server and to indicate the response type from a query in a DATA
+        * message.
         */
 
        /*
index 9dfb6194d40b9db217ab66a519e3d6995bf69c8b..718309bfad693678f93e1017eb5e01578b1b3b5a 100644 (file)
@@ -75,6 +75,10 @@ sdb_command_print_reply(sdb_client_t *client)
                status = (int)rcode;
 
        result = sdb_strbuf_string(recv_buf);
+       /* At the moment, we don't care about the result type. We simply print the
+        * result without further parsing it. */
+       if (status == CONNECTION_DATA)
+               result += sizeof(uint32_t);
        if (result && *result)
                printf("%s\n", result);
        else if (rcode == UINT32_MAX) {
index fc226f965f991ec65f4cc4bbfa5b61f7ba318e57..331cfa25e640912ac79ac6b37c44d3a91f374323 100644 (file)
@@ -194,7 +194,7 @@ execute_commands(sdb_client_t *client, sdb_llist_t *commands)
                }
 
                /* Wait for server replies. We might get any number of log messages
-                * but eventually see the reply to the query, which is either OK or
+                * but eventually see the reply to the query, which is either DATA or
                 * ERROR. */
                while (42) {
                        status = sdb_command_print_reply(client);
@@ -203,12 +203,19 @@ execute_commands(sdb_client_t *client, sdb_llist_t *commands)
                                break;
                        }
 
-                       if ((status == CONNECTION_OK) || (status == CONNECTION_ERROR))
+                       if ((status == CONNECTION_DATA) || (status == CONNECTION_ERROR))
                                break;
+                       if (status == CONNECTION_OK) {
+                               /* pre 0.4 versions used OK instead of DATA */
+                               sdb_log(SDB_LOG_WARNING, "Received unexpected OK status from "
+                                               "server in response to a QUERY (expected DATA); "
+                                               "assuming we're talking to an old server");
+                               break;
+                       }
                }
 
-               if (status)
-                       break;
+               if ((status != CONNECTION_OK) && (status != CONNECTION_DATA))
+                       break; /* error */
        }
 
        sdb_llist_iter_destroy(iter);
@@ -302,7 +309,9 @@ main(int argc, char **argv)
                int status = execute_commands(input.client, commands);
                sdb_llist_destroy(commands);
                sdb_client_destroy(input.client);
-               exit(status);
+               if ((status != CONNECTION_OK) && (status != CONNECTION_DATA))
+                       exit(1);
+               exit(0);
        }
 
        sdb_log(SDB_LOG_INFO, "SysDB client "SDB_CLIENT_VERSION_STRING