mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 20:03:03 +01:00
Backported fix for CORE-1439: DB corruption when killing posix CS
This commit is contained in:
parent
974df75779
commit
63e2610d3a
@ -844,66 +844,64 @@ ISC_STATUS callback_execute_immediate( ISC_STATUS* status,
|
|||||||
requests = 0;
|
requests = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Locate why_db_handle, corresponding to jrd_database_handle
|
YValve::Attachment* why_db_handle = 0;
|
||||||
|
YValve::Transaction* why_trans_handle = 0;
|
||||||
|
dsql_dbb* database = 0;
|
||||||
|
|
||||||
THREAD_EXIT();
|
THREAD_EXIT();
|
||||||
THD_MUTEX_LOCK (&databases_mutex);
|
THD_MUTEX_LOCK (&databases_mutex);
|
||||||
dsql_dbb* database;
|
try
|
||||||
|
{
|
||||||
|
// 1. Locate why_db_handle, corresponding to jrd_database_handle
|
||||||
for (database = databases; database; database = database->dbb_next)
|
for (database = databases; database; database = database->dbb_next)
|
||||||
{
|
{
|
||||||
if (WHY_translate_handle(database->dbb_database_handle)->handle.h_dbb == jrd_attachment_handle)
|
if (YValve::translate<YValve::Attachment>(&database->dbb_database_handle)->handle == jrd_attachment_handle)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! database) {
|
if (! database)
|
||||||
status[0] = isc_arg_gds;
|
{
|
||||||
status[1] = isc_bad_db_handle;
|
Firebird::status_exception::raise(isc_bad_db_handle, isc_arg_end);
|
||||||
status[2] = isc_arg_end;
|
|
||||||
THD_MUTEX_UNLOCK(&databases_mutex);
|
|
||||||
THREAD_ENTER();
|
|
||||||
return status[1];
|
|
||||||
}
|
}
|
||||||
WHY_DBB why_db_handle = WHY_translate_handle(database->dbb_database_handle);
|
why_db_handle = YValve::translate<YValve::Attachment>(&database->dbb_database_handle);
|
||||||
|
|
||||||
/* 2. Create why_trans_handle - it's new, but points to the same jrd
|
// 2. Create why_trans_handle - it's new, but points to the same jrd
|
||||||
transaction as original before callback. */
|
// transaction as original before callback.
|
||||||
WHY_TRA why_trans_handle = WHY_alloc_handle(why_db_handle->implementation, HANDLE_transaction);
|
why_trans_handle = new YValve::Transaction(jrd_transaction_handle, 0, why_db_handle);
|
||||||
if (!why_trans_handle) {
|
}
|
||||||
status[0] = isc_arg_gds;
|
catch (const std::exception& e)
|
||||||
status[1] = isc_virmemexh;
|
{
|
||||||
status[2] = isc_arg_end;
|
|
||||||
THD_MUTEX_UNLOCK(&databases_mutex);
|
THD_MUTEX_UNLOCK(&databases_mutex);
|
||||||
THREAD_ENTER();
|
THREAD_ENTER();
|
||||||
return status[1];
|
return Firebird::stuff_exception(status, e);
|
||||||
}
|
}
|
||||||
why_trans_handle->handle.h_tra = jrd_transaction_handle;
|
|
||||||
why_trans_handle->parent = why_db_handle;
|
|
||||||
THD_MUTEX_UNLOCK (&databases_mutex);
|
|
||||||
THREAD_ENTER();
|
|
||||||
|
|
||||||
// 3. Call execute... function
|
// 3. Call execute... function
|
||||||
|
THD_MUTEX_UNLOCK (&databases_mutex);
|
||||||
|
THREAD_ENTER();
|
||||||
const ISC_STATUS rc = dsql8_execute_immediate_common(status,
|
const ISC_STATUS rc = dsql8_execute_immediate_common(status,
|
||||||
&database->dbb_database_handle, &why_trans_handle->public_handle,
|
&database->dbb_database_handle, &why_trans_handle->public_handle,
|
||||||
sql_operator.length(), sql_operator.c_str(),
|
sql_operator.length(), sql_operator.c_str(),
|
||||||
database->dbb_db_SQL_dialect,
|
database->dbb_db_SQL_dialect,
|
||||||
0, NULL, 0, 0, NULL, 0, NULL, 0, 0, NULL, requests);
|
0, NULL, 0, 0, NULL, 0, NULL, 0, 0, NULL, requests);
|
||||||
WHY_cleanup_transaction(why_trans_handle);
|
delete why_trans_handle;
|
||||||
WHY_free_handle(why_trans_handle->public_handle);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WHY_DBB GetWhyAttachment (ISC_STATUS* status,
|
YValve::Attachment* GetWhyAttachment(ISC_STATUS* status,
|
||||||
Jrd::Attachment* jrd_attachment_handle)
|
Jrd::Attachment* jrd_attachment_handle)
|
||||||
{
|
{
|
||||||
THREAD_EXIT();
|
THREAD_EXIT();
|
||||||
THD_MUTEX_LOCK (&databases_mutex);
|
THD_MUTEX_LOCK (&databases_mutex);
|
||||||
dsql_dbb* database;
|
dsql_dbb* database;
|
||||||
WHY_DBB db_handle = 0;
|
YValve::Attachment* db_handle = 0;
|
||||||
for (database = databases; database; database = database->dbb_next)
|
for (database = databases; database; database = database->dbb_next)
|
||||||
{
|
{
|
||||||
db_handle = WHY_translate_handle(database->dbb_database_handle);
|
db_handle = YValve::translate<YValve::Attachment>(&database->dbb_database_handle);
|
||||||
if (db_handle->handle.h_dbb == jrd_attachment_handle)
|
if (db_handle->handle == jrd_attachment_handle)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -382,7 +382,7 @@ ISC_STATUS API_ROUTINE gds__create_database(ISC_STATUS* status_vector,
|
|||||||
|
|
||||||
ISC_STATUS API_ROUTINE gds__database_cleanup(ISC_STATUS * status_vector,
|
ISC_STATUS API_ROUTINE gds__database_cleanup(ISC_STATUS * status_vector,
|
||||||
FB_API_HANDLE* db_handle,
|
FB_API_HANDLE* db_handle,
|
||||||
DatabaseCleanupRoutine *routine, void* arg)
|
AttachmentCleanupRoutine* routine, void* arg)
|
||||||
{
|
{
|
||||||
|
|
||||||
return isc_database_cleanup(status_vector, db_handle, routine, arg);
|
return isc_database_cleanup(status_vector, db_handle, routine, arg);
|
||||||
|
@ -66,7 +66,7 @@ ISC_STATUS API_ROUTINE gds__create_database( ISC_STATUS*, SSHORT, const SCHAR*,
|
|||||||
FB_API_HANDLE*, SSHORT, const SCHAR*, SSHORT);
|
FB_API_HANDLE*, SSHORT, const SCHAR*, SSHORT);
|
||||||
|
|
||||||
ISC_STATUS API_ROUTINE gds__database_cleanup(ISC_STATUS*, FB_API_HANDLE*,
|
ISC_STATUS API_ROUTINE gds__database_cleanup(ISC_STATUS*, FB_API_HANDLE*,
|
||||||
DatabaseCleanupRoutine*, void * );
|
AttachmentCleanupRoutine*, void * );
|
||||||
|
|
||||||
ISC_STATUS API_ROUTINE gds__database_info(ISC_STATUS*, FB_API_HANDLE*, SSHORT,
|
ISC_STATUS API_ROUTINE gds__database_info(ISC_STATUS*, FB_API_HANDLE*, SSHORT,
|
||||||
const SCHAR*, SSHORT, SCHAR*);
|
const SCHAR*, SSHORT, SCHAR*);
|
||||||
|
@ -496,13 +496,9 @@ USHORT BLB_get_segment(thread_db* tdbb,
|
|||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
Database* dbb = tdbb->tdbb_database;
|
Database* dbb = tdbb->tdbb_database;
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
|
||||||
|
|
||||||
if (--tdbb->tdbb_quantum < 0)
|
if (--tdbb->tdbb_quantum < 0)
|
||||||
JRD_reschedule(tdbb, 0, true);
|
JRD_reschedule(tdbb, 0, true);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we reached end of file, we're still there */
|
/* If we reached end of file, we're still there */
|
||||||
|
|
||||||
if (blob->blb_flags & BLB_eof)
|
if (blob->blb_flags & BLB_eof)
|
||||||
|
@ -3859,11 +3859,9 @@ static SLONG fast_load(thread_db* tdbb,
|
|||||||
pointers[level] = levelPointer;
|
pointers[level] = levelPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
|
||||||
if (--tdbb->tdbb_quantum < 0) {
|
if (--tdbb->tdbb_quantum < 0) {
|
||||||
error = JRD_reschedule(tdbb, 0, false);
|
error = JRD_reschedule(tdbb, 0, false);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// To finish up, put an end of level marker on the last bucket
|
// To finish up, put an end of level marker on the last bucket
|
||||||
@ -6414,7 +6412,6 @@ static CONTENTS remove_leaf_node(thread_db* tdbb, index_insertion* insertion, WI
|
|||||||
} while (--l);
|
} while (--l);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
|
||||||
// Until deletion of duplicate nodes becomes efficient, limit
|
// Until deletion of duplicate nodes becomes efficient, limit
|
||||||
// leaf level traversal by rescheduling.
|
// leaf level traversal by rescheduling.
|
||||||
if (--tdbb->tdbb_quantum < 0) {
|
if (--tdbb->tdbb_quantum < 0) {
|
||||||
@ -6423,7 +6420,6 @@ static CONTENTS remove_leaf_node(thread_db* tdbb, index_insertion* insertion, WI
|
|||||||
ERR_punt();
|
ERR_punt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've needed to search thru a significant number of pages, warn the
|
// If we've needed to search thru a significant number of pages, warn the
|
||||||
|
@ -84,9 +84,10 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CANCEL_OPERATION
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
#ifdef SUPERSERVER
|
||||||
#define GOVERNOR
|
#define GOVERNOR
|
||||||
#define CANCEL_OPERATION
|
|
||||||
#define FB_ARCHITECTURE isc_info_db_class_server_access
|
#define FB_ARCHITECTURE isc_info_db_class_server_access
|
||||||
#else
|
#else
|
||||||
#define FB_ARCHITECTURE isc_info_db_class_classic_access
|
#define FB_ARCHITECTURE isc_info_db_class_classic_access
|
||||||
|
@ -578,10 +578,8 @@ void EXE_receive(thread_db* tdbb,
|
|||||||
|
|
||||||
DEV_BLKCHK(request, type_req);
|
DEV_BLKCHK(request, type_req);
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
|
||||||
if (--tdbb->tdbb_quantum < 0)
|
if (--tdbb->tdbb_quantum < 0)
|
||||||
JRD_reschedule(tdbb, 0, true);
|
JRD_reschedule(tdbb, 0, true);
|
||||||
#endif
|
|
||||||
|
|
||||||
jrd_tra* transaction = request->req_transaction;
|
jrd_tra* transaction = request->req_transaction;
|
||||||
|
|
||||||
@ -722,10 +720,8 @@ void EXE_send(thread_db* tdbb,
|
|||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
DEV_BLKCHK(request, type_req);
|
DEV_BLKCHK(request, type_req);
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
|
||||||
if (--tdbb->tdbb_quantum < 0)
|
if (--tdbb->tdbb_quantum < 0)
|
||||||
JRD_reschedule(tdbb, 0, true);
|
JRD_reschedule(tdbb, 0, true);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!(request->req_flags & req_active))
|
if (!(request->req_flags & req_active))
|
||||||
ERR_post(isc_req_sync, isc_arg_end);
|
ERR_post(isc_req_sync, isc_arg_end);
|
||||||
@ -1630,16 +1626,12 @@ static jrd_nod* looper(thread_db* tdbb, jrd_req* request, jrd_nod* in_node)
|
|||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
|
||||||
|
|
||||||
if (request->req_operation == jrd_req::req_evaluate &&
|
if (request->req_operation == jrd_req::req_evaluate &&
|
||||||
(--tdbb->tdbb_quantum < 0))
|
(--tdbb->tdbb_quantum < 0))
|
||||||
{
|
{
|
||||||
JRD_reschedule(tdbb, 0, true);
|
JRD_reschedule(tdbb, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(DEBUG_GDS_ALLOC) && FALSE
|
#if defined(DEBUG_GDS_ALLOC) && FALSE
|
||||||
int node_type = node->nod_type;
|
int node_type = node->nod_type;
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include "../jrd/jrd.h"
|
#include "../jrd/jrd.h"
|
||||||
#include "../jrd/tra.h"
|
#include "../jrd/tra.h"
|
||||||
#include "../jrd/dsc.h"
|
#include "../jrd/dsc.h"
|
||||||
#include "../jrd/y_handle.h"
|
|
||||||
#include "../jrd/thd.h"
|
#include "../jrd/thd.h"
|
||||||
#include "../jrd/err_proto.h"
|
#include "../jrd/err_proto.h"
|
||||||
#include "../jrd/mov_proto.h"
|
#include "../jrd/mov_proto.h"
|
||||||
@ -44,6 +43,7 @@
|
|||||||
#include "../jrd/thread_proto.h"
|
#include "../jrd/thread_proto.h"
|
||||||
#define WHY_NO_API
|
#define WHY_NO_API
|
||||||
#include "../jrd/why_proto.h"
|
#include "../jrd/why_proto.h"
|
||||||
|
#include "../jrd/y_handle.h"
|
||||||
|
|
||||||
#include "../jrd/align.h"
|
#include "../jrd/align.h"
|
||||||
#include "../jrd/execute_statement.h"
|
#include "../jrd/execute_statement.h"
|
||||||
@ -53,8 +53,7 @@
|
|||||||
using namespace Jrd;
|
using namespace Jrd;
|
||||||
using namespace Firebird;
|
using namespace Firebird;
|
||||||
|
|
||||||
WHY_DBB GetWhyAttachment(ISC_STATUS* status,
|
YValve::Attachment* GetWhyAttachment(ISC_STATUS*, Attachment*);
|
||||||
Attachment* jrd_attachment_handle);
|
|
||||||
|
|
||||||
static const SSHORT sqlType[] =
|
static const SSHORT sqlType[] =
|
||||||
{
|
{
|
||||||
@ -112,19 +111,14 @@ void ExecuteStatement::Open(thread_db* tdbb, jrd_nod* sql, SSHORT nVars, bool Si
|
|||||||
memcpy(StartOfSqlOperator, SqlText.c_str(), sizeof(StartOfSqlOperator) - 1);
|
memcpy(StartOfSqlOperator, SqlText.c_str(), sizeof(StartOfSqlOperator) - 1);
|
||||||
StartOfSqlOperator[sizeof(StartOfSqlOperator) - 1] = 0;
|
StartOfSqlOperator[sizeof(StartOfSqlOperator) - 1] = 0;
|
||||||
|
|
||||||
WHY_DBB temp_dbb = GetWhyAttachment(tdbb->tdbb_status_vector,
|
YValve::Attachment* temp_dbb = GetWhyAttachment(tdbb->tdbb_status_vector,
|
||||||
tdbb->tdbb_attachment);
|
tdbb->tdbb_attachment);
|
||||||
if (!temp_dbb)
|
if (!temp_dbb)
|
||||||
ERR_punt();
|
ERR_punt();
|
||||||
|
|
||||||
Attachment = temp_dbb->public_handle;
|
Attachment = temp_dbb->public_handle;
|
||||||
|
|
||||||
WHY_TRA temp_tra = WHY_alloc_handle(temp_dbb->implementation, HANDLE_transaction);
|
YValve::Transaction* temp_tra = new YValve::Transaction(tdbb->tdbb_transaction, &Transaction, temp_dbb);
|
||||||
if (!temp_tra)
|
|
||||||
ERR_post(isc_virmemexh, isc_arg_end);
|
|
||||||
Transaction = temp_tra->public_handle;
|
|
||||||
temp_tra->handle.h_tra = tdbb->tdbb_transaction;
|
|
||||||
temp_tra->parent = temp_dbb;
|
|
||||||
|
|
||||||
Statement = 0;
|
Statement = 0;
|
||||||
Sqlda = MakeSqlda(tdbb, nVars ? nVars : 1);
|
Sqlda = MakeSqlda(tdbb, nVars ? nVars : 1);
|
||||||
@ -290,12 +284,9 @@ void ExecuteStatement::Close(thread_db* tdbb)
|
|||||||
delete[] p;
|
delete[] p;
|
||||||
Sqlda = 0;
|
Sqlda = 0;
|
||||||
if (Transaction) {
|
if (Transaction) {
|
||||||
THREAD_EXIT();
|
delete YValve::translate<YValve::Transaction>(&Transaction);
|
||||||
WHY_cleanup_transaction(WHY_translate_handle(Transaction));
|
|
||||||
THREAD_ENTER();
|
|
||||||
}
|
|
||||||
WHY_free_handle(Transaction);
|
|
||||||
Transaction = 0;
|
Transaction = 0;
|
||||||
|
}
|
||||||
delete[] Buffer;
|
delete[] Buffer;
|
||||||
Buffer = 0;
|
Buffer = 0;
|
||||||
}
|
}
|
||||||
|
@ -488,10 +488,8 @@ void IDX_create_index(
|
|||||||
delete record;
|
delete record;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
|
||||||
if (--tdbb->tdbb_quantum < 0)
|
if (--tdbb->tdbb_quantum < 0)
|
||||||
cancel = JRD_reschedule(tdbb, 0, false);
|
cancel = JRD_reschedule(tdbb, 0, false);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gc_record->rec_flags &= ~REC_gc_active;
|
gc_record->rec_flags &= ~REC_gc_active;
|
||||||
|
269
src/jrd/jrd.cpp
269
src/jrd/jrd.cpp
@ -4424,7 +4424,6 @@ void JRD_print_procedure_info(thread_db* tdbb, const char* mesg)
|
|||||||
#endif /* DEBUG_PROCS */
|
#endif /* DEBUG_PROCS */
|
||||||
|
|
||||||
|
|
||||||
#ifdef MULTI_THREAD
|
|
||||||
bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
|
bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
@ -4439,9 +4438,10 @@ bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
|
|||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
|
|
||||||
/* Force garbage colletion activity to yield the
|
#ifdef MULTI_THREAD
|
||||||
processor in case client threads haven't had
|
// Force garbage collection activity to yield the
|
||||||
an opportunity to enter the scheduling queue. */
|
// processor in case client threads haven't had
|
||||||
|
// an opportunity to enter the scheduling queue.
|
||||||
|
|
||||||
if (!(tdbb->tdbb_flags & TDBB_sweeper))
|
if (!(tdbb->tdbb_flags & TDBB_sweeper))
|
||||||
SCH_schedule();
|
SCH_schedule();
|
||||||
@ -4450,6 +4450,7 @@ bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
|
|||||||
THREAD_YIELD();
|
THREAD_YIELD();
|
||||||
THREAD_ENTER();
|
THREAD_ENTER();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Test various flags and unwind/throw if required.
|
// Test various flags and unwind/throw if required.
|
||||||
// But do that only if we're not in the verb cleanup state,
|
// But do that only if we're not in the verb cleanup state,
|
||||||
@ -4533,13 +4534,16 @@ bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tdbb->tdbb_quantum = (tdbb->tdbb_quantum <= 0) ?
|
tdbb->tdbb_quantum = (tdbb->tdbb_quantum <= 0) ?
|
||||||
|
#ifdef MULTI_THREAD
|
||||||
(quantum ? quantum : (ThreadPriorityScheduler::boosted() ?
|
(quantum ? quantum : (ThreadPriorityScheduler::boosted() ?
|
||||||
Config::getPriorityBoost() : 1) * QUANTUM) :
|
Config::getPriorityBoost() : 1) * QUANTUM) :
|
||||||
|
#else
|
||||||
|
(quantum ? quantum : QUANTUM) :
|
||||||
|
#endif
|
||||||
tdbb->tdbb_quantum;
|
tdbb->tdbb_quantum;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void JRD_restore_context(void)
|
void JRD_restore_context(void)
|
||||||
@ -5014,7 +5018,8 @@ static ISC_STATUS error(ISC_STATUS* user_status)
|
|||||||
use count is erroneously left set. */
|
use count is erroneously left set. */
|
||||||
|
|
||||||
#if (defined DEV_BUILD && !defined MULTI_THREAD)
|
#if (defined DEV_BUILD && !defined MULTI_THREAD)
|
||||||
if (dbb && dbb->dbb_use_count && !(dbb->dbb_flags & DBB_security_db)) {
|
if (dbb && dbb->dbb_use_count && !(dbb->dbb_flags & DBB_security_db))
|
||||||
|
{
|
||||||
dbb->dbb_use_count = 0;
|
dbb->dbb_use_count = 0;
|
||||||
ISC_STATUS* p = user_status;
|
ISC_STATUS* p = user_status;
|
||||||
*p++ = isc_arg_gds;
|
*p++ = isc_arg_gds;
|
||||||
@ -6123,6 +6128,129 @@ void JRD_set_cache_default(ULONG* num_ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ISC_STATUS shutdown_dbb(thread_db* tdbb, Database* dbb, Attachment** released)
|
||||||
|
{
|
||||||
|
/**************************************
|
||||||
|
*
|
||||||
|
* s h u t d o w n _ d b b
|
||||||
|
*
|
||||||
|
**************************************
|
||||||
|
*
|
||||||
|
* Functional description
|
||||||
|
* rollback every transaction,
|
||||||
|
* release every attachment,
|
||||||
|
* and shutdown database.
|
||||||
|
*
|
||||||
|
**************************************/
|
||||||
|
if (!(dbb->dbb_flags & (DBB_bugcheck | DBB_not_in_use | DBB_security_db)) &&
|
||||||
|
!(dbb->dbb_ast_flags & DBB_shutdown &&
|
||||||
|
dbb->dbb_ast_flags & DBB_shutdown_locks))
|
||||||
|
{
|
||||||
|
Attachment* att_next;
|
||||||
|
for (Attachment* attach = dbb->dbb_attachments; attach; attach = att_next)
|
||||||
|
{
|
||||||
|
att_next = attach->att_next;
|
||||||
|
tdbb->tdbb_database = dbb;
|
||||||
|
tdbb->tdbb_attachment = attach;
|
||||||
|
tdbb->tdbb_request = NULL;
|
||||||
|
tdbb->tdbb_transaction = NULL;
|
||||||
|
tdbb->tdbb_flags |= TDBB_shutdown_manager;
|
||||||
|
Jrd::ContextPoolHolder context(tdbb, 0);
|
||||||
|
++dbb->dbb_use_count;
|
||||||
|
|
||||||
|
// purge_attachment() below can do an ERR_post
|
||||||
|
ISC_STATUS_ARRAY user_status;
|
||||||
|
tdbb->tdbb_status_vector = user_status;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// purge attachment, rollback any open transactions
|
||||||
|
#if defined(V4_THREADING) && !defined(SUPERSERVER)
|
||||||
|
V4_JRD_MUTEX_LOCK(dbb->dbb_mutexes + DBB_MUTX_init_fini);
|
||||||
|
#endif
|
||||||
|
purge_attachment(tdbb, user_status, attach, true);
|
||||||
|
#if defined(V4_THREADING) && !defined(SUPERSERVER)
|
||||||
|
V4_JRD_MUTEX_UNLOCK(databases_mutex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (const std::exception& ex)
|
||||||
|
{
|
||||||
|
if (released)
|
||||||
|
{
|
||||||
|
*released = 0;
|
||||||
|
}
|
||||||
|
return error(user_status, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// attach became invalid pointer
|
||||||
|
// if we have someone, intereted in that fact, inform him
|
||||||
|
if (released)
|
||||||
|
{
|
||||||
|
*released++ = attach;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (released)
|
||||||
|
{
|
||||||
|
*released = 0;
|
||||||
|
}
|
||||||
|
return FB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ISC_STATUS shutdown_all()
|
||||||
|
{
|
||||||
|
/**************************************
|
||||||
|
*
|
||||||
|
* s h u t d o w n _ a l l
|
||||||
|
*
|
||||||
|
**************************************
|
||||||
|
*
|
||||||
|
* Functional description
|
||||||
|
* rollback every transaction,
|
||||||
|
* release every attachment,
|
||||||
|
* and shutdown every database.
|
||||||
|
*
|
||||||
|
**************************************/
|
||||||
|
THREAD_ENTER();
|
||||||
|
// NOTE!!!
|
||||||
|
// This routine doesn't contain THREAD_EXIT to help ensure
|
||||||
|
// that no threads will get in and try to access the data
|
||||||
|
// structures we released here
|
||||||
|
|
||||||
|
thread_db thd_context;
|
||||||
|
thread_db* tdbb = JRD_MAIN_set_thread_data(thd_context);
|
||||||
|
|
||||||
|
if (initialized) {
|
||||||
|
JRD_SS_MUTEX_LOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Database* dbb_next;
|
||||||
|
for (Database* dbb = databases; dbb; dbb = dbb_next)
|
||||||
|
{
|
||||||
|
dbb_next = dbb->dbb_next;
|
||||||
|
|
||||||
|
ISC_STATUS rc = shutdown_dbb(tdbb, dbb, 0);
|
||||||
|
if (rc != FB_SUCCESS)
|
||||||
|
{
|
||||||
|
if (initialized)
|
||||||
|
{
|
||||||
|
JRD_SS_MUTEX_UNLOCK;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialized) {
|
||||||
|
JRD_SS_MUTEX_UNLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
JRD_restore_context();
|
||||||
|
|
||||||
|
return FB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef SERVER_SHUTDOWN
|
#ifdef SERVER_SHUTDOWN
|
||||||
TEXT* JRD_num_attachments(TEXT* const buf, USHORT buf_len, USHORT flag,
|
TEXT* JRD_num_attachments(TEXT* const buf, USHORT buf_len, USHORT flag,
|
||||||
USHORT* atts, USHORT* dbs)
|
USHORT* atts, USHORT* dbs)
|
||||||
@ -6356,92 +6484,9 @@ static void ExtractDriveLetter(const TEXT* file_name, ULONG* drive_mask)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
ISC_STATUS shutdown_all()
|
|
||||||
{
|
|
||||||
/**************************************
|
|
||||||
*
|
|
||||||
* s h u t d o w n _ a l l
|
|
||||||
*
|
|
||||||
**************************************
|
|
||||||
*
|
|
||||||
* Functional description
|
|
||||||
* rollback every transaction,
|
|
||||||
* release every attachment,
|
|
||||||
* and shutdown every database.
|
|
||||||
*
|
|
||||||
**************************************/
|
|
||||||
THREAD_ENTER();
|
|
||||||
// NOTE!!!
|
|
||||||
// This routine doesn't contain THREAD_EXIT to help ensure
|
|
||||||
// that no threads will get in and try to access the data
|
|
||||||
// structures we released here
|
|
||||||
|
|
||||||
thread_db thd_context;
|
|
||||||
thread_db* tdbb = JRD_MAIN_set_thread_data(thd_context);
|
|
||||||
|
|
||||||
if (initialized) {
|
|
||||||
JRD_SS_MUTEX_LOCK;
|
|
||||||
}
|
|
||||||
ISC_STATUS_ARRAY user_status;
|
|
||||||
|
|
||||||
Database* dbb_next;
|
|
||||||
for (Database* dbb = databases; dbb; dbb = dbb_next)
|
|
||||||
{
|
|
||||||
dbb_next = dbb->dbb_next;
|
|
||||||
if (!(dbb->dbb_flags & (DBB_bugcheck | DBB_not_in_use | DBB_security_db)) &&
|
|
||||||
!(dbb->dbb_ast_flags & DBB_shutdown &&
|
|
||||||
dbb->dbb_ast_flags & DBB_shutdown_locks))
|
|
||||||
{
|
|
||||||
Attachment* att_next;
|
|
||||||
for (Attachment* attach = dbb->dbb_attachments; attach; attach = att_next)
|
|
||||||
{
|
|
||||||
att_next = attach->att_next;
|
|
||||||
tdbb->tdbb_database = dbb;
|
|
||||||
tdbb->tdbb_attachment = attach;
|
|
||||||
tdbb->tdbb_request = NULL;
|
|
||||||
tdbb->tdbb_transaction = NULL;
|
|
||||||
tdbb->tdbb_flags |= TDBB_shutdown_manager;
|
|
||||||
Jrd::ContextPoolHolder context(tdbb, 0);
|
|
||||||
|
|
||||||
++dbb->dbb_use_count;
|
|
||||||
|
|
||||||
/* purge_attachment below can do an ERR_post */
|
|
||||||
|
|
||||||
tdbb->tdbb_status_vector = user_status;
|
|
||||||
|
|
||||||
try {
|
|
||||||
/* purge attachment, rollback any open transactions */
|
|
||||||
|
|
||||||
#if defined(V4_THREADING) && !defined(SUPERSERVER)
|
|
||||||
V4_JRD_MUTEX_LOCK(dbb->dbb_mutexes + DBB_MUTX_init_fini);
|
|
||||||
#endif
|
|
||||||
purge_attachment(tdbb, user_status, attach, true);
|
|
||||||
#if defined(V4_THREADING) && !defined(SUPERSERVER)
|
|
||||||
V4_JRD_MUTEX_UNLOCK(databases_mutex);
|
|
||||||
#endif
|
|
||||||
} // try
|
|
||||||
catch (const std::exception& ex) {
|
|
||||||
if (initialized) {
|
|
||||||
JRD_SS_MUTEX_UNLOCK;
|
|
||||||
}
|
|
||||||
return error(user_status, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (initialized) {
|
|
||||||
JRD_SS_MUTEX_UNLOCK;
|
|
||||||
}
|
|
||||||
|
|
||||||
JRD_restore_context();
|
|
||||||
|
|
||||||
return FB_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
#ifdef SUPERSERVER
|
||||||
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg) {
|
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg)
|
||||||
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
* s h u t d o w n _ t h r e a d
|
* s h u t d o w n _ t h r e a d
|
||||||
@ -6476,9 +6521,9 @@ void JRD_shutdown_all(bool asyncMode)
|
|||||||
* asynchronous shutdown.
|
* asynchronous shutdown.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
#ifdef SUPERSERVER
|
|
||||||
int flShutdownComplete = 0;
|
int flShutdownComplete = 0;
|
||||||
|
|
||||||
|
#ifdef SUPERSERVER
|
||||||
if (asyncMode)
|
if (asyncMode)
|
||||||
{
|
{
|
||||||
gds__thread_start(shutdown_thread, &flShutdownComplete,
|
gds__thread_start(shutdown_thread, &flShutdownComplete,
|
||||||
@ -6492,6 +6537,7 @@ void JRD_shutdown_all(bool asyncMode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // sync mode
|
else // sync mode
|
||||||
|
#endif // SUPERSERVER
|
||||||
{
|
{
|
||||||
flShutdownComplete = (shutdown_all() == FB_SUCCESS);
|
flShutdownComplete = (shutdown_all() == FB_SUCCESS);
|
||||||
}
|
}
|
||||||
@ -6500,8 +6546,45 @@ void JRD_shutdown_all(bool asyncMode)
|
|||||||
{
|
{
|
||||||
gds__log("Forced server shutdown - not all databases closed");
|
gds__log("Forced server shutdown - not all databases closed");
|
||||||
}
|
}
|
||||||
#endif // SUPERSERVER
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else // SERVER_SHUTDOWN
|
||||||
|
|
||||||
|
// This conditional compilation, though sitting under not
|
||||||
|
// defined SERVER_SHUTDOWN, performs full or partial shutdown
|
||||||
|
// of database. SERVER_SHUTDOWN defined controls some other
|
||||||
|
// aspects of operation, therefore was left "as is".
|
||||||
|
// Who wants to invent better naem for it, please do it.
|
||||||
|
|
||||||
|
void JRD_process_close()
|
||||||
|
{
|
||||||
|
shutdown_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JRD_database_close(Attachment** handle, Attachment** released)
|
||||||
|
{
|
||||||
|
THREAD_ENTER();
|
||||||
|
thread_db thd_context;
|
||||||
|
thread_db* tdbb = JRD_MAIN_set_thread_data(thd_context);
|
||||||
|
|
||||||
|
Database* dbb = databases;
|
||||||
|
for (; dbb; dbb = dbb->dbb_next)
|
||||||
|
{
|
||||||
|
for (Attachment* attach = dbb->dbb_attachments; attach; attach = attach->att_next)
|
||||||
|
{
|
||||||
|
if (attach == *handle)
|
||||||
|
{
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
found:
|
||||||
|
// got dbb to be closed
|
||||||
|
shutdown_dbb(tdbb, dbb, released);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* SERVER_SHUTDOWN */
|
#endif /* SERVER_SHUTDOWN */
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,6 +148,9 @@ const USHORT JRD_info_dbnames = 2;
|
|||||||
|
|
||||||
TEXT* JRD_num_attachments(TEXT* const, USHORT, USHORT, USHORT*, USHORT*);
|
TEXT* JRD_num_attachments(TEXT* const, USHORT, USHORT, USHORT*, USHORT*);
|
||||||
void JRD_shutdown_all(bool);
|
void JRD_shutdown_all(bool);
|
||||||
|
#else /* SERVER_SHUTDOWN */
|
||||||
|
void JRD_process_close();
|
||||||
|
void JRD_database_close(Jrd::Attachment**, Jrd::Attachment**);
|
||||||
#endif /* SERVER_SHUTDOWN */
|
#endif /* SERVER_SHUTDOWN */
|
||||||
|
|
||||||
void JRD_set_cache_default(ULONG *);
|
void JRD_set_cache_default(ULONG *);
|
||||||
|
@ -34,7 +34,7 @@ int ISC_kill(SLONG, SLONG, void *);
|
|||||||
#else
|
#else
|
||||||
// And that are functions to manage UNIX signals
|
// And that are functions to manage UNIX signals
|
||||||
int ISC_kill(SLONG, SLONG);
|
int ISC_kill(SLONG, SLONG);
|
||||||
void ISC_signal(int, FPTR_VOID_PTR, void *);
|
bool ISC_signal(int, FPTR_VOID_PTR, void *);
|
||||||
void ISC_signal_cancel(int, FPTR_VOID_PTR, void *);
|
void ISC_signal_cancel(int, FPTR_VOID_PTR, void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: isc_ipc.cpp,v 1.17.4.5 2008-08-28 06:37:33 alexpeshkoff Exp $ */
|
/* $Id: isc_ipc.cpp,v 1.17.4.6 2008-09-15 11:25:41 alexpeshkoff Exp $ */
|
||||||
|
|
||||||
#include "firebird.h"
|
#include "firebird.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -128,7 +128,7 @@ static int volatile relay_pipe = 0;
|
|||||||
|
|
||||||
|
|
||||||
static void cleanup(void* arg);
|
static void cleanup(void* arg);
|
||||||
static void isc_signal2(int signal, FPTR_VOID handler, void* arg, ULONG);
|
static bool isc_signal2(int signal, FPTR_VOID handler, void* arg, ULONG);
|
||||||
static SLONG overflow_handler(void* arg);
|
static SLONG overflow_handler(void* arg);
|
||||||
static SIG que_signal(int signal, FPTR_VOID handler, void* arg, int flags);
|
static SIG que_signal(int signal, FPTR_VOID handler, void* arg, int flags);
|
||||||
|
|
||||||
@ -242,6 +242,9 @@ int ISC_kill(SLONG pid, SLONG signal_number)
|
|||||||
* Notify somebody else.
|
* Notify somebody else.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
|
if (! pid)
|
||||||
|
pid = getpid();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const int status = kill(pid, signal_number);
|
const int status = kill(pid, signal_number);
|
||||||
|
|
||||||
@ -302,7 +305,7 @@ int ISC_kill(SLONG pid, SLONG signal_number)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ISC_signal(int signal_number, FPTR_VOID_PTR handler, void* arg)
|
bool ISC_signal(int signal_number, FPTR_VOID_PTR handler, void* arg)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
@ -314,11 +317,11 @@ void ISC_signal(int signal_number, FPTR_VOID_PTR handler, void* arg)
|
|||||||
* Multiplex multiple handers into single signal.
|
* Multiplex multiple handers into single signal.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
isc_signal2(signal_number, reinterpret_cast<FPTR_VOID>(handler), arg, SIG_user);
|
return isc_signal2(signal_number, reinterpret_cast<FPTR_VOID>(handler), arg, SIG_user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void isc_signal2(
|
static bool isc_signal2(
|
||||||
int signal_number,
|
int signal_number,
|
||||||
FPTR_VOID handler, void* arg, ULONG flags)
|
FPTR_VOID handler, void* arg, ULONG flags)
|
||||||
{
|
{
|
||||||
@ -334,6 +337,7 @@ static void isc_signal2(
|
|||||||
**************************************/
|
**************************************/
|
||||||
|
|
||||||
SIG sig;
|
SIG sig;
|
||||||
|
bool rc = false;
|
||||||
|
|
||||||
/* The signal handler needs the process id */
|
/* The signal handler needs the process id */
|
||||||
if (!process_id)
|
if (!process_id)
|
||||||
@ -377,6 +381,7 @@ static void isc_signal2(
|
|||||||
{
|
{
|
||||||
que_signal(signal_number, reinterpret_cast<FPTR_VOID>(oact.sa_handler),
|
que_signal(signal_number, reinterpret_cast<FPTR_VOID>(oact.sa_handler),
|
||||||
NULL, SIG_client);
|
NULL, SIG_client);
|
||||||
|
rc = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,6 +390,8 @@ static void isc_signal2(
|
|||||||
que_signal(signal_number, handler, arg, flags);
|
que_signal(signal_number, handler, arg, flags);
|
||||||
|
|
||||||
THD_MUTEX_UNLOCK(&sig_mutex);
|
THD_MUTEX_UNLOCK(&sig_mutex);
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1794,15 +1794,11 @@ static bool get_record(thread_db* tdbb,
|
|||||||
**************************************/
|
**************************************/
|
||||||
SET_TDBB(tdbb);
|
SET_TDBB(tdbb);
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
|
||||||
|
|
||||||
if (--tdbb->tdbb_quantum < 0)
|
if (--tdbb->tdbb_quantum < 0)
|
||||||
{
|
{
|
||||||
JRD_reschedule(tdbb, 0, true);
|
JRD_reschedule(tdbb, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* check request flags for special processing */
|
/* check request flags for special processing */
|
||||||
|
|
||||||
jrd_req* request = tdbb->tdbb_request;
|
jrd_req* request = tdbb->tdbb_request;
|
||||||
|
@ -821,10 +821,8 @@ static FETCH_CODE fetch_page(thread_db* tdbb,
|
|||||||
Database* dbb = tdbb->tdbb_database;
|
Database* dbb = tdbb->tdbb_database;
|
||||||
CHECK_DBB(dbb);
|
CHECK_DBB(dbb);
|
||||||
|
|
||||||
#ifdef SUPERSERVER
|
|
||||||
if (--tdbb->tdbb_quantum < 0)
|
if (--tdbb->tdbb_quantum < 0)
|
||||||
JRD_reschedule(tdbb, 0, true);
|
JRD_reschedule(tdbb, 0, true);
|
||||||
#endif
|
|
||||||
|
|
||||||
window->win_page = page_number;
|
window->win_page = page_number;
|
||||||
window->win_flags = 0;
|
window->win_flags = 0;
|
||||||
|
@ -3607,14 +3607,12 @@ static void garbage_collect(thread_db* tdbb,
|
|||||||
if (rpb->rpb_record) {
|
if (rpb->rpb_record) {
|
||||||
going.push(rpb->rpb_record);
|
going.push(rpb->rpb_record);
|
||||||
}
|
}
|
||||||
#ifdef SUPERSERVER
|
|
||||||
/* Don't monopolize the server while chasing long
|
/* Don't monopolize the server while chasing long
|
||||||
back version chains. */
|
back version chains. */
|
||||||
|
|
||||||
if (--tdbb->tdbb_quantum < 0) {
|
if (--tdbb->tdbb_quantum < 0) {
|
||||||
JRD_reschedule(tdbb, 0, true);
|
JRD_reschedule(tdbb, 0, true);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BLB_garbage_collect(tdbb, going, staying, prior_page, rpb->rpb_relation);
|
BLB_garbage_collect(tdbb, going, staying, prior_page, rpb->rpb_relation);
|
||||||
@ -4069,14 +4067,12 @@ static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& stayin
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
depth++;
|
depth++;
|
||||||
#ifdef SUPERSERVER
|
|
||||||
/* Don't monopolize the server while chasing long
|
/* Don't monopolize the server while chasing long
|
||||||
back version chains. */
|
back version chains. */
|
||||||
|
|
||||||
if (--tdbb->tdbb_quantum < 0) {
|
if (--tdbb->tdbb_quantum < 0) {
|
||||||
JRD_reschedule(tdbb, 0, true);
|
JRD_reschedule(tdbb, 0, true);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (timed_out) {
|
if (timed_out) {
|
||||||
continue;
|
continue;
|
||||||
|
3773
src/jrd/why.cpp
3773
src/jrd/why.cpp
File diff suppressed because it is too large
Load Diff
@ -255,8 +255,6 @@ SLONG API_ROUTINE isc_reset_fpe(USHORT);
|
|||||||
#endif /* JRD_IBASE_H */
|
#endif /* JRD_IBASE_H */
|
||||||
#endif /* WHY_NO_API */
|
#endif /* WHY_NO_API */
|
||||||
|
|
||||||
typedef void DatabaseCleanupRoutine(FB_API_HANDLE*, void*);
|
|
||||||
|
|
||||||
#ifdef CANCEL_OPERATION
|
#ifdef CANCEL_OPERATION
|
||||||
#define CANCEL_disable 1
|
#define CANCEL_disable 1
|
||||||
#define CANCEL_enable 2
|
#define CANCEL_enable 2
|
||||||
@ -264,8 +262,11 @@ typedef void DatabaseCleanupRoutine(FB_API_HANDLE*, void*);
|
|||||||
ISC_STATUS API_ROUTINE gds__cancel_operation(ISC_STATUS*, FB_API_HANDLE*, USHORT);
|
ISC_STATUS API_ROUTINE gds__cancel_operation(ISC_STATUS*, FB_API_HANDLE*, USHORT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef void AttachmentCleanupRoutine(FB_API_HANDLE*, void*);
|
||||||
|
typedef void TransactionCleanupRoutine(FB_API_HANDLE, void*);
|
||||||
|
|
||||||
ISC_STATUS API_ROUTINE isc_database_cleanup(ISC_STATUS*, FB_API_HANDLE*,
|
ISC_STATUS API_ROUTINE isc_database_cleanup(ISC_STATUS*, FB_API_HANDLE*,
|
||||||
DatabaseCleanupRoutine*, void*);
|
AttachmentCleanupRoutine*, void*);
|
||||||
int API_ROUTINE gds__disable_subsystem(TEXT*);
|
int API_ROUTINE gds__disable_subsystem(TEXT*);
|
||||||
int API_ROUTINE gds__enable_subsystem(TEXT*);
|
int API_ROUTINE gds__enable_subsystem(TEXT*);
|
||||||
|
|
||||||
@ -275,7 +276,6 @@ ISC_STATUS gds__handle_cleanup(ISC_STATUS*, FB_API_HANDLE*);
|
|||||||
#define INTL_FUNCTION_OCTET_LENGTH 2
|
#define INTL_FUNCTION_OCTET_LENGTH 2
|
||||||
ISC_STATUS API_ROUTINE gds__intl_function(ISC_STATUS*, FB_API_HANDLE*, USHORT, UCHAR, USHORT, const UCHAR*, USHORT*);
|
ISC_STATUS API_ROUTINE gds__intl_function(ISC_STATUS*, FB_API_HANDLE*, USHORT, UCHAR, USHORT, const UCHAR*, USHORT*);
|
||||||
|
|
||||||
typedef void TransactionCleanupRoutine(FB_API_HANDLE, void*);
|
|
||||||
ISC_STATUS API_ROUTINE gds__transaction_cleanup(ISC_STATUS*, FB_API_HANDLE*,
|
ISC_STATUS API_ROUTINE gds__transaction_cleanup(ISC_STATUS*, FB_API_HANDLE*,
|
||||||
TransactionCleanupRoutine*, void*);
|
TransactionCleanupRoutine*, void*);
|
||||||
void WHY_cleanup_transaction(struct why_hndl* transaction);
|
void WHY_cleanup_transaction(struct why_hndl* transaction);
|
||||||
@ -290,9 +290,5 @@ BOOLEAN WHY_get_shutdown();
|
|||||||
} /* extern "C"*/
|
} /* extern "C"*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct why_hndl* WHY_alloc_handle(int implementation, int handle_type);
|
|
||||||
struct why_hndl* WHY_translate_handle(FB_API_HANDLE handle);
|
|
||||||
void WHY_free_handle(FB_API_HANDLE handle);
|
|
||||||
|
|
||||||
#endif // JRD_WHY_PROTO_H
|
#endif // JRD_WHY_PROTO_H
|
||||||
|
|
||||||
|
@ -25,12 +25,15 @@
|
|||||||
#ifndef JRD_Y_HANDLE_H
|
#ifndef JRD_Y_HANDLE_H
|
||||||
#define JRD_Y_HANDLE_H
|
#define JRD_Y_HANDLE_H
|
||||||
|
|
||||||
/*
|
#include "../common/classes/alloc.h"
|
||||||
* These definitions placed into separate file
|
#include "../common/classes/array.h"
|
||||||
* to avoid multiple definition of struct why_hndl in why.cpp
|
#include "../common/classes/fb_string.h"
|
||||||
* and dsql.cpp
|
#include "../dsql/sqlda_pub.h"
|
||||||
*
|
#include "../dsql/sqlda.h"
|
||||||
*/
|
#include "../jrd/thread_proto.h"
|
||||||
|
|
||||||
|
#include "gen/iberror.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Jrd {
|
namespace Jrd {
|
||||||
class Attachment;
|
class Attachment;
|
||||||
@ -38,52 +41,352 @@ namespace Jrd {
|
|||||||
class jrd_req;
|
class jrd_req;
|
||||||
}
|
}
|
||||||
|
|
||||||
union any_handle {
|
class dsql_req;
|
||||||
struct why_hndl* h_why;
|
|
||||||
class dsql_req* h_dsql;
|
|
||||||
Jrd::Attachment* h_dbb;
|
|
||||||
Jrd::jrd_tra* h_tra;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct why_hndl
|
namespace YValve
|
||||||
{
|
{
|
||||||
|
// flags
|
||||||
|
const UCHAR HANDLE_TRANSACTION_limbo = 1;
|
||||||
|
const UCHAR HANDLE_BLOB_filter = 2; /* Blob is locally filtered */
|
||||||
|
const UCHAR HANDLE_STATEMENT_local = 4; /* Process DSQL statement locally */
|
||||||
|
const UCHAR HANDLE_STATEMENT_prepared = 8;
|
||||||
|
const UCHAR HANDLE_shutdown = 0x10; // Database shutdown
|
||||||
|
|
||||||
|
// forwards
|
||||||
|
class Attachment;
|
||||||
|
class Transaction;
|
||||||
|
class Request;
|
||||||
|
class Blob;
|
||||||
|
class Statement;
|
||||||
|
class Service;
|
||||||
|
|
||||||
|
// force use of default memory pool for Y-Valve objects
|
||||||
|
class DefaultMemory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void* operator new(size_t size)
|
||||||
|
{
|
||||||
|
return getDefaultMemoryPool()->allocate(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void* mem)
|
||||||
|
{
|
||||||
|
getDefaultMemoryPool()->deallocate(mem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// stored handle types
|
||||||
|
typedef Jrd::jrd_tra StTra;
|
||||||
|
typedef void StReq;
|
||||||
|
typedef void StBlb;
|
||||||
|
typedef Jrd::Attachment StAtt;
|
||||||
|
typedef dsql_req StStm;
|
||||||
|
typedef void StSvc;
|
||||||
|
|
||||||
|
template <typename CleanupRoutine, typename CleanupArg>
|
||||||
|
class Clean : public DefaultMemory
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct st_clean
|
||||||
|
{
|
||||||
|
CleanupRoutine *Routine;
|
||||||
|
void* clean_arg;
|
||||||
|
st_clean(CleanupRoutine *r, void* a)
|
||||||
|
: Routine(r), clean_arg(a) { }
|
||||||
|
st_clean()
|
||||||
|
: Routine(0), clean_arg(0) { }
|
||||||
|
};
|
||||||
|
Firebird::HalfStaticArray<st_clean, 1> calls;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Clean() : calls(*getDefaultMemoryPool()) { }
|
||||||
|
|
||||||
|
void add(CleanupRoutine *r, void* a)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < calls.getCount(); ++i)
|
||||||
|
{
|
||||||
|
if (calls[i].Routine == r &&
|
||||||
|
calls[i].clean_arg == a)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
calls.add(st_clean(r, a));
|
||||||
|
}
|
||||||
|
|
||||||
|
void call(CleanupArg public_handle)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < calls.getCount(); ++i)
|
||||||
|
{
|
||||||
|
if (calls[i].Routine)
|
||||||
|
{
|
||||||
|
THREAD_EXIT();
|
||||||
|
calls[i].Routine(public_handle, calls[i].clean_arg);
|
||||||
|
THREAD_ENTER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Handle : public DefaultMemory
|
||||||
|
{
|
||||||
|
public:
|
||||||
UCHAR type;
|
UCHAR type;
|
||||||
UCHAR flags;
|
UCHAR flags;
|
||||||
USHORT implementation;
|
USHORT implementation;
|
||||||
FB_API_HANDLE public_handle;
|
FB_API_HANDLE public_handle;
|
||||||
union any_handle handle;
|
Attachment* parent;
|
||||||
struct why_hndl* parent;
|
|
||||||
struct why_hndl* next;
|
|
||||||
union {
|
|
||||||
struct why_hndl* requests;
|
|
||||||
struct sqlda_sup* das;
|
|
||||||
};
|
|
||||||
struct why_hndl* statements;
|
|
||||||
struct why_hndl* blobs;
|
|
||||||
FB_API_HANDLE* user_handle;
|
FB_API_HANDLE* user_handle;
|
||||||
struct clean* cleanup;
|
|
||||||
TEXT* db_path;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef why_hndl *WHY_HNDL;
|
protected:
|
||||||
typedef why_hndl *WHY_REQ;
|
Handle(UCHAR t, FB_API_HANDLE* pub, Attachment* par, USHORT imp = ~0);
|
||||||
typedef why_hndl *WHY_DBB;
|
|
||||||
typedef why_hndl *WHY_TRA;
|
|
||||||
typedef why_hndl *WHY_BLB;
|
|
||||||
typedef why_hndl *WHY_ATT;
|
|
||||||
typedef why_hndl *WHY_STMT;
|
|
||||||
typedef why_hndl *WHY_SVC;
|
|
||||||
|
|
||||||
const int HANDLE_invalid = 0;
|
public:
|
||||||
const int HANDLE_database = 1;
|
static Handle* translate(FB_API_HANDLE);
|
||||||
const int HANDLE_transaction = 2;
|
Jrd::Attachment* getAttachmentHandle();
|
||||||
const int HANDLE_request = 3;
|
void cancel();
|
||||||
const int HANDLE_blob = 4;
|
~Handle();
|
||||||
const int HANDLE_statement = 5;
|
|
||||||
const int HANDLE_service = 6;
|
|
||||||
|
|
||||||
const int HANDLE_TRANSACTION_limbo = 1;
|
// required to put pointers to it into the tree
|
||||||
const int HANDLE_BLOB_filter = 2; /* Blob is locally filtered */
|
static const FB_API_HANDLE& generate(const void* sender, Handle* value) {
|
||||||
const int HANDLE_STATEMENT_local = 4; /* Process DSQL statement locally */
|
return value->public_handle;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename HType>
|
||||||
|
void toParent(Firebird::SortedArray<HType*>& members, HType* newMember)
|
||||||
|
{
|
||||||
|
members.add(newMember);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename HType>
|
||||||
|
void fromParent(Firebird::SortedArray<HType*>& members, HType* newMember)
|
||||||
|
{
|
||||||
|
size_t pos;
|
||||||
|
if (members.find(newMember, pos))
|
||||||
|
{
|
||||||
|
members.remove(pos);
|
||||||
|
}
|
||||||
|
#ifdef DEV_BUILD
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Attempt to deregister not registered member
|
||||||
|
fb_assert(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ToHandle>
|
||||||
|
ToHandle* translate(FB_API_HANDLE* handle)
|
||||||
|
{
|
||||||
|
if (handle && *handle)
|
||||||
|
{
|
||||||
|
Handle* rc = Handle::translate(*handle);
|
||||||
|
if (rc && rc->type == ToHandle::hType())
|
||||||
|
{
|
||||||
|
return reinterpret_cast<ToHandle*>(rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Firebird::status_exception::raise(ToHandle::hError(),
|
||||||
|
isc_arg_end);
|
||||||
|
// compiler warning silencer
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Attachment : public Handle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Firebird::SortedArray<Transaction*> transactions;
|
||||||
|
Firebird::SortedArray<Request*> requests;
|
||||||
|
Firebird::SortedArray<Blob*> blobs;
|
||||||
|
Firebird::SortedArray<Statement*> statements;
|
||||||
|
|
||||||
|
Clean<AttachmentCleanupRoutine, FB_API_HANDLE*> cleanup;
|
||||||
|
StAtt* handle;
|
||||||
|
Firebird::PathName db_path;
|
||||||
|
|
||||||
|
static ISC_STATUS hError()
|
||||||
|
{
|
||||||
|
return isc_bad_db_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UCHAR hType()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Attachment(StAtt*, FB_API_HANDLE*, USHORT);
|
||||||
|
void cancel2();
|
||||||
|
~Attachment();
|
||||||
|
};
|
||||||
|
|
||||||
|
class Transaction : public Handle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Clean<TransactionCleanupRoutine, FB_API_HANDLE> cleanup;
|
||||||
|
Transaction* next;
|
||||||
|
StTra* handle;
|
||||||
|
|
||||||
|
static ISC_STATUS hError()
|
||||||
|
{
|
||||||
|
return isc_bad_trans_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UCHAR hType()
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Transaction(StTra* h, FB_API_HANDLE* pub, Attachment* par)
|
||||||
|
: Handle(hType(), pub, par),
|
||||||
|
next(0), handle(h)
|
||||||
|
{
|
||||||
|
toParent(parent->transactions, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction(FB_API_HANDLE* pub, USHORT implementation)
|
||||||
|
: Handle(hType(), pub, 0, implementation),
|
||||||
|
next(0), handle(0)
|
||||||
|
{
|
||||||
|
// toParent(parent->transactions, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Transaction()
|
||||||
|
{
|
||||||
|
cleanup.call(public_handle);
|
||||||
|
if (parent)
|
||||||
|
{
|
||||||
|
fromParent(parent->transactions, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Request : public Handle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StReq* handle;
|
||||||
|
|
||||||
|
static ISC_STATUS hError()
|
||||||
|
{
|
||||||
|
return isc_bad_req_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UCHAR hType()
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Request(StReq* h, FB_API_HANDLE* pub, Attachment* par)
|
||||||
|
: Handle(hType(), pub, par), handle(h)
|
||||||
|
{
|
||||||
|
toParent(parent->requests, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Request()
|
||||||
|
{
|
||||||
|
fromParent(parent->requests, this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Blob : public Handle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StBlb* handle;
|
||||||
|
|
||||||
|
static ISC_STATUS hError()
|
||||||
|
{
|
||||||
|
return isc_bad_segstr_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UCHAR hType()
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Blob(StBlb* h, FB_API_HANDLE* pub, Attachment* par)
|
||||||
|
: Handle(hType(), pub, par), handle(h)
|
||||||
|
{
|
||||||
|
toParent(parent->blobs, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Blob()
|
||||||
|
{
|
||||||
|
fromParent(parent->blobs, this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Statement : public Handle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StStm* handle;
|
||||||
|
struct sqlda_sup das;
|
||||||
|
|
||||||
|
static ISC_STATUS hError()
|
||||||
|
{
|
||||||
|
return isc_bad_stmt_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UCHAR hType()
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Statement(StStm* h, FB_API_HANDLE* pub, Attachment* par)
|
||||||
|
: Handle(hType(), pub, par), handle(h)
|
||||||
|
{
|
||||||
|
toParent(parent->statements, this);
|
||||||
|
memset(&das, 0, sizeof das);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkPrepared()
|
||||||
|
{
|
||||||
|
if (!(flags & HANDLE_STATEMENT_prepared))
|
||||||
|
{
|
||||||
|
Firebird::status_exception::raise(isc_unprepared_stmt, isc_arg_end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Statement()
|
||||||
|
{
|
||||||
|
fromParent(parent->statements, this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Service : public Handle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Clean<AttachmentCleanupRoutine, FB_API_HANDLE*> cleanup;
|
||||||
|
StSvc* handle;
|
||||||
|
|
||||||
|
static ISC_STATUS hError()
|
||||||
|
{
|
||||||
|
return isc_bad_svc_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UCHAR hType()
|
||||||
|
{
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Service(StSvc* h, FB_API_HANDLE* pub, USHORT impl)
|
||||||
|
: Handle(hType(), pub, 0, impl), handle(h)
|
||||||
|
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~Service()
|
||||||
|
{
|
||||||
|
cleanup.call(&public_handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif // JRD_Y_HANDLE_H
|
#endif // JRD_Y_HANDLE_H
|
||||||
|
@ -4429,6 +4429,15 @@ ISC_STATUS rem_port::send_response( PACKET* sendL,
|
|||||||
|
|
||||||
this->send(sendL);
|
this->send(sendL);
|
||||||
|
|
||||||
|
#ifndef SUPERSERVER
|
||||||
|
// In case of CS remote listener we have a single connection system.
|
||||||
|
// If database is shut down, it's no use running fb_inet_server any more.
|
||||||
|
if (exit_code == isc_shutdown)
|
||||||
|
{
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user