|
|
|
@ -77,6 +77,7 @@ typedef struct { |
|
|
|
|
|
|
|
|
|
typedef enum { |
|
|
|
|
CALL_CREATED, |
|
|
|
|
CALL_WAITING_FOR_SEND, |
|
|
|
|
CALL_WAITING_FOR_CONFIG, |
|
|
|
|
CALL_WAITING_FOR_PICK, |
|
|
|
|
CALL_WAITING_FOR_CALL, |
|
|
|
@ -101,6 +102,9 @@ struct call_data { |
|
|
|
|
grpc_linked_mdelem details; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static grpc_iomgr_closure *merge_into_waiting_op(grpc_call_element *elem, |
|
|
|
|
grpc_transport_stream_op *new_op) GRPC_MUST_USE_RESULT; |
|
|
|
|
|
|
|
|
|
static void handle_op_after_cancellation(grpc_call_element *elem, |
|
|
|
|
grpc_transport_stream_op *op) { |
|
|
|
|
call_data *calld = elem->call_data; |
|
|
|
@ -241,12 +245,13 @@ static void pick_target(grpc_lb_policy *lb_policy, call_data *calld) { |
|
|
|
|
&calld->picked_channel, &calld->async_setup_task); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void merge_into_waiting_op(grpc_call_element *elem, |
|
|
|
|
static grpc_iomgr_closure *merge_into_waiting_op(grpc_call_element *elem, |
|
|
|
|
grpc_transport_stream_op *new_op) { |
|
|
|
|
call_data *calld = elem->call_data; |
|
|
|
|
grpc_iomgr_closure *consumed_op = NULL; |
|
|
|
|
grpc_transport_stream_op *waiting_op = &calld->waiting_op; |
|
|
|
|
GPR_ASSERT((waiting_op->send_ops == NULL) != (new_op->send_ops == NULL)); |
|
|
|
|
GPR_ASSERT((waiting_op->recv_ops == NULL) != (new_op->recv_ops == NULL)); |
|
|
|
|
GPR_ASSERT((waiting_op->send_ops == NULL) != (new_op->send_ops == NULL) || waiting_op->send_ops == NULL); |
|
|
|
|
GPR_ASSERT((waiting_op->recv_ops == NULL) != (new_op->recv_ops == NULL) || waiting_op->recv_ops == NULL); |
|
|
|
|
if (new_op->send_ops != NULL) { |
|
|
|
|
waiting_op->send_ops = new_op->send_ops; |
|
|
|
|
waiting_op->is_last_send = new_op->is_last_send; |
|
|
|
@ -257,13 +262,16 @@ static void merge_into_waiting_op(grpc_call_element *elem, |
|
|
|
|
waiting_op->recv_state = new_op->recv_state; |
|
|
|
|
waiting_op->on_done_recv = new_op->on_done_recv; |
|
|
|
|
} |
|
|
|
|
if (waiting_op->on_consumed == NULL) { |
|
|
|
|
if (new_op->on_consumed != NULL) { |
|
|
|
|
if (waiting_op->on_consumed != NULL) { |
|
|
|
|
consumed_op = waiting_op->on_consumed; |
|
|
|
|
} |
|
|
|
|
waiting_op->on_consumed = new_op->on_consumed; |
|
|
|
|
new_op->on_consumed = NULL; |
|
|
|
|
} |
|
|
|
|
if (new_op->cancel_with_status != GRPC_STATUS_OK) { |
|
|
|
|
waiting_op->cancel_with_status = new_op->cancel_with_status; |
|
|
|
|
} |
|
|
|
|
return consumed_op; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void perform_transport_stream_op(grpc_call_element *elem, |
|
|
|
@ -274,6 +282,7 @@ static void perform_transport_stream_op(grpc_call_element *elem, |
|
|
|
|
grpc_subchannel_call *subchannel_call; |
|
|
|
|
grpc_lb_policy *lb_policy; |
|
|
|
|
grpc_transport_stream_op op2; |
|
|
|
|
grpc_iomgr_closure *consumed_op = NULL; |
|
|
|
|
GPR_ASSERT(elem->filter == &grpc_client_channel_filter); |
|
|
|
|
GRPC_CALL_LOG_OP(GPR_INFO, elem, op); |
|
|
|
|
|
|
|
|
@ -289,6 +298,17 @@ static void perform_transport_stream_op(grpc_call_element *elem, |
|
|
|
|
gpr_mu_unlock(&calld->mu_state); |
|
|
|
|
handle_op_after_cancellation(elem, op); |
|
|
|
|
break; |
|
|
|
|
case CALL_WAITING_FOR_SEND: |
|
|
|
|
GPR_ASSERT(!continuation); |
|
|
|
|
consumed_op = merge_into_waiting_op(elem, op); |
|
|
|
|
if (!calld->waiting_op.send_ops && calld->waiting_op.cancel_with_status == GRPC_STATUS_OK) { |
|
|
|
|
gpr_mu_unlock(&calld->mu_state); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
*op = calld->waiting_op; |
|
|
|
|
memset(&calld->waiting_op, 0, sizeof(calld->waiting_op)); |
|
|
|
|
continuation = 1; |
|
|
|
|
/* fall through */ |
|
|
|
|
case CALL_WAITING_FOR_CONFIG: |
|
|
|
|
case CALL_WAITING_FOR_PICK: |
|
|
|
|
case CALL_WAITING_FOR_CALL: |
|
|
|
@ -308,7 +328,7 @@ static void perform_transport_stream_op(grpc_call_element *elem, |
|
|
|
|
handle_op_after_cancellation(elem, op); |
|
|
|
|
handle_op_after_cancellation(elem, &op2); |
|
|
|
|
} else { |
|
|
|
|
merge_into_waiting_op(elem, op); |
|
|
|
|
consumed_op = merge_into_waiting_op(elem, op); |
|
|
|
|
gpr_mu_unlock(&calld->mu_state); |
|
|
|
|
if (op->on_consumed != NULL) { |
|
|
|
|
op->on_consumed->cb(op->on_consumed->cb_arg, 0); |
|
|
|
@ -325,26 +345,37 @@ static void perform_transport_stream_op(grpc_call_element *elem, |
|
|
|
|
} else { |
|
|
|
|
calld->waiting_op = *op; |
|
|
|
|
|
|
|
|
|
gpr_mu_lock(&chand->mu_config); |
|
|
|
|
lb_policy = chand->lb_policy; |
|
|
|
|
if (lb_policy) { |
|
|
|
|
GRPC_LB_POLICY_REF(lb_policy, "pick"); |
|
|
|
|
gpr_mu_unlock(&chand->mu_config); |
|
|
|
|
calld->state = CALL_WAITING_FOR_PICK; |
|
|
|
|
if (op->send_ops == NULL) { |
|
|
|
|
/* need to have some send ops before we can select the
|
|
|
|
|
lb target */ |
|
|
|
|
calld->state = CALL_WAITING_FOR_SEND; |
|
|
|
|
gpr_mu_unlock(&calld->mu_state); |
|
|
|
|
|
|
|
|
|
pick_target(lb_policy, calld); |
|
|
|
|
|
|
|
|
|
GRPC_LB_POLICY_UNREF(lb_policy, "pick"); |
|
|
|
|
} else { |
|
|
|
|
calld->state = CALL_WAITING_FOR_CONFIG; |
|
|
|
|
add_to_lb_policy_wait_queue_locked_state_config(elem); |
|
|
|
|
gpr_mu_unlock(&chand->mu_config); |
|
|
|
|
gpr_mu_unlock(&calld->mu_state); |
|
|
|
|
gpr_mu_lock(&chand->mu_config); |
|
|
|
|
lb_policy = chand->lb_policy; |
|
|
|
|
if (lb_policy) { |
|
|
|
|
GRPC_LB_POLICY_REF(lb_policy, "pick"); |
|
|
|
|
gpr_mu_unlock(&chand->mu_config); |
|
|
|
|
calld->state = CALL_WAITING_FOR_PICK; |
|
|
|
|
gpr_mu_unlock(&calld->mu_state); |
|
|
|
|
|
|
|
|
|
pick_target(lb_policy, calld); |
|
|
|
|
|
|
|
|
|
GRPC_LB_POLICY_UNREF(lb_policy, "pick"); |
|
|
|
|
} else { |
|
|
|
|
calld->state = CALL_WAITING_FOR_CONFIG; |
|
|
|
|
add_to_lb_policy_wait_queue_locked_state_config(elem); |
|
|
|
|
gpr_mu_unlock(&chand->mu_config); |
|
|
|
|
gpr_mu_unlock(&calld->mu_state); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (consumed_op != NULL) { |
|
|
|
|
consumed_op->cb(consumed_op->cb_arg, 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void cc_start_transport_stream_op(grpc_call_element *elem, |
|
|
|
@ -503,6 +534,7 @@ static void destroy_call_elem(grpc_call_element *elem) { |
|
|
|
|
case CALL_WAITING_FOR_PICK: |
|
|
|
|
case CALL_WAITING_FOR_CONFIG: |
|
|
|
|
case CALL_WAITING_FOR_CALL: |
|
|
|
|
case CALL_WAITING_FOR_SEND: |
|
|
|
|
gpr_log(GPR_ERROR, "should never reach here"); |
|
|
|
|
abort(); |
|
|
|
|
break; |
|
|
|
|