Esempio n. 1
0
int pn_selector_select(pn_selector_t *selector, int timeout)
{
  assert(selector);
  pn_error_clear(selector->error);
  pn_timestamp_t deadline = 0;
  pn_timestamp_t now = pn_i_now();

  if (timeout) {
    if (selector->deadlines_head)
      deadline = selector->deadlines_head->deadline;
  }
  if (deadline) {
    int64_t delta = deadline - now;
    if (delta < 0) {
      delta = 0;
    }
    if (timeout < 0)
      timeout = delta;
    else if (timeout > delta)
      timeout = delta;
  }
  deadline = (timeout >= 0) ? now + timeout : 0;

  // Process all currently available completions, even if matched events available
  pni_iocp_drain_completions(selector->iocp);
  pni_zombie_check(selector->iocp, now);
  // Loop until an interested event is matched, or until deadline
  while (true) {
    if (selector->triggered_list_head)
      break;
    if (deadline && deadline <= now)
      break;
    pn_timestamp_t completion_deadline = deadline;
    pn_timestamp_t zd = pni_zombie_deadline(selector->iocp);
    if (zd)
      completion_deadline = completion_deadline ? pn_min(zd, completion_deadline) : zd;

    int completion_timeout = (!completion_deadline) ? -1 : completion_deadline - now;
    int rv = pni_iocp_wait_one(selector->iocp, completion_timeout, selector->error);
    if (rv < 0)
      return pn_error_code(selector->error);

    now = pn_i_now();
    if (zd && zd <= now) {
      pni_zombie_check(selector->iocp, now);
    }
  }

  selector->current = 0;
  selector->awoken = now;
  for (iocpdesc_t *iocpd = selector->deadlines_head; iocpd; iocpd = iocpd->deadlines_next) {
    if (iocpd->deadline <= now)
      pni_events_update(iocpd, iocpd->events | PN_EXPIRED);
    else
      break;
  }
  selector->current_triggered = selector->triggered_list_head;
  return pn_error_code(selector->error);
}
Esempio n. 2
0
int pn_messenger_errno(pn_messenger_t *messenger)
{
  if (messenger) {
    return pn_error_code(messenger->error);
  } else {
    return PN_ARG_ERR;
  }
}
Esempio n. 3
0
ssize_t pni_iocp_begin_write(iocpdesc_t *iocpd, const void *buf, size_t len, bool *would_block, pn_error_t *error)
{
  if (len == 0) return 0;
  *would_block = false;
  if (is_listener(iocpd)) {
    set_iocp_error_status(error, PN_ERR, WSAEOPNOTSUPP);
    return INVALID_SOCKET;
  }
  if (iocpd->closing) {
    set_iocp_error_status(error, PN_ERR, WSAESHUTDOWN);
    return SOCKET_ERROR;
  }
  if (iocpd->write_closed) {
    assert(pn_error_code(iocpd->error));
    pn_error_copy(error, iocpd->error);
    if (iocpd->iocp->iocp_trace)
      iocp_log("write error: %s\n", pn_error_text(error));
    return SOCKET_ERROR;
  }
  if (len == 0) return 0;
  if (!(iocpd->events & PN_WRITABLE)) {
    *would_block = true;
    return SOCKET_ERROR;
  }

  size_t written = 0;
  size_t requested = len;
  const char *outgoing = (const char *) buf;
  size_t available = pni_write_pipeline_reserve(iocpd->pipeline, len);
  if (!available) {
    *would_block = true;
    return SOCKET_ERROR;
  }

  for (size_t wr_count = 0; wr_count < available; wr_count++) {
    write_result_t *result = pni_write_pipeline_next(iocpd->pipeline);
    assert(result);
    result->base.iocpd = iocpd;
    ssize_t actual_len = pn_min(len, result->buffer.size);
    result->requested = actual_len;
    memmove((void *)result->buffer.start, outgoing, actual_len);
    outgoing += actual_len;
    written += actual_len;
    len -= actual_len;

    int werror = submit_write(result, result->buffer.start, actual_len);
    if (werror && WSAGetLastError() != ERROR_IO_PENDING) {
      pni_write_pipeline_return(iocpd->pipeline, result);
      iocpdesc_fail(iocpd, WSAGetLastError(), "overlapped send");
      return SOCKET_ERROR;
    }
    iocpd->ops_in_progress++;
  }

  if (!pni_write_pipeline_writable(iocpd->pipeline))
    pni_events_update(iocpd, iocpd->events & ~PN_WRITABLE);
  return written;
}
Esempio n. 4
0
int pn_error_copy(pn_error_t *error, pn_error_t *src)
{
  assert(error);
  if (src) {
    return pn_error_set(error, pn_error_code(src), pn_error_text(src));
  } else {
    pn_error_clear(error);
    return 0;
  }
}
Esempio n. 5
0
ssize_t pni_iocp_recv(iocpdesc_t *iocpd, void *buf, size_t size, bool *would_block, pn_error_t *error)
{
  if (size == 0) return 0;
  *would_block = false;
  if (is_listener(iocpd)) {
    set_iocp_error_status(error, PN_ERR, WSAEOPNOTSUPP);
    return SOCKET_ERROR;
  }
  if (iocpd->closing) {
    // Previous call to pn_close()
    set_iocp_error_status(error, PN_ERR, WSAESHUTDOWN);
    return SOCKET_ERROR;
  }
  if (iocpd->read_closed) {
    if (pn_error_code(iocpd->error))
      pn_error_copy(error, iocpd->error);
    else
      set_iocp_error_status(error, PN_ERR, WSAENOTCONN);
    return SOCKET_ERROR;
  }

  int count = recv(iocpd->socket, (char *) buf, size, 0);
  if (count > 0) {
    pni_events_update(iocpd, iocpd->events & ~PN_READABLE);
    begin_zero_byte_read(iocpd);
    return (ssize_t) count;
  } else if (count == 0) {
    iocpd->read_closed = true;
    return 0;
  }
  if (WSAGetLastError() == WSAEWOULDBLOCK)
    *would_block = true;
  else {
    set_iocp_error_status(error, PN_ERR, WSAGetLastError());
    iocpd->read_closed = true;
  }
  return SOCKET_ERROR;
}
Esempio n. 6
0
int pn_scanner_errno(pn_scanner_t *scanner)
{
  return pn_error_code(scanner->error);
}