From 2f557958d0762ad00e068f997e2d25a205ded4b7 Mon Sep 17 00:00:00 2001 From: Pawel Wodkowski Date: Thu, 18 Oct 2018 14:48:43 +0200 Subject: [PATCH] jsonrpc: add internal poll handler As preparation for non blocking mode make the spdk_jsonrpc_client_send_request functon just queue the request. Then in spdk_jsonrpc_client_recv_response we actually send it. Without this change send function will stay blocking. Change-Id: Ida2290696d78afcb06d84a4538b74e2311043911 Signed-off-by: Pawel Wodkowski Reviewed-on: https://review.gerrithub.io/429910 Tested-by: SPDK CI Jenkins Chandler-Test-Pool: SPDK Automated Test System Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- include/spdk/jsonrpc.h | 15 ++++++++++- lib/jsonrpc/jsonrpc_client.c | 3 +++ lib/jsonrpc/jsonrpc_client_tcp.c | 43 ++++++++++++++++++++++++++----- lib/jsonrpc/jsonrpc_internal.h | 8 +++--- test/rpc_client/rpc_client_test.c | 1 - 5 files changed, 58 insertions(+), 12 deletions(-) diff --git a/include/spdk/jsonrpc.h b/include/spdk/jsonrpc.h index 0fa5fb421..39ffebf6b 100644 --- a/include/spdk/jsonrpc.h +++ b/include/spdk/jsonrpc.h @@ -219,7 +219,10 @@ struct spdk_jsonrpc_client *spdk_jsonrpc_client_connect(const char *rpc_sock_add int addr_family); /** - * Close the JSON-RPC client. + * Close JSON-RPC connection and free \c client object. + * + * This function is not thread safe and should only be called from one thread at + * a time while no other threads are actively \c client object. * * \param client JSON-RPC client. */ @@ -245,10 +248,14 @@ void spdk_jsonrpc_client_free_request(struct spdk_jsonrpc_client_request *req); * Send the JSON-RPC request in JSON-RPC client. Library takes ownership of the * request object and will free it when done. * + * This function is not thread safe and should only be called from one thread at + * a time while no other threads are actively \c client object. + * * \param client JSON-RPC client. * \param req JSON-RPC request. * * \return 0 on success or negative error code. + * -ENOSPC - no space left to queue another request. Try again later. */ int spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client *client, struct spdk_jsonrpc_client_request *req); @@ -256,6 +263,9 @@ int spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client *client, /** * Receive the JSON-RPC response in JSON-RPC client. * + * This function is not thread safe and should only be called from one thread at + * a time while no other threads are actively \c client object. + * * \param client JSON-RPC client. * * \return 0 on success. @@ -266,6 +276,9 @@ int spdk_jsonrpc_client_recv_response(struct spdk_jsonrpc_client *client); * Return JSON RPC response object representing next available response from client connection. * Returned pointer must be freed using \c spdk_jsonrpc_client_free_response * + * This function is not thread safe and should only be called from one thread at + * a time while no other threads are actively \c client object. + * * \param client * \return pointer to JSON RPC response object or NULL if no response available. */ diff --git a/lib/jsonrpc/jsonrpc_client.c b/lib/jsonrpc/jsonrpc_client.c index 3ee8d2520..f6dd34ecc 100644 --- a/lib/jsonrpc/jsonrpc_client.c +++ b/lib/jsonrpc/jsonrpc_client.c @@ -144,9 +144,12 @@ spdk_jsonrpc_parse_response(struct spdk_jsonrpc_client *client) goto err; } + r->ready = 1; + return 0; err: + client->resp = NULL; spdk_jsonrpc_client_free_response(&r->jsonrpc); return -EINVAL; } diff --git a/lib/jsonrpc/jsonrpc_client_tcp.c b/lib/jsonrpc/jsonrpc_client_tcp.c index 8324a9319..55908bf31 100644 --- a/lib/jsonrpc/jsonrpc_client_tcp.c +++ b/lib/jsonrpc/jsonrpc_client_tcp.c @@ -36,6 +36,8 @@ #define RPC_DEFAULT_PORT "5260" +static int _spdk_jsonrpc_client_poll(struct spdk_jsonrpc_client *client); + static struct spdk_jsonrpc_client * _spdk_jsonrpc_client_connect(int domain, int protocol, struct sockaddr *server_addr, socklen_t addrlen) @@ -176,11 +178,15 @@ spdk_jsonrpc_client_free_request(struct spdk_jsonrpc_client_request *req) free(req); } -int -spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client *client, - struct spdk_jsonrpc_client_request *request) +static int +_spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client *client) { ssize_t rc; + struct spdk_jsonrpc_client_request *request = client->request; + + if (!request) { + return 0; + } /* Reset offset in request */ request->send_offset = 0; @@ -200,6 +206,9 @@ spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client *client, request->send_len -= rc; } + client->request = NULL; + + spdk_jsonrpc_client_free_request(request); return 0; } @@ -225,12 +234,14 @@ recv_buf_expand(struct spdk_jsonrpc_client *client) return 0; } -int -spdk_jsonrpc_client_recv_response(struct spdk_jsonrpc_client *client) +static int +_spdk_jsonrpc_client_poll(struct spdk_jsonrpc_client *client) { ssize_t rc = 0; size_t recv_avail; + _spdk_jsonrpc_client_send_request(client); + if (client->recv_buf == NULL) { /* memory malloc for recv-buf */ client->recv_buf = malloc(SPDK_JSONRPC_SEND_BUF_SIZE_INIT); @@ -284,12 +295,30 @@ spdk_jsonrpc_client_recv_response(struct spdk_jsonrpc_client *client) return 0; } +int +spdk_jsonrpc_client_recv_response(struct spdk_jsonrpc_client *client) +{ + return _spdk_jsonrpc_client_poll(client); +} + +int spdk_jsonrpc_client_send_request(struct spdk_jsonrpc_client *client, + struct spdk_jsonrpc_client_request *req) +{ + if (client->request != NULL) { + return -ENOSPC; + } + + client->request = req; + return 0; +} + struct spdk_jsonrpc_client_response * spdk_jsonrpc_client_get_response(struct spdk_jsonrpc_client *client) { - struct spdk_jsonrpc_client_response_internal *r = client->resp; + struct spdk_jsonrpc_client_response_internal *r; - if (r == NULL) { + r = client->resp; + if (r == NULL || r->ready == false) { return NULL; } diff --git a/lib/jsonrpc/jsonrpc_internal.h b/lib/jsonrpc/jsonrpc_internal.h index 1518145b4..50f509bf9 100644 --- a/lib/jsonrpc/jsonrpc_internal.h +++ b/lib/jsonrpc/jsonrpc_internal.h @@ -108,6 +108,7 @@ struct spdk_jsonrpc_client_request { struct spdk_jsonrpc_client_response_internal { struct spdk_jsonrpc_client_response jsonrpc; + bool ready; uint8_t *buf; size_t values_cnt; struct spdk_json_val values[]; @@ -116,12 +117,13 @@ struct spdk_jsonrpc_client_response_internal { struct spdk_jsonrpc_client { int sockfd; - /* Parsed response */ - struct spdk_jsonrpc_client_response_internal *resp; - size_t recv_buf_size; size_t recv_offset; char *recv_buf; + + /* Parsed response */ + struct spdk_jsonrpc_client_response_internal *resp; + struct spdk_jsonrpc_client_request *request; }; /* jsonrpc_server_tcp */ diff --git a/test/rpc_client/rpc_client_test.c b/test/rpc_client/rpc_client_test.c index 62b3cd924..5e9514ad0 100644 --- a/test/rpc_client/rpc_client_test.c +++ b/test/rpc_client/rpc_client_test.c @@ -72,7 +72,6 @@ spdk_jsonrpc_client_check_rpc_method(struct spdk_jsonrpc_client *client, char *m w = spdk_jsonrpc_begin_request(request, 1, "get_rpc_methods"); spdk_jsonrpc_end_request(request, w); spdk_jsonrpc_client_send_request(client, request); - spdk_jsonrpc_client_free_request(request); rc = spdk_jsonrpc_client_recv_response(client); if (rc) {