Exemple #1
0
/* Cleaning up a list with pending alarms. */
void destruction_test(void) {
  grpc_alarm alarms[5];
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;

  grpc_alarm_list_init(gpr_time_0(GPR_CLOCK_REALTIME));
  memset(cb_called, 0, sizeof(cb_called));

  grpc_alarm_init(&exec_ctx, &alarms[0], tfm(100), cb, (void *)(gpr_intptr)0,
                  gpr_time_0(GPR_CLOCK_REALTIME));
  grpc_alarm_init(&exec_ctx, &alarms[1], tfm(3), cb, (void *)(gpr_intptr)1,
                  gpr_time_0(GPR_CLOCK_REALTIME));
  grpc_alarm_init(&exec_ctx, &alarms[2], tfm(100), cb, (void *)(gpr_intptr)2,
                  gpr_time_0(GPR_CLOCK_REALTIME));
  grpc_alarm_init(&exec_ctx, &alarms[3], tfm(3), cb, (void *)(gpr_intptr)3,
                  gpr_time_0(GPR_CLOCK_REALTIME));
  grpc_alarm_init(&exec_ctx, &alarms[4], tfm(1), cb, (void *)(gpr_intptr)4,
                  gpr_time_0(GPR_CLOCK_REALTIME));
  GPR_ASSERT(1 == grpc_alarm_check(&exec_ctx, tfm(2), NULL));
  grpc_exec_ctx_finish(&exec_ctx);
  GPR_ASSERT(1 == cb_called[4][1]);
  grpc_alarm_cancel(&exec_ctx, &alarms[0]);
  grpc_alarm_cancel(&exec_ctx, &alarms[3]);
  grpc_exec_ctx_finish(&exec_ctx);
  GPR_ASSERT(1 == cb_called[0][0]);
  GPR_ASSERT(1 == cb_called[3][0]);

  grpc_alarm_list_shutdown(&exec_ctx);
  grpc_exec_ctx_finish(&exec_ctx);
  GPR_ASSERT(1 == cb_called[1][0]);
  GPR_ASSERT(1 == cb_called[2][0]);
}
Exemple #2
0
/* Cleaning up a list with pending alarms. */
void destruction_test(void) {
    grpc_alarm alarms[5];

    grpc_alarm_list_init(gpr_time_0);
    memset(cb_called, 0, sizeof(cb_called));

    grpc_alarm_init(&alarms[0], gpr_time_from_millis(100), cb,
                    (void *)(gpr_intptr)0, gpr_time_0);
    grpc_alarm_init(&alarms[1], gpr_time_from_millis(3), cb,
                    (void *)(gpr_intptr)1, gpr_time_0);
    grpc_alarm_init(&alarms[2], gpr_time_from_millis(100), cb,
                    (void *)(gpr_intptr)2, gpr_time_0);
    grpc_alarm_init(&alarms[3], gpr_time_from_millis(3), cb,
                    (void *)(gpr_intptr)3, gpr_time_0);
    grpc_alarm_init(&alarms[4], gpr_time_from_millis(1), cb,
                    (void *)(gpr_intptr)4, gpr_time_0);
    GPR_ASSERT(1 == grpc_alarm_check(NULL, gpr_time_from_millis(2), NULL));
    GPR_ASSERT(1 == cb_called[4][1]);
    grpc_alarm_cancel(&alarms[0]);
    grpc_alarm_cancel(&alarms[3]);
    GPR_ASSERT(1 == cb_called[0][0]);
    GPR_ASSERT(1 == cb_called[3][0]);

    grpc_alarm_list_shutdown();
    GPR_ASSERT(1 == cb_called[1][0]);
    GPR_ASSERT(1 == cb_called[2][0]);
}
Exemple #3
0
static void add_test(void) {
    gpr_timespec start = gpr_now(GPR_CLOCK_REALTIME);
    int i;
    grpc_alarm alarms[20];

    grpc_alarm_list_init(start);
    memset(cb_called, 0, sizeof(cb_called));

    /* 10 ms alarms.  will expire in the current epoch */
    for (i = 0; i < 10; i++) {
        grpc_alarm_init(&alarms[i], gpr_time_add(start, gpr_time_from_millis(10)),
                        cb, (void *)(gpr_intptr)i, start);
    }

    /* 1010 ms alarms.  will expire in the next epoch */
    for (i = 10; i < 20; i++) {
        grpc_alarm_init(&alarms[i], gpr_time_add(start, gpr_time_from_millis(1010)),
                        cb, (void *)(gpr_intptr)i, start);
    }

    /* collect alarms.  Only the first batch should be ready. */
    GPR_ASSERT(10 ==
               grpc_alarm_check(
                   NULL, gpr_time_add(start, gpr_time_from_millis(500)), NULL));
    for (i = 0; i < 20; i++) {
        GPR_ASSERT(cb_called[i][1] == (i < 10));
        GPR_ASSERT(cb_called[i][0] == 0);
    }

    GPR_ASSERT(0 ==
               grpc_alarm_check(
                   NULL, gpr_time_add(start, gpr_time_from_millis(600)), NULL));
    for (i = 0; i < 30; i++) {
        GPR_ASSERT(cb_called[i][1] == (i < 10));
        GPR_ASSERT(cb_called[i][0] == 0);
    }

    /* collect the rest of the alarms */
    GPR_ASSERT(10 ==
               grpc_alarm_check(
                   NULL, gpr_time_add(start, gpr_time_from_millis(1500)), NULL));
    for (i = 0; i < 30; i++) {
        GPR_ASSERT(cb_called[i][1] == (i < 20));
        GPR_ASSERT(cb_called[i][0] == 0);
    }

    GPR_ASSERT(0 ==
               grpc_alarm_check(
                   NULL, gpr_time_add(start, gpr_time_from_millis(1600)), NULL));
    for (i = 0; i < 30; i++) {
        GPR_ASSERT(cb_called[i][1] == (i < 20));
        GPR_ASSERT(cb_called[i][0] == 0);
    }

    grpc_alarm_list_shutdown();
}
Exemple #4
0
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());
}
Exemple #5
0
static void set_deadline_alarm(grpc_call *call, gpr_timespec deadline) {
  if (call->have_alarm) {
    gpr_log(GPR_ERROR, "Attempt to set deadline alarm twice");
    assert(0);
    return;
  }
  GRPC_CALL_INTERNAL_REF(call, "alarm");
  call->have_alarm = 1;
  grpc_alarm_init(&call->alarm, deadline, call_alarm, call, gpr_now());
}
Exemple #6
0
void grpc_client_setup_request_finish(grpc_client_setup_request *r,
                                      int was_successful) {
  int retry = !was_successful;
  grpc_client_setup *s = r->setup;

  gpr_mu_lock(&s->mu);
  if (s->active_request == r) {
    s->active_request = NULL;
  } else {
    retry = 0;
  }

  if (!retry && 0 == --s->refs) {
    gpr_mu_unlock(&s->mu);
    destroy_setup(s);
    destroy_request(r);
  } else if (retry) {
    /* TODO(klempner): Replace these values with further consideration. 2x is
       probably too aggressive of a backoff. */
    gpr_timespec max_backoff = gpr_time_from_minutes(2);
    gpr_timespec now = gpr_now();
    gpr_timespec deadline = gpr_time_add(s->current_backoff_interval, now);
    GPR_ASSERT(!s->in_alarm);
    s->in_alarm = 1;
    grpc_alarm_init(&s->backoff_alarm, deadline, backoff_alarm_done, r, now);
    s->current_backoff_interval =
        gpr_time_add(s->current_backoff_interval, s->current_backoff_interval);
    if (gpr_time_cmp(s->current_backoff_interval, max_backoff) > 0) {
      s->current_backoff_interval = max_backoff;
    }
    gpr_mu_unlock(&s->mu);
  } else {
    gpr_mu_unlock(&s->mu);
    destroy_request(r);
  }
}
Exemple #7
0
void grpc_tcp_client_connect(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
                             grpc_endpoint **ep,
                             grpc_pollset_set *interested_parties,
                             const struct sockaddr *addr, size_t addr_len,
                             gpr_timespec deadline) {
  int fd;
  grpc_dualstack_mode dsmode;
  int err;
  async_connect *ac;
  struct sockaddr_in6 addr6_v4mapped;
  struct sockaddr_in addr4_copy;
  grpc_fd *fdobj;
  char *name;
  char *addr_str;

  *ep = NULL;

  /* Use dualstack sockets where available. */
  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
    addr = (const struct sockaddr *)&addr6_v4mapped;
    addr_len = sizeof(addr6_v4mapped);
  }

  fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
  if (fd < 0) {
    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
  }
  if (dsmode == GRPC_DSMODE_IPV4) {
    /* If we got an AF_INET socket, map the address back to IPv4. */
    GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy));
    addr = (struct sockaddr *)&addr4_copy;
    addr_len = sizeof(addr4_copy);
  }
  if (!prepare_socket(addr, fd)) {
    grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
    return;
  }

  do {
    GPR_ASSERT(addr_len < ~(socklen_t)0);
    err = connect(fd, addr, (socklen_t)addr_len);
  } while (err < 0 && errno == EINTR);

  addr_str = grpc_sockaddr_to_uri(addr);
  gpr_asprintf(&name, "tcp-client:%s", addr_str);

  fdobj = grpc_fd_create(fd, name);

  if (err >= 0) {
    *ep = grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str);
    grpc_exec_ctx_enqueue(exec_ctx, closure, 1);
    goto done;
  }

  if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
    gpr_log(GPR_ERROR, "connect error to '%s': %s", addr_str, strerror(errno));
    grpc_fd_orphan(exec_ctx, fdobj, NULL, "tcp_client_connect_error");
    grpc_exec_ctx_enqueue(exec_ctx, closure, 0);
    goto done;
  }

  grpc_pollset_set_add_fd(exec_ctx, interested_parties, fdobj);

  ac = gpr_malloc(sizeof(async_connect));
  ac->closure = closure;
  ac->ep = ep;
  ac->fd = fdobj;
  ac->interested_parties = interested_parties;
  ac->addr_str = addr_str;
  addr_str = NULL;
  gpr_mu_init(&ac->mu);
  ac->refs = 2;
  ac->write_closure.cb = on_writable;
  ac->write_closure.cb_arg = ac;

  if (grpc_tcp_trace) {
    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting",
            ac->addr_str);
  }

  gpr_mu_lock(&ac->mu);
  grpc_alarm_init(exec_ctx, &ac->alarm,
                  gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
                  tc_on_alarm, ac, gpr_now(GPR_CLOCK_MONOTONIC));
  grpc_fd_notify_on_write(exec_ctx, ac->fd, &ac->write_closure);
  gpr_mu_unlock(&ac->mu);

done:
  gpr_free(name);
  gpr_free(addr_str);
}
Exemple #8
0
void grpc_tcp_client_connect(void (*cb)(void *arg, grpc_endpoint *ep),
                             void *arg, const struct sockaddr *addr,
                             int addr_len, gpr_timespec deadline) {
  int fd;
  grpc_dualstack_mode dsmode;
  int err;
  async_connect *ac;
  struct sockaddr_in6 addr6_v4mapped;
  struct sockaddr_in addr4_copy;

  /* Use dualstack sockets where available. */
  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
    addr = (const struct sockaddr *)&addr6_v4mapped;
    addr_len = sizeof(addr6_v4mapped);
  }

  fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
  if (fd < 0) {
    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
  }
  if (dsmode == GRPC_DSMODE_IPV4) {
    /* If we got an AF_INET socket, map the address back to IPv4. */
    GPR_ASSERT(grpc_sockaddr_is_v4mapped(addr, &addr4_copy));
    addr = (struct sockaddr *)&addr4_copy;
    addr_len = sizeof(addr4_copy);
  }
  if (!prepare_socket(addr, fd)) {
    cb(arg, NULL);
    return;
  }

  do {
    err = connect(fd, addr, addr_len);
  } while (err < 0 && errno == EINTR);

  if (err >= 0) {
    gpr_log(GPR_DEBUG, "instant connect");
    cb(arg,
       grpc_tcp_create(grpc_fd_create(fd), GRPC_TCP_DEFAULT_READ_SLICE_SIZE));
    return;
  }

  if (errno != EWOULDBLOCK && errno != EINPROGRESS) {
    gpr_log(GPR_ERROR, "connect error: %s", strerror(errno));
    close(fd);
    cb(arg, NULL);
    return;
  }

  ac = gpr_malloc(sizeof(async_connect));
  ac->cb = cb;
  ac->cb_arg = arg;
  ac->fd = grpc_fd_create(fd);
  gpr_mu_init(&ac->mu);
  ac->refs = 2;
  ac->write_closure.cb = on_writable;
  ac->write_closure.cb_arg = ac;

  grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now());
  grpc_fd_notify_on_write(ac->fd, &ac->write_closure);
}
Exemple #9
0
/* Test grpc_alarm add and cancel. */
static void test_grpc_alarm(void) {
  grpc_alarm alarm;
  grpc_alarm alarm_to_cancel;
  /* Timeout on the alarm cond. var, so make big enough to absorb time
     deviations. Otherwise, operations after wait will not be properly ordered
   */
  gpr_timespec alarm_deadline;
  gpr_timespec followup_deadline;

  alarm_arg arg;
  alarm_arg arg2;
  void *fdone;

  grpc_iomgr_init();

  arg.counter = 0;
  arg.success = SUCCESS_NOT_SET;
  arg.done_success_ctr = 0;
  arg.done_cancel_ctr = 0;
  arg.done = 0;
  gpr_mu_init(&arg.mu);
  gpr_cv_init(&arg.cv);
  gpr_event_init(&arg.fcb_arg);

  grpc_alarm_init(&alarm, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100), alarm_cb, &arg,
                  gpr_now());

  alarm_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1);
  gpr_mu_lock(&arg.mu);
  while (arg.done == 0) {
    if (gpr_cv_wait(&arg.cv, &arg.mu, alarm_deadline)) {
      gpr_log(GPR_ERROR, "alarm deadline exceeded");
      break;
    }
  }
  gpr_mu_unlock(&arg.mu);

  followup_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
  fdone = gpr_event_wait(&arg.fcb_arg, followup_deadline);

  if (arg.counter != 1) {
    gpr_log(GPR_ERROR, "Alarm callback not called");
    GPR_ASSERT(0);
  } else if (arg.done_success_ctr != 1) {
    gpr_log(GPR_ERROR, "Alarm done callback not called with success");
    GPR_ASSERT(0);
  } else if (arg.done_cancel_ctr != 0) {
    gpr_log(GPR_ERROR, "Alarm done callback called with cancel");
    GPR_ASSERT(0);
  } else if (arg.success == SUCCESS_NOT_SET) {
    gpr_log(GPR_ERROR, "Alarm callback without status");
    GPR_ASSERT(0);
  } else {
    gpr_log(GPR_INFO, "Alarm callback called successfully");
  }

  if (fdone != (void *)&arg.fcb_arg) {
    gpr_log(GPR_ERROR, "Followup callback #1 not invoked properly %p %p", fdone,
            &arg.fcb_arg);
    GPR_ASSERT(0);
  }
  gpr_cv_destroy(&arg.cv);
  gpr_mu_destroy(&arg.mu);

  arg2.counter = 0;
  arg2.success = SUCCESS_NOT_SET;
  arg2.done_success_ctr = 0;
  arg2.done_cancel_ctr = 0;
  arg2.done = 0;
  gpr_mu_init(&arg2.mu);
  gpr_cv_init(&arg2.cv);
  gpr_event_init(&arg2.fcb_arg);

  grpc_alarm_init(&alarm_to_cancel, GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100),
                  alarm_cb, &arg2, gpr_now());
  grpc_alarm_cancel(&alarm_to_cancel);

  alarm_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1);
  gpr_mu_lock(&arg2.mu);
  while (arg2.done == 0) {
    gpr_cv_wait(&arg2.cv, &arg2.mu, alarm_deadline);
  }
  gpr_mu_unlock(&arg2.mu);

  gpr_log(GPR_INFO, "alarm done = %d", arg2.done);

  followup_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5);
  fdone = gpr_event_wait(&arg2.fcb_arg, followup_deadline);

  if (arg2.counter != arg2.done_success_ctr) {
    gpr_log(GPR_ERROR, "Alarm callback called but didn't lead to done success");
    GPR_ASSERT(0);
  } else if (arg2.done_success_ctr && arg2.done_cancel_ctr) {
    gpr_log(GPR_ERROR, "Alarm done callback called with success and cancel");
    GPR_ASSERT(0);
  } else if (arg2.done_cancel_ctr + arg2.done_success_ctr != 1) {
    gpr_log(GPR_ERROR, "Alarm done callback called incorrect number of times");
    GPR_ASSERT(0);
  } else if (arg2.success == SUCCESS_NOT_SET) {
    gpr_log(GPR_ERROR, "Alarm callback without status");
    GPR_ASSERT(0);
  } else if (arg2.done_success_ctr) {
    gpr_log(GPR_INFO, "Alarm callback executed before cancel");
    gpr_log(GPR_INFO, "Current value of triggered is %d\n",
            alarm_to_cancel.triggered);
  } else if (arg2.done_cancel_ctr) {
    gpr_log(GPR_INFO, "Alarm callback canceled");
    gpr_log(GPR_INFO, "Current value of triggered is %d\n",
            alarm_to_cancel.triggered);
  } else {
    gpr_log(GPR_ERROR, "Alarm cancel test should not be here");
    GPR_ASSERT(0);
  }

  if (fdone != (void *)&arg2.fcb_arg) {
    gpr_log(GPR_ERROR, "Followup callback #2 not invoked properly %p %p", fdone,
            &arg2.fcb_arg);
    GPR_ASSERT(0);
  }
  gpr_cv_destroy(&arg2.cv);
  gpr_mu_destroy(&arg2.mu);

  grpc_iomgr_shutdown();
}
void grpc_tcp_client_connect(void(*cb)(void *arg, grpc_endpoint *tcp),
                             void *arg, const struct sockaddr *addr,
                             int addr_len, gpr_timespec deadline) {
  SOCKET sock = INVALID_SOCKET;
  BOOL success;
  int status;
  struct sockaddr_in6 addr6_v4mapped;
  struct sockaddr_in6 local_address;
  async_connect *ac;
  grpc_winsocket *socket = NULL;
  LPFN_CONNECTEX ConnectEx;
  GUID guid = WSAID_CONNECTEX;
  DWORD ioctl_num_bytes;
  const char *message = NULL;
  char *utf8_message;
  grpc_winsocket_callback_info *info;

  /* Use dualstack sockets where available. */
  if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
    addr = (const struct sockaddr *)&addr6_v4mapped;
    addr_len = sizeof(addr6_v4mapped);
  }

  sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
                   WSA_FLAG_OVERLAPPED);
  if (sock == INVALID_SOCKET) {
    message = "Unable to create socket: %s";
    goto failure;
  }

  if (!grpc_tcp_prepare_socket(sock)) {
    message = "Unable to set socket options: %s";
    goto failure;
  }

  status = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
                    &guid, sizeof(guid), &ConnectEx, sizeof(ConnectEx),
                    &ioctl_num_bytes, NULL, NULL);

  if (status != 0) {
    message = "Unable to retreive ConnectEx pointer: %s";
    goto failure;
  }

  grpc_sockaddr_make_wildcard6(0, &local_address);

  status = bind(sock, (struct sockaddr *) &local_address,
                sizeof(local_address));
  if (status != 0) {
    message = "Unable to bind socket: %s";
    goto failure;
  }

  socket = grpc_winsocket_create(sock);
  info = &socket->write_info;
  success = ConnectEx(sock, addr, addr_len, NULL, 0, NULL, &info->overlapped);

  if (!success) {
    int error = WSAGetLastError();
    if (error != ERROR_IO_PENDING) {
      message = "ConnectEx failed: %s";
      goto failure;
    }
  }

  ac = gpr_malloc(sizeof(async_connect));
  ac->cb = cb;
  ac->cb_arg = arg;
  ac->socket = socket;
  gpr_mu_init(&ac->mu);
  ac->refs = 2;

  grpc_alarm_init(&ac->alarm, deadline, on_alarm, ac, gpr_now());
  grpc_socket_notify_on_write(socket, on_connect, ac);
  return;

failure:
  utf8_message = gpr_format_message(WSAGetLastError());
  gpr_log(GPR_ERROR, message, utf8_message);
  gpr_free(utf8_message);
  if (socket) {
    grpc_winsocket_orphan(socket);
  } else if (sock != INVALID_SOCKET) {
    closesocket(sock);
  }
  cb(arg, NULL);
}