mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-06-19 16:47:14 +02:00
Add MariaDB Connector/C as a built-in alternative (v3.2.3).
This commit is contained in:
27
vendor/MDBC/plugins/pvio/CMakeLists.txt
vendored
Normal file
27
vendor/MDBC/plugins/pvio/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
SET(PVIO_DIR ${CC_SOURCE_DIR}/plugins/pvio)
|
||||
|
||||
INCLUDE_DIRECTORIES(${PVIO_DIR})
|
||||
INCLUDE_DIRECTORIES(${CC_SOURCE_DIR}/include)
|
||||
|
||||
#native password
|
||||
REGISTER_PLUGIN(TARGET pvio_socket
|
||||
TYPE MARIADB_CLIENT_PLUGIN_PVIO
|
||||
CONFIGURATIONS STATIC DYNAMIC DEFAULT
|
||||
DEFAULT STATIC
|
||||
SOURCES ${CC_SOURCE_DIR}/plugins/pvio/pvio_socket.c)
|
||||
|
||||
IF(WIN32)
|
||||
# named pipe
|
||||
REGISTER_PLUGIN(TARGET pvio_npipe
|
||||
TYPE MARIADB_CLIENT_PLUGIN_PVIO
|
||||
CONFIGURATIONS STATIC DYNAMIC DEFAULT
|
||||
DEFAULT DYNAMIC
|
||||
SOURCES ${CC_SOURCE_DIR}/plugins/pvio/pvio_npipe.c)
|
||||
|
||||
# shared memory
|
||||
REGISTER_PLUGIN(TARGET pvio_shmem
|
||||
TYPE MARIADB_CLIENT_PLUGIN_PVIO
|
||||
CONFIGURATIONS STATIC DYNAMIC DEFAULT
|
||||
DEFAULT DYNAMIC
|
||||
SOURCES ${CC_SOURCE_DIR}/plugins/pvio/pvio_shmem.c)
|
||||
ENDIF()
|
359
vendor/MDBC/plugins/pvio/pvio_npipe.c
vendored
Normal file
359
vendor/MDBC/plugins/pvio/pvio_npipe.c
vendored
Normal file
@ -0,0 +1,359 @@
|
||||
/************************************************************************************
|
||||
Copyright (C) 2015 Georg Richter and MariaDB Corporation AB
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||
|
||||
*************************************************************************************/
|
||||
|
||||
/* MariaDB virtual IO plugin for Windows named pipe communication */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <ma_global.h>
|
||||
#include <ma_sys.h>
|
||||
#include <errmsg.h>
|
||||
#include <mysql.h>
|
||||
#include <mysql/client_plugin.h>
|
||||
#include <string.h>
|
||||
#include <ma_string.h>
|
||||
|
||||
/* Function prototypes */
|
||||
my_bool pvio_npipe_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
|
||||
int pvio_npipe_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
|
||||
ssize_t pvio_npipe_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
|
||||
ssize_t pvio_npipe_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
|
||||
|
||||
my_bool pvio_npipe_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
|
||||
my_bool pvio_npipe_close(MARIADB_PVIO *pvio);
|
||||
int pvio_npipe_fast_send(MARIADB_PVIO *pvio);
|
||||
int pvio_npipe_keepalive(MARIADB_PVIO *pvio);
|
||||
my_bool pvio_npipe_get_handle(MARIADB_PVIO *pvio, void *handle);
|
||||
my_bool pvio_npipe_is_blocking(MARIADB_PVIO *pvio);
|
||||
int pvio_npipe_shutdown(MARIADB_PVIO *pvio);
|
||||
my_bool pvio_npipe_is_alive(MARIADB_PVIO *pvio);
|
||||
|
||||
struct st_ma_pvio_methods pvio_npipe_methods= {
|
||||
pvio_npipe_set_timeout,
|
||||
pvio_npipe_get_timeout,
|
||||
pvio_npipe_read,
|
||||
NULL,
|
||||
pvio_npipe_write,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
pvio_npipe_connect,
|
||||
pvio_npipe_close,
|
||||
pvio_npipe_fast_send,
|
||||
pvio_npipe_keepalive,
|
||||
pvio_npipe_get_handle,
|
||||
pvio_npipe_is_blocking,
|
||||
pvio_npipe_is_alive,
|
||||
NULL,
|
||||
pvio_npipe_shutdown
|
||||
};
|
||||
|
||||
#ifndef PLUGIN_DYNAMIC
|
||||
MARIADB_PVIO_PLUGIN pvio_npipe_client_plugin =
|
||||
#else
|
||||
MARIADB_PVIO_PLUGIN _mysql_client_plugin_declaration_ =
|
||||
#endif
|
||||
{
|
||||
MARIADB_CLIENT_PVIO_PLUGIN,
|
||||
MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION,
|
||||
"pvio_npipe",
|
||||
"Georg Richter",
|
||||
"MariaDB virtual IO plugin for named pipe connection",
|
||||
{1, 0, 0},
|
||||
"LGPL",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&pvio_npipe_methods
|
||||
};
|
||||
|
||||
struct st_pvio_npipe {
|
||||
HANDLE pipe;
|
||||
OVERLAPPED overlapped;
|
||||
MYSQL *mysql;
|
||||
};
|
||||
|
||||
my_bool pvio_npipe_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
|
||||
{
|
||||
int timeout_ms;
|
||||
|
||||
if (!pvio)
|
||||
return 1;
|
||||
if (timeout > INT_MAX/1000)
|
||||
timeout_ms= -1;
|
||||
else if (timeout <=0)
|
||||
timeout_ms= -1;
|
||||
else
|
||||
timeout_ms = timeout*1000;
|
||||
|
||||
pvio->timeout[type]= timeout_ms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pvio_npipe_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type)
|
||||
{
|
||||
if (!pvio)
|
||||
return -1;
|
||||
return pvio->timeout[type] / 1000;
|
||||
}
|
||||
|
||||
static BOOL complete_io(HANDLE file, OVERLAPPED *ov, BOOL ret, DWORD timeout, DWORD *size)
|
||||
{
|
||||
if (ret)
|
||||
timeout = 0; /* IO completed successfully, do not WaitForSingleObject */
|
||||
else
|
||||
{
|
||||
assert(timeout);
|
||||
if (GetLastError() != ERROR_IO_PENDING)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
HANDLE wait_handle= ov->hEvent;
|
||||
assert(wait_handle && (wait_handle != INVALID_HANDLE_VALUE));
|
||||
|
||||
DWORD wait_ret= WaitForSingleObject(wait_handle, timeout);
|
||||
switch (wait_ret)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
CancelIoEx(file, ov);
|
||||
SetLastError(ERROR_TIMEOUT);
|
||||
return FALSE;
|
||||
default:
|
||||
/* WAIT_ABANDONED or WAIT_FAILED unexpected. */
|
||||
assert(0);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GetOverlappedResult(file, ov, size, FALSE);
|
||||
}
|
||||
|
||||
ssize_t pvio_npipe_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
|
||||
{
|
||||
BOOL ret;
|
||||
ssize_t r= -1;
|
||||
struct st_pvio_npipe *cpipe= NULL;
|
||||
DWORD size;
|
||||
|
||||
if (!pvio || !pvio->data)
|
||||
return -1;
|
||||
|
||||
cpipe= (struct st_pvio_npipe *)pvio->data;
|
||||
|
||||
ret= ReadFile(cpipe->pipe, buffer, (DWORD)length, NULL, &cpipe->overlapped);
|
||||
ret= complete_io(cpipe->pipe, &cpipe->overlapped, ret, pvio->timeout[PVIO_READ_TIMEOUT], &size);
|
||||
r= ret? (ssize_t) size:-1;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
ssize_t pvio_npipe_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
|
||||
{
|
||||
ssize_t r= -1;
|
||||
struct st_pvio_npipe *cpipe= NULL;
|
||||
BOOL ret;
|
||||
DWORD size;
|
||||
|
||||
if (!pvio || !pvio->data)
|
||||
return -1;
|
||||
|
||||
cpipe= (struct st_pvio_npipe *)pvio->data;
|
||||
|
||||
ret= WriteFile(cpipe->pipe, buffer, (DWORD)length, NULL , &cpipe->overlapped);
|
||||
ret= complete_io(cpipe->pipe, &cpipe->overlapped, ret, pvio->timeout[PVIO_WRITE_TIMEOUT], &size);
|
||||
r= ret ? (ssize_t)size : -1;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int pvio_npipe_keepalive(MARIADB_PVIO *pvio)
|
||||
{
|
||||
/* keep alive is used for TCP/IP connections only */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pvio_npipe_fast_send(MARIADB_PVIO *pvio)
|
||||
{
|
||||
/* not supported */
|
||||
return 0;
|
||||
}
|
||||
my_bool pvio_npipe_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
|
||||
{
|
||||
struct st_pvio_npipe *cpipe= NULL;
|
||||
|
||||
if (!pvio || !cinfo)
|
||||
return 1;
|
||||
|
||||
/* if connect timeout is set, we will overwrite read/write timeout */
|
||||
if (pvio->timeout[PVIO_CONNECT_TIMEOUT])
|
||||
{
|
||||
pvio->timeout[PVIO_READ_TIMEOUT]= pvio->timeout[PVIO_WRITE_TIMEOUT]= pvio->timeout[PVIO_CONNECT_TIMEOUT];
|
||||
}
|
||||
|
||||
if (!(cpipe= (struct st_pvio_npipe *)LocalAlloc(LMEM_ZEROINIT, sizeof(struct st_pvio_npipe))))
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, "HY000", 0, "");
|
||||
return 1;
|
||||
}
|
||||
pvio->data= (void *)cpipe;
|
||||
cpipe->pipe= INVALID_HANDLE_VALUE;
|
||||
pvio->mysql= cinfo->mysql;
|
||||
pvio->type= cinfo->type;
|
||||
|
||||
if (cinfo->type == PVIO_TYPE_NAMEDPIPE)
|
||||
{
|
||||
char szPipeName[MAX_PATH];
|
||||
ULONGLONG deadline;
|
||||
LONGLONG wait_ms;
|
||||
DWORD backoff= 0; /* Avoid busy wait if ERROR_PIPE_BUSY.*/
|
||||
if ( ! cinfo->unix_socket || (cinfo->unix_socket)[0] == 0x00)
|
||||
cinfo->unix_socket = MARIADB_NAMEDPIPE;
|
||||
if (!cinfo->host || !strcmp(cinfo->host,LOCAL_HOST))
|
||||
cinfo->host=LOCAL_HOST_NAMEDPIPE;
|
||||
|
||||
szPipeName[MAX_PATH - 1]= 0;
|
||||
snprintf(szPipeName, MAX_PATH - 1, "\\\\%s\\pipe\\%s", cinfo->host, cinfo->unix_socket);
|
||||
|
||||
if (pvio->timeout[PVIO_CONNECT_TIMEOUT] > 0)
|
||||
deadline = GetTickCount64() + pvio->timeout[PVIO_CONNECT_TIMEOUT];
|
||||
else
|
||||
deadline = INFINITE;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if ((cpipe->pipe = CreateFile(szPipeName,
|
||||
GENERIC_READ |
|
||||
GENERIC_WRITE,
|
||||
0, /* no sharing */
|
||||
NULL, /* default security attributes */
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
NULL)) != INVALID_HANDLE_VALUE)
|
||||
break;
|
||||
|
||||
if (GetLastError() != ERROR_PIPE_BUSY)
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_NAMEDPIPEOPEN_ERROR, "HY000", 0,
|
||||
cinfo->host, cinfo->unix_socket, GetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
Sleep(backoff);
|
||||
if (!backoff)
|
||||
backoff = 1;
|
||||
|
||||
wait_ms = deadline - GetTickCount64();
|
||||
if (wait_ms > INFINITE)
|
||||
wait_ms = INFINITE;
|
||||
|
||||
if ((wait_ms <= 0) || !WaitNamedPipe(szPipeName, (DWORD)wait_ms))
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_NAMEDPIPEWAIT_ERROR, "HY000", 0,
|
||||
cinfo->host, cinfo->unix_socket, ERROR_TIMEOUT);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!(cpipe->overlapped.hEvent= CreateEvent(NULL, FALSE, FALSE, NULL)))
|
||||
{
|
||||
pvio->set_error(pvio->mysql, CR_EVENT_CREATE_FAILED, "HY000", 0,
|
||||
GetLastError());
|
||||
goto end;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
end:
|
||||
if (cpipe)
|
||||
{
|
||||
if (cpipe->pipe != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(cpipe->pipe);
|
||||
LocalFree(cpipe);
|
||||
pvio->data= NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
my_bool pvio_npipe_close(MARIADB_PVIO *pvio)
|
||||
{
|
||||
struct st_pvio_npipe *cpipe= NULL;
|
||||
int r= 0;
|
||||
|
||||
if (!pvio)
|
||||
return 1;
|
||||
|
||||
if (pvio->data)
|
||||
{
|
||||
cpipe= (struct st_pvio_npipe *)pvio->data;
|
||||
CloseHandle(cpipe->overlapped.hEvent);
|
||||
if (cpipe->pipe != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(cpipe->pipe);
|
||||
cpipe->pipe= INVALID_HANDLE_VALUE;
|
||||
}
|
||||
LocalFree(pvio->data);
|
||||
pvio->data= NULL;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
my_bool pvio_npipe_get_handle(MARIADB_PVIO *pvio, void *handle)
|
||||
{
|
||||
if (pvio && pvio->data)
|
||||
{
|
||||
*(HANDLE *)handle= ((struct st_pvio_npipe *)pvio->data)->pipe;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
my_bool pvio_npipe_is_blocking(MARIADB_PVIO *pvio)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pvio_npipe_shutdown(MARIADB_PVIO *pvio)
|
||||
{
|
||||
HANDLE h;
|
||||
if (pvio_npipe_get_handle(pvio, &h) == 0)
|
||||
{
|
||||
return(CancelIoEx(h, NULL) ? 0 : 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
my_bool pvio_npipe_is_alive(MARIADB_PVIO *pvio)
|
||||
{
|
||||
HANDLE handle;
|
||||
if (!pvio || !pvio->data)
|
||||
return FALSE;
|
||||
|
||||
handle= ((struct st_pvio_npipe *)pvio->data)->pipe;
|
||||
/* Copy data from named pipe without removing it */
|
||||
if (PeekNamedPipe(handle, NULL, 0, NULL, NULL, NULL))
|
||||
return TRUE;
|
||||
return test(GetLastError() != ERROR_BROKEN_PIPE);
|
||||
}
|
||||
#endif
|
2
vendor/MDBC/plugins/pvio/pvio_plugin.def
vendored
Normal file
2
vendor/MDBC/plugins/pvio/pvio_plugin.def
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
EXPORTS
|
||||
_mysql_client_plugin_declaration_ DATA
|
469
vendor/MDBC/plugins/pvio/pvio_shmem.c
vendored
Normal file
469
vendor/MDBC/plugins/pvio/pvio_shmem.c
vendored
Normal file
@ -0,0 +1,469 @@
|
||||
/************************************************************************************
|
||||
Copyright (C) 2015 Georg Richter and MariaDB Corporation AB
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not see <http://www.gnu.org/licenses>
|
||||
or write to the Free Software Foundation, Inc.,
|
||||
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
|
||||
|
||||
*************************************************************************************/
|
||||
/* MariaDB virtual IO plugin for Windows shared memory communication */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <ma_global.h>
|
||||
#include <ma_sys.h>
|
||||
#include <errmsg.h>
|
||||
#include <mysql.h>
|
||||
#include <mysql/client_plugin.h>
|
||||
#include <string.h>
|
||||
#include <ma_string.h>
|
||||
|
||||
#define PVIO_SHM_BUFFER_SIZE (16000 + 4)
|
||||
|
||||
my_bool pvio_shm_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout);
|
||||
int pvio_shm_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type);
|
||||
ssize_t pvio_shm_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length);
|
||||
ssize_t pvio_shm_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length);
|
||||
int pvio_shm_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout);
|
||||
int pvio_shm_blocking(MARIADB_PVIO *pvio, my_bool value, my_bool *old_value);
|
||||
my_bool pvio_shm_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
|
||||
my_bool pvio_shm_close(MARIADB_PVIO *pvio);
|
||||
int pvio_shm_shutdown(MARIADB_PVIO *pvio);
|
||||
my_bool pvio_shm_is_alive(MARIADB_PVIO *pvio);
|
||||
my_bool pvio_shm_get_handle(MARIADB_PVIO *pvio, void *handle);
|
||||
|
||||
struct st_ma_pvio_methods pvio_shm_methods= {
|
||||
pvio_shm_set_timeout,
|
||||
pvio_shm_get_timeout,
|
||||
pvio_shm_read,
|
||||
NULL,
|
||||
pvio_shm_write,
|
||||
NULL,
|
||||
pvio_shm_wait_io_or_timeout,
|
||||
pvio_shm_blocking,
|
||||
pvio_shm_connect,
|
||||
pvio_shm_close,
|
||||
NULL,
|
||||
NULL,
|
||||
pvio_shm_get_handle,
|
||||
NULL,
|
||||
pvio_shm_is_alive,
|
||||
NULL,
|
||||
pvio_shm_shutdown
|
||||
};
|
||||
|
||||
#ifndef PLUGIN_DYNAMIC
|
||||
MARIADB_PVIO_PLUGIN pvio_shmem_client_plugin=
|
||||
#else
|
||||
MARIADB_PVIO_PLUGIN _mysql_client_plugin_declaration_=
|
||||
#endif
|
||||
{
|
||||
MARIADB_CLIENT_PVIO_PLUGIN,
|
||||
MARIADB_CLIENT_PVIO_PLUGIN_INTERFACE_VERSION,
|
||||
"pvio_shmem",
|
||||
"Georg Richter",
|
||||
"MariaDB virtual IO plugin for Windows shared memory communication",
|
||||
{1, 0, 0},
|
||||
"LGPPL",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&pvio_shm_methods,
|
||||
|
||||
};
|
||||
|
||||
enum enum_shm_events
|
||||
{
|
||||
PVIO_SHM_SERVER_WROTE= 0,
|
||||
PVIO_SHM_SERVER_READ,
|
||||
PVIO_SHM_CLIENT_WROTE,
|
||||
PVIO_SHM_CLIENT_READ,
|
||||
PVIO_SHM_CONNECTION_CLOSED
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
HANDLE event[5];
|
||||
HANDLE file_map;
|
||||
LPVOID *map;
|
||||
char *read_pos;
|
||||
size_t buffer_size;
|
||||
} PVIO_SHM;
|
||||
|
||||
const char *StrEvent[]= {"SERVER_WROTE", "SERVER_READ", "CLIENT_WROTE", "CLIENT_READ", "CONNECTION_CLOSED"};
|
||||
|
||||
struct st_pvio_shm {
|
||||
char *shm_name;
|
||||
};
|
||||
|
||||
my_bool pvio_shm_set_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type, int timeout)
|
||||
{
|
||||
if (!pvio)
|
||||
return 1;
|
||||
pvio->timeout[type]= (timeout > 0) ? timeout * 1000 : INFINITE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pvio_shm_get_timeout(MARIADB_PVIO *pvio, enum enum_pvio_timeout type)
|
||||
{
|
||||
if (!pvio)
|
||||
return -1;
|
||||
return pvio->timeout[type] / 1000;
|
||||
}
|
||||
|
||||
ssize_t pvio_shm_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
|
||||
{
|
||||
PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
|
||||
size_t copy_size= length;
|
||||
HANDLE events[2];
|
||||
|
||||
if (!pvio_shm)
|
||||
return -1;
|
||||
|
||||
/* we need to wait for write and close events */
|
||||
if (!pvio_shm->buffer_size)
|
||||
{
|
||||
events[0]= pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED];
|
||||
events[1]= pvio_shm->event[PVIO_SHM_SERVER_WROTE];
|
||||
|
||||
switch(WaitForMultipleObjects(2, events, 0, pvio->timeout[PVIO_READ_TIMEOUT]))
|
||||
{
|
||||
case WAIT_OBJECT_0: /* server closed connection */
|
||||
SetLastError(ERROR_GRACEFUL_DISCONNECT);
|
||||
return -1;
|
||||
case WAIT_OBJECT_0 +1: /* server_wrote event */
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
SetLastError(ETIMEDOUT);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
/* server sent data */
|
||||
pvio_shm->read_pos= (char *)pvio_shm->map;
|
||||
pvio_shm->buffer_size= uint4korr(pvio_shm->read_pos);
|
||||
pvio_shm->read_pos+= 4;
|
||||
}
|
||||
|
||||
if (pvio_shm->buffer_size < copy_size)
|
||||
copy_size= pvio_shm->buffer_size;
|
||||
|
||||
if (copy_size)
|
||||
{
|
||||
memcpy(buffer, (uchar *)pvio_shm->read_pos, pvio_shm->buffer_size);
|
||||
pvio_shm->read_pos+= copy_size;
|
||||
pvio_shm->buffer_size-= copy_size;
|
||||
}
|
||||
|
||||
/* we need to read again */
|
||||
if (!pvio_shm->buffer_size)
|
||||
if (!SetEvent(pvio_shm->event[PVIO_SHM_CLIENT_READ]))
|
||||
return -1;
|
||||
|
||||
return (ssize_t)copy_size;
|
||||
}
|
||||
|
||||
ssize_t pvio_shm_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
|
||||
{
|
||||
HANDLE events[2];
|
||||
PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
|
||||
size_t bytes_to_write= length;
|
||||
uchar *buffer_pos= (uchar *)buffer;
|
||||
|
||||
if (!pvio_shm)
|
||||
return -1;
|
||||
|
||||
events[0]= pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED];
|
||||
events[1]= pvio_shm->event[PVIO_SHM_SERVER_READ];
|
||||
|
||||
while (bytes_to_write)
|
||||
{
|
||||
size_t pkt_length;
|
||||
switch (WaitForMultipleObjects(2, events, 0, pvio->timeout[PVIO_WRITE_TIMEOUT])) {
|
||||
case WAIT_OBJECT_0: /* connection closed */
|
||||
SetLastError(ERROR_GRACEFUL_DISCONNECT);
|
||||
return -1;
|
||||
case WAIT_OBJECT_0 + 1: /* server_read */
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
SetLastError(ETIMEDOUT);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
pkt_length= MIN(PVIO_SHM_BUFFER_SIZE, length);
|
||||
int4store(pvio_shm->map, pkt_length);
|
||||
memcpy((uchar *)pvio_shm->map + 4, buffer_pos, length);
|
||||
buffer_pos+= length;
|
||||
bytes_to_write-= length;
|
||||
|
||||
if (!SetEvent(pvio_shm->event[PVIO_SHM_CLIENT_WROTE]))
|
||||
return -1;
|
||||
}
|
||||
return (ssize_t)length;
|
||||
}
|
||||
|
||||
|
||||
int pvio_shm_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pvio_shm_blocking(MARIADB_PVIO *pvio, my_bool block, my_bool *previous_mode)
|
||||
{
|
||||
/* not supported */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pvio_shm_keepalive(MARIADB_PVIO *pvio)
|
||||
{
|
||||
/* not supported */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pvio_shm_fast_send(MARIADB_PVIO *pvio)
|
||||
{
|
||||
/* not supported */
|
||||
return 0;
|
||||
}
|
||||
|
||||
my_bool pvio_shm_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo)
|
||||
{
|
||||
const char *base_memory_name;
|
||||
char *prefixes[]= {"", "Global\\", NULL};
|
||||
char *shm_name, *shm_suffix, *shm_prefix;
|
||||
uchar i= 0;
|
||||
int len;
|
||||
int cid;
|
||||
DWORD dwDesiredAccess= EVENT_MODIFY_STATE | SYNCHRONIZE;
|
||||
HANDLE hdlConnectRequest= NULL,
|
||||
hdlConnectRequestAnswer= NULL,
|
||||
file_map= NULL;
|
||||
LPVOID map= NULL;
|
||||
PVIO_SHM *pvio_shm= (PVIO_SHM*)LocalAlloc(LMEM_ZEROINIT, sizeof(PVIO_SHM));
|
||||
|
||||
if (!pvio_shm)
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, "HY000", 0, "");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* MariaDB server constructs the event name as follows:
|
||||
"Global\\base_memory_name" or
|
||||
"\\base_memory_name"
|
||||
*/
|
||||
|
||||
|
||||
base_memory_name= (cinfo->host) ? cinfo->host : SHM_DEFAULT_NAME;
|
||||
|
||||
if (!(shm_name= (char *)LocalAlloc(LMEM_ZEROINIT, strlen(base_memory_name) + 40)))
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, "HY000", 0, "");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* iterate through prefixes */
|
||||
while (prefixes[i])
|
||||
{
|
||||
len= sprintf(shm_name, "%s%s_", prefixes[i], base_memory_name);
|
||||
shm_suffix= shm_name + len;
|
||||
strcpy(shm_suffix, "CONNECT_REQUEST");
|
||||
if ((hdlConnectRequest= OpenEvent(dwDesiredAccess, 0, shm_name)))
|
||||
{
|
||||
/* save prefix to prevent further loop */
|
||||
shm_prefix= prefixes[i];
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!hdlConnectRequest)
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Opening CONNECT_REQUEST event failed", GetLastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
strcpy(shm_suffix, "CONNECT_ANSWER");
|
||||
if (!(hdlConnectRequestAnswer= OpenEvent(dwDesiredAccess, 0, shm_name)))
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Opening CONNECT_ANSWER event failed", GetLastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* get connection id, so we can build the filename used for connection */
|
||||
strcpy(shm_suffix, "CONNECT_DATA");
|
||||
if (!(file_map= OpenFileMapping(FILE_MAP_WRITE, 0, shm_name)))
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "OpenFileMapping failed", GetLastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* try to get first 4 bytes, which represents connection_id */
|
||||
if (!(map= MapViewOfFile(file_map, FILE_MAP_WRITE, 0, 0, sizeof(cid))))
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Reading connection_id failed", GetLastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* notify server */
|
||||
if (!SetEvent(hdlConnectRequest))
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Failed sending connection request", GetLastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Wait for server answer */
|
||||
switch(WaitForSingleObject(hdlConnectRequestAnswer, pvio->timeout[PVIO_CONNECT_TIMEOUT])) {
|
||||
case WAIT_ABANDONED:
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Mutex was not released in time", GetLastError());
|
||||
goto error;
|
||||
break;
|
||||
case WAIT_FAILED:
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Operation wait failed", GetLastError());
|
||||
goto error;
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Operation timed out", GetLastError());
|
||||
goto error;
|
||||
break;
|
||||
case WAIT_OBJECT_0:
|
||||
break;
|
||||
default:
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Wait for server failed", GetLastError());
|
||||
break;
|
||||
}
|
||||
|
||||
cid= uint4korr(map);
|
||||
|
||||
len= sprintf(shm_name, "%s%s_%d_", shm_prefix, base_memory_name, cid);
|
||||
shm_suffix= shm_name + len;
|
||||
|
||||
strcpy(shm_suffix, "DATA");
|
||||
pvio_shm->file_map= OpenFileMapping(FILE_MAP_WRITE, 0, shm_name);
|
||||
if (pvio_shm->file_map == NULL)
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "OpenFileMapping failed", GetLastError());
|
||||
goto error;
|
||||
}
|
||||
if (!(pvio_shm->map= MapViewOfFile(pvio_shm->file_map, FILE_MAP_WRITE, 0, 0, PVIO_SHM_BUFFER_SIZE)))
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "MapViewOfFile failed", GetLastError());
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i=0; i < 5; i++)
|
||||
{
|
||||
strcpy(shm_suffix, StrEvent[i]);
|
||||
if (!(pvio_shm->event[i]= OpenEvent(dwDesiredAccess, 0, shm_name)))
|
||||
{
|
||||
PVIO_SET_ERROR(cinfo->mysql, CR_SHARED_MEMORY_CONNECT_ERROR, "HY000", 0, "Couldn't create event", GetLastError());
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
/* we will first read from server */
|
||||
SetEvent(pvio_shm->event[PVIO_SHM_SERVER_READ]);
|
||||
|
||||
error:
|
||||
if (hdlConnectRequest)
|
||||
CloseHandle(hdlConnectRequest);
|
||||
if (hdlConnectRequestAnswer)
|
||||
CloseHandle(hdlConnectRequestAnswer);
|
||||
if (shm_name)
|
||||
LocalFree(shm_name);
|
||||
if (map)
|
||||
UnmapViewOfFile(map);
|
||||
if (file_map)
|
||||
CloseHandle(file_map);
|
||||
if (pvio_shm)
|
||||
{
|
||||
/* check if all events are set */
|
||||
if (pvio_shm->event[4])
|
||||
{
|
||||
pvio->data= (void *)pvio_shm;
|
||||
pvio->mysql= cinfo->mysql;
|
||||
pvio->type= cinfo->type;
|
||||
pvio_shm->read_pos= (char *)pvio_shm->map;
|
||||
pvio->mysql->net.pvio= pvio;
|
||||
return 0;
|
||||
}
|
||||
for (i=0;i < 5; i++)
|
||||
if (pvio_shm->event[i])
|
||||
CloseHandle(pvio_shm->event[i]);
|
||||
if (pvio_shm->map)
|
||||
UnmapViewOfFile(pvio_shm->map);
|
||||
if (pvio_shm->file_map)
|
||||
CloseHandle(pvio_shm->file_map);
|
||||
LocalFree(pvio_shm);
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
my_bool pvio_shm_close(MARIADB_PVIO *pvio)
|
||||
{
|
||||
PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
|
||||
int i;
|
||||
|
||||
if (!pvio_shm)
|
||||
return 1;
|
||||
|
||||
/* notify server */
|
||||
SetEvent(pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED]);
|
||||
|
||||
UnmapViewOfFile(pvio_shm->map);
|
||||
CloseHandle(pvio_shm->file_map);
|
||||
|
||||
for (i=0; i < 5; i++)
|
||||
CloseHandle(pvio_shm->event[i]);
|
||||
|
||||
LocalFree(pvio_shm);
|
||||
pvio->data= NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
my_bool pvio_shm_get_socket(MARIADB_PVIO *pvio, void *handle)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
my_bool pvio_shm_is_blocking(MARIADB_PVIO *pvio)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pvio_shm_shutdown(MARIADB_PVIO *pvio)
|
||||
{
|
||||
PVIO_SHM *pvio_shm= (PVIO_SHM *)pvio->data;
|
||||
if (pvio_shm)
|
||||
return (SetEvent(pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED]) ? 0 : 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
my_bool pvio_shm_is_alive(MARIADB_PVIO *pvio)
|
||||
{
|
||||
PVIO_SHM *pvio_shm;
|
||||
if (!pvio || !pvio->data)
|
||||
return FALSE;
|
||||
pvio_shm= (PVIO_SHM *)pvio->data;
|
||||
return WaitForSingleObject(pvio_shm->event[PVIO_SHM_CONNECTION_CLOSED], 0)!=WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
my_bool pvio_shm_get_handle(MARIADB_PVIO *pvio, void *handle)
|
||||
{
|
||||
|
||||
*(HANDLE **)handle= 0;
|
||||
if (!pvio || !pvio->data)
|
||||
return FALSE;
|
||||
*(HANDLE **)handle= ((PVIO_SHM*)pvio->data)->event;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
1128
vendor/MDBC/plugins/pvio/pvio_socket.c
vendored
Normal file
1128
vendor/MDBC/plugins/pvio/pvio_socket.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user