mysql5/mysql-5.7.27/sql/conn_handler/shared_memory_connection.cc

376 lines
12 KiB
C++

/*
Copyright (c) 2013, 2019, 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 "shared_memory_connection.h"
#include "violite.h" // Vio
#include "channel_info.h" // Channel_info
#include "connection_handler_manager.h" // Connection_handler_manager
#include "log.h" // sql_print_error
#include "sql_class.h" // THD
///////////////////////////////////////////////////////////////////////////
// Channel_info_shared_mem implementation
///////////////////////////////////////////////////////////////////////////
/**
This class abstracts the info. about the windows shared memory mode
of communication with the server.
*/
class Channel_info_shared_mem : public Channel_info
{
HANDLE m_handle_client_file_map;
char* m_handle_client_map;
HANDLE m_event_server_wrote;
HANDLE m_event_server_read;
HANDLE m_event_client_wrote;
HANDLE m_event_client_read;
HANDLE m_event_conn_closed;
protected:
virtual Vio* create_and_init_vio() const
{
return vio_new_win32shared_memory(m_handle_client_file_map,
m_handle_client_map,
m_event_client_wrote,
m_event_client_read,
m_event_server_wrote,
m_event_server_read,
m_event_conn_closed);
}
public:
/**
Constructor to instantiate Channel_info_shared_mem object
@param handle_client_file_map handle to client file map.
@param handle_client_map handle to client map.
@param event_server_wrote handle object for server write event.
@param event_server_read handle object for server read event.
@param event_client_wrote handle object for client write event.
@param event_client_read handle object for client read event.
@param event_conn_closed handle object for connection close event.
*/
Channel_info_shared_mem(HANDLE handle_client_file_map,
char* handle_client_map,
HANDLE event_server_wrote,
HANDLE event_server_read,
HANDLE event_client_wrote,
HANDLE event_client_read,
HANDLE event_conn_closed)
: m_handle_client_file_map(handle_client_file_map),
m_handle_client_map(handle_client_map),
m_event_server_wrote(event_server_wrote),
m_event_server_read(event_server_read),
m_event_client_wrote(event_client_wrote),
m_event_client_read(event_client_read),
m_event_conn_closed(event_conn_closed)
{ }
virtual THD* create_thd()
{
THD* thd= Channel_info::create_thd();
if (thd != NULL)
thd->security_context()->set_host_ptr(my_localhost, strlen(my_localhost));
return thd;
}
virtual void send_error_and_close_channel(uint errorcode,
int error,
bool senderror)
{
Channel_info::send_error_and_close_channel(errorcode, error, senderror);
// Channel_info::send_error_and_close_channel will have closed
// handles on senderror
if (!senderror)
{
if (m_handle_client_file_map)
CloseHandle(m_handle_client_file_map);
if (m_handle_client_map)
UnmapViewOfFile(m_handle_client_map);
if (m_event_server_wrote)
CloseHandle(m_event_server_wrote);
if (m_event_server_read)
CloseHandle(m_event_server_read);
if (m_event_client_wrote)
CloseHandle(m_event_client_wrote);
if (m_event_client_read)
CloseHandle(m_event_client_read);
if (m_event_conn_closed)
CloseHandle(m_event_conn_closed);
}
}
};
///////////////////////////////////////////////////////////////////////////
// Shared_mem_listener implementation
///////////////////////////////////////////////////////////////////////////
void Shared_mem_listener::close_shared_mem()
{
if (m_temp_buffer)
my_free(m_temp_buffer);
my_security_attr_free(m_sa_event);
my_security_attr_free(m_sa_mapping);
if (m_connect_map)
UnmapViewOfFile(m_connect_map);
if (m_connect_named_mutex)
CloseHandle(m_connect_named_mutex);
if (m_connect_file_map)
CloseHandle(m_connect_file_map);
if (m_event_connect_answer)
CloseHandle(m_event_connect_answer);
if (m_event_connect_request)
CloseHandle(m_event_connect_request);
}
bool Shared_mem_listener::setup_listener()
{
const char *errmsg= NULL;
sql_print_information("Shared memory setting up listener");
/*
get enough space base-name + '_' + longest suffix we might ever send
*/
if (!(m_temp_buffer= (char *)my_malloc(key_memory_shared_memory_name,
m_shared_mem_name.length() + 32L, MYF(MY_FAE))))
goto error;
if (my_security_attr_create(&m_sa_event, &errmsg,
GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE))
goto error;
if (my_security_attr_create(&m_sa_mapping, &errmsg,
GENERIC_ALL, FILE_MAP_READ | FILE_MAP_WRITE))
goto error;
/*
The name of event and file-mapping events create agree next rule:
shared_memory_base_name+unique_part
Where:
shared_memory_base_name is unique value for each server
unique_part is unique value for each object (events and file-mapping)
*/
m_suffix_pos= strxmov(m_temp_buffer,m_shared_mem_name.c_str(),"_",NullS);
my_stpcpy(m_suffix_pos, "CONNECT_REQUEST");
if ((m_event_connect_request= CreateEvent(m_sa_event,
FALSE, FALSE, m_temp_buffer)) == 0)
{
errmsg= "Could not create request event";
goto error;
}
my_stpcpy(m_suffix_pos, "CONNECT_ANSWER");
if ((m_event_connect_answer= CreateEvent(m_sa_event, FALSE,
FALSE, m_temp_buffer)) == 0)
{
errmsg="Could not create answer event";
goto error;
}
my_stpcpy(m_suffix_pos, "CONNECT_NAMED_MUTEX");
m_connect_named_mutex= CreateMutex(NULL, FALSE, m_temp_buffer);
if (m_connect_named_mutex == NULL)
{
errmsg="Unable to create connect named mutex.";
goto error;
}
if ( GetLastError() == ERROR_ALREADY_EXISTS)
{
errmsg="Another instance of application already running.";
goto error;
}
my_stpcpy(m_suffix_pos, "CONNECT_DATA");
if ((m_connect_file_map=
CreateFileMapping(INVALID_HANDLE_VALUE, m_sa_mapping, PAGE_READWRITE, 0,
sizeof(m_connect_number), m_temp_buffer)) == 0)
{
errmsg= "Could not create file mapping";
goto error;
}
if ((m_connect_map= (char *)MapViewOfFile(m_connect_file_map,
FILE_MAP_WRITE,0,0,
sizeof(DWORD))) == 0)
{
errmsg= "Could not create shared memory service";
goto error;
}
return false;
error:
if (errmsg)
{
sql_print_error("Can't create shared memory service: %s. : %s",
errmsg, strerror(errno));
}
close_shared_mem();
return true;
}
Channel_info* Shared_mem_listener::listen_for_connection_event()
{
/* Wait for a request from client */
WaitForSingleObject(m_event_connect_request, INFINITE);
/*
it can be after shutdown command
*/
if (abort_loop)
return NULL;
char connect_number_char[22];
char* p= int10_to_str(m_connect_number, connect_number_char, 10);
/*
The name of event and file-mapping events create agree next rule:
shared_memory_base_name+unique_part+number_of_connection
Where:
shared_memory_base_name is uniquel value for each server
unique_part is unique value for each object (events and file-mapping)
number_of_connection is connection-number between server and client
*/
m_suffix_pos= strxmov(m_temp_buffer, m_shared_mem_name.c_str(), "_",
connect_number_char, "_", NullS);
const char *errmsg= NULL;
ulong smem_buffer_length= shared_memory_buffer_length + 4;
my_stpcpy(m_suffix_pos, "DATA");
if ((m_handle_client_file_map=
CreateFileMapping(INVALID_HANDLE_VALUE, m_sa_mapping, PAGE_READWRITE,
0, smem_buffer_length, m_temp_buffer)) == 0)
{
errmsg= "Could not create file mapping";
goto errorconn;
}
if ((m_handle_client_map= (char*)MapViewOfFile(m_handle_client_file_map,
FILE_MAP_WRITE,0,0,
smem_buffer_length)) == 0)
{
errmsg= "Could not create memory map";
goto errorconn;
}
my_stpcpy(m_suffix_pos, "CLIENT_WROTE");
if ((m_event_client_wrote= CreateEvent(m_sa_event, FALSE, FALSE,
m_temp_buffer)) == 0)
{
errmsg= "Could not create client write event";
goto errorconn;
}
my_stpcpy(m_suffix_pos, "CLIENT_READ");
if ((m_event_client_read= CreateEvent(m_sa_event, FALSE, FALSE,
m_temp_buffer)) == 0)
{
errmsg= "Could not create client read event";
goto errorconn;
}
my_stpcpy(m_suffix_pos, "SERVER_READ");
if ((m_event_server_read= CreateEvent(m_sa_event, FALSE, FALSE,
m_temp_buffer)) == 0)
{
errmsg= "Could not create server read event";
goto errorconn;
}
my_stpcpy(m_suffix_pos, "SERVER_WROTE");
if ((m_event_server_wrote= CreateEvent(m_sa_event, FALSE, FALSE,
m_temp_buffer)) == 0)
{
errmsg= "Could not create server write event";
goto errorconn;
}
my_stpcpy(m_suffix_pos, "CONNECTION_CLOSED");
if ((m_event_conn_closed= CreateEvent(m_sa_event, TRUE, FALSE,
m_temp_buffer)) == 0)
{
errmsg= "Could not create closed connection event";
goto errorconn;
}
if (abort_loop)
goto errorconn;
Channel_info* channel_info= new (std::nothrow)
Channel_info_shared_mem(m_handle_client_file_map,
m_handle_client_map,
m_event_server_wrote,
m_event_server_read,
m_event_client_wrote,
m_event_client_read,
m_event_conn_closed);
if (channel_info != NULL)
{
int4store(m_connect_map, m_connect_number);
if (!SetEvent(m_event_connect_answer))
{
errmsg= "Could not send answer event";
delete channel_info;
goto errorconn;
}
if (!SetEvent(m_event_client_read))
{
errmsg= "Could not set client to read mode";
delete channel_info;
goto errorconn;
}
m_connect_number++;
return channel_info;
}
errorconn:
/* Could not form connection; Free used handlers/memort and retry */
if (errmsg)
{
sql_print_error("Can't create shared memory connection: %s. : %s",
errmsg, strerror(errno));
}
if (m_handle_client_file_map)
CloseHandle(m_handle_client_file_map);
if (m_handle_client_map)
UnmapViewOfFile(m_handle_client_map);
if (m_event_server_wrote)
CloseHandle(m_event_server_wrote);
if (m_event_server_read)
CloseHandle(m_event_server_read);
if (m_event_client_wrote)
CloseHandle(m_event_client_wrote);
if (m_event_client_read)
CloseHandle(m_event_client_read);
if (m_event_conn_closed)
CloseHandle(m_event_conn_closed);
return NULL;
}
void Shared_mem_listener::close_listener()
{
if (!SetEvent(m_event_connect_request))
{
DBUG_PRINT("error",
("Got error: %ld from SetEvent of mem_event_connect_request",
GetLastError()));
}
close_shared_mem();
}