Beispiel #1
0
/* {{{ size_t ma_pvio_read_async */
static size_t ma_pvio_read_async(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
{
  ssize_t res;
  struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
  int timeout= pvio->timeout[PVIO_READ_TIMEOUT];

  if (!pvio->methods->async_read)
  {
    PVIO_SET_ERROR(pvio->mysql, CR_ASYNC_NOT_SUPPORTED, unknown_sqlstate, 0);
    return -1;
  }

  for (;;)
  {
    if (pvio->methods->async_read)
      res= pvio->methods->async_read(pvio, buffer, length);
    if (res >= 0 || IS_BLOCKING_ERROR())
      return res;
    b->events_to_wait_for= MYSQL_WAIT_READ;
    if (timeout >= 0)
    {
      b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
      b->timeout_value= timeout;
    }
    if (b->suspend_resume_hook)
      (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
    my_context_yield(&b->async_context);
    if (b->suspend_resume_hook)
      (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
    if (b->events_occured & MYSQL_WAIT_TIMEOUT)
      return -1;
  }
}
Beispiel #2
0
/* {{{ ma_pvio_wait_async */
static my_bool
ma_pvio_wait_async(struct mysql_async_context *b, enum enum_pvio_io_event event,
                 int timeout)
{
  switch (event)
  {
  case VIO_IO_EVENT_READ:
    b->events_to_wait_for = MYSQL_WAIT_READ;
    break;
  case VIO_IO_EVENT_WRITE:
    b->events_to_wait_for = MYSQL_WAIT_WRITE;
    break;
  case VIO_IO_EVENT_CONNECT:
    b->events_to_wait_for = MYSQL_WAIT_WRITE | IF_WIN(0, MYSQL_WAIT_EXCEPT);
    break;
  }

  if (timeout >= 0)
  {
    b->events_to_wait_for |= MYSQL_WAIT_TIMEOUT;
    b->timeout_value= timeout;
  }
  if (b->suspend_resume_hook)
    (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
  my_context_yield(&b->async_context);
  if (b->suspend_resume_hook)
    (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
  return (b->events_occured & MYSQL_WAIT_TIMEOUT) ? 0 : 1;
}
Beispiel #3
0
/* {{{ size_t ma_pvio_write_async */
static size_t ma_pvio_write_async(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
{
  ssize_t res;
  struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
  int timeout= pvio->timeout[PVIO_WRITE_TIMEOUT];

  for (;;)
  {
    if (pvio->methods->async_write)
      res= pvio->methods->async_write(pvio, buffer, length);
    if (res >= 0 || IS_BLOCKING_ERROR())
      return res;
    b->events_to_wait_for= MYSQL_WAIT_WRITE;
    if (timeout >= 0)
    {
      b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
      b->timeout_value= timeout;
    }
    if (b->suspend_resume_hook)
      (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
    my_context_yield(&b->async_context);
    if (b->suspend_resume_hook)
      (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
    if (b->events_occured & MYSQL_WAIT_TIMEOUT)
      return -1;
  }
}
Beispiel #4
0
static my_bool
my_ssl_async_check_result(int res, struct mysql_async_context *b, SSL *ssl)
{
  int ssl_err;
  b->events_to_wait_for= 0;
  if (res >= 0)
    return 1;
  ssl_err= SSL_get_error(ssl, res);
  if (ssl_err == SSL_ERROR_WANT_READ)
    b->events_to_wait_for|= MYSQL_WAIT_READ;
  else if (ssl_err == SSL_ERROR_WANT_WRITE)
    b->events_to_wait_for|= MYSQL_WAIT_WRITE;
  else
    return 1;
  if (b->suspend_resume_hook)
    (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
  my_context_yield(&b->async_context);
  if (b->suspend_resume_hook)
    (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
  return 0;
}
Beispiel #5
0
/* Asynchronous connect(); socket must already be set non-blocking. */
int
my_connect_async(struct mysql_async_context *b, my_socket fd,
                 const struct sockaddr *name, uint namelen, int vio_timeout)
{
  int res;
  size_socket s_err_size;

  /* Make the socket non-blocking. */
#ifdef __WIN__
  ulong arg= 1;
  ioctlsocket(fd, FIONBIO, (void *)&arg);
#else
  fcntl(fd, F_SETFL, O_NONBLOCK);
#endif

  b->events_to_wait_for= 0;
  /*
    Start to connect asynchronously.
    If this will block, we suspend the call and return control to the
    application context. The application will then resume us when the socket
    polls ready for write, indicating that the connection attempt completed.
  */
  res= connect(fd, name, namelen);
  if (res != 0)
  {
#ifdef __WIN__
    int wsa_err= WSAGetLastError();
    if (wsa_err != WSAEWOULDBLOCK)
      return res;
    b->events_to_wait_for|= MYSQL_WAIT_EXCEPT;
#else
    int err= errno;
    if (err != EINPROGRESS && err != EALREADY && err != EAGAIN)
      return res;
#endif
    b->events_to_wait_for|= MYSQL_WAIT_WRITE;
    if (vio_timeout >= 0)
    {
      b->timeout_value= vio_timeout;
      b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
    }
    else
      b->timeout_value= 0;
    if (b->suspend_resume_hook)
      (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
    my_context_yield(&b->async_context);
    if (b->suspend_resume_hook)
      (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
    if (b->events_occurred & MYSQL_WAIT_TIMEOUT)
      return -1;

    s_err_size= sizeof(res);
    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0)
      return -1;
    if (res)
    {
      errno= res;
      return -1;
    }
  }
  return res;
}
/* Asynchronous connect(); socket must already be set non-blocking. */
int
my_connect_async(MARIADB_PVIO *pvio,
                 const struct sockaddr *name, uint namelen, int vio_timeout)
{
  int res;
  size_socket s_err_size;
  struct mysql_async_context *b= pvio->mysql->options.extension->async_context;
  my_socket sock;

  ma_pvio_get_handle(pvio, &sock);

  /* Make the socket non-blocking. */
  ma_pvio_blocking(pvio, 0, 0);

  b->events_to_wait_for= 0;
  /*
    Start to connect asynchronously.
    If this will block, we suspend the call and return control to the
    application context. The application will then resume us when the socket
    polls ready for write, indicating that the connection attempt completed.
  */
  res= connect(sock, name, namelen);
  if (res != 0)
  {
#ifdef _WIN32
    int wsa_err= WSAGetLastError();
    if (wsa_err != WSAEWOULDBLOCK)
      return res;
    b->events_to_wait_for|= MYSQL_WAIT_EXCEPT;
#else
    int err= errno;
    if (err != EINPROGRESS && err != EALREADY && err != EAGAIN)
      return res;
#endif
    b->events_to_wait_for|= MYSQL_WAIT_WRITE;
    if (vio_timeout >= 0)
    {
      b->timeout_value= vio_timeout;
      b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
    }
    else
      b->timeout_value= 0;
    if (b->suspend_resume_hook)
      (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
    my_context_yield(&b->async_context);
    if (b->suspend_resume_hook)
      (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
    if (b->events_occured & MYSQL_WAIT_TIMEOUT)
      return -1;

    s_err_size= sizeof(res);
    if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0)
      return -1;
    if (res)
    {
      errno= res;
      return -1;
    }
  }
  return res;
}