Пример #1
0
static void publish_registered_or_batch(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;
  grpc_cq_end_op_complete(calld->cq_new, tag, call, do_nothing, NULL, status);
}
Пример #2
0
static void publish_registered_or_batch(grpc_call *call, int success,
                                        void *tag) {
  grpc_call_element *elem =
      grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
  call_data *calld = elem->call_data;
  grpc_cq_end_op(calld->cq_new, tag, call, success);
}
Пример #3
0
static grpc_call_error queue_call_request(grpc_exec_ctx *exec_ctx,
                                          grpc_server *server, size_t cq_idx,
                                          requested_call *rc) {
  call_data *calld = NULL;
  request_matcher *rm = NULL;
  int request_id;
  if (gpr_atm_acq_load(&server->shutdown_flag)) {
    fail_call(exec_ctx, server, cq_idx, rc,
              GRPC_ERROR_CREATE("Server Shutdown"));
    return GRPC_CALL_OK;
  }
  request_id = gpr_stack_lockfree_pop(server->request_freelist_per_cq[cq_idx]);
  if (request_id == -1) {
    /* out of request ids: just fail this one */
    fail_call(exec_ctx, server, cq_idx, rc,
              grpc_error_set_int(GRPC_ERROR_CREATE("Out of request ids"),
                                 GRPC_ERROR_INT_LIMIT,
                                 server->max_requested_calls_per_cq));
    return GRPC_CALL_OK;
  }
  switch (rc->type) {
    case BATCH_CALL:
      rm = &server->unregistered_request_matcher;
      break;
    case REGISTERED_CALL:
      rm = &rc->data.registered.registered_method->request_matcher;
      break;
  }
  server->requested_calls_per_cq[cq_idx][request_id] = *rc;
  gpr_free(rc);
  if (gpr_stack_lockfree_push(rm->requests_per_cq[cq_idx], request_id)) {
    /* this was the first queued request: we need to lock and start
       matching calls */
    gpr_mu_lock(&server->mu_call);
    while ((calld = rm->pending_head) != NULL) {
      request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[cq_idx]);
      if (request_id == -1) break;
      rm->pending_head = calld->pending_next;
      gpr_mu_unlock(&server->mu_call);
      gpr_mu_lock(&calld->mu_state);
      if (calld->state == ZOMBIED) {
        gpr_mu_unlock(&calld->mu_state);
        grpc_closure_init(
            &calld->kill_zombie_closure, kill_zombie,
            grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
        grpc_exec_ctx_sched(exec_ctx, &calld->kill_zombie_closure,
                            GRPC_ERROR_NONE, NULL);
      } else {
        GPR_ASSERT(calld->state == PENDING);
        calld->state = ACTIVATED;
        gpr_mu_unlock(&calld->mu_state);
        publish_call(exec_ctx, server, calld, cq_idx,
                     &server->requested_calls_per_cq[cq_idx][request_id]);
      }
      gpr_mu_lock(&server->mu_call);
    }
    gpr_mu_unlock(&server->mu_call);
  }
  return GRPC_CALL_OK;
}
Пример #4
0
static void test_create_channel_stack(void) {
  const grpc_channel_filter filter = {
      call_func,
      channel_func,
      sizeof(int),
      call_init_func,
      grpc_call_stack_ignore_set_pollset_or_pollset_set,
      call_destroy_func,
      sizeof(int),
      channel_init_func,
      channel_destroy_func,
      get_peer,
      "some_test_filter"};
  const grpc_channel_filter *filters = &filter;
  grpc_channel_stack *channel_stack;
  grpc_call_stack *call_stack;
  grpc_channel_element *channel_elem;
  grpc_call_element *call_elem;
  grpc_arg arg;
  grpc_channel_args chan_args;
  int *channel_data;
  int *call_data;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;

  arg.type = GRPC_ARG_INTEGER;
  arg.key = "test_key";
  arg.value.integer = 42;

  chan_args.num_args = 1;
  chan_args.args = &arg;

  channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1));
  grpc_channel_stack_init(&exec_ctx, 1, free_channel, channel_stack, &filters,
                          1, &chan_args, NULL, "test", channel_stack);
  GPR_ASSERT(channel_stack->count == 1);
  channel_elem = grpc_channel_stack_element(channel_stack, 0);
  channel_data = (int *)channel_elem->channel_data;
  GPR_ASSERT(*channel_data == 0);

  call_stack = gpr_malloc(channel_stack->call_stack_size);
  grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack, NULL,
                       NULL, call_stack);
  GPR_ASSERT(call_stack->count == 1);
  call_elem = grpc_call_stack_element(call_stack, 0);
  GPR_ASSERT(call_elem->filter == channel_elem->filter);
  GPR_ASSERT(call_elem->channel_data == channel_elem->channel_data);
  call_data = (int *)call_elem->call_data;
  GPR_ASSERT(*call_data == 0);
  GPR_ASSERT(*channel_data == 1);

  GRPC_CALL_STACK_UNREF(&exec_ctx, call_stack, "done");
  grpc_exec_ctx_flush(&exec_ctx);
  GPR_ASSERT(*channel_data == 2);

  GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done");

  grpc_exec_ctx_finish(&exec_ctx);
}
Пример #5
0
static void test_create_channel_stack(void) {
  const grpc_channel_filter filter = {
      call_func, channel_func, sizeof(int), call_init_func, call_destroy_func,
      sizeof(int), channel_init_func, channel_destroy_func, "some_test_filter"};
  const grpc_channel_filter *filters = &filter;
  grpc_channel_stack *channel_stack;
  grpc_call_stack *call_stack;
  grpc_channel_element *channel_elem;
  grpc_call_element *call_elem;
  grpc_arg arg;
  grpc_channel_args chan_args;
  grpc_mdctx *metadata_context;
  int *channel_data;
  int *call_data;

  LOG_TEST_NAME();

  metadata_context = grpc_mdctx_create();

  arg.type = GRPC_ARG_INTEGER;
  arg.key = "test_key";
  arg.value.integer = 42;

  chan_args.num_args = 1;
  chan_args.args = &arg;

  channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1));
  grpc_channel_stack_init(&filters, 1, &chan_args, metadata_context,
                          channel_stack);
  GPR_ASSERT(channel_stack->count == 1);
  channel_elem = grpc_channel_stack_element(channel_stack, 0);
  channel_data = (int *)channel_elem->channel_data;
  GPR_ASSERT(*channel_data == 0);

  call_stack = gpr_malloc(channel_stack->call_stack_size);
  grpc_call_stack_init(channel_stack, NULL, NULL, call_stack);
  GPR_ASSERT(call_stack->count == 1);
  call_elem = grpc_call_stack_element(call_stack, 0);
  GPR_ASSERT(call_elem->filter == channel_elem->filter);
  GPR_ASSERT(call_elem->channel_data == channel_elem->channel_data);
  call_data = (int *)call_elem->call_data;
  GPR_ASSERT(*call_data == 0);
  GPR_ASSERT(*channel_data == 1);

  grpc_call_stack_destroy(call_stack);
  gpr_free(call_stack);
  GPR_ASSERT(*channel_data == 2);

  grpc_channel_stack_destroy(channel_stack);
  gpr_free(channel_stack);

  grpc_mdctx_unref(metadata_context);
}
Пример #6
0
static void publish_registered_or_batch(grpc_exec_ctx *exec_ctx, void *prc,
                                        bool success) {
  requested_call *rc = prc;
  grpc_call *call = *rc->call;
  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;
  server_ref(chand->server);
  grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, success, done_request_event,
                 rc, &rc->completion);
  GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "server");
}
Пример #7
0
static void request_matcher_zombify_all_pending_calls(grpc_exec_ctx *exec_ctx,
                                                      request_matcher *rm) {
  while (rm->pending_head) {
    call_data *calld = rm->pending_head;
    rm->pending_head = calld->pending_next;
    gpr_mu_lock(&calld->mu_state);
    calld->state = ZOMBIED;
    gpr_mu_unlock(&calld->mu_state);
    grpc_closure_init(
        &calld->kill_zombie_closure, kill_zombie,
        grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
    grpc_exec_ctx_enqueue(exec_ctx, &calld->kill_zombie_closure, true, NULL);
  }
}
Пример #8
0
static void publish_new_rpc(grpc_exec_ctx *exec_ctx, void *arg,
                            grpc_error *error) {
  grpc_call_element *call_elem = arg;
  call_data *calld = call_elem->call_data;
  channel_data *chand = call_elem->channel_data;
  request_matcher *rm = calld->request_matcher;
  grpc_server *server = rm->server;

  if (error != GRPC_ERROR_NONE || gpr_atm_acq_load(&server->shutdown_flag)) {
    gpr_mu_lock(&calld->mu_state);
    calld->state = ZOMBIED;
    gpr_mu_unlock(&calld->mu_state);
    grpc_closure_init(
        &calld->kill_zombie_closure, kill_zombie,
        grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
    grpc_exec_ctx_sched(exec_ctx, &calld->kill_zombie_closure, error, NULL);
    return;
  }

  for (size_t i = 0; i < server->cq_count; i++) {
    size_t cq_idx = (chand->cq_idx + i) % server->cq_count;
    int request_id = gpr_stack_lockfree_pop(rm->requests_per_cq[cq_idx]);
    if (request_id == -1) {
      continue;
    } else {
      gpr_mu_lock(&calld->mu_state);
      calld->state = ACTIVATED;
      gpr_mu_unlock(&calld->mu_state);
      publish_call(exec_ctx, server, calld, cq_idx,
                   &server->requested_calls_per_cq[cq_idx][request_id]);
      return; /* early out */
    }
  }

  /* no cq to take the request found: queue it on the slow list */
  gpr_mu_lock(&server->mu_call);
  gpr_mu_lock(&calld->mu_state);
  calld->state = PENDING;
  gpr_mu_unlock(&calld->mu_state);
  if (rm->pending_head == NULL) {
    rm->pending_tail = rm->pending_head = calld;
  } else {
    rm->pending_tail->pending_next = calld;
    rm->pending_tail = calld;
  }
  calld->pending_next = NULL;
  gpr_mu_unlock(&server->mu_call);
}
Пример #9
0
void grpc_server_destroy(grpc_server *server) {
  channel_data *c;
  listener *l;
  size_t i;
  call_data *calld;

  gpr_mu_lock(&server->mu);
  if (!server->shutdown) {
    gpr_mu_unlock(&server->mu);
    grpc_server_shutdown(server);
    gpr_mu_lock(&server->mu);
  }

  while (server->listeners_destroyed != num_listeners(server)) {
    for (i = 0; i < server->cq_count; i++) {
      gpr_mu_unlock(&server->mu);
      grpc_cq_hack_spin_pollset(server->cqs[i]);
      gpr_mu_lock(&server->mu);
    }

    gpr_cv_wait(&server->cv, &server->mu,
                gpr_time_add(gpr_now(), gpr_time_from_millis(100)));
  }

  while (server->listeners) {
    l = server->listeners;
    server->listeners = l->next;
    gpr_free(l);
  }

  while ((calld = call_list_remove_head(&server->lists[PENDING_START],
                                        PENDING_START)) != NULL) {
    gpr_log(GPR_DEBUG, "server destroys call %p", calld->call);
    calld->state = ZOMBIED;
    grpc_iomgr_add_callback(
        kill_zombie,
        grpc_call_stack_element(grpc_call_get_call_stack(calld->call), 0));
  }

  for (c = server->root_channel_data.next; c != &server->root_channel_data;
       c = c->next) {
    shutdown_channel(c);
  }
  gpr_mu_unlock(&server->mu);

  server_unref(server);
}
Пример #10
0
static void publish_legacy(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->unregistered_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 {
    gpr_log(GPR_ERROR, "should never reach here");
    abort();
  }
}
Пример #11
0
static void accept_stream(grpc_exec_ctx *exec_ctx, void *cd,
                          grpc_transport *transport,
                          const void *transport_server_data) {
  channel_data *chand = cd;
  /* create a call */
  grpc_call *call = grpc_call_create(chand->channel, NULL, 0, NULL, NULL,
                                     transport_server_data, NULL, 0,
                                     gpr_inf_future(GPR_CLOCK_MONOTONIC));
  grpc_call_element *elem =
      grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
  call_data *calld = elem->call_data;
  grpc_op op;
  memset(&op, 0, sizeof(op));
  op.op = GRPC_OP_RECV_INITIAL_METADATA;
  op.data.recv_initial_metadata = &calld->initial_metadata;
  grpc_closure_init(&calld->got_initial_metadata, got_initial_metadata, elem);
  grpc_call_start_batch_and_execute(exec_ctx, call, &op, 1,
                                    &calld->got_initial_metadata);
}
Пример #12
0
static void publish_call(grpc_exec_ctx *exec_ctx, grpc_server *server,
                         call_data *calld, size_t cq_idx, requested_call *rc) {
  grpc_call_set_completion_queue(exec_ctx, calld->call, rc->cq_bound_to_call);
  grpc_call *call = calld->call;
  *rc->call = call;
  calld->cq_new = server->cqs[cq_idx];
  GPR_SWAP(grpc_metadata_array, *rc->initial_metadata, calld->initial_metadata);
  switch (rc->type) {
    case BATCH_CALL:
      GPR_ASSERT(calld->host != NULL);
      GPR_ASSERT(calld->path != NULL);
      cpstr(&rc->data.batch.details->host,
            &rc->data.batch.details->host_capacity, calld->host);
      cpstr(&rc->data.batch.details->method,
            &rc->data.batch.details->method_capacity, calld->path);
      rc->data.batch.details->deadline = calld->deadline;
      rc->data.batch.details->flags =
          0 | (calld->recv_idempotent_request
                   ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST
                   : 0);
      break;
    case REGISTERED_CALL:
      *rc->data.registered.deadline = calld->deadline;
      if (rc->data.registered.optional_payload) {
        *rc->data.registered.optional_payload = calld->payload;
      }
      break;
    default:
      GPR_UNREACHABLE_CODE(return );
  }

  grpc_call_element *elem =
      grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
  channel_data *chand = elem->channel_data;
  server_ref(chand->server);
  grpc_cq_end_op(exec_ctx, calld->cq_new, rc->tag, GRPC_ERROR_NONE,
                 done_request_event, rc, &rc->completion);
}
Пример #13
0
static void test_create_channel_stack(void) {
  const grpc_channel_filter filter = {
      call_func,
      channel_func,
      sizeof(int),
      call_init_func,
      grpc_call_stack_ignore_set_pollset_or_pollset_set,
      call_destroy_func,
      sizeof(int),
      channel_init_func,
      channel_destroy_func,
      get_peer,
      grpc_channel_next_get_info,
      "some_test_filter"};
  const grpc_channel_filter *filters = &filter;
  grpc_channel_stack *channel_stack;
  grpc_call_stack *call_stack;
  grpc_channel_element *channel_elem;
  grpc_call_element *call_elem;
  grpc_arg arg;
  grpc_channel_args chan_args;
  int *channel_data;
  int *call_data;
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
  grpc_mdstr *path = grpc_mdstr_from_string("/service/method");

  arg.type = GRPC_ARG_INTEGER;
  arg.key = "test_key";
  arg.value.integer = 42;

  chan_args.num_args = 1;
  chan_args.args = &arg;

  channel_stack = gpr_malloc(grpc_channel_stack_size(&filters, 1));
  grpc_channel_stack_init(&exec_ctx, 1, free_channel, channel_stack, &filters,
                          1, &chan_args, NULL, "test", channel_stack);
  GPR_ASSERT(channel_stack->count == 1);
  channel_elem = grpc_channel_stack_element(channel_stack, 0);
  channel_data = (int *)channel_elem->channel_data;
  GPR_ASSERT(*channel_data == 0);

  call_stack = gpr_malloc(channel_stack->call_stack_size);
  grpc_error *error =
      grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack,
                           NULL, NULL, path, gpr_now(GPR_CLOCK_MONOTONIC),
                           gpr_inf_future(GPR_CLOCK_MONOTONIC), call_stack);
  GPR_ASSERT(error == GRPC_ERROR_NONE);
  GPR_ASSERT(call_stack->count == 1);
  call_elem = grpc_call_stack_element(call_stack, 0);
  GPR_ASSERT(call_elem->filter == channel_elem->filter);
  GPR_ASSERT(call_elem->channel_data == channel_elem->channel_data);
  call_data = (int *)call_elem->call_data;
  GPR_ASSERT(*call_data == 0);
  GPR_ASSERT(*channel_data == 1);

  GRPC_CALL_STACK_UNREF(&exec_ctx, call_stack, "done");
  grpc_exec_ctx_flush(&exec_ctx);
  GPR_ASSERT(*channel_data == 2);

  GRPC_CHANNEL_STACK_UNREF(&exec_ctx, channel_stack, "done");

  grpc_exec_ctx_finish(&exec_ctx);
  GRPC_MDSTR_UNREF(path);
}