mirror of
https://github.com/MariaDB/server.git
synced 2026-05-15 03:17:20 +02:00
Backport of Bug#41860 to mysql-next-mr
------------------------------------------------------------ revno: 3317 revision-id: davi.arnaut@sun.com-20090522170916-fzc5ca3tjs9roy1t parent: patrick.crews@sun.com-20090522152933-ole8s3suy4zqyvku committer: Davi Arnaut <Davi.Arnaut@Sun.COM> branch nick: 41860-6.0 timestamp: Fri 2009-05-22 14:09:16 -0300 message: Bug#41860: Without Windows named pipe The problem was that the patch for Bug#10374 broke named pipe and shared memory transports on Windows due to a failure to implement a dummy poll method for transports other than BSD sockets. Another problem was that mysqltest lacked support for named pipe and shared memory connections, which lead to misleading test cases that were supposed run common queries over both transports. The solution is to properly implement, at the VIO layer, the poll and is_connected methods. The is_connected method is implemented for every suppported transport and the poll one only where it makes sense. Furthermore, support for named pipe and shared memory connections is added to mysqltest as to enable testing of both transports using the test suite. client/mysqltest.cc: Add support for named pipe and shared memory connections. include/violite.h: Move private functions to vio/vio_priv.h Add poll_read and is_connected methods. mysql-test/t/named_pipe.test: Run tests over a named pipe connection. mysql-test/t/shm.test: Run tests over a shared memory connection. sql/item_func.cc: Rename method. sql/sql_class.cc: Remove higher-level vio_is_connected implementation. sql/sql_class.h: Rename vio_is_connected to not conflict with the vio one. Verify that there is a valid vio. vio/vio.c: Add poll_read and is_connected methods. vio/vio_priv.h: Add private functions. vio/viosocket.c: Implement the is_connected method for the various transports.
This commit is contained in:
parent
80582b000f
commit
17871ade9a
10 changed files with 223 additions and 47 deletions
30
vio/vio.c
30
vio/vio.c
|
|
@ -22,6 +22,28 @@
|
|||
|
||||
#include "vio_priv.h"
|
||||
|
||||
#if defined(__WIN__) || defined(HAVE_SMEM)
|
||||
|
||||
/**
|
||||
Stub poll_read method that defaults to indicate that there
|
||||
is data to read.
|
||||
|
||||
Used for named pipe and shared memory VIO types.
|
||||
|
||||
@param vio Unused.
|
||||
@param timeout Unused.
|
||||
|
||||
@retval FALSE There is data to read.
|
||||
*/
|
||||
|
||||
static my_bool no_poll_read(Vio *vio __attribute__((unused)),
|
||||
uint timeout __attribute__((unused)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Helper to fill most of the Vio* with defaults.
|
||||
*/
|
||||
|
|
@ -60,6 +82,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
|
|||
vio->vioblocking =vio_blocking;
|
||||
vio->is_blocking =vio_is_blocking;
|
||||
vio->timeout =vio_ignore_timeout;
|
||||
vio->poll_read =no_poll_read;
|
||||
vio->is_connected =vio_is_connected_pipe;
|
||||
}
|
||||
else /* default is VIO_TYPE_TCPIP */
|
||||
#endif
|
||||
|
|
@ -80,6 +104,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
|
|||
vio->vioblocking =vio_blocking;
|
||||
vio->is_blocking =vio_is_blocking;
|
||||
vio->timeout =vio_ignore_timeout;
|
||||
vio->poll_read =no_poll_read;
|
||||
vio->is_connected =vio_is_connected_shared_memory;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
|
@ -100,6 +126,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
|
|||
vio->vioblocking =vio_ssl_blocking;
|
||||
vio->is_blocking =vio_is_blocking;
|
||||
vio->timeout =vio_timeout;
|
||||
vio->poll_read =vio_poll_read;
|
||||
vio->is_connected =vio_is_connected;
|
||||
}
|
||||
else /* default is VIO_TYPE_TCPIP */
|
||||
#endif /* HAVE_OPENSSL */
|
||||
|
|
@ -118,6 +146,8 @@ static void vio_init(Vio* vio, enum enum_vio_type type,
|
|||
vio->vioblocking =vio_blocking;
|
||||
vio->is_blocking =vio_is_blocking;
|
||||
vio->timeout =vio_timeout;
|
||||
vio->poll_read =vio_poll_read;
|
||||
vio->is_connected =vio_is_connected;
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,20 @@
|
|||
#include <m_string.h>
|
||||
#include <violite.h>
|
||||
|
||||
#ifdef __WIN__
|
||||
size_t vio_read_pipe(Vio *vio, uchar * buf, size_t size);
|
||||
size_t vio_write_pipe(Vio *vio, const uchar * buf, size_t size);
|
||||
my_bool vio_is_connected_pipe(Vio *vio);
|
||||
int vio_close_pipe(Vio * vio);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SMEM
|
||||
size_t vio_read_shared_memory(Vio *vio, uchar * buf, size_t size);
|
||||
size_t vio_write_shared_memory(Vio *vio, const uchar * buf, size_t size);
|
||||
my_bool vio_is_connected_shared_memory(Vio *vio);
|
||||
int vio_close_shared_memory(Vio * vio);
|
||||
#endif
|
||||
|
||||
void vio_ignore_timeout(Vio *vio, uint which, uint timeout);
|
||||
void vio_timeout(Vio *vio,uint which, uint timeout);
|
||||
|
||||
|
|
|
|||
123
vio/viosocket.c
123
vio/viosocket.c
|
|
@ -356,15 +356,26 @@ void vio_in_addr(Vio *vio, struct in_addr *in)
|
|||
}
|
||||
|
||||
|
||||
/* Return 0 if there is data to be read */
|
||||
/**
|
||||
Indicate whether there is data to read on a given socket.
|
||||
|
||||
my_bool vio_poll_read(Vio *vio,uint timeout)
|
||||
@note An exceptional condition event and/or errors are
|
||||
interpreted as if there is data to read.
|
||||
|
||||
@param sd A connected socket.
|
||||
@param timeout Maximum time in seconds to poll.
|
||||
|
||||
@retval FALSE There is data to read.
|
||||
@retval TRUE There is no data to read.
|
||||
*/
|
||||
|
||||
static my_bool socket_poll_read(my_socket sd, uint timeout)
|
||||
{
|
||||
#ifdef __WIN__
|
||||
int res, fd= vio->sd;
|
||||
my_socket fd= sd;
|
||||
fd_set readfds, errorfds;
|
||||
struct timeval tm;
|
||||
DBUG_ENTER("vio_poll");
|
||||
DBUG_ENTER("socket_poll_read");
|
||||
tm.tv_sec= timeout;
|
||||
tm.tv_usec= 0;
|
||||
FD_ZERO(&readfds);
|
||||
|
|
@ -380,8 +391,8 @@ my_bool vio_poll_read(Vio *vio,uint timeout)
|
|||
#elif defined(HAVE_POLL)
|
||||
struct pollfd fds;
|
||||
int res;
|
||||
DBUG_ENTER("vio_poll");
|
||||
fds.fd=vio->sd;
|
||||
DBUG_ENTER("socket_poll_read");
|
||||
fds.fd=sd;
|
||||
fds.events=POLLIN;
|
||||
fds.revents=0;
|
||||
if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
|
||||
|
|
@ -395,7 +406,17 @@ my_bool vio_poll_read(Vio *vio,uint timeout)
|
|||
}
|
||||
|
||||
|
||||
my_bool vio_peek_read(Vio *vio, uint *bytes)
|
||||
/**
|
||||
Retrieve the amount of data that can be read from a socket.
|
||||
|
||||
@param vio A VIO object.
|
||||
@param bytes[out] The amount of bytes available.
|
||||
|
||||
@retval FALSE Success.
|
||||
@retval TRUE Failure.
|
||||
*/
|
||||
|
||||
static my_bool socket_peek_read(Vio *vio, uint *bytes)
|
||||
{
|
||||
#ifdef __WIN__
|
||||
int len;
|
||||
|
|
@ -419,6 +440,78 @@ my_bool vio_peek_read(Vio *vio, uint *bytes)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Indicate whether there is data to read on a given socket.
|
||||
|
||||
@remark Errors are interpreted as if there is data to read.
|
||||
|
||||
@param sd A connected socket.
|
||||
@param timeout Maximum time in seconds to wait.
|
||||
|
||||
@retval FALSE There is data (or EOF) to read. Also FALSE if error.
|
||||
@retval TRUE There is _NO_ data to read or timed out.
|
||||
*/
|
||||
|
||||
my_bool vio_poll_read(Vio *vio, uint timeout)
|
||||
{
|
||||
my_socket sd= vio->sd;
|
||||
DBUG_ENTER("vio_poll_read");
|
||||
#ifdef HAVE_OPENSSL
|
||||
if (vio->type == VIO_TYPE_SSL)
|
||||
sd= SSL_get_fd((SSL*) vio->ssl_arg);
|
||||
#endif
|
||||
DBUG_RETURN(socket_poll_read(sd, timeout));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Determine if the endpoint of a connection is still available.
|
||||
|
||||
@remark The socket is assumed to be disconnected if an EOF
|
||||
condition is encountered.
|
||||
|
||||
@param vio The VIO object.
|
||||
|
||||
@retval TRUE EOF condition not found.
|
||||
@retval FALSE EOF condition is signaled.
|
||||
*/
|
||||
|
||||
my_bool vio_is_connected(Vio *vio)
|
||||
{
|
||||
uint bytes= 0;
|
||||
DBUG_ENTER("vio_is_connected");
|
||||
|
||||
/* In the presence of errors the socket is assumed to be connected. */
|
||||
|
||||
/*
|
||||
The first step of detecting a EOF condition is veryfing
|
||||
whether there is data to read. Data in this case would
|
||||
be the EOF.
|
||||
*/
|
||||
if (vio_poll_read(vio, 0))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/*
|
||||
The second step is read() or recv() from the socket returning
|
||||
0 (EOF). Unfortunelly, it's not possible to call read directly
|
||||
as we could inadvertently read meaningful connection data.
|
||||
Simulate a read by retrieving the number of bytes available to
|
||||
read -- 0 meaning EOF.
|
||||
*/
|
||||
if (socket_peek_read(vio, &bytes))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
/* There might be buffered data at the SSL layer. */
|
||||
if (!bytes && vio->type == VIO_TYPE_SSL)
|
||||
bytes= SSL_pending((SSL*) vio->ssl_arg);
|
||||
#endif
|
||||
|
||||
DBUG_RETURN(bytes ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
|
||||
void vio_timeout(Vio *vio, uint which, uint timeout)
|
||||
{
|
||||
#if defined(SO_SNDTIMEO) && defined(SO_RCVTIMEO)
|
||||
|
|
@ -487,6 +580,16 @@ size_t vio_write_pipe(Vio * vio, const uchar* buf, size_t size)
|
|||
DBUG_RETURN((size_t) length);
|
||||
}
|
||||
|
||||
|
||||
my_bool vio_is_connected_pipe(Vio *vio)
|
||||
{
|
||||
if (PeekNamedPipe(vio->hPipe, NULL, 0, NULL, NULL, NULL))
|
||||
return TRUE;
|
||||
else
|
||||
return (GetLastError() != ERROR_BROKEN_PIPE);
|
||||
}
|
||||
|
||||
|
||||
int vio_close_pipe(Vio * vio)
|
||||
{
|
||||
int r;
|
||||
|
|
@ -625,6 +728,12 @@ size_t vio_write_shared_memory(Vio * vio, const uchar* buf, size_t size)
|
|||
}
|
||||
|
||||
|
||||
my_bool vio_is_connected_shared_memory(Vio *vio)
|
||||
{
|
||||
return (WaitForSingleObject(vio->event_conn_closed, 0) != WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Close shared memory and DBUG_PRINT any errors that happen on closing.
|
||||
@return Zero if all closing functions succeed, and nonzero otherwise.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue