From cce17ac033ac89563141f8c4cad9c842adac37ef Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 20 Jan 2015 09:29:28 -0800 Subject: [PATCH 01/93] First compiling version of the new C api. --- README.md | 4 +- include/grpc/grpc.h | 90 +- src/core/channel/connected_channel.c | 8 +- src/core/surface/call.c | 1265 ++++++++--------- src/core/surface/call.h | 17 +- src/core/surface/channel.c | 2 +- src/core/surface/client.c | 10 +- src/core/surface/completion_queue.c | 23 +- src/core/surface/completion_queue.h | 4 + src/core/surface/event_string.c | 6 +- src/core/surface/lame_client.c | 16 +- src/core/surface/server.c | 218 ++- src/core/transport/chttp2/stream_encoder.c | 2 +- src/cpp/client/channel.cc | 1 + test/core/echo/client.c | 2 +- test/core/echo/server.c | 2 +- test/core/end2end/cq_verifier.c | 12 +- test/core/end2end/dualstack_socket_test.c | 4 +- test/core/end2end/no_server_test.c | 2 +- test/core/end2end/tests/cancel_after_accept.c | 5 +- .../cancel_after_accept_and_writes_closed.c | 5 +- test/core/end2end/tests/cancel_after_invoke.c | 3 +- .../core/end2end/tests/cancel_before_invoke.c | 3 +- test/core/end2end/tests/cancel_in_a_vacuum.c | 3 +- .../end2end/tests/census_simple_request.c | 5 +- test/core/end2end/tests/disappearing_server.c | 5 +- ..._server_shutdown_finishes_inflight_calls.c | 5 +- .../early_server_shutdown_finishes_tags.c | 2 +- .../end2end/tests/graceful_server_shutdown.c | 5 +- .../core/end2end/tests/invoke_large_request.c | 5 +- .../end2end/tests/max_concurrent_streams.c | 18 +- test/core/end2end/tests/ping_pong_streaming.c | 5 +- ...esponse_with_binary_metadata_and_payload.c | 5 +- ...quest_response_with_metadata_and_payload.c | 5 +- .../tests/request_response_with_payload.c | 5 +- ...ponse_with_trailing_metadata_and_payload.c | 5 +- .../tests/request_with_large_metadata.c | 5 +- .../core/end2end/tests/request_with_payload.c | 5 +- .../end2end/tests/simple_delayed_request.c | 5 +- test/core/end2end/tests/simple_request.c | 10 +- test/core/end2end/tests/thread_stress.c | 4 +- .../writes_done_hangs_with_pending_read.c | 5 +- test/core/fling/client.c | 4 +- test/core/fling/server.c | 2 +- test/core/surface/completion_queue_test.c | 27 - test/core/surface/lame_client_test.c | 2 +- 46 files changed, 910 insertions(+), 936 deletions(-) diff --git a/README.md b/README.md index fa39d3b3089..dde057e55a2 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ fleshing out the details of each of the required operations. A gRPC RPC comprises of a bidirectional stream of messages, initiated by the client. In the client-to-server direction, this stream begins with a mandatory `Call Header`, followed by optional `Initial-Metadata`, followed by zero or more `Payload Messages`. The server-to-client direction contains an optional `Initial-Metadata`, followed by zero or more `Payload Messages` terminated with a mandatory `Status` and optional `Status-Metadata` (a.k.a.,`Trailing-Metadata`). ## Implementation over HTTP/2 -The abstract protocol defined above is implemented over [HTTP/2](https://http2.github.io/). gRPC bidirectional streams are mapped to HTTP/2 streams. The contents of `Call Header` and `Initial Metadata` are sent as HTTP/2 headers and subject to HPAC compression. `Payload Messages` are serialized into a byte stream of length prefixed gRPC frames which are then fragmented into HTTP/2 frames at the sender and reassembled at the receiver. `Status` and `Trailing-Metadata` are sent as HTTP/2 trailing headers (a.k.a., trailers). +The abstract protocol defined above is implemented over [HTTP/2](https://http2.github.io/). gRPC bidirectional streams are mapped to HTTP/2 streams. The contents of `Call Header` and `Initial Metadata` are sent as HTTP/2 headers and subject to HPACK compression. `Payload Messages` are serialized into a byte stream of length prefixed gRPC frames which are then fragmented into HTTP/2 frames at the sender and reassembled at the receiver. `Status` and `Trailing-Metadata` are sent as HTTP/2 trailing headers (a.k.a., trailers). ## Flow Control -gRPC inherits the flow control mchanims in HTTP/2 and uses them to enable fine-grained control of the amount of memory used for buffering in-flight messages. +gRPC inherits the flow control mechanisms in HTTP/2 and uses them to enable fine-grained control of the amount of memory used for buffering in-flight messages. diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index af52dd95f4f..93deeaab0ae 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -183,12 +183,11 @@ typedef struct grpc_metadata { } grpc_metadata; typedef enum grpc_completion_type { - GRPC_QUEUE_SHUTDOWN, /* Shutting down */ - GRPC_READ, /* A read has completed */ - GRPC_INVOKE_ACCEPTED, /* An invoke call has been accepted by flow - control */ - GRPC_WRITE_ACCEPTED, /* A write has been accepted by - flow control */ + GRPC_QUEUE_SHUTDOWN, /* Shutting down */ + GRPC_IOREQ, /* grpc_call_ioreq completion */ + GRPC_READ, /* A read has completed */ + GRPC_WRITE_ACCEPTED, /* A write has been accepted by + flow control */ GRPC_FINISH_ACCEPTED, /* writes_done or write_status has been accepted */ GRPC_CLIENT_METADATA_READ, /* The metadata array sent by server received at client */ @@ -213,6 +212,7 @@ typedef struct grpc_event { grpc_op_error write_accepted; grpc_op_error finish_accepted; grpc_op_error invoke_accepted; + grpc_op_error ioreq; struct { size_t count; grpc_metadata *elements; @@ -233,6 +233,67 @@ typedef struct grpc_event { } data; } grpc_event; +typedef struct { + size_t count; + size_t capacity; + grpc_metadata *metadata; +} grpc_metadata_array; + +typedef struct { + size_t count; + size_t capacity; + grpc_byte_buffer **buffers; +} grpc_byte_buffer_array; + +typedef struct { + grpc_status_code status; + size_t details_length; + size_t details_capacity; + char *details; +} grpc_recv_status; + +typedef struct { + const char *method; + const char *host; + gpr_timespec deadline; +} grpc_call_details; + +typedef enum { + GRPC_IOREQ_SEND_INITIAL_METADATA = 0, + GRPC_IOREQ_SEND_TRAILING_METADATA, + GRPC_IOREQ_SEND_MESSAGES, + GRPC_IOREQ_SEND_CLOSE, + GRPC_IOREQ_RECV_INITIAL_METADATA, + GRPC_IOREQ_RECV_TRAILING_METADATA, + GRPC_IOREQ_RECV_MESSAGES, + GRPC_IOREQ_RECV_STATUS, + GRPC_IOREQ_OP_COUNT +} grpc_ioreq_op; + +typedef union { + struct { + size_t count; + const grpc_metadata *metadata; + } send_metadata; + struct { + size_t count; + grpc_byte_buffer **messages; + } send_messages; + struct { + /* fields only make sense on the server */ + grpc_status_code status; + const char *details; + } send_close; + grpc_metadata_array *recv_metadata; + grpc_byte_buffer_array *recv_messages; + grpc_recv_status *recv_status; +} grpc_ioreq_data; + +typedef struct grpc_ioreq { + grpc_ioreq_op op; + grpc_ioreq_data data; +} grpc_ioreq; + /* Initialize the grpc library */ void grpc_init(void); @@ -275,8 +336,15 @@ void grpc_completion_queue_destroy(grpc_completion_queue *cq); /* Create a call given a grpc_channel, in order to call 'method'. The request is not sent until grpc_call_invoke is called. All completions are sent to 'completion_queue'. */ -grpc_call *grpc_channel_create_call(grpc_channel *channel, const char *method, - const char *host, gpr_timespec deadline); + +grpc_call *grpc_channel_create_call_old(grpc_channel *channel, const char *method, const char *host, gpr_timespec deadline); + +grpc_call *grpc_channel_create_call(grpc_channel *channel, + grpc_completion_queue *cq, + const grpc_call_details *details); + +grpc_call_error grpc_call_start_ioreq(grpc_call *call, const grpc_ioreq *reqs, + size_t nreqs, void *tag); /* Create a client channel */ grpc_channel *grpc_channel_create(const char *target, @@ -414,7 +482,11 @@ void grpc_call_destroy(grpc_call *call); tag_cancel. REQUIRES: Server must not have been shutdown. NOTE: calling this is the only way to obtain GRPC_SERVER_RPC_NEW events. */ -grpc_call_error grpc_server_request_call(grpc_server *server, void *tag_new); +grpc_call_error grpc_server_request_call_old(grpc_server *server, void *tag_new); + +grpc_call_error grpc_server_request_call( + grpc_server *server, grpc_completion_queue *cq, grpc_call_details *details, + grpc_metadata_array *initial_metadata, void *tag); /* Create a server */ grpc_server *grpc_server_create(grpc_completion_queue *cq, diff --git a/src/core/channel/connected_channel.c b/src/core/channel/connected_channel.c index d35cede97b5..61a6caf0328 100644 --- a/src/core/channel/connected_channel.c +++ b/src/core/channel/connected_channel.c @@ -298,10 +298,6 @@ static void recv_error(channel_data *chand, call_data *calld, int line, static void do_nothing(void *calldata, grpc_op_error error) {} -static void done_message(void *user_data, grpc_op_error error) { - grpc_byte_buffer_destroy(user_data); -} - static void finish_message(channel_data *chand, call_data *calld) { grpc_call_element *elem = calld->elem; grpc_call_op call_op; @@ -309,9 +305,9 @@ static void finish_message(channel_data *chand, call_data *calld) { call_op.flags = 0; /* if we got all the bytes for this message, call up the stack */ call_op.type = GRPC_RECV_MESSAGE; - call_op.done_cb = done_message; + call_op.done_cb = do_nothing; /* TODO(ctiller): this could be a lot faster if coded directly */ - call_op.user_data = call_op.data.message = grpc_byte_buffer_create( + call_op.data.message = grpc_byte_buffer_create( calld->incoming_message.slices, calld->incoming_message.count); gpr_slice_buffer_reset_and_unref(&calld->incoming_message); diff --git a/src/core/surface/call.c b/src/core/surface/call.c index e088793f01a..6a39d93f057 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -47,169 +47,78 @@ #define INVALID_TAG ((void *)0xdeadbeef) -/* Pending read queue - - This data structure tracks reads that need to be presented to the completion - queue but are waiting for the application to ask for them. */ - -#define INITIAL_PENDING_READ_COUNT 4 - typedef struct { - grpc_byte_buffer *byte_buffer; - void *user_data; - void (*on_finish)(void *user_data, grpc_op_error error); -} pending_read; - -/* TODO(ctiller): inline an element or two into this struct to avoid per-call - allocations */ -typedef struct { - pending_read *data; - size_t count; - size_t capacity; -} pending_read_array; - -typedef struct { - size_t drain_pos; - pending_read_array filling; - pending_read_array draining; -} pending_read_queue; - -static void pra_init(pending_read_array *array) { - array->data = gpr_malloc(sizeof(pending_read) * INITIAL_PENDING_READ_COUNT); - array->count = 0; - array->capacity = INITIAL_PENDING_READ_COUNT; -} - -static void pra_destroy(pending_read_array *array, - size_t finish_starting_from) { - size_t i; - for (i = finish_starting_from; i < array->count; i++) { - array->data[i].on_finish(array->data[i].user_data, GRPC_OP_ERROR); - } - gpr_free(array->data); -} - -/* Append an operation to an array, expanding as needed */ -static void pra_push(pending_read_array *a, grpc_byte_buffer *buffer, - void (*on_finish)(void *user_data, grpc_op_error error), - void *user_data) { - if (a->count == a->capacity) { - a->capacity *= 2; - a->data = gpr_realloc(a->data, sizeof(pending_read) * a->capacity); - } - a->data[a->count].byte_buffer = buffer; - a->data[a->count].user_data = user_data; - a->data[a->count].on_finish = on_finish; - a->count++; -} - -static void prq_init(pending_read_queue *q) { - q->drain_pos = 0; - pra_init(&q->filling); - pra_init(&q->draining); -} - -static void prq_destroy(pending_read_queue *q) { - pra_destroy(&q->filling, 0); - pra_destroy(&q->draining, q->drain_pos); -} - -static int prq_is_empty(pending_read_queue *q) { - return (q->drain_pos == q->draining.count && q->filling.count == 0); -} - -static void prq_push(pending_read_queue *q, grpc_byte_buffer *buffer, - void (*on_finish)(void *user_data, grpc_op_error error), - void *user_data) { - pra_push(&q->filling, buffer, on_finish, user_data); -} + size_t md_out_count; + size_t md_out_capacity; + grpc_mdelem **md_out; + grpc_byte_buffer *msg_out; + + /* input buffers */ + grpc_metadata_array md_in; + grpc_metadata_array trail_md_in; + grpc_recv_status status_in; + size_t msg_in_read_idx; + grpc_byte_buffer_array msg_in; -/* Take the first queue element and move it to the completion queue. Do nothing - if q is empty */ -static int prq_pop_to_cq(pending_read_queue *q, void *tag, grpc_call *call, - grpc_completion_queue *cq) { - pending_read_array temp_array; - pending_read *pr; - - if (q->drain_pos == q->draining.count) { - if (q->filling.count == 0) { - return 0; - } - q->draining.count = 0; - q->drain_pos = 0; - /* swap arrays */ - temp_array = q->filling; - q->filling = q->draining; - q->draining = temp_array; - } - - pr = q->draining.data + q->drain_pos; - q->drain_pos++; - grpc_cq_end_read(cq, tag, call, pr->on_finish, pr->user_data, - pr->byte_buffer); - return 1; -} - -/* grpc_call proper */ + void *finished_tag; +} legacy_state; -/* the state of a call, based upon which functions have been called against - said call */ -typedef enum { - CALL_CREATED, - CALL_BOUNDCQ, - CALL_STARTED, - CALL_FINISHED -} call_state; +typedef struct reqinfo { + grpc_ioreq_data data; + struct reqinfo *master; + grpc_ioreq_completion_func on_complete; + void *user_data; + gpr_uint32 need_mask; + gpr_uint32 complete_mask; +} reqinfo; struct grpc_call { grpc_completion_queue *cq; grpc_channel *channel; grpc_mdctx *metadata_context; + /* TODO(ctiller): share with cq if possible? */ + gpr_mu mu; - call_state state; gpr_uint8 is_client; - gpr_uint8 have_write; - grpc_metadata_buffer incoming_metadata; - - /* protects variables in this section */ - gpr_mu read_mu; - gpr_uint8 received_start; - gpr_uint8 start_ok; - gpr_uint8 reads_done; - gpr_uint8 received_finish; - gpr_uint8 received_metadata; - gpr_uint8 have_read; + gpr_uint8 got_initial_metadata; gpr_uint8 have_alarm; - gpr_uint8 pending_writes_done; + gpr_uint8 read_closed; + gpr_uint8 stream_closed; gpr_uint8 got_status_code; - /* The current outstanding read message tag (only valid if have_read == 1) */ - void *read_tag; - void *metadata_tag; - void *finished_tag; - pending_read_queue prq; - - grpc_alarm alarm; - /* The current outstanding send message/context/invoke/end tag (only valid if - have_write == 1) */ - void *write_tag; - grpc_byte_buffer *pending_write; - gpr_uint32 pending_write_flags; + reqinfo requests[GRPC_IOREQ_OP_COUNT]; + grpc_byte_buffer_array buffered_messages; + grpc_metadata_array buffered_initial_metadata; + grpc_metadata_array buffered_trailing_metadata; + size_t write_index; - /* The final status of the call */ grpc_status_code status_code; grpc_mdstr *status_details; + grpc_alarm alarm; + gpr_refcount internal_refcount; + + legacy_state *legacy_state; }; -#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) +#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call)+1)) #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1) #define CALL_ELEM_FROM_CALL(call, idx) \ grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx) #define CALL_FROM_TOP_ELEM(top_elem) \ CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem)) +#define SWAP(type, x, y) \ + do { \ + type temp = x; \ + x = y; \ + y = temp; \ + } while (0) + +#define TOMBSTONE_MASTER ((void *)1) +#define IS_LIVE_MASTER(x) ((x) != NULL && (x) != TOMBSTONE_MASTER) + static void do_nothing(void *ignored, grpc_op_error also_ignored) {} grpc_call *grpc_call_create(grpc_channel *channel, @@ -217,79 +126,328 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel); grpc_call *call = gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size); - call->cq = NULL; + memset(call, 0, sizeof(grpc_call)); + gpr_mu_init(&call->mu); call->channel = channel; + call->is_client = server_transport_data == NULL; grpc_channel_internal_ref(channel); call->metadata_context = grpc_channel_get_metadata_context(channel); - call->state = CALL_CREATED; - call->is_client = (server_transport_data == NULL); - call->write_tag = INVALID_TAG; - call->read_tag = INVALID_TAG; - call->metadata_tag = INVALID_TAG; - call->finished_tag = INVALID_TAG; - call->have_read = 0; - call->have_write = 0; - call->have_alarm = 0; - call->received_metadata = 0; - call->got_status_code = 0; - call->start_ok = 0; - call->status_code = - server_transport_data != NULL ? GRPC_STATUS_OK : GRPC_STATUS_UNKNOWN; - call->status_details = NULL; - call->received_finish = 0; - call->reads_done = 0; - call->received_start = 0; - call->pending_write = NULL; - call->pending_writes_done = 0; - grpc_metadata_buffer_init(&call->incoming_metadata); gpr_ref_init(&call->internal_refcount, 1); grpc_call_stack_init(channel_stack, server_transport_data, CALL_STACK_FROM_CALL(call)); - prq_init(&call->prq); - gpr_mu_init(&call->read_mu); return call; } +legacy_state *get_legacy_state(grpc_call *call) { + if (call->legacy_state == NULL) { + call->legacy_state = gpr_malloc(sizeof(legacy_state)); + memset(call->legacy_state, 0, sizeof(legacy_state)); + } + return call->legacy_state; +} + void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } void grpc_call_internal_unref(grpc_call *c) { if (gpr_unref(&c->internal_refcount)) { grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); - grpc_metadata_buffer_destroy(&c->incoming_metadata, GRPC_OP_OK); - if (c->status_details) { - grpc_mdstr_unref(c->status_details); - } - prq_destroy(&c->prq); - gpr_mu_destroy(&c->read_mu); grpc_channel_internal_unref(c->channel); + gpr_mu_destroy(&c->mu); + if (c->legacy_state) { + gpr_free(c->legacy_state->md_out); + gpr_free(c->legacy_state->md_in.metadata); + gpr_free(c->legacy_state->trail_md_in.metadata); + gpr_free(c->legacy_state->status_in.details); + gpr_free(c->legacy_state); + } gpr_free(c); } } +static grpc_call_error bind_cq(grpc_call *call, grpc_completion_queue *cq) { + if (call->cq) return GRPC_CALL_ERROR_ALREADY_INVOKED; + call->cq = cq; + return GRPC_CALL_OK; +} + +static void request_more_data(grpc_call *call) { + grpc_call_op op; + + /* call down */ + op.type = GRPC_REQUEST_DATA; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.done_cb = do_nothing; + op.user_data = NULL; + + grpc_call_execute_op(call, &op); +} + +#define OP_IN_MASK(op, mask) (((1 << (op)) & (mask)) != 0) + +static void start_next_step_and_unlock(grpc_call *call, reqinfo *master); + +static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, + grpc_op_error status) { + reqinfo *master = call->requests[op].master; + size_t i; + if (master == NULL || master == TOMBSTONE_MASTER) { + return; /* inactive */ + } + master->complete_mask |= 1 << op; + if (master->complete_mask == master->need_mask || status == GRPC_OP_ERROR) { + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + if (call->requests[i].master == master) { + call->requests[i].master = + (i == GRPC_IOREQ_SEND_MESSAGES || i == GRPC_IOREQ_RECV_MESSAGES) + ? NULL + : TOMBSTONE_MASTER; + } + master->on_complete(call, status, master->user_data); + } + } +} + +static void finish_write_step(void *pc, grpc_op_error error) { + grpc_call *call = pc; + gpr_mu_lock(&call->mu); + if (error == GRPC_OP_OK) { + if (call->write_index == + call->requests[GRPC_IOREQ_SEND_MESSAGES].data.send_messages.count) { + finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGES, GRPC_OP_OK); + } + start_next_step_and_unlock(call, + call->requests[GRPC_IOREQ_SEND_MESSAGES].master); + } else { + finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGES, GRPC_OP_ERROR); + gpr_mu_unlock(&call->mu); + } +} + +static void finish_finish_step(void *pc, grpc_op_error error) { + grpc_call *call = pc; + if (error == GRPC_OP_OK) { + gpr_mu_lock(&call->mu); + start_next_step_and_unlock(call, + call->requests[GRPC_IOREQ_SEND_CLOSE].master); + } else { + gpr_log(GPR_ERROR, "not implemented"); + abort(); + } +} + +static void start_next_step_and_unlock(grpc_call *call, reqinfo *master) { + reqinfo *requests = call->requests; + grpc_byte_buffer *send_message = NULL; + size_t i; + gpr_uint32 incomplete = master->need_mask & ~master->complete_mask; + gpr_uint8 send_initial_metadata = 0; + gpr_uint8 send_trailing_metadata = 0; + gpr_uint8 send_blocked = 0; + gpr_uint8 send_finished = 0; + gpr_uint8 completed; + + if (!send_blocked && + OP_IN_MASK(GRPC_IOREQ_SEND_INITIAL_METADATA, incomplete)) { + send_initial_metadata = 1; + finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_OP_OK); + master->complete_mask |= 1 << GRPC_IOREQ_SEND_INITIAL_METADATA; + } + + if (!send_blocked && OP_IN_MASK(GRPC_IOREQ_SEND_MESSAGES, incomplete)) { + grpc_ioreq_data data = requests[GRPC_IOREQ_SEND_MESSAGES].data; + send_message = data.send_messages.messages[call->write_index]; + send_blocked = 1; + call->write_index++; + } + + if (!send_blocked && (OP_IN_MASK(GRPC_IOREQ_SEND_CLOSE, incomplete))) { + send_finished = 1; + send_blocked = 1; + } + + if (!send_blocked && + OP_IN_MASK(GRPC_IOREQ_SEND_TRAILING_METADATA, incomplete)) { + send_trailing_metadata = 1; + finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); + } + + completed = !send_blocked && master->complete_mask == master->need_mask; + + if (completed) { + master->on_complete(call, GRPC_OP_OK, master->user_data); + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + if (call->requests[i].master == master) { + call->requests[i].master = + (i == GRPC_IOREQ_SEND_MESSAGES || i == GRPC_IOREQ_RECV_MESSAGES) + ? NULL + : TOMBSTONE_MASTER; + } + } + } + + gpr_mu_unlock(&call->mu); + + if (send_initial_metadata) { + grpc_ioreq_data data = requests[GRPC_IOREQ_SEND_INITIAL_METADATA].data; + for (i = 0; i < data.send_metadata.count; i++) { + const grpc_metadata *md = &data.send_metadata.metadata[i]; + grpc_call_element_send_metadata( + CALL_ELEM_FROM_CALL(call, 0), + grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, + (const gpr_uint8 *)md->value, + md->value_length)); + } + } + + if (send_message) { + grpc_call_op op; + op.type = GRPC_SEND_MESSAGE; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.data.message = send_message; + op.done_cb = finish_write_step; + op.user_data = call; + grpc_call_execute_op(call, &op); + } + + if (send_finished) { + grpc_call_op op; + op.type = GRPC_SEND_FINISH; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.done_cb = finish_finish_step; + op.user_data = call; + grpc_call_execute_op(call, &op); + } + + if (send_trailing_metadata) { + grpc_ioreq_data data = requests[GRPC_IOREQ_SEND_TRAILING_METADATA].data; + for (i = 0; i < data.send_metadata.count; i++) { + const grpc_metadata *md = &data.send_metadata.metadata[i]; + grpc_call_element_send_metadata( + CALL_ELEM_FROM_CALL(call, 0), + grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, + (const gpr_uint8 *)md->value, + md->value_length)); + } + } +} + +static grpc_call_error start_ioreq_error(grpc_call *call, + gpr_uint32 mutated_ops, + grpc_call_error ret) { + size_t i; + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + if (mutated_ops & (1 << i)) { + call->requests[i].master = NULL; + } + } + gpr_mu_unlock(&call->mu); + return ret; +} + +static grpc_call_error start_ioreq_and_unlock( + grpc_call *call, const grpc_ioreq *reqs, size_t nreqs, + grpc_ioreq_completion_func completion, void *user_data) { + size_t i; + gpr_uint32 have_ops = 0; + gpr_uint32 precomplete = 0; + grpc_ioreq_op op; + reqinfo *master = NULL; + reqinfo *requests = call->requests; + grpc_ioreq_data data; + + for (i = 0; i < nreqs; i++) { + op = reqs[i].op; + if (requests[op].master) { + return start_ioreq_error(call, have_ops, + GRPC_CALL_ERROR_TOO_MANY_OPERATIONS); + } + if (master == NULL) { + master = &requests[op]; + } + have_ops |= 1 << op; + data = reqs[i].data; + + switch (op) { + default: + break; + case GRPC_IOREQ_RECV_MESSAGES: + data.recv_messages->count = 0; + if (call->buffered_messages.count > 0) { + SWAP(grpc_byte_buffer_array, *data.recv_messages, + call->buffered_messages); + precomplete |= 1 << op; + } + break; + case GRPC_IOREQ_SEND_MESSAGES: + call->write_index = 0; + break; + } + + requests[op].data = data; + requests[op].master = master; + } + + GPR_ASSERT(master != NULL); + master->need_mask = have_ops; + master->complete_mask = precomplete; + master->on_complete = completion; + master->user_data = user_data; + + start_next_step_and_unlock(call, master); + + if (OP_IN_MASK(GRPC_IOREQ_RECV_MESSAGES, have_ops & ~precomplete)) { + request_more_data(call); + } + + 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) { + gpr_mu_lock(&call->mu); + return start_ioreq_and_unlock(call, reqs, nreqs, call_start_ioreq_done, tag); +} + +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) { + gpr_mu_lock(&call->mu); + return start_ioreq_and_unlock(call, reqs, nreqs, on_complete, user_data); +} + void grpc_call_destroy(grpc_call *c) { int cancel; - gpr_mu_lock(&c->read_mu); + gpr_mu_lock(&c->mu); if (c->have_alarm) { grpc_alarm_cancel(&c->alarm); c->have_alarm = 0; } - cancel = !c->received_finish; - gpr_mu_unlock(&c->read_mu); + cancel = !c->stream_closed; + gpr_mu_unlock(&c->mu); if (cancel) grpc_call_cancel(c); grpc_call_internal_unref(c); } static void maybe_set_status_code(grpc_call *call, gpr_uint32 status) { - if (!call->got_status_code) { - call->status_code = status; - call->got_status_code = 1; - } + if (call->got_status_code) return; + call->status_code = status; + call->got_status_code = 1; } static void maybe_set_status_details(grpc_call *call, grpc_mdstr *status) { - if (!call->status_details) { - call->status_details = grpc_mdstr_ref(status); + if (call->status_details != NULL) { + grpc_mdstr_unref(status); + return; } + call->status_details = status; } grpc_call_error grpc_call_cancel(grpc_call *c) { @@ -314,12 +472,12 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *c, grpc_mdstr *details = description ? grpc_mdstr_from_string(c->metadata_context, description) : NULL; - gpr_mu_lock(&c->read_mu); + gpr_mu_lock(&c->mu); maybe_set_status_code(c, status); if (details) { maybe_set_status_details(c, details); } - gpr_mu_unlock(&c->read_mu); + gpr_mu_unlock(&c->mu); return grpc_call_cancel(c); } @@ -332,525 +490,259 @@ void grpc_call_execute_op(grpc_call *call, grpc_call_op *op) { void grpc_call_add_mdelem(grpc_call *call, grpc_mdelem *mdelem, gpr_uint32 flags) { - grpc_call_element *elem; - grpc_call_op op; - - GPR_ASSERT(call->state < CALL_FINISHED); - - op.type = GRPC_SEND_METADATA; - op.dir = GRPC_CALL_DOWN; - op.flags = flags; - op.done_cb = do_nothing; - op.user_data = NULL; - op.data.metadata = mdelem; + legacy_state *ls = get_legacy_state(call); - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); + if (ls->md_out_count == ls->md_out_capacity) { + ls->md_out_capacity = + GPR_MAX(ls->md_out_count * 3 / 2, ls->md_out_count + 8); + ls->md_out = + gpr_realloc(ls->md_out, sizeof(grpc_mdelem *) * ls->md_out_capacity); + } + ls->md_out[ls->md_out_count++] = mdelem; } grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, gpr_uint32 flags) { - grpc_mdelem *mdelem; - - if (call->is_client) { - if (call->state >= CALL_STARTED) { - return GRPC_CALL_ERROR_ALREADY_INVOKED; - } - } else { - if (call->state >= CALL_FINISHED) { - return GRPC_CALL_ERROR_ALREADY_FINISHED; - } - } - - mdelem = grpc_mdelem_from_string_and_buffer( - call->metadata_context, metadata->key, (gpr_uint8 *)metadata->value, - metadata->value_length); - grpc_call_add_mdelem(call, mdelem, flags); + grpc_call_add_mdelem( + call, grpc_mdelem_from_string_and_buffer( + call->metadata_context, metadata->key, + (gpr_uint8 *)metadata->value, metadata->value_length), + flags); return GRPC_CALL_OK; } -static void finish_call(grpc_call *call) { - size_t count; - grpc_metadata *elements; - count = grpc_metadata_buffer_count(&call->incoming_metadata); - elements = grpc_metadata_buffer_extract_elements(&call->incoming_metadata); - grpc_cq_end_finished( - call->cq, call->finished_tag, call, grpc_metadata_buffer_cleanup_elements, - elements, call->status_code, - call->status_details - ? (char *)grpc_mdstr_as_c_string(call->status_details) - : NULL, - elements, count); -} - -static void done_write(void *user_data, grpc_op_error error) { - grpc_call *call = user_data; - void *tag = call->write_tag; +static void finish_status(grpc_call *call, grpc_op_error status, void *tag) { + legacy_state *ls; - GPR_ASSERT(call->have_write); - call->have_write = 0; - call->write_tag = INVALID_TAG; - grpc_cq_end_write_accepted(call->cq, tag, call, NULL, NULL, error); -} - -static void done_writes_done(void *user_data, grpc_op_error error) { - grpc_call *call = user_data; - void *tag = call->write_tag; - - GPR_ASSERT(call->have_write); - call->have_write = 0; - call->write_tag = INVALID_TAG; - grpc_cq_end_finish_accepted(call->cq, tag, call, NULL, NULL, error); -} - -static void call_started(void *user_data, grpc_op_error error) { - grpc_call *call = user_data; - grpc_call_element *elem; - grpc_byte_buffer *pending_write = NULL; - gpr_uint32 pending_write_flags = 0; - gpr_uint8 pending_writes_done = 0; - int ok; - grpc_call_op op; + gpr_mu_lock(&call->mu); + ls = get_legacy_state(call); + gpr_mu_unlock(&call->mu); - gpr_mu_lock(&call->read_mu); - GPR_ASSERT(!call->received_start); - call->received_start = 1; - ok = call->start_ok = (error == GRPC_OP_OK); - pending_write = call->pending_write; - pending_write_flags = call->pending_write_flags; - pending_writes_done = call->pending_writes_done; - gpr_mu_unlock(&call->read_mu); - - if (pending_write) { - if (ok) { - op.type = GRPC_SEND_MESSAGE; - op.dir = GRPC_CALL_DOWN; - op.flags = pending_write_flags; - op.done_cb = done_write; - op.user_data = call; - op.data.message = pending_write; - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); - } else { - done_write(call, error); - } - grpc_byte_buffer_destroy(pending_write); - } - if (pending_writes_done) { - if (ok) { - op.type = GRPC_SEND_FINISH; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = done_writes_done; - op.user_data = call; - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); - } else { - done_writes_done(call, error); + if (status == GRPC_OP_OK) { + grpc_cq_end_finished(call->cq, tag, call, do_nothing, NULL, + ls->status_in.status, ls->status_in.details, + ls->trail_md_in.metadata, ls->trail_md_in.count); + } else { + grpc_cq_end_finished(call->cq, tag, call, do_nothing, NULL, + GRPC_STATUS_UNKNOWN, "Read status failed", NULL, 0); + } +} + +static void finish_recv_metadata(grpc_call *call, grpc_op_error status, + void *tag) { + grpc_ioreq reqs[2]; + legacy_state *ls; + + gpr_mu_lock(&call->mu); + ls = get_legacy_state(call); + if (status == GRPC_OP_OK) { + grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, + ls->md_in.count, ls->md_in.metadata); + + reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA; + reqs[0].data.recv_metadata = &ls->trail_md_in; + reqs[1].op = GRPC_IOREQ_RECV_STATUS; + reqs[1].data.recv_status = &ls->status_in; + if (GRPC_CALL_OK != start_ioreq_and_unlock(call, reqs, GPR_ARRAY_SIZE(reqs), + finish_status, + ls->finished_tag)) { + grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, + GRPC_STATUS_UNKNOWN, + "Failed to start reading status", NULL, 0); } + } else { + gpr_mu_unlock(&call->mu); + grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, 0, + NULL); + grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, + GRPC_STATUS_UNKNOWN, "Failed to read initial metadata", + NULL, 0); } - - grpc_call_internal_unref(call); } grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, void *metadata_read_tag, void *finished_tag, gpr_uint32 flags) { - grpc_call_element *elem; - grpc_call_op op; + grpc_ioreq req; + legacy_state *ls = get_legacy_state(call); + grpc_call_error err; - /* validate preconditions */ - if (!call->is_client) { - gpr_log(GPR_ERROR, "can only call %s on clients", __FUNCTION__); - return GRPC_CALL_ERROR_NOT_ON_SERVER; - } - - if (call->state >= CALL_STARTED || call->cq) { - gpr_log(GPR_ERROR, "call is already invoked"); - return GRPC_CALL_ERROR_ALREADY_INVOKED; - } - - if (call->have_write) { - gpr_log(GPR_ERROR, "can only have one pending write operation at a time"); - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } - - if (call->have_read) { - gpr_log(GPR_ERROR, "can only have one pending read operation at a time"); - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } - - if (flags & GRPC_WRITE_NO_COMPRESS) { - return GRPC_CALL_ERROR_INVALID_FLAGS; - } - - /* inform the completion queue of an incoming operation */ - grpc_cq_begin_op(cq, call, GRPC_FINISHED); grpc_cq_begin_op(cq, call, GRPC_CLIENT_METADATA_READ); + grpc_cq_begin_op(cq, call, GRPC_FINISHED); - gpr_mu_lock(&call->read_mu); - - /* update state */ - call->cq = cq; - call->state = CALL_STARTED; - call->finished_tag = finished_tag; - - if (call->received_finish) { - /* handle early cancellation */ - grpc_cq_end_client_metadata_read(call->cq, metadata_read_tag, call, NULL, - NULL, 0, NULL); - finish_call(call); - - /* early out.. unlock & return */ - gpr_mu_unlock(&call->read_mu); - return GRPC_CALL_OK; - } - - call->metadata_tag = metadata_read_tag; - - gpr_mu_unlock(&call->read_mu); - - /* call down the filter stack */ - op.type = GRPC_SEND_START; - op.dir = GRPC_CALL_DOWN; - op.flags = flags; - op.done_cb = call_started; - op.data.start.pollset = grpc_cq_pollset(cq); - op.user_data = call; - grpc_call_internal_ref(call); - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); + gpr_mu_lock(&call->mu); + err = bind_cq(call, cq); + if (err != GRPC_CALL_OK) return err; - return GRPC_CALL_OK; + req.op = GRPC_IOREQ_RECV_INITIAL_METADATA; + req.data.recv_metadata = &ls->md_in; + return start_ioreq_and_unlock(call, &req, 1, finish_recv_metadata, + metadata_read_tag); } grpc_call_error grpc_call_server_accept(grpc_call *call, grpc_completion_queue *cq, void *finished_tag) { - /* validate preconditions */ - if (call->is_client) { - gpr_log(GPR_ERROR, "can only call %s on servers", __FUNCTION__); - return GRPC_CALL_ERROR_NOT_ON_CLIENT; - } - - if (call->state >= CALL_BOUNDCQ) { - gpr_log(GPR_ERROR, "call is already accepted"); - return GRPC_CALL_ERROR_ALREADY_ACCEPTED; - } + grpc_ioreq req; /* inform the completion queue of an incoming operation (corresponding to finished_tag) */ grpc_cq_begin_op(cq, call, GRPC_FINISHED); - /* update state */ - gpr_mu_lock(&call->read_mu); - call->state = CALL_BOUNDCQ; - call->cq = cq; - call->finished_tag = finished_tag; - call->received_start = 1; - if (prq_is_empty(&call->prq) && call->received_finish) { - finish_call(call); + bind_cq(call, cq); - /* early out.. unlock & return */ - gpr_mu_unlock(&call->read_mu); - return GRPC_CALL_OK; - } - gpr_mu_unlock(&call->read_mu); - - return GRPC_CALL_OK; + req.op = GRPC_IOREQ_RECV_STATUS; + req.data.recv_status = &get_legacy_state(call)->status_in; + return start_ioreq_and_unlock(call, &req, 1, finish_status, finished_tag); } grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, gpr_uint32 flags) { - grpc_call_element *elem; - grpc_call_op op; - - /* validate preconditions */ - if (call->is_client) { - gpr_log(GPR_ERROR, "can only call %s on servers", __FUNCTION__); - return GRPC_CALL_ERROR_NOT_ON_CLIENT; - } - - if (call->state >= CALL_STARTED) { - gpr_log(GPR_ERROR, "call is already started"); - return GRPC_CALL_ERROR_ALREADY_INVOKED; - } - - if (flags & GRPC_WRITE_NO_COMPRESS) { - return GRPC_CALL_ERROR_INVALID_FLAGS; - } - - /* update state */ - call->state = CALL_STARTED; - - /* call down */ - op.type = GRPC_SEND_START; - op.dir = GRPC_CALL_DOWN; - op.flags = flags; - op.done_cb = do_nothing; - op.data.start.pollset = grpc_cq_pollset(call->cq); - op.user_data = NULL; - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); - return GRPC_CALL_OK; } void grpc_call_client_initial_metadata_complete( grpc_call_element *surface_element) { grpc_call *call = grpc_call_from_top_element(surface_element); - size_t count; - grpc_metadata *elements; - - gpr_mu_lock(&call->read_mu); - count = grpc_metadata_buffer_count(&call->incoming_metadata); - elements = grpc_metadata_buffer_extract_elements(&call->incoming_metadata); - - GPR_ASSERT(!call->received_metadata); - grpc_cq_end_client_metadata_read(call->cq, call->metadata_tag, call, - grpc_metadata_buffer_cleanup_elements, - elements, count, elements); - call->received_metadata = 1; - call->metadata_tag = INVALID_TAG; - gpr_mu_unlock(&call->read_mu); -} - -static void request_more_data(grpc_call *call) { - grpc_call_element *elem; - grpc_call_op op; - - /* call down */ - op.type = GRPC_REQUEST_DATA; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = do_nothing; - op.user_data = NULL; - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); + gpr_mu_lock(&call->mu); + call->got_initial_metadata = 1; + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + gpr_mu_unlock(&call->mu); +} + +static void finish_read(grpc_call *call, grpc_op_error error, void *tag) { + legacy_state *ls; + gpr_mu_lock(&call->mu); + ls = get_legacy_state(call); + if (ls->msg_in.count == 0) { + grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, NULL); + } else { + grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, + ls->msg_in.buffers[ls->msg_in_read_idx++]); + } + gpr_mu_unlock(&call->mu); } grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { - gpr_uint8 request_more = 0; - - switch (call->state) { - case CALL_CREATED: - return GRPC_CALL_ERROR_NOT_INVOKED; - case CALL_BOUNDCQ: - case CALL_STARTED: - break; - case CALL_FINISHED: - return GRPC_CALL_ERROR_ALREADY_FINISHED; - } - - gpr_mu_lock(&call->read_mu); - - if (call->have_read) { - gpr_mu_unlock(&call->read_mu); - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } + legacy_state *ls; + grpc_ioreq req; grpc_cq_begin_op(call->cq, call, GRPC_READ); - if (!prq_pop_to_cq(&call->prq, tag, call, call->cq)) { - if (call->reads_done) { - grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, NULL); - } else { - call->read_tag = tag; - call->have_read = 1; - request_more = call->received_start; - } - } else if (prq_is_empty(&call->prq) && call->received_finish) { - finish_call(call); - } - - gpr_mu_unlock(&call->read_mu); + gpr_mu_lock(&call->mu); + ls = get_legacy_state(call); - if (request_more) { - request_more_data(call); + if (ls->msg_in_read_idx == ls->msg_in.count) { + ls->msg_in_read_idx = 0; + req.op = GRPC_IOREQ_RECV_MESSAGES; + req.data.recv_messages = &ls->msg_in; + return start_ioreq_and_unlock(call, &req, 1, finish_read, tag); } + grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, + ls->msg_in.buffers[ls->msg_in_read_idx++]); + gpr_mu_unlock(&call->mu); return GRPC_CALL_OK; } +static void finish_write(grpc_call *call, grpc_op_error status, void *tag) { + grpc_cq_end_write_accepted(call->cq, tag, call, do_nothing, NULL, status); +} + grpc_call_error grpc_call_start_write(grpc_call *call, grpc_byte_buffer *byte_buffer, void *tag, gpr_uint32 flags) { - grpc_call_element *elem; - grpc_call_op op; - - switch (call->state) { - case CALL_CREATED: - case CALL_BOUNDCQ: - return GRPC_CALL_ERROR_NOT_INVOKED; - case CALL_STARTED: - break; - case CALL_FINISHED: - return GRPC_CALL_ERROR_ALREADY_FINISHED; - } - - if (call->have_write) { - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } + grpc_ioreq req; + legacy_state *ls; grpc_cq_begin_op(call->cq, call, GRPC_WRITE_ACCEPTED); - /* TODO(ctiller): if flags & GRPC_WRITE_BUFFER_HINT == 0, this indicates a - flush, and that flush should be propogated down from here */ - if (byte_buffer == NULL) { - grpc_cq_end_write_accepted(call->cq, tag, call, NULL, NULL, GRPC_OP_OK); - return GRPC_CALL_OK; - } - - call->write_tag = tag; - call->have_write = 1; - - gpr_mu_lock(&call->read_mu); - if (!call->received_start) { - call->pending_write = grpc_byte_buffer_copy(byte_buffer); - call->pending_write_flags = flags; - - gpr_mu_unlock(&call->read_mu); - } else { - gpr_mu_unlock(&call->read_mu); - - op.type = GRPC_SEND_MESSAGE; - op.dir = GRPC_CALL_DOWN; - op.flags = flags; - op.done_cb = done_write; - op.user_data = call; - op.data.message = byte_buffer; - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); - } + gpr_mu_lock(&call->mu); + ls = get_legacy_state(call); + ls->msg_out = byte_buffer; + req.op = GRPC_IOREQ_SEND_MESSAGES; + req.data.send_messages.count = 1; + req.data.send_messages.messages = &ls->msg_out; + return start_ioreq_and_unlock(call, &req, 1, finish_write, tag); +} - return GRPC_CALL_OK; +static void finish_finish(grpc_call *call, grpc_op_error status, void *tag) { + grpc_cq_end_finish_accepted(call->cq, tag, call, do_nothing, NULL, status); } grpc_call_error grpc_call_writes_done(grpc_call *call, void *tag) { - grpc_call_element *elem; - grpc_call_op op; - - if (!call->is_client) { - return GRPC_CALL_ERROR_NOT_ON_SERVER; - } - - switch (call->state) { - case CALL_CREATED: - case CALL_BOUNDCQ: - return GRPC_CALL_ERROR_NOT_INVOKED; - case CALL_FINISHED: - return GRPC_CALL_ERROR_ALREADY_FINISHED; - case CALL_STARTED: - break; - } - - if (call->have_write) { - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } - + grpc_ioreq req; grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); - call->write_tag = tag; - call->have_write = 1; - - gpr_mu_lock(&call->read_mu); - if (!call->received_start) { - call->pending_writes_done = 1; - - gpr_mu_unlock(&call->read_mu); - } else { - gpr_mu_unlock(&call->read_mu); - - op.type = GRPC_SEND_FINISH; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = done_writes_done; - op.user_data = call; - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); - } - - return GRPC_CALL_OK; + gpr_mu_lock(&call->mu); + req.op = GRPC_IOREQ_SEND_CLOSE; + return start_ioreq_and_unlock(call, &req, 1, finish_finish, tag); } grpc_call_error grpc_call_start_write_status(grpc_call *call, grpc_status_code status, const char *details, void *tag) { - grpc_call_element *elem; - grpc_call_op op; + grpc_ioreq req; + grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); - if (call->is_client) { - return GRPC_CALL_ERROR_NOT_ON_CLIENT; - } + gpr_mu_lock(&call->mu); + req.op = GRPC_IOREQ_SEND_CLOSE; + req.data.send_close.status = status; + req.data.send_close.details = details; + return start_ioreq_and_unlock(call, &req, 1, finish_finish, tag); +} - switch (call->state) { - case CALL_CREATED: - case CALL_BOUNDCQ: - return GRPC_CALL_ERROR_NOT_INVOKED; - case CALL_FINISHED: - return GRPC_CALL_ERROR_ALREADY_FINISHED; - case CALL_STARTED: - break; - } +grpc_call *grpc_call_from_top_element(grpc_call_element *elem) { + return CALL_FROM_TOP_ELEM(elem); +} - if (call->have_write) { - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; +static void call_alarm(void *arg, int success) { + grpc_call *call = arg; + if (success) { + if (call->is_client) { + grpc_call_cancel_with_status(call, GRPC_STATUS_DEADLINE_EXCEEDED, + "Deadline Exceeded"); + } else { + grpc_call_cancel(call); + } } + grpc_call_internal_unref(call); +} - elem = CALL_ELEM_FROM_CALL(call, 0); - - if (details && details[0]) { - grpc_mdelem *md = grpc_mdelem_from_strings(call->metadata_context, - "grpc-message", details); +void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); - op.type = GRPC_SEND_METADATA; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = do_nothing; - op.user_data = NULL; - op.data.metadata = md; - elem->filter->call_op(elem, NULL, &op); + if (call->have_alarm) { + gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice"); } + grpc_call_internal_ref(call); + call->have_alarm = 1; + grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); +} - /* always send status */ - { - grpc_mdelem *md; - char buffer[GPR_LTOA_MIN_BUFSIZE]; - gpr_ltoa(status, buffer); - md = - grpc_mdelem_from_strings(call->metadata_context, "grpc-status", buffer); +void grpc_call_read_closed(grpc_call_element *elem) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + gpr_mu_lock(&call->mu); + GPR_ASSERT(!call->read_closed); + call->read_closed = 1; + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); + gpr_mu_unlock(&call->mu); +} - op.type = GRPC_SEND_METADATA; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = do_nothing; - op.user_data = NULL; - op.data.metadata = md; - elem->filter->call_op(elem, NULL, &op); +void grpc_call_stream_closed(grpc_call_element *elem) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + gpr_mu_lock(&call->mu); + if (!call->read_closed) { + call->read_closed = 1; + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); } - - grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); - - call->state = CALL_FINISHED; - call->write_tag = tag; - call->have_write = 1; - - op.type = GRPC_SEND_FINISH; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = done_writes_done; - op.user_data = call; - - elem->filter->call_op(elem, NULL, &op); - - return GRPC_CALL_OK; + call->stream_closed = 1; + finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); + gpr_mu_unlock(&call->mu); } /* we offset status by a small amount when storing it into transport metadata @@ -863,7 +755,7 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { gpr_uint32 status; void *user_data = grpc_mdelem_get_user_data(md, destroy_status); if (user_data) { - status = ((gpr_uint32)(gpr_intptr)user_data) - STATUS_OFFSET; + status = ((gpr_uint32)(gpr_intptr) user_data) - STATUS_OFFSET; } else { if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value), GPR_SLICE_LENGTH(md->value->slice), @@ -876,113 +768,66 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { return status; } -void grpc_call_recv_metadata(grpc_call_element *elem, grpc_call_op *op) { +void grpc_call_recv_message(grpc_call_element *elem, + grpc_byte_buffer *byte_buffer) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); - grpc_mdelem *md = op->data.metadata; - grpc_mdstr *key = md->key; - gpr_log(GPR_DEBUG, "call %p got metadata %s %s", call, - grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value)); - if (key == grpc_channel_get_status_string(call->channel)) { - maybe_set_status_code(call, decode_status(md)); - grpc_mdelem_unref(md); - op->done_cb(op->user_data, GRPC_OP_OK); - } else if (key == grpc_channel_get_message_string(call->channel)) { - maybe_set_status_details(call, md->value); - grpc_mdelem_unref(md); - op->done_cb(op->user_data, GRPC_OP_OK); + grpc_byte_buffer_array *dest; + gpr_mu_lock(&call->mu); + if (call->requests[GRPC_IOREQ_RECV_MESSAGES].master != NULL) { + dest = call->requests[GRPC_IOREQ_RECV_MESSAGES].data.recv_messages; } else { - grpc_metadata_buffer_queue(&call->incoming_metadata, op); + dest = &call->buffered_messages; } -} - -void grpc_call_recv_finish(grpc_call_element *elem, int is_full_close) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); - - gpr_mu_lock(&call->read_mu); - - if (call->have_read) { - grpc_cq_end_read(call->cq, call->read_tag, call, do_nothing, NULL, NULL); - call->read_tag = INVALID_TAG; - call->have_read = 0; + if (dest->count == dest->capacity) { + dest->capacity = GPR_MAX(dest->capacity + 1, dest->capacity * 3 / 2); + dest->buffers = + gpr_realloc(dest->buffers, sizeof(grpc_byte_buffer *) * dest->capacity); } - if (call->is_client && !call->received_metadata && call->cq) { - size_t count; - grpc_metadata *elements; - - call->received_metadata = 1; - - count = grpc_metadata_buffer_count(&call->incoming_metadata); - elements = grpc_metadata_buffer_extract_elements(&call->incoming_metadata); - grpc_cq_end_client_metadata_read(call->cq, call->metadata_tag, call, - grpc_metadata_buffer_cleanup_elements, - elements, count, elements); - } - if (is_full_close) { - if (call->have_alarm) { - grpc_alarm_cancel(&call->alarm); - call->have_alarm = 0; - } - call->received_finish = 1; - if (prq_is_empty(&call->prq) && call->cq != NULL) { - finish_call(call); - } - } else { - call->reads_done = 1; - } - gpr_mu_unlock(&call->read_mu); + dest->buffers[dest->count++] = byte_buffer; + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); + gpr_mu_unlock(&call->mu); } -void grpc_call_recv_message(grpc_call_element *elem, grpc_byte_buffer *message, - void (*on_finish)(void *user_data, - grpc_op_error error), - void *user_data) { +void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); + grpc_mdstr *key = md->key; + grpc_metadata_array *dest; + grpc_metadata *mdusr; - gpr_mu_lock(&call->read_mu); - if (call->have_read) { - grpc_cq_end_read(call->cq, call->read_tag, call, on_finish, user_data, - message); - call->read_tag = INVALID_TAG; - call->have_read = 0; + gpr_mu_lock(&call->mu); + if (key == grpc_channel_get_status_string(call->channel)) { + maybe_set_status_code(call, decode_status(md)); + grpc_mdelem_unref(md); + } else if (key == grpc_channel_get_message_string(call->channel)) { + maybe_set_status_details(call, md->value); + grpc_mdelem_unref(md); } else { - prq_push(&call->prq, message, on_finish, user_data); - } - gpr_mu_unlock(&call->read_mu); -} - -grpc_call *grpc_call_from_top_element(grpc_call_element *elem) { - return CALL_FROM_TOP_ELEM(elem); -} - -grpc_metadata_buffer *grpc_call_get_metadata_buffer(grpc_call *call) { - return &call->incoming_metadata; -} - -static void call_alarm(void *arg, int success) { - grpc_call *call = arg; - if (success) { - if (call->is_client) { - grpc_call_cancel_with_status(call, GRPC_STATUS_DEADLINE_EXCEEDED, - "Deadline Exceeded"); + if (!call->got_initial_metadata) { + dest = IS_LIVE_MASTER( + call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].master) + ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] + .data.recv_metadata + : &call->buffered_initial_metadata; } else { - grpc_call_cancel(call); + dest = IS_LIVE_MASTER( + call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].master) + ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] + .data.recv_metadata + : &call->buffered_trailing_metadata; } + if (dest->count == dest->capacity) { + dest->capacity = GPR_MAX(dest->capacity + 1, dest->capacity * 3 / 2); + dest->metadata = + gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity); + } + mdusr = &dest->metadata[dest->count++]; + mdusr->key = (char *)grpc_mdstr_as_c_string(md->key); + mdusr->value = (char *)grpc_mdstr_as_c_string(md->value); + mdusr->value_length = GPR_SLICE_LENGTH(md->value->slice); } - grpc_call_internal_unref(call); -} - -void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); - - if (call->have_alarm) { - gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice"); - } - grpc_call_internal_ref(call); - call->have_alarm = 1; - grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); + gpr_mu_unlock(&call->mu); } grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) { return CALL_STACK_FROM_CALL(call); } - diff --git a/src/core/surface/call.h b/src/core/surface/call.h index 804b387cb19..2da40607c5f 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -38,6 +38,9 @@ #include "src/core/channel/metadata_buffer.h" #include +typedef void (*grpc_ioreq_completion_func)(grpc_call *call, grpc_op_error status, + void *user_data); + grpc_call *grpc_call_create(grpc_channel *channel, const void *server_transport_data); @@ -47,14 +50,15 @@ void grpc_call_internal_unref(grpc_call *call); /* Helpers for grpc_client, grpc_server filters to publish received data to the completion queue/surface layer */ void grpc_call_recv_metadata(grpc_call_element *surface_element, - grpc_call_op *op); + grpc_mdelem *md); void grpc_call_recv_message( - grpc_call_element *surface_element, grpc_byte_buffer *message, - void (*on_finish)(void *user_data, grpc_op_error error), void *user_data); -void grpc_call_recv_finish(grpc_call_element *surface_element, - int is_full_close); + grpc_call_element *surface_element, grpc_byte_buffer *message); +void grpc_call_read_closed(grpc_call_element *surface_element); +void grpc_call_stream_closed(grpc_call_element *surface_element); void grpc_call_execute_op(grpc_call *call, grpc_call_op *op); +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); /* Called when it's known that the initial batch of metadata is complete on the client side (must not be called on the server) */ @@ -69,9 +73,6 @@ grpc_call_stack *grpc_call_get_call_stack(grpc_call *call); /* Given the top call_element, get the call object. */ grpc_call *grpc_call_from_top_element(grpc_call_element *surface_element); -/* Get the metadata buffer. */ -grpc_metadata_buffer *grpc_call_get_metadata_buffer(grpc_call *call); - void grpc_call_add_mdelem(grpc_call *call, grpc_mdelem *mdelem, gpr_uint32 flags); diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index a1bcea58ddb..d63fb4e141c 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -74,7 +74,7 @@ grpc_channel *grpc_channel_create_from_filters( static void do_nothing(void *ignored, grpc_op_error error) {} -grpc_call *grpc_channel_create_call(grpc_channel *channel, const char *method, +grpc_call *grpc_channel_create_call_old(grpc_channel *channel, const char *method, const char *host, gpr_timespec absolute_deadline) { grpc_call *call; diff --git a/src/core/surface/client.c b/src/core/surface/client.c index a7c9b902ed4..42f46fdaa66 100644 --- a/src/core/surface/client.c +++ b/src/core/surface/client.c @@ -56,20 +56,20 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, grpc_call_next_op(elem, op); break; case GRPC_RECV_METADATA: - grpc_call_recv_metadata(elem, op); + grpc_call_recv_metadata(elem, op->data.metadata); break; case GRPC_RECV_DEADLINE: gpr_log(GPR_ERROR, "Deadline received by client (ignored)"); break; case GRPC_RECV_MESSAGE: - grpc_call_recv_message(elem, op->data.message, op->done_cb, - op->user_data); + grpc_call_recv_message(elem, op->data.message); + op->done_cb(op->user_data, GRPC_OP_OK); break; case GRPC_RECV_HALF_CLOSE: - grpc_call_recv_finish(elem, 0); + grpc_call_read_closed(elem); break; case GRPC_RECV_FINISH: - grpc_call_recv_finish(elem, 1); + grpc_call_stream_closed(elem); break; case GRPC_RECV_END_OF_INITIAL_METADATA: grpc_call_client_initial_metadata_complete(elem); diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c index 2bf31c50a8f..5854afbeefd 100644 --- a/src/core/surface/completion_queue.c +++ b/src/core/surface/completion_queue.c @@ -173,18 +173,6 @@ void grpc_cq_end_read(grpc_completion_queue *cc, void *tag, grpc_call *call, gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } -void grpc_cq_end_invoke_accepted(grpc_completion_queue *cc, void *tag, - grpc_call *call, - grpc_event_finish_func on_finish, - void *user_data, grpc_op_error error) { - event *ev; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); - ev = add_locked(cc, GRPC_INVOKE_ACCEPTED, tag, call, on_finish, user_data); - ev->base.data.invoke_accepted = error; - end_op_locked(cc, GRPC_INVOKE_ACCEPTED); - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); -} - void grpc_cq_end_write_accepted(grpc_completion_queue *cc, void *tag, grpc_call *call, grpc_event_finish_func on_finish, @@ -197,6 +185,17 @@ void grpc_cq_end_write_accepted(grpc_completion_queue *cc, void *tag, gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } +void grpc_cq_end_ioreq(grpc_completion_queue *cc, void *tag, grpc_call *call, + grpc_event_finish_func on_finish, void *user_data, + grpc_op_error error) { + event *ev; + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + ev = add_locked(cc, GRPC_IOREQ, tag, call, on_finish, user_data); + ev->base.data.write_accepted = error; + end_op_locked(cc, GRPC_IOREQ); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); +} + void grpc_cq_end_finish_accepted(grpc_completion_queue *cc, void *tag, grpc_call *call, grpc_event_finish_func on_finish, diff --git a/src/core/surface/completion_queue.h b/src/core/surface/completion_queue.h index 85984075f78..fea8336b633 100644 --- a/src/core/surface/completion_queue.h +++ b/src/core/surface/completion_queue.h @@ -97,6 +97,10 @@ void grpc_cq_end_new_rpc(grpc_completion_queue *cc, void *tag, grpc_call *call, gpr_timespec deadline, size_t metadata_count, grpc_metadata *metadata_elements); +void grpc_cq_end_ioreq(grpc_completion_queue *cc, void *tag, grpc_call *call, + grpc_event_finish_func on_finish, void *user_data, + grpc_op_error error); + void grpc_cq_end_server_shutdown(grpc_completion_queue *cc, void *tag); /* disable polling for some tests */ diff --git a/src/core/surface/event_string.c b/src/core/surface/event_string.c index 8975d312eec..7c76bf93d7c 100644 --- a/src/core/surface/event_string.c +++ b/src/core/surface/event_string.c @@ -87,10 +87,10 @@ char *grpc_event_string(grpc_event *ev) { gpr_strvec_add(&buf, gpr_strdup(" end-of-stream")); } break; - case GRPC_INVOKE_ACCEPTED: - gpr_strvec_add(&buf, gpr_strdup("INVOKE_ACCEPTED: ")); + case GRPC_IOREQ: + gpr_strvec_add(&buf, gpr_strdup("IOREQ: ")); addhdr(&buf, ev); - adderr(&buf, ev->data.invoke_accepted); + adderr(&buf, ev->data.ioreq); break; case GRPC_WRITE_ACCEPTED: gpr_strvec_add(&buf, gpr_strdup("WRITE_ACCEPTED: ")); diff --git a/src/core/surface/lame_client.c b/src/core/surface/lame_client.c index 6098ac78de4..2f5eff55844 100644 --- a/src/core/surface/lame_client.c +++ b/src/core/surface/lame_client.c @@ -50,26 +50,16 @@ typedef struct { grpc_mdelem *message; } channel_data; -static void do_nothing(void *data, grpc_op_error error) {} - static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, grpc_call_op *op) { channel_data *channeld = elem->channel_data; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); switch (op->type) { - case GRPC_SEND_START: { - grpc_call_op set_status_op; - grpc_mdelem_ref(channeld->message); - memset(&set_status_op, 0, sizeof(grpc_call_op)); - set_status_op.dir = GRPC_CALL_UP; - set_status_op.type = GRPC_RECV_METADATA; - set_status_op.done_cb = do_nothing; - set_status_op.data.metadata = channeld->message; - grpc_call_recv_metadata(elem, &set_status_op); - grpc_call_recv_finish(elem, 1); + case GRPC_SEND_START: + grpc_call_recv_metadata(elem, grpc_mdelem_ref(channeld->message)); + grpc_call_stream_closed(elem); break; - } case GRPC_SEND_METADATA: grpc_mdelem_unref(op->data.metadata); break; diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 9a001f4c33d..d46e3de85f0 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -44,6 +44,7 @@ #include "src/core/surface/call.h" #include "src/core/surface/channel.h" #include "src/core/surface/completion_queue.h" +#include "src/core/transport/metadata.h" #include #include #include @@ -63,11 +64,22 @@ typedef struct channel_data channel_data; struct channel_data { grpc_server *server; grpc_channel *channel; + grpc_mdstr *path_key; + grpc_mdstr *authority_key; /* linked list of all channels on a server */ channel_data *next; channel_data *prev; }; +typedef void (*new_call_cb)(grpc_server *server, grpc_completion_queue *cq, grpc_metadata_array *initial_metadata, call_data *calld, void *user_data); + +typedef struct { + void *user_data; + grpc_completion_queue *cq; + grpc_metadata_array *initial_metadata; + new_call_cb cb; +} requested_call; + struct grpc_server { size_t channel_filter_count; const grpc_channel_filter **channel_filters; @@ -76,9 +88,9 @@ struct grpc_server { gpr_mu mu; - void **tags; - size_t ntags; - size_t tag_cap; + requested_call *requested_calls; + size_t requested_call_count; + size_t requested_call_capacity; gpr_uint8 shutdown; gpr_uint8 have_shutdown_tag; @@ -107,11 +119,19 @@ typedef enum { ZOMBIED } call_state; +typedef struct legacy_data { + grpc_metadata_array client_metadata; +} legacy_data; + struct call_data { grpc_call *call; call_state state; gpr_timespec deadline; + grpc_mdstr *path; + grpc_mdstr *host; + + legacy_data *legacy; gpr_uint8 included[CALL_LIST_COUNT]; call_link links[CALL_LIST_COUNT]; @@ -179,7 +199,7 @@ static void server_unref(grpc_server *server) { grpc_channel_args_destroy(server->channel_args); gpr_mu_destroy(&server->mu); gpr_free(server->channel_filters); - gpr_free(server->tags); + gpr_free(server->requested_calls); gpr_free(server); } } @@ -210,62 +230,37 @@ static void destroy_channel(channel_data *chand) { grpc_iomgr_add_callback(finish_destroy_channel, chand); } -static void queue_new_rpc(grpc_server *server, call_data *calld, void *tag) { - grpc_call *call = calld->call; - grpc_metadata_buffer *mdbuf = grpc_call_get_metadata_buffer(call); - size_t count = grpc_metadata_buffer_count(mdbuf); - grpc_metadata *elements = grpc_metadata_buffer_extract_elements(mdbuf); - const char *host = NULL; - const char *method = NULL; - size_t i; - - for (i = 0; i < count; i++) { - if (0 == strcmp(elements[i].key, ":authority")) { - host = elements[i].value; - } else if (0 == strcmp(elements[i].key, ":path")) { - method = elements[i].value; - } - } - - grpc_call_internal_ref(call); - grpc_cq_end_new_rpc(server->cq, tag, call, - grpc_metadata_buffer_cleanup_elements, elements, method, - host, calld->deadline, count, elements); -} - static void start_new_rpc(grpc_call_element *elem) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; grpc_server *server = chand->server; gpr_mu_lock(&server->mu); - if (server->ntags) { + if (server->requested_call_count > 0) { + requested_call rc = server->requested_calls[--server->requested_call_count]; calld->state = ACTIVATED; - queue_new_rpc(server, calld, server->tags[--server->ntags]); + gpr_mu_unlock(&server->mu); + rc.cb(server, rc.cq, rc.initial_metadata, calld, rc.user_data); } else { calld->state = PENDING; call_list_join(server, calld, PENDING_START); + gpr_mu_unlock(&server->mu); } - gpr_mu_unlock(&server->mu); } static void kill_zombie(void *elem, int success) { grpc_call_destroy(grpc_call_from_top_element(elem)); } -static void finish_rpc(grpc_call_element *elem, int is_full_close) { +static void stream_closed(grpc_call_element *elem) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; gpr_mu_lock(&chand->server->mu); switch (calld->state) { case ACTIVATED: - grpc_call_recv_finish(elem, is_full_close); + grpc_call_stream_closed(elem); break; case PENDING: - if (!is_full_close) { - grpc_call_recv_finish(elem, is_full_close); - break; - } call_list_remove(chand->server, calld, PENDING_START); /* fallthrough intended */ case NOT_STARTED: @@ -278,25 +273,56 @@ static void finish_rpc(grpc_call_element *elem, int is_full_close) { gpr_mu_unlock(&chand->server->mu); } +static void read_closed(grpc_call_element *elem) { + call_data *calld = elem->call_data; + channel_data *chand = elem->channel_data; + gpr_mu_lock(&chand->server->mu); + switch (calld->state) { + case ACTIVATED: + case PENDING: + grpc_call_read_closed(elem); + break; + case NOT_STARTED: + calld->state = ZOMBIED; + grpc_iomgr_add_callback(kill_zombie, elem); + break; + case ZOMBIED: + break; + } + gpr_mu_unlock(&chand->server->mu); +} + static void call_op(grpc_call_element *elem, grpc_call_element *from_elemn, grpc_call_op *op) { + channel_data *chand = elem->channel_data; + call_data *calld = elem->call_data; + grpc_mdelem *md; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); switch (op->type) { case GRPC_RECV_METADATA: - grpc_call_recv_metadata(elem, op); + md = op->data.metadata; + if (md->key == chand->path_key) { + calld->path = grpc_mdstr_ref(md->value); + grpc_mdelem_unref(md); + } else if (md->key == chand->authority_key) { + calld->host = grpc_mdstr_ref(md->value); + grpc_mdelem_unref(md); + } else { + grpc_call_recv_metadata(elem, md); + } break; case GRPC_RECV_END_OF_INITIAL_METADATA: start_new_rpc(elem); break; case GRPC_RECV_MESSAGE: - grpc_call_recv_message(elem, op->data.message, op->done_cb, - op->user_data); + grpc_call_recv_message(elem, op->data.message); + op->done_cb(op->user_data, GRPC_OP_OK); break; case GRPC_RECV_HALF_CLOSE: - finish_rpc(elem, 0); + read_closed(elem); break; case GRPC_RECV_FINISH: - finish_rpc(elem, 1); + stream_closed(elem); break; case GRPC_RECV_DEADLINE: grpc_call_set_deadline(elem, op->data.deadline); @@ -395,6 +421,8 @@ static void init_channel_elem(grpc_channel_element *elem, GPR_ASSERT(!is_last); chand->server = NULL; chand->channel = NULL; + chand->path_key = grpc_mdstr_from_string(metadata_context, ":path"); + chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority"); chand->next = chand->prev = chand; } @@ -406,6 +434,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) { chand->prev->next = chand->next; chand->next = chand->prev = chand; gpr_mu_unlock(&chand->server->mu); + grpc_mdstr_unref(chand->path_key); + grpc_mdstr_unref(chand->authority_key); server_unref(chand->server); } } @@ -415,16 +445,6 @@ static const grpc_channel_filter server_surface_filter = { init_call_elem, destroy_call_elem, sizeof(channel_data), init_channel_elem, destroy_channel_elem, "server", }; -static void early_terminate_requested_calls(grpc_completion_queue *cq, - void **tags, size_t ntags) { - size_t i; - - for (i = 0; i < ntags; i++) { - grpc_cq_end_new_rpc(cq, tags[i], NULL, do_nothing, NULL, NULL, NULL, - gpr_inf_past, 0, NULL); - } -} - grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq, grpc_channel_filter **filters, size_t filter_count, @@ -517,8 +537,8 @@ grpc_transport_setup_result grpc_server_setup_transport( void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag, void *shutdown_tag) { listener *l; - void **tags; - size_t ntags; + requested_call *requested_calls; + size_t requested_call_count; channel_data **channels; channel_data *c; size_t nchannels; @@ -547,10 +567,10 @@ void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag, i++; } - tags = server->tags; - ntags = server->ntags; - server->tags = NULL; - server->ntags = 0; + requested_calls = server->requested_calls; + requested_call_count = server->requested_call_count; + server->requested_calls = NULL; + server->requested_call_count = 0; server->shutdown = 1; server->have_shutdown_tag = have_shutdown_tag; @@ -579,8 +599,10 @@ void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag, gpr_free(channels); /* terminate all the requested calls */ - early_terminate_requested_calls(server->cq, tags, ntags); - gpr_free(tags); + for (i = 0; i < requested_call_count; i++) { + requested_calls[i].cb(server, requested_calls[i].cq, requested_calls[i].initial_metadata, NULL, requested_calls[i].user_data); + } + gpr_free(requested_calls); /* Shutdown listeners */ for (l = server->listeners; l; l = l->next) { @@ -625,35 +647,81 @@ void grpc_server_add_listener(grpc_server *server, void *arg, server->listeners = l; } -grpc_call_error grpc_server_request_call(grpc_server *server, void *tag_new) { +static grpc_call_error queue_call_request(grpc_server *server, grpc_completion_queue *cq, grpc_metadata_array *initial_metadata, new_call_cb cb, void *user_data) { call_data *calld; - - grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_RPC_NEW); - + requested_call *rc; gpr_mu_lock(&server->mu); - if (server->shutdown) { gpr_mu_unlock(&server->mu); - early_terminate_requested_calls(server->cq, &tag_new, 1); + cb(server, cq, initial_metadata, NULL, user_data); return GRPC_CALL_OK; } - calld = call_list_remove_head(server, PENDING_START); if (calld) { - GPR_ASSERT(calld->state == PENDING); calld->state = ACTIVATED; - queue_new_rpc(server, calld, tag_new); + GPR_ASSERT(calld->state == PENDING); + gpr_mu_unlock(&server->mu); + cb(server, cq, initial_metadata, calld, user_data); + return GRPC_CALL_OK; } else { - if (server->tag_cap == server->ntags) { - server->tag_cap = GPR_MAX(3 * server->tag_cap / 2, server->tag_cap + 1); - server->tags = - gpr_realloc(server->tags, sizeof(void *) * server->tag_cap); + if (server->requested_call_count == server->requested_call_capacity) { + server->requested_call_capacity = GPR_MAX(server->requested_call_capacity + 8, server->requested_call_capacity * 2); + server->requested_calls = gpr_realloc(server->requested_calls, + sizeof(requested_call) * server->requested_call_capacity); } - server->tags[server->ntags++] = tag_new; + rc = &server->requested_calls[server->requested_call_count++]; + rc->cb = cb; + rc->cq = cq; + rc->user_data = user_data; + rc->initial_metadata = initial_metadata; + gpr_mu_unlock(&server->mu); + return GRPC_CALL_OK; } - gpr_mu_unlock(&server->mu); +} + +static void begin_request(grpc_server *server, grpc_completion_queue *cq, grpc_metadata_array *initial_metadata, call_data *call_data, void *tag) { + abort(); +} + +grpc_call_error grpc_server_request_call( + grpc_server *server, grpc_completion_queue *cq, grpc_call_details *details, + grpc_metadata_array *initial_metadata, void *tag) { + grpc_cq_begin_op(cq, NULL, GRPC_IOREQ); + return queue_call_request(server, cq, initial_metadata, begin_request, tag); +} + +static void publish_legacy_request(grpc_call *call, grpc_op_error status, void *tag) { + grpc_call_element *elem = grpc_call_stack_element(grpc_call_get_call_stack(call), 0); + call_data *calld = elem->call_data; + channel_data *chand = elem->channel_data; + grpc_server *server = chand->server; - return GRPC_CALL_OK; + if (status == GRPC_OP_OK) { + grpc_cq_end_new_rpc(server->cq, tag, call, + do_nothing, NULL, grpc_mdstr_as_c_string(calld->path), + grpc_mdstr_as_c_string(calld->host), calld->deadline, + calld->legacy->client_metadata.count, calld->legacy->client_metadata.metadata); + } +} + +static void begin_legacy_request(grpc_server *server, grpc_completion_queue *cq, grpc_metadata_array *initial_metadata, call_data *calld, void *tag) { + grpc_ioreq req; + if (!calld) { + gpr_free(initial_metadata); + grpc_cq_end_new_rpc(cq, tag, NULL, do_nothing, NULL, NULL, NULL, + gpr_inf_past, 0, NULL); + return; + } + req.op = GRPC_IOREQ_RECV_INITIAL_METADATA; + req.data.recv_metadata = initial_metadata; + grpc_call_start_ioreq_and_call_back(calld->call, &req, 1, publish_legacy_request, tag); +} + +grpc_call_error grpc_server_request_call_old(grpc_server *server, void *tag_new) { + grpc_metadata_array *client_metadata = gpr_malloc(sizeof(grpc_metadata_array)); + memset(client_metadata, 0, sizeof(*client_metadata)); + grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_RPC_NEW); + return queue_call_request(server, server->cq, client_metadata, begin_legacy_request, tag_new); } const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) { diff --git a/src/core/transport/chttp2/stream_encoder.c b/src/core/transport/chttp2/stream_encoder.c index c4e3ca516d1..2af18c30358 100644 --- a/src/core/transport/chttp2/stream_encoder.c +++ b/src/core/transport/chttp2/stream_encoder.c @@ -432,7 +432,7 @@ static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem, static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline, framer_state *st) { - char timeout_str[32]; + char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; grpc_chttp2_encode_timeout(gpr_time_sub(deadline, gpr_now()), timeout_str); hpack_enc(c, grpc_mdelem_from_metadata_strings( c->mdctx, grpc_mdstr_ref(c->timeout_key_str), diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc index c8b2bb2cf6e..19943ab8c63 100644 --- a/src/cpp/client/channel.cc +++ b/src/cpp/client/channel.cc @@ -102,6 +102,7 @@ Status Channel::StartBlockingRpc(const RpcMethod &method, grpc_call *call = grpc_channel_create_call( c_channel_, method.name(), target_.c_str(), context->RawDeadline()); context->set_call(call); + grpc_event *ev; void *finished_tag = reinterpret_cast(call); void *metadata_read_tag = reinterpret_cast(call) + 2; diff --git a/test/core/echo/client.c b/test/core/echo/client.c index 2ad29df53ca..3c789f84f97 100644 --- a/test/core/echo/client.c +++ b/test/core/echo/client.c @@ -78,7 +78,7 @@ int main(int argc, char **argv) { GPR_ASSERT(argc == 2); channel = grpc_channel_create(argv[1], NULL); - call = grpc_channel_create_call(channel, "/foo", "localhost", gpr_inf_future); + call = grpc_channel_create_call_old(channel, "/foo", "localhost", gpr_inf_future); GPR_ASSERT(grpc_call_invoke(call, cq, (void *)1, (void *)1, 0) == GRPC_CALL_OK); diff --git a/test/core/echo/server.c b/test/core/echo/server.c index 6b67334248a..0b9c72162d1 100644 --- a/test/core/echo/server.c +++ b/test/core/echo/server.c @@ -64,7 +64,7 @@ static void request_call(void) { call_state *tag = gpr_malloc(sizeof(*tag)); gpr_ref_init(&tag->pending_ops, 2); tag->bytes_read = 0; - grpc_server_request_call(server, tag); + grpc_server_request_call_old(server, tag); } static void assert_read_ok(call_state *s, grpc_byte_buffer *b) { diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c index 287f83eebca..b5368fffbb8 100644 --- a/test/core/end2end/cq_verifier.c +++ b/test/core/end2end/cq_verifier.c @@ -70,6 +70,7 @@ typedef struct expectation { union { grpc_op_error finish_accepted; grpc_op_error write_accepted; + grpc_op_error ioreq; struct { const char *method; const char *host; @@ -180,9 +181,6 @@ static void verify_matches(expectation *e, grpc_event *ev) { case GRPC_WRITE_ACCEPTED: GPR_ASSERT(e->data.write_accepted == ev->data.write_accepted); break; - case GRPC_INVOKE_ACCEPTED: - abort(); - break; case GRPC_SERVER_RPC_NEW: GPR_ASSERT(string_equivalent(e->data.server_rpc_new.method, ev->data.server_rpc_new.method)); @@ -222,6 +220,9 @@ static void verify_matches(expectation *e, grpc_event *ev) { GPR_ASSERT(ev->data.read == NULL); } break; + case GRPC_IOREQ: + GPR_ASSERT(e->data.ioreq == ev->data.ioreq); + break; case GRPC_SERVER_SHUTDOWN: break; case GRPC_COMPLETION_DO_NOT_USE: @@ -261,8 +262,9 @@ static void expectation_to_strvec(gpr_strvec *buf, expectation *e) { e->data.write_accepted); gpr_strvec_add(buf, tmp); break; - case GRPC_INVOKE_ACCEPTED: - gpr_strvec_add(buf, gpr_strdup("GRPC_INVOKE_ACCEPTED")); + case GRPC_IOREQ: + gpr_asprintf(&tmp, "GRPC_IOREQ result=%d", e->data.ioreq); + gpr_strvec_add(buf, tmp); break; case GRPC_SERVER_RPC_NEW: timeout = gpr_time_sub(e->data.server_rpc_new.deadline, gpr_now()); diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c index 6219f575002..340fa039fd1 100644 --- a/test/core/end2end/dualstack_socket_test.c +++ b/test/core/end2end/dualstack_socket_test.c @@ -112,7 +112,7 @@ void test_connect(const char *server_host, const char *client_host, int port, } /* Send a trivial request. */ - c = grpc_channel_create_call(client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke(c, client_cq, tag(2), tag(3), 0)); @@ -122,7 +122,7 @@ void test_connect(const char *server_host, const char *client_host, int port, cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c index 389a6429c48..e4b4e4bb7d4 100644 --- a/test/core/end2end/no_server_test.c +++ b/test/core/end2end/no_server_test.c @@ -56,7 +56,7 @@ int main(int argc, char **argv) { /* create a call, channel to a non existant server */ chan = grpc_channel_create("nonexistant:54321", NULL); - call = grpc_channel_create_call(chan, "/foo", "nonexistant", deadline); + call = grpc_channel_create_call_old(chan, "/foo", "nonexistant", deadline); GPR_ASSERT(grpc_call_invoke(call, cq, tag(2), tag(3), 0) == GRPC_CALL_OK); /* verify that all tags get completed */ cq_expect_client_metadata_read(cqv, tag(2), NULL); diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c index 33aed98c38c..8db0e3e4087 100644 --- a/test/core/end2end/tests/cancel_after_accept.c +++ b/test/core/end2end/tests/cancel_after_accept.c @@ -113,13 +113,14 @@ static void test_cancel_after_accept(grpc_end2end_test_config config, cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c b/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c index f348488b182..9dbc8dcf790 100644 --- a/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c +++ b/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c @@ -113,13 +113,14 @@ static void test_cancel_after_accept_and_writes_closed( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c index 3bb86723e6e..08b3d69bfd0 100644 --- a/test/core/end2end/tests/cancel_after_invoke.c +++ b/test/core/end2end/tests/cancel_after_invoke.c @@ -111,7 +111,8 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config, gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c index ac816484fd6..7c706029a1c 100644 --- a/test/core/end2end/tests/cancel_before_invoke.c +++ b/test/core/end2end/tests/cancel_before_invoke.c @@ -109,7 +109,8 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config) { gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c)); diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c index e4f9deecd1b..42294fc4bae 100644 --- a/test/core/end2end/tests/cancel_in_a_vacuum.c +++ b/test/core/end2end/tests/cancel_in_a_vacuum.c @@ -109,7 +109,8 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config, gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c)); diff --git a/test/core/end2end/tests/census_simple_request.c b/test/core/end2end/tests/census_simple_request.c index 86cef437be8..1b442e9e4c3 100644 --- a/test/core/end2end/tests/census_simple_request.c +++ b/test/core/end2end/tests/census_simple_request.c @@ -106,7 +106,8 @@ static void test_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); tag(1); GPR_ASSERT(GRPC_CALL_OK == @@ -116,7 +117,7 @@ static void test_body(grpc_end2end_test_fixture f) { cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/disappearing_server.c b/test/core/end2end/tests/disappearing_server.c index 036fdc2501f..eafda6132b5 100644 --- a/test/core/end2end/tests/disappearing_server.c +++ b/test/core/end2end/tests/disappearing_server.c @@ -97,7 +97,8 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f, grpc_call *s; gpr_timespec deadline = five_seconds_time(); - c = grpc_channel_create_call(f->client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f->client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == @@ -107,7 +108,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f, cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f->server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c b/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c index 66e3c44f4b9..2eb56517f7e 100644 --- a/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c +++ b/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c @@ -111,7 +111,8 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == @@ -121,7 +122,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/early_server_shutdown_finishes_tags.c b/test/core/end2end/tests/early_server_shutdown_finishes_tags.c index 88f735c8e0a..123c8bc4153 100644 --- a/test/core/end2end/tests/early_server_shutdown_finishes_tags.c +++ b/test/core/end2end/tests/early_server_shutdown_finishes_tags.c @@ -110,7 +110,7 @@ static void test_early_server_shutdown_finishes_tags( /* upon shutdown, the server should finish all requested calls indicating no new call */ - grpc_server_request_call(f.server, tag(1000)); + grpc_server_request_call_old(f.server, tag(1000)); grpc_server_shutdown(f.server); cq_expect_server_rpc_new(v_server, &s, tag(1000), NULL, NULL, gpr_inf_past, NULL); diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c index d9c9dbb8b20..7ebd8e38b03 100644 --- a/test/core/end2end/tests/graceful_server_shutdown.c +++ b/test/core/end2end/tests/graceful_server_shutdown.c @@ -110,7 +110,8 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == @@ -120,7 +121,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c index f187eceadb3..ac7071a04bd 100644 --- a/test/core/end2end/tests/invoke_large_request.c +++ b/test/core/end2end/tests/invoke_large_request.c @@ -120,9 +120,10 @@ static void test_invoke_large_request(grpc_end2end_test_config config) { /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(request_payload_slice); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c index a177a7b2f29..fc180fd9629 100644 --- a/test/core/end2end/tests/max_concurrent_streams.c +++ b/test/core/end2end/tests/max_concurrent_streams.c @@ -109,7 +109,8 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == @@ -119,7 +120,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); @@ -181,13 +182,14 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { /* start two requests - ensuring that the second is not accepted until the first completes */ deadline = five_seconds_time(); - c1 = - grpc_channel_create_call(f.client, "/alpha", "test.google.com", deadline); + c1 = grpc_channel_create_call_old(f.client, "/alpha", "test.google.com", + deadline); GPR_ASSERT(c1); - c2 = grpc_channel_create_call(f.client, "/beta", "test.google.com", deadline); + c2 = grpc_channel_create_call_old(f.client, "/beta", "test.google.com", + deadline); GPR_ASSERT(c1); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke(c1, f.client_cq, tag(301), tag(302), 0)); @@ -204,7 +206,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { /* The /alpha or /beta calls started above could be invoked (but NOT both); * check this here */ /* We'll get tag 303 or 403, we want 300, 400 */ - live_call = ((int)(gpr_intptr)ev->tag) - 3; + live_call = ((int)(gpr_intptr) ev->tag) - 3; grpc_event_finish(ev); cq_expect_server_rpc_new(v_server, &s1, tag(100), @@ -232,7 +234,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { live_call = (live_call == 300) ? 400 : 300; cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(200))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(200))); cq_expect_server_rpc_new(v_server, &s2, tag(200), live_call == 300 ? "/alpha" : "/beta", "test.google.com", deadline, NULL); diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c index 6768bd8aa9f..e8adb82c19d 100644 --- a/test/core/end2end/tests/ping_pong_streaming.c +++ b/test/core/end2end/tests/ping_pong_streaming.c @@ -118,13 +118,14 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, cq_verifier *v_server = cq_verifier_create(f.server_cq); gpr_log(GPR_INFO, "testing with %d message pairs.", messages); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); diff --git a/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c index 1dd798dc8d6..49720a7bea4 100644 --- a/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c @@ -131,13 +131,14 @@ static void test_request_response_with_metadata_and_payload( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); /* add multiple metadata */ diff --git a/test/core/end2end/tests/request_response_with_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_metadata_and_payload.c index cfc9b61f56f..14e791ae8ee 100644 --- a/test/core/end2end/tests/request_response_with_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_metadata_and_payload.c @@ -122,13 +122,14 @@ static void test_request_response_with_metadata_and_payload( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); /* add multiple metadata */ diff --git a/test/core/end2end/tests/request_response_with_payload.c b/test/core/end2end/tests/request_response_with_payload.c index 32bf5129ff4..ee1e52e54c4 100644 --- a/test/core/end2end/tests/request_response_with_payload.c +++ b/test/core/end2end/tests/request_response_with_payload.c @@ -119,9 +119,10 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) { gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c index 4f1de8b466e..65f890b4b98 100644 --- a/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c @@ -124,13 +124,14 @@ static void test_request_response_with_metadata_and_payload( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); /* add multiple metadata */ diff --git a/test/core/end2end/tests/request_with_large_metadata.c b/test/core/end2end/tests/request_with_large_metadata.c index 83628449a22..438f2ef1d14 100644 --- a/test/core/end2end/tests/request_with_large_metadata.c +++ b/test/core/end2end/tests/request_with_large_metadata.c @@ -113,7 +113,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { cq_verifier *v_server = cq_verifier_create(f.server_cq); const int large_size = 64 * 1024; - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); meta.key = "key"; meta.value = gpr_malloc(large_size + 1); @@ -121,7 +121,8 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { meta.value[large_size] = 0; meta.value_length = large_size; - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); /* add the metadata */ diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c index a3527839659..31d79df5049 100644 --- a/test/core/end2end/tests/request_with_payload.c +++ b/test/core/end2end/tests/request_with_payload.c @@ -116,10 +116,11 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) { /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(payload_slice); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c index 1e15eaa9cc4..1222d167ded 100644 --- a/test/core/end2end/tests/simple_delayed_request.c +++ b/test/core/end2end/tests/simple_delayed_request.c @@ -103,7 +103,8 @@ static void simple_delayed_request_body(grpc_end2end_test_config config, config.init_client(f, client_args); - c = grpc_channel_create_call(f->client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f->client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == @@ -117,7 +118,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config, cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f->server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c index f8894a8ba92..64a8340d54b 100644 --- a/test/core/end2end/tests/simple_request.c +++ b/test/core/end2end/tests/simple_request.c @@ -110,7 +110,8 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == @@ -120,7 +121,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); @@ -156,7 +157,8 @@ static void simple_request_body2(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == @@ -166,7 +168,7 @@ static void simple_request_body2(grpc_end2end_test_fixture f) { cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/thread_stress.c b/test/core/end2end/tests/thread_stress.c index 8fdb765951c..7e235be4f41 100644 --- a/test/core/end2end/tests/thread_stress.c +++ b/test/core/end2end/tests/thread_stress.c @@ -108,7 +108,7 @@ static void drain_cq(int client, grpc_completion_queue *cq) { static void start_request(void) { gpr_slice slice = gpr_slice_malloc(100); grpc_byte_buffer *buf; - grpc_call *call = grpc_channel_create_call( + grpc_call *call = grpc_channel_create_call_old( g_fixture.client, "/Foo", "test.google.com", g_test_end_time); memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice)); @@ -179,7 +179,7 @@ static void client_thread(void *p) { static void request_server_call(void) { gpr_refcount *rc = gpr_malloc(sizeof(gpr_refcount)); gpr_ref_init(rc, 2); - grpc_server_request_call(g_fixture.server, rc); + grpc_server_request_call_old(g_fixture.server, rc); } static void maybe_end_server_call(grpc_call *call, gpr_refcount *rc) { diff --git a/test/core/end2end/tests/writes_done_hangs_with_pending_read.c b/test/core/end2end/tests/writes_done_hangs_with_pending_read.c index eea459459ad..fb2fbdd092b 100644 --- a/test/core/end2end/tests/writes_done_hangs_with_pending_read.c +++ b/test/core/end2end/tests/writes_done_hangs_with_pending_read.c @@ -124,7 +124,8 @@ static void test_writes_done_hangs_with_pending_read( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == @@ -138,7 +139,7 @@ static void test_writes_done_hangs_with_pending_read( cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); diff --git a/test/core/fling/client.c b/test/core/fling/client.c index 7947ffecc5c..e1743c3e7ea 100644 --- a/test/core/fling/client.c +++ b/test/core/fling/client.c @@ -53,7 +53,7 @@ static grpc_call *call; static void init_ping_pong_request(void) {} static void step_ping_pong_request(void) { - call = grpc_channel_create_call(channel, "/Reflector/reflectUnary", + call = grpc_channel_create_call_old(channel, "/Reflector/reflectUnary", "localhost", gpr_inf_future); GPR_ASSERT(grpc_call_invoke(call, cq, (void *)1, (void *)1, GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); @@ -70,7 +70,7 @@ static void step_ping_pong_request(void) { } static void init_ping_pong_stream(void) { - call = grpc_channel_create_call(channel, "/Reflector/reflectStream", + call = grpc_channel_create_call_old(channel, "/Reflector/reflectStream", "localhost", gpr_inf_future); GPR_ASSERT(grpc_call_invoke(call, cq, (void *)1, (void *)1, 0) == GRPC_CALL_OK); diff --git a/test/core/fling/server.c b/test/core/fling/server.c index f811aac284c..e35597fbea2 100644 --- a/test/core/fling/server.c +++ b/test/core/fling/server.c @@ -62,7 +62,7 @@ typedef struct { static void request_call(void) { call_state *s = gpr_malloc(sizeof(call_state)); gpr_ref_init(&s->pending_ops, 2); - grpc_server_request_call(server, s); + grpc_server_request_call_old(server, s); } static void sigint_handler(int x) { got_sigint = 1; } diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c index 71f9cc22916..2928623f6de 100644 --- a/test/core/surface/completion_queue_test.c +++ b/test/core/surface/completion_queue_test.c @@ -105,32 +105,6 @@ static void test_cq_end_read(void) { shutdown_and_destroy(cc); } -static void test_cq_end_invoke_accepted(void) { - grpc_event *ev; - grpc_completion_queue *cc; - int on_finish_called = 0; - void *tag = create_test_tag(); - - LOG_TEST(); - - cc = grpc_completion_queue_create(); - - grpc_cq_begin_op(cc, NULL, GRPC_INVOKE_ACCEPTED); - grpc_cq_end_invoke_accepted(cc, tag, NULL, increment_int_on_finish, - &on_finish_called, GRPC_OP_OK); - - ev = grpc_completion_queue_next(cc, gpr_inf_past); - GPR_ASSERT(ev != NULL); - GPR_ASSERT(ev->type == GRPC_INVOKE_ACCEPTED); - GPR_ASSERT(ev->tag == tag); - GPR_ASSERT(ev->data.invoke_accepted == GRPC_OP_OK); - GPR_ASSERT(on_finish_called == 0); - grpc_event_finish(ev); - GPR_ASSERT(on_finish_called == 1); - - shutdown_and_destroy(cc); -} - static void test_cq_end_write_accepted(void) { grpc_event *ev; grpc_completion_queue *cc; @@ -421,7 +395,6 @@ int main(int argc, char **argv) { test_no_op(); test_wait_empty(); test_cq_end_read(); - test_cq_end_invoke_accepted(); test_cq_end_write_accepted(); test_cq_end_finish_accepted(); test_cq_end_client_metadata_read(); diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index 9b9f0202d6d..c43ac7c2428 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -51,7 +51,7 @@ int main(int argc, char **argv) { chan = grpc_lame_client_channel_create(); GPR_ASSERT(chan); - call = grpc_channel_create_call( + call = grpc_channel_create_call_old( chan, "/Foo", "anywhere", gpr_time_add(gpr_now(), gpr_time_from_seconds(100))); GPR_ASSERT(call); From ee2d702555e01109839ac95f6592f10fb51e1415 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 27 Jan 2015 14:09:59 -0800 Subject: [PATCH 02/93] Add missing finish --- src/core/surface/call.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 6a39d93f057..3362778224f 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -228,6 +228,7 @@ static void finish_finish_step(void *pc, grpc_op_error error) { grpc_call *call = pc; if (error == GRPC_OP_OK) { gpr_mu_lock(&call->mu); + finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_OK); start_next_step_and_unlock(call, call->requests[GRPC_IOREQ_SEND_CLOSE].master); } else { From 62ac155a684194b28aa4b263bc11d1149fe9aedd Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 27 Jan 2015 15:41:44 -0800 Subject: [PATCH 03/93] Initial fixes: we now send a request --- src/core/surface/call.c | 155 +++++++++++++++++++++++-------------- src/core/surface/call.h | 17 ++-- src/core/surface/channel.c | 21 +++-- 3 files changed, 119 insertions(+), 74 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 3362778224f..e0ce4b8cb74 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -50,7 +50,7 @@ typedef struct { size_t md_out_count; size_t md_out_capacity; - grpc_mdelem **md_out; + grpc_metadata *md_out; grpc_byte_buffer *msg_out; /* input buffers */ @@ -203,8 +203,8 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, ? NULL : TOMBSTONE_MASTER; } - master->on_complete(call, status, master->user_data); } + master->on_complete(call, status, master->user_data); } } @@ -237,22 +237,42 @@ static void finish_finish_step(void *pc, grpc_op_error error) { } } +static void finish_start_step(void *pc, grpc_op_error error) { + grpc_call *call = pc; + if (error == GRPC_OP_OK) { + finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_OP_OK); + start_next_step_and_unlock( + call, call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].master); + } else { + gpr_log(GPR_ERROR, "not implemented"); + abort(); + } +} + static void start_next_step_and_unlock(grpc_call *call, reqinfo *master) { reqinfo *requests = call->requests; grpc_byte_buffer *send_message = NULL; size_t i; - gpr_uint32 incomplete = master->need_mask & ~master->complete_mask; + grpc_call_op op; + gpr_uint32 incomplete; gpr_uint8 send_initial_metadata = 0; gpr_uint8 send_trailing_metadata = 0; gpr_uint8 send_blocked = 0; gpr_uint8 send_finished = 0; - gpr_uint8 completed; + + if (!IS_LIVE_MASTER(master)) { + gpr_mu_unlock(&call->mu); + return; + } + + incomplete = master->need_mask & ~master->complete_mask; if (!send_blocked && OP_IN_MASK(GRPC_IOREQ_SEND_INITIAL_METADATA, incomplete)) { send_initial_metadata = 1; finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_OP_OK); master->complete_mask |= 1 << GRPC_IOREQ_SEND_INITIAL_METADATA; + send_blocked = 1; } if (!send_blocked && OP_IN_MASK(GRPC_IOREQ_SEND_MESSAGES, incomplete)) { @@ -262,29 +282,15 @@ static void start_next_step_and_unlock(grpc_call *call, reqinfo *master) { call->write_index++; } - if (!send_blocked && (OP_IN_MASK(GRPC_IOREQ_SEND_CLOSE, incomplete))) { - send_finished = 1; - send_blocked = 1; - } - if (!send_blocked && OP_IN_MASK(GRPC_IOREQ_SEND_TRAILING_METADATA, incomplete)) { send_trailing_metadata = 1; finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); } - completed = !send_blocked && master->complete_mask == master->need_mask; - - if (completed) { - master->on_complete(call, GRPC_OP_OK, master->user_data); - for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { - if (call->requests[i].master == master) { - call->requests[i].master = - (i == GRPC_IOREQ_SEND_MESSAGES || i == GRPC_IOREQ_RECV_MESSAGES) - ? NULL - : TOMBSTONE_MASTER; - } - } + if (!send_blocked && (OP_IN_MASK(GRPC_IOREQ_SEND_CLOSE, incomplete))) { + send_finished = 1; + send_blocked = 1; } gpr_mu_unlock(&call->mu); @@ -299,25 +305,20 @@ static void start_next_step_and_unlock(grpc_call *call, reqinfo *master) { (const gpr_uint8 *)md->value, md->value_length)); } - } - - if (send_message) { - grpc_call_op op; - op.type = GRPC_SEND_MESSAGE; + op.type = GRPC_SEND_START; op.dir = GRPC_CALL_DOWN; op.flags = 0; - op.data.message = send_message; - op.done_cb = finish_write_step; + op.done_cb = finish_start_step; op.user_data = call; grpc_call_execute_op(call, &op); } - if (send_finished) { - grpc_call_op op; - op.type = GRPC_SEND_FINISH; + if (send_message) { + op.type = GRPC_SEND_MESSAGE; op.dir = GRPC_CALL_DOWN; op.flags = 0; - op.done_cb = finish_finish_step; + op.data.message = send_message; + op.done_cb = finish_write_step; op.user_data = call; grpc_call_execute_op(call, &op); } @@ -333,6 +334,16 @@ static void start_next_step_and_unlock(grpc_call *call, reqinfo *master) { md->value_length)); } } + + if (send_finished) { + grpc_call_op op; + op.type = GRPC_SEND_FINISH; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.done_cb = finish_finish_step; + op.user_data = call; + grpc_call_execute_op(call, &op); + } } static grpc_call_error start_ioreq_error(grpc_call *call, @@ -489,9 +500,13 @@ void grpc_call_execute_op(grpc_call *call, grpc_call_op *op) { elem->filter->call_op(elem, NULL, op); } -void grpc_call_add_mdelem(grpc_call *call, grpc_mdelem *mdelem, - gpr_uint32 flags) { - legacy_state *ls = get_legacy_state(call); +grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, + gpr_uint32 flags) { + legacy_state *ls; + grpc_metadata *mdout; + + gpr_mu_lock(&call->mu); + ls = get_legacy_state(call); if (ls->md_out_count == ls->md_out_capacity) { ls->md_out_capacity = @@ -499,16 +514,14 @@ void grpc_call_add_mdelem(grpc_call *call, grpc_mdelem *mdelem, ls->md_out = gpr_realloc(ls->md_out, sizeof(grpc_mdelem *) * ls->md_out_capacity); } - ls->md_out[ls->md_out_count++] = mdelem; -} + mdout = &ls->md_out[ls->md_out_count++]; + mdout->key = gpr_strdup(metadata->key); + mdout->value = gpr_malloc(metadata->value_length); + mdout->value_length = metadata->value_length; + memcpy(mdout->value, metadata->value, metadata->value_length); + + gpr_mu_unlock(&call->mu); -grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, - gpr_uint32 flags) { - grpc_call_add_mdelem( - call, grpc_mdelem_from_string_and_buffer( - call->metadata_context, metadata->key, - (gpr_uint8 *)metadata->value, metadata->value_length), - flags); return GRPC_CALL_OK; } @@ -531,7 +544,6 @@ static void finish_status(grpc_call *call, grpc_op_error status, void *tag) { static void finish_recv_metadata(grpc_call *call, grpc_op_error status, void *tag) { - grpc_ioreq reqs[2]; legacy_state *ls; gpr_mu_lock(&call->mu); @@ -540,24 +552,50 @@ static void finish_recv_metadata(grpc_call *call, grpc_op_error status, grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, ls->md_in.count, ls->md_in.metadata); + } else { + grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, 0, + NULL); + } + gpr_mu_unlock(&call->mu); +} + +static void finish_send_metadata(grpc_call *call, grpc_op_error status, + void *metadata_read_tag) { + grpc_ioreq reqs[2]; + legacy_state *ls; + + if (status == GRPC_OP_OK) { + /* Initially I thought about refactoring so that I could acquire this mutex + only + once, and then I remembered this API surface is deprecated and I moved + on. */ + + gpr_mu_lock(&call->mu); + ls = get_legacy_state(call); + reqs[0].op = GRPC_IOREQ_RECV_INITIAL_METADATA; + reqs[0].data.recv_metadata = &ls->md_in; + GPR_ASSERT(GRPC_CALL_OK == start_ioreq_and_unlock(call, reqs, 1, + finish_recv_metadata, + metadata_read_tag)); + + gpr_mu_lock(&call->mu); + ls = get_legacy_state(call); reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA; reqs[0].data.recv_metadata = &ls->trail_md_in; reqs[1].op = GRPC_IOREQ_RECV_STATUS; reqs[1].data.recv_status = &ls->status_in; - if (GRPC_CALL_OK != start_ioreq_and_unlock(call, reqs, GPR_ARRAY_SIZE(reqs), - finish_status, - ls->finished_tag)) { - grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, - GRPC_STATUS_UNKNOWN, - "Failed to start reading status", NULL, 0); - } + GPR_ASSERT(GRPC_CALL_OK != + start_ioreq_and_unlock(call, reqs, GPR_ARRAY_SIZE(reqs), + finish_status, ls->finished_tag)); } else { - gpr_mu_unlock(&call->mu); - grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, 0, - NULL); + gpr_mu_lock(&call->mu); + ls = get_legacy_state(call); + grpc_cq_end_client_metadata_read(call->cq, metadata_read_tag, call, + do_nothing, NULL, 0, NULL); grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, GRPC_STATUS_UNKNOWN, "Failed to read initial metadata", NULL, 0); + gpr_mu_unlock(&call->mu); } } @@ -575,9 +613,10 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, err = bind_cq(call, cq); if (err != GRPC_CALL_OK) return err; - req.op = GRPC_IOREQ_RECV_INITIAL_METADATA; - req.data.recv_metadata = &ls->md_in; - return start_ioreq_and_unlock(call, &req, 1, finish_recv_metadata, + req.op = GRPC_IOREQ_SEND_INITIAL_METADATA; + req.data.send_metadata.count = ls->md_out_count; + req.data.send_metadata.metadata = ls->md_out; + return start_ioreq_and_unlock(call, &req, 1, finish_send_metadata, metadata_read_tag); } diff --git a/src/core/surface/call.h b/src/core/surface/call.h index 2da40607c5f..10f8dbe6c8f 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -38,8 +38,9 @@ #include "src/core/channel/metadata_buffer.h" #include -typedef void (*grpc_ioreq_completion_func)(grpc_call *call, grpc_op_error status, - void *user_data); +typedef void (*grpc_ioreq_completion_func)(grpc_call *call, + grpc_op_error status, + void *user_data); grpc_call *grpc_call_create(grpc_channel *channel, const void *server_transport_data); @@ -51,14 +52,15 @@ void grpc_call_internal_unref(grpc_call *call); the completion queue/surface layer */ void grpc_call_recv_metadata(grpc_call_element *surface_element, grpc_mdelem *md); -void grpc_call_recv_message( - grpc_call_element *surface_element, grpc_byte_buffer *message); +void grpc_call_recv_message(grpc_call_element *surface_element, + grpc_byte_buffer *message); void grpc_call_read_closed(grpc_call_element *surface_element); void grpc_call_stream_closed(grpc_call_element *surface_element); void grpc_call_execute_op(grpc_call *call, grpc_call_op *op); -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); +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); /* Called when it's known that the initial batch of metadata is complete on the client side (must not be called on the server) */ @@ -73,7 +75,4 @@ grpc_call_stack *grpc_call_get_call_stack(grpc_call *call); /* Given the top call_element, get the call object. */ grpc_call *grpc_call_from_top_element(grpc_call_element *surface_element); -void grpc_call_add_mdelem(grpc_call *call, grpc_mdelem *mdelem, - gpr_uint32 flags); - #endif /* __GRPC_INTERNAL_SURFACE_CALL_H__ */ diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index d63fb4e141c..e47fea431fc 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -51,7 +51,7 @@ struct grpc_channel { grpc_mdstr *authority_string; }; -#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1)) +#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c)+1)) grpc_channel *grpc_channel_create_from_filters( const grpc_channel_filter **filters, size_t num_filters, @@ -74,12 +74,13 @@ grpc_channel *grpc_channel_create_from_filters( static void do_nothing(void *ignored, grpc_op_error error) {} -grpc_call *grpc_channel_create_call_old(grpc_channel *channel, const char *method, - const char *host, - gpr_timespec absolute_deadline) { +grpc_call *grpc_channel_create_call_old(grpc_channel *channel, + const char *method, const char *host, + gpr_timespec absolute_deadline) { grpc_call *call; grpc_mdelem *path_mdelem; grpc_mdelem *authority_mdelem; + grpc_call_op op; if (!channel->is_client) { gpr_log(GPR_ERROR, "Cannot create a call on the server."); @@ -95,16 +96,22 @@ grpc_call *grpc_channel_create_call_old(grpc_channel *channel, const char *metho path_mdelem = grpc_mdelem_from_metadata_strings( channel->metadata_context, channel->path_string, grpc_mdstr_from_string(channel->metadata_context, method)); - grpc_call_add_mdelem(call, path_mdelem, 0); + op.type = GRPC_SEND_METADATA; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.data.metadata = path_mdelem; + op.done_cb = do_nothing; + op.user_data = NULL; + grpc_call_execute_op(call, &op); grpc_mdstr_ref(channel->authority_string); authority_mdelem = grpc_mdelem_from_metadata_strings( channel->metadata_context, channel->authority_string, grpc_mdstr_from_string(channel->metadata_context, host)); - grpc_call_add_mdelem(call, authority_mdelem, 0); + op.data.metadata = authority_mdelem; + grpc_call_execute_op(call, &op); if (0 != gpr_time_cmp(absolute_deadline, gpr_inf_future)) { - grpc_call_op op; op.type = GRPC_SEND_DEADLINE; op.dir = GRPC_CALL_DOWN; op.flags = 0; From 8eb9d471cd68c1a14a76d8b34cbe5859cb00c911 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 27 Jan 2015 17:00:03 -0800 Subject: [PATCH 04/93] Rework call into a chttp2 style transaction system Simplifies locking and cross request chatter significantly --- src/core/surface/call.c | 458 +++++++++++++++++++++++----------------- 1 file changed, 270 insertions(+), 188 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index e0ce4b8cb74..ff0adb8fd3c 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -45,7 +45,7 @@ #include #include -#define INVALID_TAG ((void *)0xdeadbeef) +#define OP_IN_MASK(op, mask) (((1 << (op)) & (mask)) != 0) typedef struct { size_t md_out_count; @@ -63,7 +63,24 @@ typedef struct { void *finished_tag; } legacy_state; +typedef enum { REQ_INITIAL = 0, REQ_READY, REQ_DONE } req_state; + +typedef enum { + SEND_NOTHING, + SEND_INITIAL_METADATA, + SEND_MESSAGE, + SEND_TRAILING_METADATA, + SEND_FINISH +} send_action; + +typedef struct { + grpc_ioreq_completion_func on_complete; + void *user_data; + grpc_op_error status; +} completed_request; + typedef struct reqinfo { + req_state state; grpc_ioreq_data data; struct reqinfo *master; grpc_ioreq_completion_func on_complete; @@ -85,8 +102,11 @@ struct grpc_call { gpr_uint8 read_closed; gpr_uint8 stream_closed; gpr_uint8 got_status_code; + gpr_uint8 sending; + gpr_uint8 num_completed_requests; reqinfo requests[GRPC_IOREQ_OP_COUNT]; + completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; grpc_byte_buffer_array buffered_messages; grpc_metadata_array buffered_initial_metadata; grpc_metadata_array buffered_trailing_metadata; @@ -116,10 +136,9 @@ struct grpc_call { y = temp; \ } while (0) -#define TOMBSTONE_MASTER ((void *)1) -#define IS_LIVE_MASTER(x) ((x) != NULL && (x) != TOMBSTONE_MASTER) - 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, const void *server_transport_data) { @@ -183,166 +202,205 @@ static void request_more_data(grpc_call *call) { grpc_call_execute_op(call, &op); } -#define OP_IN_MASK(op, mask) (((1 << (op)) & (mask)) != 0) +static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); } -static void start_next_step_and_unlock(grpc_call *call, reqinfo *master); +static void unlock(grpc_call *call) { + send_action sa; + completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; + int num_completed_requests = call->num_completed_requests; + int i; + + if (num_completed_requests != 0) { + memcpy(completed_requests, call->completed_requests, + sizeof(completed_requests)); + call->num_completed_requests = 0; + } + + if (!call->sending) { + sa = choose_send_action(call); + if (sa != SEND_NOTHING) { + call->sending = 1; + } + } + + gpr_mu_unlock(&call->mu); + + if (sa != SEND_NOTHING) { + enact_send_action(call, sa); + } + + for (i = 0; i < num_completed_requests; i++) { + completed_requests[i].on_complete(call, completed_requests[i].status, + completed_requests[i].user_data); + } +} static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, grpc_op_error status) { reqinfo *master = call->requests[op].master; + completed_request *cr; size_t i; - if (master == NULL || master == TOMBSTONE_MASTER) { - return; /* inactive */ - } - master->complete_mask |= 1 << op; - if (master->complete_mask == master->need_mask || status == GRPC_OP_ERROR) { - for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { - if (call->requests[i].master == master) { - call->requests[i].master = - (i == GRPC_IOREQ_SEND_MESSAGES || i == GRPC_IOREQ_RECV_MESSAGES) - ? NULL - : TOMBSTONE_MASTER; + switch (call->requests[op].state) { + case REQ_INITIAL: /* not started yet */ + return; + case REQ_DONE: /* already finished */ + abort(); + return; + case REQ_READY: + master->complete_mask |= 1 << op; + call->requests[op].state = + (op == GRPC_IOREQ_SEND_MESSAGES || op == GRPC_IOREQ_RECV_MESSAGES) + ? REQ_INITIAL + : REQ_DONE; + if (master->complete_mask == master->need_mask || + status == GRPC_OP_ERROR) { + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + if (call->requests[i].master == master) { + call->requests[i].master = NULL; + } + } + cr = &call->completed_requests[call->num_completed_requests++]; + cr->status = status; + cr->on_complete = master->on_complete; + cr->user_data = master->user_data; } - } - master->on_complete(call, status, master->user_data); } } static void finish_write_step(void *pc, grpc_op_error error) { grpc_call *call = pc; - gpr_mu_lock(&call->mu); + lock(call); if (error == GRPC_OP_OK) { if (call->write_index == call->requests[GRPC_IOREQ_SEND_MESSAGES].data.send_messages.count) { finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGES, GRPC_OP_OK); } - start_next_step_and_unlock(call, - call->requests[GRPC_IOREQ_SEND_MESSAGES].master); } else { finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGES, GRPC_OP_ERROR); - gpr_mu_unlock(&call->mu); } + call->sending = 0; + unlock(call); } static void finish_finish_step(void *pc, grpc_op_error error) { grpc_call *call = pc; + lock(call); if (error == GRPC_OP_OK) { - gpr_mu_lock(&call->mu); finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_OK); - start_next_step_and_unlock(call, - call->requests[GRPC_IOREQ_SEND_CLOSE].master); } else { gpr_log(GPR_ERROR, "not implemented"); abort(); } + call->sending = 0; + unlock(call); } static void finish_start_step(void *pc, grpc_op_error error) { grpc_call *call = pc; + lock(call); if (error == GRPC_OP_OK) { finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_OP_OK); - start_next_step_and_unlock( - call, call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].master); } else { gpr_log(GPR_ERROR, "not implemented"); abort(); } -} - -static void start_next_step_and_unlock(grpc_call *call, reqinfo *master) { - reqinfo *requests = call->requests; - grpc_byte_buffer *send_message = NULL; - size_t i; + call->sending = 0; + unlock(call); +} + +static send_action choose_send_action(grpc_call *call) { + switch (call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].state) { + case REQ_INITIAL: + return SEND_NOTHING; + case REQ_READY: + return SEND_INITIAL_METADATA; + case REQ_DONE: + break; + } + switch (call->requests[GRPC_IOREQ_SEND_MESSAGES].state) { + case REQ_INITIAL: + return SEND_NOTHING; + case REQ_READY: + return SEND_MESSAGE; + case REQ_DONE: + break; + } + switch (call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].state) { + case REQ_INITIAL: + return SEND_NOTHING; + case REQ_READY: + finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); + return SEND_TRAILING_METADATA; + case REQ_DONE: + break; + } + switch (call->requests[GRPC_IOREQ_SEND_CLOSE].state) { + default: + return SEND_NOTHING; + case REQ_READY: + return SEND_FINISH; + } +} + +static void enact_send_action(grpc_call *call, send_action sa) { + grpc_ioreq_data data; grpc_call_op op; - gpr_uint32 incomplete; - gpr_uint8 send_initial_metadata = 0; - gpr_uint8 send_trailing_metadata = 0; - gpr_uint8 send_blocked = 0; - gpr_uint8 send_finished = 0; - - if (!IS_LIVE_MASTER(master)) { - gpr_mu_unlock(&call->mu); - return; - } - - incomplete = master->need_mask & ~master->complete_mask; - - if (!send_blocked && - OP_IN_MASK(GRPC_IOREQ_SEND_INITIAL_METADATA, incomplete)) { - send_initial_metadata = 1; - finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_OP_OK); - master->complete_mask |= 1 << GRPC_IOREQ_SEND_INITIAL_METADATA; - send_blocked = 1; - } - - if (!send_blocked && OP_IN_MASK(GRPC_IOREQ_SEND_MESSAGES, incomplete)) { - grpc_ioreq_data data = requests[GRPC_IOREQ_SEND_MESSAGES].data; - send_message = data.send_messages.messages[call->write_index]; - send_blocked = 1; - call->write_index++; - } - - if (!send_blocked && - OP_IN_MASK(GRPC_IOREQ_SEND_TRAILING_METADATA, incomplete)) { - send_trailing_metadata = 1; - finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); - } - - if (!send_blocked && (OP_IN_MASK(GRPC_IOREQ_SEND_CLOSE, incomplete))) { - send_finished = 1; - send_blocked = 1; - } - - gpr_mu_unlock(&call->mu); - - if (send_initial_metadata) { - grpc_ioreq_data data = requests[GRPC_IOREQ_SEND_INITIAL_METADATA].data; - for (i = 0; i < data.send_metadata.count; i++) { - const grpc_metadata *md = &data.send_metadata.metadata[i]; - grpc_call_element_send_metadata( - CALL_ELEM_FROM_CALL(call, 0), - grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, - (const gpr_uint8 *)md->value, - md->value_length)); - } - op.type = GRPC_SEND_START; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = finish_start_step; - op.user_data = call; - grpc_call_execute_op(call, &op); - } - - if (send_message) { - op.type = GRPC_SEND_MESSAGE; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.data.message = send_message; - op.done_cb = finish_write_step; - op.user_data = call; - grpc_call_execute_op(call, &op); - } - - if (send_trailing_metadata) { - grpc_ioreq_data data = requests[GRPC_IOREQ_SEND_TRAILING_METADATA].data; - for (i = 0; i < data.send_metadata.count; i++) { - const grpc_metadata *md = &data.send_metadata.metadata[i]; - grpc_call_element_send_metadata( - CALL_ELEM_FROM_CALL(call, 0), - grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, - (const gpr_uint8 *)md->value, - md->value_length)); - } - } - - if (send_finished) { - grpc_call_op op; - op.type = GRPC_SEND_FINISH; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = finish_finish_step; - op.user_data = call; - grpc_call_execute_op(call, &op); + int i; + + switch (sa) { + case SEND_NOTHING: + abort(); + break; + case SEND_INITIAL_METADATA: + data = call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].data; + for (i = 0; i < data.send_metadata.count; i++) { + const grpc_metadata *md = &data.send_metadata.metadata[i]; + grpc_call_element_send_metadata( + CALL_ELEM_FROM_CALL(call, 0), + grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, + (const gpr_uint8 *)md->value, + md->value_length)); + } + op.type = GRPC_SEND_START; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.data.start.pollset = grpc_cq_pollset(call->cq); + op.done_cb = finish_start_step; + op.user_data = call; + grpc_call_execute_op(call, &op); + break; + case SEND_MESSAGE: + data = call->requests[GRPC_IOREQ_SEND_MESSAGES].data; + op.type = GRPC_SEND_MESSAGE; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.data.message = data.send_messages.messages[call->write_index]; + op.done_cb = finish_write_step; + op.user_data = call; + grpc_call_execute_op(call, &op); + break; + case SEND_TRAILING_METADATA: + data = call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].data; + for (i = 0; i < data.send_metadata.count; i++) { + const grpc_metadata *md = &data.send_metadata.metadata[i]; + grpc_call_element_send_metadata( + CALL_ELEM_FROM_CALL(call, 0), + grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, + (const gpr_uint8 *)md->value, + md->value_length)); + } + lock(call); + call->sending = 0; + unlock(call); + break; + case SEND_FINISH: + op.type = GRPC_SEND_FINISH; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.done_cb = finish_finish_step; + op.user_data = call; + grpc_call_execute_op(call, &op); + break; } } @@ -355,13 +413,13 @@ static grpc_call_error start_ioreq_error(grpc_call *call, call->requests[i].master = NULL; } } - gpr_mu_unlock(&call->mu); return ret; } -static grpc_call_error start_ioreq_and_unlock( - grpc_call *call, const grpc_ioreq *reqs, size_t nreqs, - grpc_ioreq_completion_func completion, void *user_data) { +static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, + size_t nreqs, + grpc_ioreq_completion_func completion, + void *user_data) { size_t i; gpr_uint32 have_ops = 0; gpr_uint32 precomplete = 0; @@ -376,6 +434,16 @@ static grpc_call_error start_ioreq_and_unlock( return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_TOO_MANY_OPERATIONS); } + switch (requests[op].state) { + case REQ_INITIAL: + break; + case REQ_READY: + return start_ioreq_error(call, have_ops, + GRPC_CALL_ERROR_TOO_MANY_OPERATIONS); + case REQ_DONE: + return start_ioreq_error(call, have_ops, + GRPC_CALL_ERROR_ALREADY_INVOKED); + } if (master == NULL) { master = &requests[op]; } @@ -391,6 +459,7 @@ static grpc_call_error start_ioreq_and_unlock( SWAP(grpc_byte_buffer_array, *data.recv_messages, call->buffered_messages); precomplete |= 1 << op; + abort(); } break; case GRPC_IOREQ_SEND_MESSAGES: @@ -398,6 +467,7 @@ static grpc_call_error start_ioreq_and_unlock( break; } + requests[op].state = REQ_READY; requests[op].data = data; requests[op].master = master; } @@ -408,8 +478,6 @@ static grpc_call_error start_ioreq_and_unlock( master->on_complete = completion; master->user_data = user_data; - start_next_step_and_unlock(call, master); - if (OP_IN_MASK(GRPC_IOREQ_RECV_MESSAGES, have_ops & ~precomplete)) { request_more_data(call); } @@ -424,15 +492,21 @@ static void call_start_ioreq_done(grpc_call *call, grpc_op_error status, grpc_call_error grpc_call_start_ioreq(grpc_call *call, const grpc_ioreq *reqs, size_t nreqs, void *tag) { - gpr_mu_lock(&call->mu); - return start_ioreq_and_unlock(call, reqs, nreqs, call_start_ioreq_done, 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) { - gpr_mu_lock(&call->mu); - return start_ioreq_and_unlock(call, reqs, nreqs, on_complete, user_data); + grpc_call_error err; + lock(call); + err = start_ioreq(call, reqs, nreqs, on_complete, user_data); + unlock(call); + return err; } void grpc_call_destroy(grpc_call *c) { @@ -505,7 +579,7 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, legacy_state *ls; grpc_metadata *mdout; - gpr_mu_lock(&call->mu); + lock(call); ls = get_legacy_state(call); if (ls->md_out_count == ls->md_out_capacity) { @@ -520,7 +594,7 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, mdout->value_length = metadata->value_length; memcpy(mdout->value, metadata->value, metadata->value_length); - gpr_mu_unlock(&call->mu); + unlock(call); return GRPC_CALL_OK; } @@ -528,9 +602,9 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, static void finish_status(grpc_call *call, grpc_op_error status, void *tag) { legacy_state *ls; - gpr_mu_lock(&call->mu); + lock(call); ls = get_legacy_state(call); - gpr_mu_unlock(&call->mu); + unlock(call); if (status == GRPC_OP_OK) { grpc_cq_end_finished(call->cq, tag, call, do_nothing, NULL, @@ -546,7 +620,7 @@ static void finish_recv_metadata(grpc_call *call, grpc_op_error status, void *tag) { legacy_state *ls; - gpr_mu_lock(&call->mu); + lock(call); ls = get_legacy_state(call); if (status == GRPC_OP_OK) { grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, @@ -556,7 +630,7 @@ static void finish_recv_metadata(grpc_call *call, grpc_op_error status, grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, 0, NULL); } - gpr_mu_unlock(&call->mu); + unlock(call); } static void finish_send_metadata(grpc_call *call, grpc_op_error status, @@ -564,39 +638,30 @@ static void finish_send_metadata(grpc_call *call, grpc_op_error status, grpc_ioreq reqs[2]; legacy_state *ls; + lock(call); if (status == GRPC_OP_OK) { - /* Initially I thought about refactoring so that I could acquire this mutex - only - once, and then I remembered this API surface is deprecated and I moved - on. */ - - gpr_mu_lock(&call->mu); ls = get_legacy_state(call); reqs[0].op = GRPC_IOREQ_RECV_INITIAL_METADATA; reqs[0].data.recv_metadata = &ls->md_in; - GPR_ASSERT(GRPC_CALL_OK == start_ioreq_and_unlock(call, reqs, 1, - finish_recv_metadata, - metadata_read_tag)); + GPR_ASSERT(GRPC_CALL_OK == start_ioreq(call, reqs, 1, finish_recv_metadata, + metadata_read_tag)); - gpr_mu_lock(&call->mu); ls = get_legacy_state(call); reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA; reqs[0].data.recv_metadata = &ls->trail_md_in; reqs[1].op = GRPC_IOREQ_RECV_STATUS; reqs[1].data.recv_status = &ls->status_in; - GPR_ASSERT(GRPC_CALL_OK != - start_ioreq_and_unlock(call, reqs, GPR_ARRAY_SIZE(reqs), - finish_status, ls->finished_tag)); + GPR_ASSERT(GRPC_CALL_OK == + start_ioreq(call, reqs, 2, finish_status, ls->finished_tag)); } else { - gpr_mu_lock(&call->mu); ls = get_legacy_state(call); grpc_cq_end_client_metadata_read(call->cq, metadata_read_tag, call, do_nothing, NULL, 0, NULL); grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, GRPC_STATUS_UNKNOWN, "Failed to read initial metadata", NULL, 0); - gpr_mu_unlock(&call->mu); } + unlock(call); } grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, @@ -609,31 +674,36 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, grpc_cq_begin_op(cq, call, GRPC_CLIENT_METADATA_READ); grpc_cq_begin_op(cq, call, GRPC_FINISHED); - gpr_mu_lock(&call->mu); + lock(call); err = bind_cq(call, cq); if (err != GRPC_CALL_OK) return err; req.op = GRPC_IOREQ_SEND_INITIAL_METADATA; req.data.send_metadata.count = ls->md_out_count; req.data.send_metadata.metadata = ls->md_out; - return start_ioreq_and_unlock(call, &req, 1, finish_send_metadata, - metadata_read_tag); + err = start_ioreq(call, &req, 1, finish_send_metadata, metadata_read_tag); + unlock(call); + return err; } grpc_call_error grpc_call_server_accept(grpc_call *call, grpc_completion_queue *cq, void *finished_tag) { grpc_ioreq req; + grpc_call_error err; /* inform the completion queue of an incoming operation (corresponding to finished_tag) */ grpc_cq_begin_op(cq, call, GRPC_FINISHED); - bind_cq(call, cq); + err = bind_cq(call, cq); + if (err != GRPC_CALL_OK) return err; req.op = GRPC_IOREQ_RECV_STATUS; req.data.recv_status = &get_legacy_state(call)->status_in; - return start_ioreq_and_unlock(call, &req, 1, finish_status, finished_tag); + err = start_ioreq(call, &req, 1, finish_status, finished_tag); + unlock(call); + return err; } grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, @@ -644,15 +714,15 @@ grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, void grpc_call_client_initial_metadata_complete( grpc_call_element *surface_element) { grpc_call *call = grpc_call_from_top_element(surface_element); - gpr_mu_lock(&call->mu); + lock(call); call->got_initial_metadata = 1; finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); - gpr_mu_unlock(&call->mu); + unlock(call); } static void finish_read(grpc_call *call, grpc_op_error error, void *tag) { legacy_state *ls; - gpr_mu_lock(&call->mu); + lock(call); ls = get_legacy_state(call); if (ls->msg_in.count == 0) { grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, NULL); @@ -660,29 +730,31 @@ static void finish_read(grpc_call *call, grpc_op_error error, void *tag) { grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, ls->msg_in.buffers[ls->msg_in_read_idx++]); } - gpr_mu_unlock(&call->mu); + unlock(call); } grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { legacy_state *ls; grpc_ioreq req; + grpc_call_error err; grpc_cq_begin_op(call->cq, call, GRPC_READ); - gpr_mu_lock(&call->mu); + lock(call); ls = get_legacy_state(call); if (ls->msg_in_read_idx == ls->msg_in.count) { ls->msg_in_read_idx = 0; req.op = GRPC_IOREQ_RECV_MESSAGES; req.data.recv_messages = &ls->msg_in; - return start_ioreq_and_unlock(call, &req, 1, finish_read, tag); + err = start_ioreq(call, &req, 1, finish_read, tag); + } else { + err = GRPC_CALL_OK; + grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, + ls->msg_in.buffers[ls->msg_in_read_idx++]); } - - grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, - ls->msg_in.buffers[ls->msg_in_read_idx++]); - gpr_mu_unlock(&call->mu); - return GRPC_CALL_OK; + unlock(call); + return err; } static void finish_write(grpc_call *call, grpc_op_error status, void *tag) { @@ -694,16 +766,20 @@ grpc_call_error grpc_call_start_write(grpc_call *call, gpr_uint32 flags) { grpc_ioreq req; legacy_state *ls; + grpc_call_error err; grpc_cq_begin_op(call->cq, call, GRPC_WRITE_ACCEPTED); - gpr_mu_lock(&call->mu); + lock(call); ls = get_legacy_state(call); ls->msg_out = byte_buffer; req.op = GRPC_IOREQ_SEND_MESSAGES; req.data.send_messages.count = 1; req.data.send_messages.messages = &ls->msg_out; - return start_ioreq_and_unlock(call, &req, 1, finish_write, tag); + err = start_ioreq(call, &req, 1, finish_write, tag); + unlock(call); + + return err; } static void finish_finish(grpc_call *call, grpc_op_error status, void *tag) { @@ -712,24 +788,32 @@ static void finish_finish(grpc_call *call, grpc_op_error status, void *tag) { grpc_call_error grpc_call_writes_done(grpc_call *call, void *tag) { grpc_ioreq req; + grpc_call_error err; grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); - gpr_mu_lock(&call->mu); + lock(call); req.op = GRPC_IOREQ_SEND_CLOSE; - return start_ioreq_and_unlock(call, &req, 1, finish_finish, tag); + err = start_ioreq(call, &req, 1, finish_finish, tag); + unlock(call); + + return err; } grpc_call_error grpc_call_start_write_status(grpc_call *call, grpc_status_code status, const char *details, void *tag) { grpc_ioreq req; + grpc_call_error err; grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); - gpr_mu_lock(&call->mu); + lock(call); req.op = GRPC_IOREQ_SEND_CLOSE; req.data.send_close.status = status; req.data.send_close.details = details; - return start_ioreq_and_unlock(call, &req, 1, finish_finish, tag); + err = start_ioreq(call, &req, 1, finish_finish, tag); + unlock(call); + + return err; } grpc_call *grpc_call_from_top_element(grpc_call_element *elem) { @@ -762,18 +846,18 @@ void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { void grpc_call_read_closed(grpc_call_element *elem) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); - gpr_mu_lock(&call->mu); + lock(call); GPR_ASSERT(!call->read_closed); call->read_closed = 1; finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); - gpr_mu_unlock(&call->mu); + unlock(call); } void grpc_call_stream_closed(grpc_call_element *elem) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); - gpr_mu_lock(&call->mu); + lock(call); if (!call->read_closed) { call->read_closed = 1; finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); @@ -782,7 +866,7 @@ void grpc_call_stream_closed(grpc_call_element *elem) { } call->stream_closed = 1; finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); - gpr_mu_unlock(&call->mu); + unlock(call); } /* we offset status by a small amount when storing it into transport metadata @@ -812,7 +896,7 @@ void grpc_call_recv_message(grpc_call_element *elem, grpc_byte_buffer *byte_buffer) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); grpc_byte_buffer_array *dest; - gpr_mu_lock(&call->mu); + lock(call); if (call->requests[GRPC_IOREQ_RECV_MESSAGES].master != NULL) { dest = call->requests[GRPC_IOREQ_RECV_MESSAGES].data.recv_messages; } else { @@ -825,7 +909,7 @@ void grpc_call_recv_message(grpc_call_element *elem, } dest->buffers[dest->count++] = byte_buffer; finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); - gpr_mu_unlock(&call->mu); + unlock(call); } void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { @@ -834,7 +918,7 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { grpc_metadata_array *dest; grpc_metadata *mdusr; - gpr_mu_lock(&call->mu); + lock(call); if (key == grpc_channel_get_status_string(call->channel)) { maybe_set_status_code(call, decode_status(md)); grpc_mdelem_unref(md); @@ -843,14 +927,12 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { grpc_mdelem_unref(md); } else { if (!call->got_initial_metadata) { - dest = IS_LIVE_MASTER( - call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].master) + dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].state == REQ_READY ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] .data.recv_metadata : &call->buffered_initial_metadata; } else { - dest = IS_LIVE_MASTER( - call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].master) + dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].state == REQ_READY ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] .data.recv_metadata : &call->buffered_trailing_metadata; @@ -865,7 +947,7 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { mdusr->value = (char *)grpc_mdstr_as_c_string(md->value); mdusr->value_length = GPR_SLICE_LENGTH(md->value->slice); } - gpr_mu_unlock(&call->mu); + unlock(call); } grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) { From 9f28ac2cbec23e8a71fda3b35c7b0e9ccc511b86 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 27 Jan 2015 17:01:29 -0800 Subject: [PATCH 05/93] clang-format --- src/core/surface/server.c | 72 +++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/src/core/surface/server.c b/src/core/surface/server.c index d46e3de85f0..bb50419488e 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -71,7 +71,9 @@ struct channel_data { channel_data *prev; }; -typedef void (*new_call_cb)(grpc_server *server, grpc_completion_queue *cq, grpc_metadata_array *initial_metadata, call_data *calld, void *user_data); +typedef void (*new_call_cb)(grpc_server *server, grpc_completion_queue *cq, + grpc_metadata_array *initial_metadata, + call_data *calld, void *user_data); typedef struct { void *user_data; @@ -119,9 +121,7 @@ typedef enum { ZOMBIED } call_state; -typedef struct legacy_data { - grpc_metadata_array client_metadata; -} legacy_data; +typedef struct legacy_data { grpc_metadata_array client_metadata; } legacy_data; struct call_data { grpc_call *call; @@ -443,7 +443,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) { static const grpc_channel_filter server_surface_filter = { call_op, channel_op, sizeof(call_data), init_call_elem, destroy_call_elem, sizeof(channel_data), - init_channel_elem, destroy_channel_elem, "server", }; + init_channel_elem, destroy_channel_elem, "server", +}; grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq, grpc_channel_filter **filters, @@ -600,7 +601,9 @@ void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag, /* terminate all the requested calls */ for (i = 0; i < requested_call_count; i++) { - requested_calls[i].cb(server, requested_calls[i].cq, requested_calls[i].initial_metadata, NULL, requested_calls[i].user_data); + requested_calls[i].cb(server, requested_calls[i].cq, + requested_calls[i].initial_metadata, NULL, + requested_calls[i].user_data); } gpr_free(requested_calls); @@ -647,7 +650,10 @@ void grpc_server_add_listener(grpc_server *server, void *arg, server->listeners = l; } -static grpc_call_error queue_call_request(grpc_server *server, grpc_completion_queue *cq, grpc_metadata_array *initial_metadata, new_call_cb cb, void *user_data) { +static grpc_call_error queue_call_request(grpc_server *server, + grpc_completion_queue *cq, + grpc_metadata_array *initial_metadata, + new_call_cb cb, void *user_data) { call_data *calld; requested_call *rc; gpr_mu_lock(&server->mu); @@ -665,9 +671,12 @@ static grpc_call_error queue_call_request(grpc_server *server, grpc_completion_q return GRPC_CALL_OK; } else { if (server->requested_call_count == server->requested_call_capacity) { - server->requested_call_capacity = GPR_MAX(server->requested_call_capacity + 8, server->requested_call_capacity * 2); - server->requested_calls = gpr_realloc(server->requested_calls, - sizeof(requested_call) * server->requested_call_capacity); + server->requested_call_capacity = + GPR_MAX(server->requested_call_capacity + 8, + server->requested_call_capacity * 2); + server->requested_calls = + gpr_realloc(server->requested_calls, + sizeof(requested_call) * server->requested_call_capacity); } rc = &server->requested_calls[server->requested_call_count++]; rc->cb = cb; @@ -679,32 +688,41 @@ static grpc_call_error queue_call_request(grpc_server *server, grpc_completion_q } } -static void begin_request(grpc_server *server, grpc_completion_queue *cq, grpc_metadata_array *initial_metadata, call_data *call_data, void *tag) { +static void begin_request(grpc_server *server, grpc_completion_queue *cq, + grpc_metadata_array *initial_metadata, + call_data *call_data, void *tag) { abort(); } -grpc_call_error grpc_server_request_call( - grpc_server *server, grpc_completion_queue *cq, grpc_call_details *details, - grpc_metadata_array *initial_metadata, void *tag) { +grpc_call_error grpc_server_request_call(grpc_server *server, + grpc_completion_queue *cq, + grpc_call_details *details, + grpc_metadata_array *initial_metadata, + void *tag) { grpc_cq_begin_op(cq, NULL, GRPC_IOREQ); return queue_call_request(server, cq, initial_metadata, begin_request, tag); } -static void publish_legacy_request(grpc_call *call, grpc_op_error status, void *tag) { - grpc_call_element *elem = grpc_call_stack_element(grpc_call_get_call_stack(call), 0); +static void publish_legacy_request(grpc_call *call, grpc_op_error status, + void *tag) { + grpc_call_element *elem = + grpc_call_stack_element(grpc_call_get_call_stack(call), 0); call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; grpc_server *server = chand->server; if (status == GRPC_OP_OK) { - grpc_cq_end_new_rpc(server->cq, tag, call, - do_nothing, NULL, grpc_mdstr_as_c_string(calld->path), - grpc_mdstr_as_c_string(calld->host), calld->deadline, - calld->legacy->client_metadata.count, calld->legacy->client_metadata.metadata); + grpc_cq_end_new_rpc(server->cq, tag, call, do_nothing, NULL, + grpc_mdstr_as_c_string(calld->path), + grpc_mdstr_as_c_string(calld->host), calld->deadline, + calld->legacy->client_metadata.count, + calld->legacy->client_metadata.metadata); } } -static void begin_legacy_request(grpc_server *server, grpc_completion_queue *cq, grpc_metadata_array *initial_metadata, call_data *calld, void *tag) { +static void begin_legacy_request(grpc_server *server, grpc_completion_queue *cq, + grpc_metadata_array *initial_metadata, + call_data *calld, void *tag) { grpc_ioreq req; if (!calld) { gpr_free(initial_metadata); @@ -714,14 +732,18 @@ static void begin_legacy_request(grpc_server *server, grpc_completion_queue *cq, } req.op = GRPC_IOREQ_RECV_INITIAL_METADATA; req.data.recv_metadata = initial_metadata; - grpc_call_start_ioreq_and_call_back(calld->call, &req, 1, publish_legacy_request, tag); + grpc_call_start_ioreq_and_call_back(calld->call, &req, 1, + publish_legacy_request, tag); } -grpc_call_error grpc_server_request_call_old(grpc_server *server, void *tag_new) { - grpc_metadata_array *client_metadata = gpr_malloc(sizeof(grpc_metadata_array)); +grpc_call_error grpc_server_request_call_old(grpc_server *server, + void *tag_new) { + grpc_metadata_array *client_metadata = + gpr_malloc(sizeof(grpc_metadata_array)); memset(client_metadata, 0, sizeof(*client_metadata)); grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_RPC_NEW); - return queue_call_request(server, server->cq, client_metadata, begin_legacy_request, tag_new); + return queue_call_request(server, server->cq, client_metadata, + begin_legacy_request, tag_new); } const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) { From 23aa6c4320c82c565cfeb3591976e8e4d894da45 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 27 Jan 2015 17:16:12 -0800 Subject: [PATCH 06/93] Progress towards running code --- src/core/surface/call.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index ff0adb8fd3c..419a953e536 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -149,6 +149,9 @@ grpc_call *grpc_call_create(grpc_channel *channel, gpr_mu_init(&call->mu); call->channel = channel; call->is_client = server_transport_data == NULL; + if (call->is_client) { + call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].state = REQ_DONE; + } grpc_channel_internal_ref(channel); call->metadata_context = grpc_channel_get_metadata_context(channel); gpr_ref_init(&call->internal_refcount, 1); @@ -427,6 +430,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, reqinfo *master = NULL; reqinfo *requests = call->requests; grpc_ioreq_data data; + gpr_uint8 have_send_closed = 0; for (i = 0; i < nreqs; i++) { op = reqs[i].op; @@ -465,6 +469,9 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, case GRPC_IOREQ_SEND_MESSAGES: call->write_index = 0; break; + case GRPC_IOREQ_SEND_CLOSE: + have_send_closed = 1; + break; } requests[op].state = REQ_READY; @@ -478,6 +485,12 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, master->on_complete = completion; master->user_data = user_data; + if (have_send_closed) { + if (requests[GRPC_IOREQ_SEND_MESSAGES].state == REQ_INITIAL) { + requests[GRPC_IOREQ_SEND_MESSAGES].state = REQ_DONE; + } + } + if (OP_IN_MASK(GRPC_IOREQ_RECV_MESSAGES, have_ops & ~precomplete)) { request_more_data(call); } From eaa344b59ebef17959452f3fb89c01c5eaa1aabc Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 28 Jan 2015 09:03:50 -0800 Subject: [PATCH 07/93] Allocate required memory --- src/core/surface/server.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/surface/server.c b/src/core/surface/server.c index bb50419488e..fe03369ccc8 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -732,6 +732,8 @@ static void begin_legacy_request(grpc_server *server, grpc_completion_queue *cq, } req.op = GRPC_IOREQ_RECV_INITIAL_METADATA; req.data.recv_metadata = initial_metadata; + calld->legacy = gpr_malloc(sizeof(legacy_data)); + memset(calld->legacy, 0, sizeof(legacy_data)); grpc_call_start_ioreq_and_call_back(calld->call, &req, 1, publish_legacy_request, tag); } From 39fd4283fd52405daffedc7cafcf15c2b0aa904c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 28 Jan 2015 09:12:31 -0800 Subject: [PATCH 08/93] Trigger sending on server side --- src/core/surface/call.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 419a953e536..0c264d3d354 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -719,9 +719,24 @@ grpc_call_error grpc_call_server_accept(grpc_call *call, return err; } +static void finish_send_initial_metadata(grpc_call *call, grpc_op_error status, void *tag) { +} + grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, gpr_uint32 flags) { - return GRPC_CALL_OK; + grpc_ioreq req; + grpc_call_error err; + legacy_state *ls; + + lock(call); + ls = get_legacy_state(call); + req.op = GRPC_IOREQ_SEND_INITIAL_METADATA; + req.data.send_metadata.count = ls->md_out_count; + req.data.send_metadata.metadata = ls->md_out; + err = start_ioreq(call, &req, 1, finish_send_initial_metadata, NULL); + unlock(call); + + return err; } void grpc_call_client_initial_metadata_complete( From f31d14c7175b18067bfe22eda6375299bc5b6c55 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 28 Jan 2015 09:26:42 -0800 Subject: [PATCH 09/93] Send status from server fixes --- src/core/surface/call.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 0c264d3d354..41f0302008d 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -247,7 +247,6 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, case REQ_INITIAL: /* not started yet */ return; case REQ_DONE: /* already finished */ - abort(); return; case REQ_READY: master->complete_mask |= 1 << op; @@ -830,15 +829,18 @@ grpc_call_error grpc_call_writes_done(grpc_call *call, void *tag) { grpc_call_error grpc_call_start_write_status(grpc_call *call, grpc_status_code status, const char *details, void *tag) { - grpc_ioreq req; + grpc_ioreq reqs[2]; grpc_call_error err; grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); lock(call); - req.op = GRPC_IOREQ_SEND_CLOSE; - req.data.send_close.status = status; - req.data.send_close.details = details; - err = start_ioreq(call, &req, 1, finish_finish, tag); + reqs[0].op = GRPC_IOREQ_SEND_TRAILING_METADATA; + reqs[0].data.send_metadata.count = call->legacy_state->md_out_count; + reqs[0].data.send_metadata.metadata = call->legacy_state->md_out; + reqs[1].op = GRPC_IOREQ_SEND_CLOSE; + reqs[1].data.send_close.status = status; + reqs[1].data.send_close.details = details; + err = start_ioreq(call, reqs, 2, finish_finish, tag); unlock(call); return err; From abcf652deac6ae023b704e0c203af83aadfbcf84 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 28 Jan 2015 15:44:24 -0800 Subject: [PATCH 10/93] Make sure to send server status --- src/core/surface/call.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 41f0302008d..2a459f60631 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -122,7 +122,7 @@ struct grpc_call { legacy_state *legacy_state; }; -#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call)+1)) +#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1) #define CALL_ELEM_FROM_CALL(call, idx) \ grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx) @@ -396,6 +396,26 @@ static void enact_send_action(grpc_call *call, send_action sa) { unlock(call); break; case SEND_FINISH: + if (!call->is_client) { + /* TODO(ctiller): cache common status values */ + char status_str[GPR_LTOA_MIN_BUFSIZE]; + gpr_ltoa(data.send_close.status, status_str); + grpc_call_element_send_metadata( + CALL_ELEM_FROM_CALL(call, 0), + grpc_mdelem_from_metadata_strings( + call->metadata_context, + grpc_channel_get_status_string(call->channel), + grpc_mdstr_from_string(call->metadata_context, status_str))); + if (data.send_close.details) { + grpc_call_element_send_metadata( + CALL_ELEM_FROM_CALL(call, 0), + grpc_mdelem_from_metadata_strings( + call->metadata_context, + grpc_channel_get_message_string(call->channel), + grpc_mdstr_from_string(call->metadata_context, + data.send_close.details))); + } + } op.type = GRPC_SEND_FINISH; op.dir = GRPC_CALL_DOWN; op.flags = 0; @@ -718,8 +738,8 @@ grpc_call_error grpc_call_server_accept(grpc_call *call, return err; } -static void finish_send_initial_metadata(grpc_call *call, grpc_op_error status, void *tag) { -} +static void finish_send_initial_metadata(grpc_call *call, grpc_op_error status, + void *tag) {} grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, gpr_uint32 flags) { @@ -734,7 +754,7 @@ grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, req.data.send_metadata.metadata = ls->md_out; err = start_ioreq(call, &req, 1, finish_send_initial_metadata, NULL); unlock(call); - + return err; } @@ -909,7 +929,7 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { gpr_uint32 status; void *user_data = grpc_mdelem_get_user_data(md, destroy_status); if (user_data) { - status = ((gpr_uint32)(gpr_intptr) user_data) - STATUS_OFFSET; + status = ((gpr_uint32)(gpr_intptr)user_data) - STATUS_OFFSET; } else { if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value), GPR_SLICE_LENGTH(md->value->slice), From 9724de88f3be465d9b3e639647f20bb80edcc5b0 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 28 Jan 2015 17:06:29 -0800 Subject: [PATCH 11/93] Send simple request completes its request --- include/grpc/grpc.h | 4 +--- src/core/surface/call.c | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 93deeaab0ae..6a818fcd478 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -247,9 +247,7 @@ typedef struct { typedef struct { grpc_status_code status; - size_t details_length; - size_t details_capacity; - char *details; + const char *details; } grpc_recv_status; typedef struct { diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 2a459f60631..99a8755d6d2 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -179,7 +179,7 @@ void grpc_call_internal_unref(grpc_call *c) { gpr_free(c->legacy_state->md_out); gpr_free(c->legacy_state->md_in.metadata); gpr_free(c->legacy_state->trail_md_in.metadata); - gpr_free(c->legacy_state->status_in.details); + /*gpr_free(c->legacy_state->status_in.details);*/ gpr_free(c->legacy_state); } gpr_free(c); @@ -256,6 +256,10 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, : REQ_DONE; if (master->complete_mask == master->need_mask || status == GRPC_OP_ERROR) { + if (OP_IN_MASK(GRPC_IOREQ_RECV_STATUS, master->need_mask)) { + call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->status = call->status_code; + call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->details = call->status_details? grpc_mdstr_as_c_string(call->status_details) : NULL; + } for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { if (call->requests[i].master == master) { call->requests[i].master = NULL; @@ -399,6 +403,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { if (!call->is_client) { /* TODO(ctiller): cache common status values */ char status_str[GPR_LTOA_MIN_BUFSIZE]; + data = call->requests[GRPC_IOREQ_SEND_CLOSE].data; gpr_ltoa(data.send_close.status, status_str); grpc_call_element_send_metadata( CALL_ELEM_FROM_CALL(call, 0), @@ -543,13 +548,13 @@ grpc_call_error grpc_call_start_ioreq_and_call_back( void grpc_call_destroy(grpc_call *c) { int cancel; - gpr_mu_lock(&c->mu); + lock(c); if (c->have_alarm) { grpc_alarm_cancel(&c->alarm); c->have_alarm = 0; } cancel = !c->stream_closed; - gpr_mu_unlock(&c->mu); + unlock(c); if (cancel) grpc_call_cancel(c); grpc_call_internal_unref(c); } @@ -590,12 +595,12 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *c, grpc_mdstr *details = description ? grpc_mdstr_from_string(c->metadata_context, description) : NULL; - gpr_mu_lock(&c->mu); + lock(c); maybe_set_status_code(c, status); if (details) { maybe_set_status_details(c, details); } - gpr_mu_unlock(&c->mu); + unlock(c); return grpc_call_cancel(c); } @@ -710,6 +715,8 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, err = bind_cq(call, cq); if (err != GRPC_CALL_OK) return err; + get_legacy_state(call)->finished_tag = finished_tag; + req.op = GRPC_IOREQ_SEND_INITIAL_METADATA; req.data.send_metadata.count = ls->md_out_count; req.data.send_metadata.metadata = ls->md_out; From f26370d610af794579f1c2d13166bb74c36d6cc5 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 10:00:11 -0800 Subject: [PATCH 12/93] Formatting --- src/core/surface/call.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 99a8755d6d2..7e1148f6b01 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -122,7 +122,7 @@ struct grpc_call { legacy_state *legacy_state; }; -#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) +#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call)+1)) #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1) #define CALL_ELEM_FROM_CALL(call, idx) \ grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx) @@ -257,8 +257,12 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, if (master->complete_mask == master->need_mask || status == GRPC_OP_ERROR) { if (OP_IN_MASK(GRPC_IOREQ_RECV_STATUS, master->need_mask)) { - call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->status = call->status_code; - call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->details = call->status_details? grpc_mdstr_as_c_string(call->status_details) : NULL; + call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->status = + call->status_code; + call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->details = + call->status_details + ? grpc_mdstr_as_c_string(call->status_details) + : NULL; } for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { if (call->requests[i].master == master) { @@ -936,7 +940,7 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { gpr_uint32 status; void *user_data = grpc_mdelem_get_user_data(md, destroy_status); if (user_data) { - status = ((gpr_uint32)(gpr_intptr)user_data) - STATUS_OFFSET; + status = ((gpr_uint32)(gpr_intptr) user_data) - STATUS_OFFSET; } else { if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value), GPR_SLICE_LENGTH(md->value->slice), From dddbf69d8f07d5ab7a4ddf7d2fdf5e91c031cb61 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 10:25:33 -0800 Subject: [PATCH 13/93] Fix refcount leak on server rpc_new --- src/core/surface/call.c | 14 +++++++++----- src/core/surface/call.h | 4 ++-- src/core/surface/completion_queue.c | 20 ++++++++++++++++++-- src/core/surface/server.c | 3 +++ 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 7e1148f6b01..87bba3ab0c9 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -168,9 +168,13 @@ legacy_state *get_legacy_state(grpc_call *call) { return call->legacy_state; } -void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } +void grpc_call_internal_ref(grpc_call *c, const char *reason) { + gpr_log(GPR_DEBUG, "ref %p %s", c, reason); + gpr_ref(&c->internal_refcount); +} -void grpc_call_internal_unref(grpc_call *c) { +void grpc_call_internal_unref(grpc_call *c, const char *reason) { + gpr_log(GPR_DEBUG, "unref %p %s", c, reason); if (gpr_unref(&c->internal_refcount)) { grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_channel_internal_unref(c->channel); @@ -560,7 +564,7 @@ void grpc_call_destroy(grpc_call *c) { cancel = !c->stream_closed; unlock(c); if (cancel) grpc_call_cancel(c); - grpc_call_internal_unref(c); + grpc_call_internal_unref(c, "destroy"); } static void maybe_set_status_code(grpc_call *call, gpr_uint32 status) { @@ -891,7 +895,7 @@ static void call_alarm(void *arg, int success) { grpc_call_cancel(call); } } - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, "alarm"); } void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { @@ -900,7 +904,7 @@ void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { if (call->have_alarm) { gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice"); } - grpc_call_internal_ref(call); + grpc_call_internal_ref(call, "alarm"); call->have_alarm = 1; grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); } diff --git a/src/core/surface/call.h b/src/core/surface/call.h index 10f8dbe6c8f..6ed6fdf54a2 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -45,8 +45,8 @@ typedef void (*grpc_ioreq_completion_func)(grpc_call *call, grpc_call *grpc_call_create(grpc_channel *channel, const void *server_transport_data); -void grpc_call_internal_ref(grpc_call *call); -void grpc_call_internal_unref(grpc_call *call); +void grpc_call_internal_ref(grpc_call *call, const char *reason); +void grpc_call_internal_unref(grpc_call *call, const char *reason); /* Helpers for grpc_client, grpc_server filters to publish received data to the completion queue/surface layer */ diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c index 5854afbeefd..62008648207 100644 --- a/src/core/surface/completion_queue.c +++ b/src/core/surface/completion_queue.c @@ -132,10 +132,26 @@ static event *add_locked(grpc_completion_queue *cc, grpc_completion_type type, return ev; } +static char *op_string(grpc_completion_type type) { + switch (type) { + case GRPC_QUEUE_SHUTDOWN: return "shutdown"; + case GRPC_IOREQ: return "ioreq"; + case GRPC_WRITE_ACCEPTED: return "write_accepted"; + case GRPC_READ: return "read"; + case GRPC_FINISH_ACCEPTED: return "finish_accepted"; + case GRPC_CLIENT_METADATA_READ: return "client_metadata_read"; + case GRPC_FINISHED: return "finished"; + case GRPC_SERVER_RPC_NEW: return "rpc_new"; + case GRPC_SERVER_SHUTDOWN: return "server_shutdown"; + case GRPC_COMPLETION_DO_NOT_USE: return "do_not_use"; + } + return "unknown"; +} + void grpc_cq_begin_op(grpc_completion_queue *cc, grpc_call *call, grpc_completion_type type) { gpr_ref(&cc->refs); - if (call) grpc_call_internal_ref(call); + if (call) grpc_call_internal_ref(call, op_string(type)); #ifndef NDEBUG gpr_atm_no_barrier_fetch_add(&cc->pending_op_count[type], 1); #endif @@ -388,7 +404,7 @@ void grpc_event_finish(grpc_event *base) { event *ev = (event *)base; ev->on_finish(ev->on_finish_user_data, GRPC_OP_OK); if (ev->base.call) { - grpc_call_internal_unref(ev->base.call); + grpc_call_internal_unref(ev->base.call, op_string(base->type)); } gpr_free(ev); } diff --git a/src/core/surface/server.c b/src/core/surface/server.c index fe03369ccc8..8d31870e27c 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -712,11 +712,14 @@ static void publish_legacy_request(grpc_call *call, grpc_op_error status, grpc_server *server = chand->server; if (status == GRPC_OP_OK) { + grpc_call_internal_ref(call, "rpc_new"); grpc_cq_end_new_rpc(server->cq, tag, call, do_nothing, NULL, grpc_mdstr_as_c_string(calld->path), grpc_mdstr_as_c_string(calld->host), calld->deadline, calld->legacy->client_metadata.count, calld->legacy->client_metadata.metadata); + } else { + abort(); } } From 2f38be65264bc2e99573b753e6e9cfc498a1d2de Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 10:26:22 -0800 Subject: [PATCH 14/93] Fix uninitialized variable --- src/core/surface/call.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 87bba3ab0c9..6ce9c8c0510 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -212,7 +212,7 @@ static void request_more_data(grpc_call *call) { static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); } static void unlock(grpc_call *call) { - send_action sa; + send_action sa = SEND_NOTHING; completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; int num_completed_requests = call->num_completed_requests; int i; From 8884d7f581701eae62f8a9178b5b921ba66f9fa9 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 10:46:45 -0800 Subject: [PATCH 15/93] Small cleanups --- src/core/surface/call.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 6ce9c8c0510..f6001166e68 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -169,12 +169,12 @@ legacy_state *get_legacy_state(grpc_call *call) { } void grpc_call_internal_ref(grpc_call *c, const char *reason) { - gpr_log(GPR_DEBUG, "ref %p %s", c, reason); + gpr_log(GPR_DEBUG, "ref %p %s %d", c, reason, (int)c->internal_refcount.count); gpr_ref(&c->internal_refcount); } void grpc_call_internal_unref(grpc_call *c, const char *reason) { - gpr_log(GPR_DEBUG, "unref %p %s", c, reason); + gpr_log(GPR_DEBUG, "unref %p %s %d", c, reason, (int)c->internal_refcount.count); if (gpr_unref(&c->internal_refcount)) { grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_channel_internal_unref(c->channel); @@ -417,14 +417,14 @@ static void enact_send_action(grpc_call *call, send_action sa) { CALL_ELEM_FROM_CALL(call, 0), grpc_mdelem_from_metadata_strings( call->metadata_context, - grpc_channel_get_status_string(call->channel), + grpc_mdstr_ref(grpc_channel_get_status_string(call->channel)), grpc_mdstr_from_string(call->metadata_context, status_str))); if (data.send_close.details) { grpc_call_element_send_metadata( CALL_ELEM_FROM_CALL(call, 0), grpc_mdelem_from_metadata_strings( call->metadata_context, - grpc_channel_get_message_string(call->channel), + grpc_mdstr_ref(grpc_channel_get_message_string(call->channel)), grpc_mdstr_from_string(call->metadata_context, data.send_close.details))); } @@ -743,6 +743,7 @@ grpc_call_error grpc_call_server_accept(grpc_call *call, finished_tag) */ grpc_cq_begin_op(cq, call, GRPC_FINISHED); + lock(call); err = bind_cq(call, cq); if (err != GRPC_CALL_OK) return err; From f63fed74cbacd4cb6521c617da44f0949926a354 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 10:49:34 -0800 Subject: [PATCH 16/93] Spam cleanup --- src/core/surface/call.c | 12 +++++------- src/core/surface/call.h | 4 ++-- src/core/surface/completion_queue.c | 20 ++------------------ src/core/surface/server.c | 2 +- 4 files changed, 10 insertions(+), 28 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index f6001166e68..3eb0fe528c0 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -168,13 +168,11 @@ legacy_state *get_legacy_state(grpc_call *call) { return call->legacy_state; } -void grpc_call_internal_ref(grpc_call *c, const char *reason) { - gpr_log(GPR_DEBUG, "ref %p %s %d", c, reason, (int)c->internal_refcount.count); +void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } -void grpc_call_internal_unref(grpc_call *c, const char *reason) { - gpr_log(GPR_DEBUG, "unref %p %s %d", c, reason, (int)c->internal_refcount.count); +void grpc_call_internal_unref(grpc_call *c) { if (gpr_unref(&c->internal_refcount)) { grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_channel_internal_unref(c->channel); @@ -564,7 +562,7 @@ void grpc_call_destroy(grpc_call *c) { cancel = !c->stream_closed; unlock(c); if (cancel) grpc_call_cancel(c); - grpc_call_internal_unref(c, "destroy"); + grpc_call_internal_unref(c); } static void maybe_set_status_code(grpc_call *call, gpr_uint32 status) { @@ -896,7 +894,7 @@ static void call_alarm(void *arg, int success) { grpc_call_cancel(call); } } - grpc_call_internal_unref(call, "alarm"); + grpc_call_internal_unref(call); } void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { @@ -905,7 +903,7 @@ void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { if (call->have_alarm) { gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice"); } - grpc_call_internal_ref(call, "alarm"); + grpc_call_internal_ref(call); call->have_alarm = 1; grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); } diff --git a/src/core/surface/call.h b/src/core/surface/call.h index 6ed6fdf54a2..10f8dbe6c8f 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -45,8 +45,8 @@ typedef void (*grpc_ioreq_completion_func)(grpc_call *call, grpc_call *grpc_call_create(grpc_channel *channel, const void *server_transport_data); -void grpc_call_internal_ref(grpc_call *call, const char *reason); -void grpc_call_internal_unref(grpc_call *call, const char *reason); +void grpc_call_internal_ref(grpc_call *call); +void grpc_call_internal_unref(grpc_call *call); /* Helpers for grpc_client, grpc_server filters to publish received data to the completion queue/surface layer */ diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c index 62008648207..5854afbeefd 100644 --- a/src/core/surface/completion_queue.c +++ b/src/core/surface/completion_queue.c @@ -132,26 +132,10 @@ static event *add_locked(grpc_completion_queue *cc, grpc_completion_type type, return ev; } -static char *op_string(grpc_completion_type type) { - switch (type) { - case GRPC_QUEUE_SHUTDOWN: return "shutdown"; - case GRPC_IOREQ: return "ioreq"; - case GRPC_WRITE_ACCEPTED: return "write_accepted"; - case GRPC_READ: return "read"; - case GRPC_FINISH_ACCEPTED: return "finish_accepted"; - case GRPC_CLIENT_METADATA_READ: return "client_metadata_read"; - case GRPC_FINISHED: return "finished"; - case GRPC_SERVER_RPC_NEW: return "rpc_new"; - case GRPC_SERVER_SHUTDOWN: return "server_shutdown"; - case GRPC_COMPLETION_DO_NOT_USE: return "do_not_use"; - } - return "unknown"; -} - void grpc_cq_begin_op(grpc_completion_queue *cc, grpc_call *call, grpc_completion_type type) { gpr_ref(&cc->refs); - if (call) grpc_call_internal_ref(call, op_string(type)); + if (call) grpc_call_internal_ref(call); #ifndef NDEBUG gpr_atm_no_barrier_fetch_add(&cc->pending_op_count[type], 1); #endif @@ -404,7 +388,7 @@ void grpc_event_finish(grpc_event *base) { event *ev = (event *)base; ev->on_finish(ev->on_finish_user_data, GRPC_OP_OK); if (ev->base.call) { - grpc_call_internal_unref(ev->base.call, op_string(base->type)); + grpc_call_internal_unref(ev->base.call); } gpr_free(ev); } diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 8d31870e27c..e0f3766022f 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -712,7 +712,7 @@ static void publish_legacy_request(grpc_call *call, grpc_op_error status, grpc_server *server = chand->server; if (status == GRPC_OP_OK) { - grpc_call_internal_ref(call, "rpc_new"); + grpc_call_internal_ref(call); grpc_cq_end_new_rpc(server->cq, tag, call, do_nothing, NULL, grpc_mdstr_as_c_string(calld->path), grpc_mdstr_as_c_string(calld->host), calld->deadline, From db7db998fb2029b3ac059fc9c3a775d915d8c61d Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 11:19:01 -0800 Subject: [PATCH 17/93] Fix leak --- src/core/surface/server.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/core/surface/server.c b/src/core/surface/server.c index e0f3766022f..6d3aeb51967 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -121,7 +121,7 @@ typedef enum { ZOMBIED } call_state; -typedef struct legacy_data { grpc_metadata_array client_metadata; } legacy_data; +typedef struct legacy_data { grpc_metadata_array *initial_metadata; } legacy_data; struct call_data { grpc_call *call; @@ -397,6 +397,7 @@ static void init_call_elem(grpc_call_element *elem, static void destroy_call_elem(grpc_call_element *elem) { channel_data *chand = elem->channel_data; + call_data *calld = elem->call_data; int i; gpr_mu_lock(&chand->server->mu); @@ -409,6 +410,10 @@ static void destroy_call_elem(grpc_call_element *elem) { } gpr_mu_unlock(&chand->server->mu); + if (calld->legacy) { + gpr_free(calld->legacy); + } + server_unref(chand->server); } @@ -712,12 +717,11 @@ static void publish_legacy_request(grpc_call *call, grpc_op_error status, grpc_server *server = chand->server; if (status == GRPC_OP_OK) { - grpc_call_internal_ref(call); grpc_cq_end_new_rpc(server->cq, tag, call, do_nothing, NULL, grpc_mdstr_as_c_string(calld->path), grpc_mdstr_as_c_string(calld->host), calld->deadline, - calld->legacy->client_metadata.count, - calld->legacy->client_metadata.metadata); + calld->legacy->initial_metadata->count, + calld->legacy->initial_metadata->metadata); } else { abort(); } @@ -737,6 +741,8 @@ static void begin_legacy_request(grpc_server *server, grpc_completion_queue *cq, req.data.recv_metadata = initial_metadata; calld->legacy = gpr_malloc(sizeof(legacy_data)); memset(calld->legacy, 0, sizeof(legacy_data)); + calld->legacy->initial_metadata = initial_metadata; + grpc_call_internal_ref(calld->call); grpc_call_start_ioreq_and_call_back(calld->call, &req, 1, publish_legacy_request, tag); } From 9d96145080ce475d9adee7eaaf264ccba8f203af Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 11:19:58 -0800 Subject: [PATCH 18/93] Fix leak --- src/core/surface/server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 6d3aeb51967..ebdadd5c685 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -411,6 +411,7 @@ static void destroy_call_elem(grpc_call_element *elem) { gpr_mu_unlock(&chand->server->mu); if (calld->legacy) { + gpr_free(calld->legacy->initial_metadata); gpr_free(calld->legacy); } From a4541105a9989a8ab943c68a5aafc94395ed2f0b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 11:46:11 -0800 Subject: [PATCH 19/93] More fixes --- src/core/surface/call.c | 48 +++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 3eb0fe528c0..701a519f26b 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -154,7 +154,9 @@ grpc_call *grpc_call_create(grpc_channel *channel, } grpc_channel_internal_ref(channel); call->metadata_context = grpc_channel_get_metadata_context(channel); - gpr_ref_init(&call->internal_refcount, 1); + /* one ref is dropped in response to destroy, the other in + stream_closed */ + gpr_ref_init(&call->internal_refcount, 2); grpc_call_stack_init(channel_stack, server_transport_data, CALL_STACK_FROM_CALL(call)); return call; @@ -172,19 +174,26 @@ void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } +static void destroy_call(grpc_call *c) { + grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); + grpc_channel_internal_unref(c->channel); + gpr_mu_destroy(&c->mu); + if (c->status_details) { + grpc_mdstr_unref(c->status_details); + } + if (c->legacy_state) { + gpr_free(c->legacy_state->md_out); + gpr_free(c->legacy_state->md_in.metadata); + gpr_free(c->legacy_state->trail_md_in.metadata); + /*gpr_free(c->legacy_state->status_in.details);*/ + gpr_free(c->legacy_state); + } + gpr_free(c); +} + void grpc_call_internal_unref(grpc_call *c) { if (gpr_unref(&c->internal_refcount)) { - grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); - grpc_channel_internal_unref(c->channel); - gpr_mu_destroy(&c->mu); - if (c->legacy_state) { - gpr_free(c->legacy_state->md_out); - gpr_free(c->legacy_state->md_in.metadata); - gpr_free(c->legacy_state->trail_md_in.metadata); - /*gpr_free(c->legacy_state->status_in.details);*/ - gpr_free(c->legacy_state); - } - gpr_free(c); + destroy_call(c); } } @@ -225,6 +234,7 @@ static void unlock(grpc_call *call) { sa = choose_send_action(call); if (sa != SEND_NOTHING) { call->sending = 1; + grpc_call_internal_ref(call); } } @@ -245,6 +255,7 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, reqinfo *master = call->requests[op].master; completed_request *cr; size_t i; + gpr_log(GPR_DEBUG, "finish op %d refs=%d", (int)op, (int)call->internal_refcount.count); switch (call->requests[op].state) { case REQ_INITIAL: /* not started yet */ return; @@ -292,6 +303,7 @@ static void finish_write_step(void *pc, grpc_op_error error) { } call->sending = 0; unlock(call); + grpc_call_internal_unref(call); } static void finish_finish_step(void *pc, grpc_op_error error) { @@ -305,6 +317,7 @@ static void finish_finish_step(void *pc, grpc_op_error error) { } call->sending = 0; unlock(call); + grpc_call_internal_unref(call); } static void finish_start_step(void *pc, grpc_op_error error) { @@ -318,6 +331,7 @@ static void finish_start_step(void *pc, grpc_op_error error) { } call->sending = 0; unlock(call); + grpc_call_internal_unref(call); } static send_action choose_send_action(grpc_call *call) { @@ -404,6 +418,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { lock(call); call->sending = 0; unlock(call); + grpc_call_internal_unref(call); break; case SEND_FINISH: if (!call->is_client) { @@ -819,6 +834,9 @@ grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { } static void finish_write(grpc_call *call, grpc_op_error status, void *tag) { + lock(call); + grpc_byte_buffer_destroy(get_legacy_state(call)->msg_out); + unlock(call); grpc_cq_end_write_accepted(call->cq, tag, call, do_nothing, NULL, status); } @@ -833,7 +851,7 @@ grpc_call_error grpc_call_start_write(grpc_call *call, lock(call); ls = get_legacy_state(call); - ls->msg_out = byte_buffer; + ls->msg_out = grpc_byte_buffer_copy(byte_buffer); req.op = GRPC_IOREQ_SEND_MESSAGES; req.data.send_messages.count = 1; req.data.send_messages.messages = &ls->msg_out; @@ -922,6 +940,7 @@ void grpc_call_read_closed(grpc_call_element *elem) { void grpc_call_stream_closed(grpc_call_element *elem) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); lock(call); + GPR_ASSERT(!call->stream_closed); if (!call->read_closed) { call->read_closed = 1; finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); @@ -931,6 +950,7 @@ void grpc_call_stream_closed(grpc_call_element *elem) { call->stream_closed = 1; finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); unlock(call); + grpc_call_internal_unref(call); } /* we offset status by a small amount when storing it into transport metadata @@ -1002,7 +1022,7 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { : &call->buffered_trailing_metadata; } if (dest->count == dest->capacity) { - dest->capacity = GPR_MAX(dest->capacity + 1, dest->capacity * 3 / 2); + dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2); dest->metadata = gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity); } From a5d4e770fe63d8290b8d4d9af6d4853d4648604c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 11:52:37 -0800 Subject: [PATCH 20/93] Dont skip first call element --- src/core/surface/call.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 701a519f26b..8adb2318ca6 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -368,6 +368,17 @@ static send_action choose_send_action(grpc_call *call) { } } +static void send_metadata(grpc_call *call, grpc_mdelem *elem) { + grpc_call_op op; + op.type = GRPC_SEND_METADATA; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.data.metadata = elem; + op.done_cb = do_nothing; + op.user_data = NULL; + grpc_call_execute_op(call, &op); +} + static void enact_send_action(grpc_call *call, send_action sa) { grpc_ioreq_data data; grpc_call_op op; @@ -381,8 +392,8 @@ static void enact_send_action(grpc_call *call, send_action sa) { data = call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].data; for (i = 0; i < data.send_metadata.count; i++) { const grpc_metadata *md = &data.send_metadata.metadata[i]; - grpc_call_element_send_metadata( - CALL_ELEM_FROM_CALL(call, 0), + send_metadata( + call, grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, (const gpr_uint8 *)md->value, md->value_length)); @@ -409,8 +420,8 @@ static void enact_send_action(grpc_call *call, send_action sa) { data = call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].data; for (i = 0; i < data.send_metadata.count; i++) { const grpc_metadata *md = &data.send_metadata.metadata[i]; - grpc_call_element_send_metadata( - CALL_ELEM_FROM_CALL(call, 0), + send_metadata( + call, grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, (const gpr_uint8 *)md->value, md->value_length)); @@ -426,15 +437,15 @@ static void enact_send_action(grpc_call *call, send_action sa) { char status_str[GPR_LTOA_MIN_BUFSIZE]; data = call->requests[GRPC_IOREQ_SEND_CLOSE].data; gpr_ltoa(data.send_close.status, status_str); - grpc_call_element_send_metadata( - CALL_ELEM_FROM_CALL(call, 0), + send_metadata( + call, grpc_mdelem_from_metadata_strings( call->metadata_context, grpc_mdstr_ref(grpc_channel_get_status_string(call->channel)), grpc_mdstr_from_string(call->metadata_context, status_str))); if (data.send_close.details) { - grpc_call_element_send_metadata( - CALL_ELEM_FROM_CALL(call, 0), + send_metadata( + call, grpc_mdelem_from_metadata_strings( call->metadata_context, grpc_mdstr_ref(grpc_channel_get_message_string(call->channel)), From a991687818c3c5dc941a863501fc432ffb08f52c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 12:02:27 -0800 Subject: [PATCH 21/93] Increment write index --- src/core/surface/call.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 8adb2318ca6..a36193d70be 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -232,6 +232,7 @@ static void unlock(grpc_call *call) { if (!call->sending) { sa = choose_send_action(call); + gpr_log(GPR_DEBUG, "sa=%d", sa); if (sa != SEND_NOTHING) { call->sending = 1; grpc_call_internal_ref(call); @@ -411,7 +412,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { op.type = GRPC_SEND_MESSAGE; op.dir = GRPC_CALL_DOWN; op.flags = 0; - op.data.message = data.send_messages.messages[call->write_index]; + op.data.message = data.send_messages.messages[call->write_index++]; op.done_cb = finish_write_step; op.user_data = call; grpc_call_execute_op(call, &op); From ba7a43fbd1995cce7fbcba710834004ba17781b0 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 12:26:52 -0800 Subject: [PATCH 22/93] Fix uninitialized value, naming --- src/core/channel/channel_stack.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/core/channel/channel_stack.c b/src/core/channel/channel_stack.c index af47df844a9..08cb36bd8b3 100644 --- a/src/core/channel/channel_stack.c +++ b/src/core/channel/channel_stack.c @@ -220,6 +220,7 @@ void grpc_call_element_send_metadata(grpc_call_element *cur_elem, metadata_op.dir = GRPC_CALL_DOWN; metadata_op.done_cb = do_nothing; metadata_op.user_data = NULL; + metadata_op.flags = 0; metadata_op.data.metadata = mdelem; grpc_call_next_op(cur_elem, &metadata_op); } @@ -230,14 +231,16 @@ void grpc_call_element_send_cancel(grpc_call_element *cur_elem) { cancel_op.dir = GRPC_CALL_DOWN; cancel_op.done_cb = do_nothing; cancel_op.user_data = NULL; + cancel_op.flags = 0; grpc_call_next_op(cur_elem, &cancel_op); } void grpc_call_element_send_finish(grpc_call_element *cur_elem) { - grpc_call_op cancel_op; - cancel_op.type = GRPC_SEND_FINISH; - cancel_op.dir = GRPC_CALL_DOWN; - cancel_op.done_cb = do_nothing; - cancel_op.user_data = NULL; - grpc_call_next_op(cur_elem, &cancel_op); + grpc_call_op finish_op; + finish_op.type = GRPC_SEND_FINISH; + finish_op.dir = GRPC_CALL_DOWN; + finish_op.done_cb = do_nothing; + finish_op.user_data = NULL; + finish_op.flags = 0; + grpc_call_next_op(cur_elem, &finish_op); } From 8cfd624c994db528cc462345116ee057898a7fe5 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 12:27:07 -0800 Subject: [PATCH 23/93] Small cleanup --- src/core/surface/channel.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index e47fea431fc..c33ea923e82 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -92,9 +92,8 @@ grpc_call *grpc_channel_create_call_old(grpc_channel *channel, /* Add :path and :authority headers. */ /* TODO(klempner): Consider optimizing this by stashing mdelems for common values of method and host. */ - grpc_mdstr_ref(channel->path_string); path_mdelem = grpc_mdelem_from_metadata_strings( - channel->metadata_context, channel->path_string, + channel->metadata_context, grpc_mdstr_ref(channel->path_string), grpc_mdstr_from_string(channel->metadata_context, method)); op.type = GRPC_SEND_METADATA; op.dir = GRPC_CALL_DOWN; From 3b8599f2e031ce3820869d59b0d048b702b8f0df Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 12:29:52 -0800 Subject: [PATCH 24/93] Fix uninitialized value --- src/core/channel/channel_stack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/channel/channel_stack.c b/src/core/channel/channel_stack.c index 08cb36bd8b3..623ccd1c862 100644 --- a/src/core/channel/channel_stack.c +++ b/src/core/channel/channel_stack.c @@ -209,6 +209,7 @@ void grpc_call_element_recv_metadata(grpc_call_element *cur_elem, metadata_op.dir = GRPC_CALL_UP; metadata_op.done_cb = do_nothing; metadata_op.user_data = NULL; + metadata_op.flags = 0; metadata_op.data.metadata = mdelem; grpc_call_next_op(cur_elem, &metadata_op); } From d0179b4c34e874239a07a86f9e94fac5e27931d9 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 12:32:47 -0800 Subject: [PATCH 25/93] Add missing ref --- src/core/surface/call.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index a36193d70be..4932f20ba18 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -1019,7 +1019,7 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { maybe_set_status_code(call, decode_status(md)); grpc_mdelem_unref(md); } else if (key == grpc_channel_get_message_string(call->channel)) { - maybe_set_status_details(call, md->value); + maybe_set_status_details(call, grpc_mdstr_ref(md->value)); grpc_mdelem_unref(md); } else { if (!call->got_initial_metadata) { From 4069b682b32f576df143ffc2737406db98c562ab Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 14:01:19 -0800 Subject: [PATCH 26/93] Fix server starting --- src/core/surface/call.c | 2 +- src/core/surface/call.h | 5 ++--- src/core/surface/client.c | 2 +- src/core/surface/server.c | 1 + 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 4932f20ba18..cfa77a8fd3a 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -799,7 +799,7 @@ grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, return err; } -void grpc_call_client_initial_metadata_complete( +void grpc_call_initial_metadata_complete( grpc_call_element *surface_element) { grpc_call *call = grpc_call_from_top_element(surface_element); lock(call); diff --git a/src/core/surface/call.h b/src/core/surface/call.h index 10f8dbe6c8f..57592089eef 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -62,9 +62,8 @@ 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); -/* Called when it's known that the initial batch of metadata is complete on the - client side (must not be called on the server) */ -void grpc_call_client_initial_metadata_complete( +/* Called when it's known that the initial batch of metadata is complete */ +void grpc_call_initial_metadata_complete( grpc_call_element *surface_element); void grpc_call_set_deadline(grpc_call_element *surface_element, diff --git a/src/core/surface/client.c b/src/core/surface/client.c index 42f46fdaa66..fa63e855cc8 100644 --- a/src/core/surface/client.c +++ b/src/core/surface/client.c @@ -72,7 +72,7 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, grpc_call_stream_closed(elem); break; case GRPC_RECV_END_OF_INITIAL_METADATA: - grpc_call_client_initial_metadata_complete(elem); + grpc_call_initial_metadata_complete(elem); break; default: GPR_ASSERT(op->dir == GRPC_CALL_DOWN); diff --git a/src/core/surface/server.c b/src/core/surface/server.c index ebdadd5c685..0f21a3aefb6 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -313,6 +313,7 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elemn, break; case GRPC_RECV_END_OF_INITIAL_METADATA: start_new_rpc(elem); + grpc_call_initial_metadata_complete(elem); break; case GRPC_RECV_MESSAGE: grpc_call_recv_message(elem, op->data.message); From 2e10357eba77ad16a0c877c840d6e244098b2a19 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 14:12:07 -0800 Subject: [PATCH 27/93] Fix read path --- src/core/surface/call.c | 55 ++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index cfa77a8fd3a..3726d1f44ca 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -104,6 +104,7 @@ struct grpc_call { gpr_uint8 got_status_code; gpr_uint8 sending; gpr_uint8 num_completed_requests; + gpr_uint8 need_more_data; reqinfo requests[GRPC_IOREQ_OP_COUNT]; completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; @@ -222,8 +223,11 @@ static void unlock(grpc_call *call) { send_action sa = SEND_NOTHING; completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; int num_completed_requests = call->num_completed_requests; + int need_more_data = call->need_more_data; int i; + call->need_more_data = 0; + if (num_completed_requests != 0) { memcpy(completed_requests, call->completed_requests, sizeof(completed_requests)); @@ -241,6 +245,10 @@ static void unlock(grpc_call *call) { gpr_mu_unlock(&call->mu); + if (need_more_data) { + request_more_data(call); + } + if (sa != SEND_NOTHING) { enact_send_action(call, sa); } @@ -487,7 +495,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, reqinfo *master = NULL; reqinfo *requests = call->requests; grpc_ioreq_data data; - gpr_uint8 have_send_closed = 0; for (i = 0; i < nreqs; i++) { op = reqs[i].op; @@ -511,26 +518,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, have_ops |= 1 << op; data = reqs[i].data; - switch (op) { - default: - break; - case GRPC_IOREQ_RECV_MESSAGES: - data.recv_messages->count = 0; - if (call->buffered_messages.count > 0) { - SWAP(grpc_byte_buffer_array, *data.recv_messages, - call->buffered_messages); - precomplete |= 1 << op; - abort(); - } - break; - case GRPC_IOREQ_SEND_MESSAGES: - call->write_index = 0; - break; - case GRPC_IOREQ_SEND_CLOSE: - have_send_closed = 1; - break; - } - requests[op].state = REQ_READY; requests[op].data = data; requests[op].master = master; @@ -542,14 +529,32 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, master->on_complete = completion; master->user_data = user_data; - if (have_send_closed) { - if (requests[GRPC_IOREQ_SEND_MESSAGES].state == REQ_INITIAL) { - requests[GRPC_IOREQ_SEND_MESSAGES].state = REQ_DONE; + for (i = 0; i < nreqs; i++) { + op = reqs[i].op; + switch (op) { + default: + break; + case GRPC_IOREQ_RECV_MESSAGES: + data.recv_messages->count = 0; + if (call->buffered_messages.count > 0) { + SWAP(grpc_byte_buffer_array, *data.recv_messages, + call->buffered_messages); + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); + } + break; + case GRPC_IOREQ_SEND_MESSAGES: + call->write_index = 0; + break; + case GRPC_IOREQ_SEND_CLOSE: + if (requests[GRPC_IOREQ_SEND_MESSAGES].state == REQ_INITIAL) { + requests[GRPC_IOREQ_SEND_MESSAGES].state = REQ_DONE; + } + break; } } if (OP_IN_MASK(GRPC_IOREQ_RECV_MESSAGES, have_ops & ~precomplete)) { - request_more_data(call); + call->need_more_data = 1; } return GRPC_CALL_OK; From 1b40944424a104094cf8c9415cde3a42e547abeb Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 14:36:17 -0800 Subject: [PATCH 28/93] Better check start edge conditions --- src/core/surface/call.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 3726d1f44ca..37b5711795d 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -490,7 +490,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, void *user_data) { size_t i; gpr_uint32 have_ops = 0; - gpr_uint32 precomplete = 0; grpc_ioreq_op op; reqinfo *master = NULL; reqinfo *requests = call->requests; @@ -525,7 +524,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, GPR_ASSERT(master != NULL); master->need_mask = have_ops; - master->complete_mask = precomplete; + master->complete_mask = 0; master->on_complete = completion; master->user_data = user_data; @@ -536,10 +535,12 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, break; case GRPC_IOREQ_RECV_MESSAGES: data.recv_messages->count = 0; - if (call->buffered_messages.count > 0) { + if (call->buffered_messages.count > 0 || call->read_closed) { SWAP(grpc_byte_buffer_array, *data.recv_messages, call->buffered_messages); finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); + } else { + call->need_more_data = 1; } break; case GRPC_IOREQ_SEND_MESSAGES: @@ -550,13 +551,27 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, requests[GRPC_IOREQ_SEND_MESSAGES].state = REQ_DONE; } break; + case GRPC_IOREQ_RECV_INITIAL_METADATA: + data.recv_metadata->count = 0; + if (call->buffered_initial_metadata.count > 0) { + SWAP(grpc_metadata_array, *data.recv_metadata, call->buffered_initial_metadata); + } + if (call->got_initial_metadata) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + } + break; + case GRPC_IOREQ_RECV_TRAILING_METADATA: + data.recv_metadata->count = 0; + if (call->buffered_trailing_metadata.count > 0) { + SWAP(grpc_metadata_array, *data.recv_metadata, call->buffered_trailing_metadata); + } + if (call->read_closed) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); + } + break; } } - if (OP_IN_MASK(GRPC_IOREQ_RECV_MESSAGES, have_ops & ~precomplete)) { - call->need_more_data = 1; - } - return GRPC_CALL_OK; } From fbd96e114852c7850e69cb6e78a28a380021cf7b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 14:37:31 -0800 Subject: [PATCH 29/93] Spam cleanup --- src/core/surface/call.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 37b5711795d..a59f54eb8b8 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -236,7 +236,6 @@ static void unlock(grpc_call *call) { if (!call->sending) { sa = choose_send_action(call); - gpr_log(GPR_DEBUG, "sa=%d", sa); if (sa != SEND_NOTHING) { call->sending = 1; grpc_call_internal_ref(call); @@ -264,7 +263,6 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, reqinfo *master = call->requests[op].master; completed_request *cr; size_t i; - gpr_log(GPR_DEBUG, "finish op %d refs=%d", (int)op, (int)call->internal_refcount.count); switch (call->requests[op].state) { case REQ_INITIAL: /* not started yet */ return; From b4d3eb05204f15ea5d3a2109fae0dd140e3af9d4 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 14:42:10 -0800 Subject: [PATCH 30/93] Remove some silly code --- src/core/surface/call.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index a59f54eb8b8..2011516a777 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -316,12 +316,7 @@ static void finish_write_step(void *pc, grpc_op_error error) { static void finish_finish_step(void *pc, grpc_op_error error) { grpc_call *call = pc; lock(call); - if (error == GRPC_OP_OK) { - finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_OK); - } else { - gpr_log(GPR_ERROR, "not implemented"); - abort(); - } + finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, error); call->sending = 0; unlock(call); grpc_call_internal_unref(call); @@ -330,12 +325,7 @@ static void finish_finish_step(void *pc, grpc_op_error error) { static void finish_start_step(void *pc, grpc_op_error error) { grpc_call *call = pc; lock(call); - if (error == GRPC_OP_OK) { - finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_OP_OK); - } else { - gpr_log(GPR_ERROR, "not implemented"); - abort(); - } + finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, error); call->sending = 0; unlock(call); grpc_call_internal_unref(call); From 6875272b86629e108a527ac2e24e810d878c02c6 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 14:59:54 -0800 Subject: [PATCH 31/93] Robust status overriding --- src/core/surface/call.c | 81 ++++++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 30 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 2011516a777..be624bfe9b0 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -89,6 +89,19 @@ typedef struct reqinfo { gpr_uint32 complete_mask; } reqinfo; +typedef enum { + STATUS_FROM_API_OVERRIDE = 0, + STATUS_FROM_WIRE, + STATUS_FROM_FAILED_OP, + STATUS_SOURCE_COUNT +} status_source; + +typedef struct { + gpr_uint8 set; + grpc_status_code code; + grpc_mdstr *details; +} received_status; + struct grpc_call { grpc_completion_queue *cq; grpc_channel *channel; @@ -113,8 +126,7 @@ struct grpc_call { grpc_metadata_array buffered_trailing_metadata; size_t write_index; - grpc_status_code status_code; - grpc_mdstr *status_details; + received_status status[STATUS_SOURCE_COUNT]; grpc_alarm alarm; @@ -176,11 +188,14 @@ void grpc_call_internal_ref(grpc_call *c) { } static void destroy_call(grpc_call *c) { + int i; grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_channel_internal_unref(c->channel); gpr_mu_destroy(&c->mu); - if (c->status_details) { - grpc_mdstr_unref(c->status_details); + for (i = 0; i < STATUS_SOURCE_COUNT; i++) { + if (c->status[i].details) { + grpc_mdstr_unref(c->status[i].details); + } } if (c->legacy_state) { gpr_free(c->legacy_state->md_out); @@ -198,6 +213,18 @@ void grpc_call_internal_unref(grpc_call *c) { } } +static void set_status_code(grpc_call *call, status_source source, gpr_uint32 status) { + call->status[source].set = 1; + call->status[source].code = status; +} + +static void set_status_details(grpc_call *call, status_source source, grpc_mdstr *status) { + if (call->status[source].details != NULL) { + grpc_mdstr_unref(call->status[source].details); + } + call->status[source].details = status; +} + static grpc_call_error bind_cq(grpc_call *call, grpc_completion_queue *cq) { if (call->cq) return GRPC_CALL_ERROR_ALREADY_INVOKED; call->cq = cq; @@ -258,6 +285,19 @@ static void unlock(grpc_call *call) { } } +static void get_final_status(grpc_call *call, grpc_status_code *code, const char **details) { + int i; + for (i = 0; i < STATUS_SOURCE_COUNT; i++) { + if (call->status[i].set) { + *code = call->status[i].code; + *details = grpc_mdstr_as_c_string(call->status[i].details); + return; + } + } + *code = GRPC_STATUS_UNKNOWN; + *details = NULL; +} + static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, grpc_op_error status) { reqinfo *master = call->requests[op].master; @@ -277,12 +317,9 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, if (master->complete_mask == master->need_mask || status == GRPC_OP_ERROR) { if (OP_IN_MASK(GRPC_IOREQ_RECV_STATUS, master->need_mask)) { - call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->status = - call->status_code; - call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->details = - call->status_details - ? grpc_mdstr_as_c_string(call->status_details) - : NULL; + get_final_status(call, + &call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->status, + &call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->details); } for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { if (call->requests[i].master == master) { @@ -600,20 +637,6 @@ void grpc_call_destroy(grpc_call *c) { grpc_call_internal_unref(c); } -static void maybe_set_status_code(grpc_call *call, gpr_uint32 status) { - if (call->got_status_code) return; - call->status_code = status; - call->got_status_code = 1; -} - -static void maybe_set_status_details(grpc_call *call, grpc_mdstr *status) { - if (call->status_details != NULL) { - grpc_mdstr_unref(status); - return; - } - call->status_details = status; -} - grpc_call_error grpc_call_cancel(grpc_call *c) { grpc_call_element *elem; grpc_call_op op; @@ -637,10 +660,8 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *c, description ? grpc_mdstr_from_string(c->metadata_context, description) : NULL; lock(c); - maybe_set_status_code(c, status); - if (details) { - maybe_set_status_details(c, details); - } + set_status_code(c, STATUS_FROM_API_OVERRIDE, status); + set_status_details(c, STATUS_FROM_API_OVERRIDE, details); unlock(c); return grpc_call_cancel(c); } @@ -1024,10 +1045,10 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { lock(call); if (key == grpc_channel_get_status_string(call->channel)) { - maybe_set_status_code(call, decode_status(md)); + set_status_code(call, STATUS_FROM_WIRE, decode_status(md)); grpc_mdelem_unref(md); } else if (key == grpc_channel_get_message_string(call->channel)) { - maybe_set_status_details(call, grpc_mdstr_ref(md->value)); + set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value)); grpc_mdelem_unref(md); } else { if (!call->got_initial_metadata) { From 928fbc8ed0588f016fa2dd71517f532b25d6eb3c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 15:06:42 -0800 Subject: [PATCH 32/93] Robust status overriding --- src/core/surface/call.c | 154 ++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 71 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index be624bfe9b0..6a1fa361de6 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -183,9 +183,7 @@ legacy_state *get_legacy_state(grpc_call *call) { return call->legacy_state; } -void grpc_call_internal_ref(grpc_call *c) { - gpr_ref(&c->internal_refcount); -} +void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } static void destroy_call(grpc_call *c) { int i; @@ -213,12 +211,14 @@ void grpc_call_internal_unref(grpc_call *c) { } } -static void set_status_code(grpc_call *call, status_source source, gpr_uint32 status) { +static void set_status_code(grpc_call *call, status_source source, + gpr_uint32 status) { call->status[source].set = 1; call->status[source].code = status; } -static void set_status_details(grpc_call *call, status_source source, grpc_mdstr *status) { +static void set_status_details(grpc_call *call, status_source source, + grpc_mdstr *status) { if (call->status[source].details != NULL) { grpc_mdstr_unref(call->status[source].details); } @@ -285,7 +285,8 @@ static void unlock(grpc_call *call) { } } -static void get_final_status(grpc_call *call, grpc_status_code *code, const char **details) { +static void get_final_status(grpc_call *call, grpc_status_code *code, + const char **details) { int i; for (i = 0; i < STATUS_SOURCE_COUNT; i++) { if (call->status[i].set) { @@ -317,9 +318,11 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, if (master->complete_mask == master->need_mask || status == GRPC_OP_ERROR) { if (OP_IN_MASK(GRPC_IOREQ_RECV_STATUS, master->need_mask)) { - get_final_status(call, - &call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->status, - &call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->details); + get_final_status( + call, + &call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->status, + &call->requests[GRPC_IOREQ_RECV_STATUS] + .data.recv_status->details); } for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { if (call->requests[i].master == master) { @@ -426,11 +429,10 @@ static void enact_send_action(grpc_call *call, send_action sa) { data = call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].data; for (i = 0; i < data.send_metadata.count; i++) { const grpc_metadata *md = &data.send_metadata.metadata[i]; - send_metadata( - call, - grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, - (const gpr_uint8 *)md->value, - md->value_length)); + send_metadata(call, + grpc_mdelem_from_string_and_buffer( + call->metadata_context, md->key, + (const gpr_uint8 *)md->value, md->value_length)); } op.type = GRPC_SEND_START; op.dir = GRPC_CALL_DOWN; @@ -454,11 +456,10 @@ static void enact_send_action(grpc_call *call, send_action sa) { data = call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].data; for (i = 0; i < data.send_metadata.count; i++) { const grpc_metadata *md = &data.send_metadata.metadata[i]; - send_metadata( - call, - grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key, - (const gpr_uint8 *)md->value, - md->value_length)); + send_metadata(call, + grpc_mdelem_from_string_and_buffer( + call->metadata_context, md->key, + (const gpr_uint8 *)md->value, md->value_length)); } lock(call); call->sending = 0; @@ -478,13 +479,13 @@ static void enact_send_action(grpc_call *call, send_action sa) { grpc_mdstr_ref(grpc_channel_get_status_string(call->channel)), grpc_mdstr_from_string(call->metadata_context, status_str))); if (data.send_close.details) { - send_metadata( - call, - grpc_mdelem_from_metadata_strings( - call->metadata_context, - grpc_mdstr_ref(grpc_channel_get_message_string(call->channel)), - grpc_mdstr_from_string(call->metadata_context, - data.send_close.details))); + send_metadata(call, + grpc_mdelem_from_metadata_strings( + call->metadata_context, + grpc_mdstr_ref( + grpc_channel_get_message_string(call->channel)), + grpc_mdstr_from_string(call->metadata_context, + data.send_close.details))); } } op.type = GRPC_SEND_FINISH; @@ -556,44 +557,46 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, for (i = 0; i < nreqs; i++) { op = reqs[i].op; switch (op) { - default: - break; - case GRPC_IOREQ_RECV_MESSAGES: - data.recv_messages->count = 0; - if (call->buffered_messages.count > 0 || call->read_closed) { - SWAP(grpc_byte_buffer_array, *data.recv_messages, - call->buffered_messages); - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); - } else { - call->need_more_data = 1; - } - break; - case GRPC_IOREQ_SEND_MESSAGES: - call->write_index = 0; - break; - case GRPC_IOREQ_SEND_CLOSE: - if (requests[GRPC_IOREQ_SEND_MESSAGES].state == REQ_INITIAL) { - requests[GRPC_IOREQ_SEND_MESSAGES].state = REQ_DONE; - } - break; - case GRPC_IOREQ_RECV_INITIAL_METADATA: - data.recv_metadata->count = 0; - if (call->buffered_initial_metadata.count > 0) { - SWAP(grpc_metadata_array, *data.recv_metadata, call->buffered_initial_metadata); - } - if (call->got_initial_metadata) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); - } - break; - case GRPC_IOREQ_RECV_TRAILING_METADATA: - data.recv_metadata->count = 0; - if (call->buffered_trailing_metadata.count > 0) { - SWAP(grpc_metadata_array, *data.recv_metadata, call->buffered_trailing_metadata); - } - if (call->read_closed) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); - } - break; + default: + break; + case GRPC_IOREQ_RECV_MESSAGES: + data.recv_messages->count = 0; + if (call->buffered_messages.count > 0 || call->read_closed) { + SWAP(grpc_byte_buffer_array, *data.recv_messages, + call->buffered_messages); + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); + } else { + call->need_more_data = 1; + } + break; + case GRPC_IOREQ_SEND_MESSAGES: + call->write_index = 0; + break; + case GRPC_IOREQ_SEND_CLOSE: + if (requests[GRPC_IOREQ_SEND_MESSAGES].state == REQ_INITIAL) { + requests[GRPC_IOREQ_SEND_MESSAGES].state = REQ_DONE; + } + break; + case GRPC_IOREQ_RECV_INITIAL_METADATA: + data.recv_metadata->count = 0; + if (call->buffered_initial_metadata.count > 0) { + SWAP(grpc_metadata_array, *data.recv_metadata, + call->buffered_initial_metadata); + } + if (call->got_initial_metadata) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + } + break; + case GRPC_IOREQ_RECV_TRAILING_METADATA: + data.recv_metadata->count = 0; + if (call->buffered_trailing_metadata.count > 0) { + SWAP(grpc_metadata_array, *data.recv_metadata, + call->buffered_trailing_metadata); + } + if (call->read_closed) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); + } + break; } } @@ -698,6 +701,18 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, return GRPC_CALL_OK; } +static void publish_failed_finished(grpc_call *call, grpc_status_code status, + const char *desc) { + grpc_status_code status_code; + const char *details; + set_status_code(call, STATUS_FROM_FAILED_OP, status); + set_status_details(call, STATUS_FROM_FAILED_OP, + grpc_mdstr_from_string(call->metadata_context, desc)); + get_final_status(call, &status_code, &details); + grpc_cq_end_finished(call->cq, get_legacy_state(call)->finished_tag, call, + do_nothing, NULL, status_code, details, NULL, 0); +} + static void finish_status(grpc_call *call, grpc_op_error status, void *tag) { legacy_state *ls; @@ -710,8 +725,7 @@ static void finish_status(grpc_call *call, grpc_op_error status, void *tag) { ls->status_in.status, ls->status_in.details, ls->trail_md_in.metadata, ls->trail_md_in.count); } else { - grpc_cq_end_finished(call->cq, tag, call, do_nothing, NULL, - GRPC_STATUS_UNKNOWN, "Read status failed", NULL, 0); + publish_failed_finished(call, GRPC_STATUS_UNKNOWN, "Read status failed"); } } @@ -756,9 +770,8 @@ static void finish_send_metadata(grpc_call *call, grpc_op_error status, ls = get_legacy_state(call); grpc_cq_end_client_metadata_read(call->cq, metadata_read_tag, call, do_nothing, NULL, 0, NULL); - grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, - GRPC_STATUS_UNKNOWN, "Failed to read initial metadata", - NULL, 0); + publish_failed_finished(call, GRPC_STATUS_UNKNOWN, + "Failed to read initial metadata"); } unlock(call); } @@ -828,8 +841,7 @@ grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, return err; } -void grpc_call_initial_metadata_complete( - grpc_call_element *surface_element) { +void grpc_call_initial_metadata_complete(grpc_call_element *surface_element) { grpc_call *call = grpc_call_from_top_element(surface_element); lock(call); call->got_initial_metadata = 1; From 11e3c929bc452d7d2de95b8f55cc91f07e7f382e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 15:10:41 -0800 Subject: [PATCH 33/93] NULL pointer check --- src/core/surface/call.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 6a1fa361de6..5caa3a6b040 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -291,7 +291,9 @@ static void get_final_status(grpc_call *call, grpc_status_code *code, for (i = 0; i < STATUS_SOURCE_COUNT; i++) { if (call->status[i].set) { *code = call->status[i].code; - *details = grpc_mdstr_as_c_string(call->status[i].details); + *details = call->status[i].details + ? grpc_mdstr_as_c_string(call->status[i].details) + : NULL; return; } } From fa8f4016eeda879e4552242daac9330284a2be71 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 16:16:58 -0800 Subject: [PATCH 34/93] Fix typo --- src/core/surface/call.c | 105 +++++++++++++++------------------------- 1 file changed, 39 insertions(+), 66 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 5caa3a6b040..135ad0c1102 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -59,8 +59,6 @@ typedef struct { grpc_recv_status status_in; size_t msg_in_read_idx; grpc_byte_buffer_array msg_in; - - void *finished_tag; } legacy_state; typedef enum { REQ_INITIAL = 0, REQ_READY, REQ_DONE } req_state; @@ -558,6 +556,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, for (i = 0; i < nreqs; i++) { op = reqs[i].op; + data = reqs[i].data; switch (op) { default: break; @@ -688,9 +687,9 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, if (ls->md_out_count == ls->md_out_capacity) { ls->md_out_capacity = - GPR_MAX(ls->md_out_count * 3 / 2, ls->md_out_count + 8); + GPR_MAX(ls->md_out_capacity * 3 / 2, ls->md_out_capacity + 8); ls->md_out = - gpr_realloc(ls->md_out, sizeof(grpc_mdelem *) * ls->md_out_capacity); + gpr_realloc(ls->md_out, sizeof(grpc_metadata) * ls->md_out_capacity); } mdout = &ls->md_out[ls->md_out_count++]; mdout->key = gpr_strdup(metadata->key); @@ -703,18 +702,6 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, return GRPC_CALL_OK; } -static void publish_failed_finished(grpc_call *call, grpc_status_code status, - const char *desc) { - grpc_status_code status_code; - const char *details; - set_status_code(call, STATUS_FROM_FAILED_OP, status); - set_status_details(call, STATUS_FROM_FAILED_OP, - grpc_mdstr_from_string(call->metadata_context, desc)); - get_final_status(call, &status_code, &details); - grpc_cq_end_finished(call->cq, get_legacy_state(call)->finished_tag, call, - do_nothing, NULL, status_code, details, NULL, 0); -} - static void finish_status(grpc_call *call, grpc_op_error status, void *tag) { legacy_state *ls; @@ -722,13 +709,9 @@ static void finish_status(grpc_call *call, grpc_op_error status, void *tag) { ls = get_legacy_state(call); unlock(call); - if (status == GRPC_OP_OK) { - grpc_cq_end_finished(call->cq, tag, call, do_nothing, NULL, - ls->status_in.status, ls->status_in.details, - ls->trail_md_in.metadata, ls->trail_md_in.count); - } else { - publish_failed_finished(call, GRPC_STATUS_UNKNOWN, "Read status failed"); - } + grpc_cq_end_finished(call->cq, tag, call, do_nothing, NULL, + ls->status_in.status, ls->status_in.details, + ls->trail_md_in.metadata, ls->trail_md_in.count); } static void finish_recv_metadata(grpc_call *call, grpc_op_error status, @@ -748,56 +731,44 @@ static void finish_recv_metadata(grpc_call *call, grpc_op_error status, unlock(call); } -static void finish_send_metadata(grpc_call *call, grpc_op_error status, - void *metadata_read_tag) { - grpc_ioreq reqs[2]; - legacy_state *ls; - - lock(call); - if (status == GRPC_OP_OK) { - ls = get_legacy_state(call); - reqs[0].op = GRPC_IOREQ_RECV_INITIAL_METADATA; - reqs[0].data.recv_metadata = &ls->md_in; - GPR_ASSERT(GRPC_CALL_OK == start_ioreq(call, reqs, 1, finish_recv_metadata, - metadata_read_tag)); - - ls = get_legacy_state(call); - reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA; - reqs[0].data.recv_metadata = &ls->trail_md_in; - reqs[1].op = GRPC_IOREQ_RECV_STATUS; - reqs[1].data.recv_status = &ls->status_in; - GPR_ASSERT(GRPC_CALL_OK == - start_ioreq(call, reqs, 2, finish_status, ls->finished_tag)); - } else { - ls = get_legacy_state(call); - grpc_cq_end_client_metadata_read(call->cq, metadata_read_tag, call, - do_nothing, NULL, 0, NULL); - publish_failed_finished(call, GRPC_STATUS_UNKNOWN, - "Failed to read initial metadata"); - } - unlock(call); -} +static void finish_send_metadata(grpc_call *call, grpc_op_error status, void *tag) {} grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, void *metadata_read_tag, void *finished_tag, gpr_uint32 flags) { - grpc_ioreq req; - legacy_state *ls = get_legacy_state(call); + grpc_ioreq reqs[2]; + legacy_state *ls; grpc_call_error err; grpc_cq_begin_op(cq, call, GRPC_CLIENT_METADATA_READ); grpc_cq_begin_op(cq, call, GRPC_FINISHED); lock(call); + ls = get_legacy_state(call); err = bind_cq(call, cq); - if (err != GRPC_CALL_OK) return err; - - get_legacy_state(call)->finished_tag = finished_tag; - - req.op = GRPC_IOREQ_SEND_INITIAL_METADATA; - req.data.send_metadata.count = ls->md_out_count; - req.data.send_metadata.metadata = ls->md_out; - err = start_ioreq(call, &req, 1, finish_send_metadata, metadata_read_tag); + if (err != GRPC_CALL_OK) goto done; + + reqs[0].op = GRPC_IOREQ_SEND_INITIAL_METADATA; + reqs[0].data.send_metadata.count = ls->md_out_count; + reqs[0].data.send_metadata.metadata = ls->md_out; + ls->md_out_count = 0; + err = start_ioreq(call, reqs, 1, finish_send_metadata, NULL); + if (err != GRPC_CALL_OK) goto done; + + reqs[0].op = GRPC_IOREQ_RECV_INITIAL_METADATA; + reqs[0].data.recv_metadata = &ls->md_in; + err = start_ioreq(call, reqs, 1, finish_recv_metadata, + metadata_read_tag); + if (err != GRPC_CALL_OK) goto done; + + reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA; + reqs[0].data.recv_metadata = &ls->trail_md_in; + reqs[1].op = GRPC_IOREQ_RECV_STATUS; + reqs[1].data.recv_status = &ls->status_in; + err = start_ioreq(call, reqs, 2, finish_status, finished_tag); + if (err != GRPC_CALL_OK) goto done; + +done: unlock(call); return err; } @@ -938,12 +909,14 @@ grpc_call_error grpc_call_start_write_status(grpc_call *call, const char *details, void *tag) { grpc_ioreq reqs[2]; grpc_call_error err; + legacy_state *ls; grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); lock(call); + ls = get_legacy_state(call); reqs[0].op = GRPC_IOREQ_SEND_TRAILING_METADATA; - reqs[0].data.send_metadata.count = call->legacy_state->md_out_count; - reqs[0].data.send_metadata.metadata = call->legacy_state->md_out; + reqs[0].data.send_metadata.count = ls->md_out_count; + reqs[0].data.send_metadata.metadata = ls->md_out; reqs[1].op = GRPC_IOREQ_SEND_CLOSE; reqs[1].data.send_close.status = status; reqs[1].data.send_close.details = details; @@ -1071,8 +1044,8 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { .data.recv_metadata : &call->buffered_initial_metadata; } else { - dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].state == REQ_READY - ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] + dest = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].state == REQ_READY + ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] .data.recv_metadata : &call->buffered_trailing_metadata; } From b58f95d285e923c4dd66c6ed302cf1e9f321906d Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 16:32:52 -0800 Subject: [PATCH 35/93] Fix early edge cases --- src/core/surface/call.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 135ad0c1102..5e3f581509e 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -569,8 +569,19 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, } else { call->need_more_data = 1; } + if (call->stream_closed) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); + } + break; + case GRPC_IOREQ_RECV_STATUS: + if (call->stream_closed && call->buffered_messages.count == 0) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); + } break; case GRPC_IOREQ_SEND_MESSAGES: + if (call->stream_closed) { + finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGES, GRPC_OP_ERROR); + } call->write_index = 0; break; case GRPC_IOREQ_SEND_CLOSE: @@ -578,6 +589,11 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, requests[GRPC_IOREQ_SEND_MESSAGES].state = REQ_DONE; } break; + case GRPC_IOREQ_SEND_INITIAL_METADATA: + if (call->stream_closed) { + finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_OP_ERROR); + } + break; case GRPC_IOREQ_RECV_INITIAL_METADATA: data.recv_metadata->count = 0; if (call->buffered_initial_metadata.count > 0) { @@ -586,6 +602,8 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, } if (call->got_initial_metadata) { finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + } else if (call->stream_closed) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_ERROR); } break; case GRPC_IOREQ_RECV_TRAILING_METADATA: @@ -976,7 +994,9 @@ void grpc_call_stream_closed(grpc_call_element *elem) { finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); } call->stream_closed = 1; - finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); + if (call->buffered_messages.count == 0) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); + } unlock(call); grpc_call_internal_unref(call); } From bb3f22f4d6e61c9b0f12b2b54cdc3e38934d541e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 16:40:56 -0800 Subject: [PATCH 36/93] Fix somewhat obvious error --- src/core/surface/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 0f21a3aefb6..b71c57d9bb1 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -671,8 +671,8 @@ static grpc_call_error queue_call_request(grpc_server *server, } calld = call_list_remove_head(server, PENDING_START); if (calld) { - calld->state = ACTIVATED; GPR_ASSERT(calld->state == PENDING); + calld->state = ACTIVATED; gpr_mu_unlock(&server->mu); cb(server, cq, initial_metadata, calld, user_data); return GRPC_CALL_OK; From 4433e6e68d740d99774bfbe8ad775ef6f219c103 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 16:43:25 -0800 Subject: [PATCH 37/93] Fix echo test --- test/core/echo/echo_test.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/core/echo/echo_test.c b/test/core/echo/echo_test.c index 6449b2414f3..550ad782677 100644 --- a/test/core/echo/echo_test.c +++ b/test/core/echo/echo_test.c @@ -99,12 +99,13 @@ int main(int argc, char **argv) { svr = fork(); if (svr == 0) { gpr_asprintf(&args[0], "%s/echo_server", root); - gpr_join_host_port(&args[1], "::", port); - args[2] = 0; + args[1] = "-bind"; + gpr_join_host_port(&args[2], "::", port); + args[3] = 0; execv(args[0], args); gpr_free(args[0]); - gpr_free(args[1]); + gpr_free(args[2]); return 1; } /* wait a little */ From cb818ba745f8a23b91a56f3db05417bf921f98fe Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 17:08:01 -0800 Subject: [PATCH 38/93] Free stream ops outside transport lock Resolves a deadlock caused by flow control callbacks being made under the lock. --- src/core/transport/chttp2_transport.c | 43 +++++++++++++++++++-------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 5465d3306a5..478d4a6944b 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -237,6 +237,9 @@ struct transport { /* state for a stream that's not yet been created */ grpc_stream_op_buffer new_stream_sopb; + /* stream ops that need to be destroyed, but outside of the lock */ + grpc_stream_op_buffer nuke_later_sopb; + /* active parser */ void *parser_data; stream *incoming_stream; @@ -343,6 +346,7 @@ static void unref_transport(transport *t) { grpc_chttp2_hpack_parser_destroy(&t->hpack_parser); grpc_chttp2_hpack_compressor_destroy(&t->hpack_compressor); grpc_chttp2_goaway_parser_destroy(&t->goaway_parser); + grpc_sopb_destroy(&t->nuke_later_sopb); grpc_mdstr_unref(t->str_grpc_timeout); @@ -416,6 +420,7 @@ static void init_transport(transport *t, grpc_transport_setup_callback setup, t->cap_pending_goaways = 0; gpr_slice_buffer_init(&t->outbuf); gpr_slice_buffer_init(&t->qbuf); + grpc_sopb_init(&t->nuke_later_sopb); if (is_client) { gpr_slice_buffer_add(&t->qbuf, gpr_slice_from_copied_string(CLIENT_CONNECT_STRING)); @@ -525,7 +530,7 @@ static int init_stream(grpc_transport *gt, grpc_stream *gs, lock(t); s->id = 0; } else { - s->id = (gpr_uint32)(gpr_uintptr)server_data; + s->id = (gpr_uint32)(gpr_uintptr) server_data; t->incoming_stream = s; grpc_chttp2_stream_map_add(&t->stream_map, s->id, s); } @@ -555,6 +560,11 @@ static int init_stream(grpc_transport *gt, grpc_stream *gs, return 0; } +static void schedule_nuke_sopb(transport *t, grpc_stream_op_buffer *sopb) { + grpc_sopb_append(&t->nuke_later_sopb, sopb->ops, sopb->nops); + sopb->nops = 0; +} + static void destroy_stream(grpc_transport *gt, grpc_stream *gs) { transport *t = (transport *)gt; stream *s = (stream *)gs; @@ -681,6 +691,11 @@ static void unlock(transport *t) { int i; pending_goaway *goaways = NULL; grpc_endpoint *ep = t->ep; + grpc_stream_op_buffer nuke_now = t->nuke_later_sopb; + + if (nuke_now.nops) { + memset(&t->nuke_later_sopb, 0, sizeof(t->nuke_later_sopb)); + } /* see if we need to trigger a write - and if so, get the data ready */ if (ep && !t->writing) { @@ -750,6 +765,10 @@ static void unlock(transport *t) { unref_transport(t); } + if (nuke_now.nops) { + grpc_sopb_reset(&nuke_now); + } + gpr_free(goaways); } @@ -1006,9 +1025,9 @@ static void cancel_stream_inner(transport *t, stream *s, gpr_uint32 id, if (s) { /* clear out any unreported input & output: nobody cares anymore */ - grpc_sopb_reset(&s->parser.incoming_sopb); had_outgoing = s->outgoing_sopb.nops != 0; - grpc_sopb_reset(&s->outgoing_sopb); + schedule_nuke_sopb(t, &s->parser.incoming_sopb); + schedule_nuke_sopb(t, &s->outgoing_sopb); if (s->cancelled) { send_rst = 0; } else if (!s->read_closed || !s->sent_write_closed || had_outgoing) { @@ -1238,7 +1257,7 @@ static int init_header_frame_parser(transport *t, int is_continuation) { t->incoming_stream = NULL; /* if stream is accepted, we set incoming_stream in init_stream */ t->cb->accept_stream(t->cb_user_data, &t->base, - (void *)(gpr_uintptr)t->incoming_stream_id); + (void *)(gpr_uintptr) t->incoming_stream_id); s = t->incoming_stream; if (!s) { gpr_log(GPR_ERROR, "stream not accepted"); @@ -1503,8 +1522,8 @@ static int process_read(transport *t, gpr_slice slice) { "Connect string mismatch: expected '%c' (%d) got '%c' (%d) " "at byte %d", CLIENT_CONNECT_STRING[t->deframe_state], - (int)(gpr_uint8)CLIENT_CONNECT_STRING[t->deframe_state], *cur, - (int)*cur, t->deframe_state); + (int)(gpr_uint8) CLIENT_CONNECT_STRING[t->deframe_state], + *cur, (int)*cur, t->deframe_state); drop_connection(t); return 0; } @@ -1518,7 +1537,7 @@ static int process_read(transport *t, gpr_slice slice) { dts_fh_0: case DTS_FH_0: GPR_ASSERT(cur < end); - t->incoming_frame_size = ((gpr_uint32) * cur) << 16; + t->incoming_frame_size = ((gpr_uint32)*cur) << 16; if (++cur == end) { t->deframe_state = DTS_FH_1; return 1; @@ -1526,7 +1545,7 @@ static int process_read(transport *t, gpr_slice slice) { /* fallthrough */ case DTS_FH_1: GPR_ASSERT(cur < end); - t->incoming_frame_size |= ((gpr_uint32) * cur) << 8; + t->incoming_frame_size |= ((gpr_uint32)*cur) << 8; if (++cur == end) { t->deframe_state = DTS_FH_2; return 1; @@ -1558,7 +1577,7 @@ static int process_read(transport *t, gpr_slice slice) { /* fallthrough */ case DTS_FH_5: GPR_ASSERT(cur < end); - t->incoming_stream_id = (((gpr_uint32) * cur) << 24) & 0x7f; + t->incoming_stream_id = (((gpr_uint32)*cur) << 24) & 0x7f; if (++cur == end) { t->deframe_state = DTS_FH_6; return 1; @@ -1566,7 +1585,7 @@ static int process_read(transport *t, gpr_slice slice) { /* fallthrough */ case DTS_FH_6: GPR_ASSERT(cur < end); - t->incoming_stream_id |= ((gpr_uint32) * cur) << 16; + t->incoming_stream_id |= ((gpr_uint32)*cur) << 16; if (++cur == end) { t->deframe_state = DTS_FH_7; return 1; @@ -1574,7 +1593,7 @@ static int process_read(transport *t, gpr_slice slice) { /* fallthrough */ case DTS_FH_7: GPR_ASSERT(cur < end); - t->incoming_stream_id |= ((gpr_uint32) * cur) << 8; + t->incoming_stream_id |= ((gpr_uint32)*cur) << 8; if (++cur == end) { t->deframe_state = DTS_FH_8; return 1; @@ -1582,7 +1601,7 @@ static int process_read(transport *t, gpr_slice slice) { /* fallthrough */ case DTS_FH_8: GPR_ASSERT(cur < end); - t->incoming_stream_id |= ((gpr_uint32) * cur); + t->incoming_stream_id |= ((gpr_uint32)*cur); t->deframe_state = DTS_FRAME; if (!init_frame_parser(t)) { return 0; From aef25da3e8efbc1c5b60ef35d7afbd03b693735e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 17:19:45 -0800 Subject: [PATCH 39/93] Allow asynchronous call destruction in some cases If there's a chance we're being called via a callback, we need to delay destruction until later. Otherwise, for performance, destroy it inline. --- src/core/surface/call.c | 25 +++++++++++++++---------- src/core/surface/call.h | 2 +- src/core/surface/completion_queue.c | 2 +- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 5e3f581509e..8fb42e29bef 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -183,8 +183,9 @@ legacy_state *get_legacy_state(grpc_call *call) { void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } -static void destroy_call(grpc_call *c) { +static void destroy_call(void *call, int ignored_success) { int i; + grpc_call *c = call; grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_channel_internal_unref(c->channel); gpr_mu_destroy(&c->mu); @@ -203,9 +204,13 @@ static void destroy_call(grpc_call *c) { gpr_free(c); } -void grpc_call_internal_unref(grpc_call *c) { +void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) { if (gpr_unref(&c->internal_refcount)) { - destroy_call(c); + if (allow_immediate_deletion) { + destroy_call(c, 1); + } else { + grpc_iomgr_add_callback(destroy_call, c); + } } } @@ -350,7 +355,7 @@ static void finish_write_step(void *pc, grpc_op_error error) { } call->sending = 0; unlock(call); - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 0); } static void finish_finish_step(void *pc, grpc_op_error error) { @@ -359,7 +364,7 @@ static void finish_finish_step(void *pc, grpc_op_error error) { finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, error); call->sending = 0; unlock(call); - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 0); } static void finish_start_step(void *pc, grpc_op_error error) { @@ -368,7 +373,7 @@ static void finish_start_step(void *pc, grpc_op_error error) { finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, error); call->sending = 0; unlock(call); - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 0); } static send_action choose_send_action(grpc_call *call) { @@ -464,7 +469,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { lock(call); call->sending = 0; unlock(call); - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 0); break; case SEND_FINISH: if (!call->is_client) { @@ -656,7 +661,7 @@ void grpc_call_destroy(grpc_call *c) { cancel = !c->stream_closed; unlock(c); if (cancel) grpc_call_cancel(c); - grpc_call_internal_unref(c); + grpc_call_internal_unref(c, 1); } grpc_call_error grpc_call_cancel(grpc_call *c) { @@ -958,7 +963,7 @@ static void call_alarm(void *arg, int success) { grpc_call_cancel(call); } } - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 1); } void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { @@ -998,7 +1003,7 @@ void grpc_call_stream_closed(grpc_call_element *elem) { finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); } unlock(call); - grpc_call_internal_unref(call); + grpc_call_internal_unref(call, 0); } /* we offset status by a small amount when storing it into transport metadata diff --git a/src/core/surface/call.h b/src/core/surface/call.h index 57592089eef..c130a13b81d 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -46,7 +46,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, const void *server_transport_data); void grpc_call_internal_ref(grpc_call *call); -void grpc_call_internal_unref(grpc_call *call); +void grpc_call_internal_unref(grpc_call *call, int allow_immediate_deletion); /* Helpers for grpc_client, grpc_server filters to publish received data to the completion queue/surface layer */ diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c index 5854afbeefd..ae3b96035c1 100644 --- a/src/core/surface/completion_queue.c +++ b/src/core/surface/completion_queue.c @@ -388,7 +388,7 @@ void grpc_event_finish(grpc_event *base) { event *ev = (event *)base; ev->on_finish(ev->on_finish_user_data, GRPC_OP_OK); if (ev->base.call) { - grpc_call_internal_unref(ev->base.call); + grpc_call_internal_unref(ev->base.call, 1); } gpr_free(ev); } From a0935d9e3661b073f5f630b1b2333ed63d55a1cb Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 17:36:37 -0800 Subject: [PATCH 40/93] Add missing wait --- test/core/fling/client.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/core/fling/client.c b/test/core/fling/client.c index e1743c3e7ea..b526f018874 100644 --- a/test/core/fling/client.c +++ b/test/core/fling/client.c @@ -65,6 +65,7 @@ static void step_ping_pong_request(void) { grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); + grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); grpc_call_destroy(call); call = NULL; } From 4acdbb3352628a56002cdfe9901c53773cca3172 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 21:02:52 -0800 Subject: [PATCH 41/93] Signedness fix --- src/core/surface/call.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 8fb42e29bef..c28380aea8b 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -424,7 +424,7 @@ static void send_metadata(grpc_call *call, grpc_mdelem *elem) { static void enact_send_action(grpc_call *call, send_action sa) { grpc_ioreq_data data; grpc_call_op op; - int i; + size_t i; switch (sa) { case SEND_NOTHING: From f25b0eea4296e83238fc65827b89118dcbc3e5ba Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 21:03:39 -0800 Subject: [PATCH 42/93] Init fix --- test/core/fling/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/fling/client.c b/test/core/fling/client.c index d3838cd10d6..fa8f2639413 100644 --- a/test/core/fling/client.c +++ b/test/core/fling/client.c @@ -114,7 +114,7 @@ int main(int argc, char **argv) { char *target = "localhost:443"; gpr_cmdline *cl; char *scenario_name = "ping-pong-request"; - scenario sc = {NULL}; + scenario sc = {NULL, NULL, NULL}; GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; From 48d01aef37605a7c2200e27823db85ac761bcd23 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 22:08:59 -0800 Subject: [PATCH 43/93] Fix some TSAN reported errors --- src/core/iomgr/pollset_multipoller_with_poll_posix.c | 7 +++++-- src/core/iomgr/pollset_posix.c | 12 +++++++----- src/core/iomgr/pollset_posix.h | 4 +++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/core/iomgr/pollset_multipoller_with_poll_posix.c b/src/core/iomgr/pollset_multipoller_with_poll_posix.c index 7c9a9491cb0..e88296979df 100644 --- a/src/core/iomgr/pollset_multipoller_with_poll_posix.c +++ b/src/core/iomgr/pollset_multipoller_with_poll_posix.c @@ -147,8 +147,6 @@ static int multipoll_with_poll_pollset_maybe_work( grpc_fd_unref(h->fds[i]); } else { h->fds[nf++] = h->fds[i]; - h->pfds[np].events = - grpc_fd_begin_poll(h->fds[i], pollset, POLLIN, POLLOUT); h->selfds[np] = h->fds[i]; h->pfds[np].fd = h->fds[i]->fd; h->pfds[np].revents = 0; @@ -168,6 +166,11 @@ static int multipoll_with_poll_pollset_maybe_work( pollset->counter = 1; gpr_mu_unlock(&pollset->mu); + for (i = 1; i < np; i++) { + h->pfds[i].events = + grpc_fd_begin_poll(h->selfds[i], pollset, POLLIN, POLLOUT); + } + r = poll(h->pfds, h->pfd_count, timeout); if (r < 0) { if (errno != EINTR) { diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index 39e2dc46672..b1c2c64a18c 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -75,11 +75,12 @@ static void backup_poller(void *p) { } void grpc_pollset_kick(grpc_pollset *p) { - if (!p->counter) return; - grpc_pollset_kick_kick(&p->kick_state); + if (p->counter) { + grpc_pollset_kick_kick(&p->kick_state); + } } -void grpc_pollset_force_kick(grpc_pollset *p) { grpc_pollset_kick(p); } +void grpc_pollset_force_kick(grpc_pollset *p) { grpc_pollset_kick_kick(&p->kick_state); } /* global state management */ @@ -244,11 +245,12 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset, pfd[0].events = POLLIN; pfd[0].revents = 0; pfd[1].fd = fd->fd; - pfd[1].events = grpc_fd_begin_poll(fd, pollset, POLLIN, POLLOUT); pfd[1].revents = 0; pollset->counter = 1; gpr_mu_unlock(&pollset->mu); + pfd[1].events = grpc_fd_begin_poll(fd, pollset, POLLIN, POLLOUT); + r = poll(pfd, GPR_ARRAY_SIZE(pfd), timeout); if (r < 0) { if (errno != EINTR) { @@ -269,9 +271,9 @@ static int unary_poll_pollset_maybe_work(grpc_pollset *pollset, } grpc_pollset_kick_post_poll(&pollset->kick_state); + grpc_fd_end_poll(fd, pollset); gpr_mu_lock(&pollset->mu); - grpc_fd_end_poll(fd, pollset); pollset->counter = 0; gpr_cv_broadcast(&pollset->cv); return 1; diff --git a/src/core/iomgr/pollset_posix.h b/src/core/iomgr/pollset_posix.h index f62433707e7..3da025151d7 100644 --- a/src/core/iomgr/pollset_posix.h +++ b/src/core/iomgr/pollset_posix.h @@ -78,7 +78,9 @@ void grpc_pollset_add_fd(grpc_pollset *pollset, struct grpc_fd *fd); poll after an fd is orphaned) */ void grpc_pollset_del_fd(grpc_pollset *pollset, struct grpc_fd *fd); -/* Force any current pollers to break polling */ +/* Force any current pollers to break polling: it's the callers responsibility + to ensure that the pollset indeed needs to be kicked. + Does not touch pollset->mu. */ void grpc_pollset_force_kick(grpc_pollset *pollset); /* Returns the fd to listen on for kicks */ int grpc_kick_read_fd(grpc_pollset *p); From 50524cc67dc145d1930c16c241141748f3459956 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 23:00:00 -0800 Subject: [PATCH 44/93] Properly deal with end of stream --- Makefile | 2 ++ src/core/surface/call.c | 53 ++++++++++++++++++++++++++----------- templates/Makefile.template | 2 ++ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 1465f36bd61..92889092693 100644 --- a/Makefile +++ b/Makefile @@ -189,11 +189,13 @@ OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/ope ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS) PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/perftools.c -lprofiler $(LDFLAGS) +ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_PERFTOOLS = $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_SYSTEM_PERFTOOLS),true) DEFINES += GRPC_HAVE_PERFTOOLS LIBS += profiler endif +endif ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index c28380aea8b..f8c12077935 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -59,6 +59,9 @@ typedef struct { grpc_recv_status status_in; size_t msg_in_read_idx; grpc_byte_buffer_array msg_in; + + gpr_uint8 got_status; + void *finished_tag; } legacy_state; typedef enum { REQ_INITIAL = 0, REQ_READY, REQ_DONE } req_state; @@ -596,7 +599,8 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, break; case GRPC_IOREQ_SEND_INITIAL_METADATA: if (call->stream_closed) { - finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_OP_ERROR); + finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, + GRPC_OP_ERROR); } break; case GRPC_IOREQ_RECV_INITIAL_METADATA: @@ -608,7 +612,8 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, if (call->got_initial_metadata) { finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); } else if (call->stream_closed) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_ERROR); + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, + GRPC_OP_ERROR); } break; case GRPC_IOREQ_RECV_TRAILING_METADATA: @@ -725,16 +730,25 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, return GRPC_CALL_OK; } -static void finish_status(grpc_call *call, grpc_op_error status, void *tag) { +static void maybe_finish_legacy(grpc_call *call) { + legacy_state *ls = get_legacy_state(call); + gpr_log(GPR_DEBUG, "%d %d %d", ls->got_status, ls->msg_in_read_idx, ls->msg_in.count); + if (ls->got_status && ls->msg_in_read_idx == ls->msg_in.count) { + grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, + ls->status_in.status, ls->status_in.details, + ls->trail_md_in.metadata, ls->trail_md_in.count); + } +} + +static void finish_status(grpc_call *call, grpc_op_error status, + void *ignored) { legacy_state *ls; lock(call); ls = get_legacy_state(call); + ls->got_status = 1; + maybe_finish_legacy(call); unlock(call); - - grpc_cq_end_finished(call->cq, tag, call, do_nothing, NULL, - ls->status_in.status, ls->status_in.details, - ls->trail_md_in.metadata, ls->trail_md_in.count); } static void finish_recv_metadata(grpc_call *call, grpc_op_error status, @@ -754,7 +768,8 @@ static void finish_recv_metadata(grpc_call *call, grpc_op_error status, unlock(call); } -static void finish_send_metadata(grpc_call *call, grpc_op_error status, void *tag) {} +static void finish_send_metadata(grpc_call *call, grpc_op_error status, + void *tag) {} grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, void *metadata_read_tag, void *finished_tag, @@ -771,6 +786,8 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, err = bind_cq(call, cq); if (err != GRPC_CALL_OK) goto done; + ls->finished_tag = finished_tag; + reqs[0].op = GRPC_IOREQ_SEND_INITIAL_METADATA; reqs[0].data.send_metadata.count = ls->md_out_count; reqs[0].data.send_metadata.metadata = ls->md_out; @@ -780,15 +797,14 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, reqs[0].op = GRPC_IOREQ_RECV_INITIAL_METADATA; reqs[0].data.recv_metadata = &ls->md_in; - err = start_ioreq(call, reqs, 1, finish_recv_metadata, - metadata_read_tag); + err = start_ioreq(call, reqs, 1, finish_recv_metadata, metadata_read_tag); if (err != GRPC_CALL_OK) goto done; reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA; reqs[0].data.recv_metadata = &ls->trail_md_in; reqs[1].op = GRPC_IOREQ_RECV_STATUS; reqs[1].data.recv_status = &ls->status_in; - err = start_ioreq(call, reqs, 2, finish_status, finished_tag); + err = start_ioreq(call, reqs, 2, finish_status, NULL); if (err != GRPC_CALL_OK) goto done; done: @@ -810,9 +826,11 @@ grpc_call_error grpc_call_server_accept(grpc_call *call, err = bind_cq(call, cq); if (err != GRPC_CALL_OK) return err; + get_legacy_state(call)->finished_tag = finished_tag; + req.op = GRPC_IOREQ_RECV_STATUS; req.data.recv_status = &get_legacy_state(call)->status_in; - err = start_ioreq(call, &req, 1, finish_status, finished_tag); + err = start_ioreq(call, &req, 1, finish_status, NULL); unlock(call); return err; } @@ -854,6 +872,7 @@ static void finish_read(grpc_call *call, grpc_op_error error, void *tag) { } else { grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, ls->msg_in.buffers[ls->msg_in_read_idx++]); + maybe_finish_legacy(call); } unlock(call); } @@ -877,6 +896,7 @@ grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { err = GRPC_CALL_OK; grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, ls->msg_in.buffers[ls->msg_in_read_idx++]); + maybe_finish_legacy(call); } unlock(call); return err; @@ -1069,10 +1089,11 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { .data.recv_metadata : &call->buffered_initial_metadata; } else { - dest = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].state == REQ_READY - ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] - .data.recv_metadata - : &call->buffered_trailing_metadata; + dest = + call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].state == REQ_READY + ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] + .data.recv_metadata + : &call->buffered_trailing_metadata; } if (dest->count == dest->capacity) { dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2); diff --git a/templates/Makefile.template b/templates/Makefile.template index 142d188d0c6..c34949cf2a7 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -206,11 +206,13 @@ OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/ope ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS) PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/perftools.c -lprofiler $(LDFLAGS) +ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_PERFTOOLS = $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_SYSTEM_PERFTOOLS),true) DEFINES += GRPC_HAVE_PERFTOOLS LIBS += profiler endif +endif ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) From f5c914694d14bc91bff60dfe6ac460177f827117 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 23:00:56 -0800 Subject: [PATCH 45/93] Fix spam --- src/core/surface/call.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index f8c12077935..702b00caba0 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -732,7 +732,6 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, static void maybe_finish_legacy(grpc_call *call) { legacy_state *ls = get_legacy_state(call); - gpr_log(GPR_DEBUG, "%d %d %d", ls->got_status, ls->msg_in_read_idx, ls->msg_in.count); if (ls->got_status && ls->msg_in_read_idx == ls->msg_in.count) { grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, ls->status_in.status, ls->status_in.details, From e6b92e62f1f5d6e0c2d59637fa4cd64e81daac8b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 23:10:16 -0800 Subject: [PATCH 46/93] Dont request more data until the first message is received --- src/core/surface/call.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 702b00caba0..ba19ee7a566 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -118,6 +118,7 @@ struct grpc_call { gpr_uint8 got_status_code; gpr_uint8 sending; gpr_uint8 num_completed_requests; + gpr_uint8 got_any_data; gpr_uint8 need_more_data; reqinfo requests[GRPC_IOREQ_OP_COUNT]; @@ -575,7 +576,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, call->buffered_messages); finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); } else { - call->need_more_data = 1; + call->need_more_data = call->got_any_data; } if (call->stream_closed) { finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); @@ -1053,6 +1054,7 @@ void grpc_call_recv_message(grpc_call_element *elem, grpc_call *call = CALL_FROM_TOP_ELEM(elem); grpc_byte_buffer_array *dest; lock(call); + call->got_any_data = 1; if (call->requests[GRPC_IOREQ_RECV_MESSAGES].master != NULL) { dest = call->requests[GRPC_IOREQ_RECV_MESSAGES].data.recv_messages; } else { From cffbcb7be886fd850dcf210b20bba3d61a67cb26 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 29 Jan 2015 23:16:33 -0800 Subject: [PATCH 47/93] Actually, dont start reading until initial metadata send is done --- src/core/surface/call.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index ba19ee7a566..719f12bae50 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -118,7 +118,6 @@ struct grpc_call { gpr_uint8 got_status_code; gpr_uint8 sending; gpr_uint8 num_completed_requests; - gpr_uint8 got_any_data; gpr_uint8 need_more_data; reqinfo requests[GRPC_IOREQ_OP_COUNT]; @@ -257,10 +256,14 @@ static void unlock(grpc_call *call) { send_action sa = SEND_NOTHING; completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; int num_completed_requests = call->num_completed_requests; - int need_more_data = call->need_more_data; + int need_more_data = + call->need_more_data && + call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].state == REQ_DONE; int i; - call->need_more_data = 0; + if (need_more_data) { + call->need_more_data = 0; + } if (num_completed_requests != 0) { memcpy(completed_requests, call->completed_requests, @@ -576,7 +579,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, call->buffered_messages); finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); } else { - call->need_more_data = call->got_any_data; + call->need_more_data = 1; } if (call->stream_closed) { finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); @@ -1054,7 +1057,6 @@ void grpc_call_recv_message(grpc_call_element *elem, grpc_call *call = CALL_FROM_TOP_ELEM(elem); grpc_byte_buffer_array *dest; lock(call); - call->got_any_data = 1; if (call->requests[GRPC_IOREQ_RECV_MESSAGES].master != NULL) { dest = call->requests[GRPC_IOREQ_RECV_MESSAGES].data.recv_messages; } else { From 79ce823fb13ee3d42bf2a2764f318a0e3134bba2 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 07:32:59 -0800 Subject: [PATCH 48/93] Cleanup unused state --- src/core/surface/call.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 719f12bae50..a8ead0bc03a 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -93,7 +93,6 @@ typedef struct reqinfo { typedef enum { STATUS_FROM_API_OVERRIDE = 0, STATUS_FROM_WIRE, - STATUS_FROM_FAILED_OP, STATUS_SOURCE_COUNT } status_source; From 3a4749fd79c844791e72ae33ceaa719e9d35c15b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 07:51:45 -0800 Subject: [PATCH 49/93] Call owns all metadata until its destroyed --- src/core/surface/call.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index a8ead0bc03a..b080e11e00c 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -125,6 +125,9 @@ struct grpc_call { grpc_metadata_array buffered_initial_metadata; grpc_metadata_array buffered_trailing_metadata; size_t write_index; + grpc_mdelem **owned_metadata; + size_t owned_metadata_count; + size_t owned_metadata_capacity; received_status status[STATUS_SOURCE_COUNT]; @@ -186,7 +189,7 @@ legacy_state *get_legacy_state(grpc_call *call) { void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } static void destroy_call(void *call, int ignored_success) { - int i; + size_t i; grpc_call *c = call; grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_channel_internal_unref(c->channel); @@ -196,6 +199,10 @@ static void destroy_call(void *call, int ignored_success) { grpc_mdstr_unref(c->status[i].details); } } + for (i = 0; i < c->owned_metadata_count; i++) { + grpc_mdelem_unref(c->owned_metadata[i]); + } + gpr_free(c->owned_metadata); if (c->legacy_state) { gpr_free(c->legacy_state->md_out); gpr_free(c->legacy_state->md_in.metadata); @@ -1106,6 +1113,14 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { mdusr->key = (char *)grpc_mdstr_as_c_string(md->key); mdusr->value = (char *)grpc_mdstr_as_c_string(md->value); mdusr->value_length = GPR_SLICE_LENGTH(md->value->slice); + if (call->owned_metadata_count == call->owned_metadata_capacity) { + call->owned_metadata_capacity = GPR_MAX( + call->owned_metadata_capacity + 8, call->owned_metadata_capacity * 2); + call->owned_metadata = + gpr_realloc(call->owned_metadata, + sizeof(grpc_mdelem *) * call->owned_metadata_capacity); + } + call->owned_metadata[call->owned_metadata_count++] = md; } unlock(call); } From 68f55a0804e956feb879beeaa95875295c74a582 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 07:54:48 -0800 Subject: [PATCH 50/93] Free the messages --- src/core/surface/call.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index b080e11e00c..ba461fee7db 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -872,6 +872,10 @@ void grpc_call_initial_metadata_complete(grpc_call_element *surface_element) { unlock(call); } +static void finish_read_event(void *p, grpc_op_error error) { + grpc_byte_buffer_destroy(p); +} + static void finish_read(grpc_call *call, grpc_op_error error, void *tag) { legacy_state *ls; lock(call); @@ -879,8 +883,8 @@ static void finish_read(grpc_call *call, grpc_op_error error, void *tag) { if (ls->msg_in.count == 0) { grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, NULL); } else { - grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, - ls->msg_in.buffers[ls->msg_in_read_idx++]); + grpc_byte_buffer *msg = ls->msg_in.buffers[ls->msg_in_read_idx++]; + grpc_cq_end_read(call->cq, tag, call, finish_read_event, msg, msg); maybe_finish_legacy(call); } unlock(call); From 1500b952ec41367988f169a000f205e26ac3687c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 08:03:00 -0800 Subject: [PATCH 51/93] Free the messages --- src/core/surface/call.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index ba461fee7db..10941912719 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -188,6 +188,15 @@ legacy_state *get_legacy_state(grpc_call *call) { void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } +static void destroy_message_array(grpc_byte_buffer_array *array, + size_t start_idx) { + size_t i; + for (i = start_idx; i < array->count; i++) { + grpc_byte_buffer_destroy(array->buffers[i]); + } + gpr_free(array->buffers); +} + static void destroy_call(void *call, int ignored_success) { size_t i; grpc_call *c = call; @@ -203,11 +212,13 @@ static void destroy_call(void *call, int ignored_success) { grpc_mdelem_unref(c->owned_metadata[i]); } gpr_free(c->owned_metadata); + destroy_message_array(&c->buffered_messages, 0); if (c->legacy_state) { gpr_free(c->legacy_state->md_out); gpr_free(c->legacy_state->md_in.metadata); gpr_free(c->legacy_state->trail_md_in.metadata); - /*gpr_free(c->legacy_state->status_in.details);*/ + destroy_message_array(&c->legacy_state->msg_in, + c->legacy_state->msg_in_read_idx); gpr_free(c->legacy_state); } gpr_free(c); From 05b034dbd15a9bb9db3d1910248cf2aa3dd50172 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 09:35:02 -0800 Subject: [PATCH 52/93] Free the messages --- src/core/surface/call.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 10941912719..127c2dc117d 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -138,7 +138,7 @@ struct grpc_call { legacy_state *legacy_state; }; -#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call)+1)) +#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1) #define CALL_ELEM_FROM_CALL(call, idx) \ grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx) @@ -905,6 +905,7 @@ grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { legacy_state *ls; grpc_ioreq req; grpc_call_error err; + grpc_byte_buffer *msg; grpc_cq_begin_op(call->cq, call, GRPC_READ); @@ -918,8 +919,8 @@ grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { err = start_ioreq(call, &req, 1, finish_read, tag); } else { err = GRPC_CALL_OK; - grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, - ls->msg_in.buffers[ls->msg_in_read_idx++]); + msg = ls->msg_in.buffers[ls->msg_in_read_idx++]; + grpc_cq_end_read(call->cq, tag, call, finish_read_event, msg, msg); maybe_finish_legacy(call); } unlock(call); @@ -1060,7 +1061,7 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { gpr_uint32 status; void *user_data = grpc_mdelem_get_user_data(md, destroy_status); if (user_data) { - status = ((gpr_uint32)(gpr_intptr) user_data) - STATUS_OFFSET; + status = ((gpr_uint32)(gpr_intptr)user_data) - STATUS_OFFSET; } else { if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value), GPR_SLICE_LENGTH(md->value->slice), From 924e1bbe1ed503f5b15397b1ba845adff611d724 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 09:41:25 -0800 Subject: [PATCH 53/93] Free some leaks in http_server_filter --- src/core/channel/http_server_filter.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c index 2658a6d42ea..3e5bb0506ac 100644 --- a/src/core/channel/http_server_filter.c +++ b/src/core/channel/http_server_filter.c @@ -319,8 +319,8 @@ static void init_channel_elem(grpc_channel_element *elem, if (channeld->gettable_count == gettable_capacity) { gettable_capacity = GPR_MAX(gettable_capacity * 3 / 2, gettable_capacity + 1); - channeld->gettables = - gpr_realloc(channeld->gettables, gettable_capacity * sizeof(gettable)); + channeld->gettables = gpr_realloc(channeld->gettables, + gettable_capacity * sizeof(gettable)); } g = &channeld->gettables[channeld->gettable_count++]; g->path = grpc_mdelem_from_strings(mdctx, ":path", p->path); @@ -334,9 +334,17 @@ static void init_channel_elem(grpc_channel_element *elem, /* Destructor for channel data */ static void destroy_channel_elem(grpc_channel_element *elem) { + size_t i; + /* grab pointers to our data from the channel element */ channel_data *channeld = elem->channel_data; + for (i = 0; i < channeld->gettable_count; i++) { + grpc_mdelem_unref(channeld->gettables[i].path); + grpc_mdelem_unref(channeld->gettables[i].content_type); + } + gpr_free(channeld->gettables); + grpc_mdelem_unref(channeld->te_trailers); grpc_mdelem_unref(channeld->status_ok); grpc_mdelem_unref(channeld->status_not_found); @@ -350,6 +358,6 @@ static void destroy_channel_elem(grpc_channel_element *elem) { } const grpc_channel_filter grpc_http_server_filter = { - call_op, channel_op, sizeof(call_data), - init_call_elem, destroy_call_elem, sizeof(channel_data), - init_channel_elem, destroy_channel_elem, "http-server"}; + call_op, channel_op, sizeof(call_data), init_call_elem, destroy_call_elem, + sizeof(channel_data), init_channel_elem, destroy_channel_elem, + "http-server"}; From 4df31a60b872445f1bcd527cb00d0e6cba437759 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 09:44:31 -0800 Subject: [PATCH 54/93] Free host, path strings --- src/core/surface/server.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/surface/server.c b/src/core/surface/server.c index b71c57d9bb1..7fe50ee9bb9 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -411,6 +411,13 @@ static void destroy_call_elem(grpc_call_element *elem) { } gpr_mu_unlock(&chand->server->mu); + if (calld->host) { + grpc_mdstr_unref(calld->host); + } + if (calld->path) { + grpc_mdstr_unref(calld->path); + } + if (calld->legacy) { gpr_free(calld->legacy->initial_metadata); gpr_free(calld->legacy); From 7c886bd4c6e09a346a1c3e481e9541c07f7046c9 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 09:45:50 -0800 Subject: [PATCH 55/93] Fix memory leak --- src/core/channel/http_server_filter.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c index 3e5bb0506ac..b70af434a79 100644 --- a/src/core/channel/http_server_filter.c +++ b/src/core/channel/http_server_filter.c @@ -328,6 +328,7 @@ static void init_channel_elem(grpc_channel_element *elem, grpc_mdelem_from_strings(mdctx, "content-type", p->content_type); slice = gpr_slice_from_copied_string(p->content); g->content = grpc_byte_buffer_create(&slice, 1); + gpr_slice_unref(slice); } } } @@ -342,6 +343,7 @@ static void destroy_channel_elem(grpc_channel_element *elem) { for (i = 0; i < channeld->gettable_count; i++) { grpc_mdelem_unref(channeld->gettables[i].path); grpc_mdelem_unref(channeld->gettables[i].content_type); + grpc_byte_buffer_destroy(channeld->gettables[i].content); } gpr_free(channeld->gettables); From c689ca31e23d141555ceb5e294b22b514d1ec687 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 10:59:52 -0800 Subject: [PATCH 56/93] Free mdout buffers --- src/core/surface/call.c | 45 ++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 127c2dc117d..43083256211 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -48,9 +48,10 @@ #define OP_IN_MASK(op, mask) (((1 << (op)) & (mask)) != 0) typedef struct { - size_t md_out_count; - size_t md_out_capacity; - grpc_metadata *md_out; + gpr_uint8 md_out_buffer; + size_t md_out_count[2]; + size_t md_out_capacity[2]; + grpc_metadata *md_out[2]; grpc_byte_buffer *msg_out; /* input buffers */ @@ -198,7 +199,7 @@ static void destroy_message_array(grpc_byte_buffer_array *array, } static void destroy_call(void *call, int ignored_success) { - size_t i; + size_t i, j; grpc_call *c = call; grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_channel_internal_unref(c->channel); @@ -213,8 +214,16 @@ static void destroy_call(void *call, int ignored_success) { } gpr_free(c->owned_metadata); destroy_message_array(&c->buffered_messages, 0); + gpr_free(c->buffered_initial_metadata.metadata); + gpr_free(c->buffered_trailing_metadata.metadata); if (c->legacy_state) { - gpr_free(c->legacy_state->md_out); + for (i = 0; i < 2; i++) { + for (j = 0; j < c->legacy_state->md_out_count[i]; j++) { + gpr_free(c->legacy_state->md_out[i][j].key); + gpr_free(c->legacy_state->md_out[i][j].value); + } + gpr_free(c->legacy_state->md_out[i]); + } gpr_free(c->legacy_state->md_in.metadata); gpr_free(c->legacy_state->trail_md_in.metadata); destroy_message_array(&c->legacy_state->msg_in, @@ -734,13 +743,13 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, lock(call); ls = get_legacy_state(call); - if (ls->md_out_count == ls->md_out_capacity) { - ls->md_out_capacity = - GPR_MAX(ls->md_out_capacity * 3 / 2, ls->md_out_capacity + 8); - ls->md_out = - gpr_realloc(ls->md_out, sizeof(grpc_metadata) * ls->md_out_capacity); + if (ls->md_out_count[ls->md_out_buffer] == ls->md_out_capacity[ls->md_out_buffer]) { + ls->md_out_capacity[ls->md_out_buffer] = + GPR_MAX(ls->md_out_capacity[ls->md_out_buffer] * 3 / 2, ls->md_out_capacity[ls->md_out_buffer] + 8); + ls->md_out[ls->md_out_buffer] = + gpr_realloc(ls->md_out[ls->md_out_buffer], sizeof(grpc_metadata) * ls->md_out_capacity[ls->md_out_buffer]); } - mdout = &ls->md_out[ls->md_out_count++]; + mdout = &ls->md_out[ls->md_out_buffer][ls->md_out_count[ls->md_out_buffer]++]; mdout->key = gpr_strdup(metadata->key); mdout->value = gpr_malloc(metadata->value_length); mdout->value_length = metadata->value_length; @@ -809,9 +818,9 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, ls->finished_tag = finished_tag; reqs[0].op = GRPC_IOREQ_SEND_INITIAL_METADATA; - reqs[0].data.send_metadata.count = ls->md_out_count; - reqs[0].data.send_metadata.metadata = ls->md_out; - ls->md_out_count = 0; + reqs[0].data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; + reqs[0].data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; + ls->md_out_buffer++; err = start_ioreq(call, reqs, 1, finish_send_metadata, NULL); if (err != GRPC_CALL_OK) goto done; @@ -867,8 +876,8 @@ grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, lock(call); ls = get_legacy_state(call); req.op = GRPC_IOREQ_SEND_INITIAL_METADATA; - req.data.send_metadata.count = ls->md_out_count; - req.data.send_metadata.metadata = ls->md_out; + req.data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; + req.data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; err = start_ioreq(call, &req, 1, finish_send_initial_metadata, NULL); unlock(call); @@ -983,8 +992,8 @@ grpc_call_error grpc_call_start_write_status(grpc_call *call, lock(call); ls = get_legacy_state(call); reqs[0].op = GRPC_IOREQ_SEND_TRAILING_METADATA; - reqs[0].data.send_metadata.count = ls->md_out_count; - reqs[0].data.send_metadata.metadata = ls->md_out; + reqs[0].data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; + reqs[0].data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; reqs[1].op = GRPC_IOREQ_SEND_CLOSE; reqs[1].data.send_close.status = status; reqs[1].data.send_close.details = details; From 8ed35ea35fc1c39bad540d0cd5dd167fadf284d4 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 11:27:43 -0800 Subject: [PATCH 57/93] Fix memory leak --- src/core/transport/chttp2_transport.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 478d4a6944b..48a10058331 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -346,7 +346,6 @@ static void unref_transport(transport *t) { grpc_chttp2_hpack_parser_destroy(&t->hpack_parser); grpc_chttp2_hpack_compressor_destroy(&t->hpack_compressor); grpc_chttp2_goaway_parser_destroy(&t->goaway_parser); - grpc_sopb_destroy(&t->nuke_later_sopb); grpc_mdstr_unref(t->str_grpc_timeout); @@ -374,6 +373,8 @@ static void unref_transport(transport *t) { } gpr_free(t->pending_goaways); + grpc_sopb_destroy(&t->nuke_later_sopb); + gpr_free(t); } @@ -530,7 +531,7 @@ static int init_stream(grpc_transport *gt, grpc_stream *gs, lock(t); s->id = 0; } else { - s->id = (gpr_uint32)(gpr_uintptr) server_data; + s->id = (gpr_uint32)(gpr_uintptr)server_data; t->incoming_stream = s; grpc_chttp2_stream_map_add(&t->stream_map, s->id, s); } @@ -766,7 +767,7 @@ static void unlock(transport *t) { } if (nuke_now.nops) { - grpc_sopb_reset(&nuke_now); + grpc_sopb_destroy(&nuke_now); } gpr_free(goaways); @@ -1257,7 +1258,7 @@ static int init_header_frame_parser(transport *t, int is_continuation) { t->incoming_stream = NULL; /* if stream is accepted, we set incoming_stream in init_stream */ t->cb->accept_stream(t->cb_user_data, &t->base, - (void *)(gpr_uintptr) t->incoming_stream_id); + (void *)(gpr_uintptr)t->incoming_stream_id); s = t->incoming_stream; if (!s) { gpr_log(GPR_ERROR, "stream not accepted"); @@ -1522,8 +1523,8 @@ static int process_read(transport *t, gpr_slice slice) { "Connect string mismatch: expected '%c' (%d) got '%c' (%d) " "at byte %d", CLIENT_CONNECT_STRING[t->deframe_state], - (int)(gpr_uint8) CLIENT_CONNECT_STRING[t->deframe_state], - *cur, (int)*cur, t->deframe_state); + (int)(gpr_uint8)CLIENT_CONNECT_STRING[t->deframe_state], *cur, + (int)*cur, t->deframe_state); drop_connection(t); return 0; } @@ -1757,9 +1758,9 @@ static void add_to_pollset(grpc_transport *gt, grpc_pollset *pollset) { */ static const grpc_transport_vtable vtable = { - sizeof(stream), init_stream, send_batch, set_allow_window_updates, - add_to_pollset, destroy_stream, abort_stream, goaway, - close_transport, send_ping, destroy_transport}; + sizeof(stream), init_stream, send_batch, set_allow_window_updates, + add_to_pollset, destroy_stream, abort_stream, goaway, close_transport, + send_ping, destroy_transport}; void grpc_create_chttp2_transport(grpc_transport_setup_callback setup, void *arg, From 03d5bf7e947601c5e751cdc03239ae7102dd8134 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 12:01:30 -0800 Subject: [PATCH 58/93] Rename some stuff --- src/core/surface/call.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 43083256211..733c980502c 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -55,8 +55,8 @@ typedef struct { grpc_byte_buffer *msg_out; /* input buffers */ - grpc_metadata_array md_in; - grpc_metadata_array trail_md_in; + grpc_metadata_array initial_md_in; + grpc_metadata_array trailing_md_in; grpc_recv_status status_in; size_t msg_in_read_idx; grpc_byte_buffer_array msg_in; @@ -224,8 +224,8 @@ static void destroy_call(void *call, int ignored_success) { } gpr_free(c->legacy_state->md_out[i]); } - gpr_free(c->legacy_state->md_in.metadata); - gpr_free(c->legacy_state->trail_md_in.metadata); + gpr_free(c->legacy_state->initial_md_in.metadata); + gpr_free(c->legacy_state->trailing_md_in.metadata); destroy_message_array(&c->legacy_state->msg_in, c->legacy_state->msg_in_read_idx); gpr_free(c->legacy_state); @@ -765,7 +765,7 @@ static void maybe_finish_legacy(grpc_call *call) { if (ls->got_status && ls->msg_in_read_idx == ls->msg_in.count) { grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, ls->status_in.status, ls->status_in.details, - ls->trail_md_in.metadata, ls->trail_md_in.count); + ls->trailing_md_in.metadata, ls->trailing_md_in.count); } } @@ -788,7 +788,7 @@ static void finish_recv_metadata(grpc_call *call, grpc_op_error status, ls = get_legacy_state(call); if (status == GRPC_OP_OK) { grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, - ls->md_in.count, ls->md_in.metadata); + ls->initial_md_in.count, ls->initial_md_in.metadata); } else { grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, 0, @@ -825,12 +825,12 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, if (err != GRPC_CALL_OK) goto done; reqs[0].op = GRPC_IOREQ_RECV_INITIAL_METADATA; - reqs[0].data.recv_metadata = &ls->md_in; + reqs[0].data.recv_metadata = &ls->initial_md_in; err = start_ioreq(call, reqs, 1, finish_recv_metadata, metadata_read_tag); if (err != GRPC_CALL_OK) goto done; reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA; - reqs[0].data.recv_metadata = &ls->trail_md_in; + reqs[0].data.recv_metadata = &ls->trailing_md_in; reqs[1].op = GRPC_IOREQ_RECV_STATUS; reqs[1].data.recv_status = &ls->status_in; err = start_ioreq(call, reqs, 2, finish_status, NULL); @@ -1117,12 +1117,15 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value)); grpc_mdelem_unref(md); } else { + char *sel; if (!call->got_initial_metadata) { + sel = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].state == REQ_READY? "req_init" : "buf_init"; dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].state == REQ_READY ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] .data.recv_metadata : &call->buffered_initial_metadata; } else { + sel = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].state == REQ_READY? "req_trail" : "buf_trail"; dest = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].state == REQ_READY ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] From 149c112d00ae06d4e68579b1ef18b63fdd739752 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 12:01:41 -0800 Subject: [PATCH 59/93] Fix memory leak --- src/core/surface/server.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 7fe50ee9bb9..05cb2181255 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -419,6 +419,7 @@ static void destroy_call_elem(grpc_call_element *elem) { } if (calld->legacy) { + gpr_free(calld->legacy->initial_metadata->metadata); gpr_free(calld->legacy->initial_metadata); gpr_free(calld->legacy); } From 97c943db8d2800806c374fb3a5a36b66af8f427a Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 12:03:20 -0800 Subject: [PATCH 60/93] Remove unused variable --- src/core/surface/call.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 733c980502c..5040aeef137 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -1117,15 +1117,12 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value)); grpc_mdelem_unref(md); } else { - char *sel; if (!call->got_initial_metadata) { - sel = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].state == REQ_READY? "req_init" : "buf_init"; dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].state == REQ_READY ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] .data.recv_metadata : &call->buffered_initial_metadata; } else { - sel = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].state == REQ_READY? "req_trail" : "buf_trail"; dest = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].state == REQ_READY ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] From 1e0d4c43d1b6d7db1f01c1ce7508eacb5dcdd85d Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 16:17:29 -0800 Subject: [PATCH 61/93] Rename & semantic fixup progress --- include/grpc/grpc.h | 93 +++--- src/core/surface/byte_buffer_queue.c | 112 +++++++ src/core/surface/byte_buffer_queue.h | 53 +++ src/core/surface/call.c | 305 +++++++++--------- src/core/surface/call.h | 41 +++ test/core/echo/client.c | 2 +- test/core/end2end/dualstack_socket_test.c | 2 +- test/core/end2end/no_server_test.c | 2 +- test/core/end2end/tests/cancel_after_accept.c | 3 +- .../cancel_after_accept_and_writes_closed.c | 3 +- test/core/end2end/tests/cancel_after_invoke.c | 3 +- .../core/end2end/tests/cancel_before_invoke.c | 3 +- test/core/end2end/tests/cancel_in_a_vacuum.c | 3 +- .../end2end/tests/census_simple_request.c | 3 +- test/core/end2end/tests/disappearing_server.c | 3 +- ..._server_shutdown_finishes_inflight_calls.c | 3 +- .../end2end/tests/graceful_server_shutdown.c | 3 +- .../core/end2end/tests/invoke_large_request.c | 3 +- .../end2end/tests/max_concurrent_streams.c | 10 +- test/core/end2end/tests/ping_pong_streaming.c | 3 +- ...esponse_with_binary_metadata_and_payload.c | 3 +- ...quest_response_with_metadata_and_payload.c | 3 +- .../tests/request_response_with_payload.c | 3 +- ...ponse_with_trailing_metadata_and_payload.c | 3 +- .../tests/request_with_large_metadata.c | 3 +- .../core/end2end/tests/request_with_payload.c | 3 +- .../end2end/tests/simple_delayed_request.c | 3 +- test/core/end2end/tests/simple_request.c | 6 +- test/core/end2end/tests/thread_stress.c | 2 +- .../writes_done_hangs_with_pending_read.c | 3 +- test/core/fling/client.c | 4 +- test/core/surface/lame_client_test.c | 2 +- 32 files changed, 441 insertions(+), 250 deletions(-) create mode 100644 src/core/surface/byte_buffer_queue.c create mode 100644 src/core/surface/byte_buffer_queue.h diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 6a818fcd478..0ebfad88249 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -239,12 +239,6 @@ typedef struct { grpc_metadata *metadata; } grpc_metadata_array; -typedef struct { - size_t count; - size_t capacity; - grpc_byte_buffer **buffers; -} grpc_byte_buffer_array; - typedef struct { grpc_status_code status; const char *details; @@ -257,40 +251,43 @@ typedef struct { } grpc_call_details; typedef enum { - GRPC_IOREQ_SEND_INITIAL_METADATA = 0, - GRPC_IOREQ_SEND_TRAILING_METADATA, - GRPC_IOREQ_SEND_MESSAGES, - GRPC_IOREQ_SEND_CLOSE, - GRPC_IOREQ_RECV_INITIAL_METADATA, - GRPC_IOREQ_RECV_TRAILING_METADATA, - GRPC_IOREQ_RECV_MESSAGES, - GRPC_IOREQ_RECV_STATUS, - GRPC_IOREQ_OP_COUNT -} grpc_ioreq_op; - -typedef union { - struct { - size_t count; - const grpc_metadata *metadata; - } send_metadata; - struct { - size_t count; - grpc_byte_buffer **messages; - } send_messages; - struct { - /* fields only make sense on the server */ - grpc_status_code status; - const char *details; - } send_close; - grpc_metadata_array *recv_metadata; - grpc_byte_buffer_array *recv_messages; - grpc_recv_status *recv_status; -} grpc_ioreq_data; - -typedef struct grpc_ioreq { - grpc_ioreq_op op; - grpc_ioreq_data data; -} grpc_ioreq; + GRPC_OP_SEND_INITIAL_METADATA = 0, + GRPC_OP_SEND_MESSAGE, + GRPC_OP_SEND_CLOSE_FROM_CLIENT, + GRPC_OP_SEND_STATUS_FROM_SERVER, + GRPC_OP_RECV_INITIAL_METADATA, + GRPC_OP_RECV_MESSAGES, + GRPC_OP_RECV_STATUS_ON_CLIENT, + GRPC_OP_RECV_CLOSE_ON_SERVER +} grpc_op_type; + +typedef struct grpc_op { + grpc_op_type op; + union { + struct { + size_t count; + const grpc_metadata *metadata; + } send_initial_metadata; + grpc_byte_buffer *send_message; + struct { + size_t trailing_metadata_count; + grpc_metadata *trailing_metadata; + grpc_status_code status; + const char *status_details; + } send_status_from_server; + grpc_metadata_array *recv_initial_metadata; + grpc_byte_buffer **recv_message; + struct { + grpc_metadata_array *trailing_metadata; + grpc_status_code *status; + char **status_details; + size_t *status_details_capacity; + } recv_status_on_client; + struct { + int *cancelled; + } recv_close_on_server; + } data; +} grpc_op; /* Initialize the grpc library */ void grpc_init(void); @@ -335,14 +332,12 @@ void grpc_completion_queue_destroy(grpc_completion_queue *cq); is not sent until grpc_call_invoke is called. All completions are sent to 'completion_queue'. */ -grpc_call *grpc_channel_create_call_old(grpc_channel *channel, const char *method, const char *host, gpr_timespec deadline); - -grpc_call *grpc_channel_create_call(grpc_channel *channel, - grpc_completion_queue *cq, - const grpc_call_details *details); +grpc_call *grpc_channel_create_call(grpc_channel *channel, const char *method, + const char *host, gpr_timespec deadline); -grpc_call_error grpc_call_start_ioreq(grpc_call *call, const grpc_ioreq *reqs, - size_t nreqs, void *tag); +grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops, + size_t nops, grpc_completion_queue *cq, + void *tag); /* Create a client channel */ grpc_channel *grpc_channel_create(const char *target, @@ -483,8 +478,8 @@ void grpc_call_destroy(grpc_call *call); grpc_call_error grpc_server_request_call_old(grpc_server *server, void *tag_new); grpc_call_error grpc_server_request_call( - grpc_server *server, grpc_completion_queue *cq, grpc_call_details *details, - grpc_metadata_array *initial_metadata, void *tag); + grpc_server *server, grpc_call_details *details, + grpc_metadata_array *initial_metadata, grpc_completion_queue *cq, void *tag); /* Create a server */ grpc_server *grpc_server_create(grpc_completion_queue *cq, diff --git a/src/core/surface/byte_buffer_queue.c b/src/core/surface/byte_buffer_queue.c new file mode 100644 index 00000000000..bd5263b2f64 --- /dev/null +++ b/src/core/surface/byte_buffer_queue.c @@ -0,0 +1,112 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/surface/byte_buffer_queue.h" + +#define INITIAL_PENDING_READ_COUNT 4 + +static void pra_init(pending_read_array *array) { + array->data = gpr_malloc(sizeof(pending_read) * INITIAL_PENDING_READ_COUNT); + array->count = 0; + array->capacity = INITIAL_PENDING_READ_COUNT; +} + +static void pra_destroy(pending_read_array *array, + size_t finish_starting_from) { + size_t i; + for (i = finish_starting_from; i < array->count; i++) { + array->data[i].on_finish(array->data[i].user_data, GRPC_OP_ERROR); + } + gpr_free(array->data); +} + +/* Append an operation to an array, expanding as needed */ +static void pra_push(pending_read_array *a, grpc_byte_buffer *buffer, + void (*on_finish)(void *user_data, grpc_op_error error), + void *user_data) { + if (a->count == a->capacity) { + a->capacity *= 2; + a->data = gpr_realloc(a->data, sizeof(pending_read) * a->capacity); + } + a->data[a->count].byte_buffer = buffer; + a->data[a->count].user_data = user_data; + a->data[a->count].on_finish = on_finish; + a->count++; +} + +static void prq_init(pending_read_queue *q) { + q->drain_pos = 0; + pra_init(&q->filling); + pra_init(&q->draining); +} + +static void prq_destroy(pending_read_queue *q) { + pra_destroy(&q->filling, 0); + pra_destroy(&q->draining, q->drain_pos); +} + +static int prq_is_empty(pending_read_queue *q) { + return (q->drain_pos == q->draining.count && q->filling.count == 0); +} + +static void prq_push(pending_read_queue *q, grpc_byte_buffer *buffer, + void (*on_finish)(void *user_data, grpc_op_error error), + void *user_data) { + pra_push(&q->filling, buffer, on_finish, user_data); +} + +/* Take the first queue element and move it to the completion queue. Do nothing + if q is empty */ +static int prq_pop_to_cq(pending_read_queue *q, void *tag, grpc_call *call, + grpc_completion_queue *cq) { + pending_read_array temp_array; + pending_read *pr; + + if (q->drain_pos == q->draining.count) { + if (q->filling.count == 0) { + return 0; + } + q->draining.count = 0; + q->drain_pos = 0; + /* swap arrays */ + temp_array = q->filling; + q->filling = q->draining; + q->draining = temp_array; + } + + pr = q->draining.data + q->drain_pos; + q->drain_pos++; + grpc_cq_end_read(cq, tag, call, pr->on_finish, pr->user_data, + pr->byte_buffer); + return 1; +} diff --git a/src/core/surface/byte_buffer_queue.h b/src/core/surface/byte_buffer_queue.h new file mode 100644 index 00000000000..ffd2616d9d7 --- /dev/null +++ b/src/core/surface/byte_buffer_queue.h @@ -0,0 +1,53 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __GRPC_INTERNAL_SURFACE_BYTE_BUFFER_QUEUE_H__ +#define __GRPC_INTERNAL_SURFACE_BYTE_BUFFER_QUEUE_H__ + +/* TODO(ctiller): inline an element or two into this struct to avoid per-call + allocations */ +typedef struct { + grpc_byte_buffer **data; + size_t count; + size_t capacity; +} grpc_bbq_array; + +typedef struct { + size_t drain_pos; + grpc_bbq_array filling; + grpc_bbq_array draining; +} grpc_byte_buffer_queue; + +grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q); + +#endif /* __GRPC_INTERNAL_SURFACE_BYTE_BUFFER_QUEUE_H__ */ diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 5040aeef137..4f8ac6193a9 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -36,6 +36,7 @@ #include "src/core/channel/metadata_buffer.h" #include "src/core/iomgr/alarm.h" #include "src/core/support/string.h" +#include "src/core/surface/byte_buffer_queue.h" #include "src/core/surface/channel.h" #include "src/core/surface/completion_queue.h" #include @@ -59,7 +60,7 @@ typedef struct { grpc_metadata_array trailing_md_in; grpc_recv_status status_in; size_t msg_in_read_idx; - grpc_byte_buffer_array msg_in; + grpc_byte_buffer *msg_in; gpr_uint8 got_status; void *finished_tag; @@ -72,6 +73,7 @@ typedef enum { SEND_INITIAL_METADATA, SEND_MESSAGE, SEND_TRAILING_METADATA, + SEND_STATUS, SEND_FINISH } send_action; @@ -81,10 +83,24 @@ typedef struct { grpc_op_error status; } completed_request; +/* See reqinfo.set below for a description */ +#define REQSET_EMPTY 255 +#define REQSET_DONE 254 + +/* The state of an ioreq */ typedef struct reqinfo { - req_state state; + /* User supplied parameters */ grpc_ioreq_data data; - struct reqinfo *master; + /* In which set is this ioreq? + This value could be: + - an element of grpc_ioreq_op enumeration, in which case + it designates the master ioreq in a set of requests + - REQSET_EMPTY, in which case this reqinfo type has no application + request against it + - REQSET_DONE, in which case this reqinfo has been satisfied for + all time for this call, and no further use will be made of it */ + gpr_uint8 set; + grpc_op_error status; grpc_ioreq_completion_func on_complete; void *user_data; gpr_uint32 need_mask; @@ -122,10 +138,9 @@ struct grpc_call { reqinfo requests[GRPC_IOREQ_OP_COUNT]; completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; - grpc_byte_buffer_array buffered_messages; + grpc_byte_buffer_queue incoming_queue; grpc_metadata_array buffered_initial_metadata; grpc_metadata_array buffered_trailing_metadata; - size_t write_index; grpc_mdelem **owned_metadata; size_t owned_metadata_count; size_t owned_metadata_capacity; @@ -159,6 +174,7 @@ static void enact_send_action(grpc_call *call, send_action sa); grpc_call *grpc_call_create(grpc_channel *channel, const void *server_transport_data) { + size_t i; grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel); grpc_call *call = gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size); @@ -166,8 +182,11 @@ grpc_call *grpc_call_create(grpc_channel *channel, gpr_mu_init(&call->mu); call->channel = channel; call->is_client = server_transport_data == NULL; + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + call->requests[i].set = REQSET_EMPTY; + } if (call->is_client) { - call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].state = REQ_DONE; + call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].set = REQSET_DONE; } grpc_channel_internal_ref(channel); call->metadata_context = grpc_channel_get_metadata_context(channel); @@ -189,15 +208,6 @@ legacy_state *get_legacy_state(grpc_call *call) { void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } -static void destroy_message_array(grpc_byte_buffer_array *array, - size_t start_idx) { - size_t i; - for (i = start_idx; i < array->count; i++) { - grpc_byte_buffer_destroy(array->buffers[i]); - } - gpr_free(array->buffers); -} - static void destroy_call(void *call, int ignored_success) { size_t i, j; grpc_call *c = call; @@ -213,7 +223,6 @@ static void destroy_call(void *call, int ignored_success) { grpc_mdelem_unref(c->owned_metadata[i]); } gpr_free(c->owned_metadata); - destroy_message_array(&c->buffered_messages, 0); gpr_free(c->buffered_initial_metadata.metadata); gpr_free(c->buffered_trailing_metadata.metadata); if (c->legacy_state) { @@ -226,8 +235,6 @@ static void destroy_call(void *call, int ignored_success) { } gpr_free(c->legacy_state->initial_md_in.metadata); gpr_free(c->legacy_state->trailing_md_in.metadata); - destroy_message_array(&c->legacy_state->msg_in, - c->legacy_state->msg_in_read_idx); gpr_free(c->legacy_state); } gpr_free(c); @@ -284,7 +291,7 @@ static void unlock(grpc_call *call) { int num_completed_requests = call->num_completed_requests; int need_more_data = call->need_more_data && - call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].state == REQ_DONE; + call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].set == REQSET_DONE; int i; if (need_more_data) { @@ -321,124 +328,131 @@ static void unlock(grpc_call *call) { } } -static void get_final_status(grpc_call *call, grpc_status_code *code, - const char **details) { +static void get_final_status(grpc_call *call, grpc_recv_status_args args) { int i; for (i = 0; i < STATUS_SOURCE_COUNT; i++) { if (call->status[i].set) { - *code = call->status[i].code; - *details = call->status[i].details - ? grpc_mdstr_as_c_string(call->status[i].details) - : NULL; + *args.code = call->status[i].code; + 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); + } + memcpy(*args.details, GPR_SLICE_START_PTR(details), len); + (*args.details)[len] = 0; + } else { + goto no_details; + } return; } } - *code = GRPC_STATUS_UNKNOWN; - *details = NULL; + *args.code = GRPC_STATUS_UNKNOWN; + +no_details: + if (0 == *args.details_capacity) { + *args.details_capacity = 8; + *args.details = gpr_malloc(*args.details_capacity); + } + **args.details = 0; } static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, grpc_op_error status) { - reqinfo *master = call->requests[op].master; completed_request *cr; size_t i; - switch (call->requests[op].state) { - case REQ_INITIAL: /* not started yet */ - return; - case REQ_DONE: /* already finished */ - return; - case REQ_READY: - master->complete_mask |= 1 << op; - call->requests[op].state = - (op == GRPC_IOREQ_SEND_MESSAGES || op == GRPC_IOREQ_RECV_MESSAGES) - ? REQ_INITIAL - : REQ_DONE; - if (master->complete_mask == master->need_mask || - status == GRPC_OP_ERROR) { - if (OP_IN_MASK(GRPC_IOREQ_RECV_STATUS, master->need_mask)) { - get_final_status( - call, - &call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status->status, - &call->requests[GRPC_IOREQ_RECV_STATUS] - .data.recv_status->details); - } - for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { - if (call->requests[i].master == master) { - call->requests[i].master = NULL; + if (call->requests[op].set < GRPC_IOREQ_OP_COUNT) { + reqinfo *master = &call->requests[call->requests[op].set]; + /* ioreq is live: we need to do something */ + master->complete_mask |= 1 << op; + call->requests[op].set = + (op == GRPC_IOREQ_SEND_MESSAGE || op == GRPC_IOREQ_RECV_MESSAGE) + ? REQSET_EMPTY + : REQSET_DONE; + if (master->complete_mask == master->need_mask || + status == GRPC_OP_ERROR) { + if (OP_IN_MASK(GRPC_IOREQ_RECV_STATUS, master->need_mask)) { + get_final_status( + call, + call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status); + } + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + if (call->requests[i].set == op) { + if (call->requests[i].status != GRPC_OP_OK) { + status = GRPC_OP_ERROR; } + call->requests[i].set = REQSET_EMPTY; } - cr = &call->completed_requests[call->num_completed_requests++]; - cr->status = status; - cr->on_complete = master->on_complete; - cr->user_data = master->user_data; } + cr = &call->completed_requests[call->num_completed_requests++]; + cr->status = status; + cr->on_complete = master->on_complete; + cr->user_data = master->user_data; + } } } -static void finish_write_step(void *pc, grpc_op_error error) { - grpc_call *call = pc; +static void finish_send_op(grpc_call *call, grpc_ioreq_op op, grpc_op_error error) { lock(call); - if (error == GRPC_OP_OK) { - if (call->write_index == - call->requests[GRPC_IOREQ_SEND_MESSAGES].data.send_messages.count) { - finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGES, GRPC_OP_OK); - } - } else { - finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGES, GRPC_OP_ERROR); - } + finish_ioreq_op(call, op, error); call->sending = 0; unlock(call); grpc_call_internal_unref(call, 0); } +static void finish_write_step(void *pc, grpc_op_error error) { + finish_send_op(pc, GRPC_IOREQ_SEND_MESSAGE, error); +} + static void finish_finish_step(void *pc, grpc_op_error error) { - grpc_call *call = pc; - lock(call); - finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, error); - call->sending = 0; - unlock(call); - grpc_call_internal_unref(call, 0); + finish_send_op(pc, GRPC_IOREQ_SEND_CLOSE, error); } static void finish_start_step(void *pc, grpc_op_error error) { - grpc_call *call = pc; - lock(call); - finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, error); - call->sending = 0; - unlock(call); - grpc_call_internal_unref(call, 0); + finish_send_op(pc, GRPC_IOREQ_SEND_INITIAL_METADATA, error); } static send_action choose_send_action(grpc_call *call) { - switch (call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].state) { - case REQ_INITIAL: + switch (call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].set) { + case REQSET_EMPTY: return SEND_NOTHING; - case REQ_READY: + default: return SEND_INITIAL_METADATA; - case REQ_DONE: + case REQSET_DONE: break; } - switch (call->requests[GRPC_IOREQ_SEND_MESSAGES].state) { - case REQ_INITIAL: + switch (call->requests[GRPC_IOREQ_SEND_MESSAGE].set) { + case REQSET_EMPTY: return SEND_NOTHING; - case REQ_READY: + default: return SEND_MESSAGE; - case REQ_DONE: + case REQSET_DONE: break; } - switch (call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].state) { - case REQ_INITIAL: + switch (call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].set) { + case REQSET_EMPTY: return SEND_NOTHING; - case REQ_READY: + default: finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); return SEND_TRAILING_METADATA; - case REQ_DONE: + case REQSET_DONE: break; } - switch (call->requests[GRPC_IOREQ_SEND_CLOSE].state) { + switch (call->requests[GRPC_IOREQ_SEND_STATUS].set) { + case REQSET_EMPTY: + return SEND_NOTHING; default: + finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, GRPC_OP_OK); + return SEND_STATUS; + case REQSET_DONE: + break; + } + switch (call->requests[GRPC_IOREQ_SEND_CLOSE].set) { + case REQSET_EMPTY: + case REQSET_DONE: return SEND_NOTHING; - case REQ_READY: + default: return SEND_FINISH; } } @@ -458,6 +472,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { grpc_ioreq_data data; grpc_call_op op; size_t i; + char status_str[GPR_LTOA_MIN_BUFSIZE]; switch (sa) { case SEND_NOTHING: @@ -481,11 +496,11 @@ static void enact_send_action(grpc_call *call, send_action sa) { grpc_call_execute_op(call, &op); break; case SEND_MESSAGE: - data = call->requests[GRPC_IOREQ_SEND_MESSAGES].data; + data = call->requests[GRPC_IOREQ_SEND_MESSAGE].data; op.type = GRPC_SEND_MESSAGE; op.dir = GRPC_CALL_DOWN; op.flags = 0; - op.data.message = data.send_messages.messages[call->write_index++]; + op.data.message = data.send_message; op.done_cb = finish_write_step; op.user_data = call; grpc_call_execute_op(call, &op); @@ -504,28 +519,27 @@ static void enact_send_action(grpc_call *call, send_action sa) { unlock(call); grpc_call_internal_unref(call, 0); break; - case SEND_FINISH: - if (!call->is_client) { - /* TODO(ctiller): cache common status values */ - char status_str[GPR_LTOA_MIN_BUFSIZE]; - data = call->requests[GRPC_IOREQ_SEND_CLOSE].data; - gpr_ltoa(data.send_close.status, status_str); - send_metadata( - call, - grpc_mdelem_from_metadata_strings( - call->metadata_context, - grpc_mdstr_ref(grpc_channel_get_status_string(call->channel)), - grpc_mdstr_from_string(call->metadata_context, status_str))); - if (data.send_close.details) { - send_metadata(call, - grpc_mdelem_from_metadata_strings( - call->metadata_context, - grpc_mdstr_ref( - grpc_channel_get_message_string(call->channel)), - grpc_mdstr_from_string(call->metadata_context, - data.send_close.details))); - } + case SEND_STATUS: + /* TODO(ctiller): cache common status values */ + data = call->requests[GRPC_IOREQ_SEND_CLOSE].data; + gpr_ltoa(data.send_status.code, status_str); + send_metadata( + call, + grpc_mdelem_from_metadata_strings( + call->metadata_context, + grpc_mdstr_ref(grpc_channel_get_status_string(call->channel)), + grpc_mdstr_from_string(call->metadata_context, status_str))); + if (data.send_status.details) { + send_metadata(call, + grpc_mdelem_from_metadata_strings( + call->metadata_context, + grpc_mdstr_ref( + grpc_channel_get_message_string(call->channel)), + grpc_mdstr_from_string(call->metadata_context, + data.send_status.details))); } + break; + case SEND_FINISH: op.type = GRPC_SEND_FINISH; op.dir = GRPC_CALL_DOWN; op.flags = 0; @@ -542,7 +556,7 @@ static grpc_call_error start_ioreq_error(grpc_call *call, size_t i; for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { if (mutated_ops & (1 << i)) { - call->requests[i].master = NULL; + call->requests[i].set = REQSET_EMPTY; } } return ret; @@ -555,35 +569,32 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, size_t i; gpr_uint32 have_ops = 0; grpc_ioreq_op op; - reqinfo *master = NULL; reqinfo *requests = call->requests; + reqinfo *master; grpc_ioreq_data data; + gpr_uint8 set; + + if (nreqs == 0) { + return GRPC_CALL_OK; + } + + set = reqs[0].op; + master = &requests[set]; for (i = 0; i < nreqs; i++) { op = reqs[i].op; - if (requests[op].master) { + if (requests[op].set < GRPC_IOREQ_OP_COUNT) { return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_TOO_MANY_OPERATIONS); - } - switch (requests[op].state) { - case REQ_INITIAL: - break; - case REQ_READY: - return start_ioreq_error(call, have_ops, - GRPC_CALL_ERROR_TOO_MANY_OPERATIONS); - case REQ_DONE: - return start_ioreq_error(call, have_ops, - GRPC_CALL_ERROR_ALREADY_INVOKED); - } - if (master == NULL) { - master = &requests[op]; + } else if (requests[op].set == REQSET_DONE) { + return start_ioreq_error(call, have_ops, + GRPC_CALL_ERROR_ALREADY_INVOKED); } have_ops |= 1 << op; data = reqs[i].data; - requests[op].state = REQ_READY; requests[op].data = data; - requests[op].master = master; + requests[op].set = set; } GPR_ASSERT(master != NULL); @@ -598,12 +609,10 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, switch (op) { default: break; - case GRPC_IOREQ_RECV_MESSAGES: - data.recv_messages->count = 0; - if (call->buffered_messages.count > 0 || call->read_closed) { - SWAP(grpc_byte_buffer_array, *data.recv_messages, - call->buffered_messages); - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); + case GRPC_IOREQ_RECV_MESSAGE: + *data.recv_message = grpc_bbq_pop(&call->incoming_queue); + if (*data.recv_message) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); } else { call->need_more_data = 1; } @@ -612,19 +621,18 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, } break; case GRPC_IOREQ_RECV_STATUS: - if (call->stream_closed && call->buffered_messages.count == 0) { + if (call->stream_closed) { finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); } break; - case GRPC_IOREQ_SEND_MESSAGES: + case GRPC_IOREQ_SEND_MESSAGE: if (call->stream_closed) { - finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGES, GRPC_OP_ERROR); + finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGE, GRPC_OP_ERROR); } - call->write_index = 0; break; case GRPC_IOREQ_SEND_CLOSE: - if (requests[GRPC_IOREQ_SEND_MESSAGES].state == REQ_INITIAL) { - requests[GRPC_IOREQ_SEND_MESSAGES].state = REQ_DONE; + if (requests[GRPC_IOREQ_SEND_MESSAGE].set == REQSET_EMPTY) { + requests[GRPC_IOREQ_SEND_MESSAGE].set = REQSET_DONE; } break; case GRPC_IOREQ_SEND_INITIAL_METADATA: @@ -1088,8 +1096,13 @@ void grpc_call_recv_message(grpc_call_element *elem, grpc_call *call = CALL_FROM_TOP_ELEM(elem); grpc_byte_buffer_array *dest; lock(call); - if (call->requests[GRPC_IOREQ_RECV_MESSAGES].master != NULL) { - dest = call->requests[GRPC_IOREQ_RECV_MESSAGES].data.recv_messages; + if (call->requests[GRPC_IOREQ_RECV_MESSAGE].master != NULL) { + if (call->requests[GRPC_IOREQ_RECV_MESSAGE].state != REQ_READY) { + call->requests[GRPC_IOREQ_RECV_MESSAGE].status = GRPC_OP_ERROR; + } else { + *call->requests[GRPC_IOREQ_RECV_MESSAGE].data.recv_message = byte_buffer; + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + } } else { dest = &call->buffered_messages; } diff --git a/src/core/surface/call.h b/src/core/surface/call.h index c130a13b81d..45816a312eb 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -38,6 +38,47 @@ #include "src/core/channel/metadata_buffer.h" #include +/* Primitive operation types - grpc_op's get rewritten into these */ +typedef enum { + GRPC_IOREQ_RECV_INITIAL_METADATA, + GRPC_IOREQ_RECV_MESSAGE, + GRPC_IOREQ_RECV_TRAILING_METADATA, + GRPC_IOREQ_RECV_STATUS, + GPRC_IOREQ_RECV_CLOSE, + GRPC_IOREQ_SEND_INITIAL_METADATA, + GRPC_IOREQ_SEND_MESSAGE, + GRPC_IOREQ_SEND_TRAILING_METADATA, + GRPC_IOREQ_SEND_STATUS, + GRPC_IOREQ_SEND_CLOSE, + GRPC_IOREQ_OP_COUNT +} grpc_ioreq_op; + +typedef struct { + grpc_status_code *code; + char **details; + size_t *details_capacity; +} grpc_recv_status_args; + +typedef union { + grpc_metadata_array *recv_metadata; + grpc_byte_buffer **recv_message; + grpc_recv_status_args recv_status; + struct { + size_t count; + grpc_metadata *metadata; + } send_metadata; + grpc_byte_buffer *send_message; + struct { + grpc_status_code code; + char *details; + } send_status; +} grpc_ioreq_data; + +typedef struct { + grpc_ioreq_op op; + grpc_ioreq_data data; +} grpc_ioreq; + typedef void (*grpc_ioreq_completion_func)(grpc_call *call, grpc_op_error status, void *user_data); diff --git a/test/core/echo/client.c b/test/core/echo/client.c index 32e85a1401a..7d895c3f19c 100644 --- a/test/core/echo/client.c +++ b/test/core/echo/client.c @@ -78,7 +78,7 @@ int main(int argc, char **argv) { GPR_ASSERT(argc == 2); channel = grpc_channel_create(argv[1], NULL); - call = grpc_channel_create_call_old( + call = grpc_channel_create_call( channel, "/foo", "localhost", gpr_time_add(gpr_time_from_seconds(5), gpr_now())); GPR_ASSERT(grpc_call_invoke(call, cq, (void *)1, (void *)1, 0) == diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c index 340fa039fd1..14db4495f22 100644 --- a/test/core/end2end/dualstack_socket_test.c +++ b/test/core/end2end/dualstack_socket_test.c @@ -112,7 +112,7 @@ void test_connect(const char *server_host, const char *client_host, int port, } /* Send a trivial request. */ - c = grpc_channel_create_call_old(client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call(client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke(c, client_cq, tag(2), tag(3), 0)); diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c index e4b4e4bb7d4..389a6429c48 100644 --- a/test/core/end2end/no_server_test.c +++ b/test/core/end2end/no_server_test.c @@ -56,7 +56,7 @@ int main(int argc, char **argv) { /* create a call, channel to a non existant server */ chan = grpc_channel_create("nonexistant:54321", NULL); - call = grpc_channel_create_call_old(chan, "/foo", "nonexistant", deadline); + call = grpc_channel_create_call(chan, "/foo", "nonexistant", deadline); GPR_ASSERT(grpc_call_invoke(call, cq, tag(2), tag(3), 0) == GRPC_CALL_OK); /* verify that all tags get completed */ cq_expect_client_metadata_read(cqv, tag(2), NULL); diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c index 3a71daa9a4c..8c00e86f7ed 100644 --- a/test/core/end2end/tests/cancel_after_accept.c +++ b/test/core/end2end/tests/cancel_after_accept.c @@ -113,8 +113,7 @@ static void test_cancel_after_accept(grpc_end2end_test_config config, cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c b/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c index b258dd4251f..416b4946689 100644 --- a/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c +++ b/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c @@ -113,8 +113,7 @@ static void test_cancel_after_accept_and_writes_closed( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c index 12de361383f..5dfb3f756ab 100644 --- a/test/core/end2end/tests/cancel_after_invoke.c +++ b/test/core/end2end/tests/cancel_after_invoke.c @@ -111,8 +111,7 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config, gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c index 7c706029a1c..ac816484fd6 100644 --- a/test/core/end2end/tests/cancel_before_invoke.c +++ b/test/core/end2end/tests/cancel_before_invoke.c @@ -109,8 +109,7 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config) { gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c)); diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c index 6b5194fb07f..5257ece297e 100644 --- a/test/core/end2end/tests/cancel_in_a_vacuum.c +++ b/test/core/end2end/tests/cancel_in_a_vacuum.c @@ -109,8 +109,7 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config, gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c)); diff --git a/test/core/end2end/tests/census_simple_request.c b/test/core/end2end/tests/census_simple_request.c index 1b442e9e4c3..cb37bf956d5 100644 --- a/test/core/end2end/tests/census_simple_request.c +++ b/test/core/end2end/tests/census_simple_request.c @@ -106,8 +106,7 @@ static void test_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); tag(1); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/disappearing_server.c b/test/core/end2end/tests/disappearing_server.c index eafda6132b5..50de3347b67 100644 --- a/test/core/end2end/tests/disappearing_server.c +++ b/test/core/end2end/tests/disappearing_server.c @@ -97,8 +97,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f, grpc_call *s; gpr_timespec deadline = five_seconds_time(); - c = grpc_channel_create_call_old(f->client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f->client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c b/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c index 2eb56517f7e..2f14c1b5652 100644 --- a/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c +++ b/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c @@ -111,8 +111,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c index 7ebd8e38b03..b918648cb14 100644 --- a/test/core/end2end/tests/graceful_server_shutdown.c +++ b/test/core/end2end/tests/graceful_server_shutdown.c @@ -110,8 +110,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c index ac7071a04bd..3ce661893c9 100644 --- a/test/core/end2end/tests/invoke_large_request.c +++ b/test/core/end2end/tests/invoke_large_request.c @@ -122,8 +122,7 @@ static void test_invoke_large_request(grpc_end2end_test_config config) { GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c index fc180fd9629..a18c0453c61 100644 --- a/test/core/end2end/tests/max_concurrent_streams.c +++ b/test/core/end2end/tests/max_concurrent_streams.c @@ -109,8 +109,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == @@ -182,11 +181,10 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { /* start two requests - ensuring that the second is not accepted until the first completes */ deadline = five_seconds_time(); - c1 = grpc_channel_create_call_old(f.client, "/alpha", "test.google.com", - deadline); + c1 = + grpc_channel_create_call(f.client, "/alpha", "test.google.com", deadline); GPR_ASSERT(c1); - c2 = grpc_channel_create_call_old(f.client, "/beta", "test.google.com", - deadline); + c2 = grpc_channel_create_call(f.client, "/beta", "test.google.com", deadline); GPR_ASSERT(c1); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c index e8adb82c19d..adaab4ecd5e 100644 --- a/test/core/end2end/tests/ping_pong_streaming.c +++ b/test/core/end2end/tests/ping_pong_streaming.c @@ -118,8 +118,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, cq_verifier *v_server = cq_verifier_create(f.server_cq); gpr_log(GPR_INFO, "testing with %d message pairs.", messages); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c index 49720a7bea4..c3cf2d7123c 100644 --- a/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c @@ -137,8 +137,7 @@ static void test_request_response_with_metadata_and_payload( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); /* add multiple metadata */ diff --git a/test/core/end2end/tests/request_response_with_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_metadata_and_payload.c index 14e791ae8ee..fb7b1553676 100644 --- a/test/core/end2end/tests/request_response_with_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_metadata_and_payload.c @@ -128,8 +128,7 @@ static void test_request_response_with_metadata_and_payload( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); /* add multiple metadata */ diff --git a/test/core/end2end/tests/request_response_with_payload.c b/test/core/end2end/tests/request_response_with_payload.c index ee1e52e54c4..87ed30c8f82 100644 --- a/test/core/end2end/tests/request_response_with_payload.c +++ b/test/core/end2end/tests/request_response_with_payload.c @@ -121,8 +121,7 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) { GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c index 65f890b4b98..c1f0e499d66 100644 --- a/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c @@ -130,8 +130,7 @@ static void test_request_response_with_metadata_and_payload( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); /* add multiple metadata */ diff --git a/test/core/end2end/tests/request_with_large_metadata.c b/test/core/end2end/tests/request_with_large_metadata.c index 438f2ef1d14..543bb999be3 100644 --- a/test/core/end2end/tests/request_with_large_metadata.c +++ b/test/core/end2end/tests/request_with_large_metadata.c @@ -121,8 +121,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { meta.value[large_size] = 0; meta.value_length = large_size; - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); /* add the metadata */ diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c index 31d79df5049..a2b5cfa7500 100644 --- a/test/core/end2end/tests/request_with_payload.c +++ b/test/core/end2end/tests/request_with_payload.c @@ -116,8 +116,7 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) { /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c index 1222d167ded..7e7ab54523f 100644 --- a/test/core/end2end/tests/simple_delayed_request.c +++ b/test/core/end2end/tests/simple_delayed_request.c @@ -103,8 +103,7 @@ static void simple_delayed_request_body(grpc_end2end_test_config config, config.init_client(f, client_args); - c = grpc_channel_create_call_old(f->client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f->client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c index 64a8340d54b..cbade1252a7 100644 --- a/test/core/end2end/tests/simple_request.c +++ b/test/core/end2end/tests/simple_request.c @@ -110,8 +110,7 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == @@ -157,8 +156,7 @@ static void simple_request_body2(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/end2end/tests/thread_stress.c b/test/core/end2end/tests/thread_stress.c index 7e235be4f41..9d40ed16a8b 100644 --- a/test/core/end2end/tests/thread_stress.c +++ b/test/core/end2end/tests/thread_stress.c @@ -108,7 +108,7 @@ static void drain_cq(int client, grpc_completion_queue *cq) { static void start_request(void) { gpr_slice slice = gpr_slice_malloc(100); grpc_byte_buffer *buf; - grpc_call *call = grpc_channel_create_call_old( + grpc_call *call = grpc_channel_create_call( g_fixture.client, "/Foo", "test.google.com", g_test_end_time); memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice)); diff --git a/test/core/end2end/tests/writes_done_hangs_with_pending_read.c b/test/core/end2end/tests/writes_done_hangs_with_pending_read.c index fb2fbdd092b..f3ec4ae4f10 100644 --- a/test/core/end2end/tests/writes_done_hangs_with_pending_read.c +++ b/test/core/end2end/tests/writes_done_hangs_with_pending_read.c @@ -124,8 +124,7 @@ static void test_writes_done_hangs_with_pending_read( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", - deadline); + c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == diff --git a/test/core/fling/client.c b/test/core/fling/client.c index fa8f2639413..6f197f1cd7e 100644 --- a/test/core/fling/client.c +++ b/test/core/fling/client.c @@ -53,7 +53,7 @@ static grpc_call *call; static void init_ping_pong_request(void) {} static void step_ping_pong_request(void) { - call = grpc_channel_create_call_old(channel, "/Reflector/reflectUnary", + call = grpc_channel_create_call(channel, "/Reflector/reflectUnary", "localhost", gpr_inf_future); GPR_ASSERT(grpc_call_invoke(call, cq, (void *)1, (void *)1, GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); @@ -71,7 +71,7 @@ static void step_ping_pong_request(void) { } static void init_ping_pong_stream(void) { - call = grpc_channel_create_call_old(channel, "/Reflector/reflectStream", + call = grpc_channel_create_call(channel, "/Reflector/reflectStream", "localhost", gpr_inf_future); GPR_ASSERT(grpc_call_invoke(call, cq, (void *)1, (void *)1, 0) == GRPC_CALL_OK); diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index c43ac7c2428..9b9f0202d6d 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -51,7 +51,7 @@ int main(int argc, char **argv) { chan = grpc_lame_client_channel_create(); GPR_ASSERT(chan); - call = grpc_channel_create_call_old( + call = grpc_channel_create_call( chan, "/Foo", "anywhere", gpr_time_add(gpr_now(), gpr_time_from_seconds(100))); GPR_ASSERT(call); From 05140d032bf8f527ae93e92ca41684be998562c5 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 16:43:40 -0800 Subject: [PATCH 62/93] Made call.c compile again --- src/core/surface/byte_buffer_queue.h | 2 + src/core/surface/call.c | 102 ++++++++++++--------------- src/core/surface/call.h | 2 +- 3 files changed, 48 insertions(+), 58 deletions(-) diff --git a/src/core/surface/byte_buffer_queue.h b/src/core/surface/byte_buffer_queue.h index ffd2616d9d7..01cc06077ed 100644 --- a/src/core/surface/byte_buffer_queue.h +++ b/src/core/surface/byte_buffer_queue.h @@ -49,5 +49,7 @@ typedef struct { } grpc_byte_buffer_queue; grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q); +int grpc_bbq_empty(grpc_byte_buffer_queue *q); +void grpc_bbq_push(grpc_byte_buffer_queue *q, grpc_byte_buffer *bb); #endif /* __GRPC_INTERNAL_SURFACE_BYTE_BUFFER_QUEUE_H__ */ diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 4f8ac6193a9..e2e8fe23a52 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -58,7 +58,11 @@ typedef struct { /* input buffers */ grpc_metadata_array initial_md_in; grpc_metadata_array trailing_md_in; - grpc_recv_status status_in; + + size_t details_capacity; + char *details; + grpc_status_code status; + size_t msg_in_read_idx; grpc_byte_buffer *msg_in; @@ -770,9 +774,9 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, static void maybe_finish_legacy(grpc_call *call) { legacy_state *ls = get_legacy_state(call); - if (ls->got_status && ls->msg_in_read_idx == ls->msg_in.count) { + if (ls->got_status) { grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, - ls->status_in.status, ls->status_in.details, + ls->status, ls->details, ls->trailing_md_in.metadata, ls->trailing_md_in.count); } } @@ -811,7 +815,7 @@ static void finish_send_metadata(grpc_call *call, grpc_op_error status, grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, void *metadata_read_tag, void *finished_tag, gpr_uint32 flags) { - grpc_ioreq reqs[2]; + grpc_ioreq reqs[3]; legacy_state *ls; grpc_call_error err; @@ -840,7 +844,10 @@ grpc_call_error grpc_call_invoke(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 = &ls->status_in; + 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, 2, finish_status, NULL); if (err != GRPC_CALL_OK) goto done; @@ -852,22 +859,28 @@ done: grpc_call_error grpc_call_server_accept(grpc_call *call, grpc_completion_queue *cq, void *finished_tag) { - grpc_ioreq req; + grpc_ioreq reqs[2]; grpc_call_error err; + legacy_state *ls; /* inform the completion queue of an incoming operation (corresponding to finished_tag) */ grpc_cq_begin_op(cq, call, GRPC_FINISHED); lock(call); + ls = get_legacy_state(call); + err = bind_cq(call, cq); if (err != GRPC_CALL_OK) return err; - get_legacy_state(call)->finished_tag = finished_tag; + ls->finished_tag = finished_tag; - req.op = GRPC_IOREQ_RECV_STATUS; - req.data.recv_status = &get_legacy_state(call)->status_in; - err = start_ioreq(call, &req, 1, finish_status, NULL); + 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[1].op = GRPC_IOREQ_RECV_CLOSE; + err = start_ioreq(call, reqs, 2, finish_status, NULL); unlock(call); return err; } @@ -906,15 +919,11 @@ static void finish_read_event(void *p, grpc_op_error error) { static void finish_read(grpc_call *call, grpc_op_error error, void *tag) { legacy_state *ls; + grpc_byte_buffer *msg; lock(call); ls = get_legacy_state(call); - if (ls->msg_in.count == 0) { - grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, NULL); - } else { - grpc_byte_buffer *msg = ls->msg_in.buffers[ls->msg_in_read_idx++]; - grpc_cq_end_read(call->cq, tag, call, finish_read_event, msg, msg); - maybe_finish_legacy(call); - } + msg = ls->msg_in; + grpc_cq_end_read(call->cq, tag, call, finish_read_event, msg, msg); unlock(call); } @@ -922,24 +931,14 @@ grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { legacy_state *ls; grpc_ioreq req; grpc_call_error err; - grpc_byte_buffer *msg; grpc_cq_begin_op(call->cq, call, GRPC_READ); lock(call); ls = get_legacy_state(call); - - if (ls->msg_in_read_idx == ls->msg_in.count) { - ls->msg_in_read_idx = 0; - req.op = GRPC_IOREQ_RECV_MESSAGES; - req.data.recv_messages = &ls->msg_in; - err = start_ioreq(call, &req, 1, finish_read, tag); - } else { - err = GRPC_CALL_OK; - msg = ls->msg_in.buffers[ls->msg_in_read_idx++]; - grpc_cq_end_read(call->cq, tag, call, finish_read_event, msg, msg); - maybe_finish_legacy(call); - } + req.op = GRPC_IOREQ_RECV_MESSAGE; + req.data.recv_message = &ls->msg_in; + err = start_ioreq(call, &req, 1, finish_read, tag); unlock(call); return err; } @@ -963,9 +962,8 @@ grpc_call_error grpc_call_start_write(grpc_call *call, lock(call); ls = get_legacy_state(call); ls->msg_out = grpc_byte_buffer_copy(byte_buffer); - req.op = GRPC_IOREQ_SEND_MESSAGES; - req.data.send_messages.count = 1; - req.data.send_messages.messages = &ls->msg_out; + req.op = GRPC_IOREQ_SEND_MESSAGE; + req.data.send_message = ls->msg_out; err = start_ioreq(call, &req, 1, finish_write, tag); unlock(call); @@ -992,7 +990,7 @@ grpc_call_error grpc_call_writes_done(grpc_call *call, void *tag) { grpc_call_error grpc_call_start_write_status(grpc_call *call, grpc_status_code status, const char *details, void *tag) { - grpc_ioreq reqs[2]; + grpc_ioreq reqs[3]; grpc_call_error err; legacy_state *ls; grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); @@ -1003,8 +1001,9 @@ grpc_call_error grpc_call_start_write_status(grpc_call *call, reqs[0].data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; reqs[0].data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; reqs[1].op = GRPC_IOREQ_SEND_CLOSE; - reqs[1].data.send_close.status = status; - reqs[1].data.send_close.details = details; + reqs[1].data.send_status.code = status; + /* MEMLEAK */ + reqs[1].data.send_status.details = gpr_strdup(details); err = start_ioreq(call, reqs, 2, finish_finish, tag); unlock(call); @@ -1044,7 +1043,7 @@ void grpc_call_read_closed(grpc_call_element *elem) { lock(call); GPR_ASSERT(!call->read_closed); call->read_closed = 1; - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); unlock(call); @@ -1056,12 +1055,12 @@ void grpc_call_stream_closed(grpc_call_element *elem) { GPR_ASSERT(!call->stream_closed); if (!call->read_closed) { call->read_closed = 1; - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); } call->stream_closed = 1; - if (call->buffered_messages.count == 0) { + if (grpc_bbq_empty(&call->incoming_queue)) { finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); } unlock(call); @@ -1094,25 +1093,14 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { void grpc_call_recv_message(grpc_call_element *elem, grpc_byte_buffer *byte_buffer) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); - grpc_byte_buffer_array *dest; lock(call); - if (call->requests[GRPC_IOREQ_RECV_MESSAGE].master != NULL) { - if (call->requests[GRPC_IOREQ_RECV_MESSAGE].state != REQ_READY) { - call->requests[GRPC_IOREQ_RECV_MESSAGE].status = GRPC_OP_ERROR; - } else { - *call->requests[GRPC_IOREQ_RECV_MESSAGE].data.recv_message = byte_buffer; - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - } + if (call->requests[GRPC_IOREQ_RECV_MESSAGE].set < GRPC_IOREQ_OP_COUNT) { + /* there's an outstanding read */ + *call->requests[GRPC_IOREQ_RECV_MESSAGE].data.recv_message = byte_buffer; + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); } else { - dest = &call->buffered_messages; - } - if (dest->count == dest->capacity) { - dest->capacity = GPR_MAX(dest->capacity + 1, dest->capacity * 3 / 2); - dest->buffers = - gpr_realloc(dest->buffers, sizeof(grpc_byte_buffer *) * dest->capacity); + grpc_bbq_push(&call->incoming_queue, byte_buffer); } - dest->buffers[dest->count++] = byte_buffer; - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGES, GRPC_OP_OK); unlock(call); } @@ -1131,13 +1119,13 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { grpc_mdelem_unref(md); } else { if (!call->got_initial_metadata) { - dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].state == REQ_READY + dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].set < GRPC_IOREQ_OP_COUNT ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] .data.recv_metadata : &call->buffered_initial_metadata; } else { dest = - call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].state == REQ_READY + call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].set < GRPC_IOREQ_OP_COUNT ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] .data.recv_metadata : &call->buffered_trailing_metadata; diff --git a/src/core/surface/call.h b/src/core/surface/call.h index 45816a312eb..936fb29f2ef 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -44,7 +44,7 @@ typedef enum { GRPC_IOREQ_RECV_MESSAGE, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_IOREQ_RECV_STATUS, - GPRC_IOREQ_RECV_CLOSE, + GRPC_IOREQ_RECV_CLOSE, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_IOREQ_SEND_MESSAGE, GRPC_IOREQ_SEND_TRAILING_METADATA, From 4741adeb8db8076a6e51fe5f66d3413bf0d3728b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 16:45:19 -0800 Subject: [PATCH 63/93] Cleanup --- include/grpc/grpc.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 0ebfad88249..47d2e44e80e 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -239,11 +239,6 @@ typedef struct { grpc_metadata *metadata; } grpc_metadata_array; -typedef struct { - grpc_status_code status; - const char *details; -} grpc_recv_status; - typedef struct { const char *method; const char *host; From ffa4a59f2343c2664a266b3af352b0365e0deb7d Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 16:47:28 -0800 Subject: [PATCH 64/93] Fix up function signatures --- src/core/surface/channel.c | 2 +- src/core/surface/server.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index c33ea923e82..4839a464277 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -74,7 +74,7 @@ grpc_channel *grpc_channel_create_from_filters( static void do_nothing(void *ignored, grpc_op_error error) {} -grpc_call *grpc_channel_create_call_old(grpc_channel *channel, +grpc_call *grpc_channel_create_call(grpc_channel *channel, const char *method, const char *host, gpr_timespec absolute_deadline) { grpc_call *call; diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 05cb2181255..769b68c997d 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -710,9 +710,9 @@ static void begin_request(grpc_server *server, grpc_completion_queue *cq, } grpc_call_error grpc_server_request_call(grpc_server *server, - grpc_completion_queue *cq, grpc_call_details *details, grpc_metadata_array *initial_metadata, + grpc_completion_queue *cq, void *tag) { grpc_cq_begin_op(cq, NULL, GRPC_IOREQ); return queue_call_request(server, cq, initial_metadata, begin_request, tag); From 4450db2ac982fbabcbc46c5e39bffd24370f2df4 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 16:49:22 -0800 Subject: [PATCH 65/93] Add bbq --- Makefile | 351 +++++++++--------- build.json | 162 ++++---- tools/run_tests/tests.json | 24 +- vsprojects/vs2013/grpc.vcxproj | 5 +- vsprojects/vs2013/grpc.vcxproj.filters | 10 +- vsprojects/vs2013/grpc_unsecure.vcxproj | 5 +- .../vs2013/grpc_unsecure.vcxproj.filters | 10 +- 7 files changed, 296 insertions(+), 271 deletions(-) diff --git a/Makefile b/Makefile index 92889092693..c8b5ab935f8 100644 --- a/Makefile +++ b/Makefile @@ -359,6 +359,9 @@ hpack_table_test: bins/$(CONFIG)/hpack_table_test httpcli_format_request_test: bins/$(CONFIG)/httpcli_format_request_test httpcli_parser_test: bins/$(CONFIG)/httpcli_parser_test httpcli_test: bins/$(CONFIG)/httpcli_test +json_rewrite: bins/$(CONFIG)/json_rewrite +json_rewrite_test: bins/$(CONFIG)/json_rewrite_test +json_test: bins/$(CONFIG)/json_test lame_client_test: bins/$(CONFIG)/lame_client_test low_level_ping_pong_benchmark: bins/$(CONFIG)/low_level_ping_pong_benchmark message_compress_test: bins/$(CONFIG)/message_compress_test @@ -376,23 +379,20 @@ time_averaged_stats_test: bins/$(CONFIG)/time_averaged_stats_test time_test: bins/$(CONFIG)/time_test timeout_encoding_test: bins/$(CONFIG)/timeout_encoding_test transport_metadata_test: bins/$(CONFIG)/transport_metadata_test -json_test: bins/$(CONFIG)/json_test -json_rewrite: bins/$(CONFIG)/json_rewrite -json_rewrite_test: bins/$(CONFIG)/json_rewrite_test channel_arguments_test: bins/$(CONFIG)/channel_arguments_test cpp_plugin: bins/$(CONFIG)/cpp_plugin credentials_test: bins/$(CONFIG)/credentials_test end2end_test: bins/$(CONFIG)/end2end_test interop_client: bins/$(CONFIG)/interop_client interop_server: bins/$(CONFIG)/interop_server -tips_client: bins/$(CONFIG)/tips_client -tips_client_test: bins/$(CONFIG)/tips_client_test qps_client: bins/$(CONFIG)/qps_client qps_server: bins/$(CONFIG)/qps_server ruby_plugin: bins/$(CONFIG)/ruby_plugin status_test: bins/$(CONFIG)/status_test sync_client_async_server_test: bins/$(CONFIG)/sync_client_async_server_test thread_pool_test: bins/$(CONFIG)/thread_pool_test +tips_client: bins/$(CONFIG)/tips_client +tips_client_test: bins/$(CONFIG)/tips_client_test chttp2_fake_security_cancel_after_accept_test: bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test chttp2_fake_security_cancel_after_accept_and_writes_closed_test: bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test chttp2_fake_security_cancel_after_invoke_test: bins/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test @@ -570,9 +570,9 @@ privatelibs_cxx: libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libtips_cl buildtests: buildtests_c buildtests_cxx -buildtests_c: privatelibs_c bins/$(CONFIG)/alarm_heap_test bins/$(CONFIG)/alarm_list_test bins/$(CONFIG)/alarm_test bins/$(CONFIG)/alpn_test bins/$(CONFIG)/bin_encoder_test bins/$(CONFIG)/census_hash_table_test bins/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test bins/$(CONFIG)/census_statistics_multiple_writers_test bins/$(CONFIG)/census_statistics_performance_test bins/$(CONFIG)/census_statistics_quick_test bins/$(CONFIG)/census_statistics_small_log_test bins/$(CONFIG)/census_stub_test bins/$(CONFIG)/census_window_stats_test bins/$(CONFIG)/chttp2_status_conversion_test bins/$(CONFIG)/chttp2_stream_encoder_test bins/$(CONFIG)/chttp2_stream_map_test bins/$(CONFIG)/chttp2_transport_end2end_test bins/$(CONFIG)/dualstack_socket_test bins/$(CONFIG)/echo_client bins/$(CONFIG)/echo_server bins/$(CONFIG)/echo_test bins/$(CONFIG)/fd_posix_test bins/$(CONFIG)/fling_client bins/$(CONFIG)/fling_server bins/$(CONFIG)/fling_stream_test bins/$(CONFIG)/fling_test bins/$(CONFIG)/gpr_cancellable_test bins/$(CONFIG)/gpr_cmdline_test bins/$(CONFIG)/gpr_histogram_test bins/$(CONFIG)/gpr_host_port_test bins/$(CONFIG)/gpr_log_test bins/$(CONFIG)/gpr_slice_buffer_test bins/$(CONFIG)/gpr_slice_test bins/$(CONFIG)/gpr_string_test bins/$(CONFIG)/gpr_sync_test bins/$(CONFIG)/gpr_thd_test bins/$(CONFIG)/gpr_time_test bins/$(CONFIG)/gpr_useful_test bins/$(CONFIG)/grpc_base64_test bins/$(CONFIG)/grpc_byte_buffer_reader_test bins/$(CONFIG)/grpc_channel_stack_test bins/$(CONFIG)/grpc_completion_queue_test bins/$(CONFIG)/grpc_credentials_test bins/$(CONFIG)/grpc_json_token_test bins/$(CONFIG)/grpc_stream_op_test bins/$(CONFIG)/hpack_parser_test bins/$(CONFIG)/hpack_table_test bins/$(CONFIG)/httpcli_format_request_test bins/$(CONFIG)/httpcli_parser_test bins/$(CONFIG)/httpcli_test bins/$(CONFIG)/lame_client_test bins/$(CONFIG)/message_compress_test bins/$(CONFIG)/metadata_buffer_test bins/$(CONFIG)/murmur_hash_test bins/$(CONFIG)/no_server_test bins/$(CONFIG)/poll_kick_posix_test bins/$(CONFIG)/resolve_address_test bins/$(CONFIG)/secure_endpoint_test bins/$(CONFIG)/sockaddr_utils_test bins/$(CONFIG)/tcp_client_posix_test bins/$(CONFIG)/tcp_posix_test bins/$(CONFIG)/tcp_server_posix_test bins/$(CONFIG)/time_averaged_stats_test bins/$(CONFIG)/time_test bins/$(CONFIG)/timeout_encoding_test bins/$(CONFIG)/transport_metadata_test bins/$(CONFIG)/json_test bins/$(CONFIG)/json_rewrite bins/$(CONFIG)/json_rewrite_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test bins/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test bins/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_fake_security_census_simple_request_test bins/$(CONFIG)/chttp2_fake_security_disappearing_server_test bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_fake_security_invoke_large_request_test bins/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test bins/$(CONFIG)/chttp2_fake_security_no_op_test bins/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test bins/$(CONFIG)/chttp2_fake_security_simple_request_test bins/$(CONFIG)/chttp2_fake_security_thread_stress_test bins/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_fullstack_no_op_test bins/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_fullstack_simple_request_test bins/$(CONFIG)/chttp2_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test bins/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test bins/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_socket_pair_census_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_disappearing_server_test bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test bins/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test bins/$(CONFIG)/chttp2_socket_pair_no_op_test bins/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test bins/$(CONFIG)/chttp2_socket_pair_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_thread_stress_test bins/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test +buildtests_c: privatelibs_c bins/$(CONFIG)/alarm_heap_test bins/$(CONFIG)/alarm_list_test bins/$(CONFIG)/alarm_test bins/$(CONFIG)/alpn_test bins/$(CONFIG)/bin_encoder_test bins/$(CONFIG)/census_hash_table_test bins/$(CONFIG)/census_statistics_multiple_writers_circular_buffer_test bins/$(CONFIG)/census_statistics_multiple_writers_test bins/$(CONFIG)/census_statistics_performance_test bins/$(CONFIG)/census_statistics_quick_test bins/$(CONFIG)/census_statistics_small_log_test bins/$(CONFIG)/census_stub_test bins/$(CONFIG)/census_window_stats_test bins/$(CONFIG)/chttp2_status_conversion_test bins/$(CONFIG)/chttp2_stream_encoder_test bins/$(CONFIG)/chttp2_stream_map_test bins/$(CONFIG)/chttp2_transport_end2end_test bins/$(CONFIG)/dualstack_socket_test bins/$(CONFIG)/echo_client bins/$(CONFIG)/echo_server bins/$(CONFIG)/echo_test bins/$(CONFIG)/fd_posix_test bins/$(CONFIG)/fling_client bins/$(CONFIG)/fling_server bins/$(CONFIG)/fling_stream_test bins/$(CONFIG)/fling_test bins/$(CONFIG)/gpr_cancellable_test bins/$(CONFIG)/gpr_cmdline_test bins/$(CONFIG)/gpr_histogram_test bins/$(CONFIG)/gpr_host_port_test bins/$(CONFIG)/gpr_log_test bins/$(CONFIG)/gpr_slice_buffer_test bins/$(CONFIG)/gpr_slice_test bins/$(CONFIG)/gpr_string_test bins/$(CONFIG)/gpr_sync_test bins/$(CONFIG)/gpr_thd_test bins/$(CONFIG)/gpr_time_test bins/$(CONFIG)/gpr_useful_test bins/$(CONFIG)/grpc_base64_test bins/$(CONFIG)/grpc_byte_buffer_reader_test bins/$(CONFIG)/grpc_channel_stack_test bins/$(CONFIG)/grpc_completion_queue_test bins/$(CONFIG)/grpc_credentials_test bins/$(CONFIG)/grpc_json_token_test bins/$(CONFIG)/grpc_stream_op_test bins/$(CONFIG)/hpack_parser_test bins/$(CONFIG)/hpack_table_test bins/$(CONFIG)/httpcli_format_request_test bins/$(CONFIG)/httpcli_parser_test bins/$(CONFIG)/httpcli_test bins/$(CONFIG)/json_rewrite bins/$(CONFIG)/json_rewrite_test bins/$(CONFIG)/json_test bins/$(CONFIG)/lame_client_test bins/$(CONFIG)/message_compress_test bins/$(CONFIG)/metadata_buffer_test bins/$(CONFIG)/murmur_hash_test bins/$(CONFIG)/no_server_test bins/$(CONFIG)/poll_kick_posix_test bins/$(CONFIG)/resolve_address_test bins/$(CONFIG)/secure_endpoint_test bins/$(CONFIG)/sockaddr_utils_test bins/$(CONFIG)/tcp_client_posix_test bins/$(CONFIG)/tcp_posix_test bins/$(CONFIG)/tcp_server_posix_test bins/$(CONFIG)/time_averaged_stats_test bins/$(CONFIG)/time_test bins/$(CONFIG)/timeout_encoding_test bins/$(CONFIG)/transport_metadata_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_fake_security_cancel_after_invoke_test bins/$(CONFIG)/chttp2_fake_security_cancel_before_invoke_test bins/$(CONFIG)/chttp2_fake_security_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_fake_security_census_simple_request_test bins/$(CONFIG)/chttp2_fake_security_disappearing_server_test bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_fake_security_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_fake_security_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_fake_security_invoke_large_request_test bins/$(CONFIG)/chttp2_fake_security_max_concurrent_streams_test bins/$(CONFIG)/chttp2_fake_security_no_op_test bins/$(CONFIG)/chttp2_fake_security_ping_pong_streaming_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_payload_test bins/$(CONFIG)/chttp2_fake_security_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_fake_security_simple_delayed_request_test bins/$(CONFIG)/chttp2_fake_security_simple_request_test bins/$(CONFIG)/chttp2_fake_security_thread_stress_test bins/$(CONFIG)/chttp2_fake_security_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_fullstack_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_fullstack_no_op_test bins/$(CONFIG)/chttp2_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_fullstack_simple_request_test bins/$(CONFIG)/chttp2_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_no_op_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_simple_ssl_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_after_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_before_invoke_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_census_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_disappearing_server_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_invoke_large_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_max_concurrent_streams_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_no_op_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_ping_pong_streaming_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_delayed_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_simple_request_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_thread_stress_test bins/$(CONFIG)/chttp2_simple_ssl_with_oauth2_fullstack_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_socket_pair_cancel_after_invoke_test bins/$(CONFIG)/chttp2_socket_pair_cancel_before_invoke_test bins/$(CONFIG)/chttp2_socket_pair_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_socket_pair_census_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_disappearing_server_test bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_socket_pair_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_socket_pair_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_socket_pair_invoke_large_request_test bins/$(CONFIG)/chttp2_socket_pair_max_concurrent_streams_test bins/$(CONFIG)/chttp2_socket_pair_no_op_test bins/$(CONFIG)/chttp2_socket_pair_ping_pong_streaming_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_payload_test bins/$(CONFIG)/chttp2_socket_pair_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_simple_delayed_request_test bins/$(CONFIG)/chttp2_socket_pair_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_thread_stress_test bins/$(CONFIG)/chttp2_socket_pair_writes_done_hangs_with_pending_read_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_accept_and_writes_closed_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_after_invoke_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_before_invoke_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_cancel_in_a_vacuum_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_census_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_disappearing_server_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_inflight_calls_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_early_server_shutdown_finishes_tags_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_graceful_server_shutdown_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_invoke_large_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_max_concurrent_streams_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_no_op_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_ping_pong_streaming_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_binary_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_request_response_with_trailing_metadata_and_payload_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_delayed_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_simple_request_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_thread_stress_test bins/$(CONFIG)/chttp2_socket_pair_one_byte_at_a_time_writes_done_hangs_with_pending_read_test -buildtests_cxx: privatelibs_cxx bins/$(CONFIG)/channel_arguments_test bins/$(CONFIG)/credentials_test bins/$(CONFIG)/end2end_test bins/$(CONFIG)/interop_client bins/$(CONFIG)/interop_server bins/$(CONFIG)/tips_client bins/$(CONFIG)/tips_client_test bins/$(CONFIG)/qps_client bins/$(CONFIG)/qps_server bins/$(CONFIG)/status_test bins/$(CONFIG)/sync_client_async_server_test bins/$(CONFIG)/thread_pool_test +buildtests_cxx: privatelibs_cxx bins/$(CONFIG)/channel_arguments_test bins/$(CONFIG)/credentials_test bins/$(CONFIG)/end2end_test bins/$(CONFIG)/interop_client bins/$(CONFIG)/interop_server bins/$(CONFIG)/qps_client bins/$(CONFIG)/qps_server bins/$(CONFIG)/status_test bins/$(CONFIG)/sync_client_async_server_test bins/$(CONFIG)/thread_pool_test bins/$(CONFIG)/tips_client bins/$(CONFIG)/tips_client_test test: test_c test_cxx @@ -669,6 +669,8 @@ test_c: buildtests_c $(Q) ./bins/$(CONFIG)/httpcli_parser_test || ( echo test httpcli_parser_test failed ; exit 1 ) $(E) "[RUN] Testing httpcli_test" $(Q) ./bins/$(CONFIG)/httpcli_test || ( echo test httpcli_test failed ; exit 1 ) + $(E) "[RUN] Testing json_test" + $(Q) ./bins/$(CONFIG)/json_test || ( echo test json_test failed ; exit 1 ) $(E) "[RUN] Testing lame_client_test" $(Q) ./bins/$(CONFIG)/lame_client_test || ( echo test lame_client_test failed ; exit 1 ) $(E) "[RUN] Testing message_compress_test" @@ -701,8 +703,6 @@ test_c: buildtests_c $(Q) ./bins/$(CONFIG)/timeout_encoding_test || ( echo test timeout_encoding_test failed ; exit 1 ) $(E) "[RUN] Testing transport_metadata_test" $(Q) ./bins/$(CONFIG)/transport_metadata_test || ( echo test transport_metadata_test failed ; exit 1 ) - $(E) "[RUN] Testing json_test" - $(Q) ./bins/$(CONFIG)/json_test || ( echo test json_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fake_security_cancel_after_accept_test" $(Q) ./bins/$(CONFIG)/chttp2_fake_security_cancel_after_accept_test || ( echo test chttp2_fake_security_cancel_after_accept_test failed ; exit 1 ) $(E) "[RUN] Testing chttp2_fake_security_cancel_after_accept_and_writes_closed_test" @@ -976,8 +976,6 @@ test_cxx: buildtests_cxx $(Q) ./bins/$(CONFIG)/credentials_test || ( echo test credentials_test failed ; exit 1 ) $(E) "[RUN] Testing end2end_test" $(Q) ./bins/$(CONFIG)/end2end_test || ( echo test end2end_test failed ; exit 1 ) - $(E) "[RUN] Testing tips_client_test" - $(Q) ./bins/$(CONFIG)/tips_client_test || ( echo test tips_client_test failed ; exit 1 ) $(E) "[RUN] Testing qps_client" $(Q) ./bins/$(CONFIG)/qps_client || ( echo test qps_client failed ; exit 1 ) $(E) "[RUN] Testing qps_server" @@ -988,6 +986,8 @@ test_cxx: buildtests_cxx $(Q) ./bins/$(CONFIG)/sync_client_async_server_test || ( echo test sync_client_async_server_test failed ; exit 1 ) $(E) "[RUN] Testing thread_pool_test" $(Q) ./bins/$(CONFIG)/thread_pool_test || ( echo test thread_pool_test failed ; exit 1 ) + $(E) "[RUN] Testing tips_client_test" + $(Q) ./bins/$(CONFIG)/tips_client_test || ( echo test tips_client_test failed ; exit 1 ) tools: privatelibs bins/$(CONFIG)/gen_hpack_tables bins/$(CONFIG)/grpc_fetch_oauth2 @@ -1435,6 +1435,7 @@ LIBGRPC_SRC = \ src/core/statistics/hash_table.c \ src/core/statistics/window_stats.c \ src/core/surface/byte_buffer.c \ + src/core/surface/byte_buffer_queue.c \ src/core/surface/byte_buffer_reader.c \ src/core/surface/call.c \ src/core/surface/channel.c \ @@ -1561,6 +1562,7 @@ src/core/statistics/census_tracing.c: $(OPENSSL_DEP) src/core/statistics/hash_table.c: $(OPENSSL_DEP) src/core/statistics/window_stats.c: $(OPENSSL_DEP) src/core/surface/byte_buffer.c: $(OPENSSL_DEP) +src/core/surface/byte_buffer_queue.c: $(OPENSSL_DEP) src/core/surface/byte_buffer_reader.c: $(OPENSSL_DEP) src/core/surface/call.c: $(OPENSSL_DEP) src/core/surface/channel.c: $(OPENSSL_DEP) @@ -1709,6 +1711,7 @@ objs/$(CONFIG)/src/core/statistics/census_tracing.o: objs/$(CONFIG)/src/core/statistics/hash_table.o: objs/$(CONFIG)/src/core/statistics/window_stats.o: objs/$(CONFIG)/src/core/surface/byte_buffer.o: +objs/$(CONFIG)/src/core/surface/byte_buffer_queue.o: objs/$(CONFIG)/src/core/surface/byte_buffer_reader.o: objs/$(CONFIG)/src/core/surface/call.o: objs/$(CONFIG)/src/core/surface/channel.o: @@ -1876,6 +1879,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/statistics/hash_table.c \ src/core/statistics/window_stats.c \ src/core/surface/byte_buffer.c \ + src/core/surface/byte_buffer_queue.c \ src/core/surface/byte_buffer_reader.c \ src/core/surface/call.c \ src/core/surface/channel.c \ @@ -2007,6 +2011,7 @@ objs/$(CONFIG)/src/core/statistics/census_tracing.o: objs/$(CONFIG)/src/core/statistics/hash_table.o: objs/$(CONFIG)/src/core/statistics/window_stats.o: objs/$(CONFIG)/src/core/surface/byte_buffer.o: +objs/$(CONFIG)/src/core/surface/byte_buffer_queue.o: objs/$(CONFIG)/src/core/surface/byte_buffer_reader.o: objs/$(CONFIG)/src/core/surface/call.o: objs/$(CONFIG)/src/core/surface/channel.o: @@ -2186,9 +2191,9 @@ objs/$(CONFIG)/src/cpp/util/time.o: LIBGRPC++_TEST_UTIL_SRC = \ - gens/test/cpp/util/messages.pb.cc \ gens/test/cpp/util/echo.pb.cc \ gens/test/cpp/util/echo_duplicate.pb.cc \ + gens/test/cpp/util/messages.pb.cc \ test/cpp/end2end/async_test_server.cc \ test/cpp/util/create_test_channel.cc \ @@ -2205,9 +2210,9 @@ libs/$(CONFIG)/libgrpc++_test_util.a: openssl_dep_error else ifneq ($(OPENSSL_DEP),) -test/cpp/util/messages.proto: $(OPENSSL_DEP) test/cpp/util/echo.proto: $(OPENSSL_DEP) test/cpp/util/echo_duplicate.proto: $(OPENSSL_DEP) +test/cpp/util/messages.proto: $(OPENSSL_DEP) test/cpp/end2end/async_test_server.cc: $(OPENSSL_DEP) test/cpp/util/create_test_channel.cc: $(OPENSSL_DEP) endif @@ -2236,13 +2241,13 @@ endif -objs/$(CONFIG)/test/cpp/end2end/async_test_server.o: gens/test/cpp/util/messages.pb.cc gens/test/cpp/util/echo.pb.cc gens/test/cpp/util/echo_duplicate.pb.cc -objs/$(CONFIG)/test/cpp/util/create_test_channel.o: gens/test/cpp/util/messages.pb.cc gens/test/cpp/util/echo.pb.cc gens/test/cpp/util/echo_duplicate.pb.cc +objs/$(CONFIG)/test/cpp/end2end/async_test_server.o: gens/test/cpp/util/echo.pb.cc gens/test/cpp/util/echo_duplicate.pb.cc gens/test/cpp/util/messages.pb.cc +objs/$(CONFIG)/test/cpp/util/create_test_channel.o: gens/test/cpp/util/echo.pb.cc gens/test/cpp/util/echo_duplicate.pb.cc gens/test/cpp/util/messages.pb.cc LIBTIPS_CLIENT_LIB_SRC = \ - gens/examples/tips/label.pb.cc \ gens/examples/tips/empty.pb.cc \ + gens/examples/tips/label.pb.cc \ gens/examples/tips/pubsub.pb.cc \ examples/tips/client.cc \ @@ -2259,8 +2264,8 @@ libs/$(CONFIG)/libtips_client_lib.a: openssl_dep_error else ifneq ($(OPENSSL_DEP),) -examples/tips/label.proto: $(OPENSSL_DEP) examples/tips/empty.proto: $(OPENSSL_DEP) +examples/tips/label.proto: $(OPENSSL_DEP) examples/tips/pubsub.proto: $(OPENSSL_DEP) examples/tips/client.cc: $(OPENSSL_DEP) endif @@ -2289,7 +2294,7 @@ endif -objs/$(CONFIG)/examples/tips/client.o: gens/examples/tips/label.pb.cc gens/examples/tips/empty.pb.cc gens/examples/tips/pubsub.pb.cc +objs/$(CONFIG)/examples/tips/client.o: gens/examples/tips/empty.pb.cc gens/examples/tips/label.pb.cc gens/examples/tips/pubsub.pb.cc LIBEND2END_FIXTURE_CHTTP2_FAKE_SECURITY_SRC = \ @@ -4883,6 +4888,99 @@ endif endif +JSON_REWRITE_SRC = \ + test/core/json/json_rewrite.c \ + +JSON_REWRITE_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_REWRITE_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +bins/$(CONFIG)/json_rewrite: openssl_dep_error + +else + +bins/$(CONFIG)/json_rewrite: $(JSON_REWRITE_OBJS) libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(JSON_REWRITE_OBJS) libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/json_rewrite + +endif + +objs/$(CONFIG)/test/core/json/json_rewrite.o: libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a + +deps_json_rewrite: $(JSON_REWRITE_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(JSON_REWRITE_OBJS:.o=.dep) +endif +endif + + +JSON_REWRITE_TEST_SRC = \ + test/core/json/json_rewrite_test.c \ + +JSON_REWRITE_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_REWRITE_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +bins/$(CONFIG)/json_rewrite_test: openssl_dep_error + +else + +bins/$(CONFIG)/json_rewrite_test: $(JSON_REWRITE_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(JSON_REWRITE_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/json_rewrite_test + +endif + +objs/$(CONFIG)/test/core/json/json_rewrite_test.o: libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a + +deps_json_rewrite_test: $(JSON_REWRITE_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(JSON_REWRITE_TEST_OBJS:.o=.dep) +endif +endif + + +JSON_TEST_SRC = \ + test/core/json/json_test.c \ + +JSON_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +bins/$(CONFIG)/json_test: openssl_dep_error + +else + +bins/$(CONFIG)/json_test: $(JSON_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(JSON_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/json_test + +endif + +objs/$(CONFIG)/test/core/json/json_test.o: libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a + +deps_json_test: $(JSON_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(JSON_TEST_OBJS:.o=.dep) +endif +endif + + LAME_CLIENT_TEST_SRC = \ test/core/surface/lame_client_test.c \ @@ -5410,99 +5508,6 @@ endif endif -JSON_TEST_SRC = \ - test/core/json/json_test.c \ - -JSON_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_TEST_SRC)))) - -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -bins/$(CONFIG)/json_test: openssl_dep_error - -else - -bins/$(CONFIG)/json_test: $(JSON_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(JSON_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/json_test - -endif - -objs/$(CONFIG)/test/core/json/json_test.o: libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a - -deps_json_test: $(JSON_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(JSON_TEST_OBJS:.o=.dep) -endif -endif - - -JSON_REWRITE_SRC = \ - test/core/json/json_rewrite.c \ - -JSON_REWRITE_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_REWRITE_SRC)))) - -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -bins/$(CONFIG)/json_rewrite: openssl_dep_error - -else - -bins/$(CONFIG)/json_rewrite: $(JSON_REWRITE_OBJS) libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(JSON_REWRITE_OBJS) libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/json_rewrite - -endif - -objs/$(CONFIG)/test/core/json/json_rewrite.o: libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr.a - -deps_json_rewrite: $(JSON_REWRITE_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(JSON_REWRITE_OBJS:.o=.dep) -endif -endif - - -JSON_REWRITE_TEST_SRC = \ - test/core/json/json_rewrite_test.c \ - -JSON_REWRITE_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(JSON_REWRITE_TEST_SRC)))) - -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -bins/$(CONFIG)/json_rewrite_test: openssl_dep_error - -else - -bins/$(CONFIG)/json_rewrite_test: $(JSON_REWRITE_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LD) $(LDFLAGS) $(JSON_REWRITE_TEST_OBJS) libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/json_rewrite_test - -endif - -objs/$(CONFIG)/test/core/json/json_rewrite_test.o: libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a - -deps_json_rewrite_test: $(JSON_REWRITE_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(JSON_REWRITE_TEST_OBJS:.o=.dep) -endif -endif - - CHANNEL_ARGUMENTS_TEST_SRC = \ test/cpp/client/channel_arguments_test.cc \ @@ -5691,68 +5696,6 @@ endif endif -TIPS_CLIENT_SRC = \ - examples/tips/client_main.cc \ - -TIPS_CLIENT_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(TIPS_CLIENT_SRC)))) - -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -bins/$(CONFIG)/tips_client: openssl_dep_error - -else - -bins/$(CONFIG)/tips_client: $(TIPS_CLIENT_OBJS) libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(TIPS_CLIENT_OBJS) $(GTEST_LIB) libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/tips_client - -endif - -objs/$(CONFIG)/examples/tips/client_main.o: libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a - -deps_tips_client: $(TIPS_CLIENT_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(TIPS_CLIENT_OBJS:.o=.dep) -endif -endif - - -TIPS_CLIENT_TEST_SRC = \ - examples/tips/client_test.cc \ - -TIPS_CLIENT_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(TIPS_CLIENT_TEST_SRC)))) - -ifeq ($(NO_SECURE),true) - -# You can't build secure targets if you don't have OpenSSL with ALPN. - -bins/$(CONFIG)/tips_client_test: openssl_dep_error - -else - -bins/$(CONFIG)/tips_client_test: $(TIPS_CLIENT_TEST_OBJS) libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a - $(E) "[LD] Linking $@" - $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) $(TIPS_CLIENT_TEST_OBJS) $(GTEST_LIB) libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/tips_client_test - -endif - -objs/$(CONFIG)/examples/tips/client_test.o: libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a - -deps_tips_client_test: $(TIPS_CLIENT_TEST_OBJS:.o=.dep) - -ifneq ($(NO_SECURE),true) -ifneq ($(NO_DEPS),true) --include $(TIPS_CLIENT_TEST_OBJS:.o=.dep) -endif -endif - - QPS_CLIENT_SRC = \ gens/test/cpp/qps/qpstest.pb.cc \ test/cpp/qps/client.cc \ @@ -5933,6 +5876,68 @@ endif endif +TIPS_CLIENT_SRC = \ + examples/tips/client_main.cc \ + +TIPS_CLIENT_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(TIPS_CLIENT_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +bins/$(CONFIG)/tips_client: openssl_dep_error + +else + +bins/$(CONFIG)/tips_client: $(TIPS_CLIENT_OBJS) libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(TIPS_CLIENT_OBJS) $(GTEST_LIB) libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/tips_client + +endif + +objs/$(CONFIG)/examples/tips/client_main.o: libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a + +deps_tips_client: $(TIPS_CLIENT_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(TIPS_CLIENT_OBJS:.o=.dep) +endif +endif + + +TIPS_CLIENT_TEST_SRC = \ + examples/tips/client_test.cc \ + +TIPS_CLIENT_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(TIPS_CLIENT_TEST_SRC)))) + +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL with ALPN. + +bins/$(CONFIG)/tips_client_test: openssl_dep_error + +else + +bins/$(CONFIG)/tips_client_test: $(TIPS_CLIENT_TEST_OBJS) libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LDXX) $(LDFLAGS) $(TIPS_CLIENT_TEST_OBJS) $(GTEST_LIB) libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS) $(LDLIBS_SECURE) -o bins/$(CONFIG)/tips_client_test + +endif + +objs/$(CONFIG)/examples/tips/client_test.o: libs/$(CONFIG)/libtips_client_lib.a libs/$(CONFIG)/libgrpc++_test_util.a libs/$(CONFIG)/libgrpc_test_util.a libs/$(CONFIG)/libgrpc++.a libs/$(CONFIG)/libgrpc.a libs/$(CONFIG)/libgpr_test_util.a libs/$(CONFIG)/libgpr.a + +deps_tips_client_test: $(TIPS_CLIENT_TEST_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(TIPS_CLIENT_TEST_OBJS:.o=.dep) +endif +endif + + CHTTP2_FAKE_SECURITY_CANCEL_AFTER_ACCEPT_TEST_SRC = \ CHTTP2_FAKE_SECURITY_CANCEL_AFTER_ACCEPT_TEST_OBJS = $(addprefix objs/$(CONFIG)/, $(addsuffix .o, $(basename $(CHTTP2_FAKE_SECURITY_CANCEL_AFTER_ACCEPT_TEST_SRC)))) diff --git a/build.json b/build.json index 40187b9d500..e8820b359e7 100644 --- a/build.json +++ b/build.json @@ -61,8 +61,8 @@ "src/core/iomgr/tcp_posix.h", "src/core/iomgr/tcp_server.h", "src/core/iomgr/time_averaged_stats.h", - "src/core/iomgr/wakeup_fd_posix.h", "src/core/iomgr/wakeup_fd_pipe.h", + "src/core/iomgr/wakeup_fd_posix.h", "src/core/json/json.h", "src/core/json/json_common.h", "src/core/json/json_reader.h", @@ -73,6 +73,7 @@ "src/core/statistics/census_tracing.h", "src/core/statistics/hash_table.h", "src/core/statistics/window_stats.h", + "src/core/surface/byte_buffer_queue.h", "src/core/surface/call.h", "src/core/surface/channel.h", "src/core/surface/client.h", @@ -159,6 +160,7 @@ "src/core/statistics/hash_table.c", "src/core/statistics/window_stats.c", "src/core/surface/byte_buffer.c", + "src/core/surface/byte_buffer_queue.c", "src/core/surface/byte_buffer_reader.c", "src/core/surface/call.c", "src/core/surface/channel.c", @@ -418,9 +420,9 @@ "build": "private", "language": "c++", "src": [ - "test/cpp/util/messages.proto", "test/cpp/util/echo.proto", "test/cpp/util/echo_duplicate.proto", + "test/cpp/util/messages.proto", "test/cpp/end2end/async_test_server.cc", "test/cpp/util/create_test_channel.cc" ] @@ -430,8 +432,8 @@ "build": "private", "language": "c++", "src": [ - "examples/tips/label.proto", "examples/tips/empty.proto", + "examples/tips/label.proto", "examples/tips/pubsub.proto", "examples/tips/client.cc" ], @@ -1192,6 +1194,48 @@ "gpr" ] }, + { + "name": "json_rewrite", + "build": "test", + "language": "c", + "src": [ + "test/core/json/json_rewrite.c" + ], + "deps": [ + "grpc", + "gpr" + ], + "run": false + }, + { + "name": "json_rewrite_test", + "build": "test", + "language": "c", + "src": [ + "test/core/json/json_rewrite_test.c" + ], + "deps": [ + "grpc_test_util", + "grpc", + "gpr_test_util", + "gpr" + ], + "run": false + }, + { + "name": "json_test", + "build": "test", + "language": "c", + "src": [ + "test/core/json/json_test.c" + ], + "deps": [ + "grpc_test_util", + "grpc", + "gpr_test_util", + "gpr" + ] + }, { "name": "lame_client_test", "build": "test", @@ -1428,48 +1472,6 @@ "gpr" ] }, - { - "name": "json_test", - "build": "test", - "language": "c", - "src": [ - "test/core/json/json_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "json_rewrite", - "build": "test", - "language": "c", - "src": [ - "test/core/json/json_rewrite.c" - ], - "deps": [ - "grpc", - "gpr" - ], - "run": false - }, - { - "name": "json_rewrite_test", - "build": "test", - "language": "c", - "src": [ - "test/core/json/json_rewrite_test.c" - ], - "deps": [ - "grpc_test_util", - "grpc", - "gpr_test_util", - "gpr" - ], - "run": false - }, { "name": "channel_arguments_test", "build": "test", @@ -1567,41 +1569,6 @@ ], "run": false }, - { - "name": "tips_client", - "build": "test", - "run": false, - "language": "c++", - "src": [ - "examples/tips/client_main.cc" - ], - "deps": [ - "tips_client_lib", - "grpc++_test_util", - "grpc_test_util", - "grpc++", - "grpc", - "gpr_test_util", - "gpr" - ] - }, - { - "name": "tips_client_test", - "build": "test", - "language": "c++", - "src": [ - "examples/tips/client_test.cc" - ], - "deps": [ - "tips_client_lib", - "grpc++_test_util", - "grpc_test_util", - "grpc++", - "grpc", - "gpr_test_util", - "gpr" - ] - }, { "name": "qps_client", "build": "test", @@ -1698,6 +1665,41 @@ "gpr_test_util", "gpr" ] + }, + { + "name": "tips_client", + "build": "test", + "language": "c++", + "src": [ + "examples/tips/client_main.cc" + ], + "deps": [ + "tips_client_lib", + "grpc++_test_util", + "grpc_test_util", + "grpc++", + "grpc", + "gpr_test_util", + "gpr" + ], + "run": false + }, + { + "name": "tips_client_test", + "build": "test", + "language": "c++", + "src": [ + "examples/tips/client_test.cc" + ], + "deps": [ + "tips_client_lib", + "grpc++_test_util", + "grpc_test_util", + "grpc++", + "grpc", + "gpr_test_util", + "gpr" + ] } ] } diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json index b3ebc1f8695..fd151821208 100644 --- a/tools/run_tests/tests.json +++ b/tools/run_tests/tests.json @@ -185,6 +185,14 @@ "language": "c", "name": "httpcli_test" }, + { + "language": "c", + "name": "json_rewrite_test" + }, + { + "language": "c", + "name": "json_test" + }, { "language": "c", "name": "lame_client_test" @@ -249,14 +257,6 @@ "language": "c", "name": "transport_metadata_test" }, - { - "language": "c", - "name": "json_test" - }, - { - "language": "c", - "name": "json_rewrite_test" - }, { "language": "c++", "name": "channel_arguments_test" @@ -269,10 +269,6 @@ "language": "c++", "name": "end2end_test" }, - { - "language": "c++", - "name": "tips_client_test" - }, { "language": "c++", "name": "status_test" @@ -285,6 +281,10 @@ "language": "c++", "name": "thread_pool_test" }, + { + "language": "c++", + "name": "tips_client_test" + }, { "language": "c", "name": "chttp2_fake_security_cancel_after_accept_test" diff --git a/vsprojects/vs2013/grpc.vcxproj b/vsprojects/vs2013/grpc.vcxproj index 8756bbf0ecc..8c12b2daf03 100644 --- a/vsprojects/vs2013/grpc.vcxproj +++ b/vsprojects/vs2013/grpc.vcxproj @@ -134,8 +134,8 @@ - + @@ -146,6 +146,7 @@ + @@ -312,6 +313,8 @@ + + diff --git a/vsprojects/vs2013/grpc.vcxproj.filters b/vsprojects/vs2013/grpc.vcxproj.filters index 5d39d406e2b..62f0b60c85b 100644 --- a/vsprojects/vs2013/grpc.vcxproj.filters +++ b/vsprojects/vs2013/grpc.vcxproj.filters @@ -202,6 +202,9 @@ src\core\surface + + src\core\surface + src\core\surface @@ -485,10 +488,10 @@ src\core\iomgr - + src\core\iomgr - + src\core\iomgr @@ -521,6 +524,9 @@ src\core\statistics + + src\core\surface + src\core\surface diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj b/vsprojects/vs2013/grpc_unsecure.vcxproj index 8756bbf0ecc..8c12b2daf03 100644 --- a/vsprojects/vs2013/grpc_unsecure.vcxproj +++ b/vsprojects/vs2013/grpc_unsecure.vcxproj @@ -134,8 +134,8 @@ - + @@ -146,6 +146,7 @@ + @@ -312,6 +313,8 @@ + + diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj.filters b/vsprojects/vs2013/grpc_unsecure.vcxproj.filters index b644d54082b..5ed5e9b9b6b 100644 --- a/vsprojects/vs2013/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vs2013/grpc_unsecure.vcxproj.filters @@ -163,6 +163,9 @@ src\core\surface + + src\core\surface + src\core\surface @@ -410,10 +413,10 @@ src\core\iomgr - + src\core\iomgr - + src\core\iomgr @@ -446,6 +449,9 @@ src\core\statistics + + src\core\surface + src\core\surface From b8a318acd9c2d7c289b3fda532c22d486173d9e7 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 30 Jan 2015 16:56:58 -0800 Subject: [PATCH 66/93] Finish bbq api Modelled after old pending read queue code. --- src/core/surface/byte_buffer_queue.c | 63 +++++++--------------------- src/core/surface/byte_buffer_queue.h | 4 ++ 2 files changed, 19 insertions(+), 48 deletions(-) diff --git a/src/core/surface/byte_buffer_queue.c b/src/core/surface/byte_buffer_queue.c index bd5263b2f64..36c082f4847 100644 --- a/src/core/surface/byte_buffer_queue.c +++ b/src/core/surface/byte_buffer_queue.c @@ -32,69 +32,40 @@ */ #include "src/core/surface/byte_buffer_queue.h" +#include -#define INITIAL_PENDING_READ_COUNT 4 - -static void pra_init(pending_read_array *array) { - array->data = gpr_malloc(sizeof(pending_read) * INITIAL_PENDING_READ_COUNT); - array->count = 0; - array->capacity = INITIAL_PENDING_READ_COUNT; -} - -static void pra_destroy(pending_read_array *array, - size_t finish_starting_from) { - size_t i; - for (i = finish_starting_from; i < array->count; i++) { - array->data[i].on_finish(array->data[i].user_data, GRPC_OP_ERROR); - } +static void bba_destroy(grpc_bbq_array *array) { gpr_free(array->data); } /* Append an operation to an array, expanding as needed */ -static void pra_push(pending_read_array *a, grpc_byte_buffer *buffer, - void (*on_finish)(void *user_data, grpc_op_error error), - void *user_data) { +static void bba_push(grpc_bbq_array *a, grpc_byte_buffer *buffer) { if (a->count == a->capacity) { a->capacity *= 2; - a->data = gpr_realloc(a->data, sizeof(pending_read) * a->capacity); + a->data = gpr_realloc(a->data, sizeof(grpc_byte_buffer*) * a->capacity); } - a->data[a->count].byte_buffer = buffer; - a->data[a->count].user_data = user_data; - a->data[a->count].on_finish = on_finish; - a->count++; -} - -static void prq_init(pending_read_queue *q) { - q->drain_pos = 0; - pra_init(&q->filling); - pra_init(&q->draining); + a->data[a->count++] = buffer; } -static void prq_destroy(pending_read_queue *q) { - pra_destroy(&q->filling, 0); - pra_destroy(&q->draining, q->drain_pos); +void grpc_bbq_destroy(grpc_byte_buffer_queue *q) { + bba_destroy(&q->filling); + bba_destroy(&q->draining); } -static int prq_is_empty(pending_read_queue *q) { +int grpc_bbq_empty(grpc_byte_buffer_queue *q) { return (q->drain_pos == q->draining.count && q->filling.count == 0); } -static void prq_push(pending_read_queue *q, grpc_byte_buffer *buffer, - void (*on_finish)(void *user_data, grpc_op_error error), - void *user_data) { - pra_push(&q->filling, buffer, on_finish, user_data); +void grpc_bbq_push(grpc_byte_buffer_queue *q, grpc_byte_buffer *buffer) { + bba_push(&q->filling, buffer); } -/* Take the first queue element and move it to the completion queue. Do nothing - if q is empty */ -static int prq_pop_to_cq(pending_read_queue *q, void *tag, grpc_call *call, - grpc_completion_queue *cq) { - pending_read_array temp_array; - pending_read *pr; +grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q) { + grpc_bbq_array temp_array; if (q->drain_pos == q->draining.count) { if (q->filling.count == 0) { - return 0; + return NULL; } q->draining.count = 0; q->drain_pos = 0; @@ -104,9 +75,5 @@ static int prq_pop_to_cq(pending_read_queue *q, void *tag, grpc_call *call, q->draining = temp_array; } - pr = q->draining.data + q->drain_pos; - q->drain_pos++; - grpc_cq_end_read(cq, tag, call, pr->on_finish, pr->user_data, - pr->byte_buffer); - return 1; + return q->draining.data[q->drain_pos++]; } diff --git a/src/core/surface/byte_buffer_queue.h b/src/core/surface/byte_buffer_queue.h index 01cc06077ed..358a42d5af0 100644 --- a/src/core/surface/byte_buffer_queue.h +++ b/src/core/surface/byte_buffer_queue.h @@ -34,6 +34,8 @@ #ifndef __GRPC_INTERNAL_SURFACE_BYTE_BUFFER_QUEUE_H__ #define __GRPC_INTERNAL_SURFACE_BYTE_BUFFER_QUEUE_H__ +#include + /* TODO(ctiller): inline an element or two into this struct to avoid per-call allocations */ typedef struct { @@ -42,12 +44,14 @@ typedef struct { size_t capacity; } grpc_bbq_array; +/* should be initialized by zeroing memory */ typedef struct { size_t drain_pos; grpc_bbq_array filling; grpc_bbq_array draining; } grpc_byte_buffer_queue; +void grpc_bbq_destroy(grpc_byte_buffer_queue *q); grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q); int grpc_bbq_empty(grpc_byte_buffer_queue *q); void grpc_bbq_push(grpc_byte_buffer_queue *q, grpc_byte_buffer *bb); From 1c1419011afa631ed25224d9d97ce7ce8a185880 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Sat, 31 Jan 2015 08:51:54 -0800 Subject: [PATCH 67/93] Get server status send working --- src/core/surface/call.c | 117 +++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 63 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index e2e8fe23a52..a6389799590 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -58,7 +58,7 @@ typedef struct { /* input buffers */ grpc_metadata_array initial_md_in; grpc_metadata_array trailing_md_in; - + size_t details_capacity; char *details; grpc_status_code status; @@ -76,8 +76,7 @@ typedef enum { SEND_NOTHING, SEND_INITIAL_METADATA, SEND_MESSAGE, - SEND_TRAILING_METADATA, - SEND_STATUS, + SEND_TRAILING_METADATA_AND_FINISH, SEND_FINISH } send_action; @@ -89,7 +88,7 @@ typedef struct { /* See reqinfo.set below for a description */ #define REQSET_EMPTY 255 -#define REQSET_DONE 254 +#define REQSET_DONE 254 /* The state of an ioreq */ typedef struct reqinfo { @@ -158,7 +157,7 @@ struct grpc_call { legacy_state *legacy_state; }; -#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) +#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call)+1)) #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1) #define CALL_ELEM_FROM_CALL(call, idx) \ grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx) @@ -191,6 +190,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, } if (call->is_client) { call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].set = REQSET_DONE; + call->requests[GRPC_IOREQ_SEND_STATUS].set = REQSET_DONE; } grpc_channel_internal_ref(channel); call->metadata_context = grpc_channel_get_metadata_context(channel); @@ -341,7 +341,8 @@ static void get_final_status(grpc_call *call, grpc_recv_status_args args) { 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_capacity = + GPR_MAX(len + 1, *args.details_capacity * 3 / 2); *args.details = gpr_realloc(*args.details, *args.details_capacity); } memcpy(*args.details, GPR_SLICE_START_PTR(details), len); @@ -374,12 +375,10 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, (op == GRPC_IOREQ_SEND_MESSAGE || op == GRPC_IOREQ_RECV_MESSAGE) ? REQSET_EMPTY : REQSET_DONE; - if (master->complete_mask == master->need_mask || - status == GRPC_OP_ERROR) { + if (master->complete_mask == master->need_mask || status == GRPC_OP_ERROR) { if (OP_IN_MASK(GRPC_IOREQ_RECV_STATUS, master->need_mask)) { get_final_status( - call, - call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status); + call, call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status); } for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { if (call->requests[i].set == op) { @@ -397,7 +396,8 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, } } -static void finish_send_op(grpc_call *call, grpc_ioreq_op op, grpc_op_error error) { +static void finish_send_op(grpc_call *call, grpc_ioreq_op op, + grpc_op_error error) { lock(call); finish_ioreq_op(call, op, error); call->sending = 0; @@ -434,30 +434,20 @@ static send_action choose_send_action(grpc_call *call) { case REQSET_DONE: break; } - switch (call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].set) { - case REQSET_EMPTY: - return SEND_NOTHING; - default: - finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); - return SEND_TRAILING_METADATA; - case REQSET_DONE: - break; - } - switch (call->requests[GRPC_IOREQ_SEND_STATUS].set) { - case REQSET_EMPTY: - return SEND_NOTHING; - default: - finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, GRPC_OP_OK); - return SEND_STATUS; - case REQSET_DONE: - break; - } switch (call->requests[GRPC_IOREQ_SEND_CLOSE].set) { case REQSET_EMPTY: case REQSET_DONE: return SEND_NOTHING; default: - return SEND_FINISH; + if (call->is_client) { + return SEND_FINISH; + } else if (call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].set != + REQSET_EMPTY && + call->requests[GRPC_IOREQ_SEND_STATUS].set != REQSET_EMPTY) { + return SEND_TRAILING_METADATA_AND_FINISH; + } else { + return SEND_NOTHING; + } } } @@ -509,7 +499,8 @@ static void enact_send_action(grpc_call *call, send_action sa) { op.user_data = call; grpc_call_execute_op(call, &op); break; - case SEND_TRAILING_METADATA: + case SEND_TRAILING_METADATA_AND_FINISH: + /* send trailing metadata */ data = call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].data; for (i = 0; i < data.send_metadata.count; i++) { const grpc_metadata *md = &data.send_metadata.metadata[i]; @@ -518,12 +509,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { call->metadata_context, md->key, (const gpr_uint8 *)md->value, md->value_length)); } - lock(call); - call->sending = 0; - unlock(call); - grpc_call_internal_unref(call, 0); - break; - case SEND_STATUS: + /* send status */ /* TODO(ctiller): cache common status values */ data = call->requests[GRPC_IOREQ_SEND_CLOSE].data; gpr_ltoa(data.send_status.code, status_str); @@ -534,15 +520,15 @@ static void enact_send_action(grpc_call *call, send_action sa) { grpc_mdstr_ref(grpc_channel_get_status_string(call->channel)), grpc_mdstr_from_string(call->metadata_context, status_str))); if (data.send_status.details) { - send_metadata(call, - grpc_mdelem_from_metadata_strings( - call->metadata_context, - grpc_mdstr_ref( - grpc_channel_get_message_string(call->channel)), - grpc_mdstr_from_string(call->metadata_context, - data.send_status.details))); + send_metadata( + call, + grpc_mdelem_from_metadata_strings( + call->metadata_context, + grpc_mdstr_ref(grpc_channel_get_message_string(call->channel)), + grpc_mdstr_from_string(call->metadata_context, + data.send_status.details))); } - break; + /* fallthrough: see choose_send_action for details */ case SEND_FINISH: op.type = GRPC_SEND_FINISH; op.dir = GRPC_CALL_DOWN; @@ -591,8 +577,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_TOO_MANY_OPERATIONS); } else if (requests[op].set == REQSET_DONE) { - return start_ioreq_error(call, have_ops, - GRPC_CALL_ERROR_ALREADY_INVOKED); + return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_ALREADY_INVOKED); } have_ops |= 1 << op; data = reqs[i].data; @@ -755,11 +740,14 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, lock(call); ls = get_legacy_state(call); - if (ls->md_out_count[ls->md_out_buffer] == ls->md_out_capacity[ls->md_out_buffer]) { + if (ls->md_out_count[ls->md_out_buffer] == + ls->md_out_capacity[ls->md_out_buffer]) { ls->md_out_capacity[ls->md_out_buffer] = - GPR_MAX(ls->md_out_capacity[ls->md_out_buffer] * 3 / 2, ls->md_out_capacity[ls->md_out_buffer] + 8); - ls->md_out[ls->md_out_buffer] = - gpr_realloc(ls->md_out[ls->md_out_buffer], sizeof(grpc_metadata) * ls->md_out_capacity[ls->md_out_buffer]); + GPR_MAX(ls->md_out_capacity[ls->md_out_buffer] * 3 / 2, + ls->md_out_capacity[ls->md_out_buffer] + 8); + ls->md_out[ls->md_out_buffer] = gpr_realloc( + ls->md_out[ls->md_out_buffer], + sizeof(grpc_metadata) * ls->md_out_capacity[ls->md_out_buffer]); } mdout = &ls->md_out[ls->md_out_buffer][ls->md_out_count[ls->md_out_buffer]++]; mdout->key = gpr_strdup(metadata->key); @@ -776,8 +764,8 @@ static void maybe_finish_legacy(grpc_call *call) { legacy_state *ls = get_legacy_state(call); if (ls->got_status) { grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, - ls->status, ls->details, - ls->trailing_md_in.metadata, ls->trailing_md_in.count); + ls->status, ls->details, ls->trailing_md_in.metadata, + ls->trailing_md_in.count); } } @@ -800,7 +788,8 @@ static void finish_recv_metadata(grpc_call *call, grpc_op_error status, ls = get_legacy_state(call); if (status == GRPC_OP_OK) { grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, - ls->initial_md_in.count, ls->initial_md_in.metadata); + ls->initial_md_in.count, + ls->initial_md_in.metadata); } else { grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, 0, @@ -1000,11 +989,12 @@ grpc_call_error grpc_call_start_write_status(grpc_call *call, reqs[0].op = GRPC_IOREQ_SEND_TRAILING_METADATA; reqs[0].data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; reqs[0].data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; - reqs[1].op = GRPC_IOREQ_SEND_CLOSE; + reqs[1].op = GRPC_IOREQ_SEND_STATUS; reqs[1].data.send_status.code = status; /* MEMLEAK */ reqs[1].data.send_status.details = gpr_strdup(details); - err = start_ioreq(call, reqs, 2, finish_finish, tag); + reqs[2].op = GRPC_IOREQ_SEND_CLOSE; + err = start_ioreq(call, reqs, 3, finish_finish, tag); unlock(call); return err; @@ -1077,7 +1067,7 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { gpr_uint32 status; void *user_data = grpc_mdelem_get_user_data(md, destroy_status); if (user_data) { - status = ((gpr_uint32)(gpr_intptr)user_data) - STATUS_OFFSET; + status = ((gpr_uint32)(gpr_intptr) user_data) - STATUS_OFFSET; } else { if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value), GPR_SLICE_LENGTH(md->value->slice), @@ -1119,16 +1109,17 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { grpc_mdelem_unref(md); } else { if (!call->got_initial_metadata) { - dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].set < GRPC_IOREQ_OP_COUNT + dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].set < + GRPC_IOREQ_OP_COUNT ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] .data.recv_metadata : &call->buffered_initial_metadata; } else { - dest = - call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].set < GRPC_IOREQ_OP_COUNT - ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] - .data.recv_metadata - : &call->buffered_trailing_metadata; + dest = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].set < + GRPC_IOREQ_OP_COUNT + ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] + .data.recv_metadata + : &call->buffered_trailing_metadata; } if (dest->count == dest->capacity) { dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2); From 9a3f2b24335f54c174a1e4b7ce272f9a56fb4091 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Sat, 31 Jan 2015 09:01:03 -0800 Subject: [PATCH 68/93] Look in the right array element --- src/core/surface/call.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index a6389799590..b64e42e8e37 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -511,7 +511,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { } /* send status */ /* TODO(ctiller): cache common status values */ - data = call->requests[GRPC_IOREQ_SEND_CLOSE].data; + data = call->requests[GRPC_IOREQ_SEND_STATUS].data; gpr_ltoa(data.send_status.code, status_str); send_metadata( call, From 7a9d79244f33870d4ee7b50d177286f285cba147 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Sat, 31 Jan 2015 09:35:20 -0800 Subject: [PATCH 69/93] Fix simple request --- src/core/surface/call.c | 47 ++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index b64e42e8e37..2b5bcc2f52d 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -66,7 +66,6 @@ typedef struct { size_t msg_in_read_idx; grpc_byte_buffer *msg_in; - gpr_uint8 got_status; void *finished_tag; } legacy_state; @@ -134,7 +133,6 @@ struct grpc_call { gpr_uint8 have_alarm; gpr_uint8 read_closed; gpr_uint8 stream_closed; - gpr_uint8 got_status_code; gpr_uint8 sending; gpr_uint8 num_completed_requests; gpr_uint8 need_more_data; @@ -337,6 +335,7 @@ static void get_final_status(grpc_call *call, grpc_recv_status_args args) { for (i = 0; i < STATUS_SOURCE_COUNT; i++) { if (call->status[i].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); @@ -354,6 +353,7 @@ static void get_final_status(grpc_call *call, grpc_recv_status_args args) { } } *args.code = GRPC_STATUS_UNKNOWN; + if (!args.details) return; no_details: if (0 == *args.details_capacity) { @@ -444,6 +444,8 @@ static send_action choose_send_action(grpc_call *call) { } else if (call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].set != REQSET_EMPTY && call->requests[GRPC_IOREQ_SEND_STATUS].set != REQSET_EMPTY) { + finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, GRPC_OP_OK); return SEND_TRAILING_METADATA_AND_FINISH; } else { return SEND_NOTHING; @@ -602,15 +604,14 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, *data.recv_message = grpc_bbq_pop(&call->incoming_queue); if (*data.recv_message) { finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + } else if (call->stream_closed) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); } else { call->need_more_data = 1; } - if (call->stream_closed) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); - } break; case GRPC_IOREQ_RECV_STATUS: - if (call->stream_closed) { + if (call->read_closed) { finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); } break; @@ -760,23 +761,15 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, return GRPC_CALL_OK; } -static void maybe_finish_legacy(grpc_call *call) { - legacy_state *ls = get_legacy_state(call); - if (ls->got_status) { - grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, - ls->status, ls->details, ls->trailing_md_in.metadata, - ls->trailing_md_in.count); - } -} - static void finish_status(grpc_call *call, grpc_op_error status, void *ignored) { legacy_state *ls; lock(call); ls = get_legacy_state(call); - ls->got_status = 1; - maybe_finish_legacy(call); + grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, + ls->status, ls->details, ls->trailing_md_in.metadata, + ls->trailing_md_in.count); unlock(call); } @@ -1028,14 +1021,19 @@ void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); } -void grpc_call_read_closed(grpc_call_element *elem) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); - lock(call); - GPR_ASSERT(!call->read_closed); +static void mark_read_closed(grpc_call *call) { call->read_closed = 1; finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); +} + +void grpc_call_read_closed(grpc_call_element *elem) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + lock(call); + GPR_ASSERT(!call->read_closed); + mark_read_closed(call); unlock(call); } @@ -1044,14 +1042,11 @@ void grpc_call_stream_closed(grpc_call_element *elem) { lock(call); GPR_ASSERT(!call->stream_closed); if (!call->read_closed) { - call->read_closed = 1; - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); - finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); + mark_read_closed(call); } call->stream_closed = 1; if (grpc_bbq_empty(&call->incoming_queue)) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); } unlock(call); grpc_call_internal_unref(call, 0); From 8f4f6e207f3ba74bc3aea4658e2c63529bf7d20f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Sat, 31 Jan 2015 20:01:37 -0800 Subject: [PATCH 70/93] Check for null pointer --- src/core/surface/call.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 2b5bcc2f52d..11b65be8711 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -896,7 +896,7 @@ void grpc_call_initial_metadata_complete(grpc_call_element *surface_element) { } static void finish_read_event(void *p, grpc_op_error error) { - grpc_byte_buffer_destroy(p); + if (p) grpc_byte_buffer_destroy(p); } static void finish_read(grpc_call *call, grpc_op_error error, void *tag) { From 7431fa985385dfb513f9b99cae614f733f23860d Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Sat, 31 Jan 2015 20:06:02 -0800 Subject: [PATCH 71/93] Preserve proto order --- build.json | 4 ++-- tools/buildgen/build-cleaner.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.json b/build.json index e8820b359e7..291c7e6f53c 100644 --- a/build.json +++ b/build.json @@ -420,9 +420,9 @@ "build": "private", "language": "c++", "src": [ + "test/cpp/util/messages.proto", "test/cpp/util/echo.proto", "test/cpp/util/echo_duplicate.proto", - "test/cpp/util/messages.proto", "test/cpp/end2end/async_test_server.cc", "test/cpp/util/create_test_channel.cc" ] @@ -432,8 +432,8 @@ "build": "private", "language": "c++", "src": [ - "examples/tips/empty.proto", "examples/tips/label.proto", + "examples/tips/empty.proto", "examples/tips/pubsub.proto", "examples/tips/client.cc" ], diff --git a/tools/buildgen/build-cleaner.py b/tools/buildgen/build-cleaner.py index f9307360c32..4992beb8970 100755 --- a/tools/buildgen/build-cleaner.py +++ b/tools/buildgen/build-cleaner.py @@ -33,9 +33,9 @@ def clean_elem(indict): for name in ['public_headers', 'headers', 'src']: if name not in indict: continue inlist = indict[name] - protos = set(x for x in inlist if os.path.splitext(x)[1] == '.proto') + protos = list(x for x in inlist if os.path.splitext(x)[1] == '.proto') others = set(x for x in inlist if x not in protos) - indict[name] = sorted(protos) + sorted(others) + indict[name] = protos + sorted(others) return rebuild_as_ordered_dict(indict, _ELEM_KEYS) for filename in sys.argv[1:]: From d2e280592274ceb0a13201229b9b0a4db16b9425 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Sat, 31 Jan 2015 20:06:21 -0800 Subject: [PATCH 72/93] Preserve proto order --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index c8b5ab935f8..7ec690ef22e 100644 --- a/Makefile +++ b/Makefile @@ -2191,9 +2191,9 @@ objs/$(CONFIG)/src/cpp/util/time.o: LIBGRPC++_TEST_UTIL_SRC = \ + gens/test/cpp/util/messages.pb.cc \ gens/test/cpp/util/echo.pb.cc \ gens/test/cpp/util/echo_duplicate.pb.cc \ - gens/test/cpp/util/messages.pb.cc \ test/cpp/end2end/async_test_server.cc \ test/cpp/util/create_test_channel.cc \ @@ -2210,9 +2210,9 @@ libs/$(CONFIG)/libgrpc++_test_util.a: openssl_dep_error else ifneq ($(OPENSSL_DEP),) +test/cpp/util/messages.proto: $(OPENSSL_DEP) test/cpp/util/echo.proto: $(OPENSSL_DEP) test/cpp/util/echo_duplicate.proto: $(OPENSSL_DEP) -test/cpp/util/messages.proto: $(OPENSSL_DEP) test/cpp/end2end/async_test_server.cc: $(OPENSSL_DEP) test/cpp/util/create_test_channel.cc: $(OPENSSL_DEP) endif @@ -2241,13 +2241,13 @@ endif -objs/$(CONFIG)/test/cpp/end2end/async_test_server.o: gens/test/cpp/util/echo.pb.cc gens/test/cpp/util/echo_duplicate.pb.cc gens/test/cpp/util/messages.pb.cc -objs/$(CONFIG)/test/cpp/util/create_test_channel.o: gens/test/cpp/util/echo.pb.cc gens/test/cpp/util/echo_duplicate.pb.cc gens/test/cpp/util/messages.pb.cc +objs/$(CONFIG)/test/cpp/end2end/async_test_server.o: gens/test/cpp/util/messages.pb.cc gens/test/cpp/util/echo.pb.cc gens/test/cpp/util/echo_duplicate.pb.cc +objs/$(CONFIG)/test/cpp/util/create_test_channel.o: gens/test/cpp/util/messages.pb.cc gens/test/cpp/util/echo.pb.cc gens/test/cpp/util/echo_duplicate.pb.cc LIBTIPS_CLIENT_LIB_SRC = \ - gens/examples/tips/empty.pb.cc \ gens/examples/tips/label.pb.cc \ + gens/examples/tips/empty.pb.cc \ gens/examples/tips/pubsub.pb.cc \ examples/tips/client.cc \ @@ -2264,8 +2264,8 @@ libs/$(CONFIG)/libtips_client_lib.a: openssl_dep_error else ifneq ($(OPENSSL_DEP),) -examples/tips/empty.proto: $(OPENSSL_DEP) examples/tips/label.proto: $(OPENSSL_DEP) +examples/tips/empty.proto: $(OPENSSL_DEP) examples/tips/pubsub.proto: $(OPENSSL_DEP) examples/tips/client.cc: $(OPENSSL_DEP) endif @@ -2294,7 +2294,7 @@ endif -objs/$(CONFIG)/examples/tips/client.o: gens/examples/tips/empty.pb.cc gens/examples/tips/label.pb.cc gens/examples/tips/pubsub.pb.cc +objs/$(CONFIG)/examples/tips/client.o: gens/examples/tips/label.pb.cc gens/examples/tips/empty.pb.cc gens/examples/tips/pubsub.pb.cc LIBEND2END_FIXTURE_CHTTP2_FAKE_SECURITY_SRC = \ From 6bc1f2761b84acd50ce3b10338882224c9a6da5f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 09:41:15 -0800 Subject: [PATCH 73/93] Fix array size --- src/core/surface/call.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 11b65be8711..0245e1b70c7 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -830,7 +830,7 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, 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, 2, finish_status, NULL); + err = start_ioreq(call, reqs, 3, finish_status, NULL); if (err != GRPC_CALL_OK) goto done; done: From a7cac78516057512d62cdae8fc5fdf9e2f90a136 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 10:16:30 -0800 Subject: [PATCH 74/93] Prepare for the new batch call API. Rename all core API functions that are on their way to deprecation with an _old tag across all wrappings. --- include/grpc/grpc.h | 47 +++++++++-------- src/core/surface/call.c | 38 +++++++------- src/core/surface/channel.c | 6 +-- src/core/surface/server.c | 3 +- src/cpp/client/channel.cc | 16 +++--- src/cpp/server/async_server.cc | 2 +- src/cpp/server/async_server_context.cc | 11 ++-- src/cpp/server/server.cc | 2 +- src/cpp/stream/stream_context.cc | 12 ++--- src/node/.gitignore | 2 + src/node/ext/call.cc | 26 +++++----- src/node/ext/server.cc | 2 +- src/php/ext/grpc/call.c | 30 +++++------ src/php/ext/grpc/server.c | 2 +- src/python/src/_adapter/_call.c | 25 ++++----- src/python/src/_adapter/_server.c | 2 +- src/ruby/ext/grpc/rb_call.c | 22 ++++---- src/ruby/ext/grpc/rb_channel.c | 7 +-- src/ruby/ext/grpc/rb_server.c | 2 +- test/core/echo/client.c | 17 ++++--- test/core/echo/server.c | 20 ++++---- test/core/end2end/dualstack_socket_test.c | 18 ++++--- test/core/end2end/no_server_test.c | 4 +- test/core/end2end/tests/cancel_after_accept.c | 12 +++-- .../cancel_after_accept_and_writes_closed.c | 16 +++--- test/core/end2end/tests/cancel_after_invoke.c | 5 +- .../core/end2end/tests/cancel_before_invoke.c | 5 +- test/core/end2end/tests/cancel_in_a_vacuum.c | 3 +- .../end2end/tests/census_simple_request.c | 16 +++--- test/core/end2end/tests/disappearing_server.c | 15 +++--- ..._server_shutdown_finishes_inflight_calls.c | 14 ++--- .../early_server_shutdown_finishes_tags.c | 2 +- .../end2end/tests/graceful_server_shutdown.c | 16 +++--- .../core/end2end/tests/invoke_large_request.c | 20 ++++---- .../end2end/tests/max_concurrent_streams.c | 51 ++++++++++--------- test/core/end2end/tests/ping_pong_streaming.c | 24 +++++---- ...esponse_with_binary_metadata_and_payload.c | 31 +++++------ ...quest_response_with_metadata_and_payload.c | 31 +++++------ .../tests/request_response_with_payload.c | 24 +++++---- ...ponse_with_trailing_metadata_and_payload.c | 35 ++++++------- .../tests/request_with_large_metadata.c | 13 ++--- .../core/end2end/tests/request_with_payload.c | 15 +++--- .../end2end/tests/simple_delayed_request.c | 15 +++--- test/core/end2end/tests/simple_request.c | 32 +++++++----- test/core/end2end/tests/thread_stress.c | 30 ++++++----- .../writes_done_hangs_with_pending_read.c | 24 +++++---- test/core/fling/client.c | 26 +++++----- test/core/fling/server.c | 18 +++---- test/core/surface/lame_client_test.c | 6 +-- 49 files changed, 433 insertions(+), 382 deletions(-) create mode 100644 src/node/.gitignore diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index af52dd95f4f..a9fae0df909 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -275,8 +275,9 @@ void grpc_completion_queue_destroy(grpc_completion_queue *cq); /* Create a call given a grpc_channel, in order to call 'method'. The request is not sent until grpc_call_invoke is called. All completions are sent to 'completion_queue'. */ -grpc_call *grpc_channel_create_call(grpc_channel *channel, const char *method, - const char *host, gpr_timespec deadline); +grpc_call *grpc_channel_create_call_old(grpc_channel *channel, + const char *method, const char *host, + gpr_timespec deadline); /* Create a client channel */ grpc_channel *grpc_channel_create(const char *target, @@ -307,8 +308,9 @@ void grpc_channel_destroy(grpc_channel *channel); REQUIRES: grpc_call_start_invoke/grpc_call_server_end_initial_metadata have not been called on this call. Produces no events. */ -grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, - gpr_uint32 flags); +grpc_call_error grpc_call_add_metadata_old(grpc_call *call, + grpc_metadata *metadata, + gpr_uint32 flags); /* Invoke the RPC. Starts sending metadata and request headers on the wire. flags is a bit-field combination of the write flags defined above. @@ -319,9 +321,9 @@ grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, Produces a GRPC_FINISHED event with finished_tag when the call has been completed (there may be other events for the call pending at this time) */ -grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, - void *metadata_read_tag, void *finished_tag, - gpr_uint32 flags); +grpc_call_error grpc_call_invoke_old(grpc_call *call, grpc_completion_queue *cq, + void *metadata_read_tag, + void *finished_tag, gpr_uint32 flags); /* Accept an incoming RPC, binding a completion queue to it. To be called before sending or receiving messages. @@ -330,9 +332,9 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, Produces a GRPC_FINISHED event with finished_tag when the call has been completed (there may be other events for the call pending at this time) */ -grpc_call_error grpc_call_server_accept(grpc_call *call, - grpc_completion_queue *cq, - void *finished_tag); +grpc_call_error grpc_call_server_accept_old(grpc_call *call, + grpc_completion_queue *cq, + void *finished_tag); /* Start sending metadata. To be called before sending messages. @@ -340,8 +342,8 @@ grpc_call_error grpc_call_server_accept(grpc_call *call, REQUIRES: Can be called at most once per call. Can only be called on the server. Must be called after grpc_call_server_accept */ -grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, - gpr_uint32 flags); +grpc_call_error grpc_call_server_end_initial_metadata_old(grpc_call *call, + gpr_uint32 flags); /* Called by clients to cancel an RPC on the server. Can be called multiple times, from any thread. */ @@ -370,9 +372,9 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *call, grpc_call_server_end_of_initial_metadata must have been called successfully. Produces a GRPC_WRITE_ACCEPTED event. */ -grpc_call_error grpc_call_start_write(grpc_call *call, - grpc_byte_buffer *byte_buffer, void *tag, - gpr_uint32 flags); +grpc_call_error grpc_call_start_write_old(grpc_call *call, + grpc_byte_buffer *byte_buffer, + void *tag, gpr_uint32 flags); /* Queue a status for writing. REQUIRES: No other writes are pending on the call. @@ -380,17 +382,17 @@ grpc_call_error grpc_call_start_write(grpc_call *call, call prior to calling this. Only callable on the server. Produces a GRPC_FINISH_ACCEPTED event when the status is sent. */ -grpc_call_error grpc_call_start_write_status(grpc_call *call, - grpc_status_code status_code, - const char *status_message, - void *tag); +grpc_call_error grpc_call_start_write_status_old(grpc_call *call, + grpc_status_code status_code, + const char *status_message, + void *tag); /* No more messages to send. REQUIRES: No other writes are pending on the call. Only callable on the client. Produces a GRPC_FINISH_ACCEPTED event when all bytes for the call have passed outgoing flow control. */ -grpc_call_error grpc_call_writes_done(grpc_call *call, void *tag); +grpc_call_error grpc_call_writes_done_old(grpc_call *call, void *tag); /* Initiate a read on a call. Output event contains a byte buffer with the result of the read. @@ -402,7 +404,7 @@ grpc_call_error grpc_call_writes_done(grpc_call *call, void *tag); On the server: grpc_call_server_accept must be called before calling this. Produces a single GRPC_READ event. */ -grpc_call_error grpc_call_start_read(grpc_call *call, void *tag); +grpc_call_error grpc_call_start_read_old(grpc_call *call, void *tag); /* Destroy a call. */ void grpc_call_destroy(grpc_call *call); @@ -414,7 +416,8 @@ void grpc_call_destroy(grpc_call *call); tag_cancel. REQUIRES: Server must not have been shutdown. NOTE: calling this is the only way to obtain GRPC_SERVER_RPC_NEW events. */ -grpc_call_error grpc_server_request_call(grpc_server *server, void *tag_new); +grpc_call_error grpc_server_request_call_old(grpc_server *server, + void *tag_new); /* Create a server */ grpc_server *grpc_server_create(grpc_completion_queue *cq, diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 8bb0779bf79..5a24264ccec 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -348,8 +348,9 @@ void grpc_call_add_mdelem(grpc_call *call, grpc_mdelem *mdelem, elem->filter->call_op(elem, NULL, &op); } -grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, - gpr_uint32 flags) { +grpc_call_error grpc_call_add_metadata_old(grpc_call *call, + grpc_metadata *metadata, + gpr_uint32 flags) { grpc_mdelem *mdelem; if (call->is_client) { @@ -455,9 +456,9 @@ static void call_started(void *user_data, grpc_op_error error) { grpc_call_internal_unref(call); } -grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, - void *metadata_read_tag, void *finished_tag, - gpr_uint32 flags) { +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_call_element *elem; grpc_call_op op; @@ -527,9 +528,9 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, return GRPC_CALL_OK; } -grpc_call_error grpc_call_server_accept(grpc_call *call, - grpc_completion_queue *cq, - void *finished_tag) { +grpc_call_error grpc_call_server_accept_old(grpc_call *call, + grpc_completion_queue *cq, + void *finished_tag) { /* validate preconditions */ if (call->is_client) { gpr_log(GPR_ERROR, "can only call %s on servers", __FUNCTION__); @@ -563,8 +564,8 @@ grpc_call_error grpc_call_server_accept(grpc_call *call, return GRPC_CALL_OK; } -grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, - gpr_uint32 flags) { +grpc_call_error grpc_call_server_end_initial_metadata_old(grpc_call *call, + gpr_uint32 flags) { grpc_call_element *elem; grpc_call_op op; @@ -634,7 +635,7 @@ static void request_more_data(grpc_call *call) { elem->filter->call_op(elem, NULL, &op); } -grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { +grpc_call_error grpc_call_start_read_old(grpc_call *call, void *tag) { gpr_uint8 request_more = 0; switch (call->state) { @@ -677,9 +678,9 @@ grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { return GRPC_CALL_OK; } -grpc_call_error grpc_call_start_write(grpc_call *call, - grpc_byte_buffer *byte_buffer, void *tag, - gpr_uint32 flags) { +grpc_call_error grpc_call_start_write_old(grpc_call *call, + grpc_byte_buffer *byte_buffer, + void *tag, gpr_uint32 flags) { grpc_call_element *elem; grpc_call_op op; @@ -732,7 +733,7 @@ grpc_call_error grpc_call_start_write(grpc_call *call, return GRPC_CALL_OK; } -grpc_call_error grpc_call_writes_done(grpc_call *call, void *tag) { +grpc_call_error grpc_call_writes_done_old(grpc_call *call, void *tag) { grpc_call_element *elem; grpc_call_op op; @@ -780,9 +781,10 @@ grpc_call_error grpc_call_writes_done(grpc_call *call, void *tag) { return GRPC_CALL_OK; } -grpc_call_error grpc_call_start_write_status(grpc_call *call, - grpc_status_code status, - const char *details, void *tag) { +grpc_call_error grpc_call_start_write_status_old(grpc_call *call, + grpc_status_code status, + const char *details, + void *tag) { grpc_call_element *elem; grpc_call_op op; diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index a1bcea58ddb..93a2c0609d8 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -74,9 +74,9 @@ grpc_channel *grpc_channel_create_from_filters( static void do_nothing(void *ignored, grpc_op_error error) {} -grpc_call *grpc_channel_create_call(grpc_channel *channel, const char *method, - const char *host, - gpr_timespec absolute_deadline) { +grpc_call *grpc_channel_create_call_old(grpc_channel *channel, + const char *method, const char *host, + gpr_timespec absolute_deadline) { grpc_call *call; grpc_mdelem *path_mdelem; grpc_mdelem *authority_mdelem; diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 9a001f4c33d..9e2e4d54780 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -625,7 +625,8 @@ void grpc_server_add_listener(grpc_server *server, void *arg, server->listeners = l; } -grpc_call_error grpc_server_request_call(grpc_server *server, void *tag_new) { +grpc_call_error grpc_server_request_call_old(grpc_server *server, + void *tag_new) { call_data *calld; grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_RPC_NEW); diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc index c8b2bb2cf6e..5822e3015fc 100644 --- a/src/cpp/client/channel.cc +++ b/src/cpp/client/channel.cc @@ -99,7 +99,7 @@ Status Channel::StartBlockingRpc(const RpcMethod &method, const google::protobuf::Message &request, google::protobuf::Message *result) { Status status; - grpc_call *call = grpc_channel_create_call( + grpc_call *call = grpc_channel_create_call_old( c_channel_, method.name(), target_.c_str(), context->RawDeadline()); context->set_call(call); grpc_event *ev; @@ -114,8 +114,8 @@ Status Channel::StartBlockingRpc(const RpcMethod &method, // add_metadata from context // // invoke - GPR_ASSERT(grpc_call_invoke(call, cq, metadata_read_tag, finished_tag, - GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_invoke_old(call, cq, metadata_read_tag, finished_tag, + GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); // write request grpc_byte_buffer *write_buffer = nullptr; bool success = SerializeProto(request, &write_buffer); @@ -126,8 +126,8 @@ Status Channel::StartBlockingRpc(const RpcMethod &method, GetFinalStatus(cq, finished_tag, nullptr); return status; } - GPR_ASSERT(grpc_call_start_write(call, write_buffer, write_tag, - GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_write_old(call, write_buffer, write_tag, + GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); grpc_byte_buffer_destroy(write_buffer); ev = grpc_completion_queue_pluck(cq, write_tag, gpr_inf_future); @@ -138,7 +138,7 @@ Status Channel::StartBlockingRpc(const RpcMethod &method, return status; } // writes done - GPR_ASSERT(grpc_call_writes_done(call, halfclose_tag) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_writes_done_old(call, halfclose_tag) == GRPC_CALL_OK); ev = grpc_completion_queue_pluck(cq, halfclose_tag, gpr_inf_future); grpc_event_finish(ev); // start read metadata @@ -146,7 +146,7 @@ Status Channel::StartBlockingRpc(const RpcMethod &method, ev = grpc_completion_queue_pluck(cq, metadata_read_tag, gpr_inf_future); grpc_event_finish(ev); // start read - GPR_ASSERT(grpc_call_start_read(call, read_tag) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_read_old(call, read_tag) == GRPC_CALL_OK); ev = grpc_completion_queue_pluck(cq, read_tag, gpr_inf_future); if (ev->data.read) { if (!DeserializeProto(ev->data.read, result)) { @@ -167,7 +167,7 @@ StreamContextInterface *Channel::CreateStream( const RpcMethod &method, ClientContext *context, const google::protobuf::Message *request, google::protobuf::Message *result) { - grpc_call *call = grpc_channel_create_call( + grpc_call *call = grpc_channel_create_call_old( c_channel_, method.name(), target_.c_str(), context->RawDeadline()); context->set_call(call); grpc_completion_queue *cq = grpc_completion_queue_create(); diff --git a/src/cpp/server/async_server.cc b/src/cpp/server/async_server.cc index d576201b11f..86faa07b317 100644 --- a/src/cpp/server/async_server.cc +++ b/src/cpp/server/async_server.cc @@ -72,7 +72,7 @@ void AsyncServer::RequestOneRpc() { return; } lock.unlock(); - grpc_call_error err = grpc_server_request_call(server_, nullptr); + grpc_call_error err = grpc_server_request_call_old(server_, nullptr); GPR_ASSERT(err == GRPC_CALL_OK); } diff --git a/src/cpp/server/async_server_context.cc b/src/cpp/server/async_server_context.cc index 92958111c0c..2dd3cd1e8e0 100644 --- a/src/cpp/server/async_server_context.cc +++ b/src/cpp/server/async_server_context.cc @@ -53,14 +53,15 @@ AsyncServerContext::AsyncServerContext( AsyncServerContext::~AsyncServerContext() { grpc_call_destroy(call_); } void AsyncServerContext::Accept(grpc_completion_queue *cq) { - GPR_ASSERT(grpc_call_server_accept(call_, cq, this) == GRPC_CALL_OK); - GPR_ASSERT(grpc_call_server_end_initial_metadata(call_, 0) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_server_accept_old(call_, cq, this) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_server_end_initial_metadata_old(call_, 0) == + GRPC_CALL_OK); } bool AsyncServerContext::StartRead(google::protobuf::Message *request) { GPR_ASSERT(request); request_ = request; - grpc_call_error err = grpc_call_start_read(call_, this); + grpc_call_error err = grpc_call_start_read_old(call_, this); return err == GRPC_CALL_OK; } @@ -70,13 +71,13 @@ bool AsyncServerContext::StartWrite(const google::protobuf::Message &response, if (!SerializeProto(response, &buffer)) { return false; } - grpc_call_error err = grpc_call_start_write(call_, buffer, this, flags); + grpc_call_error err = grpc_call_start_write_old(call_, buffer, this, flags); grpc_byte_buffer_destroy(buffer); return err == GRPC_CALL_OK; } bool AsyncServerContext::StartWriteStatus(const Status &status) { - grpc_call_error err = grpc_call_start_write_status( + grpc_call_error err = grpc_call_start_write_status_old( call_, static_cast(status.code()), status.details().empty() ? nullptr : const_cast(status.details().c_str()), diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index 193688e743e..1abdf702e21 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -111,7 +111,7 @@ void Server::Start() { void Server::AllowOneRpc() { GPR_ASSERT(started_); - grpc_call_error err = grpc_server_request_call(server_, nullptr); + grpc_call_error err = grpc_server_request_call_old(server_, nullptr); GPR_ASSERT(err == GRPC_CALL_OK); } diff --git a/src/cpp/stream/stream_context.cc b/src/cpp/stream/stream_context.cc index edb2fc5ad9f..e4f344dbb93 100644 --- a/src/cpp/stream/stream_context.cc +++ b/src/cpp/stream/stream_context.cc @@ -80,22 +80,22 @@ void StreamContext::Start(bool buffered) { if (is_client_) { // TODO(yangg) handle metadata send path int flag = buffered ? GRPC_WRITE_BUFFER_HINT : 0; - grpc_call_error error = grpc_call_invoke( + grpc_call_error error = grpc_call_invoke_old( call(), cq(), client_metadata_read_tag(), finished_tag(), flag); GPR_ASSERT(GRPC_CALL_OK == error); } else { // TODO(yangg) metadata needs to be added before accept // TODO(yangg) correctly set flag to accept - GPR_ASSERT(grpc_call_server_accept(call(), cq(), finished_tag()) == + GPR_ASSERT(grpc_call_server_accept_old(call(), cq(), finished_tag()) == GRPC_CALL_OK); - GPR_ASSERT(grpc_call_server_end_initial_metadata(call(), 0) == + GPR_ASSERT(grpc_call_server_end_initial_metadata_old(call(), 0) == GRPC_CALL_OK); } } bool StreamContext::Read(google::protobuf::Message *msg) { // TODO(yangg) check peer_halfclosed_ here for possible early return. - grpc_call_error err = grpc_call_start_read(call(), read_tag()); + grpc_call_error err = grpc_call_start_read_old(call(), read_tag()); GPR_ASSERT(err == GRPC_CALL_OK); grpc_event *read_ev = grpc_completion_queue_pluck(cq(), read_tag(), gpr_inf_future); @@ -129,7 +129,7 @@ bool StreamContext::Write(const google::protobuf::Message *msg, bool is_last) { } int flag = is_last ? GRPC_WRITE_BUFFER_HINT : 0; grpc_call_error err = - grpc_call_start_write(call(), out_buf, write_tag(), flag); + grpc_call_start_write_old(call(), out_buf, write_tag(), flag); grpc_byte_buffer_destroy(out_buf); GPR_ASSERT(err == GRPC_CALL_OK); @@ -140,7 +140,7 @@ bool StreamContext::Write(const google::protobuf::Message *msg, bool is_last) { grpc_event_finish(ev); } if (ret && is_last) { - grpc_call_error err = grpc_call_writes_done(call(), halfclose_tag()); + grpc_call_error err = grpc_call_writes_done_old(call(), halfclose_tag()); GPR_ASSERT(err == GRPC_CALL_OK); ev = grpc_completion_queue_pluck(cq(), halfclose_tag(), gpr_inf_future); GPR_ASSERT(ev->type == GRPC_FINISH_ACCEPTED); diff --git a/src/node/.gitignore b/src/node/.gitignore new file mode 100644 index 00000000000..e3fbd98336e --- /dev/null +++ b/src/node/.gitignore @@ -0,0 +1,2 @@ +build +node_modules diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc index 3261b780f77..23aead07b29 100644 --- a/src/node/ext/call.cc +++ b/src/node/ext/call.cc @@ -152,9 +152,9 @@ NAN_METHOD(Call::New) { NanUtf8String method(args[1]); double deadline = args[2]->NumberValue(); grpc_channel *wrapped_channel = channel->GetWrappedChannel(); - grpc_call *wrapped_call = - grpc_channel_create_call(wrapped_channel, *method, channel->GetHost(), - MillisecondsToTimespec(deadline)); + grpc_call *wrapped_call = grpc_channel_create_call_old( + wrapped_channel, *method, channel->GetHost(), + MillisecondsToTimespec(deadline)); call = new Call(wrapped_call); args.This()->SetHiddenValue(String::NewSymbol("channel_"), channel_object); @@ -195,7 +195,7 @@ NAN_METHOD(Call::AddMetadata) { if (Buffer::HasInstance(value)) { metadata.value = Buffer::Data(value); metadata.value_length = Buffer::Length(value); - error = grpc_call_add_metadata(call->wrapped_call, &metadata, 0); + error = grpc_call_add_metadata_old(call->wrapped_call, &metadata, 0); } else if (value->IsString()) { Handle string_value = value->ToString(); NanUtf8String utf8_value(string_value); @@ -203,7 +203,7 @@ NAN_METHOD(Call::AddMetadata) { metadata.value_length = string_value->Length(); gpr_log(GPR_DEBUG, "adding metadata: %s, %s, %d", metadata.key, metadata.value, metadata.value_length); - error = grpc_call_add_metadata(call->wrapped_call, &metadata, 0); + error = grpc_call_add_metadata_old(call->wrapped_call, &metadata, 0); } else { return NanThrowTypeError( "addMetadata values must be strings or buffers"); @@ -232,7 +232,7 @@ NAN_METHOD(Call::Invoke) { } Call *call = ObjectWrap::Unwrap(args.This()); unsigned int flags = args[3]->Uint32Value(); - grpc_call_error error = grpc_call_invoke( + grpc_call_error error = grpc_call_invoke_old( call->wrapped_call, CompletionQueueAsyncWorker::GetQueue(), CreateTag(args[0], args.This()), CreateTag(args[1], args.This()), flags); if (error == GRPC_CALL_OK) { @@ -253,7 +253,7 @@ NAN_METHOD(Call::ServerAccept) { return NanThrowTypeError("accept's first argument must be a function"); } Call *call = ObjectWrap::Unwrap(args.This()); - grpc_call_error error = grpc_call_server_accept( + grpc_call_error error = grpc_call_server_accept_old( call->wrapped_call, CompletionQueueAsyncWorker::GetQueue(), CreateTag(args[0], args.This())); if (error == GRPC_CALL_OK) { @@ -277,7 +277,7 @@ NAN_METHOD(Call::ServerEndInitialMetadata) { Call *call = ObjectWrap::Unwrap(args.This()); unsigned int flags = args[1]->Uint32Value(); grpc_call_error error = - grpc_call_server_end_initial_metadata(call->wrapped_call, flags); + grpc_call_server_end_initial_metadata_old(call->wrapped_call, flags); if (error != GRPC_CALL_OK) { return NanThrowError("serverEndInitialMetadata failed", error); } @@ -315,7 +315,7 @@ NAN_METHOD(Call::StartWrite) { Call *call = ObjectWrap::Unwrap(args.This()); grpc_byte_buffer *buffer = BufferToByteBuffer(args[0]); unsigned int flags = args[2]->Uint32Value(); - grpc_call_error error = grpc_call_start_write( + grpc_call_error error = grpc_call_start_write_old( call->wrapped_call, buffer, CreateTag(args[1], args.This()), flags); if (error == GRPC_CALL_OK) { CompletionQueueAsyncWorker::Next(); @@ -345,7 +345,7 @@ NAN_METHOD(Call::StartWriteStatus) { } Call *call = ObjectWrap::Unwrap(args.This()); NanUtf8String details(args[1]); - grpc_call_error error = grpc_call_start_write_status( + grpc_call_error error = grpc_call_start_write_status_old( call->wrapped_call, (grpc_status_code)args[0]->Uint32Value(), *details, CreateTag(args[2], args.This())); if (error == GRPC_CALL_OK) { @@ -365,7 +365,7 @@ NAN_METHOD(Call::WritesDone) { return NanThrowTypeError("writesDone's first argument must be a function"); } Call *call = ObjectWrap::Unwrap(args.This()); - grpc_call_error error = grpc_call_writes_done( + grpc_call_error error = grpc_call_writes_done_old( call->wrapped_call, CreateTag(args[0], args.This())); if (error == GRPC_CALL_OK) { CompletionQueueAsyncWorker::Next(); @@ -384,8 +384,8 @@ NAN_METHOD(Call::StartRead) { return NanThrowTypeError("startRead's first argument must be a function"); } Call *call = ObjectWrap::Unwrap(args.This()); - grpc_call_error error = - grpc_call_start_read(call->wrapped_call, CreateTag(args[0], args.This())); + grpc_call_error error = grpc_call_start_read_old( + call->wrapped_call, CreateTag(args[0], args.This())); if (error == GRPC_CALL_OK) { CompletionQueueAsyncWorker::Next(); } else { diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc index b102775d337..6b8ccef9b17 100644 --- a/src/node/ext/server.cc +++ b/src/node/ext/server.cc @@ -175,7 +175,7 @@ NAN_METHOD(Server::RequestCall) { return NanThrowTypeError("requestCall can only be called on a Server"); } Server *server = ObjectWrap::Unwrap(args.This()); - grpc_call_error error = grpc_server_request_call( + grpc_call_error error = grpc_server_request_call_old( server->wrapped_server, CreateTag(args[0], NanNull())); if (error == GRPC_CALL_OK) { CompletionQueueAsyncWorker::Next(); diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c index b171c9c176b..bd3490b3627 100644 --- a/src/php/ext/grpc/call.c +++ b/src/php/ext/grpc/call.c @@ -135,7 +135,7 @@ int php_grpc_call_add_metadata_array_walk(void *elem TSRMLS_DC, int num_args, metadata.key = (char *)key; metadata.value = Z_STRVAL_P(*data); metadata.value_length = Z_STRLEN_P(*data); - error_code = grpc_call_add_metadata(call, &metadata, 0u); + error_code = grpc_call_add_metadata_old(call, &metadata, 0u); MAYBE_THROW_CALL_ERROR(add_metadata, error_code); break; case IS_ARRAY: @@ -188,8 +188,8 @@ PHP_METHOD(Call, __construct) { wrapped_grpc_timeval *deadline = (wrapped_grpc_timeval *)zend_object_store_get_object( deadline_obj TSRMLS_CC); - call->wrapped = grpc_channel_create_call(channel->wrapped, method, - channel->target, deadline->wrapped); + call->wrapped = grpc_channel_create_call_old( + channel->wrapped, method, channel->target, deadline->wrapped); } /** @@ -252,8 +252,8 @@ PHP_METHOD(Call, invoke) { wrapped_grpc_completion_queue *queue = (wrapped_grpc_completion_queue *)zend_object_store_get_object( queue_obj TSRMLS_CC); - error_code = grpc_call_invoke(call->wrapped, queue->wrapped, (void *)tag1, - (void *)tag2, (gpr_uint32)flags); + error_code = grpc_call_invoke_old(call->wrapped, queue->wrapped, (void *)tag1, + (void *)tag2, (gpr_uint32)flags); MAYBE_THROW_CALL_ERROR(invoke, error_code); } @@ -287,7 +287,7 @@ PHP_METHOD(Call, server_accept) { (wrapped_grpc_completion_queue *)zend_object_store_get_object( queue_obj TSRMLS_CC); error_code = - grpc_call_server_accept(call->wrapped, queue->wrapped, (void *)tag); + grpc_call_server_accept_old(call->wrapped, queue->wrapped, (void *)tag); MAYBE_THROW_CALL_ERROR(server_accept, error_code); } @@ -303,7 +303,7 @@ PHP_METHOD(Call, server_end_initial_metadata) { } wrapped_grpc_call *call = (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC); - error_code = grpc_call_server_end_initial_metadata(call->wrapped, flags); + error_code = grpc_call_server_end_initial_metadata_old(call->wrapped, flags); MAYBE_THROW_CALL_ERROR(server_end_initial_metadata, error_code); } @@ -342,9 +342,9 @@ PHP_METHOD(Call, start_write) { 1 TSRMLS_CC); return; } - error_code = grpc_call_start_write(call->wrapped, - string_to_byte_buffer(buffer, buffer_len), - (void *)tag, (gpr_uint32)flags); + error_code = grpc_call_start_write_old( + call->wrapped, string_to_byte_buffer(buffer, buffer_len), (void *)tag, + (gpr_uint32)flags); MAYBE_THROW_CALL_ERROR(start_write, error_code); } @@ -372,9 +372,9 @@ PHP_METHOD(Call, start_write_status) { "start_write_status expects a long, a string, and a long", 1 TSRMLS_CC); return; } - error_code = - grpc_call_start_write_status(call->wrapped, (grpc_status_code)status_code, - status_details, (void *)tag); + error_code = grpc_call_start_write_status_old(call->wrapped, + (grpc_status_code)status_code, + status_details, (void *)tag); MAYBE_THROW_CALL_ERROR(start_write_status, error_code); } @@ -393,7 +393,7 @@ PHP_METHOD(Call, writes_done) { "writes_done expects a long", 1 TSRMLS_CC); return; } - error_code = grpc_call_writes_done(call->wrapped, (void *)tag); + error_code = grpc_call_writes_done_old(call->wrapped, (void *)tag); MAYBE_THROW_CALL_ERROR(writes_done, error_code); } @@ -414,7 +414,7 @@ PHP_METHOD(Call, start_read) { "start_read expects a long", 1 TSRMLS_CC); return; } - error_code = grpc_call_start_read(call->wrapped, (void *)tag); + error_code = grpc_call_start_read_old(call->wrapped, (void *)tag); MAYBE_THROW_CALL_ERROR(start_read, error_code); } diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c index 38777f3d541..bc4fcf07c9c 100644 --- a/src/php/ext/grpc/server.c +++ b/src/php/ext/grpc/server.c @@ -125,7 +125,7 @@ PHP_METHOD(Server, request_call) { "request_call expects a long", 1 TSRMLS_CC); return; } - error_code = grpc_server_request_call(server->wrapped, (void *)tag_new); + error_code = grpc_server_request_call_old(server->wrapped, (void *)tag_new); MAYBE_THROW_CALL_ERROR(request_call, error_code); } diff --git a/src/python/src/_adapter/_call.c b/src/python/src/_adapter/_call.c index 1f91090f7dc..b4ac503dafe 100644 --- a/src/python/src/_adapter/_call.c +++ b/src/python/src/_adapter/_call.c @@ -56,9 +56,9 @@ static int pygrpc_call_init(Call *self, PyObject *args, PyObject *kwds) { /* TODO(nathaniel): Hoist the gpr_timespec <-> PyFloat arithmetic into its own * function with its own test coverage. */ - self->c_call = - grpc_channel_create_call(((Channel *)channel)->c_channel, method, host, - gpr_time_from_nanos(deadline * GPR_NS_PER_SEC)); + self->c_call = grpc_channel_create_call_old( + ((Channel *)channel)->c_channel, method, host, + gpr_time_from_nanos(deadline * GPR_NS_PER_SEC)); return 0; } @@ -70,7 +70,7 @@ static void pygrpc_call_dealloc(Call *self) { self->ob_type->tp_free((PyObject *)self); } -static const PyObject *pygrpc_call_invoke(Call *self, PyObject *args) { +static const PyObject *pygrpc_call_invoke_old(Call *self, PyObject *args) { const PyObject *completion_queue; const PyObject *metadata_tag; const PyObject *finish_tag; @@ -82,7 +82,7 @@ static const PyObject *pygrpc_call_invoke(Call *self, PyObject *args) { return NULL; } - call_error = grpc_call_invoke( + call_error = grpc_call_invoke_old( self->c_call, ((CompletionQueue *)completion_queue)->c_completion_queue, (void *)metadata_tag, (void *)finish_tag, 0); @@ -111,7 +111,8 @@ static const PyObject *pygrpc_call_write(Call *self, PyObject *args) { byte_buffer = grpc_byte_buffer_create(&slice, 1); gpr_slice_unref(slice); - call_error = grpc_call_start_write(self->c_call, byte_buffer, (void *)tag, 0); + call_error = + grpc_call_start_write_old(self->c_call, byte_buffer, (void *)tag, 0); grpc_byte_buffer_destroy(byte_buffer); @@ -131,7 +132,7 @@ static const PyObject *pygrpc_call_complete(Call *self, PyObject *args) { return NULL; } - call_error = grpc_call_writes_done(self->c_call, (void *)tag); + call_error = grpc_call_writes_done_old(self->c_call, (void *)tag); result = pygrpc_translate_call_error(call_error); if (result != NULL) { @@ -151,7 +152,7 @@ static const PyObject *pygrpc_call_accept(Call *self, PyObject *args) { return NULL; } - call_error = grpc_call_server_accept( + call_error = grpc_call_server_accept_old( self->c_call, ((CompletionQueue *)completion_queue)->c_completion_queue, (void *)tag); result = pygrpc_translate_call_error(call_error); @@ -166,7 +167,7 @@ static const PyObject *pygrpc_call_accept(Call *self, PyObject *args) { static const PyObject *pygrpc_call_premetadata(Call *self, PyObject *args) { /* TODO(b/18702680): Actually support metadata. */ return pygrpc_translate_call_error( - grpc_call_server_end_initial_metadata(self->c_call, 0)); + grpc_call_server_end_initial_metadata_old(self->c_call, 0)); } static const PyObject *pygrpc_call_read(Call *self, PyObject *args) { @@ -178,7 +179,7 @@ static const PyObject *pygrpc_call_read(Call *self, PyObject *args) { return NULL; } - call_error = grpc_call_start_read(self->c_call, (void *)tag); + call_error = grpc_call_start_read_old(self->c_call, (void *)tag); result = pygrpc_translate_call_error(call_error); if (result != NULL) { @@ -208,8 +209,8 @@ static const PyObject *pygrpc_call_status(Call *self, PyObject *args) { Py_DECREF(code); Py_DECREF(details); - call_error = grpc_call_start_write_status(self->c_call, c_code, c_message, - (void *)tag); + call_error = grpc_call_start_write_status_old(self->c_call, c_code, c_message, + (void *)tag); result = pygrpc_translate_call_error(call_error); if (result != NULL) { diff --git a/src/python/src/_adapter/_server.c b/src/python/src/_adapter/_server.c index a40d32ff516..d2730d9ae87 100644 --- a/src/python/src/_adapter/_server.c +++ b/src/python/src/_adapter/_server.c @@ -88,7 +88,7 @@ static const PyObject *pygrpc_server_service(Server *self, PyObject *args) { return NULL; } - call_error = grpc_server_request_call(self->c_server, (void *)tag); + call_error = grpc_server_request_call_old(self->c_server, (void *)tag); result = pygrpc_translate_call_error(call_error); if (result != NULL) { diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c index 1b6565f729a..5d723076682 100644 --- a/src/ruby/ext/grpc/rb_call.c +++ b/src/ruby/ext/grpc/rb_call.c @@ -125,7 +125,7 @@ int grpc_rb_call_add_metadata_hash_cb(VALUE key, VALUE val, VALUE call_obj) { md_obj_args[1] = rb_ary_entry(val, i); md_obj = rb_class_new_instance(2, md_obj_args, rb_cMetadata); md = grpc_rb_get_wrapped_metadata(md_obj); - err = grpc_call_add_metadata(call, md, NUM2UINT(flags)); + err = grpc_call_add_metadata_old(call, md, NUM2UINT(flags)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "add metadata failed: %s (code=%d)", grpc_call_error_detail_of(err), err); @@ -136,7 +136,7 @@ int grpc_rb_call_add_metadata_hash_cb(VALUE key, VALUE val, VALUE call_obj) { md_obj_args[1] = val; md_obj = rb_class_new_instance(2, md_obj_args, rb_cMetadata); md = grpc_rb_get_wrapped_metadata(md_obj); - err = grpc_call_add_metadata(call, md, NUM2UINT(flags)); + err = grpc_call_add_metadata_old(call, md, NUM2UINT(flags)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "add metadata failed: %s (code=%d)", grpc_call_error_detail_of(err), err); @@ -220,8 +220,8 @@ static VALUE grpc_rb_call_invoke(int argc, VALUE *argv, VALUE self) { } cq = grpc_rb_get_wrapped_completion_queue(cqueue); Data_Get_Struct(self, grpc_call, call); - err = grpc_call_invoke(call, cq, ROBJECT(metadata_read_tag), - ROBJECT(finished_tag), NUM2UINT(flags)); + err = grpc_call_invoke_old(call, cq, ROBJECT(metadata_read_tag), + ROBJECT(finished_tag), NUM2UINT(flags)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "invoke failed: %s (code=%d)", grpc_call_error_detail_of(err), err); @@ -242,7 +242,7 @@ static VALUE grpc_rb_call_start_read(VALUE self, VALUE tag) { grpc_call *call = NULL; grpc_call_error err; Data_Get_Struct(self, grpc_call, call); - err = grpc_call_start_read(call, ROBJECT(tag)); + err = grpc_call_start_read_old(call, ROBJECT(tag)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "start read failed: %s (code=%d)", grpc_call_error_detail_of(err), err); @@ -330,7 +330,7 @@ static VALUE grpc_rb_call_start_write(int argc, VALUE *argv, VALUE self) { } bfr = grpc_rb_get_wrapped_byte_buffer(byte_buffer); Data_Get_Struct(self, grpc_call, call); - err = grpc_call_start_write(call, bfr, ROBJECT(tag), NUM2UINT(flags)); + err = grpc_call_start_write_old(call, bfr, ROBJECT(tag), NUM2UINT(flags)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "start write failed: %s (code=%d)", grpc_call_error_detail_of(err), err); @@ -358,8 +358,8 @@ static VALUE grpc_rb_call_start_write_status(VALUE self, VALUE code, grpc_call *call = NULL; grpc_call_error err; Data_Get_Struct(self, grpc_call, call); - err = grpc_call_start_write_status(call, NUM2UINT(code), - StringValueCStr(status), ROBJECT(tag)); + err = grpc_call_start_write_status_old(call, NUM2UINT(code), + StringValueCStr(status), ROBJECT(tag)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "start write status: %s (code=%d)", grpc_call_error_detail_of(err), err); @@ -374,7 +374,7 @@ static VALUE grpc_rb_call_writes_done(VALUE self, VALUE tag) { grpc_call *call = NULL; grpc_call_error err; Data_Get_Struct(self, grpc_call, call); - err = grpc_call_writes_done(call, ROBJECT(tag)); + err = grpc_call_writes_done_old(call, ROBJECT(tag)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "writes done: %s (code=%d)", grpc_call_error_detail_of(err), err); @@ -405,7 +405,7 @@ static VALUE grpc_rb_call_server_end_initial_metadata(int argc, VALUE *argv, flags = UINT2NUM(0); /* Default to no flags */ } Data_Get_Struct(self, grpc_call, call); - err = grpc_call_server_end_initial_metadata(call, NUM2UINT(flags)); + err = grpc_call_server_end_initial_metadata_old(call, NUM2UINT(flags)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "end_initial_metadata failed: %s (code=%d)", grpc_call_error_detail_of(err), err); @@ -430,7 +430,7 @@ static VALUE grpc_rb_call_server_accept(VALUE self, VALUE cqueue, grpc_completion_queue *cq = grpc_rb_get_wrapped_completion_queue(cqueue); grpc_call_error err; Data_Get_Struct(self, grpc_call, call); - err = grpc_call_server_accept(call, cq, ROBJECT(finished_tag)); + err = grpc_call_server_accept_old(call, cq, ROBJECT(finished_tag)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "server_accept failed: %s (code=%d)", grpc_call_error_detail_of(err), err); diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index c0187d2d117..7c98e66c33d 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -192,9 +192,10 @@ static VALUE grpc_rb_channel_create_call(VALUE self, VALUE method, VALUE host, rb_raise(rb_eRuntimeError, "closed!"); } - call = grpc_channel_create_call(ch, method_chars, host_chars, - grpc_rb_time_timeval(deadline, - /* absolute time */ 0)); + call = + grpc_channel_create_call_old(ch, method_chars, host_chars, + grpc_rb_time_timeval(deadline, + /* absolute time */ 0)); if (call == NULL) { rb_raise(rb_eRuntimeError, "cannot create call with method %s", method_chars); diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 436d0067603..e68843e12b1 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -175,7 +175,7 @@ static VALUE grpc_rb_server_request_call(VALUE self, VALUE tag_new) { if (s->wrapped == NULL) { rb_raise(rb_eRuntimeError, "closed!"); } else { - err = grpc_server_request_call(s->wrapped, ROBJECT(tag_new)); + err = grpc_server_request_call_old(s->wrapped, ROBJECT(tag_new)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "server request failed: %s (code=%d)", grpc_call_error_detail_of(err), err); diff --git a/test/core/echo/client.c b/test/core/echo/client.c index bb478c4b4b8..5652fd9f38b 100644 --- a/test/core/echo/client.c +++ b/test/core/echo/client.c @@ -52,7 +52,7 @@ static void start_write_next_slice(grpc_call *call, int first, int length) { for (i = 0; i < length; i++) GPR_SLICE_START_PTR(slice)[i] = (first + i) % 256; byte_buffer = grpc_byte_buffer_create(&slice, 1); - GPR_ASSERT(grpc_call_start_write(call, byte_buffer, (void *)1, 0) == + GPR_ASSERT(grpc_call_start_write_old(call, byte_buffer, (void *)1, 0) == GRPC_CALL_OK); gpr_slice_unref(slice); grpc_byte_buffer_destroy(byte_buffer); @@ -78,15 +78,15 @@ int main(int argc, char **argv) { GPR_ASSERT(argc == 2); channel = grpc_channel_create(argv[1], NULL); - call = grpc_channel_create_call(channel, "/foo", "localhost", - gpr_time_add(gpr_time_from_seconds(5), - gpr_now())); - GPR_ASSERT(grpc_call_invoke(call, cq, (void *)1, (void *)1, 0) == + call = grpc_channel_create_call_old( + channel, "/foo", "localhost", + gpr_time_add(gpr_time_from_seconds(5), gpr_now())); + GPR_ASSERT(grpc_call_invoke_old(call, cq, (void *)1, (void *)1, 0) == GRPC_CALL_OK); start_write_next_slice(call, bytes_written, WRITE_SLICE_LENGTH); bytes_written += WRITE_SLICE_LENGTH; - GPR_ASSERT(grpc_call_start_read(call, (void *)1) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_read_old(call, (void *)1) == GRPC_CALL_OK); waiting_finishes = 2; while (waiting_finishes) { ev = grpc_completion_queue_next(cq, gpr_inf_future); @@ -96,7 +96,8 @@ int main(int argc, char **argv) { start_write_next_slice(call, bytes_written, WRITE_SLICE_LENGTH); bytes_written += WRITE_SLICE_LENGTH; } else { - GPR_ASSERT(grpc_call_writes_done(call, (void *)1) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_writes_done_old(call, (void *)1) == + GRPC_CALL_OK); } break; case GRPC_CLIENT_METADATA_READ: @@ -112,7 +113,7 @@ int main(int argc, char **argv) { } grpc_byte_buffer_reader_destroy(bb_reader); if (bytes_read < TOTAL_BYTES) { - GPR_ASSERT(grpc_call_start_read(call, (void *)1) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_read_old(call, (void *)1) == GRPC_CALL_OK); } break; case GRPC_FINISHED: diff --git a/test/core/echo/server.c b/test/core/echo/server.c index 2764a9ef0e0..6e494d50fff 100644 --- a/test/core/echo/server.c +++ b/test/core/echo/server.c @@ -64,7 +64,7 @@ static void request_call(void) { call_state *tag = gpr_malloc(sizeof(*tag)); gpr_ref_init(&tag->pending_ops, 2); tag->bytes_read = 0; - grpc_server_request_call(server, tag); + grpc_server_request_call_old(server, tag); } static void assert_read_ok(call_state *s, grpc_byte_buffer *b) { @@ -173,10 +173,10 @@ int main(int argc, char **argv) { case GRPC_SERVER_RPC_NEW: if (ev->call != NULL) { /* initial ops are already started in request_call */ - grpc_call_server_accept(ev->call, cq, s); - grpc_call_server_end_initial_metadata(ev->call, - GRPC_WRITE_BUFFER_HINT); - GPR_ASSERT(grpc_call_start_read(ev->call, s) == GRPC_CALL_OK); + grpc_call_server_accept_old(ev->call, cq, s); + grpc_call_server_end_initial_metadata_old(ev->call, + GRPC_WRITE_BUFFER_HINT); + GPR_ASSERT(grpc_call_start_read_old(ev->call, s) == GRPC_CALL_OK); request_call(); } else { GPR_ASSERT(shutdown_started); @@ -185,17 +185,17 @@ int main(int argc, char **argv) { break; case GRPC_WRITE_ACCEPTED: GPR_ASSERT(ev->data.write_accepted == GRPC_OP_OK); - GPR_ASSERT(grpc_call_start_read(ev->call, s) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_read_old(ev->call, s) == GRPC_CALL_OK); break; case GRPC_READ: if (ev->data.read) { assert_read_ok(ev->tag, ev->data.read); - GPR_ASSERT(grpc_call_start_write(ev->call, ev->data.read, s, - GRPC_WRITE_BUFFER_HINT) == + GPR_ASSERT(grpc_call_start_write_old(ev->call, ev->data.read, s, + GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); } else { - GPR_ASSERT(grpc_call_start_write_status(ev->call, GRPC_STATUS_OK, - NULL, s) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_write_status_old(ev->call, GRPC_STATUS_OK, + NULL, s) == GRPC_CALL_OK); } break; case GRPC_FINISH_ACCEPTED: diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c index 6219f575002..eeb454ca581 100644 --- a/test/core/end2end/dualstack_socket_test.c +++ b/test/core/end2end/dualstack_socket_test.c @@ -112,29 +112,31 @@ void test_connect(const char *server_host, const char *client_host, int port, } /* Send a trivial request. */ - c = grpc_channel_create_call(client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(client, "/foo", "test.google.com", deadline); GPR_ASSERT(c); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke(c, client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_invoke_old(c, client_cq, tag(2), tag(3), 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4))); if (expect_ok) { /* Check for a successful request. */ cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write_status(s, GRPC_STATUS_UNIMPLEMENTED, "xyz", - tag(5))); + grpc_call_start_write_status_old(s, GRPC_STATUS_UNIMPLEMENTED, + "xyz", tag(5))); cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); cq_verify(v_client); diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c index 389a6429c48..85d95338ddb 100644 --- a/test/core/end2end/no_server_test.c +++ b/test/core/end2end/no_server_test.c @@ -56,8 +56,8 @@ int main(int argc, char **argv) { /* create a call, channel to a non existant server */ chan = grpc_channel_create("nonexistant:54321", NULL); - call = grpc_channel_create_call(chan, "/foo", "nonexistant", deadline); - GPR_ASSERT(grpc_call_invoke(call, cq, tag(2), tag(3), 0) == GRPC_CALL_OK); + call = grpc_channel_create_call_old(chan, "/foo", "nonexistant", deadline); + GPR_ASSERT(grpc_call_invoke_old(call, cq, tag(2), tag(3), 0) == GRPC_CALL_OK); /* verify that all tags get completed */ cq_expect_client_metadata_read(cqv, tag(2), NULL); cq_expect_finished_with_status(cqv, tag(3), GRPC_STATUS_DEADLINE_EXCEEDED, diff --git a/test/core/end2end/tests/cancel_after_accept.c b/test/core/end2end/tests/cancel_after_accept.c index 05a2dc8bbb8..f9bf9fabf40 100644 --- a/test/core/end2end/tests/cancel_after_accept.c +++ b/test/core/end2end/tests/cancel_after_accept.c @@ -113,19 +113,21 @@ static void test_cancel_after_accept(grpc_end2end_test_config config, cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); diff --git a/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c b/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c index db245a37e1b..b8a1438ca43 100644 --- a/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c +++ b/test/core/end2end/tests/cancel_after_accept_and_writes_closed.c @@ -113,27 +113,29 @@ static void test_cancel_after_accept_and_writes_closed( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4))); cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(s, tag(101))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(101))); cq_expect_empty_read(v_server, tag(101)); cq_verify(v_server); diff --git a/test/core/end2end/tests/cancel_after_invoke.c b/test/core/end2end/tests/cancel_after_invoke.c index 5dfb3f756ab..8b282230405 100644 --- a/test/core/end2end/tests/cancel_after_invoke.c +++ b/test/core/end2end/tests/cancel_after_invoke.c @@ -111,11 +111,12 @@ static void test_cancel_after_invoke(grpc_end2end_test_config config, gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c)); diff --git a/test/core/end2end/tests/cancel_before_invoke.c b/test/core/end2end/tests/cancel_before_invoke.c index ac816484fd6..5851277d201 100644 --- a/test/core/end2end/tests/cancel_before_invoke.c +++ b/test/core/end2end/tests/cancel_before_invoke.c @@ -109,13 +109,14 @@ static void test_cancel_before_invoke(grpc_end2end_test_config config) { gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_CANCELLED, NULL, NULL); diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.c b/test/core/end2end/tests/cancel_in_a_vacuum.c index 5257ece297e..6b5194fb07f 100644 --- a/test/core/end2end/tests/cancel_in_a_vacuum.c +++ b/test/core/end2end/tests/cancel_in_a_vacuum.c @@ -109,7 +109,8 @@ static void test_cancel_in_a_vacuum(grpc_end2end_test_config config, gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c)); diff --git a/test/core/end2end/tests/census_simple_request.c b/test/core/end2end/tests/census_simple_request.c index 86cef437be8..1edb5b0d3a1 100644 --- a/test/core/end2end/tests/census_simple_request.c +++ b/test/core/end2end/tests/census_simple_request.c @@ -106,27 +106,29 @@ static void test_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); tag(1); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4))); cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5))); cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); diff --git a/test/core/end2end/tests/disappearing_server.c b/test/core/end2end/tests/disappearing_server.c index 036fdc2501f..9b2f16890bd 100644 --- a/test/core/end2end/tests/disappearing_server.c +++ b/test/core/end2end/tests/disappearing_server.c @@ -97,24 +97,25 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f, grpc_call *s; gpr_timespec deadline = five_seconds_time(); - c = grpc_channel_create_call(f->client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f->client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f->client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f->client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4))); cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f->server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_server_accept(s, f->server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + grpc_call_server_accept_old(s, f->server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); @@ -122,7 +123,7 @@ static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f, - and still complete the request */ grpc_server_shutdown(f->server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5))); cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); diff --git a/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c b/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c index 66e3c44f4b9..a9d34e2db5a 100644 --- a/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c +++ b/test/core/end2end/tests/early_server_shutdown_finishes_inflight_calls.c @@ -111,23 +111,25 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4))); cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); diff --git a/test/core/end2end/tests/early_server_shutdown_finishes_tags.c b/test/core/end2end/tests/early_server_shutdown_finishes_tags.c index 88f735c8e0a..123c8bc4153 100644 --- a/test/core/end2end/tests/early_server_shutdown_finishes_tags.c +++ b/test/core/end2end/tests/early_server_shutdown_finishes_tags.c @@ -110,7 +110,7 @@ static void test_early_server_shutdown_finishes_tags( /* upon shutdown, the server should finish all requested calls indicating no new call */ - grpc_server_request_call(f.server, tag(1000)); + grpc_server_request_call_old(f.server, tag(1000)); grpc_server_shutdown(f.server); cq_expect_server_rpc_new(v_server, &s, tag(1000), NULL, NULL, gpr_inf_past, NULL); diff --git a/test/core/end2end/tests/graceful_server_shutdown.c b/test/core/end2end/tests/graceful_server_shutdown.c index d9c9dbb8b20..dcd6192799a 100644 --- a/test/core/end2end/tests/graceful_server_shutdown.c +++ b/test/core/end2end/tests/graceful_server_shutdown.c @@ -110,23 +110,25 @@ static void test_early_server_shutdown_finishes_inflight_calls( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4))); cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); @@ -134,7 +136,7 @@ static void test_early_server_shutdown_finishes_inflight_calls( grpc_server_shutdown_and_notify(f.server, tag(0xdead)); cq_verify_empty(v_server); - grpc_call_start_write_status(s, GRPC_STATUS_OK, NULL, tag(103)); + grpc_call_start_write_status_old(s, GRPC_STATUS_OK, NULL, tag(103)); grpc_call_destroy(s); cq_expect_finish_accepted(v_server, tag(103), GRPC_OP_OK); cq_expect_finished(v_server, tag(102), NULL); diff --git a/test/core/end2end/tests/invoke_large_request.c b/test/core/end2end/tests/invoke_large_request.c index f187eceadb3..7774fe4521d 100644 --- a/test/core/end2end/tests/invoke_large_request.c +++ b/test/core/end2end/tests/invoke_large_request.c @@ -120,16 +120,17 @@ static void test_invoke_large_request(grpc_end2end_test_config config) { /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(request_payload_slice); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(c, request_payload, tag(4), 0)); + grpc_call_start_write_old(c, request_payload, tag(4), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(request_payload); @@ -141,20 +142,21 @@ static void test_invoke_large_request(grpc_end2end_test_config config) { deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(s, tag(5))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5))); /* now the write can be accepted */ cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); cq_expect_read(v_server, tag(5), large_slice()); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(8))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9))); cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK); diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c index a177a7b2f29..0e26577903f 100644 --- a/test/core/end2end/tests/max_concurrent_streams.c +++ b/test/core/end2end/tests/max_concurrent_streams.c @@ -109,27 +109,29 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4))); cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5))); cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); @@ -181,20 +183,21 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { /* start two requests - ensuring that the second is not accepted until the first completes */ deadline = five_seconds_time(); - c1 = - grpc_channel_create_call(f.client, "/alpha", "test.google.com", deadline); + c1 = grpc_channel_create_call_old(f.client, "/alpha", "test.google.com", + deadline); GPR_ASSERT(c1); - c2 = grpc_channel_create_call(f.client, "/beta", "test.google.com", deadline); + c2 = grpc_channel_create_call_old(f.client, "/beta", "test.google.com", + deadline); GPR_ASSERT(c1); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c1, f.client_cq, tag(301), tag(302), 0)); + grpc_call_invoke_old(c1, f.client_cq, tag(301), tag(302), 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c2, f.client_cq, tag(401), tag(402), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c1, tag(303))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c2, tag(303))); + grpc_call_invoke_old(c2, f.client_cq, tag(401), tag(402), 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c1, tag(303))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c2, tag(303))); ev = grpc_completion_queue_next( f.client_cq, gpr_time_add(gpr_now(), gpr_time_from_seconds(10))); @@ -213,14 +216,14 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_server_accept(s1, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s1, 0)); + grpc_call_server_accept_old(s1, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s1, 0)); cq_expect_client_metadata_read(v_client, tag(live_call + 1), NULL); cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write_status(s1, GRPC_STATUS_UNIMPLEMENTED, "xyz", - tag(103))); + grpc_call_start_write_status_old(s1, GRPC_STATUS_UNIMPLEMENTED, + "xyz", tag(103))); cq_expect_finish_accepted(v_server, tag(103), GRPC_OP_OK); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); @@ -232,21 +235,21 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { live_call = (live_call == 300) ? 400 : 300; cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(200))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(200))); cq_expect_server_rpc_new(v_server, &s2, tag(200), live_call == 300 ? "/alpha" : "/beta", "test.google.com", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_server_accept(s2, f.server_cq, tag(202))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s2, 0)); + grpc_call_server_accept_old(s2, f.server_cq, tag(202))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s2, 0)); cq_expect_client_metadata_read(v_client, tag(live_call + 1), NULL); cq_verify(v_client); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write_status(s2, GRPC_STATUS_UNIMPLEMENTED, "xyz", - tag(203))); + grpc_call_start_write_status_old(s2, GRPC_STATUS_UNIMPLEMENTED, + "xyz", tag(203))); cq_expect_finish_accepted(v_server, tag(203), GRPC_OP_OK); cq_expect_finished(v_server, tag(202), NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/ping_pong_streaming.c b/test/core/end2end/tests/ping_pong_streaming.c index 6768bd8aa9f..0c034a1996e 100644 --- a/test/core/end2end/tests/ping_pong_streaming.c +++ b/test/core/end2end/tests/ping_pong_streaming.c @@ -118,19 +118,21 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, cq_verifier *v_server = cq_verifier_create(f.server_cq); gpr_log(GPR_INFO, "testing with %d message pairs.", messages); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); @@ -138,7 +140,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, for (i = 0; i < messages; i++) { request_payload = grpc_byte_buffer_create(&request_payload_slice, 1); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(c, request_payload, tag(2), 0)); + grpc_call_start_write_old(c, request_payload, tag(2), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ @@ -146,14 +148,14 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, cq_expect_write_accepted(v_client, tag(2), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(s, tag(3))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(3))); cq_expect_read(v_server, tag(3), gpr_slice_from_copied_string("hello world")); cq_verify(v_server); response_payload = grpc_byte_buffer_create(&response_payload_slice, 1); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(s, response_payload, tag(4), 0)); + grpc_call_start_write_old(s, response_payload, tag(4), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ @@ -161,7 +163,7 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, cq_expect_write_accepted(v_server, tag(4), GRPC_OP_OK); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(c, tag(5))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(5))); cq_expect_read(v_client, tag(5), gpr_slice_from_copied_string("hello you")); cq_verify(v_client); } @@ -169,8 +171,8 @@ static void test_pingpong_streaming(grpc_end2end_test_config config, gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(6))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(6))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(7))); cq_expect_finish_accepted(v_client, tag(6), GRPC_OP_OK); diff --git a/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c index 1dd798dc8d6..daadcf619be 100644 --- a/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_binary_metadata_and_payload.c @@ -131,24 +131,25 @@ static void test_request_response_with_metadata_and_payload( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); /* add multiple metadata */ - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(c, &meta1, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(c, &meta2, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta1, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta2, 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(c, request_payload, tag(4), 0)); + grpc_call_start_write_old(c, request_payload, tag(4), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(request_payload); @@ -161,20 +162,20 @@ static void test_request_response_with_metadata_and_payload( "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d", NULL); cq_verify(v_server); - grpc_call_server_accept(s, f.server_cq, tag(102)); + grpc_call_server_accept_old(s, f.server_cq, tag(102)); /* add multiple metadata */ - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(s, &meta3, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(s, &meta4, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta3, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta4, 0)); - grpc_call_server_end_initial_metadata(s, 0); + grpc_call_server_end_initial_metadata_old(s, 0); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(s, tag(5))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5))); cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world")); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(s, response_payload, tag(6), 0)); + grpc_call_start_write_old(s, response_payload, tag(6), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(response_payload); @@ -189,12 +190,12 @@ static void test_request_response_with_metadata_and_payload( "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(c, tag(7))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7))); cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you")); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(8))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9))); cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK); diff --git a/test/core/end2end/tests/request_response_with_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_metadata_and_payload.c index cfc9b61f56f..0a58398c4ae 100644 --- a/test/core/end2end/tests/request_response_with_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_metadata_and_payload.c @@ -122,24 +122,25 @@ static void test_request_response_with_metadata_and_payload( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); /* add multiple metadata */ - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(c, &meta1, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(c, &meta2, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta1, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta2, 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(c, request_payload, tag(4), 0)); + grpc_call_start_write_old(c, request_payload, tag(4), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(request_payload); @@ -150,20 +151,20 @@ static void test_request_response_with_metadata_and_payload( deadline, "key1", "val1", "key2", "val2", NULL); cq_verify(v_server); - grpc_call_server_accept(s, f.server_cq, tag(102)); + grpc_call_server_accept_old(s, f.server_cq, tag(102)); /* add multiple metadata */ - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(s, &meta3, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(s, &meta4, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta3, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta4, 0)); - grpc_call_server_end_initial_metadata(s, 0); + grpc_call_server_end_initial_metadata_old(s, 0); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(s, tag(5))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5))); cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world")); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(s, response_payload, tag(6), 0)); + grpc_call_start_write_old(s, response_payload, tag(6), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(response_payload); @@ -175,12 +176,12 @@ static void test_request_response_with_metadata_and_payload( "val4", NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(c, tag(7))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7))); cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you")); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(8))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9))); cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK); diff --git a/test/core/end2end/tests/request_response_with_payload.c b/test/core/end2end/tests/request_response_with_payload.c index 32bf5129ff4..d3b237bc340 100644 --- a/test/core/end2end/tests/request_response_with_payload.c +++ b/test/core/end2end/tests/request_response_with_payload.c @@ -119,16 +119,17 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) { gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(c, request_payload, tag(4), 0)); + grpc_call_start_write_old(c, request_payload, tag(4), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(request_payload); @@ -139,28 +140,29 @@ static void request_response_with_payload(grpc_end2end_test_fixture f) { deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(s, tag(5))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5))); cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world")); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(s, response_payload, tag(6), 0)); + grpc_call_start_write_old(s, response_payload, tag(6), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(response_payload); cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(c, tag(7))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7))); cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you")); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(8))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9))); cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK); diff --git a/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c index 4f1de8b466e..f5f0e646ea9 100644 --- a/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c +++ b/test/core/end2end/tests/request_response_with_trailing_metadata_and_payload.c @@ -124,24 +124,25 @@ static void test_request_response_with_metadata_and_payload( cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); /* add multiple metadata */ - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(c, &meta1, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(c, &meta2, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta1, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta2, 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(c, request_payload, tag(4), 0)); + grpc_call_start_write_old(c, request_payload, tag(4), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(request_payload); @@ -152,23 +153,23 @@ static void test_request_response_with_metadata_and_payload( deadline, "key1", "val1", "key2", "val2", NULL); cq_verify(v_server); - grpc_call_server_accept(s, f.server_cq, tag(102)); + grpc_call_server_accept_old(s, f.server_cq, tag(102)); /* add multiple metadata */ - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(s, &meta3, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(s, &meta4, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta3, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta4, 0)); - grpc_call_server_end_initial_metadata(s, 0); + grpc_call_server_end_initial_metadata_old(s, 0); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(s, &meta5, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(s, &meta6, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta5, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(s, &meta6, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(s, tag(5))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5))); cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world")); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(s, response_payload, tag(6), 0)); + grpc_call_start_write_old(s, response_payload, tag(6), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(response_payload); @@ -180,12 +181,12 @@ static void test_request_response_with_metadata_and_payload( "val4", NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(c, tag(7))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(7))); cq_expect_read(v_client, tag(7), gpr_slice_from_copied_string("hello you")); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(8))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(9))); cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK); diff --git a/test/core/end2end/tests/request_with_large_metadata.c b/test/core/end2end/tests/request_with_large_metadata.c index 83628449a22..f6c892cbcb5 100644 --- a/test/core/end2end/tests/request_with_large_metadata.c +++ b/test/core/end2end/tests/request_with_large_metadata.c @@ -113,7 +113,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { cq_verifier *v_server = cq_verifier_create(f.server_cq); const int large_size = 64 * 1024; - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); meta.key = "key"; meta.value = gpr_malloc(large_size + 1); @@ -121,14 +121,15 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { meta.value[large_size] = 0; meta.value_length = large_size; - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); /* add the metadata */ - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(c, &meta, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(c, &meta, 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, "key", meta.value, NULL); @@ -140,9 +141,9 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config) { cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(8))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(8))); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write_status(s, GRPC_STATUS_OK, NULL, tag(9))); + grpc_call_start_write_status_old(s, GRPC_STATUS_OK, NULL, tag(9))); cq_expect_finish_accepted(v_client, tag(8), GRPC_OP_OK); cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_OK, NULL, NULL); diff --git a/test/core/end2end/tests/request_with_payload.c b/test/core/end2end/tests/request_with_payload.c index a3527839659..caf5d0eb9ef 100644 --- a/test/core/end2end/tests/request_with_payload.c +++ b/test/core/end2end/tests/request_with_payload.c @@ -116,15 +116,16 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) { /* byte buffer holds the slice, we can unref it already */ gpr_slice_unref(payload_slice); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write(c, payload, tag(4), 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_old(c, payload, tag(4), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(payload); @@ -139,11 +140,11 @@ static void test_invoke_request_with_payload(grpc_end2end_test_config config) { cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(s, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(4))); cq_expect_read(v_server, tag(4), gpr_slice_from_copied_string("hello world")); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(5))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(5))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(6))); cq_expect_finish_accepted(v_client, tag(5), GRPC_OP_OK); cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED, diff --git a/test/core/end2end/tests/simple_delayed_request.c b/test/core/end2end/tests/simple_delayed_request.c index 1e15eaa9cc4..a982bb5e1b5 100644 --- a/test/core/end2end/tests/simple_delayed_request.c +++ b/test/core/end2end/tests/simple_delayed_request.c @@ -103,32 +103,33 @@ static void simple_delayed_request_body(grpc_end2end_test_config config, config.init_client(f, client_args); - c = grpc_channel_create_call(f->client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f->client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f->client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f->client_cq, tag(2), tag(3), 0)); config.init_server(f, server_args); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4))); cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f->server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f->server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_server_accept(s, f->server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + grpc_call_server_accept_old(s, f->server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5))); cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c index f8894a8ba92..192d1ab87d0 100644 --- a/test/core/end2end/tests/simple_request.c +++ b/test/core/end2end/tests/simple_request.c @@ -110,27 +110,29 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4))); cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5))); cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); @@ -156,25 +158,27 @@ static void simple_request_body2(grpc_end2end_test_fixture f) { cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(4))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(4))); cq_expect_finish_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5))); cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); cq_verify(v_server); diff --git a/test/core/end2end/tests/thread_stress.c b/test/core/end2end/tests/thread_stress.c index 8fdb765951c..e950a984ce8 100644 --- a/test/core/end2end/tests/thread_stress.c +++ b/test/core/end2end/tests/thread_stress.c @@ -108,7 +108,7 @@ static void drain_cq(int client, grpc_completion_queue *cq) { static void start_request(void) { gpr_slice slice = gpr_slice_malloc(100); grpc_byte_buffer *buf; - grpc_call *call = grpc_channel_create_call( + grpc_call *call = grpc_channel_create_call_old( g_fixture.client, "/Foo", "test.google.com", g_test_end_time); memset(GPR_SLICE_START_PTR(slice), 1, GPR_SLICE_LENGTH(slice)); @@ -117,9 +117,9 @@ static void start_request(void) { g_active_requests++; GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(call, g_fixture.client_cq, NULL, NULL, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(call, NULL)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write(call, buf, NULL, 0)); + grpc_call_invoke_old(call, g_fixture.client_cq, NULL, NULL, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(call, NULL)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_old(call, buf, NULL, 0)); grpc_byte_buffer_destroy(buf); } @@ -143,7 +143,7 @@ static void client_thread(void *p) { case GRPC_READ: break; case GRPC_WRITE_ACCEPTED: - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(ev->call, NULL)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(ev->call, NULL)); break; case GRPC_FINISH_ACCEPTED: break; @@ -179,13 +179,13 @@ static void client_thread(void *p) { static void request_server_call(void) { gpr_refcount *rc = gpr_malloc(sizeof(gpr_refcount)); gpr_ref_init(rc, 2); - grpc_server_request_call(g_fixture.server, rc); + grpc_server_request_call_old(g_fixture.server, rc); } static void maybe_end_server_call(grpc_call *call, gpr_refcount *rc) { if (gpr_unref(rc)) { - GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write_status(call, GRPC_STATUS_OK, NULL, NULL)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( + call, GRPC_STATUS_OK, NULL, NULL)); gpr_free(rc); } } @@ -215,20 +215,22 @@ static void server_thread(void *p) { case GRPC_SERVER_RPC_NEW: if (ev->call) { GPR_ASSERT(GRPC_CALL_OK == - grpc_call_server_accept(ev->call, g_fixture.server_cq, - ev->tag)); + grpc_call_server_accept_old( + ev->call, g_fixture.server_cq, ev->tag)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_server_end_initial_metadata(ev->call, 0)); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(ev->call, ev->tag)); + grpc_call_server_end_initial_metadata_old(ev->call, 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(ev->call, buf, ev->tag, 0)); + grpc_call_start_read_old(ev->call, ev->tag)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_start_write_old(ev->call, buf, ev->tag, 0)); } else { gpr_free(ev->tag); } break; case GRPC_READ: if (ev->data.read) { - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(ev->call, ev->tag)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_start_read_old(ev->call, ev->tag)); } else { maybe_end_server_call(ev->call, ev->tag); } diff --git a/test/core/end2end/tests/writes_done_hangs_with_pending_read.c b/test/core/end2end/tests/writes_done_hangs_with_pending_read.c index eea459459ad..0c77aa2b4ee 100644 --- a/test/core/end2end/tests/writes_done_hangs_with_pending_read.c +++ b/test/core/end2end/tests/writes_done_hangs_with_pending_read.c @@ -124,44 +124,46 @@ static void test_writes_done_hangs_with_pending_read( gpr_slice_unref(request_payload_slice); gpr_slice_unref(response_payload_slice); - c = grpc_channel_create_call(f.client, "/foo", "test.google.com", deadline); + c = grpc_channel_create_call_old(f.client, "/foo", "test.google.com", + deadline); GPR_ASSERT(c); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_invoke(c, f.client_cq, tag(2), tag(3), 0)); + grpc_call_invoke_old(c, f.client_cq, tag(2), tag(3), 0)); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(c, request_payload, tag(4), 0)); + grpc_call_start_write_old(c, request_payload, tag(4), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(request_payload); cq_expect_write_accepted(v_client, tag(4), GRPC_OP_OK); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, tag(100))); + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call_old(f.server, tag(100))); cq_expect_server_rpc_new(v_server, &s, tag(100), "/foo", "test.google.com", deadline, NULL); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_accept(s, f.server_cq, tag(102))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata(s, 0)); + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_server_accept_old(s, f.server_cq, tag(102))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_server_end_initial_metadata_old(s, 0)); cq_expect_client_metadata_read(v_client, tag(2), NULL); cq_verify(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(s, tag(5))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(s, tag(5))); cq_expect_read(v_server, tag(5), gpr_slice_from_copied_string("hello world")); cq_verify(v_server); GPR_ASSERT(GRPC_CALL_OK == - grpc_call_start_write(s, response_payload, tag(6), 0)); + grpc_call_start_write_old(s, response_payload, tag(6), 0)); /* destroy byte buffer early to ensure async code keeps track of its contents correctly */ grpc_byte_buffer_destroy(response_payload); cq_expect_write_accepted(v_server, tag(6), GRPC_OP_OK); cq_verify(v_server); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done(c, tag(6))); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( + GPR_ASSERT(GRPC_CALL_OK == grpc_call_writes_done_old(c, tag(6))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(7))); cq_expect_finish_accepted(v_client, tag(6), GRPC_OP_OK); @@ -170,7 +172,7 @@ static void test_writes_done_hangs_with_pending_read( /* does not return status because there is a pending message to be read */ cq_verify_empty(v_client); - GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read(c, tag(8))); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_read_old(c, tag(8))); cq_expect_read(v_client, tag(8), gpr_slice_from_copied_string("hello you")); cq_verify(v_client); diff --git a/test/core/fling/client.c b/test/core/fling/client.c index d6561e99614..cd2efc3cd0d 100644 --- a/test/core/fling/client.c +++ b/test/core/fling/client.c @@ -53,15 +53,15 @@ static grpc_call *call; static void init_ping_pong_request(void) {} static void step_ping_pong_request(void) { - call = grpc_channel_create_call(channel, "/Reflector/reflectUnary", - "localhost", gpr_inf_future); - GPR_ASSERT(grpc_call_invoke(call, cq, (void *)1, (void *)1, - GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); - GPR_ASSERT(grpc_call_start_write(call, the_buffer, (void *)1, - GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); + call = grpc_channel_create_call_old(channel, "/Reflector/reflectUnary", + "localhost", gpr_inf_future); + GPR_ASSERT(grpc_call_invoke_old(call, cq, (void *)1, (void *)1, + GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_write_old(call, the_buffer, (void *)1, + GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); - GPR_ASSERT(grpc_call_start_read(call, (void *)1) == GRPC_CALL_OK); - GPR_ASSERT(grpc_call_writes_done(call, (void *)1) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_read_old(call, (void *)1) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_writes_done_old(call, (void *)1) == GRPC_CALL_OK); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); @@ -70,17 +70,17 @@ static void step_ping_pong_request(void) { } static void init_ping_pong_stream(void) { - call = grpc_channel_create_call(channel, "/Reflector/reflectStream", - "localhost", gpr_inf_future); - GPR_ASSERT(grpc_call_invoke(call, cq, (void *)1, (void *)1, 0) == + call = grpc_channel_create_call_old(channel, "/Reflector/reflectStream", + "localhost", gpr_inf_future); + GPR_ASSERT(grpc_call_invoke_old(call, cq, (void *)1, (void *)1, 0) == GRPC_CALL_OK); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); } static void step_ping_pong_stream(void) { - GPR_ASSERT(grpc_call_start_write(call, the_buffer, (void *)1, 0) == + GPR_ASSERT(grpc_call_start_write_old(call, the_buffer, (void *)1, 0) == GRPC_CALL_OK); - GPR_ASSERT(grpc_call_start_read(call, (void *)1) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_read_old(call, (void *)1) == GRPC_CALL_OK); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); } diff --git a/test/core/fling/server.c b/test/core/fling/server.c index f811aac284c..ba5e96ddc04 100644 --- a/test/core/fling/server.c +++ b/test/core/fling/server.c @@ -62,7 +62,7 @@ typedef struct { static void request_call(void) { call_state *s = gpr_malloc(sizeof(call_state)); gpr_ref_init(&s->pending_ops, 2); - grpc_server_request_call(server, s); + grpc_server_request_call_old(server, s); } static void sigint_handler(int x) { got_sigint = 1; } @@ -142,9 +142,9 @@ int main(int argc, char **argv) { } else { s->flags = GRPC_WRITE_BUFFER_HINT; } - grpc_call_server_accept(ev->call, cq, s); - grpc_call_server_end_initial_metadata(ev->call, s->flags); - GPR_ASSERT(grpc_call_start_read(ev->call, s) == GRPC_CALL_OK); + grpc_call_server_accept_old(ev->call, cq, s); + grpc_call_server_end_initial_metadata_old(ev->call, s->flags); + GPR_ASSERT(grpc_call_start_read_old(ev->call, s) == GRPC_CALL_OK); request_call(); } else { GPR_ASSERT(shutdown_started); @@ -153,15 +153,15 @@ int main(int argc, char **argv) { break; case GRPC_WRITE_ACCEPTED: GPR_ASSERT(ev->data.write_accepted == GRPC_OP_OK); - GPR_ASSERT(grpc_call_start_read(ev->call, s) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_read_old(ev->call, s) == GRPC_CALL_OK); break; case GRPC_READ: if (ev->data.read) { - GPR_ASSERT(grpc_call_start_write(ev->call, ev->data.read, s, - s->flags) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_write_old(ev->call, ev->data.read, s, + s->flags) == GRPC_CALL_OK); } else { - GPR_ASSERT(grpc_call_start_write_status(ev->call, GRPC_STATUS_OK, - NULL, s) == GRPC_CALL_OK); + GPR_ASSERT(grpc_call_start_write_status_old(ev->call, GRPC_STATUS_OK, + NULL, s) == GRPC_CALL_OK); } break; case GRPC_FINISH_ACCEPTED: diff --git a/test/core/surface/lame_client_test.c b/test/core/surface/lame_client_test.c index 9b9f0202d6d..0a6edc1630d 100644 --- a/test/core/surface/lame_client_test.c +++ b/test/core/surface/lame_client_test.c @@ -51,7 +51,7 @@ int main(int argc, char **argv) { chan = grpc_lame_client_channel_create(); GPR_ASSERT(chan); - call = grpc_channel_create_call( + call = grpc_channel_create_call_old( chan, "/Foo", "anywhere", gpr_time_add(gpr_now(), gpr_time_from_seconds(100))); GPR_ASSERT(call); @@ -59,10 +59,10 @@ int main(int argc, char **argv) { cqv = cq_verifier_create(cq); /* we should be able to add metadata */ - GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata(call, &md, 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_add_metadata_old(call, &md, 0)); /* and invoke the call */ - GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke(call, cq, tag(2), tag(3), 0)); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_invoke_old(call, cq, tag(2), tag(3), 0)); /* the call should immediately fail */ cq_expect_client_metadata_read(cqv, tag(2), NULL); From 9b5da20897fac8fa215a4aa2e98ba892b417c0e2 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 11:43:45 -0800 Subject: [PATCH 75/93] Revert accidental rename --- src/python/src/_adapter/_call.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/src/_adapter/_call.c b/src/python/src/_adapter/_call.c index b4ac503dafe..3bc35be0ef0 100644 --- a/src/python/src/_adapter/_call.c +++ b/src/python/src/_adapter/_call.c @@ -70,7 +70,7 @@ static void pygrpc_call_dealloc(Call *self) { self->ob_type->tp_free((PyObject *)self); } -static const PyObject *pygrpc_call_invoke_old(Call *self, PyObject *args) { +static const PyObject *pygrpc_call_invoke(Call *self, PyObject *args) { const PyObject *completion_queue; const PyObject *metadata_tag; const PyObject *finish_tag; From 9c5feda33d30de8bf9e2327996fad8e0a99ee99e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 12:55:31 -0800 Subject: [PATCH 76/93] Cleanup output of tests --- test/core/end2end/cq_verifier.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c index b5368fffbb8..904ed772836 100644 --- a/test/core/end2end/cq_verifier.c +++ b/test/core/end2end/cq_verifier.c @@ -243,7 +243,9 @@ static void metadata_expectation(gpr_strvec *buf, metadata *md) { gpr_asprintf(&tmp, "%c%s:%s", i ? ',' : '{', md->keys[i], md->values[i]); gpr_strvec_add(buf, tmp); } - gpr_strvec_add(buf, gpr_strdup("}")); + if (md->count) { + gpr_strvec_add(buf, gpr_strdup("}")); + } } } From 12af2bd56025bfce87fcfb0c42687208d26df463 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 13:12:29 -0800 Subject: [PATCH 77/93] Remove unnecessary assert --- src/core/surface/call.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 0245e1b70c7..fade17c01a4 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -571,7 +571,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, } set = reqs[0].op; - master = &requests[set]; for (i = 0; i < nreqs; i++) { op = reqs[i].op; @@ -588,7 +587,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, requests[op].set = set; } - GPR_ASSERT(master != NULL); + master = &requests[set]; master->need_mask = have_ops; master->complete_mask = 0; master->on_complete = completion; From 39af15104d49dd3ba243105bb14c358e53c01b4b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 13:24:38 -0800 Subject: [PATCH 78/93] Cover all edges in the switch (not correctly yet) --- src/core/surface/call.c | 53 ++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index fade17c01a4..a2fcc45984b 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -554,10 +554,18 @@ static grpc_call_error start_ioreq_error(grpc_call *call, return ret; } +static void dump_req_state(const char *debug, const char *stage, grpc_call *call) { + size_t i; + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + gpr_log(GPR_DEBUG, "%p:%s:%s:%d:%d", call, debug, stage, i, call->requests[i].set); + } +} + static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, size_t nreqs, grpc_ioreq_completion_func completion, - void *user_data) { + void *user_data, + const char *debug) { size_t i; gpr_uint32 have_ops = 0; grpc_ioreq_op op; @@ -566,6 +574,8 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, grpc_ioreq_data data; gpr_uint8 set; + dump_req_state(debug, "before", call); + if (nreqs == 0) { return GRPC_CALL_OK; } @@ -597,21 +607,24 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, op = reqs[i].op; data = reqs[i].data; switch (op) { - default: + case GRPC_IOREQ_OP_COUNT: + gpr_log(GPR_ERROR, "should never reach here"); + abort(); break; case GRPC_IOREQ_RECV_MESSAGE: *data.recv_message = grpc_bbq_pop(&call->incoming_queue); if (*data.recv_message) { finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); } else if (call->stream_closed) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); } else { call->need_more_data = 1; } break; case GRPC_IOREQ_RECV_STATUS: + case GRPC_IOREQ_RECV_CLOSE: if (call->read_closed) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); + finish_ioreq_op(call, op, GRPC_OP_OK); } break; case GRPC_IOREQ_SEND_MESSAGE: @@ -623,11 +636,15 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, if (requests[GRPC_IOREQ_SEND_MESSAGE].set == REQSET_EMPTY) { requests[GRPC_IOREQ_SEND_MESSAGE].set = REQSET_DONE; } + if (call->stream_closed) { + finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_ERROR); + } break; case GRPC_IOREQ_SEND_INITIAL_METADATA: + case GRPC_IOREQ_SEND_TRAILING_METADATA: + case GRPC_IOREQ_SEND_STATUS: if (call->stream_closed) { - finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, - GRPC_OP_ERROR); + finish_ioreq_op(call, op, GRPC_OP_ERROR); } break; case GRPC_IOREQ_RECV_INITIAL_METADATA: @@ -656,6 +673,8 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, } } + dump_req_state(debug, "after", call); + return GRPC_CALL_OK; } @@ -668,7 +687,7 @@ 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); + err = start_ioreq(call, reqs, nreqs, call_start_ioreq_done, tag, __FUNCTION__); unlock(call); return err; } @@ -678,7 +697,7 @@ grpc_call_error grpc_call_start_ioreq_and_call_back( grpc_ioreq_completion_func on_complete, void *user_data) { grpc_call_error err; lock(call); - err = start_ioreq(call, reqs, nreqs, on_complete, user_data); + err = start_ioreq(call, reqs, nreqs, on_complete, user_data, __FUNCTION__); unlock(call); return err; } @@ -814,12 +833,12 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, reqs[0].data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; reqs[0].data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; ls->md_out_buffer++; - err = start_ioreq(call, reqs, 1, finish_send_metadata, NULL); + err = start_ioreq(call, reqs, 1, finish_send_metadata, NULL, __FUNCTION__); if (err != GRPC_CALL_OK) goto done; reqs[0].op = GRPC_IOREQ_RECV_INITIAL_METADATA; reqs[0].data.recv_metadata = &ls->initial_md_in; - err = start_ioreq(call, reqs, 1, finish_recv_metadata, metadata_read_tag); + err = start_ioreq(call, reqs, 1, finish_recv_metadata, metadata_read_tag, __FUNCTION__); if (err != GRPC_CALL_OK) goto done; reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA; @@ -829,7 +848,7 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, 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); + err = start_ioreq(call, reqs, 3, finish_status, NULL, __FUNCTION__); if (err != GRPC_CALL_OK) goto done; done: @@ -861,7 +880,7 @@ grpc_call_error grpc_call_server_accept(grpc_call *call, reqs[0].data.recv_status.details_capacity = 0; reqs[0].data.recv_status.code = &ls->status; reqs[1].op = GRPC_IOREQ_RECV_CLOSE; - err = start_ioreq(call, reqs, 2, finish_status, NULL); + err = start_ioreq(call, reqs, 2, finish_status, NULL, __FUNCTION__); unlock(call); return err; } @@ -880,7 +899,7 @@ grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, req.op = GRPC_IOREQ_SEND_INITIAL_METADATA; req.data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; req.data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; - err = start_ioreq(call, &req, 1, finish_send_initial_metadata, NULL); + err = start_ioreq(call, &req, 1, finish_send_initial_metadata, NULL, __FUNCTION__); unlock(call); return err; @@ -919,7 +938,7 @@ grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { ls = get_legacy_state(call); req.op = GRPC_IOREQ_RECV_MESSAGE; req.data.recv_message = &ls->msg_in; - err = start_ioreq(call, &req, 1, finish_read, tag); + err = start_ioreq(call, &req, 1, finish_read, tag, __FUNCTION__); unlock(call); return err; } @@ -945,7 +964,7 @@ grpc_call_error grpc_call_start_write(grpc_call *call, ls->msg_out = grpc_byte_buffer_copy(byte_buffer); req.op = GRPC_IOREQ_SEND_MESSAGE; req.data.send_message = ls->msg_out; - err = start_ioreq(call, &req, 1, finish_write, tag); + err = start_ioreq(call, &req, 1, finish_write, tag, __FUNCTION__); unlock(call); return err; @@ -962,7 +981,7 @@ grpc_call_error grpc_call_writes_done(grpc_call *call, void *tag) { lock(call); req.op = GRPC_IOREQ_SEND_CLOSE; - err = start_ioreq(call, &req, 1, finish_finish, tag); + err = start_ioreq(call, &req, 1, finish_finish, tag, __FUNCTION__); unlock(call); return err; @@ -986,7 +1005,7 @@ grpc_call_error grpc_call_start_write_status(grpc_call *call, /* MEMLEAK */ reqs[1].data.send_status.details = gpr_strdup(details); reqs[2].op = GRPC_IOREQ_SEND_CLOSE; - err = start_ioreq(call, reqs, 3, finish_finish, tag); + err = start_ioreq(call, reqs, 3, finish_finish, tag, __FUNCTION__); unlock(call); return err; From 9cc6141f998c499c92053ad1148541e43d6641a9 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 14:02:52 -0800 Subject: [PATCH 79/93] clean up finish a little more --- src/core/surface/call.c | 58 ++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index a2fcc45984b..a8be3db7281 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -554,18 +554,10 @@ static grpc_call_error start_ioreq_error(grpc_call *call, return ret; } -static void dump_req_state(const char *debug, const char *stage, grpc_call *call) { - size_t i; - for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { - gpr_log(GPR_DEBUG, "%p:%s:%s:%d:%d", call, debug, stage, i, call->requests[i].set); - } -} - static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, size_t nreqs, grpc_ioreq_completion_func completion, - void *user_data, - const char *debug) { + void *user_data) { size_t i; gpr_uint32 have_ops = 0; grpc_ioreq_op op; @@ -574,8 +566,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, grpc_ioreq_data data; gpr_uint8 set; - dump_req_state(debug, "before", call); - if (nreqs == 0) { return GRPC_CALL_OK; } @@ -615,10 +605,20 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, *data.recv_message = grpc_bbq_pop(&call->incoming_queue); if (*data.recv_message) { finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - } else if (call->stream_closed) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + if (call->stream_closed && grpc_bbq_empty(&call->incoming_queue)) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); + } } else { - call->need_more_data = 1; + /* no message: either end of stream or we need more bytes */ + if (call->read_closed) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + if (call->stream_closed) { + /* stream closed AND we've drained all messages: signal to the application */ + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); + } + } else { + call->need_more_data = 1; + } } break; case GRPC_IOREQ_RECV_STATUS: @@ -627,11 +627,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, finish_ioreq_op(call, op, GRPC_OP_OK); } break; - case GRPC_IOREQ_SEND_MESSAGE: - if (call->stream_closed) { - finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGE, GRPC_OP_ERROR); - } - break; case GRPC_IOREQ_SEND_CLOSE: if (requests[GRPC_IOREQ_SEND_MESSAGE].set == REQSET_EMPTY) { requests[GRPC_IOREQ_SEND_MESSAGE].set = REQSET_DONE; @@ -640,6 +635,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_ERROR); } break; + case GRPC_IOREQ_SEND_MESSAGE: case GRPC_IOREQ_SEND_INITIAL_METADATA: case GRPC_IOREQ_SEND_TRAILING_METADATA: case GRPC_IOREQ_SEND_STATUS: @@ -673,8 +669,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, } } - dump_req_state(debug, "after", call); - return GRPC_CALL_OK; } @@ -687,7 +681,7 @@ 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, __FUNCTION__); + err = start_ioreq(call, reqs, nreqs, call_start_ioreq_done, tag); unlock(call); return err; } @@ -697,7 +691,7 @@ grpc_call_error grpc_call_start_ioreq_and_call_back( grpc_ioreq_completion_func on_complete, void *user_data) { grpc_call_error err; lock(call); - err = start_ioreq(call, reqs, nreqs, on_complete, user_data, __FUNCTION__); + err = start_ioreq(call, reqs, nreqs, on_complete, user_data); unlock(call); return err; } @@ -833,12 +827,12 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, reqs[0].data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; reqs[0].data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; ls->md_out_buffer++; - err = start_ioreq(call, reqs, 1, finish_send_metadata, NULL, __FUNCTION__); + err = start_ioreq(call, reqs, 1, finish_send_metadata, NULL); if (err != GRPC_CALL_OK) goto done; reqs[0].op = GRPC_IOREQ_RECV_INITIAL_METADATA; reqs[0].data.recv_metadata = &ls->initial_md_in; - err = start_ioreq(call, reqs, 1, finish_recv_metadata, metadata_read_tag, __FUNCTION__); + err = start_ioreq(call, reqs, 1, finish_recv_metadata, metadata_read_tag); if (err != GRPC_CALL_OK) goto done; reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA; @@ -848,7 +842,7 @@ grpc_call_error grpc_call_invoke(grpc_call *call, grpc_completion_queue *cq, 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, __FUNCTION__); + err = start_ioreq(call, reqs, 3, finish_status, NULL); if (err != GRPC_CALL_OK) goto done; done: @@ -880,7 +874,7 @@ grpc_call_error grpc_call_server_accept(grpc_call *call, reqs[0].data.recv_status.details_capacity = 0; reqs[0].data.recv_status.code = &ls->status; reqs[1].op = GRPC_IOREQ_RECV_CLOSE; - err = start_ioreq(call, reqs, 2, finish_status, NULL, __FUNCTION__); + err = start_ioreq(call, reqs, 2, finish_status, NULL); unlock(call); return err; } @@ -899,7 +893,7 @@ grpc_call_error grpc_call_server_end_initial_metadata(grpc_call *call, req.op = GRPC_IOREQ_SEND_INITIAL_METADATA; req.data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; req.data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; - err = start_ioreq(call, &req, 1, finish_send_initial_metadata, NULL, __FUNCTION__); + err = start_ioreq(call, &req, 1, finish_send_initial_metadata, NULL); unlock(call); return err; @@ -938,7 +932,7 @@ grpc_call_error grpc_call_start_read(grpc_call *call, void *tag) { ls = get_legacy_state(call); req.op = GRPC_IOREQ_RECV_MESSAGE; req.data.recv_message = &ls->msg_in; - err = start_ioreq(call, &req, 1, finish_read, tag, __FUNCTION__); + err = start_ioreq(call, &req, 1, finish_read, tag); unlock(call); return err; } @@ -964,7 +958,7 @@ grpc_call_error grpc_call_start_write(grpc_call *call, ls->msg_out = grpc_byte_buffer_copy(byte_buffer); req.op = GRPC_IOREQ_SEND_MESSAGE; req.data.send_message = ls->msg_out; - err = start_ioreq(call, &req, 1, finish_write, tag, __FUNCTION__); + err = start_ioreq(call, &req, 1, finish_write, tag); unlock(call); return err; @@ -981,7 +975,7 @@ grpc_call_error grpc_call_writes_done(grpc_call *call, void *tag) { lock(call); req.op = GRPC_IOREQ_SEND_CLOSE; - err = start_ioreq(call, &req, 1, finish_finish, tag, __FUNCTION__); + err = start_ioreq(call, &req, 1, finish_finish, tag); unlock(call); return err; @@ -1005,7 +999,7 @@ grpc_call_error grpc_call_start_write_status(grpc_call *call, /* MEMLEAK */ reqs[1].data.send_status.details = gpr_strdup(details); reqs[2].op = GRPC_IOREQ_SEND_CLOSE; - err = start_ioreq(call, reqs, 3, finish_finish, tag, __FUNCTION__); + err = start_ioreq(call, reqs, 3, finish_finish, tag); unlock(call); return err; From 701c5843bc7ed9c9a2baa3a908e400d48901f4f9 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 14:03:06 -0800 Subject: [PATCH 80/93] Fix tests to be a bit more sane --- test/core/end2end/dualstack_socket_test.c | 1 - test/core/end2end/tests/census_simple_request.c | 1 - test/core/end2end/tests/max_concurrent_streams.c | 1 - test/core/end2end/tests/simple_request.c | 5 +---- 4 files changed, 1 insertion(+), 7 deletions(-) diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c index 14db4495f22..5def5b4a419 100644 --- a/test/core/end2end/dualstack_socket_test.c +++ b/test/core/end2end/dualstack_socket_test.c @@ -140,7 +140,6 @@ void test_connect(const char *server_host, const char *client_host, int port, cq_verify(v_client); cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); - cq_verify(v_server); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/census_simple_request.c b/test/core/end2end/tests/census_simple_request.c index cb37bf956d5..5e8f1485b66 100644 --- a/test/core/end2end/tests/census_simple_request.c +++ b/test/core/end2end/tests/census_simple_request.c @@ -133,7 +133,6 @@ static void test_body(grpc_end2end_test_fixture f) { cq_verify(v_client); cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); - cq_verify(v_server); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); grpc_call_destroy(c); diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c index a18c0453c61..cf9417c6832 100644 --- a/test/core/end2end/tests/max_concurrent_streams.c +++ b/test/core/end2end/tests/max_concurrent_streams.c @@ -136,7 +136,6 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verify(v_client); cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); - cq_verify(v_server); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c index cbade1252a7..4ce3f8d921c 100644 --- a/test/core/end2end/tests/simple_request.c +++ b/test/core/end2end/tests/simple_request.c @@ -137,7 +137,6 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verify(v_client); cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); - cq_verify(v_server); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); @@ -176,16 +175,14 @@ static void simple_request_body2(grpc_end2end_test_fixture f) { GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5))); - cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); cq_verify(v_server); cq_expect_client_metadata_read(v_client, tag(2), NULL); - cq_verify(v_client); - cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); cq_verify(v_client); + cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); From a7170ac4ad04591a5db33d5271ef6ce30662e9fd Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 14:43:09 -0800 Subject: [PATCH 81/93] Get the recv close edge right --- src/core/surface/call.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index a8be3db7281..96cdb9651b2 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -622,9 +622,13 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, } break; case GRPC_IOREQ_RECV_STATUS: - case GRPC_IOREQ_RECV_CLOSE: if (call->read_closed) { - finish_ioreq_op(call, op, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); + } + break; + case GRPC_IOREQ_RECV_CLOSE: + if (call->stream_closed) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); } break; case GRPC_IOREQ_SEND_CLOSE: From 566316f3a52f67e3b3806fcb052ab442bc7c4af9 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 15:25:32 -0800 Subject: [PATCH 82/93] Split legacy code to end of file --- src/core/surface/call.c | 387 +++++++++++++++++++++------------------- 1 file changed, 200 insertions(+), 187 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 96cdb9651b2..4de453ffd02 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -48,26 +48,8 @@ #define OP_IN_MASK(op, mask) (((1 << (op)) & (mask)) != 0) -typedef struct { - gpr_uint8 md_out_buffer; - size_t md_out_count[2]; - size_t md_out_capacity[2]; - grpc_metadata *md_out[2]; - grpc_byte_buffer *msg_out; - - /* input buffers */ - grpc_metadata_array initial_md_in; - grpc_metadata_array trailing_md_in; - - size_t details_capacity; - char *details; - grpc_status_code status; - - size_t msg_in_read_idx; - grpc_byte_buffer *msg_in; - - void *finished_tag; -} legacy_state; +typedef struct legacy_state legacy_state; +static void destroy_legacy_state(legacy_state *ls); typedef enum { REQ_INITIAL = 0, REQ_READY, REQ_DONE } req_state; @@ -200,18 +182,10 @@ grpc_call *grpc_call_create(grpc_channel *channel, return call; } -legacy_state *get_legacy_state(grpc_call *call) { - if (call->legacy_state == NULL) { - call->legacy_state = gpr_malloc(sizeof(legacy_state)); - memset(call->legacy_state, 0, sizeof(legacy_state)); - } - return call->legacy_state; -} - void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } static void destroy_call(void *call, int ignored_success) { - size_t i, j; + size_t i; grpc_call *c = call; grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); grpc_channel_internal_unref(c->channel); @@ -228,16 +202,7 @@ static void destroy_call(void *call, int ignored_success) { gpr_free(c->buffered_initial_metadata.metadata); gpr_free(c->buffered_trailing_metadata.metadata); if (c->legacy_state) { - for (i = 0; i < 2; i++) { - for (j = 0; j < c->legacy_state->md_out_count[i]; j++) { - gpr_free(c->legacy_state->md_out[i][j].key); - gpr_free(c->legacy_state->md_out[i][j].value); - } - gpr_free(c->legacy_state->md_out[i]); - } - gpr_free(c->legacy_state->initial_md_in.metadata); - gpr_free(c->legacy_state->trailing_md_in.metadata); - gpr_free(c->legacy_state); + destroy_legacy_state(c->legacy_state); } gpr_free(c); } @@ -749,6 +714,202 @@ void grpc_call_execute_op(grpc_call *call, grpc_call_op *op) { elem->filter->call_op(elem, NULL, op); } +grpc_call *grpc_call_from_top_element(grpc_call_element *elem) { + return CALL_FROM_TOP_ELEM(elem); +} + +static void call_alarm(void *arg, int success) { + grpc_call *call = arg; + if (success) { + if (call->is_client) { + grpc_call_cancel_with_status(call, GRPC_STATUS_DEADLINE_EXCEEDED, + "Deadline Exceeded"); + } else { + grpc_call_cancel(call); + } + } + grpc_call_internal_unref(call, 1); +} + +void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + + if (call->have_alarm) { + gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice"); + } + grpc_call_internal_ref(call); + call->have_alarm = 1; + grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); +} + +static void mark_read_closed(grpc_call *call) { + call->read_closed = 1; + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); +} + +void grpc_call_read_closed(grpc_call_element *elem) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + lock(call); + GPR_ASSERT(!call->read_closed); + mark_read_closed(call); + unlock(call); +} + +void grpc_call_stream_closed(grpc_call_element *elem) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + lock(call); + GPR_ASSERT(!call->stream_closed); + if (!call->read_closed) { + mark_read_closed(call); + } + call->stream_closed = 1; + if (grpc_bbq_empty(&call->incoming_queue)) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); + } + unlock(call); + grpc_call_internal_unref(call, 0); +} + +/* we offset status by a small amount when storing it into transport metadata + as metadata cannot store a 0 value (which is used as OK for grpc_status_codes + */ +#define STATUS_OFFSET 1 +static void destroy_status(void *ignored) {} + +static gpr_uint32 decode_status(grpc_mdelem *md) { + gpr_uint32 status; + void *user_data = grpc_mdelem_get_user_data(md, destroy_status); + if (user_data) { + status = ((gpr_uint32)(gpr_intptr) user_data) - STATUS_OFFSET; + } else { + if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value), + GPR_SLICE_LENGTH(md->value->slice), + &status)) { + status = GRPC_STATUS_UNKNOWN; /* could not parse status code */ + } + grpc_mdelem_set_user_data(md, destroy_status, + (void *)(gpr_intptr)(status + STATUS_OFFSET)); + } + return status; +} + +void grpc_call_recv_message(grpc_call_element *elem, + grpc_byte_buffer *byte_buffer) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + lock(call); + if (call->requests[GRPC_IOREQ_RECV_MESSAGE].set < GRPC_IOREQ_OP_COUNT) { + /* there's an outstanding read */ + *call->requests[GRPC_IOREQ_RECV_MESSAGE].data.recv_message = byte_buffer; + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + } else { + grpc_bbq_push(&call->incoming_queue, byte_buffer); + } + unlock(call); +} + +void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + grpc_mdstr *key = md->key; + grpc_metadata_array *dest; + grpc_metadata *mdusr; + + lock(call); + if (key == grpc_channel_get_status_string(call->channel)) { + set_status_code(call, STATUS_FROM_WIRE, decode_status(md)); + grpc_mdelem_unref(md); + } else if (key == grpc_channel_get_message_string(call->channel)) { + set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value)); + grpc_mdelem_unref(md); + } else { + if (!call->got_initial_metadata) { + dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].set < + GRPC_IOREQ_OP_COUNT + ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] + .data.recv_metadata + : &call->buffered_initial_metadata; + } else { + dest = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].set < + GRPC_IOREQ_OP_COUNT + ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] + .data.recv_metadata + : &call->buffered_trailing_metadata; + } + if (dest->count == dest->capacity) { + dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2); + dest->metadata = + gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity); + } + mdusr = &dest->metadata[dest->count++]; + mdusr->key = (char *)grpc_mdstr_as_c_string(md->key); + mdusr->value = (char *)grpc_mdstr_as_c_string(md->value); + mdusr->value_length = GPR_SLICE_LENGTH(md->value->slice); + if (call->owned_metadata_count == call->owned_metadata_capacity) { + call->owned_metadata_capacity = GPR_MAX( + call->owned_metadata_capacity + 8, call->owned_metadata_capacity * 2); + call->owned_metadata = + gpr_realloc(call->owned_metadata, + sizeof(grpc_mdelem *) * call->owned_metadata_capacity); + } + call->owned_metadata[call->owned_metadata_count++] = md; + } + unlock(call); +} + +grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) { + return CALL_STACK_FROM_CALL(call); +} + +/* + * LEGACY API IMPLEMENTATION + * All this code will disappear as soon as wrappings are updated + */ + +struct legacy_state { + gpr_uint8 md_out_buffer; + size_t md_out_count[2]; + size_t md_out_capacity[2]; + grpc_metadata *md_out[2]; + grpc_byte_buffer *msg_out; + + /* input buffers */ + grpc_metadata_array initial_md_in; + grpc_metadata_array trailing_md_in; + + size_t details_capacity; + char *details; + grpc_status_code status; + + size_t msg_in_read_idx; + grpc_byte_buffer *msg_in; + + void *finished_tag; +}; + +static legacy_state *get_legacy_state(grpc_call *call) { + if (call->legacy_state == NULL) { + call->legacy_state = gpr_malloc(sizeof(legacy_state)); + memset(call->legacy_state, 0, sizeof(legacy_state)); + } + return call->legacy_state; +} + +static void destroy_legacy_state(legacy_state *ls) { + size_t i, j; + for (i = 0; i < 2; i++) { + for (j = 0; j < ls->md_out_count[i]; j++) { + gpr_free(ls->md_out[i][j].key); + gpr_free(ls->md_out[i][j].value); + } + gpr_free(ls->md_out[i]); + } + gpr_free(ls->initial_md_in.metadata); + gpr_free(ls->trailing_md_in.metadata); + gpr_free(ls); +} + grpc_call_error grpc_call_add_metadata(grpc_call *call, grpc_metadata *metadata, gpr_uint32 flags) { legacy_state *ls; @@ -1008,151 +1169,3 @@ grpc_call_error grpc_call_start_write_status(grpc_call *call, return err; } - -grpc_call *grpc_call_from_top_element(grpc_call_element *elem) { - return CALL_FROM_TOP_ELEM(elem); -} - -static void call_alarm(void *arg, int success) { - grpc_call *call = arg; - if (success) { - if (call->is_client) { - grpc_call_cancel_with_status(call, GRPC_STATUS_DEADLINE_EXCEEDED, - "Deadline Exceeded"); - } else { - grpc_call_cancel(call); - } - } - grpc_call_internal_unref(call, 1); -} - -void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); - - if (call->have_alarm) { - gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice"); - } - grpc_call_internal_ref(call); - call->have_alarm = 1; - grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); -} - -static void mark_read_closed(grpc_call *call) { - call->read_closed = 1; - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); - finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); - finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); -} - -void grpc_call_read_closed(grpc_call_element *elem) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); - lock(call); - GPR_ASSERT(!call->read_closed); - mark_read_closed(call); - unlock(call); -} - -void grpc_call_stream_closed(grpc_call_element *elem) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); - lock(call); - GPR_ASSERT(!call->stream_closed); - if (!call->read_closed) { - mark_read_closed(call); - } - call->stream_closed = 1; - if (grpc_bbq_empty(&call->incoming_queue)) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); - } - unlock(call); - grpc_call_internal_unref(call, 0); -} - -/* we offset status by a small amount when storing it into transport metadata - as metadata cannot store a 0 value (which is used as OK for grpc_status_codes - */ -#define STATUS_OFFSET 1 -static void destroy_status(void *ignored) {} - -static gpr_uint32 decode_status(grpc_mdelem *md) { - gpr_uint32 status; - void *user_data = grpc_mdelem_get_user_data(md, destroy_status); - if (user_data) { - status = ((gpr_uint32)(gpr_intptr) user_data) - STATUS_OFFSET; - } else { - if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value), - GPR_SLICE_LENGTH(md->value->slice), - &status)) { - status = GRPC_STATUS_UNKNOWN; /* could not parse status code */ - } - grpc_mdelem_set_user_data(md, destroy_status, - (void *)(gpr_intptr)(status + STATUS_OFFSET)); - } - return status; -} - -void grpc_call_recv_message(grpc_call_element *elem, - grpc_byte_buffer *byte_buffer) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); - lock(call); - if (call->requests[GRPC_IOREQ_RECV_MESSAGE].set < GRPC_IOREQ_OP_COUNT) { - /* there's an outstanding read */ - *call->requests[GRPC_IOREQ_RECV_MESSAGE].data.recv_message = byte_buffer; - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - } else { - grpc_bbq_push(&call->incoming_queue, byte_buffer); - } - unlock(call); -} - -void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); - grpc_mdstr *key = md->key; - grpc_metadata_array *dest; - grpc_metadata *mdusr; - - lock(call); - if (key == grpc_channel_get_status_string(call->channel)) { - set_status_code(call, STATUS_FROM_WIRE, decode_status(md)); - grpc_mdelem_unref(md); - } else if (key == grpc_channel_get_message_string(call->channel)) { - set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value)); - grpc_mdelem_unref(md); - } else { - if (!call->got_initial_metadata) { - dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].set < - GRPC_IOREQ_OP_COUNT - ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] - .data.recv_metadata - : &call->buffered_initial_metadata; - } else { - dest = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].set < - GRPC_IOREQ_OP_COUNT - ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] - .data.recv_metadata - : &call->buffered_trailing_metadata; - } - if (dest->count == dest->capacity) { - dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2); - dest->metadata = - gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity); - } - mdusr = &dest->metadata[dest->count++]; - mdusr->key = (char *)grpc_mdstr_as_c_string(md->key); - mdusr->value = (char *)grpc_mdstr_as_c_string(md->value); - mdusr->value_length = GPR_SLICE_LENGTH(md->value->slice); - if (call->owned_metadata_count == call->owned_metadata_capacity) { - call->owned_metadata_capacity = GPR_MAX( - call->owned_metadata_capacity + 8, call->owned_metadata_capacity * 2); - call->owned_metadata = - gpr_realloc(call->owned_metadata, - sizeof(grpc_mdelem *) * call->owned_metadata_capacity); - } - call->owned_metadata[call->owned_metadata_count++] = md; - } - unlock(call); -} - -grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) { - return CALL_STACK_FROM_CALL(call); -} From eac4c2363b0ef29eb44588ef4a61bab58f23685c Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 15:38:00 -0800 Subject: [PATCH 83/93] Fix server after merge --- src/core/surface/server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/surface/server.c b/src/core/surface/server.c index c40ee3b6c34..a057694f13a 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -709,7 +709,7 @@ static void begin_request(grpc_server *server, grpc_completion_queue *cq, abort(); } -grpc_call_error grpc_server_request_call_old( +grpc_call_error grpc_server_request_call( grpc_server *server, grpc_call_details *details, grpc_metadata_array *initial_metadata, grpc_completion_queue *cq, void *tag) { From c18c56e40c23586c0f87eac96973053bf725c8c9 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 15:59:13 -0800 Subject: [PATCH 84/93] Split master and reqinfo for clearer code --- src/core/surface/call.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 6a406d3c7bc..dfee93eb7d8 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -71,8 +71,14 @@ typedef struct { #define REQSET_EMPTY 255 #define REQSET_DONE 254 -/* The state of an ioreq */ -typedef struct reqinfo { +/* The state of an ioreq - we keep one of these on the call for each + grpc_ioreq_op type. + + These structures are manipulated in sets, where a set is a set of + operations begin with the same call to start_ioreq and the various + public and private api's that call it. Each set has a master reqinfo + in which we set a few additional fields. */ +typedef struct { /* User supplied parameters */ grpc_ioreq_data data; /* In which set is this ioreq? @@ -84,12 +90,15 @@ typedef struct reqinfo { - REQSET_DONE, in which case this reqinfo has been satisfied for all time for this call, and no further use will be made of it */ gpr_uint8 set; +} reqinfo; + +typedef struct { grpc_op_error status; grpc_ioreq_completion_func on_complete; void *user_data; gpr_uint32 need_mask; gpr_uint32 complete_mask; -} reqinfo; +} reqinfo_master; typedef enum { STATUS_FROM_API_OVERRIDE = 0, @@ -120,6 +129,7 @@ struct grpc_call { gpr_uint8 need_more_data; reqinfo requests[GRPC_IOREQ_OP_COUNT]; + reqinfo_master masters[GRPC_IOREQ_OP_COUNT]; completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; grpc_byte_buffer_queue incoming_queue; grpc_metadata_array buffered_initial_metadata; @@ -333,9 +343,12 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, completed_request *cr; size_t i; if (call->requests[op].set < GRPC_IOREQ_OP_COUNT) { - reqinfo *master = &call->requests[call->requests[op].set]; + reqinfo_master *master = &call->masters[call->requests[op].set]; /* ioreq is live: we need to do something */ master->complete_mask |= 1 << op; + if (status != GRPC_OP_OK) { + master->status = status; + } call->requests[op].set = (op == GRPC_IOREQ_SEND_MESSAGE || op == GRPC_IOREQ_RECV_MESSAGE) ? REQSET_EMPTY @@ -347,14 +360,11 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, } for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { if (call->requests[i].set == op) { - if (call->requests[i].status != GRPC_OP_OK) { - status = GRPC_OP_ERROR; - } call->requests[i].set = REQSET_EMPTY; } } cr = &call->completed_requests[call->num_completed_requests++]; - cr->status = status; + cr->status = master->status; cr->on_complete = master->on_complete; cr->user_data = master->user_data; } @@ -527,7 +537,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, gpr_uint32 have_ops = 0; grpc_ioreq_op op; reqinfo *requests = call->requests; - reqinfo *master; + reqinfo_master *master; grpc_ioreq_data data; gpr_uint8 set; @@ -552,7 +562,8 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, requests[op].set = set; } - master = &requests[set]; + master = &call->masters[set]; + master->status = GRPC_OP_OK; master->need_mask = have_ops; master->complete_mask = 0; master->on_complete = completion; From daceea867002a097e64e869837ac5348ac498bcc Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 16:15:53 -0800 Subject: [PATCH 85/93] Add some documentation, simplify state --- src/core/surface/call.c | 77 ++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index dfee93eb7d8..da966c874ac 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -77,7 +77,7 @@ typedef struct { These structures are manipulated in sets, where a set is a set of operations begin with the same call to start_ioreq and the various public and private api's that call it. Each set has a master reqinfo - in which we set a few additional fields. */ + in which we set a few additional fields - see reqinfo_master. */ typedef struct { /* User supplied parameters */ grpc_ioreq_data data; @@ -93,25 +93,51 @@ typedef struct { } reqinfo; typedef struct { + /* Overall status of the operation: starts OK, may degrade to + non-OK */ grpc_op_error status; + /* Completion function to call at the end of the operation */ grpc_ioreq_completion_func on_complete; void *user_data; + /* a bit mask of which request ops are needed (1 << opid) */ gpr_uint32 need_mask; + /* a bit mask of which request ops are now completed */ gpr_uint32 complete_mask; } reqinfo_master; +/* Status data for a request can come from several sources; this + enumerates them all, and acts as a priority sorting for which + status to return to the application - earlier entries override + later ones */ typedef enum { + /* Status came from the application layer overriding whatever + the wire says */ STATUS_FROM_API_OVERRIDE = 0, + /* Status came from 'the wire' - or somewhere below the surface + layer */ STATUS_FROM_WIRE, STATUS_SOURCE_COUNT } status_source; typedef struct { - gpr_uint8 set; + gpr_uint8 is_set; grpc_status_code code; grpc_mdstr *details; } received_status; +/* How far through the GRPC stream have we read? */ +typedef enum { + /* We are still waiting for initial metadata to complete */ + READ_STATE_INITIAL, + /* We have gotten initial metadata, and are reading either + messages or trailing metadata */ + READ_STATE_GOT_INITIAL_METADATA, + /* The stream is closed for reading */ + READ_STATE_READ_CLOSED, + /* The stream is closed for reading & writing */ + READ_STATE_STREAM_CLOSED +} read_state; + struct grpc_call { grpc_completion_queue *cq; grpc_channel *channel; @@ -120,10 +146,8 @@ struct grpc_call { gpr_mu mu; gpr_uint8 is_client; - gpr_uint8 got_initial_metadata; + read_state read_state; gpr_uint8 have_alarm; - gpr_uint8 read_closed; - gpr_uint8 stream_closed; gpr_uint8 sending; gpr_uint8 num_completed_requests; gpr_uint8 need_more_data; @@ -229,7 +253,7 @@ void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) { static void set_status_code(grpc_call *call, status_source source, gpr_uint32 status) { - call->status[source].set = 1; + call->status[source].is_set = 1; call->status[source].code = status; } @@ -308,7 +332,7 @@ static void unlock(grpc_call *call) { static void get_final_status(grpc_call *call, grpc_recv_status_args args) { int i; for (i = 0; i < STATUS_SOURCE_COUNT; i++) { - if (call->status[i].set) { + if (call->status[i].is_set) { *args.code = call->status[i].code; if (!args.details) return; if (call->status[i].details) { @@ -581,14 +605,14 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, *data.recv_message = grpc_bbq_pop(&call->incoming_queue); if (*data.recv_message) { finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - if (call->stream_closed && grpc_bbq_empty(&call->incoming_queue)) { + if (call->read_state == READ_STATE_STREAM_CLOSED && grpc_bbq_empty(&call->incoming_queue)) { finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); } } else { /* no message: either end of stream or we need more bytes */ - if (call->read_closed) { + if (call->read_state >= READ_STATE_READ_CLOSED) { finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - if (call->stream_closed) { + if (call->read_state == READ_STATE_STREAM_CLOSED) { /* stream closed AND we've drained all messages: signal to the application */ finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); } @@ -598,12 +622,12 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, } break; case GRPC_IOREQ_RECV_STATUS: - if (call->read_closed) { + if (call->read_state >= READ_STATE_READ_CLOSED) { finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); } break; case GRPC_IOREQ_RECV_CLOSE: - if (call->stream_closed) { + if (call->read_state == READ_STATE_STREAM_CLOSED) { finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); } break; @@ -611,7 +635,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, if (requests[GRPC_IOREQ_SEND_MESSAGE].set == REQSET_EMPTY) { requests[GRPC_IOREQ_SEND_MESSAGE].set = REQSET_DONE; } - if (call->stream_closed) { + if (call->read_state == READ_STATE_STREAM_CLOSED) { finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_ERROR); } break; @@ -619,7 +643,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, case GRPC_IOREQ_SEND_INITIAL_METADATA: case GRPC_IOREQ_SEND_TRAILING_METADATA: case GRPC_IOREQ_SEND_STATUS: - if (call->stream_closed) { + if (call->read_state == READ_STATE_STREAM_CLOSED) { finish_ioreq_op(call, op, GRPC_OP_ERROR); } break; @@ -629,11 +653,8 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, SWAP(grpc_metadata_array, *data.recv_metadata, call->buffered_initial_metadata); } - if (call->got_initial_metadata) { + if (call->read_state >= READ_STATE_GOT_INITIAL_METADATA) { finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); - } else if (call->stream_closed) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, - GRPC_OP_ERROR); } break; case GRPC_IOREQ_RECV_TRAILING_METADATA: @@ -642,7 +663,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, SWAP(grpc_metadata_array, *data.recv_metadata, call->buffered_trailing_metadata); } - if (call->read_closed) { + if (call->read_state >= READ_STATE_READ_CLOSED) { finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); } break; @@ -683,7 +704,7 @@ void grpc_call_destroy(grpc_call *c) { grpc_alarm_cancel(&c->alarm); c->have_alarm = 0; } - cancel = !c->stream_closed; + cancel = c->read_state != READ_STATE_STREAM_CLOSED; unlock(c); if (cancel) grpc_call_cancel(c); grpc_call_internal_unref(c, 1); @@ -754,7 +775,7 @@ void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { } static void mark_read_closed(grpc_call *call) { - call->read_closed = 1; + call->read_state = READ_STATE_READ_CLOSED; finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); @@ -764,7 +785,7 @@ static void mark_read_closed(grpc_call *call) { void grpc_call_read_closed(grpc_call_element *elem) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); lock(call); - GPR_ASSERT(!call->read_closed); + GPR_ASSERT(call->read_state < READ_STATE_READ_CLOSED); mark_read_closed(call); unlock(call); } @@ -772,11 +793,11 @@ void grpc_call_read_closed(grpc_call_element *elem) { void grpc_call_stream_closed(grpc_call_element *elem) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); lock(call); - GPR_ASSERT(!call->stream_closed); - if (!call->read_closed) { + GPR_ASSERT(call->read_state < READ_STATE_STREAM_CLOSED); + if (call->read_state < READ_STATE_READ_CLOSED) { mark_read_closed(call); } - call->stream_closed = 1; + call->read_state = READ_STATE_STREAM_CLOSED; if (grpc_bbq_empty(&call->incoming_queue)) { finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); } @@ -835,7 +856,7 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value)); grpc_mdelem_unref(md); } else { - if (!call->got_initial_metadata) { + if (call->read_state < READ_STATE_GOT_INITIAL_METADATA) { dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].set < GRPC_IOREQ_OP_COUNT ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] @@ -1079,7 +1100,9 @@ grpc_call_error grpc_call_server_end_initial_metadata_old(grpc_call *call, void grpc_call_initial_metadata_complete(grpc_call_element *surface_element) { grpc_call *call = grpc_call_from_top_element(surface_element); lock(call); - call->got_initial_metadata = 1; + if (call->read_state < READ_STATE_GOT_INITIAL_METADATA) { + call->read_state = READ_STATE_GOT_INITIAL_METADATA; + } finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); unlock(call); } From fef766933e8f20af555b99dafe2e80097f37a07e Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Mon, 2 Feb 2015 16:44:26 -0800 Subject: [PATCH 86/93] Back-end for new core API --- Makefile | 7 + build.json | 2 + include/grpc/grpc.h | 70 +- src/core/channel/channel_stack.c | 16 +- src/core/channel/connected_channel.c | 8 +- src/core/iomgr/pollset_posix.c | 4 +- src/core/surface/byte_buffer_queue.c | 79 + src/core/surface/byte_buffer_queue.h | 59 + src/core/surface/call.c | 1664 ++++++++++------- src/core/surface/call.h | 72 +- src/core/surface/channel.c | 18 +- src/core/surface/client.c | 12 +- src/core/surface/completion_queue.c | 25 +- src/core/surface/completion_queue.h | 4 + src/core/surface/event_string.c | 6 +- src/core/surface/lame_client.c | 16 +- src/core/surface/server.c | 261 ++- src/core/transport/chttp2/stream_encoder.c | 2 +- src/cpp/client/channel.cc | 1 + templates/Makefile.template | 2 + test/core/end2end/cq_verifier.c | 16 +- test/core/end2end/dualstack_socket_test.c | 1 - .../end2end/tests/census_simple_request.c | 1 - .../end2end/tests/max_concurrent_streams.c | 3 +- test/core/end2end/tests/simple_request.c | 5 +- test/core/fling/client.c | 1 + test/core/surface/completion_queue_test.c | 27 - tools/dockerfile/grpc_node_base/Dockerfile | 3 + tools/dockerfile/grpc_php_base/Dockerfile | 3 + tools/dockerfile/grpc_ruby_base/Dockerfile | 3 + vsprojects/vs2013/grpc.vcxproj | 3 + vsprojects/vs2013/grpc.vcxproj.filters | 6 + vsprojects/vs2013/grpc_unsecure.vcxproj | 3 + .../vs2013/grpc_unsecure.vcxproj.filters | 6 + 34 files changed, 1488 insertions(+), 921 deletions(-) create mode 100644 src/core/surface/byte_buffer_queue.c create mode 100644 src/core/surface/byte_buffer_queue.h diff --git a/Makefile b/Makefile index a3f1aaf7c8e..7ec690ef22e 100644 --- a/Makefile +++ b/Makefile @@ -189,11 +189,13 @@ OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/ope ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS) PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/perftools.c -lprofiler $(LDFLAGS) +ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_PERFTOOLS = $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_SYSTEM_PERFTOOLS),true) DEFINES += GRPC_HAVE_PERFTOOLS LIBS += profiler endif +endif ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) @@ -1433,6 +1435,7 @@ LIBGRPC_SRC = \ src/core/statistics/hash_table.c \ src/core/statistics/window_stats.c \ src/core/surface/byte_buffer.c \ + src/core/surface/byte_buffer_queue.c \ src/core/surface/byte_buffer_reader.c \ src/core/surface/call.c \ src/core/surface/channel.c \ @@ -1559,6 +1562,7 @@ src/core/statistics/census_tracing.c: $(OPENSSL_DEP) src/core/statistics/hash_table.c: $(OPENSSL_DEP) src/core/statistics/window_stats.c: $(OPENSSL_DEP) src/core/surface/byte_buffer.c: $(OPENSSL_DEP) +src/core/surface/byte_buffer_queue.c: $(OPENSSL_DEP) src/core/surface/byte_buffer_reader.c: $(OPENSSL_DEP) src/core/surface/call.c: $(OPENSSL_DEP) src/core/surface/channel.c: $(OPENSSL_DEP) @@ -1707,6 +1711,7 @@ objs/$(CONFIG)/src/core/statistics/census_tracing.o: objs/$(CONFIG)/src/core/statistics/hash_table.o: objs/$(CONFIG)/src/core/statistics/window_stats.o: objs/$(CONFIG)/src/core/surface/byte_buffer.o: +objs/$(CONFIG)/src/core/surface/byte_buffer_queue.o: objs/$(CONFIG)/src/core/surface/byte_buffer_reader.o: objs/$(CONFIG)/src/core/surface/call.o: objs/$(CONFIG)/src/core/surface/channel.o: @@ -1874,6 +1879,7 @@ LIBGRPC_UNSECURE_SRC = \ src/core/statistics/hash_table.c \ src/core/statistics/window_stats.c \ src/core/surface/byte_buffer.c \ + src/core/surface/byte_buffer_queue.c \ src/core/surface/byte_buffer_reader.c \ src/core/surface/call.c \ src/core/surface/channel.c \ @@ -2005,6 +2011,7 @@ objs/$(CONFIG)/src/core/statistics/census_tracing.o: objs/$(CONFIG)/src/core/statistics/hash_table.o: objs/$(CONFIG)/src/core/statistics/window_stats.o: objs/$(CONFIG)/src/core/surface/byte_buffer.o: +objs/$(CONFIG)/src/core/surface/byte_buffer_queue.o: objs/$(CONFIG)/src/core/surface/byte_buffer_reader.o: objs/$(CONFIG)/src/core/surface/call.o: objs/$(CONFIG)/src/core/surface/channel.o: diff --git a/build.json b/build.json index 119e61263fa..291c7e6f53c 100644 --- a/build.json +++ b/build.json @@ -73,6 +73,7 @@ "src/core/statistics/census_tracing.h", "src/core/statistics/hash_table.h", "src/core/statistics/window_stats.h", + "src/core/surface/byte_buffer_queue.h", "src/core/surface/call.h", "src/core/surface/channel.h", "src/core/surface/client.h", @@ -159,6 +160,7 @@ "src/core/statistics/hash_table.c", "src/core/statistics/window_stats.c", "src/core/surface/byte_buffer.c", + "src/core/surface/byte_buffer_queue.c", "src/core/surface/byte_buffer_reader.c", "src/core/surface/call.c", "src/core/surface/channel.c", diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index a9fae0df909..c18e47e54b7 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -183,17 +183,16 @@ typedef struct grpc_metadata { } grpc_metadata; typedef enum grpc_completion_type { - GRPC_QUEUE_SHUTDOWN, /* Shutting down */ - GRPC_READ, /* A read has completed */ - GRPC_INVOKE_ACCEPTED, /* An invoke call has been accepted by flow - control */ - GRPC_WRITE_ACCEPTED, /* A write has been accepted by - flow control */ + GRPC_QUEUE_SHUTDOWN, /* Shutting down */ + GRPC_IOREQ, /* grpc_call_ioreq completion */ + GRPC_READ, /* A read has completed */ + GRPC_WRITE_ACCEPTED, /* A write has been accepted by + flow control */ GRPC_FINISH_ACCEPTED, /* writes_done or write_status has been accepted */ GRPC_CLIENT_METADATA_READ, /* The metadata array sent by server received at client */ - GRPC_FINISHED, /* An RPC has finished. The event contains status. - On the server this will be OK or Cancelled. */ + GRPC_FINISHED, /* An RPC has finished. The event contains status. + On the server this will be OK or Cancelled. */ GRPC_SERVER_RPC_NEW, /* A new RPC has arrived at the server */ GRPC_SERVER_SHUTDOWN, /* The server has finished shutting down */ GRPC_COMPLETION_DO_NOT_USE /* must be last, forces users to include @@ -213,6 +212,7 @@ typedef struct grpc_event { grpc_op_error write_accepted; grpc_op_error finish_accepted; grpc_op_error invoke_accepted; + grpc_op_error ioreq; struct { size_t count; grpc_metadata *elements; @@ -233,6 +233,57 @@ typedef struct grpc_event { } data; } grpc_event; +typedef struct { + size_t count; + size_t capacity; + grpc_metadata *metadata; +} grpc_metadata_array; + +typedef struct { + const char *method; + const char *host; + gpr_timespec deadline; +} grpc_call_details; + +typedef enum { + GRPC_OP_SEND_INITIAL_METADATA = 0, + GRPC_OP_SEND_MESSAGE, + GRPC_OP_SEND_CLOSE_FROM_CLIENT, + GRPC_OP_SEND_STATUS_FROM_SERVER, + GRPC_OP_RECV_INITIAL_METADATA, + GRPC_OP_RECV_MESSAGES, + GRPC_OP_RECV_STATUS_ON_CLIENT, + GRPC_OP_RECV_CLOSE_ON_SERVER +} grpc_op_type; + +typedef struct grpc_op { + grpc_op_type op; + union { + struct { + size_t count; + const grpc_metadata *metadata; + } send_initial_metadata; + grpc_byte_buffer *send_message; + struct { + size_t trailing_metadata_count; + grpc_metadata *trailing_metadata; + grpc_status_code status; + const char *status_details; + } send_status_from_server; + grpc_metadata_array *recv_initial_metadata; + grpc_byte_buffer **recv_message; + struct { + grpc_metadata_array *trailing_metadata; + grpc_status_code *status; + char **status_details; + size_t *status_details_capacity; + } recv_status_on_client; + struct { + int *cancelled; + } recv_close_on_server; + } data; +} grpc_op; + /* Initialize the grpc library */ void grpc_init(void); @@ -279,6 +330,9 @@ grpc_call *grpc_channel_create_call_old(grpc_channel *channel, const char *method, const char *host, gpr_timespec deadline); +grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops, + size_t nops, void *tag); + /* Create a client channel */ grpc_channel *grpc_channel_create(const char *target, const grpc_channel_args *args); diff --git a/src/core/channel/channel_stack.c b/src/core/channel/channel_stack.c index e28bbd798d7..d9e722c4f1e 100644 --- a/src/core/channel/channel_stack.c +++ b/src/core/channel/channel_stack.c @@ -210,6 +210,7 @@ void grpc_call_element_recv_metadata(grpc_call_element *cur_elem, metadata_op.dir = GRPC_CALL_UP; metadata_op.done_cb = do_nothing; metadata_op.user_data = NULL; + metadata_op.flags = 0; metadata_op.data.metadata = mdelem; grpc_call_next_op(cur_elem, &metadata_op); } @@ -221,6 +222,7 @@ void grpc_call_element_send_metadata(grpc_call_element *cur_elem, metadata_op.dir = GRPC_CALL_DOWN; metadata_op.done_cb = do_nothing; metadata_op.user_data = NULL; + metadata_op.flags = 0; metadata_op.data.metadata = mdelem; grpc_call_next_op(cur_elem, &metadata_op); } @@ -231,14 +233,16 @@ void grpc_call_element_send_cancel(grpc_call_element *cur_elem) { cancel_op.dir = GRPC_CALL_DOWN; cancel_op.done_cb = do_nothing; cancel_op.user_data = NULL; + cancel_op.flags = 0; grpc_call_next_op(cur_elem, &cancel_op); } void grpc_call_element_send_finish(grpc_call_element *cur_elem) { - grpc_call_op cancel_op; - cancel_op.type = GRPC_SEND_FINISH; - cancel_op.dir = GRPC_CALL_DOWN; - cancel_op.done_cb = do_nothing; - cancel_op.user_data = NULL; - grpc_call_next_op(cur_elem, &cancel_op); + grpc_call_op finish_op; + finish_op.type = GRPC_SEND_FINISH; + finish_op.dir = GRPC_CALL_DOWN; + finish_op.done_cb = do_nothing; + finish_op.user_data = NULL; + finish_op.flags = 0; + grpc_call_next_op(cur_elem, &finish_op); } diff --git a/src/core/channel/connected_channel.c b/src/core/channel/connected_channel.c index d35cede97b5..61a6caf0328 100644 --- a/src/core/channel/connected_channel.c +++ b/src/core/channel/connected_channel.c @@ -298,10 +298,6 @@ static void recv_error(channel_data *chand, call_data *calld, int line, static void do_nothing(void *calldata, grpc_op_error error) {} -static void done_message(void *user_data, grpc_op_error error) { - grpc_byte_buffer_destroy(user_data); -} - static void finish_message(channel_data *chand, call_data *calld) { grpc_call_element *elem = calld->elem; grpc_call_op call_op; @@ -309,9 +305,9 @@ static void finish_message(channel_data *chand, call_data *calld) { call_op.flags = 0; /* if we got all the bytes for this message, call up the stack */ call_op.type = GRPC_RECV_MESSAGE; - call_op.done_cb = done_message; + call_op.done_cb = do_nothing; /* TODO(ctiller): this could be a lot faster if coded directly */ - call_op.user_data = call_op.data.message = grpc_byte_buffer_create( + call_op.data.message = grpc_byte_buffer_create( calld->incoming_message.slices, calld->incoming_message.count); gpr_slice_buffer_reset_and_unref(&calld->incoming_message); diff --git a/src/core/iomgr/pollset_posix.c b/src/core/iomgr/pollset_posix.c index 994dbe495de..b1c2c64a18c 100644 --- a/src/core/iomgr/pollset_posix.c +++ b/src/core/iomgr/pollset_posix.c @@ -80,9 +80,7 @@ void grpc_pollset_kick(grpc_pollset *p) { } } -void grpc_pollset_force_kick(grpc_pollset *p) { - grpc_pollset_kick_kick(&p->kick_state); -} +void grpc_pollset_force_kick(grpc_pollset *p) { grpc_pollset_kick_kick(&p->kick_state); } /* global state management */ diff --git a/src/core/surface/byte_buffer_queue.c b/src/core/surface/byte_buffer_queue.c new file mode 100644 index 00000000000..36c082f4847 --- /dev/null +++ b/src/core/surface/byte_buffer_queue.c @@ -0,0 +1,79 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "src/core/surface/byte_buffer_queue.h" +#include + +static void bba_destroy(grpc_bbq_array *array) { + gpr_free(array->data); +} + +/* Append an operation to an array, expanding as needed */ +static void bba_push(grpc_bbq_array *a, grpc_byte_buffer *buffer) { + if (a->count == a->capacity) { + a->capacity *= 2; + a->data = gpr_realloc(a->data, sizeof(grpc_byte_buffer*) * a->capacity); + } + a->data[a->count++] = buffer; +} + +void grpc_bbq_destroy(grpc_byte_buffer_queue *q) { + bba_destroy(&q->filling); + bba_destroy(&q->draining); +} + +int grpc_bbq_empty(grpc_byte_buffer_queue *q) { + return (q->drain_pos == q->draining.count && q->filling.count == 0); +} + +void grpc_bbq_push(grpc_byte_buffer_queue *q, grpc_byte_buffer *buffer) { + bba_push(&q->filling, buffer); +} + +grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q) { + grpc_bbq_array temp_array; + + if (q->drain_pos == q->draining.count) { + if (q->filling.count == 0) { + return NULL; + } + q->draining.count = 0; + q->drain_pos = 0; + /* swap arrays */ + temp_array = q->filling; + q->filling = q->draining; + q->draining = temp_array; + } + + return q->draining.data[q->drain_pos++]; +} diff --git a/src/core/surface/byte_buffer_queue.h b/src/core/surface/byte_buffer_queue.h new file mode 100644 index 00000000000..358a42d5af0 --- /dev/null +++ b/src/core/surface/byte_buffer_queue.h @@ -0,0 +1,59 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __GRPC_INTERNAL_SURFACE_BYTE_BUFFER_QUEUE_H__ +#define __GRPC_INTERNAL_SURFACE_BYTE_BUFFER_QUEUE_H__ + +#include + +/* TODO(ctiller): inline an element or two into this struct to avoid per-call + allocations */ +typedef struct { + grpc_byte_buffer **data; + size_t count; + size_t capacity; +} grpc_bbq_array; + +/* should be initialized by zeroing memory */ +typedef struct { + size_t drain_pos; + grpc_bbq_array filling; + grpc_bbq_array draining; +} grpc_byte_buffer_queue; + +void grpc_bbq_destroy(grpc_byte_buffer_queue *q); +grpc_byte_buffer *grpc_bbq_pop(grpc_byte_buffer_queue *q); +int grpc_bbq_empty(grpc_byte_buffer_queue *q); +void grpc_bbq_push(grpc_byte_buffer_queue *q, grpc_byte_buffer *bb); + +#endif /* __GRPC_INTERNAL_SURFACE_BYTE_BUFFER_QUEUE_H__ */ diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 5a24264ccec..da966c874ac 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -36,6 +36,7 @@ #include "src/core/channel/metadata_buffer.h" #include "src/core/iomgr/alarm.h" #include "src/core/support/string.h" +#include "src/core/surface/byte_buffer_queue.h" #include "src/core/surface/channel.h" #include "src/core/surface/completion_queue.h" #include @@ -45,814 +46,763 @@ #include #include -#define INVALID_TAG ((void *)0xdeadbeef) +#define OP_IN_MASK(op, mask) (((1 << (op)) & (mask)) != 0) -/* Pending read queue +typedef struct legacy_state legacy_state; +static void destroy_legacy_state(legacy_state *ls); - This data structure tracks reads that need to be presented to the completion - queue but are waiting for the application to ask for them. */ +typedef enum { REQ_INITIAL = 0, REQ_READY, REQ_DONE } req_state; -#define INITIAL_PENDING_READ_COUNT 4 +typedef enum { + SEND_NOTHING, + SEND_INITIAL_METADATA, + SEND_MESSAGE, + SEND_TRAILING_METADATA_AND_FINISH, + SEND_FINISH +} send_action; typedef struct { - grpc_byte_buffer *byte_buffer; + grpc_ioreq_completion_func on_complete; void *user_data; - void (*on_finish)(void *user_data, grpc_op_error error); -} pending_read; - -/* TODO(ctiller): inline an element or two into this struct to avoid per-call - allocations */ -typedef struct { - pending_read *data; - size_t count; - size_t capacity; -} pending_read_array; + grpc_op_error status; +} completed_request; -typedef struct { - size_t drain_pos; - pending_read_array filling; - pending_read_array draining; -} pending_read_queue; +/* See reqinfo.set below for a description */ +#define REQSET_EMPTY 255 +#define REQSET_DONE 254 -static void pra_init(pending_read_array *array) { - array->data = gpr_malloc(sizeof(pending_read) * INITIAL_PENDING_READ_COUNT); - array->count = 0; - array->capacity = INITIAL_PENDING_READ_COUNT; -} +/* The state of an ioreq - we keep one of these on the call for each + grpc_ioreq_op type. -static void pra_destroy(pending_read_array *array, - size_t finish_starting_from) { - size_t i; - for (i = finish_starting_from; i < array->count; i++) { - array->data[i].on_finish(array->data[i].user_data, GRPC_OP_ERROR); - } - gpr_free(array->data); -} - -/* Append an operation to an array, expanding as needed */ -static void pra_push(pending_read_array *a, grpc_byte_buffer *buffer, - void (*on_finish)(void *user_data, grpc_op_error error), - void *user_data) { - if (a->count == a->capacity) { - a->capacity *= 2; - a->data = gpr_realloc(a->data, sizeof(pending_read) * a->capacity); - } - a->data[a->count].byte_buffer = buffer; - a->data[a->count].user_data = user_data; - a->data[a->count].on_finish = on_finish; - a->count++; -} - -static void prq_init(pending_read_queue *q) { - q->drain_pos = 0; - pra_init(&q->filling); - pra_init(&q->draining); -} - -static void prq_destroy(pending_read_queue *q) { - pra_destroy(&q->filling, 0); - pra_destroy(&q->draining, q->drain_pos); -} - -static int prq_is_empty(pending_read_queue *q) { - return (q->drain_pos == q->draining.count && q->filling.count == 0); -} - -static void prq_push(pending_read_queue *q, grpc_byte_buffer *buffer, - void (*on_finish)(void *user_data, grpc_op_error error), - void *user_data) { - pra_push(&q->filling, buffer, on_finish, user_data); -} - -/* Take the first queue element and move it to the completion queue. Do nothing - if q is empty */ -static int prq_pop_to_cq(pending_read_queue *q, void *tag, grpc_call *call, - grpc_completion_queue *cq) { - pending_read_array temp_array; - pending_read *pr; - - if (q->drain_pos == q->draining.count) { - if (q->filling.count == 0) { - return 0; - } - q->draining.count = 0; - q->drain_pos = 0; - /* swap arrays */ - temp_array = q->filling; - q->filling = q->draining; - q->draining = temp_array; - } + These structures are manipulated in sets, where a set is a set of + operations begin with the same call to start_ioreq and the various + public and private api's that call it. Each set has a master reqinfo + in which we set a few additional fields - see reqinfo_master. */ +typedef struct { + /* User supplied parameters */ + grpc_ioreq_data data; + /* In which set is this ioreq? + This value could be: + - an element of grpc_ioreq_op enumeration, in which case + it designates the master ioreq in a set of requests + - REQSET_EMPTY, in which case this reqinfo type has no application + request against it + - REQSET_DONE, in which case this reqinfo has been satisfied for + all time for this call, and no further use will be made of it */ + gpr_uint8 set; +} reqinfo; - pr = q->draining.data + q->drain_pos; - q->drain_pos++; - grpc_cq_end_read(cq, tag, call, pr->on_finish, pr->user_data, - pr->byte_buffer); - return 1; -} +typedef struct { + /* Overall status of the operation: starts OK, may degrade to + non-OK */ + grpc_op_error status; + /* Completion function to call at the end of the operation */ + grpc_ioreq_completion_func on_complete; + void *user_data; + /* a bit mask of which request ops are needed (1 << opid) */ + gpr_uint32 need_mask; + /* a bit mask of which request ops are now completed */ + gpr_uint32 complete_mask; +} reqinfo_master; + +/* Status data for a request can come from several sources; this + enumerates them all, and acts as a priority sorting for which + status to return to the application - earlier entries override + later ones */ +typedef enum { + /* Status came from the application layer overriding whatever + the wire says */ + STATUS_FROM_API_OVERRIDE = 0, + /* Status came from 'the wire' - or somewhere below the surface + layer */ + STATUS_FROM_WIRE, + STATUS_SOURCE_COUNT +} status_source; -/* grpc_call proper */ +typedef struct { + gpr_uint8 is_set; + grpc_status_code code; + grpc_mdstr *details; +} received_status; -/* the state of a call, based upon which functions have been called against - said call */ +/* How far through the GRPC stream have we read? */ typedef enum { - CALL_CREATED, - CALL_BOUNDCQ, - CALL_STARTED, - CALL_FINISHED -} call_state; + /* We are still waiting for initial metadata to complete */ + READ_STATE_INITIAL, + /* We have gotten initial metadata, and are reading either + messages or trailing metadata */ + READ_STATE_GOT_INITIAL_METADATA, + /* The stream is closed for reading */ + READ_STATE_READ_CLOSED, + /* The stream is closed for reading & writing */ + READ_STATE_STREAM_CLOSED +} read_state; struct grpc_call { grpc_completion_queue *cq; grpc_channel *channel; grpc_mdctx *metadata_context; + /* TODO(ctiller): share with cq if possible? */ + gpr_mu mu; - call_state state; gpr_uint8 is_client; - gpr_uint8 have_write; - grpc_metadata_buffer incoming_metadata; - - /* protects variables in this section */ - gpr_mu read_mu; - gpr_uint8 received_start; - gpr_uint8 start_ok; - gpr_uint8 reads_done; - gpr_uint8 received_finish; - gpr_uint8 received_metadata; - gpr_uint8 have_read; + read_state read_state; gpr_uint8 have_alarm; - gpr_uint8 pending_writes_done; - gpr_uint8 got_status_code; - /* The current outstanding read message tag (only valid if have_read == 1) */ - void *read_tag; - void *metadata_tag; - void *finished_tag; - pending_read_queue prq; + gpr_uint8 sending; + gpr_uint8 num_completed_requests; + gpr_uint8 need_more_data; + + reqinfo requests[GRPC_IOREQ_OP_COUNT]; + reqinfo_master masters[GRPC_IOREQ_OP_COUNT]; + completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; + grpc_byte_buffer_queue incoming_queue; + grpc_metadata_array buffered_initial_metadata; + grpc_metadata_array buffered_trailing_metadata; + grpc_mdelem **owned_metadata; + size_t owned_metadata_count; + size_t owned_metadata_capacity; + + received_status status[STATUS_SOURCE_COUNT]; grpc_alarm alarm; - /* The current outstanding send message/context/invoke/end tag (only valid if - have_write == 1) */ - void *write_tag; - grpc_byte_buffer *pending_write; - gpr_uint32 pending_write_flags; - - /* The final status of the call */ - grpc_status_code status_code; - grpc_mdstr *status_details; - gpr_refcount internal_refcount; + + legacy_state *legacy_state; }; -#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) +#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call)+1)) #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1) #define CALL_ELEM_FROM_CALL(call, idx) \ grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx) #define CALL_FROM_TOP_ELEM(top_elem) \ CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem)) +#define SWAP(type, x, y) \ + do { \ + type temp = x; \ + x = y; \ + y = temp; \ + } while (0) + 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, const void *server_transport_data) { + size_t i; grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel); grpc_call *call = gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size); - call->cq = NULL; + memset(call, 0, sizeof(grpc_call)); + gpr_mu_init(&call->mu); call->channel = channel; + call->is_client = server_transport_data == NULL; + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + call->requests[i].set = REQSET_EMPTY; + } + if (call->is_client) { + call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].set = REQSET_DONE; + call->requests[GRPC_IOREQ_SEND_STATUS].set = REQSET_DONE; + } grpc_channel_internal_ref(channel); call->metadata_context = grpc_channel_get_metadata_context(channel); - call->state = CALL_CREATED; - call->is_client = (server_transport_data == NULL); - call->write_tag = INVALID_TAG; - call->read_tag = INVALID_TAG; - call->metadata_tag = INVALID_TAG; - call->finished_tag = INVALID_TAG; - call->have_read = 0; - call->have_write = 0; - call->have_alarm = 0; - call->received_metadata = 0; - call->got_status_code = 0; - call->start_ok = 0; - call->status_code = - server_transport_data != NULL ? GRPC_STATUS_OK : GRPC_STATUS_UNKNOWN; - call->status_details = NULL; - call->received_finish = 0; - call->reads_done = 0; - call->received_start = 0; - call->pending_write = NULL; - call->pending_writes_done = 0; - grpc_metadata_buffer_init(&call->incoming_metadata); - gpr_ref_init(&call->internal_refcount, 1); + /* one ref is dropped in response to destroy, the other in + stream_closed */ + gpr_ref_init(&call->internal_refcount, 2); grpc_call_stack_init(channel_stack, server_transport_data, CALL_STACK_FROM_CALL(call)); - prq_init(&call->prq); - gpr_mu_init(&call->read_mu); return call; } void grpc_call_internal_ref(grpc_call *c) { gpr_ref(&c->internal_refcount); } -void grpc_call_internal_unref(grpc_call *c) { - if (gpr_unref(&c->internal_refcount)) { - grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); - grpc_metadata_buffer_destroy(&c->incoming_metadata, GRPC_OP_OK); - if (c->status_details) { - grpc_mdstr_unref(c->status_details); +static void destroy_call(void *call, int ignored_success) { + size_t i; + grpc_call *c = call; + grpc_call_stack_destroy(CALL_STACK_FROM_CALL(c)); + grpc_channel_internal_unref(c->channel); + gpr_mu_destroy(&c->mu); + for (i = 0; i < STATUS_SOURCE_COUNT; i++) { + if (c->status[i].details) { + grpc_mdstr_unref(c->status[i].details); } - prq_destroy(&c->prq); - gpr_mu_destroy(&c->read_mu); - grpc_channel_internal_unref(c->channel); - gpr_free(c); } + for (i = 0; i < c->owned_metadata_count; i++) { + grpc_mdelem_unref(c->owned_metadata[i]); + } + gpr_free(c->owned_metadata); + gpr_free(c->buffered_initial_metadata.metadata); + gpr_free(c->buffered_trailing_metadata.metadata); + if (c->legacy_state) { + destroy_legacy_state(c->legacy_state); + } + gpr_free(c); } -void grpc_call_destroy(grpc_call *c) { - int cancel; - gpr_mu_lock(&c->read_mu); - if (c->have_alarm) { - grpc_alarm_cancel(&c->alarm); - c->have_alarm = 0; +void grpc_call_internal_unref(grpc_call *c, int allow_immediate_deletion) { + if (gpr_unref(&c->internal_refcount)) { + if (allow_immediate_deletion) { + destroy_call(c, 1); + } else { + grpc_iomgr_add_callback(destroy_call, c); + } } - cancel = !c->received_finish; - gpr_mu_unlock(&c->read_mu); - if (cancel) grpc_call_cancel(c); - grpc_call_internal_unref(c); } -static void maybe_set_status_code(grpc_call *call, gpr_uint32 status) { - if (!call->got_status_code) { - call->status_code = status; - call->got_status_code = 1; - } +static void set_status_code(grpc_call *call, status_source source, + gpr_uint32 status) { + call->status[source].is_set = 1; + call->status[source].code = status; } -static void maybe_set_status_details(grpc_call *call, grpc_mdstr *status) { - if (!call->status_details) { - call->status_details = grpc_mdstr_ref(status); +static void set_status_details(grpc_call *call, status_source source, + grpc_mdstr *status) { + if (call->status[source].details != NULL) { + grpc_mdstr_unref(call->status[source].details); } + call->status[source].details = status; } -grpc_call_error grpc_call_cancel(grpc_call *c) { - grpc_call_element *elem; +static grpc_call_error bind_cq(grpc_call *call, grpc_completion_queue *cq) { + if (call->cq) return GRPC_CALL_ERROR_ALREADY_INVOKED; + call->cq = cq; + return GRPC_CALL_OK; +} + +static void request_more_data(grpc_call *call) { grpc_call_op op; - op.type = GRPC_CANCEL_OP; + /* call down */ + op.type = GRPC_REQUEST_DATA; op.dir = GRPC_CALL_DOWN; op.flags = 0; op.done_cb = do_nothing; op.user_data = NULL; - elem = CALL_ELEM_FROM_CALL(c, 0); - elem->filter->call_op(elem, NULL, &op); - - return GRPC_CALL_OK; + grpc_call_execute_op(call, &op); } -grpc_call_error grpc_call_cancel_with_status(grpc_call *c, - grpc_status_code status, - const char *description) { - grpc_mdstr *details = - description ? grpc_mdstr_from_string(c->metadata_context, description) - : NULL; - gpr_mu_lock(&c->read_mu); - maybe_set_status_code(c, status); - if (details) { - maybe_set_status_details(c, details); +static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); } + +static void unlock(grpc_call *call) { + send_action sa = SEND_NOTHING; + completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; + int num_completed_requests = call->num_completed_requests; + int need_more_data = + call->need_more_data && + call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].set == REQSET_DONE; + int i; + + if (need_more_data) { + call->need_more_data = 0; } - gpr_mu_unlock(&c->read_mu); - return grpc_call_cancel(c); -} -void grpc_call_execute_op(grpc_call *call, grpc_call_op *op) { - grpc_call_element *elem; - GPR_ASSERT(op->dir == GRPC_CALL_DOWN); - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, op); -} + if (num_completed_requests != 0) { + memcpy(completed_requests, call->completed_requests, + sizeof(completed_requests)); + call->num_completed_requests = 0; + } -void grpc_call_add_mdelem(grpc_call *call, grpc_mdelem *mdelem, - gpr_uint32 flags) { - grpc_call_element *elem; - grpc_call_op op; + if (!call->sending) { + sa = choose_send_action(call); + if (sa != SEND_NOTHING) { + call->sending = 1; + grpc_call_internal_ref(call); + } + } - GPR_ASSERT(call->state < CALL_FINISHED); + gpr_mu_unlock(&call->mu); - op.type = GRPC_SEND_METADATA; - op.dir = GRPC_CALL_DOWN; - op.flags = flags; - op.done_cb = do_nothing; - op.user_data = NULL; - op.data.metadata = mdelem; + if (need_more_data) { + request_more_data(call); + } - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); + if (sa != SEND_NOTHING) { + enact_send_action(call, sa); + } + + for (i = 0; i < num_completed_requests; i++) { + completed_requests[i].on_complete(call, completed_requests[i].status, + completed_requests[i].user_data); + } } -grpc_call_error grpc_call_add_metadata_old(grpc_call *call, - grpc_metadata *metadata, - gpr_uint32 flags) { - grpc_mdelem *mdelem; +static void get_final_status(grpc_call *call, grpc_recv_status_args args) { + 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); + } + memcpy(*args.details, GPR_SLICE_START_PTR(details), len); + (*args.details)[len] = 0; + } else { + goto no_details; + } + return; + } + } + *args.code = GRPC_STATUS_UNKNOWN; + if (!args.details) return; - if (call->is_client) { - if (call->state >= CALL_STARTED) { - return GRPC_CALL_ERROR_ALREADY_INVOKED; +no_details: + if (0 == *args.details_capacity) { + *args.details_capacity = 8; + *args.details = gpr_malloc(*args.details_capacity); + } + **args.details = 0; +} + +static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, + grpc_op_error status) { + completed_request *cr; + size_t i; + if (call->requests[op].set < GRPC_IOREQ_OP_COUNT) { + reqinfo_master *master = &call->masters[call->requests[op].set]; + /* ioreq is live: we need to do something */ + master->complete_mask |= 1 << op; + if (status != GRPC_OP_OK) { + master->status = status; } - } else { - if (call->state >= CALL_FINISHED) { - return GRPC_CALL_ERROR_ALREADY_FINISHED; + call->requests[op].set = + (op == GRPC_IOREQ_SEND_MESSAGE || op == GRPC_IOREQ_RECV_MESSAGE) + ? REQSET_EMPTY + : REQSET_DONE; + if (master->complete_mask == master->need_mask || status == GRPC_OP_ERROR) { + if (OP_IN_MASK(GRPC_IOREQ_RECV_STATUS, master->need_mask)) { + get_final_status( + call, call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status); + } + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + if (call->requests[i].set == op) { + call->requests[i].set = REQSET_EMPTY; + } + } + cr = &call->completed_requests[call->num_completed_requests++]; + cr->status = master->status; + cr->on_complete = master->on_complete; + cr->user_data = master->user_data; } } +} - mdelem = grpc_mdelem_from_string_and_buffer( - call->metadata_context, metadata->key, (gpr_uint8 *)metadata->value, - metadata->value_length); - grpc_call_add_mdelem(call, mdelem, flags); - return GRPC_CALL_OK; +static void finish_send_op(grpc_call *call, grpc_ioreq_op op, + grpc_op_error error) { + lock(call); + finish_ioreq_op(call, op, error); + call->sending = 0; + unlock(call); + grpc_call_internal_unref(call, 0); } -static void finish_call(grpc_call *call) { - size_t count; - grpc_metadata *elements; - count = grpc_metadata_buffer_count(&call->incoming_metadata); - elements = grpc_metadata_buffer_extract_elements(&call->incoming_metadata); - grpc_cq_end_finished( - call->cq, call->finished_tag, call, grpc_metadata_buffer_cleanup_elements, - elements, call->status_code, - call->status_details - ? (char *)grpc_mdstr_as_c_string(call->status_details) - : NULL, - elements, count); +static void finish_write_step(void *pc, grpc_op_error error) { + finish_send_op(pc, GRPC_IOREQ_SEND_MESSAGE, error); } -static void done_write(void *user_data, grpc_op_error error) { - grpc_call *call = user_data; - void *tag = call->write_tag; +static void finish_finish_step(void *pc, grpc_op_error error) { + finish_send_op(pc, GRPC_IOREQ_SEND_CLOSE, error); +} - GPR_ASSERT(call->have_write); - call->have_write = 0; - call->write_tag = INVALID_TAG; - grpc_cq_end_write_accepted(call->cq, tag, call, NULL, NULL, error); +static void finish_start_step(void *pc, grpc_op_error error) { + finish_send_op(pc, GRPC_IOREQ_SEND_INITIAL_METADATA, error); } -static void done_writes_done(void *user_data, grpc_op_error error) { - grpc_call *call = user_data; - void *tag = call->write_tag; +static send_action choose_send_action(grpc_call *call) { + switch (call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].set) { + case REQSET_EMPTY: + return SEND_NOTHING; + default: + return SEND_INITIAL_METADATA; + case REQSET_DONE: + break; + } + switch (call->requests[GRPC_IOREQ_SEND_MESSAGE].set) { + case REQSET_EMPTY: + return SEND_NOTHING; + default: + return SEND_MESSAGE; + case REQSET_DONE: + break; + } + switch (call->requests[GRPC_IOREQ_SEND_CLOSE].set) { + case REQSET_EMPTY: + case REQSET_DONE: + return SEND_NOTHING; + default: + if (call->is_client) { + return SEND_FINISH; + } else if (call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].set != + REQSET_EMPTY && + call->requests[GRPC_IOREQ_SEND_STATUS].set != REQSET_EMPTY) { + finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, GRPC_OP_OK); + return SEND_TRAILING_METADATA_AND_FINISH; + } else { + return SEND_NOTHING; + } + } +} - GPR_ASSERT(call->have_write); - call->have_write = 0; - call->write_tag = INVALID_TAG; - grpc_cq_end_finish_accepted(call->cq, tag, call, NULL, NULL, error); +static void send_metadata(grpc_call *call, grpc_mdelem *elem) { + grpc_call_op op; + op.type = GRPC_SEND_METADATA; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.data.metadata = elem; + op.done_cb = do_nothing; + op.user_data = NULL; + grpc_call_execute_op(call, &op); } -static void call_started(void *user_data, grpc_op_error error) { - grpc_call *call = user_data; - grpc_call_element *elem; - grpc_byte_buffer *pending_write = NULL; - gpr_uint32 pending_write_flags = 0; - gpr_uint8 pending_writes_done = 0; - int ok; +static void enact_send_action(grpc_call *call, send_action sa) { + grpc_ioreq_data data; grpc_call_op op; + size_t i; + char status_str[GPR_LTOA_MIN_BUFSIZE]; - gpr_mu_lock(&call->read_mu); - GPR_ASSERT(!call->received_start); - call->received_start = 1; - ok = call->start_ok = (error == GRPC_OP_OK); - pending_write = call->pending_write; - pending_write_flags = call->pending_write_flags; - pending_writes_done = call->pending_writes_done; - gpr_mu_unlock(&call->read_mu); - - if (pending_write) { - if (ok) { + switch (sa) { + case SEND_NOTHING: + abort(); + break; + case SEND_INITIAL_METADATA: + data = call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].data; + for (i = 0; i < data.send_metadata.count; i++) { + const grpc_metadata *md = &data.send_metadata.metadata[i]; + send_metadata(call, + grpc_mdelem_from_string_and_buffer( + call->metadata_context, md->key, + (const gpr_uint8 *)md->value, md->value_length)); + } + op.type = GRPC_SEND_START; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.data.start.pollset = grpc_cq_pollset(call->cq); + op.done_cb = finish_start_step; + op.user_data = call; + grpc_call_execute_op(call, &op); + break; + case SEND_MESSAGE: + data = call->requests[GRPC_IOREQ_SEND_MESSAGE].data; op.type = GRPC_SEND_MESSAGE; op.dir = GRPC_CALL_DOWN; - op.flags = pending_write_flags; - op.done_cb = done_write; + op.flags = 0; + op.data.message = data.send_message; + op.done_cb = finish_write_step; op.user_data = call; - op.data.message = pending_write; - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); - } else { - done_write(call, error); - } - grpc_byte_buffer_destroy(pending_write); - } - if (pending_writes_done) { - if (ok) { + grpc_call_execute_op(call, &op); + break; + case SEND_TRAILING_METADATA_AND_FINISH: + /* send trailing metadata */ + data = call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].data; + for (i = 0; i < data.send_metadata.count; i++) { + const grpc_metadata *md = &data.send_metadata.metadata[i]; + send_metadata(call, + grpc_mdelem_from_string_and_buffer( + call->metadata_context, md->key, + (const gpr_uint8 *)md->value, md->value_length)); + } + /* send status */ + /* TODO(ctiller): cache common status values */ + data = call->requests[GRPC_IOREQ_SEND_STATUS].data; + gpr_ltoa(data.send_status.code, status_str); + send_metadata( + call, + grpc_mdelem_from_metadata_strings( + call->metadata_context, + grpc_mdstr_ref(grpc_channel_get_status_string(call->channel)), + grpc_mdstr_from_string(call->metadata_context, status_str))); + if (data.send_status.details) { + send_metadata( + call, + grpc_mdelem_from_metadata_strings( + call->metadata_context, + grpc_mdstr_ref(grpc_channel_get_message_string(call->channel)), + grpc_mdstr_from_string(call->metadata_context, + data.send_status.details))); + } + /* fallthrough: see choose_send_action for details */ + case SEND_FINISH: op.type = GRPC_SEND_FINISH; op.dir = GRPC_CALL_DOWN; op.flags = 0; - op.done_cb = done_writes_done; + op.done_cb = finish_finish_step; op.user_data = call; - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); - } else { - done_writes_done(call, error); - } + grpc_call_execute_op(call, &op); + break; } - - grpc_call_internal_unref(call); } -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_call_element *elem; - grpc_call_op op; - - /* validate preconditions */ - if (!call->is_client) { - gpr_log(GPR_ERROR, "can only call %s on clients", __FUNCTION__); - return GRPC_CALL_ERROR_NOT_ON_SERVER; +static grpc_call_error start_ioreq_error(grpc_call *call, + gpr_uint32 mutated_ops, + grpc_call_error ret) { + size_t i; + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + if (mutated_ops & (1 << i)) { + call->requests[i].set = REQSET_EMPTY; + } } + return ret; +} - if (call->state >= CALL_STARTED || call->cq) { - gpr_log(GPR_ERROR, "call is already invoked"); - return GRPC_CALL_ERROR_ALREADY_INVOKED; +static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, + size_t nreqs, + grpc_ioreq_completion_func completion, + void *user_data) { + size_t i; + gpr_uint32 have_ops = 0; + grpc_ioreq_op op; + reqinfo *requests = call->requests; + reqinfo_master *master; + grpc_ioreq_data data; + gpr_uint8 set; + + if (nreqs == 0) { + return GRPC_CALL_OK; } - if (call->have_write) { - gpr_log(GPR_ERROR, "can only have one pending write operation at a time"); - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } + set = reqs[0].op; - if (call->have_read) { - gpr_log(GPR_ERROR, "can only have one pending read operation at a time"); - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } + for (i = 0; i < nreqs; i++) { + op = reqs[i].op; + if (requests[op].set < GRPC_IOREQ_OP_COUNT) { + return start_ioreq_error(call, have_ops, + GRPC_CALL_ERROR_TOO_MANY_OPERATIONS); + } else if (requests[op].set == REQSET_DONE) { + return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_ALREADY_INVOKED); + } + have_ops |= 1 << op; + data = reqs[i].data; - if (flags & GRPC_WRITE_NO_COMPRESS) { - return GRPC_CALL_ERROR_INVALID_FLAGS; + requests[op].data = data; + requests[op].set = set; } - /* inform the completion queue of an incoming operation */ - grpc_cq_begin_op(cq, call, GRPC_FINISHED); - grpc_cq_begin_op(cq, call, GRPC_CLIENT_METADATA_READ); - - gpr_mu_lock(&call->read_mu); - - /* update state */ - call->cq = cq; - call->state = CALL_STARTED; - call->finished_tag = finished_tag; - - if (call->received_finish) { - /* handle early cancellation */ - grpc_cq_end_client_metadata_read(call->cq, metadata_read_tag, call, NULL, - NULL, 0, NULL); - finish_call(call); - - /* early out.. unlock & return */ - gpr_mu_unlock(&call->read_mu); - return GRPC_CALL_OK; + master = &call->masters[set]; + master->status = GRPC_OP_OK; + master->need_mask = have_ops; + master->complete_mask = 0; + master->on_complete = completion; + master->user_data = user_data; + + for (i = 0; i < nreqs; i++) { + op = reqs[i].op; + data = reqs[i].data; + switch (op) { + case GRPC_IOREQ_OP_COUNT: + gpr_log(GPR_ERROR, "should never reach here"); + abort(); + break; + case GRPC_IOREQ_RECV_MESSAGE: + *data.recv_message = grpc_bbq_pop(&call->incoming_queue); + if (*data.recv_message) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + if (call->read_state == READ_STATE_STREAM_CLOSED && grpc_bbq_empty(&call->incoming_queue)) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); + } + } else { + /* no message: either end of stream or we need more bytes */ + if (call->read_state >= READ_STATE_READ_CLOSED) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + if (call->read_state == READ_STATE_STREAM_CLOSED) { + /* stream closed AND we've drained all messages: signal to the application */ + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); + } + } else { + call->need_more_data = 1; + } + } + break; + case GRPC_IOREQ_RECV_STATUS: + if (call->read_state >= READ_STATE_READ_CLOSED) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); + } + break; + case GRPC_IOREQ_RECV_CLOSE: + if (call->read_state == READ_STATE_STREAM_CLOSED) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); + } + break; + case GRPC_IOREQ_SEND_CLOSE: + if (requests[GRPC_IOREQ_SEND_MESSAGE].set == REQSET_EMPTY) { + requests[GRPC_IOREQ_SEND_MESSAGE].set = REQSET_DONE; + } + if (call->read_state == READ_STATE_STREAM_CLOSED) { + finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_ERROR); + } + break; + case GRPC_IOREQ_SEND_MESSAGE: + case GRPC_IOREQ_SEND_INITIAL_METADATA: + case GRPC_IOREQ_SEND_TRAILING_METADATA: + case GRPC_IOREQ_SEND_STATUS: + if (call->read_state == READ_STATE_STREAM_CLOSED) { + finish_ioreq_op(call, op, GRPC_OP_ERROR); + } + break; + case GRPC_IOREQ_RECV_INITIAL_METADATA: + data.recv_metadata->count = 0; + if (call->buffered_initial_metadata.count > 0) { + SWAP(grpc_metadata_array, *data.recv_metadata, + call->buffered_initial_metadata); + } + if (call->read_state >= READ_STATE_GOT_INITIAL_METADATA) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + } + break; + case GRPC_IOREQ_RECV_TRAILING_METADATA: + data.recv_metadata->count = 0; + if (call->buffered_trailing_metadata.count > 0) { + SWAP(grpc_metadata_array, *data.recv_metadata, + call->buffered_trailing_metadata); + } + if (call->read_state >= READ_STATE_READ_CLOSED) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); + } + break; + } } - call->metadata_tag = metadata_read_tag; - - gpr_mu_unlock(&call->read_mu); - - /* call down the filter stack */ - op.type = GRPC_SEND_START; - op.dir = GRPC_CALL_DOWN; - op.flags = flags; - op.done_cb = call_started; - op.data.start.pollset = grpc_cq_pollset(cq); - op.user_data = call; - grpc_call_internal_ref(call); - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); - return GRPC_CALL_OK; } -grpc_call_error grpc_call_server_accept_old(grpc_call *call, - grpc_completion_queue *cq, - void *finished_tag) { - /* validate preconditions */ - if (call->is_client) { - gpr_log(GPR_ERROR, "can only call %s on servers", __FUNCTION__); - return GRPC_CALL_ERROR_NOT_ON_CLIENT; - } - - if (call->state >= CALL_BOUNDCQ) { - gpr_log(GPR_ERROR, "call is already accepted"); - return GRPC_CALL_ERROR_ALREADY_ACCEPTED; - } +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); +} - /* inform the completion queue of an incoming operation (corresponding to - finished_tag) */ - grpc_cq_begin_op(cq, call, GRPC_FINISHED); +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; +} - /* update state */ - gpr_mu_lock(&call->read_mu); - call->state = CALL_BOUNDCQ; - call->cq = cq; - call->finished_tag = finished_tag; - call->received_start = 1; - if (prq_is_empty(&call->prq) && call->received_finish) { - finish_call(call); +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) { + grpc_call_error err; + lock(call); + err = start_ioreq(call, reqs, nreqs, on_complete, user_data); + unlock(call); + return err; +} - /* early out.. unlock & return */ - gpr_mu_unlock(&call->read_mu); - return GRPC_CALL_OK; +void grpc_call_destroy(grpc_call *c) { + int cancel; + lock(c); + if (c->have_alarm) { + grpc_alarm_cancel(&c->alarm); + c->have_alarm = 0; } - gpr_mu_unlock(&call->read_mu); - - return GRPC_CALL_OK; + cancel = c->read_state != READ_STATE_STREAM_CLOSED; + unlock(c); + if (cancel) grpc_call_cancel(c); + grpc_call_internal_unref(c, 1); } -grpc_call_error grpc_call_server_end_initial_metadata_old(grpc_call *call, - gpr_uint32 flags) { +grpc_call_error grpc_call_cancel(grpc_call *c) { grpc_call_element *elem; grpc_call_op op; - /* validate preconditions */ - if (call->is_client) { - gpr_log(GPR_ERROR, "can only call %s on servers", __FUNCTION__); - return GRPC_CALL_ERROR_NOT_ON_CLIENT; - } - - if (call->state >= CALL_STARTED) { - gpr_log(GPR_ERROR, "call is already started"); - return GRPC_CALL_ERROR_ALREADY_INVOKED; - } - - if (flags & GRPC_WRITE_NO_COMPRESS) { - return GRPC_CALL_ERROR_INVALID_FLAGS; - } - - /* update state */ - call->state = CALL_STARTED; - - /* call down */ - op.type = GRPC_SEND_START; + op.type = GRPC_CANCEL_OP; op.dir = GRPC_CALL_DOWN; - op.flags = flags; + op.flags = 0; op.done_cb = do_nothing; - op.data.start.pollset = grpc_cq_pollset(call->cq); op.user_data = NULL; - elem = CALL_ELEM_FROM_CALL(call, 0); + elem = CALL_ELEM_FROM_CALL(c, 0); elem->filter->call_op(elem, NULL, &op); return GRPC_CALL_OK; } -void grpc_call_client_initial_metadata_complete( - grpc_call_element *surface_element) { - grpc_call *call = grpc_call_from_top_element(surface_element); - size_t count; - grpc_metadata *elements; - - gpr_mu_lock(&call->read_mu); - count = grpc_metadata_buffer_count(&call->incoming_metadata); - elements = grpc_metadata_buffer_extract_elements(&call->incoming_metadata); - - GPR_ASSERT(!call->received_metadata); - grpc_cq_end_client_metadata_read(call->cq, call->metadata_tag, call, - grpc_metadata_buffer_cleanup_elements, - elements, count, elements); - call->received_metadata = 1; - call->metadata_tag = INVALID_TAG; - gpr_mu_unlock(&call->read_mu); +grpc_call_error grpc_call_cancel_with_status(grpc_call *c, + grpc_status_code status, + const char *description) { + grpc_mdstr *details = + description ? grpc_mdstr_from_string(c->metadata_context, description) + : NULL; + lock(c); + set_status_code(c, STATUS_FROM_API_OVERRIDE, status); + set_status_details(c, STATUS_FROM_API_OVERRIDE, details); + unlock(c); + return grpc_call_cancel(c); } -static void request_more_data(grpc_call *call) { +void grpc_call_execute_op(grpc_call *call, grpc_call_op *op) { grpc_call_element *elem; - grpc_call_op op; - - /* call down */ - op.type = GRPC_REQUEST_DATA; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = do_nothing; - op.user_data = NULL; - + GPR_ASSERT(op->dir == GRPC_CALL_DOWN); elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); + elem->filter->call_op(elem, NULL, op); } -grpc_call_error grpc_call_start_read_old(grpc_call *call, void *tag) { - gpr_uint8 request_more = 0; - - switch (call->state) { - case CALL_CREATED: - return GRPC_CALL_ERROR_NOT_INVOKED; - case CALL_BOUNDCQ: - case CALL_STARTED: - break; - case CALL_FINISHED: - return GRPC_CALL_ERROR_ALREADY_FINISHED; - } - - gpr_mu_lock(&call->read_mu); - - if (call->have_read) { - gpr_mu_unlock(&call->read_mu); - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } - - grpc_cq_begin_op(call->cq, call, GRPC_READ); +grpc_call *grpc_call_from_top_element(grpc_call_element *elem) { + return CALL_FROM_TOP_ELEM(elem); +} - if (!prq_pop_to_cq(&call->prq, tag, call, call->cq)) { - if (call->reads_done) { - grpc_cq_end_read(call->cq, tag, call, do_nothing, NULL, NULL); +static void call_alarm(void *arg, int success) { + grpc_call *call = arg; + if (success) { + if (call->is_client) { + grpc_call_cancel_with_status(call, GRPC_STATUS_DEADLINE_EXCEEDED, + "Deadline Exceeded"); } else { - call->read_tag = tag; - call->have_read = 1; - request_more = call->received_start; + grpc_call_cancel(call); } - } else if (prq_is_empty(&call->prq) && call->received_finish) { - finish_call(call); - } - - gpr_mu_unlock(&call->read_mu); - - if (request_more) { - request_more_data(call); } - - return GRPC_CALL_OK; + grpc_call_internal_unref(call, 1); } -grpc_call_error grpc_call_start_write_old(grpc_call *call, - grpc_byte_buffer *byte_buffer, - void *tag, gpr_uint32 flags) { - grpc_call_element *elem; - grpc_call_op op; - - switch (call->state) { - case CALL_CREATED: - case CALL_BOUNDCQ: - return GRPC_CALL_ERROR_NOT_INVOKED; - case CALL_STARTED: - break; - case CALL_FINISHED: - return GRPC_CALL_ERROR_ALREADY_FINISHED; - } - - if (call->have_write) { - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } - - grpc_cq_begin_op(call->cq, call, GRPC_WRITE_ACCEPTED); - - /* TODO(ctiller): if flags & GRPC_WRITE_BUFFER_HINT == 0, this indicates a - flush, and that flush should be propogated down from here */ - if (byte_buffer == NULL) { - grpc_cq_end_write_accepted(call->cq, tag, call, NULL, NULL, GRPC_OP_OK); - return GRPC_CALL_OK; - } - - call->write_tag = tag; - call->have_write = 1; - - gpr_mu_lock(&call->read_mu); - if (!call->received_start) { - call->pending_write = grpc_byte_buffer_copy(byte_buffer); - call->pending_write_flags = flags; - - gpr_mu_unlock(&call->read_mu); - } else { - gpr_mu_unlock(&call->read_mu); - - op.type = GRPC_SEND_MESSAGE; - op.dir = GRPC_CALL_DOWN; - op.flags = flags; - op.done_cb = done_write; - op.user_data = call; - op.data.message = byte_buffer; +void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); + if (call->have_alarm) { + gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice"); } - - return GRPC_CALL_OK; + grpc_call_internal_ref(call); + call->have_alarm = 1; + grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); } -grpc_call_error grpc_call_writes_done_old(grpc_call *call, void *tag) { - grpc_call_element *elem; - grpc_call_op op; - - if (!call->is_client) { - return GRPC_CALL_ERROR_NOT_ON_SERVER; - } - - switch (call->state) { - case CALL_CREATED: - case CALL_BOUNDCQ: - return GRPC_CALL_ERROR_NOT_INVOKED; - case CALL_FINISHED: - return GRPC_CALL_ERROR_ALREADY_FINISHED; - case CALL_STARTED: - break; - } - - if (call->have_write) { - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } - - grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); - - call->write_tag = tag; - call->have_write = 1; - - gpr_mu_lock(&call->read_mu); - if (!call->received_start) { - call->pending_writes_done = 1; - - gpr_mu_unlock(&call->read_mu); - } else { - gpr_mu_unlock(&call->read_mu); - - op.type = GRPC_SEND_FINISH; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = done_writes_done; - op.user_data = call; - - elem = CALL_ELEM_FROM_CALL(call, 0); - elem->filter->call_op(elem, NULL, &op); - } - - return GRPC_CALL_OK; +static void mark_read_closed(grpc_call *call) { + call->read_state = READ_STATE_READ_CLOSED; + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); + finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); } -grpc_call_error grpc_call_start_write_status_old(grpc_call *call, - grpc_status_code status, - const char *details, - void *tag) { - grpc_call_element *elem; - grpc_call_op op; - - if (call->is_client) { - return GRPC_CALL_ERROR_NOT_ON_CLIENT; - } - - switch (call->state) { - case CALL_CREATED: - case CALL_BOUNDCQ: - return GRPC_CALL_ERROR_NOT_INVOKED; - case CALL_FINISHED: - return GRPC_CALL_ERROR_ALREADY_FINISHED; - case CALL_STARTED: - break; - } - - if (call->have_write) { - return GRPC_CALL_ERROR_TOO_MANY_OPERATIONS; - } - - elem = CALL_ELEM_FROM_CALL(call, 0); - - if (details && details[0]) { - grpc_mdelem *md = grpc_mdelem_from_strings(call->metadata_context, - "grpc-message", details); +void grpc_call_read_closed(grpc_call_element *elem) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + lock(call); + GPR_ASSERT(call->read_state < READ_STATE_READ_CLOSED); + mark_read_closed(call); + unlock(call); +} - op.type = GRPC_SEND_METADATA; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = do_nothing; - op.user_data = NULL; - op.data.metadata = md; - elem->filter->call_op(elem, NULL, &op); +void grpc_call_stream_closed(grpc_call_element *elem) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + lock(call); + GPR_ASSERT(call->read_state < READ_STATE_STREAM_CLOSED); + if (call->read_state < READ_STATE_READ_CLOSED) { + mark_read_closed(call); } - - /* always send status */ - { - grpc_mdelem *md; - char buffer[GPR_LTOA_MIN_BUFSIZE]; - gpr_ltoa(status, buffer); - md = - grpc_mdelem_from_strings(call->metadata_context, "grpc-status", buffer); - - op.type = GRPC_SEND_METADATA; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = do_nothing; - op.user_data = NULL; - op.data.metadata = md; - elem->filter->call_op(elem, NULL, &op); + call->read_state = READ_STATE_STREAM_CLOSED; + if (grpc_bbq_empty(&call->incoming_queue)) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); } - - grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); - - call->state = CALL_FINISHED; - call->write_tag = tag; - call->have_write = 1; - - op.type = GRPC_SEND_FINISH; - op.dir = GRPC_CALL_DOWN; - op.flags = 0; - op.done_cb = done_writes_done; - op.user_data = call; - - elem->filter->call_op(elem, NULL, &op); - - return GRPC_CALL_OK; + unlock(call); + grpc_call_internal_unref(call, 0); } /* we offset status by a small amount when storing it into transport metadata @@ -865,7 +815,7 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { gpr_uint32 status; void *user_data = grpc_mdelem_get_user_data(md, destroy_status); if (user_data) { - status = ((gpr_uint32)(gpr_intptr)user_data) - STATUS_OFFSET; + status = ((gpr_uint32)(gpr_intptr) user_data) - STATUS_OFFSET; } else { if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value), GPR_SLICE_LENGTH(md->value->slice), @@ -878,112 +828,380 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { return status; } -void grpc_call_recv_metadata(grpc_call_element *elem, grpc_call_op *op) { +void grpc_call_recv_message(grpc_call_element *elem, + grpc_byte_buffer *byte_buffer) { + grpc_call *call = CALL_FROM_TOP_ELEM(elem); + lock(call); + if (call->requests[GRPC_IOREQ_RECV_MESSAGE].set < GRPC_IOREQ_OP_COUNT) { + /* there's an outstanding read */ + *call->requests[GRPC_IOREQ_RECV_MESSAGE].data.recv_message = byte_buffer; + finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + } else { + grpc_bbq_push(&call->incoming_queue, byte_buffer); + } + unlock(call); +} + +void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); - grpc_mdelem *md = op->data.metadata; grpc_mdstr *key = md->key; + grpc_metadata_array *dest; + grpc_metadata *mdusr; + lock(call); if (key == grpc_channel_get_status_string(call->channel)) { - maybe_set_status_code(call, decode_status(md)); + set_status_code(call, STATUS_FROM_WIRE, decode_status(md)); grpc_mdelem_unref(md); - op->done_cb(op->user_data, GRPC_OP_OK); } else if (key == grpc_channel_get_message_string(call->channel)) { - maybe_set_status_details(call, md->value); + set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value)); grpc_mdelem_unref(md); - op->done_cb(op->user_data, GRPC_OP_OK); } else { - grpc_metadata_buffer_queue(&call->incoming_metadata, op); + if (call->read_state < READ_STATE_GOT_INITIAL_METADATA) { + dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].set < + GRPC_IOREQ_OP_COUNT + ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] + .data.recv_metadata + : &call->buffered_initial_metadata; + } else { + dest = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].set < + GRPC_IOREQ_OP_COUNT + ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] + .data.recv_metadata + : &call->buffered_trailing_metadata; + } + if (dest->count == dest->capacity) { + dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2); + dest->metadata = + gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity); + } + mdusr = &dest->metadata[dest->count++]; + mdusr->key = (char *)grpc_mdstr_as_c_string(md->key); + mdusr->value = (char *)grpc_mdstr_as_c_string(md->value); + mdusr->value_length = GPR_SLICE_LENGTH(md->value->slice); + if (call->owned_metadata_count == call->owned_metadata_capacity) { + call->owned_metadata_capacity = GPR_MAX( + call->owned_metadata_capacity + 8, call->owned_metadata_capacity * 2); + call->owned_metadata = + gpr_realloc(call->owned_metadata, + sizeof(grpc_mdelem *) * call->owned_metadata_capacity); + } + call->owned_metadata[call->owned_metadata_count++] = md; } + unlock(call); } -void grpc_call_recv_finish(grpc_call_element *elem, int is_full_close) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); +grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) { + return CALL_STACK_FROM_CALL(call); +} - gpr_mu_lock(&call->read_mu); +/* + * LEGACY API IMPLEMENTATION + * All this code will disappear as soon as wrappings are updated + */ - if (call->have_read) { - grpc_cq_end_read(call->cq, call->read_tag, call, do_nothing, NULL, NULL); - call->read_tag = INVALID_TAG; - call->have_read = 0; - } - if (call->is_client && !call->received_metadata && call->cq) { - size_t count; - grpc_metadata *elements; +struct legacy_state { + gpr_uint8 md_out_buffer; + size_t md_out_count[2]; + size_t md_out_capacity[2]; + grpc_metadata *md_out[2]; + grpc_byte_buffer *msg_out; + + /* input buffers */ + grpc_metadata_array initial_md_in; + grpc_metadata_array trailing_md_in; - call->received_metadata = 1; + size_t details_capacity; + char *details; + grpc_status_code status; - count = grpc_metadata_buffer_count(&call->incoming_metadata); - elements = grpc_metadata_buffer_extract_elements(&call->incoming_metadata); - grpc_cq_end_client_metadata_read(call->cq, call->metadata_tag, call, - grpc_metadata_buffer_cleanup_elements, - elements, count, elements); + size_t msg_in_read_idx; + grpc_byte_buffer *msg_in; + + void *finished_tag; +}; + +static legacy_state *get_legacy_state(grpc_call *call) { + if (call->legacy_state == NULL) { + call->legacy_state = gpr_malloc(sizeof(legacy_state)); + memset(call->legacy_state, 0, sizeof(legacy_state)); } - if (is_full_close) { - if (call->have_alarm) { - grpc_alarm_cancel(&call->alarm); - call->have_alarm = 0; - } - call->received_finish = 1; - if (prq_is_empty(&call->prq) && call->cq != NULL) { - finish_call(call); + return call->legacy_state; +} + +static void destroy_legacy_state(legacy_state *ls) { + size_t i, j; + for (i = 0; i < 2; i++) { + for (j = 0; j < ls->md_out_count[i]; j++) { + gpr_free(ls->md_out[i][j].key); + gpr_free(ls->md_out[i][j].value); } - } else { - call->reads_done = 1; + gpr_free(ls->md_out[i]); } - gpr_mu_unlock(&call->read_mu); + gpr_free(ls->initial_md_in.metadata); + gpr_free(ls->trailing_md_in.metadata); + gpr_free(ls); } -void grpc_call_recv_message(grpc_call_element *elem, grpc_byte_buffer *message, - void (*on_finish)(void *user_data, - grpc_op_error error), - void *user_data) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); +grpc_call_error grpc_call_add_metadata_old(grpc_call *call, + grpc_metadata *metadata, + gpr_uint32 flags) { + legacy_state *ls; + grpc_metadata *mdout; + + lock(call); + ls = get_legacy_state(call); + + if (ls->md_out_count[ls->md_out_buffer] == + ls->md_out_capacity[ls->md_out_buffer]) { + ls->md_out_capacity[ls->md_out_buffer] = + GPR_MAX(ls->md_out_capacity[ls->md_out_buffer] * 3 / 2, + ls->md_out_capacity[ls->md_out_buffer] + 8); + ls->md_out[ls->md_out_buffer] = gpr_realloc( + ls->md_out[ls->md_out_buffer], + sizeof(grpc_metadata) * ls->md_out_capacity[ls->md_out_buffer]); + } + mdout = &ls->md_out[ls->md_out_buffer][ls->md_out_count[ls->md_out_buffer]++]; + mdout->key = gpr_strdup(metadata->key); + mdout->value = gpr_malloc(metadata->value_length); + mdout->value_length = metadata->value_length; + memcpy(mdout->value, metadata->value, metadata->value_length); + + unlock(call); + + return GRPC_CALL_OK; +} + +static void finish_status(grpc_call *call, grpc_op_error status, + void *ignored) { + legacy_state *ls; + + lock(call); + ls = get_legacy_state(call); + grpc_cq_end_finished(call->cq, ls->finished_tag, call, do_nothing, NULL, + ls->status, ls->details, ls->trailing_md_in.metadata, + ls->trailing_md_in.count); + unlock(call); +} + +static void finish_recv_metadata(grpc_call *call, grpc_op_error status, + void *tag) { + legacy_state *ls; + + lock(call); + ls = get_legacy_state(call); + if (status == GRPC_OP_OK) { + grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, + ls->initial_md_in.count, + ls->initial_md_in.metadata); - gpr_mu_lock(&call->read_mu); - if (call->have_read) { - grpc_cq_end_read(call->cq, call->read_tag, call, on_finish, user_data, - message); - call->read_tag = INVALID_TAG; - call->have_read = 0; } else { - prq_push(&call->prq, message, on_finish, user_data); + grpc_cq_end_client_metadata_read(call->cq, tag, call, do_nothing, NULL, 0, + NULL); } - gpr_mu_unlock(&call->read_mu); + unlock(call); } -grpc_call *grpc_call_from_top_element(grpc_call_element *elem) { - return CALL_FROM_TOP_ELEM(elem); +static void finish_send_metadata(grpc_call *call, grpc_op_error status, + void *tag) {} + +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]; + legacy_state *ls; + grpc_call_error err; + + grpc_cq_begin_op(cq, call, GRPC_CLIENT_METADATA_READ); + grpc_cq_begin_op(cq, call, GRPC_FINISHED); + + lock(call); + ls = get_legacy_state(call); + err = bind_cq(call, cq); + if (err != GRPC_CALL_OK) goto done; + + ls->finished_tag = finished_tag; + + reqs[0].op = GRPC_IOREQ_SEND_INITIAL_METADATA; + reqs[0].data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; + reqs[0].data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; + ls->md_out_buffer++; + err = start_ioreq(call, reqs, 1, finish_send_metadata, NULL); + if (err != GRPC_CALL_OK) goto done; + + reqs[0].op = GRPC_IOREQ_RECV_INITIAL_METADATA; + reqs[0].data.recv_metadata = &ls->initial_md_in; + err = start_ioreq(call, reqs, 1, finish_recv_metadata, metadata_read_tag); + if (err != GRPC_CALL_OK) goto done; + + 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); + if (err != GRPC_CALL_OK) goto done; + +done: + unlock(call); + return err; +} + +grpc_call_error grpc_call_server_accept_old(grpc_call *call, + grpc_completion_queue *cq, + void *finished_tag) { + grpc_ioreq reqs[2]; + grpc_call_error err; + legacy_state *ls; + + /* inform the completion queue of an incoming operation (corresponding to + finished_tag) */ + grpc_cq_begin_op(cq, call, GRPC_FINISHED); + + lock(call); + ls = get_legacy_state(call); + + err = bind_cq(call, cq); + if (err != GRPC_CALL_OK) return err; + + 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[1].op = GRPC_IOREQ_RECV_CLOSE; + err = start_ioreq(call, reqs, 2, finish_status, NULL); + unlock(call); + return err; } -grpc_metadata_buffer *grpc_call_get_metadata_buffer(grpc_call *call) { - return &call->incoming_metadata; +static void finish_send_initial_metadata(grpc_call *call, grpc_op_error status, + void *tag) {} + +grpc_call_error grpc_call_server_end_initial_metadata_old(grpc_call *call, + gpr_uint32 flags) { + grpc_ioreq req; + grpc_call_error err; + legacy_state *ls; + + lock(call); + ls = get_legacy_state(call); + req.op = GRPC_IOREQ_SEND_INITIAL_METADATA; + req.data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; + req.data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; + err = start_ioreq(call, &req, 1, finish_send_initial_metadata, NULL); + unlock(call); + + return err; } -static void call_alarm(void *arg, int success) { - grpc_call *call = arg; - if (success) { - if (call->is_client) { - grpc_call_cancel_with_status(call, GRPC_STATUS_DEADLINE_EXCEEDED, - "Deadline Exceeded"); - } else { - grpc_call_cancel(call); - } +void grpc_call_initial_metadata_complete(grpc_call_element *surface_element) { + grpc_call *call = grpc_call_from_top_element(surface_element); + lock(call); + if (call->read_state < READ_STATE_GOT_INITIAL_METADATA) { + call->read_state = READ_STATE_GOT_INITIAL_METADATA; } - grpc_call_internal_unref(call); + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + unlock(call); } -void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); +static void finish_read_event(void *p, grpc_op_error error) { + if (p) grpc_byte_buffer_destroy(p); +} - if (call->have_alarm) { - gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice"); - } - grpc_call_internal_ref(call); - call->have_alarm = 1; - grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); +static void finish_read(grpc_call *call, grpc_op_error error, void *tag) { + legacy_state *ls; + grpc_byte_buffer *msg; + lock(call); + ls = get_legacy_state(call); + msg = ls->msg_in; + grpc_cq_end_read(call->cq, tag, call, finish_read_event, msg, msg); + unlock(call); } -grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) { - return CALL_STACK_FROM_CALL(call); +grpc_call_error grpc_call_start_read_old(grpc_call *call, void *tag) { + legacy_state *ls; + grpc_ioreq req; + grpc_call_error err; + + grpc_cq_begin_op(call->cq, call, GRPC_READ); + + lock(call); + ls = get_legacy_state(call); + req.op = GRPC_IOREQ_RECV_MESSAGE; + req.data.recv_message = &ls->msg_in; + err = start_ioreq(call, &req, 1, finish_read, tag); + unlock(call); + return err; +} + +static void finish_write(grpc_call *call, grpc_op_error status, void *tag) { + lock(call); + grpc_byte_buffer_destroy(get_legacy_state(call)->msg_out); + unlock(call); + grpc_cq_end_write_accepted(call->cq, tag, call, do_nothing, NULL, status); +} + +grpc_call_error grpc_call_start_write_old(grpc_call *call, + grpc_byte_buffer *byte_buffer, + void *tag, gpr_uint32 flags) { + grpc_ioreq req; + legacy_state *ls; + grpc_call_error err; + + grpc_cq_begin_op(call->cq, call, GRPC_WRITE_ACCEPTED); + + lock(call); + ls = get_legacy_state(call); + ls->msg_out = grpc_byte_buffer_copy(byte_buffer); + req.op = GRPC_IOREQ_SEND_MESSAGE; + req.data.send_message = ls->msg_out; + err = start_ioreq(call, &req, 1, finish_write, tag); + unlock(call); + + return err; +} + +static void finish_finish(grpc_call *call, grpc_op_error status, void *tag) { + grpc_cq_end_finish_accepted(call->cq, tag, call, do_nothing, NULL, status); +} + +grpc_call_error grpc_call_writes_done_old(grpc_call *call, void *tag) { + grpc_ioreq req; + grpc_call_error err; + grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); + + lock(call); + req.op = GRPC_IOREQ_SEND_CLOSE; + err = start_ioreq(call, &req, 1, finish_finish, tag); + unlock(call); + + return err; } +grpc_call_error grpc_call_start_write_status_old(grpc_call *call, + grpc_status_code status, + const char *details, + void *tag) { + grpc_ioreq reqs[3]; + grpc_call_error err; + legacy_state *ls; + grpc_cq_begin_op(call->cq, call, GRPC_FINISH_ACCEPTED); + + lock(call); + ls = get_legacy_state(call); + reqs[0].op = GRPC_IOREQ_SEND_TRAILING_METADATA; + reqs[0].data.send_metadata.count = ls->md_out_count[ls->md_out_buffer]; + reqs[0].data.send_metadata.metadata = ls->md_out[ls->md_out_buffer]; + reqs[1].op = GRPC_IOREQ_SEND_STATUS; + reqs[1].data.send_status.code = status; + /* MEMLEAK */ + reqs[1].data.send_status.details = gpr_strdup(details); + reqs[2].op = GRPC_IOREQ_SEND_CLOSE; + err = start_ioreq(call, reqs, 3, finish_finish, tag); + unlock(call); + + return err; +} diff --git a/src/core/surface/call.h b/src/core/surface/call.h index 804b387cb19..936fb29f2ef 100644 --- a/src/core/surface/call.h +++ b/src/core/surface/call.h @@ -38,27 +38,73 @@ #include "src/core/channel/metadata_buffer.h" #include +/* Primitive operation types - grpc_op's get rewritten into these */ +typedef enum { + GRPC_IOREQ_RECV_INITIAL_METADATA, + GRPC_IOREQ_RECV_MESSAGE, + GRPC_IOREQ_RECV_TRAILING_METADATA, + GRPC_IOREQ_RECV_STATUS, + GRPC_IOREQ_RECV_CLOSE, + GRPC_IOREQ_SEND_INITIAL_METADATA, + GRPC_IOREQ_SEND_MESSAGE, + GRPC_IOREQ_SEND_TRAILING_METADATA, + GRPC_IOREQ_SEND_STATUS, + GRPC_IOREQ_SEND_CLOSE, + GRPC_IOREQ_OP_COUNT +} grpc_ioreq_op; + +typedef struct { + grpc_status_code *code; + char **details; + size_t *details_capacity; +} grpc_recv_status_args; + +typedef union { + grpc_metadata_array *recv_metadata; + grpc_byte_buffer **recv_message; + grpc_recv_status_args recv_status; + struct { + size_t count; + grpc_metadata *metadata; + } send_metadata; + grpc_byte_buffer *send_message; + struct { + grpc_status_code code; + char *details; + } send_status; +} grpc_ioreq_data; + +typedef struct { + grpc_ioreq_op op; + grpc_ioreq_data data; +} grpc_ioreq; + +typedef void (*grpc_ioreq_completion_func)(grpc_call *call, + grpc_op_error status, + void *user_data); + grpc_call *grpc_call_create(grpc_channel *channel, const void *server_transport_data); void grpc_call_internal_ref(grpc_call *call); -void grpc_call_internal_unref(grpc_call *call); +void grpc_call_internal_unref(grpc_call *call, int allow_immediate_deletion); /* Helpers for grpc_client, grpc_server filters to publish received data to the completion queue/surface layer */ void grpc_call_recv_metadata(grpc_call_element *surface_element, - grpc_call_op *op); -void grpc_call_recv_message( - grpc_call_element *surface_element, grpc_byte_buffer *message, - void (*on_finish)(void *user_data, grpc_op_error error), void *user_data); -void grpc_call_recv_finish(grpc_call_element *surface_element, - int is_full_close); + grpc_mdelem *md); +void grpc_call_recv_message(grpc_call_element *surface_element, + grpc_byte_buffer *message); +void grpc_call_read_closed(grpc_call_element *surface_element); +void grpc_call_stream_closed(grpc_call_element *surface_element); void grpc_call_execute_op(grpc_call *call, grpc_call_op *op); +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); -/* Called when it's known that the initial batch of metadata is complete on the - client side (must not be called on the server) */ -void grpc_call_client_initial_metadata_complete( +/* Called when it's known that the initial batch of metadata is complete */ +void grpc_call_initial_metadata_complete( grpc_call_element *surface_element); void grpc_call_set_deadline(grpc_call_element *surface_element, @@ -69,10 +115,4 @@ grpc_call_stack *grpc_call_get_call_stack(grpc_call *call); /* Given the top call_element, get the call object. */ grpc_call *grpc_call_from_top_element(grpc_call_element *surface_element); -/* Get the metadata buffer. */ -grpc_metadata_buffer *grpc_call_get_metadata_buffer(grpc_call *call); - -void grpc_call_add_mdelem(grpc_call *call, grpc_mdelem *mdelem, - gpr_uint32 flags); - #endif /* __GRPC_INTERNAL_SURFACE_CALL_H__ */ diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c index 93a2c0609d8..c33ea923e82 100644 --- a/src/core/surface/channel.c +++ b/src/core/surface/channel.c @@ -51,7 +51,7 @@ struct grpc_channel { grpc_mdstr *authority_string; }; -#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c) + 1)) +#define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack *)((c)+1)) grpc_channel *grpc_channel_create_from_filters( const grpc_channel_filter **filters, size_t num_filters, @@ -80,6 +80,7 @@ grpc_call *grpc_channel_create_call_old(grpc_channel *channel, grpc_call *call; grpc_mdelem *path_mdelem; grpc_mdelem *authority_mdelem; + grpc_call_op op; if (!channel->is_client) { gpr_log(GPR_ERROR, "Cannot create a call on the server."); @@ -91,20 +92,25 @@ grpc_call *grpc_channel_create_call_old(grpc_channel *channel, /* Add :path and :authority headers. */ /* TODO(klempner): Consider optimizing this by stashing mdelems for common values of method and host. */ - grpc_mdstr_ref(channel->path_string); path_mdelem = grpc_mdelem_from_metadata_strings( - channel->metadata_context, channel->path_string, + channel->metadata_context, grpc_mdstr_ref(channel->path_string), grpc_mdstr_from_string(channel->metadata_context, method)); - grpc_call_add_mdelem(call, path_mdelem, 0); + op.type = GRPC_SEND_METADATA; + op.dir = GRPC_CALL_DOWN; + op.flags = 0; + op.data.metadata = path_mdelem; + op.done_cb = do_nothing; + op.user_data = NULL; + grpc_call_execute_op(call, &op); grpc_mdstr_ref(channel->authority_string); authority_mdelem = grpc_mdelem_from_metadata_strings( channel->metadata_context, channel->authority_string, grpc_mdstr_from_string(channel->metadata_context, host)); - grpc_call_add_mdelem(call, authority_mdelem, 0); + op.data.metadata = authority_mdelem; + grpc_call_execute_op(call, &op); if (0 != gpr_time_cmp(absolute_deadline, gpr_inf_future)) { - grpc_call_op op; op.type = GRPC_SEND_DEADLINE; op.dir = GRPC_CALL_DOWN; op.flags = 0; diff --git a/src/core/surface/client.c b/src/core/surface/client.c index a7c9b902ed4..fa63e855cc8 100644 --- a/src/core/surface/client.c +++ b/src/core/surface/client.c @@ -56,23 +56,23 @@ static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, grpc_call_next_op(elem, op); break; case GRPC_RECV_METADATA: - grpc_call_recv_metadata(elem, op); + grpc_call_recv_metadata(elem, op->data.metadata); break; case GRPC_RECV_DEADLINE: gpr_log(GPR_ERROR, "Deadline received by client (ignored)"); break; case GRPC_RECV_MESSAGE: - grpc_call_recv_message(elem, op->data.message, op->done_cb, - op->user_data); + grpc_call_recv_message(elem, op->data.message); + op->done_cb(op->user_data, GRPC_OP_OK); break; case GRPC_RECV_HALF_CLOSE: - grpc_call_recv_finish(elem, 0); + grpc_call_read_closed(elem); break; case GRPC_RECV_FINISH: - grpc_call_recv_finish(elem, 1); + grpc_call_stream_closed(elem); break; case GRPC_RECV_END_OF_INITIAL_METADATA: - grpc_call_client_initial_metadata_complete(elem); + grpc_call_initial_metadata_complete(elem); break; default: GPR_ASSERT(op->dir == GRPC_CALL_DOWN); diff --git a/src/core/surface/completion_queue.c b/src/core/surface/completion_queue.c index 2bf31c50a8f..ae3b96035c1 100644 --- a/src/core/surface/completion_queue.c +++ b/src/core/surface/completion_queue.c @@ -173,18 +173,6 @@ void grpc_cq_end_read(grpc_completion_queue *cc, void *tag, grpc_call *call, gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } -void grpc_cq_end_invoke_accepted(grpc_completion_queue *cc, void *tag, - grpc_call *call, - grpc_event_finish_func on_finish, - void *user_data, grpc_op_error error) { - event *ev; - gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); - ev = add_locked(cc, GRPC_INVOKE_ACCEPTED, tag, call, on_finish, user_data); - ev->base.data.invoke_accepted = error; - end_op_locked(cc, GRPC_INVOKE_ACCEPTED); - gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); -} - void grpc_cq_end_write_accepted(grpc_completion_queue *cc, void *tag, grpc_call *call, grpc_event_finish_func on_finish, @@ -197,6 +185,17 @@ void grpc_cq_end_write_accepted(grpc_completion_queue *cc, void *tag, gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); } +void grpc_cq_end_ioreq(grpc_completion_queue *cc, void *tag, grpc_call *call, + grpc_event_finish_func on_finish, void *user_data, + grpc_op_error error) { + event *ev; + gpr_mu_lock(GRPC_POLLSET_MU(&cc->pollset)); + ev = add_locked(cc, GRPC_IOREQ, tag, call, on_finish, user_data); + ev->base.data.write_accepted = error; + end_op_locked(cc, GRPC_IOREQ); + gpr_mu_unlock(GRPC_POLLSET_MU(&cc->pollset)); +} + void grpc_cq_end_finish_accepted(grpc_completion_queue *cc, void *tag, grpc_call *call, grpc_event_finish_func on_finish, @@ -389,7 +388,7 @@ void grpc_event_finish(grpc_event *base) { event *ev = (event *)base; ev->on_finish(ev->on_finish_user_data, GRPC_OP_OK); if (ev->base.call) { - grpc_call_internal_unref(ev->base.call); + grpc_call_internal_unref(ev->base.call, 1); } gpr_free(ev); } diff --git a/src/core/surface/completion_queue.h b/src/core/surface/completion_queue.h index 85984075f78..fea8336b633 100644 --- a/src/core/surface/completion_queue.h +++ b/src/core/surface/completion_queue.h @@ -97,6 +97,10 @@ void grpc_cq_end_new_rpc(grpc_completion_queue *cc, void *tag, grpc_call *call, gpr_timespec deadline, size_t metadata_count, grpc_metadata *metadata_elements); +void grpc_cq_end_ioreq(grpc_completion_queue *cc, void *tag, grpc_call *call, + grpc_event_finish_func on_finish, void *user_data, + grpc_op_error error); + void grpc_cq_end_server_shutdown(grpc_completion_queue *cc, void *tag); /* disable polling for some tests */ diff --git a/src/core/surface/event_string.c b/src/core/surface/event_string.c index 8975d312eec..7c76bf93d7c 100644 --- a/src/core/surface/event_string.c +++ b/src/core/surface/event_string.c @@ -87,10 +87,10 @@ char *grpc_event_string(grpc_event *ev) { gpr_strvec_add(&buf, gpr_strdup(" end-of-stream")); } break; - case GRPC_INVOKE_ACCEPTED: - gpr_strvec_add(&buf, gpr_strdup("INVOKE_ACCEPTED: ")); + case GRPC_IOREQ: + gpr_strvec_add(&buf, gpr_strdup("IOREQ: ")); addhdr(&buf, ev); - adderr(&buf, ev->data.invoke_accepted); + adderr(&buf, ev->data.ioreq); break; case GRPC_WRITE_ACCEPTED: gpr_strvec_add(&buf, gpr_strdup("WRITE_ACCEPTED: ")); diff --git a/src/core/surface/lame_client.c b/src/core/surface/lame_client.c index 6098ac78de4..2f5eff55844 100644 --- a/src/core/surface/lame_client.c +++ b/src/core/surface/lame_client.c @@ -50,26 +50,16 @@ typedef struct { grpc_mdelem *message; } channel_data; -static void do_nothing(void *data, grpc_op_error error) {} - static void call_op(grpc_call_element *elem, grpc_call_element *from_elem, grpc_call_op *op) { channel_data *channeld = elem->channel_data; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); switch (op->type) { - case GRPC_SEND_START: { - grpc_call_op set_status_op; - grpc_mdelem_ref(channeld->message); - memset(&set_status_op, 0, sizeof(grpc_call_op)); - set_status_op.dir = GRPC_CALL_UP; - set_status_op.type = GRPC_RECV_METADATA; - set_status_op.done_cb = do_nothing; - set_status_op.data.metadata = channeld->message; - grpc_call_recv_metadata(elem, &set_status_op); - grpc_call_recv_finish(elem, 1); + case GRPC_SEND_START: + grpc_call_recv_metadata(elem, grpc_mdelem_ref(channeld->message)); + grpc_call_stream_closed(elem); break; - } case GRPC_SEND_METADATA: grpc_mdelem_unref(op->data.metadata); break; diff --git a/src/core/surface/server.c b/src/core/surface/server.c index 9e2e4d54780..a057694f13a 100644 --- a/src/core/surface/server.c +++ b/src/core/surface/server.c @@ -44,6 +44,7 @@ #include "src/core/surface/call.h" #include "src/core/surface/channel.h" #include "src/core/surface/completion_queue.h" +#include "src/core/transport/metadata.h" #include #include #include @@ -63,11 +64,24 @@ typedef struct channel_data channel_data; struct channel_data { grpc_server *server; grpc_channel *channel; + grpc_mdstr *path_key; + grpc_mdstr *authority_key; /* linked list of all channels on a server */ channel_data *next; channel_data *prev; }; +typedef void (*new_call_cb)(grpc_server *server, grpc_completion_queue *cq, + grpc_metadata_array *initial_metadata, + call_data *calld, void *user_data); + +typedef struct { + void *user_data; + grpc_completion_queue *cq; + grpc_metadata_array *initial_metadata; + new_call_cb cb; +} requested_call; + struct grpc_server { size_t channel_filter_count; const grpc_channel_filter **channel_filters; @@ -76,9 +90,9 @@ struct grpc_server { gpr_mu mu; - void **tags; - size_t ntags; - size_t tag_cap; + requested_call *requested_calls; + size_t requested_call_count; + size_t requested_call_capacity; gpr_uint8 shutdown; gpr_uint8 have_shutdown_tag; @@ -107,11 +121,17 @@ typedef enum { ZOMBIED } call_state; +typedef struct legacy_data { grpc_metadata_array *initial_metadata; } legacy_data; + struct call_data { grpc_call *call; call_state state; gpr_timespec deadline; + grpc_mdstr *path; + grpc_mdstr *host; + + legacy_data *legacy; gpr_uint8 included[CALL_LIST_COUNT]; call_link links[CALL_LIST_COUNT]; @@ -179,7 +199,7 @@ static void server_unref(grpc_server *server) { grpc_channel_args_destroy(server->channel_args); gpr_mu_destroy(&server->mu); gpr_free(server->channel_filters); - gpr_free(server->tags); + gpr_free(server->requested_calls); gpr_free(server); } } @@ -210,62 +230,37 @@ static void destroy_channel(channel_data *chand) { grpc_iomgr_add_callback(finish_destroy_channel, chand); } -static void queue_new_rpc(grpc_server *server, call_data *calld, void *tag) { - grpc_call *call = calld->call; - grpc_metadata_buffer *mdbuf = grpc_call_get_metadata_buffer(call); - size_t count = grpc_metadata_buffer_count(mdbuf); - grpc_metadata *elements = grpc_metadata_buffer_extract_elements(mdbuf); - const char *host = NULL; - const char *method = NULL; - size_t i; - - for (i = 0; i < count; i++) { - if (0 == strcmp(elements[i].key, ":authority")) { - host = elements[i].value; - } else if (0 == strcmp(elements[i].key, ":path")) { - method = elements[i].value; - } - } - - grpc_call_internal_ref(call); - grpc_cq_end_new_rpc(server->cq, tag, call, - grpc_metadata_buffer_cleanup_elements, elements, method, - host, calld->deadline, count, elements); -} - static void start_new_rpc(grpc_call_element *elem) { channel_data *chand = elem->channel_data; call_data *calld = elem->call_data; grpc_server *server = chand->server; gpr_mu_lock(&server->mu); - if (server->ntags) { + if (server->requested_call_count > 0) { + requested_call rc = server->requested_calls[--server->requested_call_count]; calld->state = ACTIVATED; - queue_new_rpc(server, calld, server->tags[--server->ntags]); + gpr_mu_unlock(&server->mu); + rc.cb(server, rc.cq, rc.initial_metadata, calld, rc.user_data); } else { calld->state = PENDING; call_list_join(server, calld, PENDING_START); + gpr_mu_unlock(&server->mu); } - gpr_mu_unlock(&server->mu); } static void kill_zombie(void *elem, int success) { grpc_call_destroy(grpc_call_from_top_element(elem)); } -static void finish_rpc(grpc_call_element *elem, int is_full_close) { +static void stream_closed(grpc_call_element *elem) { call_data *calld = elem->call_data; channel_data *chand = elem->channel_data; gpr_mu_lock(&chand->server->mu); switch (calld->state) { case ACTIVATED: - grpc_call_recv_finish(elem, is_full_close); + grpc_call_stream_closed(elem); break; case PENDING: - if (!is_full_close) { - grpc_call_recv_finish(elem, is_full_close); - break; - } call_list_remove(chand->server, calld, PENDING_START); /* fallthrough intended */ case NOT_STARTED: @@ -278,25 +273,57 @@ static void finish_rpc(grpc_call_element *elem, int is_full_close) { gpr_mu_unlock(&chand->server->mu); } +static void read_closed(grpc_call_element *elem) { + call_data *calld = elem->call_data; + channel_data *chand = elem->channel_data; + gpr_mu_lock(&chand->server->mu); + switch (calld->state) { + case ACTIVATED: + case PENDING: + grpc_call_read_closed(elem); + break; + case NOT_STARTED: + calld->state = ZOMBIED; + grpc_iomgr_add_callback(kill_zombie, elem); + break; + case ZOMBIED: + break; + } + gpr_mu_unlock(&chand->server->mu); +} + static void call_op(grpc_call_element *elem, grpc_call_element *from_elemn, grpc_call_op *op) { + channel_data *chand = elem->channel_data; + call_data *calld = elem->call_data; + grpc_mdelem *md; GRPC_CALL_LOG_OP(GPR_INFO, elem, op); switch (op->type) { case GRPC_RECV_METADATA: - grpc_call_recv_metadata(elem, op); + md = op->data.metadata; + if (md->key == chand->path_key) { + calld->path = grpc_mdstr_ref(md->value); + grpc_mdelem_unref(md); + } else if (md->key == chand->authority_key) { + calld->host = grpc_mdstr_ref(md->value); + grpc_mdelem_unref(md); + } else { + grpc_call_recv_metadata(elem, md); + } break; case GRPC_RECV_END_OF_INITIAL_METADATA: start_new_rpc(elem); + grpc_call_initial_metadata_complete(elem); break; case GRPC_RECV_MESSAGE: - grpc_call_recv_message(elem, op->data.message, op->done_cb, - op->user_data); + grpc_call_recv_message(elem, op->data.message); + op->done_cb(op->user_data, GRPC_OP_OK); break; case GRPC_RECV_HALF_CLOSE: - finish_rpc(elem, 0); + read_closed(elem); break; case GRPC_RECV_FINISH: - finish_rpc(elem, 1); + stream_closed(elem); break; case GRPC_RECV_DEADLINE: grpc_call_set_deadline(elem, op->data.deadline); @@ -371,6 +398,7 @@ static void init_call_elem(grpc_call_element *elem, static void destroy_call_elem(grpc_call_element *elem) { channel_data *chand = elem->channel_data; + call_data *calld = elem->call_data; int i; gpr_mu_lock(&chand->server->mu); @@ -383,6 +411,19 @@ static void destroy_call_elem(grpc_call_element *elem) { } gpr_mu_unlock(&chand->server->mu); + if (calld->host) { + grpc_mdstr_unref(calld->host); + } + if (calld->path) { + grpc_mdstr_unref(calld->path); + } + + if (calld->legacy) { + gpr_free(calld->legacy->initial_metadata->metadata); + gpr_free(calld->legacy->initial_metadata); + gpr_free(calld->legacy); + } + server_unref(chand->server); } @@ -395,6 +436,8 @@ static void init_channel_elem(grpc_channel_element *elem, GPR_ASSERT(!is_last); chand->server = NULL; chand->channel = NULL; + chand->path_key = grpc_mdstr_from_string(metadata_context, ":path"); + chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority"); chand->next = chand->prev = chand; } @@ -406,6 +449,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) { chand->prev->next = chand->next; chand->next = chand->prev = chand; gpr_mu_unlock(&chand->server->mu); + grpc_mdstr_unref(chand->path_key); + grpc_mdstr_unref(chand->authority_key); server_unref(chand->server); } } @@ -413,17 +458,8 @@ static void destroy_channel_elem(grpc_channel_element *elem) { static const grpc_channel_filter server_surface_filter = { call_op, channel_op, sizeof(call_data), init_call_elem, destroy_call_elem, sizeof(channel_data), - init_channel_elem, destroy_channel_elem, "server", }; - -static void early_terminate_requested_calls(grpc_completion_queue *cq, - void **tags, size_t ntags) { - size_t i; - - for (i = 0; i < ntags; i++) { - grpc_cq_end_new_rpc(cq, tags[i], NULL, do_nothing, NULL, NULL, NULL, - gpr_inf_past, 0, NULL); - } -} + init_channel_elem, destroy_channel_elem, "server", +}; grpc_server *grpc_server_create_from_filters(grpc_completion_queue *cq, grpc_channel_filter **filters, @@ -517,8 +553,8 @@ grpc_transport_setup_result grpc_server_setup_transport( void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag, void *shutdown_tag) { listener *l; - void **tags; - size_t ntags; + requested_call *requested_calls; + size_t requested_call_count; channel_data **channels; channel_data *c; size_t nchannels; @@ -547,10 +583,10 @@ void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag, i++; } - tags = server->tags; - ntags = server->ntags; - server->tags = NULL; - server->ntags = 0; + requested_calls = server->requested_calls; + requested_call_count = server->requested_call_count; + server->requested_calls = NULL; + server->requested_call_count = 0; server->shutdown = 1; server->have_shutdown_tag = have_shutdown_tag; @@ -579,8 +615,12 @@ void shutdown_internal(grpc_server *server, gpr_uint8 have_shutdown_tag, gpr_free(channels); /* terminate all the requested calls */ - early_terminate_requested_calls(server->cq, tags, ntags); - gpr_free(tags); + for (i = 0; i < requested_call_count; i++) { + requested_calls[i].cb(server, requested_calls[i].cq, + requested_calls[i].initial_metadata, NULL, + requested_calls[i].user_data); + } + gpr_free(requested_calls); /* Shutdown listeners */ for (l = server->listeners; l; l = l->next) { @@ -625,36 +665,105 @@ void grpc_server_add_listener(grpc_server *server, void *arg, server->listeners = l; } -grpc_call_error grpc_server_request_call_old(grpc_server *server, - void *tag_new) { +static grpc_call_error queue_call_request(grpc_server *server, + grpc_completion_queue *cq, + grpc_metadata_array *initial_metadata, + new_call_cb cb, void *user_data) { call_data *calld; - - grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_RPC_NEW); - + requested_call *rc; gpr_mu_lock(&server->mu); - if (server->shutdown) { gpr_mu_unlock(&server->mu); - early_terminate_requested_calls(server->cq, &tag_new, 1); + cb(server, cq, initial_metadata, NULL, user_data); return GRPC_CALL_OK; } - calld = call_list_remove_head(server, PENDING_START); if (calld) { GPR_ASSERT(calld->state == PENDING); calld->state = ACTIVATED; - queue_new_rpc(server, calld, tag_new); + gpr_mu_unlock(&server->mu); + cb(server, cq, initial_metadata, calld, user_data); + return GRPC_CALL_OK; } else { - if (server->tag_cap == server->ntags) { - server->tag_cap = GPR_MAX(3 * server->tag_cap / 2, server->tag_cap + 1); - server->tags = - gpr_realloc(server->tags, sizeof(void *) * server->tag_cap); + if (server->requested_call_count == server->requested_call_capacity) { + server->requested_call_capacity = + GPR_MAX(server->requested_call_capacity + 8, + server->requested_call_capacity * 2); + server->requested_calls = + gpr_realloc(server->requested_calls, + sizeof(requested_call) * server->requested_call_capacity); } - server->tags[server->ntags++] = tag_new; + rc = &server->requested_calls[server->requested_call_count++]; + rc->cb = cb; + rc->cq = cq; + rc->user_data = user_data; + rc->initial_metadata = initial_metadata; + gpr_mu_unlock(&server->mu); + return GRPC_CALL_OK; } - gpr_mu_unlock(&server->mu); +} + +static void begin_request(grpc_server *server, grpc_completion_queue *cq, + grpc_metadata_array *initial_metadata, + call_data *call_data, void *tag) { + abort(); +} - return GRPC_CALL_OK; +grpc_call_error grpc_server_request_call( + grpc_server *server, grpc_call_details *details, + grpc_metadata_array *initial_metadata, grpc_completion_queue *cq, + void *tag) { + grpc_cq_begin_op(cq, NULL, GRPC_IOREQ); + return queue_call_request(server, cq, initial_metadata, begin_request, tag); +} + +static void publish_legacy_request(grpc_call *call, grpc_op_error status, + void *tag) { + grpc_call_element *elem = + grpc_call_stack_element(grpc_call_get_call_stack(call), 0); + call_data *calld = elem->call_data; + channel_data *chand = elem->channel_data; + grpc_server *server = chand->server; + + if (status == GRPC_OP_OK) { + grpc_cq_end_new_rpc(server->cq, tag, call, do_nothing, NULL, + grpc_mdstr_as_c_string(calld->path), + grpc_mdstr_as_c_string(calld->host), calld->deadline, + calld->legacy->initial_metadata->count, + calld->legacy->initial_metadata->metadata); + } else { + abort(); + } +} + +static void begin_legacy_request(grpc_server *server, grpc_completion_queue *cq, + grpc_metadata_array *initial_metadata, + call_data *calld, void *tag) { + grpc_ioreq req; + if (!calld) { + gpr_free(initial_metadata); + grpc_cq_end_new_rpc(cq, tag, NULL, do_nothing, NULL, NULL, NULL, + gpr_inf_past, 0, NULL); + return; + } + req.op = GRPC_IOREQ_RECV_INITIAL_METADATA; + req.data.recv_metadata = initial_metadata; + calld->legacy = gpr_malloc(sizeof(legacy_data)); + memset(calld->legacy, 0, sizeof(legacy_data)); + calld->legacy->initial_metadata = initial_metadata; + grpc_call_internal_ref(calld->call); + grpc_call_start_ioreq_and_call_back(calld->call, &req, 1, + publish_legacy_request, tag); +} + +grpc_call_error grpc_server_request_call_old(grpc_server *server, + void *tag_new) { + grpc_metadata_array *client_metadata = + gpr_malloc(sizeof(grpc_metadata_array)); + memset(client_metadata, 0, sizeof(*client_metadata)); + grpc_cq_begin_op(server->cq, NULL, GRPC_SERVER_RPC_NEW); + return queue_call_request(server, server->cq, client_metadata, + begin_legacy_request, tag_new); } const grpc_channel_args *grpc_server_get_channel_args(grpc_server *server) { diff --git a/src/core/transport/chttp2/stream_encoder.c b/src/core/transport/chttp2/stream_encoder.c index c4e3ca516d1..2af18c30358 100644 --- a/src/core/transport/chttp2/stream_encoder.c +++ b/src/core/transport/chttp2/stream_encoder.c @@ -432,7 +432,7 @@ static void hpack_enc(grpc_chttp2_hpack_compressor *c, grpc_mdelem *elem, static void deadline_enc(grpc_chttp2_hpack_compressor *c, gpr_timespec deadline, framer_state *st) { - char timeout_str[32]; + char timeout_str[GRPC_CHTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; grpc_chttp2_encode_timeout(gpr_time_sub(deadline, gpr_now()), timeout_str); hpack_enc(c, grpc_mdelem_from_metadata_strings( c->mdctx, grpc_mdstr_ref(c->timeout_key_str), diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc index 5822e3015fc..3f39364bda2 100644 --- a/src/cpp/client/channel.cc +++ b/src/cpp/client/channel.cc @@ -102,6 +102,7 @@ Status Channel::StartBlockingRpc(const RpcMethod &method, grpc_call *call = grpc_channel_create_call_old( c_channel_, method.name(), target_.c_str(), context->RawDeadline()); context->set_call(call); + grpc_event *ev; void *finished_tag = reinterpret_cast(call); void *metadata_read_tag = reinterpret_cast(call) + 2; diff --git a/templates/Makefile.template b/templates/Makefile.template index 142d188d0c6..c34949cf2a7 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -206,11 +206,13 @@ OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/ope ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS) PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/perftools.c -lprofiler $(LDFLAGS) +ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_PERFTOOLS = $(shell $(PERFTOOLS_CHECK_CMD) 2> /dev/null && echo true || echo false) ifeq ($(HAS_SYSTEM_PERFTOOLS),true) DEFINES += GRPC_HAVE_PERFTOOLS LIBS += profiler endif +endif ifndef REQUIRE_CUSTOM_LIBRARIES_$(CONFIG) HAS_SYSTEM_OPENSSL_ALPN = $(shell $(OPENSSL_ALPN_CHECK_CMD) 2> /dev/null && echo true || echo false) diff --git a/test/core/end2end/cq_verifier.c b/test/core/end2end/cq_verifier.c index 287f83eebca..904ed772836 100644 --- a/test/core/end2end/cq_verifier.c +++ b/test/core/end2end/cq_verifier.c @@ -70,6 +70,7 @@ typedef struct expectation { union { grpc_op_error finish_accepted; grpc_op_error write_accepted; + grpc_op_error ioreq; struct { const char *method; const char *host; @@ -180,9 +181,6 @@ static void verify_matches(expectation *e, grpc_event *ev) { case GRPC_WRITE_ACCEPTED: GPR_ASSERT(e->data.write_accepted == ev->data.write_accepted); break; - case GRPC_INVOKE_ACCEPTED: - abort(); - break; case GRPC_SERVER_RPC_NEW: GPR_ASSERT(string_equivalent(e->data.server_rpc_new.method, ev->data.server_rpc_new.method)); @@ -222,6 +220,9 @@ static void verify_matches(expectation *e, grpc_event *ev) { GPR_ASSERT(ev->data.read == NULL); } break; + case GRPC_IOREQ: + GPR_ASSERT(e->data.ioreq == ev->data.ioreq); + break; case GRPC_SERVER_SHUTDOWN: break; case GRPC_COMPLETION_DO_NOT_USE: @@ -242,7 +243,9 @@ static void metadata_expectation(gpr_strvec *buf, metadata *md) { gpr_asprintf(&tmp, "%c%s:%s", i ? ',' : '{', md->keys[i], md->values[i]); gpr_strvec_add(buf, tmp); } - gpr_strvec_add(buf, gpr_strdup("}")); + if (md->count) { + gpr_strvec_add(buf, gpr_strdup("}")); + } } } @@ -261,8 +264,9 @@ static void expectation_to_strvec(gpr_strvec *buf, expectation *e) { e->data.write_accepted); gpr_strvec_add(buf, tmp); break; - case GRPC_INVOKE_ACCEPTED: - gpr_strvec_add(buf, gpr_strdup("GRPC_INVOKE_ACCEPTED")); + case GRPC_IOREQ: + gpr_asprintf(&tmp, "GRPC_IOREQ result=%d", e->data.ioreq); + gpr_strvec_add(buf, tmp); break; case GRPC_SERVER_RPC_NEW: timeout = gpr_time_sub(e->data.server_rpc_new.deadline, gpr_now()); diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c index eeb454ca581..9d893f67a13 100644 --- a/test/core/end2end/dualstack_socket_test.c +++ b/test/core/end2end/dualstack_socket_test.c @@ -142,7 +142,6 @@ void test_connect(const char *server_host, const char *client_host, int port, cq_verify(v_client); cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); - cq_verify(v_server); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); diff --git a/test/core/end2end/tests/census_simple_request.c b/test/core/end2end/tests/census_simple_request.c index 1edb5b0d3a1..4cbaa65b321 100644 --- a/test/core/end2end/tests/census_simple_request.c +++ b/test/core/end2end/tests/census_simple_request.c @@ -135,7 +135,6 @@ static void test_body(grpc_end2end_test_fixture f) { cq_verify(v_client); cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); - cq_verify(v_server); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); grpc_call_destroy(c); diff --git a/test/core/end2end/tests/max_concurrent_streams.c b/test/core/end2end/tests/max_concurrent_streams.c index 0e26577903f..4830b85f9b7 100644 --- a/test/core/end2end/tests/max_concurrent_streams.c +++ b/test/core/end2end/tests/max_concurrent_streams.c @@ -138,7 +138,6 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verify(v_client); cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); - cq_verify(v_server); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); @@ -207,7 +206,7 @@ static void test_max_concurrent_streams(grpc_end2end_test_config config) { /* The /alpha or /beta calls started above could be invoked (but NOT both); * check this here */ /* We'll get tag 303 or 403, we want 300, 400 */ - live_call = ((int)(gpr_intptr)ev->tag) - 3; + live_call = ((int)(gpr_intptr) ev->tag) - 3; grpc_event_finish(ev); cq_expect_server_rpc_new(v_server, &s1, tag(100), diff --git a/test/core/end2end/tests/simple_request.c b/test/core/end2end/tests/simple_request.c index 192d1ab87d0..db0d6d81605 100644 --- a/test/core/end2end/tests/simple_request.c +++ b/test/core/end2end/tests/simple_request.c @@ -139,7 +139,6 @@ static void simple_request_body(grpc_end2end_test_fixture f) { cq_verify(v_client); cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); - cq_verify(v_server); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); @@ -180,16 +179,14 @@ static void simple_request_body2(grpc_end2end_test_fixture f) { GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_write_status_old( s, GRPC_STATUS_UNIMPLEMENTED, "xyz", tag(5))); - cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); cq_verify(v_server); cq_expect_client_metadata_read(v_client, tag(2), NULL); - cq_verify(v_client); - cq_expect_finished_with_status(v_client, tag(3), GRPC_STATUS_UNIMPLEMENTED, "xyz", NULL); cq_verify(v_client); + cq_expect_finish_accepted(v_server, tag(5), GRPC_OP_OK); cq_expect_finished(v_server, tag(102), NULL); cq_verify(v_server); diff --git a/test/core/fling/client.c b/test/core/fling/client.c index cd2efc3cd0d..a91dfba9b0e 100644 --- a/test/core/fling/client.c +++ b/test/core/fling/client.c @@ -65,6 +65,7 @@ static void step_ping_pong_request(void) { grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); + grpc_event_finish(grpc_completion_queue_next(cq, gpr_inf_future)); grpc_call_destroy(call); call = NULL; } diff --git a/test/core/surface/completion_queue_test.c b/test/core/surface/completion_queue_test.c index dc459d62a8f..875cf3e52aa 100644 --- a/test/core/surface/completion_queue_test.c +++ b/test/core/surface/completion_queue_test.c @@ -105,32 +105,6 @@ static void test_cq_end_read(void) { shutdown_and_destroy(cc); } -static void test_cq_end_invoke_accepted(void) { - grpc_event *ev; - grpc_completion_queue *cc; - int on_finish_called = 0; - void *tag = create_test_tag(); - - LOG_TEST(); - - cc = grpc_completion_queue_create(); - - grpc_cq_begin_op(cc, NULL, GRPC_INVOKE_ACCEPTED); - grpc_cq_end_invoke_accepted(cc, tag, NULL, increment_int_on_finish, - &on_finish_called, GRPC_OP_OK); - - ev = grpc_completion_queue_next(cc, gpr_inf_past); - GPR_ASSERT(ev != NULL); - GPR_ASSERT(ev->type == GRPC_INVOKE_ACCEPTED); - GPR_ASSERT(ev->tag == tag); - GPR_ASSERT(ev->data.invoke_accepted == GRPC_OP_OK); - GPR_ASSERT(on_finish_called == 0); - grpc_event_finish(ev); - GPR_ASSERT(on_finish_called == 1); - - shutdown_and_destroy(cc); -} - static void test_cq_end_write_accepted(void) { grpc_event *ev; grpc_completion_queue *cc; @@ -421,7 +395,6 @@ int main(int argc, char **argv) { test_no_op(); test_wait_empty(); test_cq_end_read(); - test_cq_end_invoke_accepted(); test_cq_end_write_accepted(); test_cq_end_finish_accepted(); test_cq_end_client_metadata_read(); diff --git a/tools/dockerfile/grpc_node_base/Dockerfile b/tools/dockerfile/grpc_node_base/Dockerfile index 4ca0e53c0a9..28bd7b2556f 100644 --- a/tools/dockerfile/grpc_node_base/Dockerfile +++ b/tools/dockerfile/grpc_node_base/Dockerfile @@ -15,5 +15,8 @@ RUN cd /var/local/git/grpc && \ git pull --recurse-submodules && \ git submodule update --init --recursive +# Build the C core +RUN make static_c shared_c -j12 -C /var/local/git/grpc + # Define the default command. CMD ["bash"] \ No newline at end of file diff --git a/tools/dockerfile/grpc_php_base/Dockerfile b/tools/dockerfile/grpc_php_base/Dockerfile index 900d8abe307..47266a310e3 100644 --- a/tools/dockerfile/grpc_php_base/Dockerfile +++ b/tools/dockerfile/grpc_php_base/Dockerfile @@ -88,5 +88,8 @@ RUN wget https://phar.phpunit.de/phpunit.phar \ && chmod +x phpunit.phar \ && mv phpunit.phar /usr/local/bin/phpunit +# Build the C core +RUN make static_c shared_c -j12 -C /var/local/git/grpc + # Define the default command. CMD ["bash"] diff --git a/tools/dockerfile/grpc_ruby_base/Dockerfile b/tools/dockerfile/grpc_ruby_base/Dockerfile index 787f1290b0f..ec4544d2fdf 100644 --- a/tools/dockerfile/grpc_ruby_base/Dockerfile +++ b/tools/dockerfile/grpc_ruby_base/Dockerfile @@ -53,3 +53,6 @@ RUN cd /var/local/git/grpc/third_party/protobuf && \ ./autogen.sh && \ ./configure --prefix=/usr && \ make -j12 && make check && make install && make clean + +# Build the C core +RUN make static_c shared_c -j12 -C /var/local/git/grpc diff --git a/vsprojects/vs2013/grpc.vcxproj b/vsprojects/vs2013/grpc.vcxproj index 21a1f06f6d6..8c12b2daf03 100644 --- a/vsprojects/vs2013/grpc.vcxproj +++ b/vsprojects/vs2013/grpc.vcxproj @@ -146,6 +146,7 @@ + @@ -312,6 +313,8 @@ + + diff --git a/vsprojects/vs2013/grpc.vcxproj.filters b/vsprojects/vs2013/grpc.vcxproj.filters index 3af681a4666..62f0b60c85b 100644 --- a/vsprojects/vs2013/grpc.vcxproj.filters +++ b/vsprojects/vs2013/grpc.vcxproj.filters @@ -202,6 +202,9 @@ src\core\surface + + src\core\surface + src\core\surface @@ -521,6 +524,9 @@ src\core\statistics + + src\core\surface + src\core\surface diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj b/vsprojects/vs2013/grpc_unsecure.vcxproj index 21a1f06f6d6..8c12b2daf03 100644 --- a/vsprojects/vs2013/grpc_unsecure.vcxproj +++ b/vsprojects/vs2013/grpc_unsecure.vcxproj @@ -146,6 +146,7 @@ + @@ -312,6 +313,8 @@ + + diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj.filters b/vsprojects/vs2013/grpc_unsecure.vcxproj.filters index 4dadb611921..5ed5e9b9b6b 100644 --- a/vsprojects/vs2013/grpc_unsecure.vcxproj.filters +++ b/vsprojects/vs2013/grpc_unsecure.vcxproj.filters @@ -163,6 +163,9 @@ src\core\surface + + src\core\surface + src\core\surface @@ -446,6 +449,9 @@ src\core\statistics + + src\core\surface + src\core\surface From cefb00e8ebc204f9f661184dc1602b596c7575e7 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Feb 2015 11:42:37 -0800 Subject: [PATCH 87/93] Fix potential deadlock --- src/core/transport/chttp2_transport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c index 48a10058331..f5604176173 100644 --- a/src/core/transport/chttp2_transport.c +++ b/src/core/transport/chttp2_transport.c @@ -957,7 +957,7 @@ static void send_batch(grpc_transport *gt, grpc_stream *gs, grpc_stream_op *ops, stream_list_join(t, s, WRITABLE); } } else { - grpc_stream_ops_unref_owned_objects(ops, ops_count); + grpc_sopb_append(&t->nuke_later_sopb, ops, ops_count); } if (is_last && s->outgoing_sopb.nops == 0 && s->read_closed) { stream_list_join(t, s, PENDING_CALLBACKS); From bd5920751ed66b886083250c8ef472470c6e2aec Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Feb 2015 11:55:13 -0800 Subject: [PATCH 88/93] Fix alloc of zero request --- src/core/surface/byte_buffer_queue.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/core/surface/byte_buffer_queue.c b/src/core/surface/byte_buffer_queue.c index 36c082f4847..dc280a60c50 100644 --- a/src/core/surface/byte_buffer_queue.c +++ b/src/core/surface/byte_buffer_queue.c @@ -33,16 +33,15 @@ #include "src/core/surface/byte_buffer_queue.h" #include +#include -static void bba_destroy(grpc_bbq_array *array) { - gpr_free(array->data); -} +static void bba_destroy(grpc_bbq_array *array) { gpr_free(array->data); } /* Append an operation to an array, expanding as needed */ static void bba_push(grpc_bbq_array *a, grpc_byte_buffer *buffer) { if (a->count == a->capacity) { - a->capacity *= 2; - a->data = gpr_realloc(a->data, sizeof(grpc_byte_buffer*) * a->capacity); + a->capacity = GPR_MAX(a->capacity * 2, 8); + a->data = gpr_realloc(a->data, sizeof(grpc_byte_buffer *) * a->capacity); } a->data[a->count++] = buffer; } From c12fee6a04c44f99480c6f56f7c0ca263629ca46 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Feb 2015 11:55:50 -0800 Subject: [PATCH 89/93] Simplify call.c Reduce duplication of handling in many places and simplify internally tracked state. --- src/core/surface/call.c | 420 +++++++++++++++++++--------------------- 1 file changed, 194 insertions(+), 226 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index da966c874ac..382909c8652 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -46,8 +46,6 @@ #include #include -#define OP_IN_MASK(op, mask) (((1 << (op)) & (mask)) != 0) - typedef struct legacy_state legacy_state; static void destroy_legacy_state(legacy_state *ls); @@ -67,31 +65,10 @@ typedef struct { grpc_op_error status; } completed_request; -/* See reqinfo.set below for a description */ +/* See request_set in grpc_call below for a description */ #define REQSET_EMPTY 255 #define REQSET_DONE 254 -/* The state of an ioreq - we keep one of these on the call for each - grpc_ioreq_op type. - - These structures are manipulated in sets, where a set is a set of - operations begin with the same call to start_ioreq and the various - public and private api's that call it. Each set has a master reqinfo - in which we set a few additional fields - see reqinfo_master. */ -typedef struct { - /* User supplied parameters */ - grpc_ioreq_data data; - /* In which set is this ioreq? - This value could be: - - an element of grpc_ioreq_op enumeration, in which case - it designates the master ioreq in a set of requests - - REQSET_EMPTY, in which case this reqinfo type has no application - request against it - - REQSET_DONE, in which case this reqinfo has been satisfied for - all time for this call, and no further use will be made of it */ - gpr_uint8 set; -} reqinfo; - typedef struct { /* Overall status of the operation: starts OK, may degrade to non-OK */ @@ -128,7 +105,7 @@ typedef struct { /* How far through the GRPC stream have we read? */ typedef enum { /* We are still waiting for initial metadata to complete */ - READ_STATE_INITIAL, + READ_STATE_INITIAL = 0, /* We have gotten initial metadata, and are reading either messages or trailing metadata */ READ_STATE_GOT_INITIAL_METADATA, @@ -138,6 +115,12 @@ typedef enum { READ_STATE_STREAM_CLOSED } read_state; +typedef enum { + WRITE_STATE_INITIAL = 0, + WRITE_STATE_STARTED, + WRITE_STATE_WRITE_CLOSED +} write_state; + struct grpc_call { grpc_completion_queue *cq; grpc_channel *channel; @@ -147,17 +130,18 @@ struct grpc_call { gpr_uint8 is_client; read_state read_state; + write_state write_state; gpr_uint8 have_alarm; gpr_uint8 sending; gpr_uint8 num_completed_requests; gpr_uint8 need_more_data; - reqinfo requests[GRPC_IOREQ_OP_COUNT]; + gpr_uint8 request_set[GRPC_IOREQ_OP_COUNT]; + grpc_ioreq_data request_data[GRPC_IOREQ_OP_COUNT]; reqinfo_master masters[GRPC_IOREQ_OP_COUNT]; completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; grpc_byte_buffer_queue incoming_queue; - grpc_metadata_array buffered_initial_metadata; - grpc_metadata_array buffered_trailing_metadata; + grpc_metadata_array buffered_metadata[2]; grpc_mdelem **owned_metadata; size_t owned_metadata_count; size_t owned_metadata_capacity; @@ -171,7 +155,7 @@ struct grpc_call { legacy_state *legacy_state; }; -#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call)+1)) +#define CALL_STACK_FROM_CALL(call) ((grpc_call_stack *)((call) + 1)) #define CALL_FROM_CALL_STACK(call_stack) (((grpc_call *)(call_stack)) - 1) #define CALL_ELEM_FROM_CALL(call, idx) \ grpc_call_stack_element(CALL_STACK_FROM_CALL(call), idx) @@ -200,11 +184,11 @@ grpc_call *grpc_call_create(grpc_channel *channel, call->channel = channel; call->is_client = server_transport_data == NULL; for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { - call->requests[i].set = REQSET_EMPTY; + call->request_set[i] = REQSET_EMPTY; } if (call->is_client) { - call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].set = REQSET_DONE; - call->requests[GRPC_IOREQ_SEND_STATUS].set = REQSET_DONE; + call->request_set[GRPC_IOREQ_SEND_TRAILING_METADATA] = REQSET_DONE; + call->request_set[GRPC_IOREQ_SEND_STATUS] = REQSET_DONE; } grpc_channel_internal_ref(channel); call->metadata_context = grpc_channel_get_metadata_context(channel); @@ -233,8 +217,9 @@ static void destroy_call(void *call, int ignored_success) { grpc_mdelem_unref(c->owned_metadata[i]); } gpr_free(c->owned_metadata); - gpr_free(c->buffered_initial_metadata.metadata); - gpr_free(c->buffered_trailing_metadata.metadata); + for (i = 0; i < GPR_ARRAY_SIZE(c->buffered_metadata); i++) { + gpr_free(c->buffered_metadata[i].metadata); + } if (c->legacy_state) { destroy_legacy_state(c->legacy_state); } @@ -284,6 +269,14 @@ static void request_more_data(grpc_call *call) { grpc_call_execute_op(call, &op); } +static int is_op_live(grpc_call *call, grpc_ioreq_op op) { + gpr_uint8 set = call->request_set[op]; + reqinfo_master *master; + if (set >= GRPC_IOREQ_OP_COUNT) return 0; + master = &call->masters[set]; + return (master->complete_mask & (1 << op)) == 0; +} + static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); } static void unlock(grpc_call *call) { @@ -291,8 +284,7 @@ static void unlock(grpc_call *call) { completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; int num_completed_requests = call->num_completed_requests; int need_more_data = - call->need_more_data && - call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].set == REQSET_DONE; + call->need_more_data && !is_op_live(call, GRPC_IOREQ_SEND_INITIAL_METADATA); int i; if (need_more_data) { @@ -362,36 +354,70 @@ no_details: **args.details = 0; } -static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, - grpc_op_error status) { +static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op, + grpc_op_error status) { completed_request *cr; + gpr_uint8 master_set = call->request_set[op]; + reqinfo_master *master; size_t i; - if (call->requests[op].set < GRPC_IOREQ_OP_COUNT) { - reqinfo_master *master = &call->masters[call->requests[op].set]; - /* ioreq is live: we need to do something */ - master->complete_mask |= 1 << op; - if (status != GRPC_OP_OK) { - master->status = status; - } - call->requests[op].set = - (op == GRPC_IOREQ_SEND_MESSAGE || op == GRPC_IOREQ_RECV_MESSAGE) - ? REQSET_EMPTY - : REQSET_DONE; - if (master->complete_mask == master->need_mask || status == GRPC_OP_ERROR) { - if (OP_IN_MASK(GRPC_IOREQ_RECV_STATUS, master->need_mask)) { - get_final_status( - call, call->requests[GRPC_IOREQ_RECV_STATUS].data.recv_status); + /* ioreq is live: we need to do something */ + master = &call->masters[master_set]; + master->complete_mask |= 1 << op; + if (status != GRPC_OP_OK) { + master->status = status; + master->complete_mask = master->need_mask; + } + if (master->complete_mask == master->need_mask) { + for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { + if (call->request_set[i] != master_set) { + continue; } - for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { - if (call->requests[i].set == op) { - call->requests[i].set = REQSET_EMPTY; - } + call->request_set[i] = REQSET_DONE; + switch ((grpc_ioreq_op)i) { + case GRPC_IOREQ_RECV_MESSAGE: + case GRPC_IOREQ_SEND_MESSAGE: + if (master->status == GRPC_OP_OK) { + call->request_set[i] = REQSET_EMPTY; + } else { + call->write_state = WRITE_STATE_WRITE_CLOSED; + } + break; + case GRPC_IOREQ_RECV_CLOSE: + case GRPC_IOREQ_SEND_INITIAL_METADATA: + case GRPC_IOREQ_SEND_TRAILING_METADATA: + case GRPC_IOREQ_SEND_STATUS: + case GRPC_IOREQ_SEND_CLOSE: + break; + case GRPC_IOREQ_RECV_STATUS: + get_final_status( + call, call->request_data[GRPC_IOREQ_RECV_STATUS].recv_status); + break; + case GRPC_IOREQ_RECV_INITIAL_METADATA: + SWAP(grpc_metadata_array, call->buffered_metadata[0], + *call->request_data[GRPC_IOREQ_RECV_INITIAL_METADATA] + .recv_metadata); + break; + case GRPC_IOREQ_RECV_TRAILING_METADATA: + SWAP(grpc_metadata_array, call->buffered_metadata[1], + *call->request_data[GRPC_IOREQ_RECV_TRAILING_METADATA] + .recv_metadata); + break; + case GRPC_IOREQ_OP_COUNT: + abort(); + break; } - cr = &call->completed_requests[call->num_completed_requests++]; - cr->status = master->status; - cr->on_complete = master->on_complete; - cr->user_data = master->user_data; } + cr = &call->completed_requests[call->num_completed_requests++]; + cr->status = master->status; + cr->on_complete = master->on_complete; + cr->user_data = master->user_data; + } +} + +static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, + grpc_op_error status) { + if (is_op_live(call, op)) { + finish_live_ioreq_op(call, op, status); } } @@ -417,39 +443,32 @@ static void finish_start_step(void *pc, grpc_op_error error) { } static send_action choose_send_action(grpc_call *call) { - switch (call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].set) { - case REQSET_EMPTY: - return SEND_NOTHING; - default: - return SEND_INITIAL_METADATA; - case REQSET_DONE: - break; - } - switch (call->requests[GRPC_IOREQ_SEND_MESSAGE].set) { - case REQSET_EMPTY: - return SEND_NOTHING; - default: - return SEND_MESSAGE; - case REQSET_DONE: - break; - } - switch (call->requests[GRPC_IOREQ_SEND_CLOSE].set) { - case REQSET_EMPTY: - case REQSET_DONE: + switch (call->write_state) { + case WRITE_STATE_INITIAL: + if (call->request_set[GRPC_IOREQ_SEND_INITIAL_METADATA] != + REQSET_EMPTY) { + call->write_state = WRITE_STATE_STARTED; + return SEND_INITIAL_METADATA; + } return SEND_NOTHING; - default: - if (call->is_client) { - return SEND_FINISH; - } else if (call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].set != - REQSET_EMPTY && - call->requests[GRPC_IOREQ_SEND_STATUS].set != REQSET_EMPTY) { + case WRITE_STATE_STARTED: + if (call->request_set[GRPC_IOREQ_SEND_MESSAGE] != REQSET_EMPTY) { + return SEND_MESSAGE; + } + if (call->request_set[GRPC_IOREQ_SEND_CLOSE] != REQSET_EMPTY) { + call->write_state = WRITE_STATE_WRITE_CLOSED; finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, GRPC_OP_OK); - return SEND_TRAILING_METADATA_AND_FINISH; - } else { - return SEND_NOTHING; + return call->is_client ? SEND_FINISH + : SEND_TRAILING_METADATA_AND_FINISH; } + return SEND_NOTHING; + case WRITE_STATE_WRITE_CLOSED: + return SEND_NOTHING; } + gpr_log(GPR_ERROR, "should never reach here"); + abort(); + return SEND_NOTHING; } static void send_metadata(grpc_call *call, grpc_mdelem *elem) { @@ -474,7 +493,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { abort(); break; case SEND_INITIAL_METADATA: - data = call->requests[GRPC_IOREQ_SEND_INITIAL_METADATA].data; + data = call->request_data[GRPC_IOREQ_SEND_INITIAL_METADATA]; for (i = 0; i < data.send_metadata.count; i++) { const grpc_metadata *md = &data.send_metadata.metadata[i]; send_metadata(call, @@ -491,7 +510,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { grpc_call_execute_op(call, &op); break; case SEND_MESSAGE: - data = call->requests[GRPC_IOREQ_SEND_MESSAGE].data; + data = call->request_data[GRPC_IOREQ_SEND_MESSAGE]; op.type = GRPC_SEND_MESSAGE; op.dir = GRPC_CALL_DOWN; op.flags = 0; @@ -502,7 +521,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { break; case SEND_TRAILING_METADATA_AND_FINISH: /* send trailing metadata */ - data = call->requests[GRPC_IOREQ_SEND_TRAILING_METADATA].data; + data = call->request_data[GRPC_IOREQ_SEND_TRAILING_METADATA]; for (i = 0; i < data.send_metadata.count; i++) { const grpc_metadata *md = &data.send_metadata.metadata[i]; send_metadata(call, @@ -512,7 +531,7 @@ static void enact_send_action(grpc_call *call, send_action sa) { } /* send status */ /* TODO(ctiller): cache common status values */ - data = call->requests[GRPC_IOREQ_SEND_STATUS].data; + data = call->request_data[GRPC_IOREQ_SEND_STATUS]; gpr_ltoa(data.send_status.code, status_str); send_metadata( call, @@ -547,12 +566,66 @@ static grpc_call_error start_ioreq_error(grpc_call *call, size_t i; for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { if (mutated_ops & (1 << i)) { - call->requests[i].set = REQSET_EMPTY; + call->request_set[i] = REQSET_EMPTY; } } return ret; } +static void finish_read_ops(grpc_call *call) { + int empty; + + if (is_op_live(call, GRPC_IOREQ_RECV_MESSAGE)) { + empty = + (NULL == (*call->request_data[GRPC_IOREQ_RECV_MESSAGE].recv_message = + grpc_bbq_pop(&call->incoming_queue))); + if (!empty) { + finish_live_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); + empty = grpc_bbq_empty(&call->incoming_queue); + } + } else { + empty = grpc_bbq_empty(&call->incoming_queue); + } + + switch (call->read_state) { + case READ_STATE_STREAM_CLOSED: + if (empty) { + finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); + } + /* fallthrough */ + case READ_STATE_READ_CLOSED: + if (empty) { + 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_TRAILING_METADATA, GRPC_OP_OK); + /* fallthrough */ + case READ_STATE_GOT_INITIAL_METADATA: + finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); + /* fallthrough */ + case READ_STATE_INITIAL: + /* do nothing */ + break; + } +} + +static void early_out_write_ops(grpc_call *call) { + switch (call->write_state) { + case WRITE_STATE_WRITE_CLOSED: + finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGE, GRPC_OP_ERROR); + finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, GRPC_OP_ERROR); + finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_ERROR); + finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_OK); + /* fallthrough */ + case WRITE_STATE_STARTED: + finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, GRPC_OP_ERROR); + /* fallthrough */ + case WRITE_STATE_INITIAL: + /* do nothing */ + break; + } +} + static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, size_t nreqs, grpc_ioreq_completion_func completion, @@ -560,7 +633,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, size_t i; gpr_uint32 have_ops = 0; grpc_ioreq_op op; - reqinfo *requests = call->requests; reqinfo_master *master; grpc_ioreq_data data; gpr_uint8 set; @@ -573,17 +645,17 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, for (i = 0; i < nreqs; i++) { op = reqs[i].op; - if (requests[op].set < GRPC_IOREQ_OP_COUNT) { + if (call->request_set[op] < GRPC_IOREQ_OP_COUNT) { return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_TOO_MANY_OPERATIONS); - } else if (requests[op].set == REQSET_DONE) { + } else if (call->request_set[op] == REQSET_DONE) { return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_ALREADY_INVOKED); } have_ops |= 1 << op; data = reqs[i].data; - requests[op].data = data; - requests[op].set = set; + call->request_data[op] = data; + call->request_set[op] = set; } master = &call->masters[set]; @@ -593,83 +665,13 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, master->on_complete = completion; master->user_data = user_data; - for (i = 0; i < nreqs; i++) { - op = reqs[i].op; - data = reqs[i].data; - switch (op) { - case GRPC_IOREQ_OP_COUNT: - gpr_log(GPR_ERROR, "should never reach here"); - abort(); - break; - case GRPC_IOREQ_RECV_MESSAGE: - *data.recv_message = grpc_bbq_pop(&call->incoming_queue); - if (*data.recv_message) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - if (call->read_state == READ_STATE_STREAM_CLOSED && grpc_bbq_empty(&call->incoming_queue)) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); - } - } else { - /* no message: either end of stream or we need more bytes */ - if (call->read_state >= READ_STATE_READ_CLOSED) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - if (call->read_state == READ_STATE_STREAM_CLOSED) { - /* stream closed AND we've drained all messages: signal to the application */ - finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); - } - } else { - call->need_more_data = 1; - } - } - break; - case GRPC_IOREQ_RECV_STATUS: - if (call->read_state >= READ_STATE_READ_CLOSED) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); - } - break; - case GRPC_IOREQ_RECV_CLOSE: - if (call->read_state == READ_STATE_STREAM_CLOSED) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); - } - break; - case GRPC_IOREQ_SEND_CLOSE: - if (requests[GRPC_IOREQ_SEND_MESSAGE].set == REQSET_EMPTY) { - requests[GRPC_IOREQ_SEND_MESSAGE].set = REQSET_DONE; - } - if (call->read_state == READ_STATE_STREAM_CLOSED) { - finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, GRPC_OP_ERROR); - } - break; - case GRPC_IOREQ_SEND_MESSAGE: - case GRPC_IOREQ_SEND_INITIAL_METADATA: - case GRPC_IOREQ_SEND_TRAILING_METADATA: - case GRPC_IOREQ_SEND_STATUS: - if (call->read_state == READ_STATE_STREAM_CLOSED) { - finish_ioreq_op(call, op, GRPC_OP_ERROR); - } - break; - case GRPC_IOREQ_RECV_INITIAL_METADATA: - data.recv_metadata->count = 0; - if (call->buffered_initial_metadata.count > 0) { - SWAP(grpc_metadata_array, *data.recv_metadata, - call->buffered_initial_metadata); - } - if (call->read_state >= READ_STATE_GOT_INITIAL_METADATA) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); - } - break; - case GRPC_IOREQ_RECV_TRAILING_METADATA: - data.recv_metadata->count = 0; - if (call->buffered_trailing_metadata.count > 0) { - SWAP(grpc_metadata_array, *data.recv_metadata, - call->buffered_trailing_metadata); - } - if (call->read_state >= READ_STATE_READ_CLOSED) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); - } - break; - } + if (have_ops & (1 << GRPC_IOREQ_RECV_MESSAGE)) { + call->need_more_data = 1; } + finish_read_ops(call); + early_out_write_ops(call); + return GRPC_CALL_OK; } @@ -774,34 +776,21 @@ void grpc_call_set_deadline(grpc_call_element *elem, gpr_timespec deadline) { grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now()); } -static void mark_read_closed(grpc_call *call) { - call->read_state = READ_STATE_READ_CLOSED; - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); - finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); - finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); +static void set_read_state(grpc_call *call, read_state state) { + lock(call); + GPR_ASSERT(call->read_state < state); + call->read_state = state; + finish_read_ops(call); + unlock(call); } void grpc_call_read_closed(grpc_call_element *elem) { - grpc_call *call = CALL_FROM_TOP_ELEM(elem); - lock(call); - GPR_ASSERT(call->read_state < READ_STATE_READ_CLOSED); - mark_read_closed(call); - unlock(call); + set_read_state(CALL_FROM_TOP_ELEM(elem), READ_STATE_READ_CLOSED); } void grpc_call_stream_closed(grpc_call_element *elem) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); - lock(call); - GPR_ASSERT(call->read_state < READ_STATE_STREAM_CLOSED); - if (call->read_state < READ_STATE_READ_CLOSED) { - mark_read_closed(call); - } - call->read_state = READ_STATE_STREAM_CLOSED; - if (grpc_bbq_empty(&call->incoming_queue)) { - finish_ioreq_op(call, GRPC_IOREQ_RECV_CLOSE, GRPC_OP_OK); - } - unlock(call); + set_read_state(call, READ_STATE_STREAM_CLOSED); grpc_call_internal_unref(call, 0); } @@ -815,7 +804,7 @@ static gpr_uint32 decode_status(grpc_mdelem *md) { gpr_uint32 status; void *user_data = grpc_mdelem_get_user_data(md, destroy_status); if (user_data) { - status = ((gpr_uint32)(gpr_intptr) user_data) - STATUS_OFFSET; + status = ((gpr_uint32)(gpr_intptr)user_data) - STATUS_OFFSET; } else { if (!gpr_parse_bytes_to_uint32(grpc_mdstr_as_c_string(md->value), GPR_SLICE_LENGTH(md->value->slice), @@ -832,13 +821,8 @@ void grpc_call_recv_message(grpc_call_element *elem, grpc_byte_buffer *byte_buffer) { grpc_call *call = CALL_FROM_TOP_ELEM(elem); lock(call); - if (call->requests[GRPC_IOREQ_RECV_MESSAGE].set < GRPC_IOREQ_OP_COUNT) { - /* there's an outstanding read */ - *call->requests[GRPC_IOREQ_RECV_MESSAGE].data.recv_message = byte_buffer; - finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); - } else { - grpc_bbq_push(&call->incoming_queue, byte_buffer); - } + grpc_bbq_push(&call->incoming_queue, byte_buffer); + finish_read_ops(call); unlock(call); } @@ -856,19 +840,8 @@ void grpc_call_recv_metadata(grpc_call_element *elem, grpc_mdelem *md) { set_status_details(call, STATUS_FROM_WIRE, grpc_mdstr_ref(md->value)); grpc_mdelem_unref(md); } else { - if (call->read_state < READ_STATE_GOT_INITIAL_METADATA) { - dest = call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA].set < - GRPC_IOREQ_OP_COUNT - ? call->requests[GRPC_IOREQ_RECV_INITIAL_METADATA] - .data.recv_metadata - : &call->buffered_initial_metadata; - } else { - dest = call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA].set < - GRPC_IOREQ_OP_COUNT - ? call->requests[GRPC_IOREQ_RECV_TRAILING_METADATA] - .data.recv_metadata - : &call->buffered_trailing_metadata; - } + dest = &call->buffered_metadata[call->read_state >= + READ_STATE_GOT_INITIAL_METADATA]; if (dest->count == dest->capacity) { dest->capacity = GPR_MAX(dest->capacity + 8, dest->capacity * 2); dest->metadata = @@ -894,6 +867,11 @@ grpc_call_stack *grpc_call_get_call_stack(grpc_call *call) { return CALL_STACK_FROM_CALL(call); } +void grpc_call_initial_metadata_complete(grpc_call_element *surface_element) { + grpc_call *call = grpc_call_from_top_element(surface_element); + set_read_state(call, READ_STATE_GOT_INITIAL_METADATA); +} + /* * LEGACY API IMPLEMENTATION * All this code will disappear as soon as wrappings are updated @@ -1097,16 +1075,6 @@ grpc_call_error grpc_call_server_end_initial_metadata_old(grpc_call *call, return err; } -void grpc_call_initial_metadata_complete(grpc_call_element *surface_element) { - grpc_call *call = grpc_call_from_top_element(surface_element); - lock(call); - if (call->read_state < READ_STATE_GOT_INITIAL_METADATA) { - call->read_state = READ_STATE_GOT_INITIAL_METADATA; - } - finish_ioreq_op(call, GRPC_IOREQ_RECV_INITIAL_METADATA, GRPC_OP_OK); - unlock(call); -} - static void finish_read_event(void *p, grpc_op_error error) { if (p) grpc_byte_buffer_destroy(p); } From e5d683ca7e77f04263822382043dd3e39dc00fc6 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Feb 2015 16:37:36 -0800 Subject: [PATCH 90/93] Add some documentation to call.c --- src/core/surface/call.c | 51 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 382909c8652..66db4f4f246 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -128,30 +128,79 @@ struct grpc_call { /* TODO(ctiller): share with cq if possible? */ gpr_mu mu; - gpr_uint8 is_client; + /* how far through the stream have we read? */ read_state read_state; + /* how far through the stream have we written? */ write_state write_state; + /* client or server call */ + gpr_uint8 is_client; + /* is the alarm set */ gpr_uint8 have_alarm; + /* are we currently performing a send operation */ gpr_uint8 sending; + /* pairs with completed_requests */ gpr_uint8 num_completed_requests; + /* flag that we need to request more data */ gpr_uint8 need_more_data; + /* Active ioreqs. + request_set and request_data contain one element per active ioreq + operation. + + request_set[op] is an integer specifying a set of operations to which + the request belongs: + - if it is < GRPC_IOREQ_OP_COUNT, then this operation is pending + completion, and the integer represents to which group of operations + the ioreq belongs. Each group is represented by one master, and the + integer in request_set is an index into masters to find the master + data. + - if it is REQSET_EMPTY, the ioreq op is inactive and available to be + started + - finally, if request_set[op] is REQSET_DONE, then the operation is + complete and unavailable to be started again + + request_data[op] is the request data as supplied by the initiator of + a request, and is valid iff request_set[op] <= GRPC_IOREQ_OP_COUNT. + The set fields are as per the request type specified by op. + + Finally, one element of masters[op] is set per active _group_ of ioreq + operations. It describes work left outstanding, result status, and + what work to perform upon operation completion. As one ioreq of each + op type can be active at once, by convention we choose the first element + of a the group to be the master. This allows constant time allocation + and a strong upper bound of a count of masters to be calculated. */ gpr_uint8 request_set[GRPC_IOREQ_OP_COUNT]; grpc_ioreq_data request_data[GRPC_IOREQ_OP_COUNT]; reqinfo_master masters[GRPC_IOREQ_OP_COUNT]; + + /* Dynamic array of ioreq's that have completed: the count of + elements is queued in num_completed_requests. + This list is built up under lock(), and flushed entirely during + unlock(). + We know the upper bound of the number of elements as we can only + have one ioreq of each type active at once. */ completed_request completed_requests[GRPC_IOREQ_OP_COUNT]; + /* Incoming buffer of messages */ grpc_byte_buffer_queue incoming_queue; + /* Buffered read metadata waiting to be returned to the application. + Element 0 is initial metadata, element 1 is trailing metadata. */ grpc_metadata_array buffered_metadata[2]; + /* All metadata received - unreffed at once at the end of the call */ grpc_mdelem **owned_metadata; size_t owned_metadata_count; size_t owned_metadata_capacity; + /* Received call statuses from various sources */ received_status status[STATUS_SOURCE_COUNT]; + /* Deadline alarm - if have_alarm is non-zero */ grpc_alarm alarm; + /* Call refcount - to keep the call alive during asynchronous operations */ gpr_refcount internal_refcount; + /* Data that the legacy api needs to track. To be deleted at some point + soon */ legacy_state *legacy_state; }; From d642dcf9201ccc499690b7da4afa85cb249c32d3 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Feb 2015 20:39:09 -0800 Subject: [PATCH 91/93] Use unsigned for shifts --- src/core/surface/call.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 66db4f4f246..f3b76364467 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -76,7 +76,7 @@ typedef struct { /* Completion function to call at the end of the operation */ grpc_ioreq_completion_func on_complete; void *user_data; - /* a bit mask of which request ops are needed (1 << opid) */ + /* a bit mask of which request ops are needed (1u << opid) */ gpr_uint32 need_mask; /* a bit mask of which request ops are now completed */ gpr_uint32 complete_mask; @@ -323,7 +323,7 @@ static int is_op_live(grpc_call *call, grpc_ioreq_op op) { reqinfo_master *master; if (set >= GRPC_IOREQ_OP_COUNT) return 0; master = &call->masters[set]; - return (master->complete_mask & (1 << op)) == 0; + return (master->complete_mask & (1u << op)) == 0; } static void lock(grpc_call *call) { gpr_mu_lock(&call->mu); } @@ -411,7 +411,7 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op, size_t i; /* ioreq is live: we need to do something */ master = &call->masters[master_set]; - master->complete_mask |= 1 << op; + master->complete_mask |= 1u << op; if (status != GRPC_OP_OK) { master->status = status; master->complete_mask = master->need_mask; @@ -614,7 +614,7 @@ static grpc_call_error start_ioreq_error(grpc_call *call, grpc_call_error ret) { size_t i; for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { - if (mutated_ops & (1 << i)) { + if (mutated_ops & (1u << i)) { call->request_set[i] = REQSET_EMPTY; } } @@ -700,7 +700,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, } else if (call->request_set[op] == REQSET_DONE) { return start_ioreq_error(call, have_ops, GRPC_CALL_ERROR_ALREADY_INVOKED); } - have_ops |= 1 << op; + have_ops |= 1u << op; data = reqs[i].data; call->request_data[op] = data; @@ -714,7 +714,7 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, master->on_complete = completion; master->user_data = user_data; - if (have_ops & (1 << GRPC_IOREQ_RECV_MESSAGE)) { + if (have_ops & (1u << GRPC_IOREQ_RECV_MESSAGE)) { call->need_more_data = 1; } From d6731628bcedbe150d4f7cd09656bd506979b00f Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Tue, 3 Feb 2015 22:44:13 -0800 Subject: [PATCH 92/93] Cleanup documentation --- src/core/surface/call.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index f3b76364467..8221401a70b 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -163,11 +163,12 @@ struct grpc_call { a request, and is valid iff request_set[op] <= GRPC_IOREQ_OP_COUNT. The set fields are as per the request type specified by op. - Finally, one element of masters[op] is set per active _group_ of ioreq + Finally, one element of masters is set per active _set_ of ioreq operations. It describes work left outstanding, result status, and what work to perform upon operation completion. As one ioreq of each op type can be active at once, by convention we choose the first element - of a the group to be the master. This allows constant time allocation + of the group to be the master -- ie the master of in-progress operation + op is masters[request_set[op]]. This allows constant time allocation and a strong upper bound of a count of masters to be calculated. */ gpr_uint8 request_set[GRPC_IOREQ_OP_COUNT]; grpc_ioreq_data request_data[GRPC_IOREQ_OP_COUNT]; From e2b2b1fb676eef687f0ea088aa74a13b52cbf755 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 4 Feb 2015 12:50:06 -0800 Subject: [PATCH 93/93] Fix check for whether we should write to prevent infinite loop --- src/core/surface/call.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/core/surface/call.c b/src/core/surface/call.c index 382909c8652..561c24e547e 100644 --- a/src/core/surface/call.c +++ b/src/core/surface/call.c @@ -445,17 +445,16 @@ static void finish_start_step(void *pc, grpc_op_error error) { static send_action choose_send_action(grpc_call *call) { switch (call->write_state) { case WRITE_STATE_INITIAL: - if (call->request_set[GRPC_IOREQ_SEND_INITIAL_METADATA] != - REQSET_EMPTY) { + if (is_op_live(call, GRPC_IOREQ_SEND_INITIAL_METADATA)) { call->write_state = WRITE_STATE_STARTED; return SEND_INITIAL_METADATA; } return SEND_NOTHING; case WRITE_STATE_STARTED: - if (call->request_set[GRPC_IOREQ_SEND_MESSAGE] != REQSET_EMPTY) { + if (is_op_live(call, GRPC_IOREQ_SEND_MESSAGE)) { return SEND_MESSAGE; } - if (call->request_set[GRPC_IOREQ_SEND_CLOSE] != REQSET_EMPTY) { + if (is_op_live(call, GRPC_IOREQ_SEND_CLOSE)) { call->write_state = WRITE_STATE_WRITE_CLOSED; finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, GRPC_OP_OK); finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, GRPC_OP_OK);