Code

client: Added sdb_client_rpc.
authorSebastian Harl <sh@tokkee.org>
Fri, 16 Jan 2015 22:45:23 +0000 (23:45 +0100)
committerSebastian Harl <sh@tokkee.org>
Fri, 16 Jan 2015 22:45:23 +0000 (23:45 +0100)
This function handles a full RPC call: it sends a message to the server and
waits for the reply. While doing so, it handles all asynchronous log messages.
That is, it'll return the actual result status of the command.

src/client/sock.c
src/include/client/sock.h
src/include/frontend/proto.h

index cd9c8cebe342fca2bdd1865b9e0bae051752aa83..6a1e49ff541cabb049ecc4119f83feb490592759 100644 (file)
@@ -302,6 +302,59 @@ sdb_client_close(sdb_client_t *client)
        client->eof = 1;
 } /* sdb_client_close */
 
+ssize_t
+sdb_client_rpc(sdb_client_t *client,
+               uint32_t cmd, uint32_t msg_len, const char *msg,
+               uint32_t *code, sdb_strbuf_t *buf)
+{
+       uint32_t rcode = 0;
+       ssize_t status;
+
+       if (! buf)
+               return -1;
+
+       if (sdb_client_send(client, cmd, msg_len, msg) < 0) {
+               char errbuf[1024];
+               sdb_strbuf_sprintf(buf, "Failed to send %s message to server: %s",
+                               SDB_CONN_MSGTYPE_TO_STRING(cmd),
+                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
+               if (code)
+                       *code = SDB_CONNECTION_ERROR;
+               return -1;
+       }
+
+       while (42) {
+               size_t offset = sdb_strbuf_len(buf);
+
+               status = sdb_client_recv(client, &rcode, buf);
+               if (status < 0) {
+                       char errbuf[1024];
+                       sdb_strbuf_sprintf(buf, "Failed to receive server response: %s",
+                                       sdb_strerror(errno, errbuf, sizeof(errbuf)));
+                       if (code)
+                               *code = SDB_CONNECTION_ERROR;
+                       return status;
+               }
+
+               if (rcode == SDB_CONNECTION_LOG) {
+                       uint32_t prio = 0;
+                       if (sdb_proto_unmarshal_int32(SDB_STRBUF_STR(buf), &prio) < 0) {
+                               sdb_log(SDB_LOG_WARNING, "Received a LOG message "
+                                               "with invalid or missing priority");
+                               prio = (uint32_t)SDB_LOG_ERR;
+                       }
+                       sdb_log((int)prio, "%s", sdb_strbuf_string(buf) + offset);
+                       sdb_strbuf_skip(buf, offset, sdb_strbuf_len(buf) - offset);
+                       continue;
+               }
+               break;
+       }
+
+       if (code)
+               *code = rcode;
+       return status;
+} /* sdb_client_rpc */
+
 ssize_t
 sdb_client_send(sdb_client_t *client,
                uint32_t cmd, uint32_t msg_len, const char *msg)
index 638f8626660807a33776267f8116dbe38c8449c0..9a7947b88f6d5513f51734683f19c134c420699f 100644 (file)
@@ -97,10 +97,30 @@ sdb_client_shutdown(sdb_client_t *client, int how);
 void
 sdb_client_close(sdb_client_t *client);
 
+/*
+ * sdb_client_rpc:
+ * Send the specified message to the server and wait for the reply. All
+ * received data is written to the specified buffer. If specified, the
+ * returned status code is written to the memory location pointed to by
+ * 'code'. In case of an error or an incomplete command, the status code is
+ * set to UINT32_MAX. The returned data does not include the status code and
+ * message len as received from the remote side but only the data associated
+ * with the message. The function handles all asynchronous log messages by
+ * logging them at the right log level.
+ *
+ * Returns:
+ *  - the number of bytes read
+ *    (may be zero if the message did not include any data)
+ *  - a negative value on error
+ */
+ssize_t
+sdb_client_rpc(sdb_client_t *client,
+               uint32_t cmd, uint32_t msg_len, const char *msg,
+               uint32_t *code, sdb_strbuf_t *buf);
+
 /*
  * sdb_client_send:
- * Send the specified command and accompanying data to through the client
- * connection.
+ * Send the specified command and accompanying data to the server.
  *
  * Returns:
  *  - the number of bytes send
index 52b50d197ebc868438b5d1394c41edb05ecf3188..833762d76a3644a9237c19ccb9c29f9a26e36f51 100644 (file)
@@ -300,6 +300,18 @@ typedef enum {
        SDB_CONNECTION_EXPR,
 } sdb_conn_state_t;
 
+#define SDB_CONN_MSGTYPE_TO_STRING(t) \
+       (((t) == SDB_CONNECTION_IDLE) ? "IDLE" \
+               : ((t) == SDB_CONNECTION_PING) ? "PING" \
+               : ((t) == SDB_CONNECTION_STARTUP) ? "STARTUP" \
+               : ((t) == SDB_CONNECTION_QUERY) ? "QUERY" \
+               : ((t) == SDB_CONNECTION_FETCH) ? "FETCH" \
+               : ((t) == SDB_CONNECTION_LIST) ? "LIST" \
+               : ((t) == SDB_CONNECTION_LOOKUP) ? "LOOKUP" \
+               : ((t) == SDB_CONNECTION_TIMESERIES) ? "TIMESERIES" \
+               : ((t) == SDB_CONNECTION_STORE) ? "STORE" \
+               : "UNKNOWN")
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif