예제 #1
0
static void test_constant_backoff(void) {
  gpr_backoff backoff;
  gpr_backoff_init(&backoff, 1.0, 0.0, 1000, 1000);

  gpr_timespec now = gpr_time_0(GPR_TIMESPAN);
  gpr_timespec next = gpr_backoff_begin(&backoff, now);
  GPR_ASSERT(gpr_time_to_millis(gpr_time_sub(next, now)) == 1000);
  for (int i = 0; i < 10000; i++) {
    next = gpr_backoff_step(&backoff, now);
    GPR_ASSERT(gpr_time_to_millis(gpr_time_sub(next, now)) == 1000);
    now = next;
  }
}
예제 #2
0
파일: pollset_uv.c 프로젝트: endobson/grpc
grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
                              grpc_pollset_worker **worker_hdl,
                              gpr_timespec now, gpr_timespec deadline) {
  uint64_t timeout;
  GRPC_UV_ASSERT_SAME_THREAD();
  gpr_mu_unlock(&grpc_polling_mu);
  if (grpc_pollset_work_run_loop) {
    if (gpr_time_cmp(deadline, now) >= 0) {
      timeout = (uint64_t)gpr_time_to_millis(gpr_time_sub(deadline, now));
    } else {
      timeout = 0;
    }
    /* We special-case timeout=0 so that we don't bother with the timer when
       the loop won't block anyway */
    if (timeout > 0) {
      uv_timer_start(&pollset->timer, timer_run_cb, timeout, 0);
      /* Run until there is some I/O activity or the timer triggers. It doesn't
         matter which happens */
      uv_run(uv_default_loop(), UV_RUN_ONCE);
      uv_timer_stop(&pollset->timer);
    } else {
      uv_run(uv_default_loop(), UV_RUN_NOWAIT);
    }
  }
  if (!grpc_closure_list_empty(exec_ctx->closure_list)) {
    grpc_exec_ctx_flush(exec_ctx);
  }
  gpr_mu_lock(&grpc_polling_mu);
  return GRPC_ERROR_NONE;
}
예제 #3
0
/* Convert a timespec to milliseconds:
   - Very small or negative poll times are clamped to zero to do a non-blocking
     poll (which becomes spin polling)
   - Other small values are rounded up to one millisecond
   - Longer than a millisecond polls are rounded up to the next nearest
     millisecond to avoid spinning
   - Infinite timeouts are converted to -1 */
static int poll_deadline_to_millis_timeout(gpr_timespec deadline,
                                           gpr_timespec now) {
  gpr_timespec timeout;
  if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) {
    return -1;
  }

  if (gpr_time_cmp(deadline, now) <= 0) {
    return 0;
  }

  static const gpr_timespec round_up = {
      .clock_type = GPR_TIMESPAN, .tv_sec = 0, .tv_nsec = GPR_NS_PER_MS - 1};
  timeout = gpr_time_sub(deadline, now);
  int millis = gpr_time_to_millis(gpr_time_add(timeout, round_up));
  return millis >= 1 ? millis : 1;
}

static void fd_become_readable(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
                               grpc_pollset *notifier) {
  grpc_lfev_set_ready(exec_ctx, &fd->read_closure);

  /* Note, it is possible that fd_become_readable might be called twice with
     different 'notifier's when an fd becomes readable and it is in two epoll
     sets (This can happen briefly during polling island merges). In such cases
     it does not really matter which notifer is set as the read_notifier_pollset
     (They would both point to the same polling island anyway) */
  /* Use release store to match with acquire load in fd_get_read_notifier */
  gpr_atm_rel_store(&fd->read_notifier_pollset, (gpr_atm)notifier);
}
예제 #4
0
파일: iocp_windows.c 프로젝트: kokoar/grpc
static void do_iocp_work() {
  BOOL success;
  DWORD bytes = 0;
  DWORD flags = 0;
  ULONG_PTR completion_key;
  LPOVERLAPPED overlapped;
  gpr_timespec wait_time = gpr_inf_future;
  grpc_winsocket *socket;
  grpc_winsocket_callback_info *info;
  void(*f)(void *, int) = NULL;
  void *opaque = NULL;
  success = GetQueuedCompletionStatus(g_iocp, &bytes,
                                      &completion_key, &overlapped,
                                      gpr_time_to_millis(wait_time));
  if (!success && !overlapped) {
    /* The deadline got attained. */
    return;
  }
  GPR_ASSERT(completion_key && overlapped);
  if (overlapped == &g_iocp_custom_overlap) {
    if (completion_key == (ULONG_PTR) &g_iocp_kick_token) {
      /* We were awoken from a kick. */
      return;
    }
    gpr_log(GPR_ERROR, "Unknown custom completion key.");
    abort();
  }

  socket = (grpc_winsocket*) completion_key;
  if (overlapped == &socket->write_info.overlapped) {
    info = &socket->write_info;
  } else if (overlapped == &socket->read_info.overlapped) {
    info = &socket->read_info;
  } else {
    gpr_log(GPR_ERROR, "Unknown IOCP operation");
    abort();
  }
  success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes,
                                   FALSE, &flags);
  if (socket->orphan) {
    grpc_winsocket_destroy(socket);
    gpr_atm_full_fetch_add(&g_orphans, -1);
    return;
  }
  info->bytes_transfered = bytes;
  info->wsa_error = success ? 0 : WSAGetLastError();
  GPR_ASSERT(overlapped == &info->overlapped);
  gpr_mu_lock(&socket->state_mu);
  GPR_ASSERT(!info->has_pending_iocp);
  if (info->cb) {
    f = info->cb;
    opaque = info->opaque;
    info->cb = NULL;
  } else {
    info->has_pending_iocp = 1;
  }
  gpr_mu_unlock(&socket->state_mu);
  if (f) f(opaque, 1);
}
예제 #5
0
int grpc_poll_deadline_to_millis_timeout(gpr_timespec deadline,
        gpr_timespec now) {
    gpr_timespec timeout;
    static const int64_t max_spin_polling_us = 10;
    if (gpr_time_cmp(deadline, gpr_inf_future(deadline.clock_type)) == 0) {
        return -1;
    }
    if (gpr_time_cmp(deadline, gpr_time_add(now, gpr_time_from_micros(
            max_spin_polling_us,
            GPR_TIMESPAN))) <= 0) {
        return 0;
    }
    timeout = gpr_time_sub(deadline, now);
    return gpr_time_to_millis(gpr_time_add(
                                  timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
}
예제 #6
0
static void pretty_print_backoffs(reconnect_server *server) {
  gpr_timespec diff;
  int i = 1;
  double expected_backoff = 1000.0, backoff;
  timestamp_list *head = server->head;
  gpr_log(GPR_INFO, "reconnect server: new connection");
  for (head = server->head; head && head->next; head = head->next, i++) {
    diff = gpr_time_sub(head->next->timestamp, head->timestamp);
    backoff = gpr_time_to_millis(diff);
    gpr_log(GPR_INFO,
            "retry %2d:backoff %6.2fs,expected backoff %6.2fs, jitter %4.2f%%",
            i, backoff / 1000.0, expected_backoff / 1000.0,
            (backoff - expected_backoff) * 100.0 / expected_backoff);
    expected_backoff *= 1.6;
    if (expected_backoff > 120 * 1000) {
      expected_backoff = 120 * 1000;
    }
  }
}