mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
217 lines
6 KiB
C
217 lines
6 KiB
C
/* 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) */
|
|
|