summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/mysqltest.cc38
-rw-r--r--include/violite.h17
-rw-r--r--mysql-test/t/named_pipe.test5
-rw-r--r--mysql-test/t/shm.test10
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/sql_class.cc24
-rw-r--r--sql/sql_class.h7
-rw-r--r--vio/vio.c30
-rw-r--r--vio/vio_priv.h14
-rw-r--r--vio/viosocket.c123
10 files changed, 223 insertions, 47 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index b62d101e884..93e6e58e221 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -4859,6 +4859,8 @@ do_handle_error:
<opts> - options to use for the connection
* SSL - use SSL if available
* COMPRESS - use compression if available
+ * SHM - use shared memory if available
+ * PIPE - use named pipe if available
*/
@@ -4867,6 +4869,7 @@ void do_connect(struct st_command *command)
int con_port= opt_port;
char *con_options;
my_bool con_ssl= 0, con_compress= 0;
+ my_bool con_pipe= 0, con_shm= 0;
struct st_connection* con_slot;
static DYNAMIC_STRING ds_connection_name;
@@ -4877,6 +4880,9 @@ void do_connect(struct st_command *command)
static DYNAMIC_STRING ds_port;
static DYNAMIC_STRING ds_sock;
static DYNAMIC_STRING ds_options;
+#ifdef HAVE_SMEM
+ static DYNAMIC_STRING ds_shm;
+#endif
const struct command_arg connect_args[] = {
{ "connection name", ARG_STRING, TRUE, &ds_connection_name, "Name of the connection" },
{ "host", ARG_STRING, TRUE, &ds_host, "Host to connect to" },
@@ -4904,6 +4910,11 @@ void do_connect(struct st_command *command)
die("Illegal argument for port: '%s'", ds_port.str);
}
+#ifdef HAVE_SMEM
+ /* Shared memory */
+ init_dynamic_string(&ds_shm, ds_sock.str, 0, 0);
+#endif
+
/* Sock */
if (ds_sock.length)
{
@@ -4942,6 +4953,10 @@ void do_connect(struct st_command *command)
con_ssl= 1;
else if (!strncmp(con_options, "COMPRESS", 8))
con_compress= 1;
+ else if (!strncmp(con_options, "PIPE", 4))
+ con_pipe= 1;
+ else if (!strncmp(con_options, "SHM", 3))
+ con_shm= 1;
else
die("Illegal option to connect: %.*s",
(int) (end - con_options), con_options);
@@ -4994,6 +5009,26 @@ void do_connect(struct st_command *command)
}
#endif
+#ifdef __WIN__
+ if (con_pipe)
+ {
+ uint protocol= MYSQL_PROTOCOL_PIPE;
+ mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, &protocol);
+ }
+#endif
+
+#ifdef HAVE_SMEM
+ if (con_shm)
+ {
+ uint protocol= MYSQL_PROTOCOL_MEMORY;
+ if (!ds_shm.length)
+ die("Missing shared memory base name");
+ mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, &protocol);
+ mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, ds_shm.str);
+ }
+#endif
+
+
/* Use default db name */
if (ds_database.length == 0)
dynstr_set(&ds_database, opt_db);
@@ -5026,6 +5061,9 @@ void do_connect(struct st_command *command)
dynstr_free(&ds_port);
dynstr_free(&ds_sock);
dynstr_free(&ds_options);
+#ifdef HAVE_SMEM
+ dynstr_free(&ds_shm);
+#endif
DBUG_VOID_RETURN;
}
diff --git a/include/violite.h b/include/violite.h
index 0e07e1c69ca..395feb4e0df 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -51,9 +51,6 @@ Vio* vio_new_win32shared_memory(NET *net,HANDLE handle_file_map,
HANDLE event_client_wrote,
HANDLE event_client_read,
HANDLE event_conn_closed);
-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);
-int vio_close_pipe(Vio * vio);
#else
#define HANDLE void *
#endif /* __WIN__ */
@@ -87,8 +84,8 @@ my_socket vio_fd(Vio*vio);
my_bool vio_peer_addr(Vio* vio, char *buf, uint16 *port);
/* Remotes in_addr */
void vio_in_addr(Vio *vio, struct in_addr *in);
-my_bool vio_poll_read(Vio *vio,uint timeout);
-my_bool vio_peek_read(Vio *vio, uint *bytes);
+my_bool vio_poll_read(Vio *vio, uint timeout);
+my_bool vio_is_connected(Vio *vio);
#ifdef HAVE_OPENSSL
#include <openssl/opensslv.h>
@@ -137,12 +134,6 @@ struct st_VioSSLFd
void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd);
#endif /* HAVE_OPENSSL */
-#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);
-int vio_close_shared_memory(Vio * vio);
-#endif
-
void vio_end(void);
#ifdef __cplusplus
@@ -165,6 +156,8 @@ void vio_end(void);
#define vio_peer_addr(vio, buf, prt) (vio)->peer_addr(vio, buf, prt)
#define vio_in_addr(vio, in) (vio)->in_addr(vio, in)
#define vio_timeout(vio, which, seconds) (vio)->timeout(vio, which, seconds)
+#define vio_poll_read(vio, timeout) (vio)->poll_read(vio, timeout)
+#define vio_is_connected(vio) (vio)->is_connected(vio)
#endif /* !defined(DONT_MAP_VIO) */
/* This enumerator is used in parser - should be always visible */
@@ -209,6 +202,8 @@ struct st_vio
my_bool (*was_interrupted)(Vio*);
int (*vioclose)(Vio*);
void (*timeout)(Vio*, unsigned int which, unsigned int timeout);
+ my_bool (*poll_read)(Vio *vio, uint timeout);
+ my_bool (*is_connected)(Vio*);
#ifdef HAVE_OPENSSL
void *ssl_arg;
#endif
diff --git a/mysql-test/t/named_pipe.test b/mysql-test/t/named_pipe.test
index e3dfd24bb52..e88fd8e1ef8 100644
--- a/mysql-test/t/named_pipe.test
+++ b/mysql-test/t/named_pipe.test
@@ -9,6 +9,11 @@ if (`SELECT '$nmp' != 'ON'`){
skip No named pipe support;
}
+# Connect using named pipe for testing
+connect(pipe_con,localhost,root,,,,,PIPE);
+
# Source select test case
-- source include/common-tests.inc
+connection default;
+disconnect pipe_con;
diff --git a/mysql-test/t/shm.test b/mysql-test/t/shm.test
index 88e96ae7b45..567caa4989a 100644
--- a/mysql-test/t/shm.test
+++ b/mysql-test/t/shm.test
@@ -7,10 +7,17 @@ let $shm= query_get_value("SHOW VARIABLES LIKE 'shared_memory'", Value, 1);
if (`SELECT '$shm' != 'ON'`){
skip No shm support;
}
+let $shm_name= query_get_value("SHOW GLOBAL VARIABLES LIKE 'shared_memory_base_name'", Value, 1);
+
+# Connect using SHM for testing
+connect(shm_con,localhost,root,,,,$shm_name,SHM);
# Source select test case
-- source include/common-tests.inc
+connection default;
+disconnect shm_con;
+
#
# Bug #24924: shared-memory-base-name that is too long causes buffer overflow
#
@@ -20,7 +27,6 @@ if (`SELECT '$shm' != 'ON'`){
# Bug #33899: Deadlock in mysql_real_query with shared memory connections
#
-let $name= query_get_value("SHOW GLOBAL VARIABLES LIKE 'shared_memory_base_name'", Value, 1);
let $stmt= `SELECT REPEAT('a', 2048)`;
SET @max_allowed_packet= @@global.max_allowed_packet;
@@ -30,7 +36,7 @@ SET GLOBAL max_allowed_packet= 1024;
SET GLOBAL net_buffer_length= 1024;
--error 1
---exec echo SELECT '$stmt'| $MYSQL --protocol=memory --shared-memory-base-name=$name 2>&1
+--exec echo SELECT '$stmt'| $MYSQL --protocol=memory --shared-memory-base-name=$shm_name 2>&1
SET GLOBAL max_allowed_packet= @max_allowed_packet;
SET GLOBAL net_buffer_length= @net_buffer_length;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 8f2739f8e77..c466dcc5cb9 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3471,7 +3471,7 @@ static int interruptible_wait(THD *thd, pthread_cond_t *cond,
if (error == ETIMEDOUT || error == ETIME)
{
/* Return error if timed out or connection is broken. */
- if (!timeout || !thd->vio_is_connected())
+ if (!timeout || !thd->is_connected())
break;
}
} while (error && timeout);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index e765d892884..212d727b7f1 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1618,30 +1618,6 @@ void THD::rollback_item_tree_changes()
}
-#ifndef EMBEDDED_LIBRARY
-
-/**
- Check that the endpoint is still available.
-*/
-
-bool THD::vio_is_connected()
-{
- uint bytes= 0;
-
- /* End of input is signaled by poll if the socket is aborted. */
- if (vio_poll_read(net.vio, 0))
- return TRUE;
-
- /* Socket is aborted if signaled but no data is available. */
- if (vio_peek_read(net.vio, &bytes))
- return TRUE;
-
- return bytes ? TRUE : FALSE;
-}
-
-#endif
-
-
/*****************************************************************************
** Functions to provide a interface to select results
*****************************************************************************/
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 5117304a26f..87dcf361aa3 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1962,11 +1962,14 @@ public:
}
inline bool vio_ok() const { return net.vio != 0; }
/** Return FALSE if connection to client is broken. */
- bool vio_is_connected();
+ bool is_connected()
+ {
+ return vio_ok() ? vio_is_connected(net.vio) : FALSE;
+ }
#else
void clear_error();
inline bool vio_ok() const { return TRUE; }
- inline bool vio_is_connected() { return TRUE; }
+ inline bool is_connected() { return TRUE; }
#endif
/**
Mark the current error as fatal. Warning: this does not
diff --git a/vio/vio.c b/vio/vio.c
index e088687098b..5eca4bd1dc6 100644
--- a/vio/vio.c
+++ b/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;
}
diff --git a/vio/vio_priv.h b/vio/vio_priv.h
index 792fad4cc66..c32d973393f 100644
--- a/vio/vio_priv.h
+++ b/vio/vio_priv.h
@@ -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);
diff --git a/vio/viosocket.c b/vio/viosocket.c
index e83559729b9..055112f944e 100644
--- a/vio/viosocket.c
+++ b/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.
+
+ @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.
-my_bool vio_poll_read(Vio *vio,uint timeout)
+ @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.