"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/remote/server/server.cpp" between
Firebird-3.0.2.32703-0.tar.bz2 and Firebird-3.0.4.33054-0.tar.bz2

About: Firebird is a relational database offering many ANSI SQL standard features.

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

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)