Commit a15dcb0b authored by Pawel Kaminski's avatar Pawel Kaminski Committed by Darek Stojaczyk
Browse files

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: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Signed-off-by: default avatarPawel Kaminski <pawelx.kaminski@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/459341


Reviewed-by: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 6ad6a113
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -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);

+2 −0
Original line number Diff line number Diff line
@@ -67,6 +67,8 @@ struct spdk_jsonrpc_request {

	uint8_t *send_buf;

	struct spdk_json_write_ctx *response;

	STAILQ_ENTRY(spdk_jsonrpc_request) link;
};

+31 −40
Original line number Diff line number Diff line
@@ -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)
+21 −2
Original line number Diff line number Diff line
@@ -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