From 1b6c4d55037135271c66b43e81691c5131d9813b Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Fri, 16 Jan 2015 23:45:23 +0100 Subject: [PATCH] client: Added sdb_client_rpc. 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 | 53 ++++++++++++++++++++++++++++++++++++ src/include/client/sock.h | 24 ++++++++++++++-- src/include/frontend/proto.h | 12 ++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/src/client/sock.c b/src/client/sock.c index cd9c8ce..6a1e49f 100644 --- a/src/client/sock.c +++ b/src/client/sock.c @@ -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) diff --git a/src/include/client/sock.h b/src/include/client/sock.h index 638f862..9a7947b 100644 --- a/src/include/client/sock.h +++ b/src/include/client/sock.h @@ -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 diff --git a/src/include/frontend/proto.h b/src/include/frontend/proto.h index 52b50d1..833762d 100644 --- a/src/include/frontend/proto.h +++ b/src/include/frontend/proto.h @@ -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 -- 2.30.2