mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-24 01:23:03 +01:00
This commit is contained in:
parent
e9d0c3c382
commit
5d0fd12985
@ -717,6 +717,9 @@ interface Service : ReferenceCounted
|
||||
version: // 3.0.7 => 3.0.8, 4.0.0 => 4.0.1
|
||||
[notImplementedAction if ::FB_UsedInYValve then defaultAction else call deprecatedDetach(status) endif]
|
||||
void detach(Status status);
|
||||
|
||||
version: // 3.0.9 => 3.0.10, 4.0.1 => 4.0.2
|
||||
void cancel(Status status);
|
||||
}
|
||||
|
||||
interface Provider : PluginBase
|
||||
|
@ -2714,6 +2714,7 @@ namespace Firebird
|
||||
void (CLOOP_CARG *query)(IService* self, IStatus* status, unsigned sendLength, const unsigned char* sendItems, unsigned receiveLength, const unsigned char* receiveItems, unsigned bufferLength, unsigned char* buffer) throw();
|
||||
void (CLOOP_CARG *start)(IService* self, IStatus* status, unsigned spbLength, const unsigned char* spb) throw();
|
||||
void (CLOOP_CARG *detach)(IService* self, IStatus* status) throw();
|
||||
void (CLOOP_CARG *cancel)(IService* self, IStatus* status) throw();
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -2727,7 +2728,7 @@ namespace Firebird
|
||||
}
|
||||
|
||||
public:
|
||||
static const unsigned VERSION = 4;
|
||||
static const unsigned VERSION = 5;
|
||||
|
||||
template <typename StatusType> void deprecatedDetach(StatusType* status)
|
||||
{
|
||||
@ -2767,6 +2768,19 @@ namespace Firebird
|
||||
static_cast<VTable*>(this->cloopVTable)->detach(this, status);
|
||||
StatusType::checkException(status);
|
||||
}
|
||||
|
||||
template <typename StatusType> void cancel(StatusType* status)
|
||||
{
|
||||
if (cloopVTable->version < 5)
|
||||
{
|
||||
StatusType::setVersionError(status, "IService", cloopVTable->version, 5);
|
||||
StatusType::checkException(status);
|
||||
return;
|
||||
}
|
||||
StatusType::clearException(status);
|
||||
static_cast<VTable*>(this->cloopVTable)->cancel(this, status);
|
||||
StatusType::checkException(status);
|
||||
}
|
||||
};
|
||||
|
||||
class IProvider : public IPluginBase
|
||||
@ -11460,6 +11474,7 @@ namespace Firebird
|
||||
this->query = &Name::cloopqueryDispatcher;
|
||||
this->start = &Name::cloopstartDispatcher;
|
||||
this->detach = &Name::cloopdetachDispatcher;
|
||||
this->cancel = &Name::cloopcancelDispatcher;
|
||||
}
|
||||
} vTable;
|
||||
|
||||
@ -11522,6 +11537,20 @@ namespace Firebird
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopcancelDispatcher(IService* self, IStatus* status) throw()
|
||||
{
|
||||
StatusType status2(status);
|
||||
|
||||
try
|
||||
{
|
||||
static_cast<Name*>(self)->Name::cancel(&status2);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
StatusType::catchException(&status2);
|
||||
}
|
||||
}
|
||||
|
||||
static void CLOOP_CARG cloopaddRefDispatcher(IReferenceCounted* self) throw()
|
||||
{
|
||||
try
|
||||
@ -11565,6 +11594,7 @@ namespace Firebird
|
||||
virtual void query(StatusType* status, unsigned sendLength, const unsigned char* sendItems, unsigned receiveLength, const unsigned char* receiveItems, unsigned bufferLength, unsigned char* buffer) = 0;
|
||||
virtual void start(StatusType* status, unsigned spbLength, const unsigned char* spb) = 0;
|
||||
virtual void detach(StatusType* status) = 0;
|
||||
virtual void cancel(StatusType* status) = 0;
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base>
|
||||
|
@ -414,6 +414,7 @@ type
|
||||
IService_queryPtr = procedure(this: IService; status: IStatus; sendLength: Cardinal; sendItems: BytePtr; receiveLength: Cardinal; receiveItems: BytePtr; bufferLength: Cardinal; buffer: BytePtr); cdecl;
|
||||
IService_startPtr = procedure(this: IService; status: IStatus; spbLength: Cardinal; spb: BytePtr); cdecl;
|
||||
IService_detachPtr = procedure(this: IService; status: IStatus); cdecl;
|
||||
IService_cancelPtr = procedure(this: IService; status: IStatus); cdecl;
|
||||
IProvider_attachDatabasePtr = function(this: IProvider; status: IStatus; fileName: PAnsiChar; dpbLength: Cardinal; dpb: BytePtr): IAttachment; cdecl;
|
||||
IProvider_createDatabasePtr = function(this: IProvider; status: IStatus; fileName: PAnsiChar; dpbLength: Cardinal; dpb: BytePtr): IAttachment; cdecl;
|
||||
IProvider_attachServiceManagerPtr = function(this: IProvider; status: IStatus; service: PAnsiChar; spbLength: Cardinal; spb: BytePtr): IService; cdecl;
|
||||
@ -1817,15 +1818,17 @@ type
|
||||
query: IService_queryPtr;
|
||||
start: IService_startPtr;
|
||||
detach: IService_detachPtr;
|
||||
cancel: IService_cancelPtr;
|
||||
end;
|
||||
|
||||
IService = class(IReferenceCounted)
|
||||
const VERSION = 4;
|
||||
const VERSION = 5;
|
||||
|
||||
procedure deprecatedDetach(status: IStatus);
|
||||
procedure query(status: IStatus; sendLength: Cardinal; sendItems: BytePtr; receiveLength: Cardinal; receiveItems: BytePtr; bufferLength: Cardinal; buffer: BytePtr);
|
||||
procedure start(status: IStatus; spbLength: Cardinal; spb: BytePtr);
|
||||
procedure detach(status: IStatus);
|
||||
procedure cancel(status: IStatus);
|
||||
end;
|
||||
|
||||
IServiceImpl = class(IService)
|
||||
@ -1837,6 +1840,7 @@ type
|
||||
procedure query(status: IStatus; sendLength: Cardinal; sendItems: BytePtr; receiveLength: Cardinal; receiveItems: BytePtr; bufferLength: Cardinal; buffer: BytePtr); virtual; abstract;
|
||||
procedure start(status: IStatus; spbLength: Cardinal; spb: BytePtr); virtual; abstract;
|
||||
procedure detach(status: IStatus); virtual; abstract;
|
||||
procedure cancel(status: IStatus); virtual; abstract;
|
||||
end;
|
||||
|
||||
ProviderVTable = class(PluginBaseVTable)
|
||||
@ -7085,6 +7089,17 @@ begin
|
||||
FbException.checkException(status);
|
||||
end;
|
||||
|
||||
procedure IService.cancel(status: IStatus);
|
||||
begin
|
||||
if (vTable.version < 5) then begin
|
||||
FbException.setVersionError(status, 'IService', vTable.version, 5);
|
||||
end
|
||||
else begin
|
||||
ServiceVTable(vTable).cancel(Self, status);
|
||||
end;
|
||||
FbException.checkException(status);
|
||||
end;
|
||||
|
||||
function IProvider.attachDatabase(status: IStatus; fileName: PAnsiChar; dpbLength: Cardinal; dpb: BytePtr): IAttachment;
|
||||
begin
|
||||
Result := ProviderVTable(vTable).attachDatabase(Self, status, fileName, dpbLength, dpb);
|
||||
@ -11307,6 +11322,15 @@ begin
|
||||
end
|
||||
end;
|
||||
|
||||
procedure IServiceImpl_cancelDispatcher(this: IService; status: IStatus); cdecl;
|
||||
begin
|
||||
try
|
||||
IServiceImpl(this).cancel(status);
|
||||
except
|
||||
on e: Exception do FbException.catchException(status, e);
|
||||
end
|
||||
end;
|
||||
|
||||
var
|
||||
IServiceImpl_vTable: ServiceVTable;
|
||||
|
||||
@ -15740,13 +15764,14 @@ initialization
|
||||
IAttachmentImpl_vTable.dropDatabase := @IAttachmentImpl_dropDatabaseDispatcher;
|
||||
|
||||
IServiceImpl_vTable := ServiceVTable.create;
|
||||
IServiceImpl_vTable.version := 4;
|
||||
IServiceImpl_vTable.version := 5;
|
||||
IServiceImpl_vTable.addRef := @IServiceImpl_addRefDispatcher;
|
||||
IServiceImpl_vTable.release := @IServiceImpl_releaseDispatcher;
|
||||
IServiceImpl_vTable.deprecatedDetach := @IServiceImpl_deprecatedDetachDispatcher;
|
||||
IServiceImpl_vTable.query := @IServiceImpl_queryDispatcher;
|
||||
IServiceImpl_vTable.start := @IServiceImpl_startDispatcher;
|
||||
IServiceImpl_vTable.detach := @IServiceImpl_detachDispatcher;
|
||||
IServiceImpl_vTable.cancel := @IServiceImpl_cancelDispatcher;
|
||||
|
||||
IProviderImpl_vTable := ProviderVTable.create;
|
||||
IProviderImpl_vTable.version := 4;
|
||||
|
@ -506,6 +506,7 @@ public:
|
||||
unsigned int bufferLength, unsigned char* buffer) override;
|
||||
void start(Firebird::CheckStatusWrapper* status,
|
||||
unsigned int spbLength, const unsigned char* spb) override;
|
||||
void cancel(Firebird::CheckStatusWrapper* status) override;
|
||||
|
||||
public:
|
||||
explicit JService(Jrd::Service* handle);
|
||||
|
@ -4407,6 +4407,26 @@ void JService::query(CheckStatusWrapper* user_status,
|
||||
}
|
||||
|
||||
|
||||
void JService::cancel(CheckStatusWrapper* user_status)
|
||||
{
|
||||
try
|
||||
{
|
||||
ThreadContextHolder tdbb(user_status);
|
||||
|
||||
validateHandle(svc);
|
||||
|
||||
svc->cancel(tdbb);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
ex.stuffException(user_status);
|
||||
return;
|
||||
}
|
||||
|
||||
successful_completion(user_status);
|
||||
}
|
||||
|
||||
|
||||
void JService::start(CheckStatusWrapper* user_status, unsigned int spbLength, const unsigned char* spb)
|
||||
{
|
||||
/**************************************
|
||||
|
@ -688,7 +688,8 @@ Service::Service(const TEXT* service_name, USHORT spb_length, const UCHAR* spb_d
|
||||
svc_stdout_head(0), svc_stdout_tail(0), svc_service_run(NULL),
|
||||
svc_resp_alloc(getPool()), svc_resp_buf(0), svc_resp_ptr(0), svc_resp_buf_len(0),
|
||||
svc_resp_len(0), svc_flags(SVC_finished), svc_user_flag(0), svc_spb_version(0),
|
||||
svc_do_shutdown(false), svc_shutdown_in_progress(false), svc_timeout(false),
|
||||
svc_shutdown_server(false), svc_shutdown_request(false),
|
||||
svc_shutdown_in_progress(false), svc_timeout(false),
|
||||
svc_username(getPool()), svc_sql_role(getPool()), svc_auth_block(getPool()),
|
||||
svc_expected_db(getPool()), svc_trusted_role(false), svc_utf8(false),
|
||||
svc_switches(getPool()), svc_perm_sw(getPool()), svc_address_path(getPool()),
|
||||
@ -864,7 +865,7 @@ void Service::detach()
|
||||
}
|
||||
|
||||
// save it cause after call to finish() we can't access class members any more
|
||||
const bool localDoShutdown = svc_do_shutdown;
|
||||
const bool localDoShutdown = svc_shutdown_server;
|
||||
|
||||
if (svc_trace_manager->needs(ITraceFactory::TRACE_EVENT_SERVICE_DETACH))
|
||||
{
|
||||
@ -950,7 +951,7 @@ ULONG Service::totalCount()
|
||||
|
||||
bool Service::checkForShutdown()
|
||||
{
|
||||
if (svcShutdown)
|
||||
if (svcShutdown || svc_shutdown_request)
|
||||
{
|
||||
if (svc_shutdown_in_progress)
|
||||
{
|
||||
@ -966,6 +967,20 @@ bool Service::checkForShutdown()
|
||||
}
|
||||
|
||||
|
||||
void Service::cancel(thread_db* /*tdbb*/)
|
||||
{
|
||||
svc_shutdown_request = true;
|
||||
|
||||
// signal once
|
||||
if (!(svc_flags & SVC_finished))
|
||||
svc_detach_sem.release();
|
||||
if (svc_stdin_size_requested)
|
||||
svc_stdin_semaphore.release();
|
||||
|
||||
svc_sem_full.release();
|
||||
}
|
||||
|
||||
|
||||
void Service::shutdownServices()
|
||||
{
|
||||
svcShutdown = true;
|
||||
@ -1158,7 +1173,7 @@ ISC_STATUS Service::query2(thread_db* /*tdbb*/,
|
||||
*info++ = item;
|
||||
if (svc_user_flag & SVC_user_dba)
|
||||
{
|
||||
svc_do_shutdown = false;
|
||||
svc_shutdown_server = false;
|
||||
}
|
||||
else
|
||||
need_admin_privs(status, "isc_info_svc_svr_online");
|
||||
@ -1168,7 +1183,7 @@ ISC_STATUS Service::query2(thread_db* /*tdbb*/,
|
||||
*info++ = item;
|
||||
if (svc_user_flag & SVC_user_dba)
|
||||
{
|
||||
svc_do_shutdown = true;
|
||||
svc_shutdown_server = true;
|
||||
}
|
||||
else
|
||||
need_admin_privs(status, "isc_info_svc_svr_offline");
|
||||
@ -1613,7 +1628,7 @@ void Service::query(USHORT send_item_length,
|
||||
*info++ = item;
|
||||
if (svc_user_flag & SVC_user_dba)
|
||||
{
|
||||
svc_do_shutdown = false;
|
||||
svc_shutdown_server = false;
|
||||
*info++ = 0; // Success
|
||||
}
|
||||
else
|
||||
@ -1624,7 +1639,7 @@ void Service::query(USHORT send_item_length,
|
||||
*info++ = item;
|
||||
if (svc_user_flag & SVC_user_dba)
|
||||
{
|
||||
svc_do_shutdown = true;
|
||||
svc_shutdown_server = true;
|
||||
*info++ = 0; // Success
|
||||
}
|
||||
else
|
||||
@ -1937,6 +1952,9 @@ void Service::start(USHORT spb_length, const UCHAR* spb_data)
|
||||
|
||||
try
|
||||
{
|
||||
if (!svcShutdown)
|
||||
svc_shutdown_request = svc_shutdown_in_progress = false;
|
||||
|
||||
ClumpletReader spb(ClumpletReader::SpbStart, spb_data, spb_length);
|
||||
|
||||
// The name of the service is the first element of the buffer
|
||||
|
@ -172,6 +172,8 @@ public: // external interface with service
|
||||
const UCHAR* recv_items, USHORT buffer_length, UCHAR* info);
|
||||
ISC_STATUS query2(thread_db* tdbb, USHORT send_item_length, const UCHAR* send_items,
|
||||
USHORT recv_item_length, const UCHAR* recv_items, USHORT buffer_length, UCHAR* info);
|
||||
// Cancel wait in query service
|
||||
void cancel(thread_db* tdbb);
|
||||
// Detach from service
|
||||
void detach();
|
||||
// get service version
|
||||
@ -305,7 +307,8 @@ private:
|
||||
USHORT svc_flags;
|
||||
USHORT svc_user_flag;
|
||||
USHORT svc_spb_version;
|
||||
bool svc_do_shutdown;
|
||||
bool svc_shutdown_server;
|
||||
bool svc_shutdown_request;
|
||||
bool svc_shutdown_in_progress;
|
||||
bool svc_timeout;
|
||||
char svc_arg_conv[MsgFormat::SAFEARG_MAX_ARG * 2];
|
||||
|
@ -151,6 +151,8 @@ namespace {
|
||||
cstring* ptr;
|
||||
cstring oldValue;
|
||||
};
|
||||
|
||||
GlobalPtr<PortsCleanup> outPorts;
|
||||
}
|
||||
|
||||
namespace Remote {
|
||||
@ -936,6 +938,7 @@ public:
|
||||
unsigned int receiveLength, const unsigned char* receiveItems,
|
||||
unsigned int bufferLength, unsigned char* buffer) override;
|
||||
void start(CheckStatusWrapper* status, unsigned int spbLength, const unsigned char* spb) override;
|
||||
void cancel(CheckStatusWrapper* status) override;
|
||||
|
||||
public:
|
||||
Service(Rdb* handle) : rdb(handle) { }
|
||||
@ -998,6 +1001,15 @@ private:
|
||||
void RProvider::shutdown(CheckStatusWrapper* status, unsigned int /*timeout*/, const int /*reason*/)
|
||||
{
|
||||
status->init();
|
||||
|
||||
try
|
||||
{
|
||||
outPorts->closePorts();
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
ex.stuffException(status);
|
||||
}
|
||||
}
|
||||
|
||||
void RProvider::setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback)
|
||||
@ -1063,7 +1075,7 @@ static void batch_gds_receive(rem_port*, struct rmtque *, USHORT);
|
||||
static void batch_dsql_fetch(rem_port*, struct rmtque *, USHORT);
|
||||
static void clear_queue(rem_port*);
|
||||
static void clear_stmt_que(rem_port*, Rsr*);
|
||||
static void disconnect(rem_port*);
|
||||
static void disconnect(rem_port*, bool rmRef = true);
|
||||
static void enqueue_receive(rem_port*, t_rmtque_fn, Rdb*, void*, Rrq::rrq_repeat*);
|
||||
static void dequeue_receive(rem_port*);
|
||||
static THREAD_ENTRY_DECLARE event_thread(THREAD_ENTRY_PARAM);
|
||||
@ -6435,6 +6447,28 @@ void Service::query(CheckStatusWrapper* status,
|
||||
}
|
||||
|
||||
|
||||
void Service::cancel(CheckStatusWrapper* status)
|
||||
{
|
||||
try
|
||||
{
|
||||
reset(status);
|
||||
|
||||
// Check and validate handles, etc.
|
||||
CHECK_HANDLE(rdb, isc_bad_svc_handle);
|
||||
/*
|
||||
rem_port* port = rdb->rdb_port;
|
||||
RefMutexGuard portGuard(*port->port_sync, FB_FUNCTION);
|
||||
*/
|
||||
|
||||
Arg::Gds(isc_wish_list).raise();
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
ex.stuffException(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Service::start(CheckStatusWrapper* status,
|
||||
unsigned int spbLength, const unsigned char* spb)
|
||||
{
|
||||
@ -7197,10 +7231,11 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
disconnect(port);
|
||||
disconnect(port, false);
|
||||
throw;
|
||||
}
|
||||
|
||||
outPorts->registerPort(port);
|
||||
return port;
|
||||
}
|
||||
|
||||
@ -7556,7 +7591,7 @@ static void clear_queue(rem_port* port)
|
||||
}
|
||||
|
||||
|
||||
static void disconnect( rem_port* port)
|
||||
static void disconnect(rem_port* port, bool rmRef)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -7625,6 +7660,12 @@ static void disconnect( rem_port* port)
|
||||
port->port_flags |= PORT_disconnect;
|
||||
port->disconnect();
|
||||
delete rdb;
|
||||
port->port_context = nullptr;
|
||||
|
||||
// Remove from active ports
|
||||
|
||||
if (rmRef)
|
||||
outPorts->unRegisterPort(port);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2681,23 +2681,28 @@ static void cancel_operation(rem_port* port, USHORT kind)
|
||||
if ((port->port_flags & (PORT_async | PORT_disconnect)) || !(port->port_context))
|
||||
return;
|
||||
|
||||
ServAttachment iface;
|
||||
ServAttachment dbIface;
|
||||
ServService svcIface;
|
||||
{
|
||||
RefMutexGuard portGuard(*port->port_cancel_sync, FB_FUNCTION);
|
||||
|
||||
Rdb* rdb;
|
||||
if ((port->port_flags & PORT_disconnect) || !(rdb = port->port_context))
|
||||
Rdb* rdb = port->port_context;
|
||||
if ((port->port_flags & PORT_disconnect) || !rdb)
|
||||
return;
|
||||
|
||||
iface = rdb->rdb_iface;
|
||||
if (rdb->rdb_svc)
|
||||
svcIface = rdb->rdb_svc->svc_iface;
|
||||
else
|
||||
dbIface = rdb->rdb_iface;
|
||||
}
|
||||
|
||||
if (iface)
|
||||
{
|
||||
LocalStatus ls;
|
||||
CheckStatusWrapper status_vector(&ls);
|
||||
iface->cancelOperation(&status_vector, kind);
|
||||
}
|
||||
LocalStatus ls;
|
||||
CheckStatusWrapper status_vector(&ls);
|
||||
|
||||
if (dbIface)
|
||||
dbIface->cancelOperation(&status_vector, kind);
|
||||
else if (svcIface && kind == fb_cancel_raise)
|
||||
svcIface->cancel(&status_vector);
|
||||
}
|
||||
|
||||
|
||||
@ -5054,8 +5059,11 @@ static bool process_packet(rem_port* port, PACKET* sendL, PACKET* receive, rem_p
|
||||
{
|
||||
if (!port->port_parent)
|
||||
{
|
||||
if (!Worker::isShuttingDown() && !(port->port_flags & (PORT_rdb_shutdown | PORT_detached)))
|
||||
if (!Worker::isShuttingDown() && !(port->port_flags & (PORT_rdb_shutdown | PORT_detached)) &&
|
||||
((port->port_server_flags & (SRVR_server | SRVR_multi_client)) != SRVR_server))
|
||||
{
|
||||
gds__log("SERVER/process_packet: broken port, server exiting");
|
||||
}
|
||||
port->disconnect(sendL, receive);
|
||||
return false;
|
||||
}
|
||||
|
@ -613,6 +613,7 @@ public:
|
||||
unsigned int bufferLength, unsigned char* buffer);
|
||||
void start(Firebird::CheckStatusWrapper* status,
|
||||
unsigned int spbLength, const unsigned char* spb);
|
||||
void cancel(Firebird::CheckStatusWrapper* status);
|
||||
|
||||
public:
|
||||
typedef Firebird::IService NextInterface;
|
||||
|
@ -6197,6 +6197,19 @@ void YService::query(CheckStatusWrapper* status, unsigned int sendLength, const
|
||||
}
|
||||
}
|
||||
|
||||
void YService::cancel(CheckStatusWrapper* status)
|
||||
{
|
||||
try
|
||||
{
|
||||
YEntry<YService> entry(status, this);
|
||||
entry.next()->cancel(status);
|
||||
}
|
||||
catch (const Exception& e)
|
||||
{
|
||||
e.stuffException(status);
|
||||
}
|
||||
}
|
||||
|
||||
void YService::start(CheckStatusWrapper* status, unsigned int spbLength, const unsigned char* spbItems)
|
||||
{
|
||||
try
|
||||
|
Loading…
Reference in New Issue
Block a user