8
0
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:
alexpeshkoff 2008-09-15 11:25:59 +00:00
parent 974df75779
commit 63e2610d3a
20 changed files with 2879 additions and 2687 deletions

View File

@ -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;
} }

View File

@ -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);

View File

@ -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*);

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
} }

View File

@ -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;

View File

@ -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 */

View File

@ -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 *);

View File

@ -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

View File

@ -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;
} }

View File

@ -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;

View File

@ -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;

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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;
} }