Created
September 4, 2008 12:57
-
-
Save methodmissing/8767 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* <MYSQL_ROOT>/vio/vio.c */ | |
/* Copyright (C) 2000 MySQL AB | |
This program is free software; you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation; version 2 of the License. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program; if not, write to the Free Software | |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | |
/* | |
Note that we can't have assertion on file descriptors; The reason for | |
this is that during mysql shutdown, another thread can close a file | |
we are working on. In this case we should just return read errors from | |
the file descriptior. | |
*/ | |
#include "vio_priv.h" | |
/* | |
* Helper to fill most of the Vio* with defaults. | |
*/ | |
static void vio_init(Vio* vio, enum enum_vio_type type, | |
my_socket sd, HANDLE hPipe, uint flags) | |
{ | |
DBUG_ENTER("vio_init"); | |
DBUG_PRINT("enter", ("type: %d sd: %d flags: %d", type, sd, flags)); | |
#ifndef HAVE_VIO_READ_BUFF | |
flags&= ~VIO_BUFFERED_READ; | |
#endif | |
bzero((char*) vio, sizeof(*vio)); | |
vio->type = type; | |
vio->sd = sd; | |
vio->hPipe = hPipe; | |
vio->localhost= flags & VIO_LOCALHOST; | |
if ((flags & VIO_BUFFERED_READ) && | |
!(vio->read_buffer= (char*)my_malloc(VIO_READ_BUFFER_SIZE, MYF(MY_WME)))) | |
flags&= ~VIO_BUFFERED_READ; | |
#ifdef __WIN__ | |
if (type == VIO_TYPE_NAMEDPIPE) | |
{ | |
vio->viodelete =vio_delete; | |
vio->vioerrno =vio_errno; | |
vio->read =vio_read_pipe; | |
vio->write =vio_write_pipe; | |
vio->fastsend =vio_fastsend; | |
vio->viokeepalive =vio_keepalive; | |
vio->should_retry =vio_should_retry; | |
vio->was_interrupted=vio_was_interrupted; | |
vio->vioclose =vio_close_pipe; | |
vio->peer_addr =vio_peer_addr; | |
vio->in_addr =vio_in_addr; | |
vio->vioblocking =vio_blocking; | |
vio->is_blocking =vio_is_blocking; | |
vio->timeout =vio_ignore_timeout; | |
} | |
else /* default is VIO_TYPE_TCPIP */ | |
#endif | |
#ifdef HAVE_SMEM | |
if (type == VIO_TYPE_SHARED_MEMORY) | |
{ | |
vio->viodelete =vio_delete; | |
vio->vioerrno =vio_errno; | |
vio->read =vio_read_shared_memory; | |
vio->write =vio_write_shared_memory; | |
vio->fastsend =vio_fastsend; | |
vio->viokeepalive =vio_keepalive; | |
vio->should_retry =vio_should_retry; | |
vio->was_interrupted=vio_was_interrupted; | |
vio->vioclose =vio_close_shared_memory; | |
vio->peer_addr =vio_peer_addr; | |
vio->in_addr =vio_in_addr; | |
vio->vioblocking =vio_blocking; | |
vio->is_blocking =vio_is_blocking; | |
vio->timeout =vio_ignore_timeout; | |
} | |
else | |
#endif | |
#ifdef HAVE_OPENSSL | |
if (type == VIO_TYPE_SSL) | |
{ | |
vio->viodelete =vio_ssl_delete; | |
vio->vioerrno =vio_errno; | |
vio->read =vio_ssl_read; | |
vio->write =vio_ssl_write; | |
vio->fastsend =vio_fastsend; | |
vio->viokeepalive =vio_keepalive; | |
vio->should_retry =vio_should_retry; | |
vio->was_interrupted=vio_was_interrupted; | |
vio->vioclose =vio_ssl_close; | |
vio->peer_addr =vio_peer_addr; | |
vio->in_addr =vio_in_addr; | |
vio->vioblocking =vio_ssl_blocking; | |
vio->is_blocking =vio_is_blocking; | |
vio->timeout =vio_timeout; | |
} | |
else /* default is VIO_TYPE_TCPIP */ | |
#endif /* HAVE_OPENSSL */ | |
{ | |
vio->viodelete =vio_delete; | |
vio->vioerrno =vio_errno; | |
vio->read= (flags & VIO_BUFFERED_READ) ? vio_read_buff : vio_read; | |
vio->write =vio_write; | |
vio->fastsend =vio_fastsend; | |
vio->viokeepalive =vio_keepalive; | |
vio->should_retry =vio_should_retry; | |
vio->was_interrupted=vio_was_interrupted; | |
vio->vioclose =vio_close; | |
vio->peer_addr =vio_peer_addr; | |
vio->in_addr =vio_in_addr; | |
vio->vioblocking =vio_blocking; | |
vio->is_blocking =vio_is_blocking; | |
vio->timeout =vio_timeout; | |
} | |
DBUG_VOID_RETURN; | |
} | |
/* Reset initialized VIO to use with another transport type */ | |
void vio_reset(Vio* vio, enum enum_vio_type type, | |
my_socket sd, HANDLE hPipe, uint flags) | |
{ | |
my_free(vio->read_buffer, MYF(MY_ALLOW_ZERO_PTR)); | |
vio_init(vio, type, sd, hPipe, flags); | |
} | |
/* Open the socket or TCP/IP connection and read the fnctl() status */ | |
Vio *vio_new(my_socket sd, enum enum_vio_type type, uint flags) | |
{ | |
Vio *vio; | |
DBUG_ENTER("vio_new"); | |
DBUG_PRINT("enter", ("sd: %d", sd)); | |
if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME)))) | |
{ | |
vio_init(vio, type, sd, 0, flags); | |
sprintf(vio->desc, | |
(vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"), | |
vio->sd); | |
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) | |
#if !defined(NO_FCNTL_NONBLOCK) | |
/* | |
We call fcntl() to set the flags and then immediately read them back | |
to make sure that we and the system are in agreement on the state of | |
things. | |
An example of why we need to do this is FreeBSD (and apparently some | |
other BSD-derived systems, like Mac OS X), where the system sometimes | |
reports that the socket is set for non-blocking when it really will | |
block. | |
*/ | |
fcntl(sd, F_SETFL, 0); | |
vio->fcntl_mode= fcntl(sd, F_GETFL); | |
#elif defined(HAVE_SYS_IOCTL_H) /* hpux */ | |
/* Non blocking sockets doesn't work good on HPUX 11.0 */ | |
(void) ioctl(sd,FIOSNBIO,0); | |
vio->fcntl_mode &= ~O_NONBLOCK; | |
#endif | |
#else /* !defined(__WIN__) && !defined(__EMX__) */ | |
{ | |
/* set to blocking mode by default */ | |
ulong arg=0, r; | |
r = ioctlsocket(sd,FIONBIO,(void*) &arg); | |
vio->fcntl_mode &= ~O_NONBLOCK; | |
} | |
#endif | |
} | |
DBUG_RETURN(vio); | |
} | |
#ifdef __WIN__ | |
Vio *vio_new_win32pipe(HANDLE hPipe) | |
{ | |
Vio *vio; | |
DBUG_ENTER("vio_new_handle"); | |
if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME)))) | |
{ | |
vio_init(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, VIO_LOCALHOST); | |
strmov(vio->desc, "named pipe"); | |
} | |
DBUG_RETURN(vio); | |
} | |
#ifdef HAVE_SMEM | |
Vio *vio_new_win32shared_memory(NET *net,HANDLE handle_file_map, HANDLE handle_map, | |
HANDLE event_server_wrote, HANDLE event_server_read, | |
HANDLE event_client_wrote, HANDLE event_client_read, | |
HANDLE event_conn_closed) | |
{ | |
Vio *vio; | |
DBUG_ENTER("vio_new_win32shared_memory"); | |
if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME)))) | |
{ | |
vio_init(vio, VIO_TYPE_SHARED_MEMORY, 0, 0, VIO_LOCALHOST); | |
vio->handle_file_map= handle_file_map; | |
vio->handle_map= handle_map; | |
vio->event_server_wrote= event_server_wrote; | |
vio->event_server_read= event_server_read; | |
vio->event_client_wrote= event_client_wrote; | |
vio->event_client_read= event_client_read; | |
vio->event_conn_closed= event_conn_closed; | |
vio->shared_memory_remain= 0; | |
vio->shared_memory_pos= handle_map; | |
vio->net= net; | |
strmov(vio->desc, "shared memory"); | |
} | |
DBUG_RETURN(vio); | |
} | |
#endif | |
#endif | |
void vio_delete(Vio* vio) | |
{ | |
if (!vio) | |
return; /* It must be safe to delete null pointers. */ | |
if (vio->type != VIO_CLOSED) | |
vio->vioclose(vio); | |
my_free((gptr) vio->read_buffer, MYF(MY_ALLOW_ZERO_PTR)); | |
my_free((gptr) vio,MYF(0)); | |
} | |
/* | |
Cleanup memory allocated by vio or the | |
components below it when application finish | |
*/ | |
void vio_end(void) | |
{ | |
#ifdef HAVE_YASSL | |
yaSSL_CleanUp(); | |
#endif | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* <MYSQL_ROOT>/vio/viosocket.c */ | |
/* Copyright (C) 2000 MySQL AB | |
This program is free software; you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation; version 2 of the License. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program; if not, write to the Free Software | |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | |
/* | |
Note that we can't have assertion on file descriptors; The reason for | |
this is that during mysql shutdown, another thread can close a file | |
we are working on. In this case we should just return read errors from | |
the file descriptior. | |
*/ | |
#include "vio_priv.h" | |
int vio_errno(Vio *vio __attribute__((unused))) | |
{ | |
return socket_errno; /* On Win32 this mapped to WSAGetLastError() */ | |
} | |
int vio_read(Vio * vio, gptr buf, int size) | |
{ | |
int r; | |
DBUG_ENTER("vio_read"); | |
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size)); | |
/* Ensure nobody uses vio_read_buff and vio_read simultaneously */ | |
DBUG_ASSERT(vio->read_end == vio->read_pos); | |
#ifdef __WIN__ | |
r = recv(vio->sd, buf, size,0); | |
#else | |
errno=0; /* For linux */ | |
r = read(vio->sd, buf, size); | |
#endif /* __WIN__ */ | |
#ifndef DBUG_OFF | |
if (r < 0) | |
{ | |
DBUG_PRINT("vio_error", ("Got error %d during read",errno)); | |
} | |
#endif /* DBUG_OFF */ | |
DBUG_PRINT("exit", ("%d", r)); | |
DBUG_RETURN(r); | |
} | |
/* | |
Buffered read: if average read size is small it may | |
reduce number of syscalls. | |
*/ | |
int vio_read_buff(Vio *vio, gptr buf, int size) | |
{ | |
int rc; | |
#define VIO_UNBUFFERED_READ_MIN_SIZE 2048 | |
DBUG_ENTER("vio_read_buff"); | |
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size)); | |
if (vio->read_pos < vio->read_end) | |
{ | |
rc= min(vio->read_end - vio->read_pos, size); | |
memcpy(buf, vio->read_pos, rc); | |
vio->read_pos+= rc; | |
/* | |
Do not try to read from the socket now even if rc < size: | |
vio_read can return -1 due to an error or non-blocking mode, and | |
the safest way to handle it is to move to a separate branch. | |
*/ | |
} | |
else if (size < VIO_UNBUFFERED_READ_MIN_SIZE) | |
{ | |
rc= vio_read(vio, vio->read_buffer, VIO_READ_BUFFER_SIZE); | |
if (rc > 0) | |
{ | |
if (rc > size) | |
{ | |
vio->read_pos= vio->read_buffer + size; | |
vio->read_end= vio->read_buffer + rc; | |
rc= size; | |
} | |
memcpy(buf, vio->read_buffer, rc); | |
} | |
} | |
else | |
rc= vio_read(vio, buf, size); | |
DBUG_RETURN(rc); | |
#undef VIO_UNBUFFERED_READ_MIN_SIZE | |
} | |
int vio_write(Vio * vio, const gptr buf, int size) | |
{ | |
int r; | |
DBUG_ENTER("vio_write"); | |
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, (long) buf, size)); | |
#ifdef __WIN__ | |
r = send(vio->sd, buf, size,0); | |
#else | |
r = write(vio->sd, buf, size); | |
#endif /* __WIN__ */ | |
#ifndef DBUG_OFF | |
if (r < 0) | |
{ | |
DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno)); | |
} | |
#endif /* DBUG_OFF */ | |
DBUG_PRINT("exit", ("%d", r)); | |
DBUG_RETURN(r); | |
} | |
int vio_blocking(Vio * vio __attribute__((unused)), my_bool set_blocking_mode, | |
my_bool *old_mode) | |
{ | |
int r=0; | |
DBUG_ENTER("vio_blocking"); | |
*old_mode= test(!(vio->fcntl_mode & O_NONBLOCK)); | |
DBUG_PRINT("enter", ("set_blocking_mode: %d old_mode: %d", | |
(int) set_blocking_mode, (int) *old_mode)); | |
#if !defined(__WIN__) && !defined(__EMX__) | |
#if !defined(NO_FCNTL_NONBLOCK) | |
if (vio->sd >= 0) | |
{ | |
int old_fcntl=vio->fcntl_mode; | |
if (set_blocking_mode) | |
vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */ | |
else | |
vio->fcntl_mode |= O_NONBLOCK; /* set bit */ | |
if (old_fcntl != vio->fcntl_mode) | |
{ | |
r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode); | |
if (r == -1) | |
{ | |
DBUG_PRINT("info", ("fcntl failed, errno %d", errno)); | |
vio->fcntl_mode= old_fcntl; | |
} | |
} | |
} | |
#else | |
r= set_blocking_mode ? 0 : 1; | |
#endif /* !defined(NO_FCNTL_NONBLOCK) */ | |
#else /* !defined(__WIN__) && !defined(__EMX__) */ | |
#ifndef __EMX__ | |
if (vio->type != VIO_TYPE_NAMEDPIPE && vio->type != VIO_TYPE_SHARED_MEMORY) | |
#endif | |
{ | |
ulong arg; | |
int old_fcntl=vio->fcntl_mode; | |
if (set_blocking_mode) | |
{ | |
arg = 0; | |
vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */ | |
} | |
else | |
{ | |
arg = 1; | |
vio->fcntl_mode |= O_NONBLOCK; /* set bit */ | |
} | |
if (old_fcntl != vio->fcntl_mode) | |
r = ioctlsocket(vio->sd,FIONBIO,(void*) &arg); | |
} | |
#ifndef __EMX__ | |
else | |
r= test(!(vio->fcntl_mode & O_NONBLOCK)) != set_blocking_mode; | |
#endif /* __EMX__ */ | |
#endif /* !defined(__WIN__) && !defined(__EMX__) */ | |
DBUG_PRINT("exit", ("%d", r)); | |
DBUG_RETURN(r); | |
} | |
my_bool | |
vio_is_blocking(Vio * vio) | |
{ | |
my_bool r; | |
DBUG_ENTER("vio_is_blocking"); | |
r = !(vio->fcntl_mode & O_NONBLOCK); | |
DBUG_PRINT("exit", ("%d", (int) r)); | |
DBUG_RETURN(r); | |
} | |
int vio_fastsend(Vio * vio __attribute__((unused))) | |
{ | |
int r=0; | |
DBUG_ENTER("vio_fastsend"); | |
#if defined(IPTOS_THROUGHPUT) && !defined(__EMX__) | |
{ | |
int tos = IPTOS_THROUGHPUT; | |
r= setsockopt(vio->sd, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof(tos)); | |
} | |
#endif /* IPTOS_THROUGHPUT && !__EMX__ */ | |
if (!r) | |
{ | |
#ifdef __WIN__ | |
BOOL nodelay= 1; | |
#else | |
int nodelay = 1; | |
#endif | |
r= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY, | |
IF_WIN(const char*, void*) &nodelay, | |
sizeof(nodelay)); | |
} | |
if (r) | |
{ | |
DBUG_PRINT("warning", ("Couldn't set socket option for fast send")); | |
r= -1; | |
} | |
DBUG_PRINT("exit", ("%d", r)); | |
DBUG_RETURN(r); | |
} | |
int vio_keepalive(Vio* vio, my_bool set_keep_alive) | |
{ | |
int r=0; | |
uint opt = 0; | |
DBUG_ENTER("vio_keepalive"); | |
DBUG_PRINT("enter", ("sd: %d set_keep_alive: %d", vio->sd, (int) | |
set_keep_alive)); | |
if (vio->type != VIO_TYPE_NAMEDPIPE) | |
{ | |
if (set_keep_alive) | |
opt = 1; | |
r = setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, | |
sizeof(opt)); | |
} | |
DBUG_RETURN(r); | |
} | |
my_bool | |
vio_should_retry(Vio * vio __attribute__((unused))) | |
{ | |
int en = socket_errno; | |
return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || | |
en == SOCKET_EWOULDBLOCK); | |
} | |
my_bool | |
vio_was_interrupted(Vio *vio __attribute__((unused))) | |
{ | |
int en= socket_errno; | |
return (en == SOCKET_EAGAIN || en == SOCKET_EINTR || | |
en == SOCKET_EWOULDBLOCK || en == SOCKET_ETIMEDOUT); | |
} | |
int vio_close(Vio * vio) | |
{ | |
int r=0; | |
DBUG_ENTER("vio_close"); | |
#ifdef __WIN__ | |
if (vio->type == VIO_TYPE_NAMEDPIPE) | |
{ | |
#if defined(__NT__) && defined(MYSQL_SERVER) | |
CancelIo(vio->hPipe); | |
DisconnectNamedPipe(vio->hPipe); | |
#endif | |
r=CloseHandle(vio->hPipe); | |
} | |
else | |
#endif /* __WIN__ */ | |
if (vio->type != VIO_CLOSED) | |
{ | |
DBUG_ASSERT(vio->sd >= 0); | |
if (shutdown(vio->sd, SHUT_RDWR)) | |
r= -1; | |
if (closesocket(vio->sd)) | |
r= -1; | |
} | |
if (r) | |
{ | |
DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno)); | |
/* FIXME: error handling (not critical for MySQL) */ | |
} | |
vio->type= VIO_CLOSED; | |
vio->sd= -1; | |
DBUG_RETURN(r); | |
} | |
const char *vio_description(Vio * vio) | |
{ | |
return vio->desc; | |
} | |
enum enum_vio_type vio_type(Vio* vio) | |
{ | |
return vio->type; | |
} | |
my_socket vio_fd(Vio* vio) | |
{ | |
return vio->sd; | |
} | |
my_bool vio_peer_addr(Vio * vio, char *buf, uint16 *port) | |
{ | |
DBUG_ENTER("vio_peer_addr"); | |
DBUG_PRINT("enter", ("sd: %d", vio->sd)); | |
if (vio->localhost) | |
{ | |
strmov(buf,"127.0.0.1"); | |
*port= 0; | |
} | |
else | |
{ | |
size_socket addrLen = sizeof(vio->remote); | |
if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote), | |
&addrLen) != 0) | |
{ | |
DBUG_PRINT("exit", ("getpeername gave error: %d", socket_errno)); | |
DBUG_RETURN(1); | |
} | |
my_inet_ntoa(vio->remote.sin_addr,buf); | |
*port= ntohs(vio->remote.sin_port); | |
} | |
DBUG_PRINT("exit", ("addr: %s", buf)); | |
DBUG_RETURN(0); | |
} | |
/* | |
Get in_addr for a TCP/IP connection | |
SYNOPSIS | |
vio_in_addr() | |
vio vio handle | |
in put in_addr here | |
NOTES | |
one must call vio_peer_addr() before calling this one | |
*/ | |
void vio_in_addr(Vio *vio, struct in_addr *in) | |
{ | |
DBUG_ENTER("vio_in_addr"); | |
if (vio->localhost) | |
bzero((char*) in, sizeof(*in)); | |
else | |
*in=vio->remote.sin_addr; | |
DBUG_VOID_RETURN; | |
} | |
/* Return 0 if there is data to be read */ | |
my_bool vio_poll_read(Vio *vio,uint timeout) | |
{ | |
#ifndef HAVE_POLL | |
return 0; | |
#else | |
struct pollfd fds; | |
int res; | |
DBUG_ENTER("vio_poll"); | |
fds.fd=vio->sd; | |
fds.events=POLLIN; | |
fds.revents=0; | |
if ((res=poll(&fds,1,(int) timeout*1000)) <= 0) | |
{ | |
DBUG_RETURN(res < 0 ? 0 : 1); /* Don't return 1 on errors */ | |
} | |
DBUG_RETURN(fds.revents & POLLIN ? 0 : 1); | |
#endif | |
} | |
void vio_timeout(Vio *vio, uint which, uint timeout) | |
{ | |
#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO) | |
int r; | |
DBUG_ENTER("vio_timeout"); | |
{ | |
#ifdef __WIN__ | |
/* Windows expects time in milliseconds as int */ | |
int wait_timeout= (int) timeout * 1000; | |
#else | |
/* POSIX specifies time as struct timeval. */ | |
struct timeval wait_timeout; | |
wait_timeout.tv_sec= timeout; | |
wait_timeout.tv_usec= 0; | |
#endif | |
r= setsockopt(vio->sd, SOL_SOCKET, which ? SO_SNDTIMEO : SO_RCVTIMEO, | |
IF_WIN(const char*, const void*)&wait_timeout, | |
sizeof(wait_timeout)); | |
} | |
#ifndef DBUG_OFF | |
if (r != 0) | |
DBUG_PRINT("error", ("setsockopt failed: %d, errno: %d", r, socket_errno)); | |
#endif | |
DBUG_VOID_RETURN; | |
#else | |
/* | |
Platforms not suporting setting of socket timeout should either use | |
thr_alarm or just run without read/write timeout(s) | |
*/ | |
#endif | |
} | |
#ifdef __WIN__ | |
int vio_read_pipe(Vio * vio, gptr buf, int size) | |
{ | |
DWORD length; | |
DBUG_ENTER("vio_read_pipe"); | |
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size)); | |
if (!ReadFile(vio->hPipe, buf, size, &length, NULL)) | |
DBUG_RETURN(-1); | |
DBUG_PRINT("exit", ("%d", length)); | |
DBUG_RETURN(length); | |
} | |
int vio_write_pipe(Vio * vio, const gptr buf, int size) | |
{ | |
DWORD length; | |
DBUG_ENTER("vio_write_pipe"); | |
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size)); | |
if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL)) | |
DBUG_RETURN(-1); | |
DBUG_PRINT("exit", ("%d", length)); | |
DBUG_RETURN(length); | |
} | |
int vio_close_pipe(Vio * vio) | |
{ | |
int r; | |
DBUG_ENTER("vio_close_pipe"); | |
#if defined(__NT__) && defined(MYSQL_SERVER) | |
CancelIo(vio->hPipe); | |
DisconnectNamedPipe(vio->hPipe); | |
#endif | |
r=CloseHandle(vio->hPipe); | |
if (r) | |
{ | |
DBUG_PRINT("vio_error", ("close() failed, error: %d",GetLastError())); | |
/* FIXME: error handling (not critical for MySQL) */ | |
} | |
vio->type= VIO_CLOSED; | |
vio->sd= -1; | |
DBUG_RETURN(r); | |
} | |
void vio_ignore_timeout(Vio *vio __attribute__((unused)), | |
uint which __attribute__((unused)), | |
uint timeout __attribute__((unused))) | |
{ | |
} | |
#ifdef HAVE_SMEM | |
int vio_read_shared_memory(Vio * vio, gptr buf, int size) | |
{ | |
int length; | |
int remain_local; | |
char *current_postion; | |
DBUG_ENTER("vio_read_shared_memory"); | |
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size)); | |
remain_local = size; | |
current_postion=buf; | |
do | |
{ | |
if (vio->shared_memory_remain == 0) | |
{ | |
HANDLE events[2]; | |
events[0]= vio->event_server_wrote; | |
events[1]= vio->event_conn_closed; | |
/* | |
WaitForMultipleObjects can return next values: | |
WAIT_OBJECT_0+0 - event from vio->event_server_wrote | |
WAIT_OBJECT_0+1 - event from vio->event_conn_closed. We can't read anything | |
WAIT_ABANDONED_0 and WAIT_TIMEOUT - fail. We can't read anything | |
*/ | |
if (WaitForMultipleObjects(2, (HANDLE*)&events,FALSE, | |
vio->net->read_timeout*1000) != WAIT_OBJECT_0) | |
{ | |
DBUG_RETURN(-1); | |
}; | |
vio->shared_memory_pos = vio->handle_map; | |
vio->shared_memory_remain = uint4korr((ulong*)vio->shared_memory_pos); | |
vio->shared_memory_pos+=4; | |
} | |
length = size; | |
if (vio->shared_memory_remain < length) | |
length = vio->shared_memory_remain; | |
if (length > remain_local) | |
length = remain_local; | |
memcpy(current_postion,vio->shared_memory_pos,length); | |
vio->shared_memory_remain-=length; | |
vio->shared_memory_pos+=length; | |
current_postion+=length; | |
remain_local-=length; | |
if (!vio->shared_memory_remain) | |
if (!SetEvent(vio->event_client_read)) DBUG_RETURN(-1); | |
} while (remain_local); | |
length = size; | |
DBUG_PRINT("exit", ("%d", length)); | |
DBUG_RETURN(length); | |
} | |
int vio_write_shared_memory(Vio * vio, const gptr buf, int size) | |
{ | |
int length; | |
uint remain; | |
HANDLE pos; | |
int sz; | |
char *current_postion; | |
DBUG_ENTER("vio_write_shared_memory"); | |
DBUG_PRINT("enter", ("sd: %d buf: 0x%lx size: %d", vio->sd, buf, size)); | |
remain = size; | |
current_postion = buf; | |
while (remain != 0) | |
{ | |
if (WaitForSingleObject(vio->event_server_read, vio->net->write_timeout*1000) | |
!= WAIT_OBJECT_0) | |
{ | |
DBUG_RETURN(-1); | |
}; | |
sz = remain > shared_memory_buffer_length ? shared_memory_buffer_length: remain; | |
int4store(vio->handle_map,sz); | |
pos = vio->handle_map + 4; | |
memcpy(pos,current_postion,sz); | |
remain-=sz; | |
current_postion+=sz; | |
if (!SetEvent(vio->event_client_wrote)) DBUG_RETURN(-1); | |
} | |
length = size; | |
DBUG_PRINT("exit", ("%d", length)); | |
DBUG_RETURN(length); | |
} | |
/** | |
Close shared memory and DBUG_PRINT any errors that happen on closing. | |
@return Zero if all closing functions succeed, and nonzero otherwise. | |
*/ | |
int vio_close_shared_memory(Vio * vio) | |
{ | |
int error_count= 0; | |
DBUG_ENTER("vio_close_shared_memory"); | |
if (vio->type != VIO_CLOSED) | |
{ | |
/* | |
Set event_conn_closed for notification of both client and server that | |
connection is closed | |
*/ | |
SetEvent(vio->event_conn_closed); | |
/* | |
Close all handlers. UnmapViewOfFile and CloseHandle return non-zero | |
result if they are success. | |
*/ | |
if (UnmapViewOfFile(vio->handle_map) == 0) | |
{ | |
error_count++; | |
DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed")); | |
} | |
if (CloseHandle(vio->event_server_wrote) == 0) | |
{ | |
error_count++; | |
DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed")); | |
} | |
if (CloseHandle(vio->event_server_read) == 0) | |
{ | |
error_count++; | |
DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed")); | |
} | |
if (CloseHandle(vio->event_client_wrote) == 0) | |
{ | |
error_count++; | |
DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed")); | |
} | |
if (CloseHandle(vio->event_client_read) == 0) | |
{ | |
error_count++; | |
DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed")); | |
} | |
if (CloseHandle(vio->handle_file_map) == 0) | |
{ | |
error_count++; | |
DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed")); | |
} | |
if (CloseHandle(vio->event_conn_closed) == 0) | |
{ | |
error_count++; | |
DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed")); | |
} | |
} | |
vio->type= VIO_CLOSED; | |
vio->sd= -1; | |
DBUG_RETURN(error_count); | |
} | |
#endif /* HAVE_SMEM */ | |
#endif /* __WIN__ */ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment