aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/surface/call.c
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2015-02-03 12:07:07 -0800
committerGravatar Craig Tiller <ctiller@google.com>2015-02-03 12:07:07 -0800
commitfb189f826e2e5edc9128155ef0847c447a47c6ce (patch)
tree91324ea580d473ca31670d024fccb2429d40462d /src/core/surface/call.c
parent034929cc31fe46d4943913939a4de678edf3507a (diff)
Flesh out batch API
Diffstat (limited to 'src/core/surface/call.c')
-rw-r--r--src/core/surface/call.c201
1 files changed, 160 insertions, 41 deletions
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 382909c865..1aecd3400a 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -173,7 +173,7 @@ static void do_nothing(void *ignored, grpc_op_error also_ignored) {}
static send_action choose_send_action(grpc_call *call);
static void enact_send_action(grpc_call *call, send_action sa);
-grpc_call *grpc_call_create(grpc_channel *channel,
+grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
const void *server_transport_data) {
size_t i;
grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel);
@@ -182,6 +182,7 @@ grpc_call *grpc_call_create(grpc_channel *channel,
memset(call, 0, sizeof(grpc_call));
gpr_mu_init(&call->mu);
call->channel = channel;
+ call->cq = cq;
call->is_client = server_transport_data == NULL;
for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) {
call->request_set[i] = REQSET_EMPTY;
@@ -321,37 +322,49 @@ static void unlock(grpc_call *call) {
}
}
-static void get_final_status(grpc_call *call, grpc_recv_status_args args) {
+static void get_final_status(grpc_call *call, grpc_ioreq_data out) {
+ int i;
+ for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
+ if (call->status[i].is_set) {
+ out.recv_status.set_value(call->status[i].code,
+ out.recv_status.user_data);
+ return;
+ }
+ }
+ out.recv_status.set_value(GRPC_STATUS_UNKNOWN, out.recv_status.user_data);
+}
+
+static void get_final_details(grpc_call *call, grpc_ioreq_data out) {
int i;
for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
if (call->status[i].is_set) {
- *args.code = call->status[i].code;
- if (!args.details) return;
if (call->status[i].details) {
gpr_slice details = call->status[i].details->slice;
size_t len = GPR_SLICE_LENGTH(details);
- if (len + 1 > *args.details_capacity) {
- *args.details_capacity =
- GPR_MAX(len + 1, *args.details_capacity * 3 / 2);
- *args.details = gpr_realloc(*args.details, *args.details_capacity);
+ if (len + 1 > *out.recv_status_details.details_capacity) {
+ *out.recv_status_details.details_capacity = GPR_MAX(
+ len + 1, *out.recv_status_details.details_capacity * 3 / 2);
+ *out.recv_status_details.details =
+ gpr_realloc(*out.recv_status_details.details,
+ *out.recv_status_details.details_capacity);
}
- memcpy(*args.details, GPR_SLICE_START_PTR(details), len);
- (*args.details)[len] = 0;
+ memcpy(*out.recv_status_details.details, GPR_SLICE_START_PTR(details),
+ len);
+ (*out.recv_status_details.details)[len] = 0;
} else {
goto no_details;
}
return;
}
}
- *args.code = GRPC_STATUS_UNKNOWN;
- if (!args.details) return;
no_details:
- if (0 == *args.details_capacity) {
- *args.details_capacity = 8;
- *args.details = gpr_malloc(*args.details_capacity);
+ if (0 == *out.recv_status_details.details_capacity) {
+ *out.recv_status_details.details_capacity = 8;
+ *out.recv_status_details.details =
+ gpr_malloc(*out.recv_status_details.details_capacity);
}
- **args.details = 0;
+ **out.recv_status_details.details = 0;
}
static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op,
@@ -389,8 +402,11 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op,
case GRPC_IOREQ_SEND_CLOSE:
break;
case GRPC_IOREQ_RECV_STATUS:
- get_final_status(
- call, call->request_data[GRPC_IOREQ_RECV_STATUS].recv_status);
+ get_final_status(call, call->request_data[GRPC_IOREQ_RECV_STATUS]);
+ break;
+ case GRPC_IOREQ_RECV_STATUS_DETAILS:
+ get_final_details(call,
+ call->request_data[GRPC_IOREQ_RECV_STATUS_DETAILS]);
break;
case GRPC_IOREQ_RECV_INITIAL_METADATA:
SWAP(grpc_metadata_array, call->buffered_metadata[0],
@@ -598,6 +614,7 @@ static void finish_read_ops(grpc_call *call) {
finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK);
}
finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK);
+ finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS_DETAILS, GRPC_OP_OK);
finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK);
/* fallthrough */
case READ_STATE_GOT_INITIAL_METADATA:
@@ -675,20 +692,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
return GRPC_CALL_OK;
}
-static void call_start_ioreq_done(grpc_call *call, grpc_op_error status,
- void *user_data) {
- grpc_cq_end_ioreq(call->cq, user_data, call, do_nothing, NULL, status);
-}
-
-grpc_call_error grpc_call_start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
- size_t nreqs, void *tag) {
- grpc_call_error err;
- lock(call);
- err = start_ioreq(call, reqs, nreqs, call_start_ioreq_done, tag);
- unlock(call);
- return err;
-}
-
grpc_call_error grpc_call_start_ioreq_and_call_back(
grpc_call *call, const grpc_ioreq *reqs, size_t nreqs,
grpc_ioreq_completion_func on_complete, void *user_data) {
@@ -873,6 +876,121 @@ void grpc_call_initial_metadata_complete(grpc_call_element *surface_element) {
}
/*
+ * BATCH API IMPLEMENTATION
+ */
+
+static void set_status_value_directly(grpc_status_code status, void *dest) {
+ *(grpc_status_code *)dest = status;
+}
+
+static void set_cancelled_value(grpc_status_code status, void *dest) {
+ *(grpc_status_code *)dest = (status != GRPC_STATUS_OK);
+}
+
+static void finish_batch(grpc_call *call, grpc_op_error result, void *tag) {}
+
+grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
+ size_t nops, void *tag) {
+ grpc_ioreq reqs[GRPC_IOREQ_OP_COUNT];
+ size_t in;
+ size_t out;
+ const grpc_op *op;
+ grpc_ioreq *req;
+
+ /* rewrite batch ops into ioreq ops */
+ for (in = 0, out = 0; in < nops; in++) {
+ op = &ops[in];
+ switch (op->op) {
+ case GRPC_OP_SEND_INITIAL_METADATA:
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_SEND_INITIAL_METADATA;
+ req->data.send_metadata.count = op->data.send_initial_metadata.count;
+ req->data.send_metadata.metadata =
+ op->data.send_initial_metadata.metadata;
+ break;
+ case GRPC_OP_SEND_MESSAGE:
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_SEND_MESSAGE;
+ req->data.send_message = op->data.send_message;
+ break;
+ case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
+ if (!call->is_client) {
+ return GRPC_CALL_ERROR_NOT_ON_SERVER;
+ }
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_SEND_CLOSE;
+ break;
+ case GRPC_OP_SEND_STATUS_FROM_SERVER:
+ if (call->is_client) {
+ return GRPC_CALL_ERROR_NOT_ON_CLIENT;
+ }
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_SEND_TRAILING_METADATA;
+ req->data.send_metadata.count =
+ op->data.send_status_from_server.trailing_metadata_count;
+ req->data.send_metadata.metadata =
+ op->data.send_status_from_server.trailing_metadata;
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_SEND_STATUS;
+ req->data.send_status.code = op->data.send_status_from_server.status;
+ req->data.send_status.details =
+ op->data.send_status_from_server.status_details;
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_SEND_CLOSE;
+ break;
+ case GRPC_OP_RECV_INITIAL_METADATA:
+ if (!call->is_client) {
+ return GRPC_CALL_ERROR_NOT_ON_SERVER;
+ }
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_RECV_INITIAL_METADATA;
+ req->data.recv_metadata = op->data.recv_initial_metadata;
+ break;
+ case GRPC_OP_RECV_MESSAGE:
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_RECV_MESSAGE;
+ req->data.recv_message = op->data.recv_message;
+ break;
+ case GRPC_OP_RECV_STATUS_ON_CLIENT:
+ if (!call->is_client) {
+ return GRPC_CALL_ERROR_NOT_ON_SERVER;
+ }
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_RECV_STATUS;
+ req->data.recv_status.set_value = set_status_value_directly;
+ req->data.recv_status.user_data = op->data.recv_status_on_client.status;
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_RECV_STATUS_DETAILS;
+ req->data.recv_status_details.details =
+ op->data.recv_status_on_client.status_details;
+ req->data.recv_status_details.details_capacity =
+ op->data.recv_status_on_client.status_details_capacity;
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_RECV_TRAILING_METADATA;
+ req->data.recv_metadata =
+ op->data.recv_status_on_client.trailing_metadata;
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_RECV_CLOSE;
+ break;
+ case GRPC_OP_RECV_CLOSE_ON_SERVER:
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_RECV_STATUS;
+ req->data.recv_status.set_value = set_cancelled_value;
+ req->data.recv_status.user_data =
+ op->data.recv_close_on_server.cancelled;
+ req = &reqs[out++];
+ req->op = GRPC_IOREQ_RECV_CLOSE;
+ break;
+ }
+ }
+
+ grpc_cq_begin_op(call->cq, call, GRPC_OP_COMPLETE);
+
+ return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_batch,
+ tag);
+}
+
+/*
* LEGACY API IMPLEMENTATION
* All this code will disappear as soon as wrappings are updated
*/
@@ -985,7 +1103,7 @@ static void finish_send_metadata(grpc_call *call, grpc_op_error status,
grpc_call_error grpc_call_invoke_old(grpc_call *call, grpc_completion_queue *cq,
void *metadata_read_tag,
void *finished_tag, gpr_uint32 flags) {
- grpc_ioreq reqs[3];
+ grpc_ioreq reqs[4];
legacy_state *ls;
grpc_call_error err;
@@ -1014,11 +1132,13 @@ grpc_call_error grpc_call_invoke_old(grpc_call *call, grpc_completion_queue *cq,
reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA;
reqs[0].data.recv_metadata = &ls->trailing_md_in;
reqs[1].op = GRPC_IOREQ_RECV_STATUS;
- reqs[1].data.recv_status.details = &ls->details;
- reqs[1].data.recv_status.details_capacity = &ls->details_capacity;
- reqs[1].data.recv_status.code = &ls->status;
- reqs[2].op = GRPC_IOREQ_RECV_CLOSE;
- err = start_ioreq(call, reqs, 3, finish_status, NULL);
+ reqs[1].data.recv_status.user_data = &ls->status;
+ reqs[1].data.recv_status.set_value = set_status_value_directly;
+ reqs[2].op = GRPC_IOREQ_RECV_STATUS_DETAILS;
+ reqs[2].data.recv_status_details.details = &ls->details;
+ reqs[2].data.recv_status_details.details_capacity = &ls->details_capacity;
+ reqs[3].op = GRPC_IOREQ_RECV_CLOSE;
+ err = start_ioreq(call, reqs, 4, finish_status, NULL);
if (err != GRPC_CALL_OK) goto done;
done:
@@ -1046,9 +1166,8 @@ grpc_call_error grpc_call_server_accept_old(grpc_call *call,
ls->finished_tag = finished_tag;
reqs[0].op = GRPC_IOREQ_RECV_STATUS;
- reqs[0].data.recv_status.details = NULL;
- reqs[0].data.recv_status.details_capacity = 0;
- reqs[0].data.recv_status.code = &ls->status;
+ reqs[0].data.recv_status.user_data = &ls->status;
+ reqs[0].data.recv_status.set_value = set_status_value_directly;
reqs[1].op = GRPC_IOREQ_RECV_CLOSE;
err = start_ioreq(call, reqs, 2, finish_status, NULL);
unlock(call);