jsonrpc: always allocate response for request

We already have send buffer allocated. This will greatly improving code
as we guarantee by design that there is always JSON write context
object.

Change-Id: Id487c01448e1a65d9d4ef76d40a2a9f178b2f570
Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
Signed-off-by: Pawel Kaminski <pawelx.kaminski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/459341
Reviewed-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Pawel Kaminski 2019-02-21 17:25:54 +01:00 committed by Darek Stojaczyk
parent 6ad6a1131b
commit a15dcb0bf0
4 changed files with 55 additions and 44 deletions

View File

@ -186,8 +186,7 @@ int spdk_jsonrpc_conn_del_close_cb(struct spdk_jsonrpc_server_conn *conn,
*
* \param request JSON-RPC request to respond to.
* \return JSON write context to write the response object to, or NULL if no
* response is necessary.
* \return Non-NULL pointer to JSON write context to write the response object to.
*/
struct spdk_json_write_ctx *spdk_jsonrpc_begin_result(struct spdk_jsonrpc_request *request);

View File

@ -67,6 +67,8 @@ struct spdk_jsonrpc_request {
uint8_t *send_buf;
struct spdk_json_write_ctx *response;
STAILQ_ENTRY(spdk_jsonrpc_request) link;
};

View File

@ -195,6 +195,13 @@ spdk_jsonrpc_parse_request(struct spdk_jsonrpc_server_conn *conn, const void *js
return -1;
}
request->response = spdk_json_write_begin(spdk_jsonrpc_server_write_cb, request, 0);
if (request->response == NULL) {
SPDK_ERRLOG("Failed to allocate response JSON write context.\n");
spdk_jsonrpc_free_request(request);
return -1;
}
if (rc <= 0 || rc > SPDK_JSONRPC_MAX_VALUES) {
SPDK_DEBUGLOG(SPDK_LOG_RPC, "JSON parse error\n");
spdk_jsonrpc_server_handle_error(request, SPDK_JSONRPC_ERROR_PARSE_ERROR);
@ -236,15 +243,11 @@ spdk_jsonrpc_get_conn(struct spdk_jsonrpc_request *request)
return request->conn;
}
/* Never return NULL */
static struct spdk_json_write_ctx *
begin_response(struct spdk_jsonrpc_request *request)
{
struct spdk_json_write_ctx *w;
w = spdk_json_write_begin(spdk_jsonrpc_server_write_cb, request, 0);
if (w == NULL) {
return NULL;
}
struct spdk_json_write_ctx *w = request->response;
spdk_json_write_object_begin(w);
spdk_json_write_named_string(w, "jsonrpc", "2.0");
@ -263,14 +266,18 @@ static void
skip_response(struct spdk_jsonrpc_request *request)
{
request->send_len = 0;
spdk_json_write_end(request->response);
request->response = NULL;
spdk_jsonrpc_server_send_response(request);
}
static void
end_response(struct spdk_jsonrpc_request *request, struct spdk_json_write_ctx *w)
end_response(struct spdk_jsonrpc_request *request)
{
spdk_json_write_object_end(w);
spdk_json_write_end(w);
spdk_json_write_object_end(request->response);
spdk_json_write_end(request->response);
request->response = NULL;
spdk_jsonrpc_server_write_cb(request, "\n", 1);
spdk_jsonrpc_server_send_response(request);
}
@ -282,6 +289,9 @@ spdk_jsonrpc_free_request(struct spdk_jsonrpc_request *request)
return;
}
/* We must send or skip response explicitly */
assert(request->response == NULL);
request->conn->outstanding_requests--;
free(request->recv_buffer);
free(request->values);
@ -292,22 +302,9 @@ spdk_jsonrpc_free_request(struct spdk_jsonrpc_request *request)
struct spdk_json_write_ctx *
spdk_jsonrpc_begin_result(struct spdk_jsonrpc_request *request)
{
struct spdk_json_write_ctx *w;
if (request->id == NULL || request->id->type == SPDK_JSON_VAL_NULL) {
/* Notification - no response required */
skip_response(request);
return NULL;
}
w = begin_response(request);
if (w == NULL) {
skip_response(request);
return NULL;
}
struct spdk_json_write_ctx *w = begin_response(request);
spdk_json_write_name(w, "result");
return w;
}
@ -315,43 +312,37 @@ void
spdk_jsonrpc_end_result(struct spdk_jsonrpc_request *request, struct spdk_json_write_ctx *w)
{
assert(w != NULL);
assert(w == request->response);
end_response(request, w);
/* If there was no ID in request we skip response. */
if (request->id && request->id->type != SPDK_JSON_VAL_NULL) {
end_response(request);
} else {
skip_response(request);
}
}
void
spdk_jsonrpc_send_error_response(struct spdk_jsonrpc_request *request,
int error_code, const char *msg)
{
struct spdk_json_write_ctx *w;
w = begin_response(request);
if (w == NULL) {
skip_response(request);
return;
}
struct spdk_json_write_ctx *w = begin_response(request);
spdk_json_write_named_object_begin(w, "error");
spdk_json_write_named_int32(w, "code", error_code);
spdk_json_write_named_string(w, "message", msg);
spdk_json_write_object_end(w);
end_response(request, w);
end_response(request);
}
void
spdk_jsonrpc_send_error_response_fmt(struct spdk_jsonrpc_request *request,
int error_code, const char *fmt, ...)
{
struct spdk_json_write_ctx *w;
struct spdk_json_write_ctx *w = begin_response(request);
va_list args;
w = begin_response(request);
if (w == NULL) {
skip_response(request);
return;
}
spdk_json_write_named_object_begin(w, "error");
spdk_json_write_named_int32(w, "code", error_code);
va_start(args, fmt);
@ -359,7 +350,7 @@ spdk_jsonrpc_send_error_response_fmt(struct spdk_jsonrpc_request *request,
va_end(args);
spdk_json_write_object_end(w);
end_response(request, w);
end_response(request);
}
SPDK_LOG_REGISTER_COMPONENT("rpc", SPDK_LOG_RPC)

View File

@ -133,13 +133,33 @@ const struct spdk_json_val *g_cur_param;
g_cur_param++
#define FREE_REQUEST() \
spdk_jsonrpc_free_request(g_request); \
ut_jsonrpc_free_request(g_request, g_parse_error); \
g_request = NULL; \
g_cur_param = NULL; \
g_parse_error = 0; \
g_method = NULL; \
g_cur_param = g_params = NULL
static void
ut_jsonrpc_free_request(struct spdk_jsonrpc_request *request, int err)
{
struct spdk_json_write_ctx *w;
if (!request) {
return;
}
/* Need to emulate response to get the response write contex free */
if (err == 0) {
w = spdk_jsonrpc_begin_result(request);
spdk_json_write_string(w, "UT PASS response");
spdk_jsonrpc_end_result(request, w);
} else {
spdk_jsonrpc_send_error_response_fmt(request, err, "UT error response");
}
spdk_jsonrpc_free_request(request);
}
static void
ut_handle(struct spdk_jsonrpc_request *request, int error, const struct spdk_json_val *method,
@ -168,7 +188,6 @@ spdk_jsonrpc_server_handle_request(struct spdk_jsonrpc_request *request,
void
spdk_jsonrpc_server_send_response(struct spdk_jsonrpc_request *request)
{
/* TODO */
}
static void