server.cpp (Firebird-3.0.2.32703-0.tar.bz2) | : | server.cpp (Firebird-3.0.4.33054-0.tar.bz2) | ||
---|---|---|---|---|
skipping to change at line 122 | skipping to change at line 122 | |||
explicit NetworkCallback(rem_port* prt) | explicit NetworkCallback(rem_port* prt) | |||
: port(prt), l(0), d(NULL), stopped(false), wake(false) | : port(prt), l(0), d(NULL), stopped(false), wake(false) | |||
{ } | { } | |||
unsigned int callback(unsigned int dataLength, const void* data, | unsigned int callback(unsigned int dataLength, const void* data, | |||
unsigned int bufferLength, void* buffer) | unsigned int bufferLength, void* buffer) | |||
{ | { | |||
if (stopped) | if (stopped) | |||
return 0; | return 0; | |||
if (port->port_protocol < PROTOCOL_VERSION13) | if (port->port_protocol < PROTOCOL_VERSION13 || port->port_type ! = rem_port::INET) | |||
return 0; | return 0; | |||
Reference r(*port); | Reference r(*port); | |||
d = buffer; | d = buffer; | |||
l = bufferLength; | l = bufferLength; | |||
PACKET p; | PACKET p; | |||
p.p_operation = op_crypt_key_callback; | p.p_operation = op_crypt_key_callback; | |||
p.p_cc.p_cc_data.cstr_length = dataLength; | p.p_cc.p_cc_data.cstr_length = dataLength; | |||
skipping to change at line 147 | skipping to change at line 147 | |||
if (!sem.tryEnter(60)) | if (!sem.tryEnter(60)) | |||
return 0; | return 0; | |||
return l; | return l; | |||
} | } | |||
void wakeup(unsigned int length, const void* data) | void wakeup(unsigned int length, const void* data) | |||
{ | { | |||
if (l > length) | if (l > length) | |||
l = length; | l = length; | |||
memcpy(d, data, l); | ||||
wake = true; | if (data) | |||
{ | ||||
memcpy(d, data, l); | ||||
wake = true; | ||||
} | ||||
else | ||||
stop(); | ||||
sem.release(); | sem.release(); | |||
} | } | |||
void stop() | void stop() | |||
{ | { | |||
stopped = true; | stopped = true; | |||
} | } | |||
bool isStopped() const | bool isStopped() const | |||
{ | { | |||
skipping to change at line 197 | skipping to change at line 203 | |||
unsigned int callback(unsigned int dataLength, const void* data, | unsigned int callback(unsigned int dataLength, const void* data, | |||
unsigned int bufferLength, void* buffer) | unsigned int bufferLength, void* buffer) | |||
{ | { | |||
if (keyCallback) | if (keyCallback) | |||
return keyCallback->callback(dataLength, data, bufferLeng th, buffer); | return keyCallback->callback(dataLength, data, bufferLeng th, buffer); | |||
if (networkCallback.isStopped()) | if (networkCallback.isStopped()) | |||
return 0; | return 0; | |||
Reference r(*port); | Reference r(*port); | |||
loadClientKey(); | ||||
unsigned rc = keyCallback ? | ||||
keyCallback->callback(dataLength, data, bufferLength, buf | ||||
fer) : | ||||
// use legacy behavior if holders do wish to accept keys | ||||
from client | ||||
networkCallback.callback(dataLength, data, bufferLength, | ||||
buffer); | ||||
return rc; | ||||
} | ||||
void loadClientKey() | ||||
{ | ||||
if (keyCallback) | ||||
return; | ||||
Reference r(*port); | ||||
for (GetPlugins<IKeyHolderPlugin> kh(IPluginManager::TYPE_KEY_HOL DER, port->getPortConfig()); | for (GetPlugins<IKeyHolderPlugin> kh(IPluginManager::TYPE_KEY_HOL DER, port->getPortConfig()); | |||
kh.hasData(); kh.next()) | kh.hasData(); kh.next()) | |||
{ | { | |||
IKeyHolderPlugin* keyPlugin = kh.plugin(); | IKeyHolderPlugin* keyPlugin = kh.plugin(); | |||
LocalStatus ls; | LocalStatus ls; | |||
CheckStatusWrapper st(&ls); | CheckStatusWrapper st(&ls); | |||
networkCallback.wake = false; | networkCallback.wake = false; | |||
if (keyPlugin->keyCallback(&st, &networkCallback) && netw | bool callbackResult = keyPlugin->keyCallback(&st, &networ | |||
orkCallback.wake) | kCallback); | |||
if (st.getErrors()[1] != isc_wish_list) | ||||
check(&st); | ||||
if (callbackResult && networkCallback.wake) | ||||
{ | { | |||
// current holder has a key and it seems to be fr om the client | // current holder has a key and it seems to be fr om the client | |||
keyHolder = keyPlugin; | keyHolder = keyPlugin; | |||
keyHolder->addRef(); | keyHolder->addRef(); | |||
keyCallback = keyHolder->chainHandle(&st); | keyCallback = keyHolder->chainHandle(&st); | |||
if (st.isEmpty() && keyCallback) | if (st.isEmpty()) | |||
break; | { | |||
if (keyCallback) | ||||
break; | ||||
} | ||||
else if (st.getErrors()[1] != isc_wish_list) | ||||
check(&st); | ||||
} | } | |||
} | } | |||
unsigned rc = keyCallback ? | ||||
keyCallback->callback(dataLength, data, bufferLength, buf | ||||
fer) : | ||||
// use legacy behavior if holders to do wish to accept ke | ||||
ys from client | ||||
networkCallback.callback(dataLength, data, bufferLength, | ||||
buffer); | ||||
//stop(); | ||||
return rc; | ||||
} | } | |||
void wakeup(unsigned int length, const void* data) | void wakeup(unsigned int length, const void* data) | |||
{ | { | |||
networkCallback.wakeup(length, data); | networkCallback.wakeup(length, data); | |||
} | } | |||
void stop() | void stop() | |||
{ | { | |||
networkCallback.stop(); | networkCallback.stop(); | |||
skipping to change at line 261 | skipping to change at line 282 | |||
~ServerCallback() | ~ServerCallback() | |||
{ } | { } | |||
void wakeup(unsigned int length, const void* data) | void wakeup(unsigned int length, const void* data) | |||
{ | { | |||
cryptCallback.wakeup(length, data); | cryptCallback.wakeup(length, data); | |||
} | } | |||
ICryptKeyCallback* getInterface() | ICryptKeyCallback* getInterface() | |||
{ | { | |||
cryptCallback.loadClientKey(); | ||||
return &cryptCallback; | return &cryptCallback; | |||
} | } | |||
void stop() | void stop() | |||
{ | { | |||
cryptCallback.stop(); | cryptCallback.stop(); | |||
} | } | |||
private: | private: | |||
CryptKeyCallback cryptCallback; | CryptKeyCallback cryptCallback; | |||
skipping to change at line 388 | skipping to change at line 410 | |||
if (find(login, pos)) | if (find(login, pos)) | |||
{ | { | |||
remove(pos); | remove(pos); | |||
} | } | |||
} | } | |||
}; | }; | |||
GlobalPtr<FailedLogins> usernameFailedLogins; | GlobalPtr<FailedLogins> usernameFailedLogins; | |||
GlobalPtr<FailedLogins> remoteFailedLogins; | GlobalPtr<FailedLogins> remoteFailedLogins; | |||
bool server_shutdown = false; | bool server_shutdown = false; | |||
bool engine_shutdown = false; | ||||
void loginFail(const string& login, const string& remId) | void loginFail(const string& login, const string& remId) | |||
{ | { | |||
// do not remove variables - both functions should be called | // do not remove variables - both functions should be called | |||
bool f1 = usernameFailedLogins->loginFail(login); | bool f1 = usernameFailedLogins->loginFail(login); | |||
bool f2 = remoteFailedLogins->loginFail(remId); | bool f2 = remoteFailedLogins->loginFail(remId); | |||
if ((f1 || f2) && !server_shutdown) | if ((f1 || f2) && !engine_shutdown) | |||
{ | { | |||
// Ahh, someone is too active today | // Ahh, someone is too active today | |||
Thread::sleep(FAILURE_DELAY * 1000); | Thread::sleep(FAILURE_DELAY * 1000); | |||
} | } | |||
} | } | |||
void loginSuccess(const string& login, const string& remId) | void loginSuccess(const string& login, const string& remId) | |||
{ | { | |||
usernameFailedLogins->loginSuccess(login); | usernameFailedLogins->loginSuccess(login); | |||
remoteFailedLogins->loginSuccess(remId); | remoteFailedLogins->loginSuccess(remId); | |||
skipping to change at line 913 | skipping to change at line 936 | |||
if (port->port_flags & PORT_detached) | if (port->port_flags & PORT_detached) | |||
return; | return; | |||
// hvlad: it is important to call IEvents::cancel() under protect ion | // hvlad: it is important to call IEvents::cancel() under protect ion | |||
// of async port mutex to avoid crash in rem_port::que_events | // of async port mutex to avoid crash in rem_port::que_events | |||
const bool allowCancel = event->rvnt_destroyed.compareExchange(0, 1); | const bool allowCancel = event->rvnt_destroyed.compareExchange(0, 1); | |||
if (!allowCancel) | if (!allowCancel) | |||
return; | return; | |||
if (!(port->port_flags & PORT_disconnect)) | ||||
{ | ||||
PACKET packet; | ||||
packet.p_operation = op_event; | ||||
P_EVENT* p_event = &packet.p_event; | ||||
p_event->p_event_database = rdb->rdb_id; | ||||
p_event->p_event_items.cstr_length = length; | ||||
p_event->p_event_items.cstr_address = items; | ||||
p_event->p_event_rid = event->rvnt_id; | ||||
port->send(&packet); | ||||
} | ||||
if (event->rvnt_iface) | if (event->rvnt_iface) | |||
{ | { | |||
LocalStatus ls; | LocalStatus ls; | |||
CheckStatusWrapper status_vector(&ls); | CheckStatusWrapper status_vector(&ls); | |||
event->rvnt_iface->cancel(&status_vector); | event->rvnt_iface->cancel(&status_vector); | |||
event->rvnt_iface = NULL; | event->rvnt_iface = NULL; | |||
} | } | |||
if (port->port_flags & PORT_disconnect) | ||||
return; | ||||
PACKET packet; | ||||
packet.p_operation = op_event; | ||||
P_EVENT* p_event = &packet.p_event; | ||||
p_event->p_event_database = rdb->rdb_id; | ||||
p_event->p_event_items.cstr_length = length; | ||||
p_event->p_event_items.cstr_address = items; | ||||
p_event->p_event_rid = event->rvnt_id; | ||||
port->send(&packet); | ||||
} | } | |||
int release() | int release() | |||
{ | { | |||
if (--refCounter == 0) | if (--refCounter == 0) | |||
{ | { | |||
delete this; | delete this; | |||
return 0; | return 0; | |||
} | } | |||
skipping to change at line 1086 | skipping to change at line 1109 | |||
static void release_event(Rvnt*); | static void release_event(Rvnt*); | |||
static void release_request(Rrq*, bool rlsIface = false); | static void release_request(Rrq*, bool rlsIface = false); | |||
static void release_statement(Rsr**); | static void release_statement(Rsr**); | |||
static void release_sql_request(Rsr*); | static void release_sql_request(Rsr*); | |||
static void release_transaction(Rtr*); | static void release_transaction(Rtr*); | |||
static void send_error(rem_port* port, PACKET* apacket, ISC_STATUS er rcode); | static void send_error(rem_port* port, PACKET* apacket, ISC_STATUS er rcode); | |||
static void send_error(rem_port* port, PACKET* apacket, const Firebir d::Arg::StatusVector&); | static void send_error(rem_port* port, PACKET* apacket, const Firebir d::Arg::StatusVector&); | |||
static void set_server(rem_port*, USHORT); | static void set_server(rem_port*, USHORT); | |||
static int shut_server(const int, const int, void*); | static int shut_server(const int, const int, void*); | |||
static int pre_shutdown(const int, const int, void*); | ||||
static THREAD_ENTRY_DECLARE loopThread(THREAD_ENTRY_PARAM); | static THREAD_ENTRY_DECLARE loopThread(THREAD_ENTRY_PARAM); | |||
static void zap_packet(PACKET*, bool); | static void zap_packet(PACKET*, bool); | |||
inline bool bad_db(IStatus* status_vector, Rdb* rdb) | inline bool bad_db(IStatus* status_vector, Rdb* rdb) | |||
{ | { | |||
IReferenceCounted* iface = NULL; | IReferenceCounted* iface = NULL; | |||
if (rdb) | if (rdb) | |||
iface = rdb->rdb_iface; | iface = rdb->rdb_iface; | |||
return bad_port_context(status_vector, iface, isc_bad_db_handle); | return bad_port_context(status_vector, iface, isc_bad_db_handle); | |||
} | } | |||
skipping to change at line 1132 | skipping to change at line 1156 | |||
static bool isShuttingDown() { return shutting_down; } | static bool isShuttingDown() { return shutting_down; } | |||
static void shutdown(); | static void shutdown(); | |||
private: | private: | |||
Worker* m_next; | Worker* m_next; | |||
Worker* m_prev; | Worker* m_prev; | |||
Semaphore m_sem; | Semaphore m_sem; | |||
bool m_active; | bool m_active; | |||
bool m_going; // thread was timedout and going to be de leted | ||||
#ifdef DEV_BUILD | #ifdef DEV_BUILD | |||
ThreadId m_tid; | ThreadId m_tid; | |||
#endif | #endif | |||
void remove(); | void remove(); | |||
void insert(const bool active); | void insert(const bool active); | |||
static void wakeUpAll(); | static void wakeUpAll(); | |||
static Worker* m_activeWorkers; | static Worker* m_activeWorkers; | |||
static Worker* m_idleWorkers; | static Worker* m_idleWorkers; | |||
static GlobalPtr<Mutex> m_mutex; | static GlobalPtr<Mutex> m_mutex; | |||
static int m_cntAll; | static int m_cntAll; | |||
static int m_cntIdle; | static int m_cntIdle; | |||
static int m_cntGoing; | ||||
static bool shutting_down; | static bool shutting_down; | |||
}; | }; | |||
Worker* Worker::m_activeWorkers = NULL; | Worker* Worker::m_activeWorkers = NULL; | |||
Worker* Worker::m_idleWorkers = NULL; | Worker* Worker::m_idleWorkers = NULL; | |||
GlobalPtr<Mutex> Worker::m_mutex; | GlobalPtr<Mutex> Worker::m_mutex; | |||
int Worker::m_cntAll = 0; | int Worker::m_cntAll = 0; | |||
int Worker::m_cntIdle = 0; | int Worker::m_cntIdle = 0; | |||
int Worker::m_cntGoing = 0; | ||||
bool Worker::shutting_down = false; | bool Worker::shutting_down = false; | |||
static GlobalPtr<Mutex> request_que_mutex; | static GlobalPtr<Mutex> request_que_mutex; | |||
static server_req_t* request_que = NULL; | static server_req_t* request_que = NULL; | |||
static server_req_t* free_requests = NULL; | static server_req_t* free_requests = NULL; | |||
static server_req_t* active_requests = NULL; | static server_req_t* active_requests = NULL; | |||
static int ports_active = 0; // length of active_requests | static int ports_active = 0; // length of active_requests | |||
static int ports_pending = 0; // length of requ est_que | static int ports_pending = 0; // length of requ est_que | |||
static GlobalPtr<Mutex> servers_mutex; | static GlobalPtr<Mutex> servers_mutex; | |||
skipping to change at line 1571 | skipping to change at line 1598 | |||
continue; | continue; | |||
} | } | |||
if (!port->haveRecvData()) | if (!port->haveRecvData()) | |||
{ | { | |||
port->clearRecvQue(); | port->clearRecvQue(); | |||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
request->req_receive.p_operation = ok ? op_dummy : op_exit; | request->req_receive.p_operation = ok ? op_dummy : op_exit; | |||
if (port->port_server_crypt_callb | ||||
ack) | ||||
port->port_server_crypt_c | ||||
allback->wakeup(0, NULL); | ||||
} | } | |||
request->req_port = port; | request->req_port = port; | |||
if (portLocked) | if (portLocked) | |||
{ | { | |||
portGuard.leave(); | portGuard.leave(); | |||
} | } | |||
// link_request will increment port_reque sts_queued. Port is not locked | // link_request will increment port_reque sts_queued. Port is not locked | |||
// at this point but it is safe because : | // at this point but it is safe because : | |||
skipping to change at line 1744 | skipping to change at line 1774 | |||
} | } | |||
void accept(PACKET* send, Auth::WriterImplementation* authBlock); | void accept(PACKET* send, Auth::WriterImplementation* authBlock); | |||
bool useResponse; | bool useResponse; | |||
}; | }; | |||
static void setErrorStatus(IStatus* status) | static void setErrorStatus(IStatus* status) | |||
{ | { | |||
Arg::Gds loginError(isc_login); | Arg::Gds loginError(isc_login); | |||
#ifndef DEV_BUILD | if (!(status->getState() & IStatus::STATE_ERRORS)) | |||
if (status->getErrors()[1] == isc_missing_data_structures) | status->setErrors(loginError.value()); | |||
#endif | ||||
{ | ||||
loginError << Arg::StatusVector(status->getErrors()); | ||||
} | ||||
status->setErrors(loginError.value()); | ||||
} | } | |||
static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send) | static bool accept_connection(rem_port* port, P_CNCT* connect, PACKET* send) | |||
{ | { | |||
/************************************** | /************************************** | |||
* | * | |||
* a c c e p t _ c o n n e c t i o n | * a c c e p t _ c o n n e c t i o n | |||
* | * | |||
************************************** | ************************************** | |||
* | * | |||
skipping to change at line 1796 | skipping to change at line 1821 | |||
USHORT version = 0; | USHORT version = 0; | |||
USHORT type = 0; | USHORT type = 0; | |||
bool compress = false; | bool compress = false; | |||
bool accepted = false; | bool accepted = false; | |||
USHORT weight = 0; | USHORT weight = 0; | |||
const p_cnct::p_cnct_repeat* protocol = connect->p_cnct_versions; | const p_cnct::p_cnct_repeat* protocol = connect->p_cnct_versions; | |||
for (const p_cnct::p_cnct_repeat* const end = protocol + connect->p_cnct_ count; | for (const p_cnct::p_cnct_repeat* const end = protocol + connect->p_cnct_ count; | |||
protocol < end; protocol++) | protocol < end; protocol++) | |||
{ | { | |||
if ((protocol->p_cnct_version >= PROTOCOL_VERSION10 && | if ((protocol->p_cnct_version == PROTOCOL_VERSION10 || | |||
protocol->p_cnct_version <= PROTOCOL_VERSION15) && | (protocol->p_cnct_version >= PROTOCOL_VERSION11 && | |||
protocol->p_cnct_version <= PROTOCOL_VERSION15)) && | ||||
(protocol->p_cnct_architecture == arch_generic || | (protocol->p_cnct_architecture == arch_generic || | |||
protocol->p_cnct_architecture == ARCHITECTURE) && | protocol->p_cnct_architecture == ARCHITECTURE) && | |||
protocol->p_cnct_weight >= weight) | protocol->p_cnct_weight >= weight) | |||
{ | { | |||
accepted = true; | accepted = true; | |||
weight = protocol->p_cnct_weight; | weight = protocol->p_cnct_weight; | |||
version = protocol->p_cnct_version; | version = protocol->p_cnct_version; | |||
architecture = protocol->p_cnct_architecture; | architecture = protocol->p_cnct_architecture; | |||
type = MIN(protocol->p_cnct_max_type & ptype_MASK, ptype_ lazy_send); | type = MIN(protocol->p_cnct_max_type & ptype_MASK, ptype_ lazy_send); | |||
compress = protocol->p_cnct_max_type & pflag_compress; | compress = protocol->p_cnct_max_type & pflag_compress; | |||
skipping to change at line 1972 | skipping to change at line 1998 | |||
} | } | |||
} | } | |||
} | } | |||
} | } | |||
// Send off out gracious acceptance or flag rejection | // Send off out gracious acceptance or flag rejection | |||
if (!accepted) | if (!accepted) | |||
{ | { | |||
HANDSHAKE_DEBUG(fprintf(stderr, "!accepted, sending reject\n")); | HANDSHAKE_DEBUG(fprintf(stderr, "!accepted, sending reject\n")); | |||
if (status.getState() & Firebird::IStatus::STATE_ERRORS) | if (status.getState() & Firebird::IStatus::STATE_ERRORS) | |||
port->send_response(send, 0, 0, &status, false); | { | |||
if (status.getErrors()[1] != isc_missing_data_structures) | ||||
{ | ||||
iscLogStatus("Authentication error", &status); | ||||
Arg::Gds loginError(isc_login_error); | ||||
#ifdef DEV_BUILD | ||||
loginError << Arg::StatusVector(&status); | ||||
#endif | ||||
LocalStatus tmp; | ||||
loginError.copyTo(&tmp); | ||||
port->send_response(send, 0, 0, &tmp, false); | ||||
} | ||||
else | ||||
port->send_response(send, 0, 0, &status, false); | ||||
} | ||||
else | else | |||
port->send(send); | port->send(send); | |||
return false; | return false; | |||
} | } | |||
// extractNewKeys() will also send to client list of known plugins | // extractNewKeys() will also send to client list of known plugins | |||
if (version >= PROTOCOL_VERSION13 && | if (version >= PROTOCOL_VERSION13 && | |||
port->extractNewKeys(&send->p_acpd.p_acpt_keys, returnData)) | port->extractNewKeys(&send->p_acpd.p_acpt_keys, returnData)) | |||
{ | { | |||
returnData = true; | returnData = true; | |||
skipping to change at line 2156 | skipping to change at line 2196 | |||
} | } | |||
ClumpletWriter address_record(ClumpletReader::UnTagged, MAX_UCHAR - 2); | ClumpletWriter address_record(ClumpletReader::UnTagged, MAX_UCHAR - 2); | |||
if (port->port_protocol_id.hasData()) | if (port->port_protocol_id.hasData()) | |||
address_record.insertString(isc_dpb_addr_protocol, port->port_pro tocol_id); | address_record.insertString(isc_dpb_addr_protocol, port->port_pro tocol_id); | |||
if (port->port_address.hasData()) | if (port->port_address.hasData()) | |||
address_record.insertString(isc_dpb_addr_endpoint, port->port_add ress); | address_record.insertString(isc_dpb_addr_endpoint, port->port_add ress); | |||
int flags = 0; | ||||
#ifdef WIRE_COMPRESS_SUPPORT | ||||
if (port->port_compressed) | ||||
flags |= isc_dpb_addr_flag_conn_compressed; | ||||
#endif | ||||
if (port->port_crypt_plugin) | ||||
flags |= isc_dpb_addr_flag_conn_encrypted; | ||||
if (flags) | ||||
address_record.insertInt(isc_dpb_addr_flags, flags); | ||||
// We always insert remote address descriptor as a first element | // We always insert remote address descriptor as a first element | |||
// of appropriate clumplet so user cannot fake it and engine may somewhat trust it. | // of appropriate clumplet so user cannot fake it and engine may somewhat trust it. | |||
fb_assert(address_stack_buffer.getCurOffset() == 0); | fb_assert(address_stack_buffer.getCurOffset() == 0); | |||
address_stack_buffer.insertBytes(isc_dpb_address, | address_stack_buffer.insertBytes(isc_dpb_address, | |||
address_record.getBuffer(), address_record.getBufferLength()); | address_record.getBuffer(), address_record.getBufferLength()); | |||
dpb_buffer->insertBytes(par.address_path, address_stack_buffer.getBuffer( ), | dpb_buffer->insertBytes(par.address_path, address_stack_buffer.getBuffer( ), | |||
address_stack_buf fer.getBufferLength()); | address_stack_buf fer.getBufferLength()); | |||
// Remove all remaining isc_*pb_address_path clumplets. | // Remove all remaining isc_*pb_address_path clumplets. | |||
skipping to change at line 2503 | skipping to change at line 2554 | |||
* c a n c e l _ o p e r a t i o n | * c a n c e l _ o p e r a t i o n | |||
* | * | |||
************************************** | ************************************** | |||
* | * | |||
* Functional description | * Functional description | |||
* Flag a running operation for cancel. | * Flag a running operation for cancel. | |||
* Service operations are not currently | * Service operations are not currently | |||
* able to be canceled. | * able to be canceled. | |||
* | * | |||
**************************************/ | **************************************/ | |||
Rdb* rdb; | if ((port->port_flags & (PORT_async | PORT_disconnect)) || !(port->port_c | |||
if ((port->port_flags & (PORT_async | PORT_disconnect)) || !(rdb = port-> | ontext)) | |||
port_context)) | ||||
return; | return; | |||
if (rdb->rdb_iface) | ServAttachment iface; | |||
{ | ||||
RefMutexGuard portGuard(*port->port_cancel_sync, FB_FUNCTION); | ||||
Rdb* rdb; | ||||
if ((port->port_flags & PORT_disconnect) || !(rdb = port->port_co | ||||
ntext)) | ||||
return; | ||||
iface = rdb->rdb_iface; | ||||
} | ||||
if (iface) | ||||
{ | { | |||
LocalStatus ls; | LocalStatus ls; | |||
CheckStatusWrapper status_vector(&ls); | CheckStatusWrapper status_vector(&ls); | |||
rdb->rdb_iface->cancelOperation(&status_vector, kind); | iface->cancelOperation(&status_vector, kind); | |||
} | } | |||
} | } | |||
static bool check_request(Rrq* request, USHORT incarnation, USHORT msg_number) | static bool check_request(Rrq* request, USHORT incarnation, USHORT msg_number) | |||
{ | { | |||
/************************************** | /************************************** | |||
* | * | |||
* c h e c k _ r e q u e s t | * c h e c k _ r e q u e s t | |||
* | * | |||
************************************** | ************************************** | |||
skipping to change at line 2797 | skipping to change at line 2858 | |||
// memory resources related to a limbo transactio n | // memory resources related to a limbo transactio n | |||
// as a side-effect of the database detach call b elow. | // as a side-effect of the database detach call b elow. | |||
// However, the y-valve iface must be released. | // However, the y-valve iface must be released. | |||
transaction->rtr_iface->disconnect(&status_vector ); | transaction->rtr_iface->disconnect(&status_vector ); | |||
} | } | |||
release_transaction(rdb->rdb_transactions); | release_transaction(rdb->rdb_transactions); | |||
} | } | |||
rdb->rdb_iface->detach(&status_vector); | rdb->rdb_iface->detach(&status_vector); | |||
rdb->rdb_iface = NULL; | { | |||
RefMutexGuard portGuard(*port_cancel_sync, FB_FUNCTION); | ||||
rdb->rdb_iface = NULL; | ||||
} | ||||
while (rdb->rdb_events) | while (rdb->rdb_events) | |||
release_event(rdb->rdb_events); | release_event(rdb->rdb_events); | |||
if (this->port_statement) | if (this->port_statement) | |||
release_statement(&this->port_statement); | release_statement(&this->port_statement); | |||
} | } | |||
if (rdb->rdb_svc.hasData() && rdb->rdb_svc->svc_iface) | if (rdb->rdb_svc.hasData() && rdb->rdb_svc->svc_iface) | |||
{ | { | |||
skipping to change at line 2880 | skipping to change at line 2944 | |||
rdb->rdb_iface->dropDatabase(&status_vector); | rdb->rdb_iface->dropDatabase(&status_vector); | |||
if ((status_vector.getState() & Firebird::IStatus::STATE_ERRORS) && | if ((status_vector.getState() & Firebird::IStatus::STATE_ERRORS) && | |||
(status_vector.getErrors()[1] != isc_drdb_completed_with_errs)) | (status_vector.getErrors()[1] != isc_drdb_completed_with_errs)) | |||
{ | { | |||
this->send_response(sendL, 0, 0, &status_vector, false); | this->send_response(sendL, 0, 0, &status_vector, false); | |||
return; | return; | |||
} | } | |||
rdb->rdb_iface = NULL; | { | |||
RefMutexGuard portGuard(*port_cancel_sync, FB_FUNCTION); | ||||
rdb->rdb_iface = NULL; | ||||
} | ||||
port_flags |= PORT_detached; | port_flags |= PORT_detached; | |||
if (port_async) | if (port_async) | |||
port_async->port_flags |= PORT_detached; | port_async->port_flags |= PORT_detached; | |||
while (rdb->rdb_events) | while (rdb->rdb_events) | |||
release_event(rdb->rdb_events); | release_event(rdb->rdb_events); | |||
while (rdb->rdb_requests) | while (rdb->rdb_requests) | |||
release_request(rdb->rdb_requests, true); | release_request(rdb->rdb_requests, true); | |||
skipping to change at line 2927 | skipping to change at line 2994 | |||
CheckStatusWrapper status_vector(&ls); | CheckStatusWrapper status_vector(&ls); | |||
getHandle(blob, release->p_rlse_object); | getHandle(blob, release->p_rlse_object); | |||
if (operation == op_close_blob) | if (operation == op_close_blob) | |||
blob->rbl_iface->close(&status_vector); | blob->rbl_iface->close(&status_vector); | |||
else | else | |||
blob->rbl_iface->cancel(&status_vector); | blob->rbl_iface->cancel(&status_vector); | |||
if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS)) | if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS)) | |||
{ | ||||
blob->rbl_iface = NULL; | ||||
release_blob(blob); | release_blob(blob); | |||
} | ||||
return this->send_response(sendL, 0, 0, &status_vector, false); | return this->send_response(sendL, 0, 0, &status_vector, false); | |||
} | } | |||
ISC_STATUS rem_port::end_database(P_RLSE* /*release*/, PACKET* sendL) | ISC_STATUS rem_port::end_database(P_RLSE* /*release*/, PACKET* sendL) | |||
{ | { | |||
/************************************** | /************************************** | |||
* | * | |||
* e n d _ d a t a b a s e | * e n d _ d a t a b a s e | |||
* | * | |||
skipping to change at line 2966 | skipping to change at line 3036 | |||
port_flags |= PORT_detached; | port_flags |= PORT_detached; | |||
if (port_async) | if (port_async) | |||
{ | { | |||
port_async->port_flags |= PORT_detached; | port_async->port_flags |= PORT_detached; | |||
RefMutexGuard portGuard(*port_async->port_sync, FB_FUNCTION); | RefMutexGuard portGuard(*port_async->port_sync, FB_FUNCTION); | |||
while (rdb->rdb_events) | while (rdb->rdb_events) | |||
release_event(rdb->rdb_events); | release_event(rdb->rdb_events); | |||
} | } | |||
rdb->rdb_iface = NULL; | { | |||
RefMutexGuard portGuard(*port_cancel_sync, FB_FUNCTION); | ||||
rdb->rdb_iface = NULL; | ||||
} | ||||
while (rdb->rdb_requests) | while (rdb->rdb_requests) | |||
release_request(rdb->rdb_requests, true); | release_request(rdb->rdb_requests, true); | |||
while (rdb->rdb_sql_requests) | while (rdb->rdb_sql_requests) | |||
release_sql_request(rdb->rdb_sql_requests); | release_sql_request(rdb->rdb_sql_requests); | |||
while (rdb->rdb_transactions) | while (rdb->rdb_transactions) | |||
release_transaction(rdb->rdb_transactions); | release_transaction(rdb->rdb_transactions); | |||
skipping to change at line 3004 | skipping to change at line 3077 | |||
**************************************/ | **************************************/ | |||
Rrq* requestL; | Rrq* requestL; | |||
LocalStatus ls; | LocalStatus ls; | |||
CheckStatusWrapper status_vector(&ls); | CheckStatusWrapper status_vector(&ls); | |||
getHandle(requestL, release->p_rlse_object); | getHandle(requestL, release->p_rlse_object); | |||
requestL->rrq_iface->free(&status_vector); | requestL->rrq_iface->free(&status_vector); | |||
if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS)) | if (!(status_vector.getState() & Firebird::IStatus::STATE_ERRORS)) | |||
{ | ||||
requestL->rrq_iface = NULL; | ||||
release_request(requestL); | release_request(requestL); | |||
} | ||||
return this->send_response(sendL, 0, 0, &status_vector, true); | return this->send_response(sendL, 0, 0, &status_vector, true); | |||
} | } | |||
ISC_STATUS rem_port::end_statement(P_SQLFREE* free_stmt, PACKET* sendL) | ISC_STATUS rem_port::end_statement(P_SQLFREE* free_stmt, PACKET* sendL) | |||
{ | { | |||
/***************************************** | /***************************************** | |||
* | * | |||
* e n d _ s t a t e m e n t | * e n d _ s t a t e m e n t | |||
* | * | |||
skipping to change at line 4680 | skipping to change at line 4756 | |||
if (bad_db(&status_vector, rdb)) | if (bad_db(&status_vector, rdb)) | |||
return this->send_response(sendL, 0, 0, &status_vector, false); | return this->send_response(sendL, 0, 0, &status_vector, false); | |||
// Find unused event block or, if necessary, a new one | // Find unused event block or, if necessary, a new one | |||
Rvnt* event; | Rvnt* event; | |||
for (event = rdb->rdb_events; event; event = event->rvnt_next) | for (event = rdb->rdb_events; event; event = event->rvnt_next) | |||
{ | { | |||
if (!event->rvnt_iface) | if (!event->rvnt_iface) | |||
{ | { | |||
event->rvnt_destroyed = 0; | if (event->rvnt_destroyed.compareExchange(1, 0)) | |||
break; | break; | |||
} | } | |||
} | } | |||
if (!event) | if (!event) | |||
{ | { | |||
event = FB_NEW Rvnt; | event = FB_NEW Rvnt; | |||
#ifdef DEBUG_REMOTE_MEMORY | #ifdef DEBUG_REMOTE_MEMORY | |||
printf("que_events(server) allocate event %x\n", event); | printf("que_events(server) allocate event %x\n", event); | |||
#endif | #endif | |||
event->rvnt_next = rdb->rdb_events; | event->rvnt_next = rdb->rdb_events; | |||
skipping to change at line 5097 | skipping to change at line 5173 | |||
Rdb* rdb = transaction->rtr_rdb; | Rdb* rdb = transaction->rtr_rdb; | |||
rdb->rdb_port->releaseObject(transaction->rtr_id); | rdb->rdb_port->releaseObject(transaction->rtr_id); | |||
while (transaction->rtr_blobs) | while (transaction->rtr_blobs) | |||
release_blob(transaction->rtr_blobs); | release_blob(transaction->rtr_blobs); | |||
while (transaction->rtr_cursors.hasData()) | while (transaction->rtr_cursors.hasData()) | |||
{ | { | |||
Rsr* const statement = transaction->rtr_cursors.pop(); | Rsr* const statement = transaction->rtr_cursors.pop(); | |||
fb_assert(statement->rsr_cursor); | fb_assert(statement->rsr_cursor); | |||
statement->rsr_cursor->release(); | ||||
statement->rsr_cursor = NULL; | statement->rsr_cursor = NULL; | |||
} | } | |||
for (Rtr** p = &rdb->rdb_transactions; *p; p = &(*p)->rtr_next) | for (Rtr** p = &rdb->rdb_transactions; *p; p = &(*p)->rtr_next) | |||
{ | { | |||
if (*p == transaction) | if (*p == transaction) | |||
{ | { | |||
*p = transaction->rtr_next; | *p = transaction->rtr_next; | |||
break; | break; | |||
} | } | |||
skipping to change at line 5214 | skipping to change at line 5291 | |||
// Start by translating the status vector into "generic" form | // Start by translating the status vector into "generic" form | |||
Firebird::StaticStatusVector new_vector; | Firebird::StaticStatusVector new_vector; | |||
const ISC_STATUS* old_vector = status_vector; | const ISC_STATUS* old_vector = status_vector; | |||
const ISC_STATUS exit_code = old_vector[1]; | const ISC_STATUS exit_code = old_vector[1]; | |||
char buffer[1024]; | char buffer[1024]; | |||
char* p = buffer; | char* p = buffer; | |||
char* bufferEnd = p + sizeof(buffer); | char* bufferEnd = p + sizeof(buffer); | |||
// Set limit of status vector size since old client 2.5 and below cannot | ||||
correctly handle them | ||||
const FB_SIZE_T limit = port_protocol < PROTOCOL_VERSION13 ? ISC_STATUS_L | ||||
ENGTH : 0; | ||||
for (bool sw = true; *old_vector && sw;) | for (bool sw = true; *old_vector && sw;) | |||
{ | { | |||
switch (*old_vector) | switch (*old_vector) | |||
{ | { | |||
case isc_arg_warning: | case isc_arg_warning: | |||
case isc_arg_gds: | case isc_arg_gds: | |||
if (limit && new_vector.getCount() > limit - 3) // 2 for | ||||
numbers and 1 reserved for isc_arg_end | ||||
break; | ||||
new_vector.push(*old_vector++); | new_vector.push(*old_vector++); | |||
// The status codes are converted to their offsets so tha t they | // The status codes are converted to their offsets so tha t they | |||
// were compatible with the RDB implementation. This was fine | // were compatible with the RDB implementation. This was fine | |||
// when status codes were restricted to a single facility . Now | // when status codes were restricted to a single facility . Now | |||
// that the facility is part of the status code we need t o know | // that the facility is part of the status code we need t o know | |||
// this on the client side, thus when talking with 6.0 an d newer | // this on the client side, thus when talking with 6.0 an d newer | |||
// clients, do not decode the status code, just send it t o the | // clients, do not decode the status code, just send it t o the | |||
// client. The same check is made in interface.cpp::chec k_response | // client. The same check is made in interface.cpp::chec k_response | |||
new_vector.push(*old_vector++); | new_vector.push(*old_vector++); | |||
for (;;) | for (;;) | |||
{ | { | |||
switch (*old_vector) | switch (*old_vector) | |||
{ | { | |||
case isc_arg_cstring: | case isc_arg_cstring: | |||
if (limit && new_vector.getCount() > limi | ||||
t - 4) | ||||
break; | ||||
new_vector.push(*old_vector++); | new_vector.push(*old_vector++); | |||
// fall through ... | // fall through ... | |||
case isc_arg_string: | case isc_arg_string: | |||
case isc_arg_number: | case isc_arg_number: | |||
if (limit && new_vector.getCount() > limi | ||||
t - 3) | ||||
break; | ||||
new_vector.push(*old_vector++); | new_vector.push(*old_vector++); | |||
new_vector.push(*old_vector++); | new_vector.push(*old_vector++); | |||
continue; | continue; | |||
} // switch | } // switch | |||
break; | break; | |||
} // for (;;) | } // for (;;) | |||
continue; | continue; | |||
case isc_arg_interpreted: | case isc_arg_interpreted: | |||
case isc_arg_sql_state: | case isc_arg_sql_state: | |||
if (limit && new_vector.getCount() > limit - 3) | ||||
break; | ||||
new_vector.push(*old_vector++); | new_vector.push(*old_vector++); | |||
new_vector.push(*old_vector++); | new_vector.push(*old_vector++); | |||
continue; | continue; | |||
} | } | |||
if (limit && new_vector.getCount() > limit - 3) | ||||
break; | ||||
const int l = (p < bufferEnd) ? fb_interpret(p, bufferEnd - p, &o ld_vector) : 0; | const int l = (p < bufferEnd) ? fb_interpret(p, bufferEnd - p, &o ld_vector) : 0; | |||
if (l == 0) | if (l == 0) | |||
break; | break; | |||
new_vector.push(isc_arg_interpreted); | new_vector.push(isc_arg_interpreted); | |||
new_vector.push((ISC_STATUS)(IPTR) p); | new_vector.push((ISC_STATUS)(IPTR) p); | |||
p += l; | p += l; | |||
sw = false; | sw = false; | |||
} | } | |||
skipping to change at line 5596 | skipping to change at line 5685 | |||
port_crypt_plugin = cp.plugin(); | port_crypt_plugin = cp.plugin(); | |||
port_crypt_plugin->addRef(); | port_crypt_plugin->addRef(); | |||
port_crypt_complete = true; | port_crypt_complete = true; | |||
send_response(sendL, 0, 0, &st, false); | send_response(sendL, 0, 0, &st, false); | |||
WIRECRYPT_DEBUG(fprintf(stderr, "Installed cipher %s\n", cp.name( ))); | WIRECRYPT_DEBUG(fprintf(stderr, "Installed cipher %s\n", cp.name( ))); | |||
} | } | |||
catch (const Exception& ex) | catch (const Exception& ex) | |||
{ | { | |||
iscLogException("start_crypt:", ex); | iscLogException("start_crypt:", ex); | |||
disconnect(); | disconnect(NULL, NULL); | |||
} | } | |||
} | } | |||
void set_server(rem_port* port, USHORT flags) | void set_server(rem_port* port, USHORT flags) | |||
{ | { | |||
/************************************** | /************************************** | |||
* | * | |||
* s e t _ s e r v e r | * s e t _ s e r v e r | |||
* | * | |||
************************************** | ************************************** | |||
skipping to change at line 5627 | skipping to change at line 5716 | |||
for (server = servers; server; server = server->srvr_next) | for (server = servers; server; server = server->srvr_next) | |||
{ | { | |||
if (port->port_type == server->srvr_port_type) | if (port->port_type == server->srvr_port_type) | |||
break; | break; | |||
} | } | |||
if (!server) | if (!server) | |||
{ | { | |||
servers = server = FB_NEW srvr(servers, port, flags); | servers = server = FB_NEW srvr(servers, port, flags); | |||
fb_shutdown_callback(0, shut_server, fb_shut_postproviders, 0); | fb_shutdown_callback(0, shut_server, fb_shut_postproviders, 0); | |||
fb_shutdown_callback(0, pre_shutdown, fb_shut_preproviders, 0); | ||||
} | } | |||
port->port_server = server; | port->port_server = server; | |||
} | } | |||
ISC_STATUS rem_port::start(P_OP operation, P_DATA * data, PACKET* sendL) | ISC_STATUS rem_port::start(P_OP operation, P_DATA * data, PACKET* sendL) | |||
{ | { | |||
/************************************** | /************************************** | |||
* | * | |||
* s t a r t | * s t a r t | |||
skipping to change at line 5855 | skipping to change at line 5945 | |||
// whole request packet. If it contain pa rtial packet don't clear | // whole request packet. If it contain pa rtial packet don't clear | |||
// request queue, restore receive buffer state to state before | // request queue, restore receive buffer state to state before | |||
// reading packet and wait until rest of data arrives | // reading packet and wait until rest of data arrives | |||
if (port) | if (port) | |||
{ | { | |||
fb_assert(port == request->req_po rt); | fb_assert(port == request->req_po rt); | |||
// It is very important to not re lease port_que_sync before | // It is very important to not re lease port_que_sync before | |||
// port_sync, else we can miss da ta arrived at time between | // port_sync, else we can miss da ta arrived at time between | |||
// releasing locks and will never handle it. Therefore we | // releasing locks and will never handle it. Therefore we | |||
// can't ise MutexLockGuard here | // can't use MutexLockGuard here | |||
portQueGuard.enter(); | portQueGuard.enter(); | |||
if (port->haveRecvData()) | if (port->haveRecvData()) | |||
{ | { | |||
server_req_t* new_request = alloc_request(); | server_req_t* new_request = alloc_request(); | |||
const rem_port::RecvQueSt ate recvState = port->getRecvState(); | const rem_port::RecvQueSt ate recvState = port->getRecvState(); | |||
port->receive(&new_reques t->req_receive); | port->receive(&new_reques t->req_receive); | |||
if (new_request->req_rece ive.p_operation == op_partial) | if (new_request->req_rece ive.p_operation == op_partial) | |||
{ | { | |||
skipping to change at line 6007 | skipping to change at line 6097 | |||
{ | { | |||
// We have no reliable way to distinguish network packet that sta rt | // We have no reliable way to distinguish network packet that sta rt | |||
// from the beginning of XDR packet or in the middle of it. | // from the beginning of XDR packet or in the middle of it. | |||
// Therefore try to process asynchronously only if there is no da ta | // Therefore try to process asynchronously only if there is no da ta | |||
// waiting in port queue. This can lead to fallback to synchronou s | // waiting in port queue. This can lead to fallback to synchronou s | |||
// processing of async command (i.e. with some delay), but reliab ly | // processing of async command (i.e. with some delay), but reliab ly | |||
// protects from spurious protocol breakage. | // protects from spurious protocol breakage. | |||
return 0; | return 0; | |||
} | } | |||
switch (xdr_peek_long(&port_async_receive->port_receive, buffer, dataSize | SLONG original_op = xdr_peek_long(&port_async_receive->port_receive, buff | |||
)) | er, dataSize); | |||
switch (original_op) | ||||
{ | { | |||
case op_cancel: | case op_cancel: | |||
case op_abort_aux_connection: | case op_abort_aux_connection: | |||
case op_crypt_key_callback: | case op_crypt_key_callback: | |||
break; | break; | |||
default: | default: | |||
return 0; | return 0; | |||
} | } | |||
{ // scope for guard | { // scope for guard | |||
skipping to change at line 6041 | skipping to change at line 6132 | |||
const SSHORT asyncSize = dataSize - port_async_receive->port_receive.x_ha ndy; | const SSHORT asyncSize = dataSize - port_async_receive->port_receive.x_ha ndy; | |||
fb_assert(asyncSize >= 0); | fb_assert(asyncSize >= 0); | |||
switch (asyncPacket->p_operation) | switch (asyncPacket->p_operation) | |||
{ | { | |||
case op_cancel: | case op_cancel: | |||
cancel_operation(this, asyncPacket->p_cancel_op.p_co_kind); | cancel_operation(this, asyncPacket->p_cancel_op.p_co_kind); | |||
break; | break; | |||
case op_abort_aux_connection: | case op_abort_aux_connection: | |||
if (port_async && (port_async->port_flags & PORT_connecting)) | if (port_async && (port_async->port_flags & PORT_connecting)) | |||
{ | ||||
port_async->abort_aux_connection(); | port_async->abort_aux_connection(); | |||
} | ||||
break; | break; | |||
case op_crypt_key_callback: | case op_crypt_key_callback: | |||
port_server_crypt_callback->wakeup(asyncPacket->p_cc.p_cc_data.cs tr_length, | port_server_crypt_callback->wakeup(asyncPacket->p_cc.p_cc_data.cs tr_length, | |||
asyncPacket->p_cc.p_cc_data.cstr_address); | asyncPacket->p_cc.p_cc_data.cstr_address); | |||
break; | break; | |||
case op_partial: | ||||
if (original_op == op_crypt_key_callback) | ||||
port_server_crypt_callback->wakeup(0, NULL); | ||||
break; | ||||
default: | default: | |||
fb_assert(false); | fb_assert(false); | |||
return 0; | return 0; | |||
} | } | |||
return asyncSize; | return asyncSize; | |||
} | } | |||
ISC_STATUS rem_port::transact_request(P_TRRQ* trrq, PACKET* sendL) | ISC_STATUS rem_port::transact_request(P_TRRQ* trrq, PACKET* sendL) | |||
{ | { | |||
skipping to change at line 6132 | skipping to change at line 6225 | |||
memset(&packet->p_operation, 0, sizeof(PACKET) - offsetof(PACKET, p_operation)); | memset(&packet->p_operation, 0, sizeof(PACKET) - offsetof(PACKET, p_operation)); | |||
#else | #else | |||
memset(packet, 0, sizeof(PACKET)); | memset(packet, 0, sizeof(PACKET)); | |||
#endif | #endif | |||
} | } | |||
} | } | |||
Worker::Worker() | Worker::Worker() | |||
{ | { | |||
m_active = false; | m_active = false; | |||
m_going = false; | ||||
m_next = m_prev = NULL; | m_next = m_prev = NULL; | |||
#ifdef DEV_BUILD | #ifdef DEV_BUILD | |||
m_tid = getThreadId(); | m_tid = getThreadId(); | |||
#endif | #endif | |||
MutexLockGuard guard(m_mutex, FB_FUNCTION); | MutexLockGuard guard(m_mutex, FB_FUNCTION); | |||
insert(m_active); | insert(m_active); | |||
} | } | |||
Worker::~Worker() | Worker::~Worker() | |||
{ | { | |||
MutexLockGuard guard(m_mutex, FB_FUNCTION); | MutexLockGuard guard(m_mutex, FB_FUNCTION); | |||
remove(); | remove(); | |||
--m_cntAll; | --m_cntAll; | |||
if (m_going) | ||||
--m_cntGoing; | ||||
} | } | |||
bool Worker::wait(int timeout) | bool Worker::wait(int timeout) | |||
{ | { | |||
if (m_sem.tryEnter(timeout)) | if (m_sem.tryEnter(timeout)) | |||
return true; | return true; | |||
MutexLockGuard guard(m_mutex, FB_FUNCTION); | MutexLockGuard guard(m_mutex, FB_FUNCTION); | |||
if (m_sem.tryEnter(0)) | if (m_sem.tryEnter(0)) | |||
return true; | return true; | |||
// don't exit last worker until server shutdown | ||||
if ((m_cntAll - m_cntGoing == 1) && !isShuttingDown()) | ||||
return true; | ||||
remove(); | remove(); | |||
m_going = true; | ||||
m_cntGoing++; | ||||
return false; | return false; | |||
} | } | |||
void Worker::setState(const bool active) | void Worker::setState(const bool active) | |||
{ | { | |||
if (m_active == active) | if (m_active == active) | |||
return; | return; | |||
MutexLockGuard guard(m_mutex, FB_FUNCTION); | MutexLockGuard guard(m_mutex, FB_FUNCTION); | |||
remove(); | remove(); | |||
skipping to change at line 6200 | skipping to change at line 6302 | |||
MutexLockGuard guard(m_mutex, FB_FUNCTION); | MutexLockGuard guard(m_mutex, FB_FUNCTION); | |||
if (m_idleWorkers) | if (m_idleWorkers) | |||
{ | { | |||
Worker* idle = m_idleWorkers; | Worker* idle = m_idleWorkers; | |||
idle->setState(true); | idle->setState(true); | |||
idle->m_sem.release(); | idle->m_sem.release(); | |||
return true; | return true; | |||
} | } | |||
if (m_cntAll >= ports_active + ports_pending) | if (m_cntAll - m_cntGoing >= ports_active + ports_pending) | |||
return true; | return true; | |||
return (m_cntAll >= MAX_THREADS); | return (m_cntAll - m_cntGoing >= MAX_THREADS); | |||
} | } | |||
void Worker::wakeUpAll() | void Worker::wakeUpAll() | |||
{ | { | |||
MutexLockGuard guard(m_mutex, FB_FUNCTION); | MutexLockGuard guard(m_mutex, FB_FUNCTION); | |||
for (Worker* thd = m_idleWorkers; thd; thd = thd->m_next) | for (Worker* thd = m_idleWorkers; thd; thd = thd->m_next) | |||
thd->m_sem.release(); | thd->m_sem.release(); | |||
} | } | |||
void Worker::remove() | void Worker::remove() | |||
skipping to change at line 6313 | skipping to change at line 6415 | |||
m_mutex->enter(FB_FUNCTION); | m_mutex->enter(FB_FUNCTION); | |||
} | } | |||
} | } | |||
static int shut_server(const int, const int, void*) | static int shut_server(const int, const int, void*) | |||
{ | { | |||
server_shutdown = true; | server_shutdown = true; | |||
return 0; | return 0; | |||
} | } | |||
static int pre_shutdown(const int, const int, void*) | ||||
{ | ||||
engine_shutdown = true; | ||||
return 0; | ||||
} | ||||
void SrvAuthBlock::extractDataFromPluginTo(cstring* to) | void SrvAuthBlock::extractDataFromPluginTo(cstring* to) | |||
{ | { | |||
to->cstr_allocated = 0; | to->cstr_allocated = 0; | |||
to->cstr_length = (ULONG) dataFromPlugin.getCount(); | to->cstr_length = (ULONG) dataFromPlugin.getCount(); | |||
to->cstr_address = dataFromPlugin.begin(); | to->cstr_address = dataFromPlugin.begin(); | |||
} | } | |||
bool SrvAuthBlock::authCompleted(bool flag) | bool SrvAuthBlock::authCompleted(bool flag) | |||
{ | { | |||
if (flag) | if (flag) | |||
End of changes. 53 change blocks. | ||||
60 lines changed or deleted | 176 lines changed or added |