|
|
@ -135,7 +135,7 @@ typedef struct batch_control { |
|
|
|
typedef struct { |
|
|
|
typedef struct { |
|
|
|
gpr_mu child_list_mu; |
|
|
|
gpr_mu child_list_mu; |
|
|
|
grpc_call *first_child; |
|
|
|
grpc_call *first_child; |
|
|
|
} parent_call; |
|
|
|
} parent_call_t; |
|
|
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
typedef struct { |
|
|
|
grpc_call *parent; |
|
|
|
grpc_call *parent; |
|
|
@ -144,7 +144,7 @@ typedef struct { |
|
|
|
parent->mu */ |
|
|
|
parent->mu */ |
|
|
|
grpc_call *sibling_next; |
|
|
|
grpc_call *sibling_next; |
|
|
|
grpc_call *sibling_prev; |
|
|
|
grpc_call *sibling_prev; |
|
|
|
} child_call; |
|
|
|
} child_call_t; |
|
|
|
|
|
|
|
|
|
|
|
#define RECV_NONE ((gpr_atm)0) |
|
|
|
#define RECV_NONE ((gpr_atm)0) |
|
|
|
#define RECV_INITIAL_METADATA_FIRST ((gpr_atm)1) |
|
|
|
#define RECV_INITIAL_METADATA_FIRST ((gpr_atm)1) |
|
|
@ -157,8 +157,8 @@ struct grpc_call { |
|
|
|
grpc_polling_entity pollent; |
|
|
|
grpc_polling_entity pollent; |
|
|
|
grpc_channel *channel; |
|
|
|
grpc_channel *channel; |
|
|
|
gpr_timespec start_time; |
|
|
|
gpr_timespec start_time; |
|
|
|
/* parent_call* */ gpr_atm parent_call_atm; |
|
|
|
/* parent_call_t* */ gpr_atm parent_call_atm; |
|
|
|
child_call *child_call; |
|
|
|
child_call_t *child_call; |
|
|
|
|
|
|
|
|
|
|
|
/* client or server call */ |
|
|
|
/* client or server call */ |
|
|
|
bool is_client; |
|
|
|
bool is_client; |
|
|
@ -293,32 +293,32 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx, batch_control *bctl); |
|
|
|
static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl, |
|
|
|
static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl, |
|
|
|
grpc_error *error, bool has_cancelled); |
|
|
|
grpc_error *error, bool has_cancelled); |
|
|
|
|
|
|
|
|
|
|
|
static void add_init_error(grpc_error **composite, grpc_error *new) { |
|
|
|
static void add_init_error(grpc_error **composite, grpc_error *new_err) { |
|
|
|
if (new == GRPC_ERROR_NONE) return; |
|
|
|
if (new_err == GRPC_ERROR_NONE) return; |
|
|
|
if (*composite == GRPC_ERROR_NONE) |
|
|
|
if (*composite == GRPC_ERROR_NONE) |
|
|
|
*composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Call creation failed"); |
|
|
|
*composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Call creation failed"); |
|
|
|
*composite = grpc_error_add_child(*composite, new); |
|
|
|
*composite = grpc_error_add_child(*composite, new_err); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void *grpc_call_arena_alloc(grpc_call *call, size_t size) { |
|
|
|
void *grpc_call_arena_alloc(grpc_call *call, size_t size) { |
|
|
|
return gpr_arena_alloc(call->arena, size); |
|
|
|
return gpr_arena_alloc(call->arena, size); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static parent_call *get_or_create_parent_call(grpc_call *call) { |
|
|
|
static parent_call_t *get_or_create_parent_call(grpc_call *call) { |
|
|
|
parent_call *p = (parent_call *)gpr_atm_acq_load(&call->parent_call_atm); |
|
|
|
parent_call_t *p = (parent_call_t *)gpr_atm_acq_load(&call->parent_call_atm); |
|
|
|
if (p == NULL) { |
|
|
|
if (p == NULL) { |
|
|
|
p = (parent_call *)gpr_arena_alloc(call->arena, sizeof(*p)); |
|
|
|
p = (parent_call_t *)gpr_arena_alloc(call->arena, sizeof(*p)); |
|
|
|
gpr_mu_init(&p->child_list_mu); |
|
|
|
gpr_mu_init(&p->child_list_mu); |
|
|
|
if (!gpr_atm_rel_cas(&call->parent_call_atm, (gpr_atm)NULL, (gpr_atm)p)) { |
|
|
|
if (!gpr_atm_rel_cas(&call->parent_call_atm, (gpr_atm)NULL, (gpr_atm)p)) { |
|
|
|
gpr_mu_destroy(&p->child_list_mu); |
|
|
|
gpr_mu_destroy(&p->child_list_mu); |
|
|
|
p = (parent_call *)gpr_atm_acq_load(&call->parent_call_atm); |
|
|
|
p = (parent_call_t *)gpr_atm_acq_load(&call->parent_call_atm); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return p; |
|
|
|
return p; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static parent_call *get_parent_call(grpc_call *call) { |
|
|
|
static parent_call_t *get_parent_call(grpc_call *call) { |
|
|
|
return (parent_call *)gpr_atm_acq_load(&call->parent_call_atm); |
|
|
|
return (parent_call_t *)gpr_atm_acq_load(&call->parent_call_atm); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, |
|
|
|
grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, |
|
|
@ -378,15 +378,15 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx, |
|
|
|
bool immediately_cancel = false; |
|
|
|
bool immediately_cancel = false; |
|
|
|
|
|
|
|
|
|
|
|
if (args->parent_call != NULL) { |
|
|
|
if (args->parent_call != NULL) { |
|
|
|
child_call *cc = call->child_call = |
|
|
|
child_call_t *cc = call->child_call = |
|
|
|
gpr_arena_alloc(arena, sizeof(child_call)); |
|
|
|
(child_call_t *)gpr_arena_alloc(arena, sizeof(child_call_t)); |
|
|
|
call->child_call->parent = args->parent_call; |
|
|
|
call->child_call->parent = args->parent_call; |
|
|
|
|
|
|
|
|
|
|
|
GRPC_CALL_INTERNAL_REF(args->parent_call, "child"); |
|
|
|
GRPC_CALL_INTERNAL_REF(args->parent_call, "child"); |
|
|
|
GPR_ASSERT(call->is_client); |
|
|
|
GPR_ASSERT(call->is_client); |
|
|
|
GPR_ASSERT(!args->parent_call->is_client); |
|
|
|
GPR_ASSERT(!args->parent_call->is_client); |
|
|
|
|
|
|
|
|
|
|
|
parent_call *pc = get_or_create_parent_call(args->parent_call); |
|
|
|
parent_call_t *pc = get_or_create_parent_call(args->parent_call); |
|
|
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&pc->child_list_mu); |
|
|
|
gpr_mu_lock(&pc->child_list_mu); |
|
|
|
|
|
|
|
|
|
|
@ -533,7 +533,7 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, |
|
|
|
if (c->receiving_stream != NULL) { |
|
|
|
if (c->receiving_stream != NULL) { |
|
|
|
grpc_byte_stream_destroy(exec_ctx, c->receiving_stream); |
|
|
|
grpc_byte_stream_destroy(exec_ctx, c->receiving_stream); |
|
|
|
} |
|
|
|
} |
|
|
|
parent_call *pc = get_parent_call(c); |
|
|
|
parent_call_t *pc = get_parent_call(c); |
|
|
|
if (pc != NULL) { |
|
|
|
if (pc != NULL) { |
|
|
|
gpr_mu_destroy(&pc->child_list_mu); |
|
|
|
gpr_mu_destroy(&pc->child_list_mu); |
|
|
|
} |
|
|
|
} |
|
|
@ -549,8 +549,8 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call, |
|
|
|
GRPC_CQ_INTERNAL_UNREF(exec_ctx, c->cq, "bind"); |
|
|
|
GRPC_CQ_INTERNAL_UNREF(exec_ctx, c->cq, "bind"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
get_final_status(call, set_status_value_directly, &c->final_info.final_status, |
|
|
|
get_final_status((grpc_call *)call, set_status_value_directly, |
|
|
|
NULL); |
|
|
|
&c->final_info.final_status, NULL); |
|
|
|
c->final_info.stats.latency = |
|
|
|
c->final_info.stats.latency = |
|
|
|
gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time); |
|
|
|
gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time); |
|
|
|
|
|
|
|
|
|
|
@ -570,14 +570,14 @@ void grpc_call_ref(grpc_call *c) { gpr_ref(&c->ext_ref); } |
|
|
|
void grpc_call_unref(grpc_call *c) { |
|
|
|
void grpc_call_unref(grpc_call *c) { |
|
|
|
if (!gpr_unref(&c->ext_ref)) return; |
|
|
|
if (!gpr_unref(&c->ext_ref)) return; |
|
|
|
|
|
|
|
|
|
|
|
child_call *cc = c->child_call; |
|
|
|
child_call_t *cc = c->child_call; |
|
|
|
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
|
|
|
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
|
|
|
|
|
|
|
|
|
|
|
GPR_TIMER_BEGIN("grpc_call_unref", 0); |
|
|
|
GPR_TIMER_BEGIN("grpc_call_unref", 0); |
|
|
|
GRPC_API_TRACE("grpc_call_unref(c=%p)", 1, (c)); |
|
|
|
GRPC_API_TRACE("grpc_call_unref(c=%p)", 1, (c)); |
|
|
|
|
|
|
|
|
|
|
|
if (cc) { |
|
|
|
if (cc) { |
|
|
|
parent_call *pc = get_parent_call(cc->parent); |
|
|
|
parent_call_t *pc = get_parent_call(cc->parent); |
|
|
|
gpr_mu_lock(&pc->child_list_mu); |
|
|
|
gpr_mu_lock(&pc->child_list_mu); |
|
|
|
if (c == pc->first_child) { |
|
|
|
if (c == pc->first_child) { |
|
|
|
pc->first_child = cc->sibling_next; |
|
|
|
pc->first_child = cc->sibling_next; |
|
|
@ -1309,7 +1309,7 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx, |
|
|
|
|
|
|
|
|
|
|
|
/* propagate cancellation to any interested children */ |
|
|
|
/* propagate cancellation to any interested children */ |
|
|
|
gpr_atm_rel_store(&call->received_final_op_atm, 1); |
|
|
|
gpr_atm_rel_store(&call->received_final_op_atm, 1); |
|
|
|
parent_call *pc = get_parent_call(call); |
|
|
|
parent_call_t *pc = get_parent_call(call); |
|
|
|
if (pc != NULL) { |
|
|
|
if (pc != NULL) { |
|
|
|
grpc_call *child; |
|
|
|
grpc_call *child; |
|
|
|
gpr_mu_lock(&pc->child_list_mu); |
|
|
|
gpr_mu_lock(&pc->child_list_mu); |
|
|
@ -1345,7 +1345,8 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx, |
|
|
|
if (bctl->completion_data.notify_tag.is_closure) { |
|
|
|
if (bctl->completion_data.notify_tag.is_closure) { |
|
|
|
/* unrefs bctl->error */ |
|
|
|
/* unrefs bctl->error */ |
|
|
|
bctl->call = NULL; |
|
|
|
bctl->call = NULL; |
|
|
|
GRPC_CLOSURE_RUN(exec_ctx, bctl->completion_data.notify_tag.tag, error); |
|
|
|
GRPC_CLOSURE_RUN( |
|
|
|
|
|
|
|
exec_ctx, (grpc_closure *)bctl->completion_data.notify_tag.tag, error); |
|
|
|
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion"); |
|
|
|
GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion"); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
/* unrefs bctl->error */ |
|
|
|
/* unrefs bctl->error */ |
|
|
@ -1474,7 +1475,7 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp, |
|
|
|
* acq_load is in receiving_initial_metadata_ready() */ |
|
|
|
* acq_load is in receiving_initial_metadata_ready() */ |
|
|
|
if (error != GRPC_ERROR_NONE || call->receiving_stream == NULL || |
|
|
|
if (error != GRPC_ERROR_NONE || call->receiving_stream == NULL || |
|
|
|
!gpr_atm_rel_cas(&call->recv_state, RECV_NONE, (gpr_atm)bctlp)) { |
|
|
|
!gpr_atm_rel_cas(&call->recv_state, RECV_NONE, (gpr_atm)bctlp)) { |
|
|
|
process_data_after_md(exec_ctx, bctlp); |
|
|
|
process_data_after_md(exec_ctx, (batch_control *)bctlp); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1679,11 +1680,12 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx, |
|
|
|
if (nops == 0) { |
|
|
|
if (nops == 0) { |
|
|
|
if (!is_notify_tag_closure) { |
|
|
|
if (!is_notify_tag_closure) { |
|
|
|
GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag)); |
|
|
|
GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag)); |
|
|
|
grpc_cq_end_op(exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE, |
|
|
|
grpc_cq_end_op( |
|
|
|
|
|
|
|
exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE, |
|
|
|
free_no_op_completion, NULL, |
|
|
|
free_no_op_completion, NULL, |
|
|
|
gpr_malloc(sizeof(grpc_cq_completion))); |
|
|
|
(grpc_cq_completion *)gpr_malloc(sizeof(grpc_cq_completion))); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
GRPC_CLOSURE_SCHED(exec_ctx, notify_tag, GRPC_ERROR_NONE); |
|
|
|
GRPC_CLOSURE_SCHED(exec_ctx, (grpc_closure *)notify_tag, GRPC_ERROR_NONE); |
|
|
|
} |
|
|
|
} |
|
|
|
error = GRPC_CALL_OK; |
|
|
|
error = GRPC_CALL_OK; |
|
|
|
goto done; |
|
|
|
goto done; |
|
|
|