8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 18:03:04 +01:00

Fixed few bugs for XNET under high load. Improve XNET connections error diagnostics. Don't stop processing XNET incoming connections if one of them failed at initial stage (at XNET_conect).

This commit is contained in:
hvlad 2008-11-27 22:48:21 +00:00
parent 2d50526fc3
commit 3c8c5b565c
2 changed files with 265 additions and 199 deletions

View File

@ -213,7 +213,7 @@ int WINAPI WinMain(HINSTANCE hThisInst,
ISC_enter();
int nReturnValue = 0;
ISC_STATUS_ARRAY status_vector;
ISC_STATUS_ARRAY status_vector = {0};
if (connection_handle != INVALID_HANDLE_VALUE)
{
@ -237,6 +237,8 @@ int WINAPI WinMain(HINSTANCE hThisInst,
if (port) {
service_connection(port);
}
else if (status_vector[1])
gds__log_status(0, status_vector);
fb_shutdown(0, fb_shutrsn_no_connection);
}
@ -321,6 +323,7 @@ static THREAD_ENTRY_DECLARE inet_connect_wait_thread(THREAD_ENTRY_PARAM)
ISC_STATUS_ARRAY status_vector;
while (true)
{
fb_utils::init_status(status_vector);
rem_port* port = INET_connect(protocol_inet, NULL, status_vector, server_flag, 0);
if (!port) {
@ -355,9 +358,11 @@ static THREAD_ENTRY_DECLARE wnet_connect_wait_thread(THREAD_ENTRY_PARAM)
ISC_STATUS_ARRAY status_vector;
while (true)
{
fb_utils::init_status(status_vector);
rem_port* port = WNET_connect(protocol_wnet, NULL, status_vector, server_flag);
if (!port) {
if (!port)
{
if (status_vector[1] != isc_io_error ||
status_vector[6] != isc_arg_win32 ||
status_vector[7] != ERROR_CALL_NOT_IMPLEMENTED)
@ -388,13 +393,26 @@ static THREAD_ENTRY_DECLARE xnet_connect_wait_thread(THREAD_ENTRY_PARAM)
ISC_STATUS_ARRAY status_vector;
while (true)
{
fb_utils::init_status(status_vector);
rem_port* port = XNET_connect(NULL, NULL, status_vector, server_flag);
if (!port) {
gds__log_status(0, status_vector);
break;
if (!port)
{
const ISC_STATUS err = status_vector[1];
if (err)
{
if (err == isc_net_server_shutdown)
break;
gds__log_status(0, status_vector);
}
}
else {
if (gds__thread_start(process_connection_thread, port, THREAD_medium, 0, 0))
{
gds__log("XNET: can't start worker thread, connection terminated");
port->disconnect(NULL, NULL);
}
}
gds__thread_start(process_connection_thread, port, THREAD_medium, 0, 0);
}
return 0;

View File

@ -59,11 +59,13 @@ static rem_port* aux_connect(rem_port*, PACKET*, t_event_ast);
static rem_port* aux_request(rem_port*, PACKET*);
static void cleanup_comm(XCC);
static void cleanup_mapping(XPM);
static void cleanup_port(rem_port*);
static rem_port* connect_client(PACKET*, ISC_STATUS*);
static rem_port* connect_server(ISC_STATUS*, USHORT);
static void disconnect(rem_port*);
static void exit_handler(rem_port*);
static int shut_main_port(const int, const int, void* arg);
static rem_port* receive(rem_port*, PACKET *);
static int send_full(rem_port*, PACKET *);
@ -76,7 +78,7 @@ static void server_shutdown(rem_port* port);
static rem_port* get_server_port(ULONG, XPM, ULONG, ULONG, ULONG, ISC_STATUS*);
static bool make_map(ULONG, ULONG, FILE_ID*, CADDR_T*);
static XPM make_xpm(ULONG, ULONG);
static bool server_init(USHORT);
static bool server_init(ISC_STATUS*, USHORT);
static XPM get_free_slot(ULONG*, ULONG*, ULONG*);
static bool fork(ULONG, USHORT, ULONG*);
@ -138,8 +140,9 @@ static char xnet_endpoint[BUFFER_TINY] = "";
static bool xnet_initialized = false;
static bool xnet_shutdown = false;
static Firebird::GlobalPtr<Firebird::Mutex> xnet_mutex;
static ULONG xnet_next_free_map_num = 0;
static bool connect_init();
static bool connect_init(ISC_STATUS *status);
static void connect_fini();
static void release_all();
@ -167,11 +170,25 @@ inline void make_event_name(char* buffer, size_t size, const char* format, ULONG
static int xnet_error(rem_port*, ISC_STATUS, int);
static void xnet_log_error(const char* err_msg)
static void xnet_log_error(const char* err_msg, ISC_STATUS* status = 0)
{
gds__log("XNET error: %s", err_msg);
if (status && status[1])
{
Firebird::string str("XNET error: ");
str += err_msg;
gds__log_status(str.c_str(), status);
}
else
gds__log("XNET error: %s", err_msg);
}
#ifdef DEV_BUILD
#define ERR_STR2(str, lnum) (str #lnum)
#define ERR_STR1(str, lnum) ERR_STR2(str " at line ", lnum)
#define ERR_STR(str) ERR_STR1(str, __LINE__)
#else
#define ERR_STR(str) (str)
#endif
rem_port* XNET_analyze(const Firebird::PathName& file_name,
ISC_STATUS* status_vector,
@ -387,7 +404,13 @@ rem_port* XNET_connect(const TEXT* name,
*
**************************************/
if (xnet_shutdown)
{
Arg::StatusVector temp;
temp << Arg::Gds(isc_net_server_shutdown) << Arg::Str("XNET");
temp.copyTo(status_vector);
return NULL;
}
if (packet)
{
@ -412,6 +435,7 @@ rem_port* XNET_reconnect(ULONG client_pid, ISC_STATUS* status_vector)
**************************************/
rem_port* port = NULL;
XPM xpm = NULL;
// Initialize server-side IPC endpoint to a value we know we have permissions to listen at
if (strcmp(xnet_endpoint, "") == 0) {
@ -426,48 +450,42 @@ rem_port* XNET_reconnect(ULONG client_pid, ISC_STATUS* status_vector)
// current_process_id used as map number
current_process_id = getpid();
try {
try
{
TEXT name_buffer[BUFFER_TINY];
make_obj_name(name_buffer, sizeof(name_buffer), XNET_RESPONSE_EVENT);
xnet_response_event = OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xnet_response_event) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("OpenEvent"));
}
XPM xpm = make_xpm(current_process_id, 0);
if (!xpm) {
Firebird::LongJump::raise();
}
xpm = make_xpm(current_process_id, 0);
port = get_server_port(client_pid, xpm, current_process_id, 0, 0, status_vector);
// make signal for client
SetEvent(xnet_response_event);
if (xnet_response_event) {
CloseHandle(xnet_response_event);
}
}
catch (const Firebird::Exception&) {
xnet_log_error("Unable to initialize child process");
status_vector[1] = isc_unavailable;
catch (const Firebird::Exception& ex) {
stuff_exception(status_vector, ex);
xnet_log_error("Unable to initialize child process", status_vector);
if (port) {
cleanup_port(port);
port = NULL;
}
else if (xpm)
cleanup_mapping(xpm);
}
if (xnet_response_event) {
SetEvent(xnet_response_event); // to prevent client blocking
CloseHandle(xnet_response_event);
}
if (xnet_response_event)
{
SetEvent(xnet_response_event); // to prevent client blocking
CloseHandle(xnet_response_event);
}
return port;
}
static bool connect_init()
static bool connect_init(ISC_STATUS *status)
{
/**************************************
*
@ -492,38 +510,49 @@ static bool connect_init()
try {
make_obj_name(name_buffer, sizeof(name_buffer), XNET_CONNECT_MUTEX);
xnet_connect_mutex = OpenMutex(MUTEX_ALL_ACCESS, TRUE, name_buffer);
if (!xnet_connect_mutex) {
Firebird::LongJump::raise();
if (!xnet_connect_mutex)
{
if (ERRNO == ERROR_FILE_NOT_FOUND)
{
Arg::Gds temp(isc_unavailable);
temp.copyTo(status);
return false;
}
Firebird::system_error::raise(ERR_STR("OpenMutex"));
}
make_obj_name(name_buffer, sizeof(name_buffer), XNET_CONNECT_EVENT);
xnet_connect_event = OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xnet_connect_event) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("OpenEvent"));
}
make_obj_name(name_buffer, sizeof(name_buffer), XNET_RESPONSE_EVENT);
xnet_response_event = OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xnet_response_event) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("OpenEvent"));
}
make_obj_name(name_buffer, sizeof(name_buffer), XNET_CONNECT_MAP);
xnet_connect_map_h = OpenFileMapping(FILE_MAP_WRITE, TRUE, name_buffer);
if (!xnet_connect_map_h) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("OpenFileMapping"));
}
xnet_connect_map =
xnet_connect_map =
MapViewOfFile(xnet_connect_map_h, FILE_MAP_WRITE, 0, 0,
XNET_CONNECT_RESPONZE_SIZE);
if (!xnet_connect_map) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("MapViewOfFile"));
}
return true;
}
catch (const Firebird::Exception&) {
catch (const Firebird::Exception& ex)
{
stuff_exception(status, ex);
connect_fini();
return false;
}
@ -710,7 +739,7 @@ static rem_port* aux_connect(rem_port* port, PACKET* packet, t_event_ast ast)
xcc->xcc_event_send_channel_filled =
OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xcc->xcc_event_send_channel_filled) {
Firebird::LongJump::raise();
Firebird::system_call_failed::raise(ERR_STR("OpenEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_C2S_EVNT_CHAN_EMPTED,
@ -718,7 +747,7 @@ static rem_port* aux_connect(rem_port* port, PACKET* packet, t_event_ast ast)
xcc->xcc_event_send_channel_empted =
OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xcc->xcc_event_send_channel_empted) {
Firebird::LongJump::raise();
Firebird::system_call_failed::raise(ERR_STR("OpenEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_S2C_EVNT_CHAN_FILLED,
@ -726,7 +755,7 @@ static rem_port* aux_connect(rem_port* port, PACKET* packet, t_event_ast ast)
xcc->xcc_event_recv_channel_filled =
OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xcc->xcc_event_recv_channel_filled) {
Firebird::LongJump::raise();
Firebird::system_call_failed::raise(ERR_STR("OpenEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_S2C_EVNT_CHAN_EMPTED,
@ -734,7 +763,7 @@ static rem_port* aux_connect(rem_port* port, PACKET* packet, t_event_ast ast)
xcc->xcc_event_recv_channel_empted =
OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xcc->xcc_event_recv_channel_empted) {
Firebird::LongJump::raise();
Firebird::system_call_failed::raise(ERR_STR("OpenEvent"));
}
// send and receive events channels
@ -837,7 +866,7 @@ static rem_port* aux_request(rem_port* port, PACKET* packet)
if (!xcc->xcc_event_recv_channel_filled ||
(xcc->xcc_event_recv_channel_filled && ERRNO == ERROR_ALREADY_EXISTS))
{
Firebird::LongJump::raise();
Firebird::system_call_failed::raise(ERR_STR("CreateEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_C2S_EVNT_CHAN_EMPTED,
@ -847,7 +876,7 @@ static rem_port* aux_request(rem_port* port, PACKET* packet)
if (!xcc->xcc_event_recv_channel_empted ||
(xcc->xcc_event_recv_channel_empted && ERRNO == ERROR_ALREADY_EXISTS))
{
Firebird::LongJump::raise();
Firebird::system_call_failed::raise(ERR_STR("CreateEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_S2C_EVNT_CHAN_FILLED,
@ -857,7 +886,7 @@ static rem_port* aux_request(rem_port* port, PACKET* packet)
if (!xcc->xcc_event_send_channel_filled ||
(xcc->xcc_event_send_channel_filled && ERRNO == ERROR_ALREADY_EXISTS))
{
Firebird::LongJump::raise();
Firebird::system_call_failed::raise(ERR_STR("CreateEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_S2C_EVNT_CHAN_EMPTED,
@ -867,7 +896,7 @@ static rem_port* aux_request(rem_port* port, PACKET* packet)
if (!xcc->xcc_event_send_channel_empted ||
(xcc->xcc_event_send_channel_empted && ERRNO == ERROR_ALREADY_EXISTS))
{
Firebird::LongJump::raise();
Firebird::system_call_failed::raise(ERR_STR("CreateEvent"));
}
// send and receive events channels
@ -938,7 +967,9 @@ static void cleanup_comm(XCC xcc)
*
**************************************/
XPS xps = (XPS) xcc->xcc_mapped_addr;
xps->xps_flags |= XPS_DISCONNECTED;
if (xps) {
xps->xps_flags |= XPS_DISCONNECTED;
}
if (xcc->xcc_event_send_channel_filled) {
CloseHandle(xcc->xcc_event_send_channel_filled);
@ -957,36 +988,35 @@ static void cleanup_comm(XCC xcc)
}
XPM xpm = xcc->xcc_xpm;
if (xpm) {
cleanup_mapping(xpm);
}
delete xcc;
}
static void cleanup_mapping(XPM xpm)
{
Firebird::MutexLockGuard guard(xnet_mutex);
// if this was the last area for this map, unmap it
xpm->xpm_count--;
if (!xpm->xpm_count && global_client_maps)
{
UnmapViewOfFile(xpm->xpm_address);
CloseHandle(xpm->xpm_handle);
if (xpm) {
xpm->xpm_count--;
Firebird::MutexLockGuard guard(xnet_mutex);
if (!xpm->xpm_count && global_client_maps) {
UnmapViewOfFile(xpm->xpm_address);
CloseHandle(xpm->xpm_handle);
// find xpm in chain and release
if (xpm == global_client_maps) {
global_client_maps = xpm->xpm_next;
// find xpm in chain and release
XPM *pxpm = &global_client_maps;
for (; *pxpm; pxpm = &(*pxpm)->xpm_next)
if (*pxpm == xpm)
{
*pxpm = xpm->xpm_next;
break;
}
else {
for (XPM pxpm = global_client_maps; pxpm->xpm_next;
pxpm = pxpm->xpm_next)
{
if (pxpm->xpm_next == xpm) {
pxpm->xpm_next = xpm->xpm_next;
break;
}
}
}
delete xpm;
}
delete xpm;
}
}
@ -1007,11 +1037,19 @@ static void cleanup_port(rem_port* port)
if (port->port_xcc) {
cleanup_comm((XCC) port->port_xcc);
port->port_xcc = NULL;
}
port->release();
}
static void raise_lostconn_or_syserror(const char* msg)
{
if (ERRNO == ERROR_FILE_NOT_FOUND)
Firebird::status_exception::raise(Arg::Gds(isc_lost_db_connection));
else
Firebird::system_error::raise(msg);
}
static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
{
@ -1050,22 +1088,34 @@ static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
// under restricted account in the same session as the client
fb_utils::copy_terminate(xnet_endpoint, Config::getIpcName(), sizeof(xnet_endpoint));
if (!connect_init()) {
if (!connect_init(status_vector))
{
// The client may not have permissions to create global objects,
// but still be able to connect to a local server that has such permissions.
// This is why we try to connect using Global\ namespace unconditionally
fb_utils::snprintf(xnet_endpoint, sizeof(xnet_endpoint), "Global\\%s", Config::getIpcName());
if (!connect_init()) {
fb_utils::init_status(status_vector);
if (!connect_init(status_vector)) {
return NULL;
}
}
// setup status with net read error in case of wait timeout
Arg::StatusVector temp;
temp << Arg::Gds(isc_net_read_err);
DWORD err = 0;
// waiting for XNET connect lock to release
if (WaitForSingleObject(xnet_connect_mutex, XNET_CONNECT_TIMEOUT) != WAIT_OBJECT_0)
err = WaitForSingleObject(xnet_connect_mutex, XNET_CONNECT_TIMEOUT);
if (err != WAIT_OBJECT_0)
{
connect_fini();
temp << SYS_ERR(err);
temp.copyTo(status_vector);
return NULL;
}
@ -1081,10 +1131,15 @@ static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
// waiting for server response
if (WaitForSingleObject(xnet_response_event, XNET_CONNECT_TIMEOUT) != WAIT_OBJECT_0)
err = WaitForSingleObject(xnet_response_event, XNET_CONNECT_TIMEOUT);
if (err != WAIT_OBJECT_0)
{
ReleaseMutex(xnet_connect_mutex);
connect_fini();
temp << SYS_ERR(err);
temp.copyTo(status_vector);
return NULL;
}
@ -1095,6 +1150,11 @@ static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
if (response.map_num == XNET_INVALID_MAP_NUM) {
xnet_log_error("Server failed to respond on connect request");
Arg::StatusVector temp;
temp << Arg::Gds(isc_net_connect_err);
temp.copyTo(status_vector);
return NULL;
}
@ -1136,13 +1196,13 @@ static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
map_num, timestamp);
file_handle = OpenFileMapping(FILE_MAP_WRITE, FALSE, name_buffer);
if (!file_handle) {
Firebird::LongJump::raise();
raise_lostconn_or_syserror(ERR_STR("OpenFileMapping"));
}
mapped_address = MapViewOfFile(file_handle, FILE_MAP_WRITE, 0L, 0L,
XPS_MAPPED_SIZE(global_slots_per_map, global_pages_per_slot));
if (!mapped_address) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("MapViewOfFile"));
}
xpm = new struct xpm;
@ -1156,6 +1216,8 @@ static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
xpm->xpm_timestamp = timestamp;
xpm->xpm_flags = 0;
}
xpm->xpm_count++;
} // xnet_mutex scope
// there's no thread structure, so make one
@ -1185,17 +1247,15 @@ static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
xcc->xcc_proc_h = OpenProcess(SYNCHRONIZE, 0, xps->xps_server_proc_id);
if (!xcc->xcc_proc_h) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("OpenProcess"));
}
xpm->xpm_count++;
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_C2S_DATA_CHAN_FILLED,
map_num, slot_num, timestamp);
xcc->xcc_event_send_channel_filled =
OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xcc->xcc_event_send_channel_filled) {
Firebird::LongJump::raise();
raise_lostconn_or_syserror(ERR_STR("OpenEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_C2S_DATA_CHAN_EMPTED,
@ -1203,7 +1263,7 @@ static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
xcc->xcc_event_send_channel_empted =
OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xcc->xcc_event_send_channel_empted) {
Firebird::LongJump::raise();
raise_lostconn_or_syserror(ERR_STR("OpenEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_S2C_DATA_CHAN_FILLED,
@ -1211,7 +1271,7 @@ static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
xcc->xcc_event_recv_channel_filled =
OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xcc->xcc_event_recv_channel_filled) {
Firebird::LongJump::raise();
raise_lostconn_or_syserror(ERR_STR("OpenEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_S2C_DATA_CHAN_EMPTED,
@ -1219,7 +1279,7 @@ static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
xcc->xcc_event_recv_channel_empted =
OpenEvent(EVENT_ALL_ACCESS, FALSE, name_buffer);
if (!xcc->xcc_event_recv_channel_empted) {
Firebird::LongJump::raise();
raise_lostconn_or_syserror(ERR_STR("OpenEvent"));
}
// added this here from the server side as this part is called by the client
@ -1254,33 +1314,20 @@ static rem_port* connect_client(PACKET* packet, ISC_STATUS* status_vector)
return port;
}
catch (const Firebird::Exception&) {
catch (const Firebird::Exception& ex)
{
stuff_exception(status_vector, ex);
if (file_handle) {
if (xcc)
cleanup_comm(xcc);
else if (xpm)
cleanup_mapping(xpm);
else if (file_handle) {
if (mapped_address) {
UnmapViewOfFile(mapped_address);
}
CloseHandle(file_handle);
}
delete xpm;
if (xcc) {
if (xcc->xcc_event_send_channel_filled) {
CloseHandle(xcc->xcc_event_send_channel_filled);
}
if (xcc->xcc_event_send_channel_empted) {
CloseHandle(xcc->xcc_event_send_channel_empted);
}
if (xcc->xcc_event_recv_channel_filled) {
CloseHandle(xcc->xcc_event_recv_channel_filled);
}
if (xcc->xcc_event_recv_channel_empted) {
CloseHandle(xcc->xcc_event_recv_channel_empted);
}
delete xcc;
}
return NULL;
}
}
@ -1300,7 +1347,7 @@ static rem_port* connect_server(ISC_STATUS* status_vector, USHORT flag)
**************************************/
current_process_id = getpid();
if (!server_init(flag))
if (!server_init(status_vector, flag))
return NULL;
PXNET_RESPONSE presponse = (PXNET_RESPONSE)xnet_connect_map;
@ -1332,31 +1379,35 @@ static rem_port* connect_server(ISC_STATUS* status_vector, USHORT flag)
ULONG map_num, slot_num;
ULONG timestamp = (ULONG) time(NULL);
XPM xpm = get_free_slot(&map_num, &slot_num, &timestamp);
XPM xpm = NULL;
try
{
xpm = get_free_slot(&map_num, &slot_num, &timestamp);
// pack combined mapped area and number
if (xpm) {
// pack combined mapped area and number
presponse->proc_id = 0;
presponse->map_num = map_num;
presponse->slot_num = slot_num;
presponse->timestamp = timestamp;
try {
rem_port* port =
get_server_port(client_pid, xpm, map_num, slot_num,
timestamp, status_vector);
rem_port* port =
get_server_port(client_pid, xpm, map_num, slot_num, timestamp, status_vector);
SetEvent(xnet_response_event);
SetEvent(xnet_response_event);
return port;
}
catch (const Firebird::Exception&) {
xnet_log_error("Failed to allocate server port for communication");
break;
}
return port;
}
else {
xnet_log_error("get_free_slot() failed");
catch (const Firebird::Exception& ex)
{
stuff_exception(status_vector, ex);
xnet_log_error("Failed to allocate server port for communication", status_vector);
fb_utils::init_status(status_vector);
if (xpm)
cleanup_mapping(xpm);
SetEvent(xnet_response_event);
break;
}
}
@ -1372,6 +1423,13 @@ static rem_port* connect_server(ISC_STATUS* status_vector, USHORT flag)
}
}
if (xnet_shutdown)
{
Arg::StatusVector temp;
temp << Arg::Gds(isc_net_server_shutdown) << Arg::Str("XNET");
temp.copyTo(status_vector);
}
return NULL;
}
@ -1445,6 +1503,14 @@ static void exit_handler(rem_port* main_port)
}
}
static int shut_main_port(const int, const int, void* arg)
{
xnet_shutdown = true;
SetEvent(xnet_connect_event);
return 0;
}
static rem_port* receive( rem_port* main_port, PACKET * packet)
{
@ -2075,14 +2141,23 @@ static bool make_map(ULONG map_number,
0L,
XPS_MAPPED_SIZE(global_slots_per_map, global_pages_per_slot),
name_buffer);
if (!(*map_handle) || (*map_handle && ERRNO == ERROR_ALREADY_EXISTS))
return false;
*map_address = MapViewOfFile(*map_handle, FILE_MAP_WRITE, 0, 0,
XPS_MAPPED_SIZE(global_slots_per_map, global_pages_per_slot));
if (!(*map_address)) {
CloseHandle(*map_handle);
return false;
try
{
if (!(*map_handle) || (ERRNO == ERROR_ALREADY_EXISTS))
Firebird::system_error::raise(ERR_STR("CreateFileMapping"));
*map_address = MapViewOfFile(*map_handle, FILE_MAP_WRITE, 0, 0,
XPS_MAPPED_SIZE(global_slots_per_map, global_pages_per_slot));
if (!(*map_address))
Firebird::system_error::raise(ERR_STR("MapViewOfFile"));
}
catch(const Firebird::Exception&)
{
if (*map_handle)
CloseHandle(*map_handle);
throw;
}
return true;
@ -2109,35 +2184,29 @@ static XPM make_xpm(ULONG map_number, ULONG timestamp)
// allocate XPM structure and initialize it
try
{
XPM xpm = new struct xpm;
XPM xpm = new struct xpm;
xpm->xpm_handle = map_handle;
xpm->xpm_address = map_address;
xpm->xpm_number = map_number;
xpm->xpm_count = 0;
xpm->xpm_timestamp = timestamp;
xpm->xpm_handle = map_handle;
xpm->xpm_address = map_address;
xpm->xpm_number = map_number;
xpm->xpm_count = 0;
xpm->xpm_timestamp = timestamp;
for (USHORT i = 0; i < global_slots_per_map; i++) {
xpm->xpm_ids[i] = XPM_FREE;
}
xpm->xpm_flags = 0;
Firebird::MutexLockGuard guard(xnet_mutex);
xpm->xpm_next = global_client_maps;
global_client_maps = xpm;
return xpm;
}
catch (const Firebird::Exception&) {
return NULL;
for (USHORT i = 0; i < global_slots_per_map; i++) {
xpm->xpm_ids[i] = XPM_FREE;
}
xpm->xpm_flags = 0;
Firebird::MutexLockGuard guard(xnet_mutex);
xpm->xpm_next = global_client_maps;
global_client_maps = xpm;
return xpm;
}
static bool server_init(USHORT flag)
static bool server_init(ISC_STATUS* status, USHORT flag)
{
/**************************************
*
@ -2185,7 +2254,7 @@ static bool server_init(USHORT flag)
CreateMutex(ISC_get_security_desc(), FALSE, name_buffer);
if (!xnet_connect_mutex || (xnet_connect_mutex && ERRNO == ERROR_ALREADY_EXISTS))
{
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("CreateMutex"));
}
make_obj_name(name_buffer, sizeof(name_buffer), XNET_CONNECT_EVENT);
@ -2193,7 +2262,7 @@ static bool server_init(USHORT flag)
CreateEvent(ISC_get_security_desc(), FALSE, FALSE, name_buffer);
if (!xnet_connect_event || (xnet_connect_event && ERRNO == ERROR_ALREADY_EXISTS))
{
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("CreateEvent"));
}
make_obj_name(name_buffer, sizeof(name_buffer), XNET_RESPONSE_EVENT);
@ -2201,7 +2270,7 @@ static bool server_init(USHORT flag)
CreateEvent(ISC_get_security_desc(), FALSE, FALSE, name_buffer);
if (!xnet_response_event || (xnet_response_event && ERRNO == ERROR_ALREADY_EXISTS))
{
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("CreateEvent"));
}
make_obj_name(name_buffer, sizeof(name_buffer), XNET_CONNECT_MAP);
@ -2213,23 +2282,29 @@ static bool server_init(USHORT flag)
name_buffer);
if (!xnet_connect_map_h || (xnet_connect_map_h && ERRNO == ERROR_ALREADY_EXISTS))
{
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("CreateFileMapping"));
}
xnet_connect_map = MapViewOfFile(xnet_connect_map_h, FILE_MAP_WRITE, 0L, 0L,
XNET_CONNECT_RESPONZE_SIZE);
if (!xnet_connect_map) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("MapViewOfFile"));
}
}
catch (const Firebird::Exception&) {
catch (const Firebird::Exception& ex)
{
stuff_exception(status, ex);
xnet_log_error("XNET server initialization failed", status);
connect_fini();
xnet_log_error("Server initialization failed");
xnet_shutdown = true;
return false;
}
xnet_initialized = true;
gds__register_cleanup((FPTR_VOID_PTR) exit_handler, NULL);
fb_shutdown_callback(0, shut_main_port, fb_shut_postproviders, 0);
return true;
}
@ -2257,11 +2332,6 @@ static XPM get_free_slot(ULONG* map_num, ULONG* slot_num, ULONG* timestamp)
for (xpm = global_client_maps; xpm; xpm = xpm->xpm_next)
{
// hvlad: MAX xpm_number must be recorded at the head of the list
// (i.e. at global_client_maps) but lets not depends on this implicit
// order and calculate MAX xpm_number always
free_map = MAX(xpm->xpm_number, free_map);
// find an available unused comm area
for (free_slot = 0; free_slot < global_slots_per_map; free_slot++)
@ -2284,18 +2354,12 @@ static XPM get_free_slot(ULONG* map_num, ULONG* slot_num, ULONG* timestamp)
if (!xpm)
{
free_map++;
free_map = xnet_next_free_map_num++;
// allocate new map file and first slot
xpm = make_xpm(free_map, *timestamp);
// check for errors in creation of mapped file
if (!xpm) {
return NULL;
}
free_slot = 0;
xpm->xpm_ids[0] = XPM_BUSY;
xpm->xpm_count++;
@ -2400,7 +2464,7 @@ static rem_port* get_server_port(ULONG client_pid,
xcc->xcc_proc_h = OpenProcess(SYNCHRONIZE, 0, client_pid);
if (!xcc->xcc_proc_h) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("OpenProcess"));
}
xcc->xcc_map_num = map_num;
@ -2418,7 +2482,7 @@ static rem_port* get_server_port(ULONG client_pid,
xcc->xcc_event_recv_channel_filled =
CreateEvent(ISC_get_security_desc(), FALSE, FALSE, name_buffer);
if (!xcc->xcc_event_recv_channel_filled) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("CreateEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_C2S_DATA_CHAN_EMPTED,
@ -2426,7 +2490,7 @@ static rem_port* get_server_port(ULONG client_pid,
xcc->xcc_event_recv_channel_empted =
CreateEvent(ISC_get_security_desc(), FALSE, FALSE, name_buffer);
if (!xcc->xcc_event_recv_channel_empted) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("CreateEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_S2C_DATA_CHAN_FILLED,
@ -2434,7 +2498,7 @@ static rem_port* get_server_port(ULONG client_pid,
xcc->xcc_event_send_channel_filled =
CreateEvent(ISC_get_security_desc(), FALSE, FALSE, name_buffer);
if (!xcc->xcc_event_send_channel_filled) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("CreateEvent"));
}
make_event_name(name_buffer, sizeof(name_buffer), XNET_E_S2C_DATA_CHAN_EMPTED,
@ -2442,7 +2506,7 @@ static rem_port* get_server_port(ULONG client_pid,
xcc->xcc_event_send_channel_empted =
CreateEvent(ISC_get_security_desc(), FALSE, FALSE, name_buffer);
if (!xcc->xcc_event_send_channel_empted) {
Firebird::LongJump::raise();
Firebird::system_error::raise(ERR_STR("CreateEvent"));
}
// set up the channel structures
@ -2493,26 +2557,10 @@ static rem_port* get_server_port(ULONG client_pid,
gds__register_cleanup((FPTR_VOID_PTR) exit_handler, port);
}
catch (const Firebird::Exception&) {
if (xcc) {
if (xcc->xcc_proc_h) {
CloseHandle(xcc->xcc_proc_h);
}
if (xcc->xcc_event_recv_channel_filled) {
CloseHandle(xcc->xcc_event_recv_channel_filled);
}
if (xcc->xcc_event_recv_channel_empted) {
CloseHandle(xcc->xcc_event_recv_channel_empted);
}
if (xcc->xcc_event_send_channel_filled) {
CloseHandle(xcc->xcc_event_send_channel_filled);
}
if (xcc->xcc_event_send_channel_empted) {
CloseHandle(xcc->xcc_event_send_channel_empted);
}
delete xcc;
}
if (port)
cleanup_port(port);
else if (xcc)
cleanup_comm(xcc);
throw;
}