diff options
author | Michael Widenius <monty@askmonty.org> | 2012-08-14 17:23:34 +0300 |
---|---|---|
committer | Michael Widenius <monty@askmonty.org> | 2012-08-14 17:23:34 +0300 |
commit | 60589aeee03949033c66da5c1eae70d4342179fc (patch) | |
tree | 1cd399dbed17c5c7b4ed16eb7b872dc979af1c93 /vio/vioshm.c | |
parent | b39e6e3d093b45f792959ef06fea1c175263ae1a (diff) | |
download | mariadb-git-60589aeee03949033c66da5c1eae70d4342179fc.tar.gz |
Next part of merge. See TODO for details
Diffstat (limited to 'vio/vioshm.c')
-rw-r--r-- | vio/vioshm.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/vio/vioshm.c b/vio/vioshm.c new file mode 100644 index 00000000000..acc7d2402c5 --- /dev/null +++ b/vio/vioshm.c @@ -0,0 +1,217 @@ +/* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + + 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "vio_priv.h" + +#if defined(_WIN32) && defined(HAVE_SMEM) + +size_t vio_read_shared_memory(Vio *vio, uchar *buf, size_t size) +{ + size_t length; + size_t remain_local; + char *current_position; + HANDLE events[2]; + DWORD timeout; + DBUG_ENTER("vio_read_shared_memory"); + + remain_local= size; + current_position= buf; + timeout= vio->read_timeout >= 0 ? vio->read_timeout : INFINITE; + + events[0]= vio->event_server_wrote; + events[1]= vio->event_conn_closed; + + do + { + if (vio->shared_memory_remain == 0) + { + DWORD wait_status; + + wait_status= WaitForMultipleObjects(array_elements(events), events, + FALSE, timeout); + + /* + 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 (wait_status != WAIT_OBJECT_0) + { + /* + If wait_status is WAIT_TIMEOUT, set error code to indicate a + timeout error. If vio->event_conn_closed was set, use an EOF + condition (return value of zero) to indicate that the operation + has been aborted. + */ + if (wait_status == WAIT_TIMEOUT) + SetLastError(SOCKET_ETIMEDOUT); + else if (wait_status == (WAIT_OBJECT_0 + 1)) + DBUG_RETURN(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_position, vio->shared_memory_pos, length); + + vio->shared_memory_remain-= length; + vio->shared_memory_pos+= length; + current_position+= length; + remain_local-= length; + + if (!vio->shared_memory_remain) + { + if (!SetEvent(vio->event_client_read)) + DBUG_RETURN(-1); + } + } while (remain_local); + length= size; + + DBUG_RETURN(length); +} + + +size_t vio_write_shared_memory(Vio *vio, const uchar *buf, size_t size) +{ + size_t length, remain, sz; + HANDLE pos; + const uchar *current_position; + HANDLE events[2]; + DWORD timeout; + DBUG_ENTER("vio_write_shared_memory"); + + remain= size; + current_position= buf; + timeout= vio->write_timeout >= 0 ? vio->write_timeout : INFINITE; + + events[0]= vio->event_server_read; + events[1]= vio->event_conn_closed; + + while (remain != 0) + { + DWORD wait_status; + + wait_status= WaitForMultipleObjects(array_elements(events), events, + FALSE, timeout); + + if (wait_status != WAIT_OBJECT_0) + { + /* Set error code to indicate a timeout error or disconnect. */ + if (wait_status == WAIT_TIMEOUT) + SetLastError(SOCKET_ETIMEDOUT); + else + SetLastError(ERROR_GRACEFUL_DISCONNECT); + + DBUG_RETURN((size_t) -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_position, sz); + remain-= sz; + current_position+= sz; + if (!SetEvent(vio->event_client_wrote)) + DBUG_RETURN((size_t) -1); + } + length= size; + + DBUG_RETURN(length); +} + + +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. +*/ +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->mysql_socket= MYSQL_INVALID_SOCKET; + DBUG_RETURN(error_count); +} + +#endif /* #if defined(_WIN32) && defined(HAVE_SMEM) */ + |