8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 22:43:03 +01:00

Front ported my yesterday's commits to trunk.

This commit is contained in:
dimitr 2012-12-23 07:10:56 +00:00
parent 873787b0d0
commit e29b50f980
9 changed files with 106 additions and 196 deletions

View File

@ -353,11 +353,25 @@ void Jrd::Attachment::storeBinaryBlob(thread_db* tdbb, jrd_tra* transaction,
}
void Jrd::Attachment::cancelExternalConnection(thread_db* tdbb)
void Jrd::Attachment::signalCancel(thread_db* tdbb)
{
if (att_ext_connection) {
att_flags |= ATT_cancel_raise;
if (att_ext_connection)
att_ext_connection->cancelExecution(tdbb);
}
LCK_cancel_wait(this);
}
void Jrd::Attachment::signalShutdown(thread_db* tdbb)
{
att_flags |= ATT_shutdown;
if (att_ext_connection)
att_ext_connection->cancelExecution(tdbb);
LCK_cancel_wait(this);
}
@ -531,6 +545,9 @@ void Jrd::Attachment::releaseLocks(thread_db* tdbb)
if (att_id_lock)
LCK_release(tdbb, att_id_lock);
if (att_cancel_lock)
LCK_release(tdbb, att_cancel_lock);
if (att_temp_pg_lock)
LCK_release(tdbb, att_temp_pg_lock);

View File

@ -225,6 +225,7 @@ public:
Firebird::SortedArray<jrd_req*> att_requests; // Requests belonging to attachment
Lock* att_id_lock; // Attachment lock (if any)
SLONG att_attachment_id; // Attachment ID
Lock* att_cancel_lock; // Lock to cancel the active request
const ULONG att_lock_owner_id; // ID for the lock manager
SLONG att_lock_owner_handle; // Handle for the lock manager
ULONG att_backup_state_counter; // Counter of backup state locks for attachment
@ -326,7 +327,9 @@ public:
void storeBinaryBlob(thread_db* tdbb, jrd_tra* transaction, bid* blobId,
const Firebird::ByteChunk& chunk);
void cancelExternalConnection(thread_db* tdbb);
void signalCancel(thread_db* tdbb);
void signalShutdown(thread_db* tdbb);
void detachLocksFromAttachment();
bool backupStateWriteLock(thread_db* tdbb, SSHORT wait);
@ -334,8 +337,6 @@ public:
bool backupStateReadLock(thread_db* tdbb, SSHORT wait);
void backupStateReadUnLock(thread_db* tdbb);
bool cancelRaise();
private:
Attachment(MemoryPool* pool, Database* dbb);
~Attachment();
@ -360,8 +361,6 @@ const ULONG ATT_gfix_attachment = 0x01000L; // Indicate a GFIX attachment
const ULONG ATT_gstat_attachment = 0x02000L; // Indicate a GSTAT attachment
const ULONG ATT_no_db_triggers = 0x04000L; // Don't execute database triggers
const ULONG ATT_manual_lock = 0x08000L; // Was locked manually
const ULONG ATT_terminate = 0x10000L; // Terminate currently running operation
const ULONG ATT_protected = 0x20000L; // Ignore termination flag when disconnecting
const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc);
@ -381,14 +380,6 @@ inline void Attachment::setSysTransaction(jrd_tra* trans)
att_sys_transaction = trans;
}
inline bool Attachment::cancelRaise()
{
return att_flags & ATT_protected ? false :
att_flags & ATT_terminate ? true :
att_flags & ATT_cancel_disable ? false :
att_flags & ATT_cancel_raise ? true : false;
}
} // namespace Jrd
#endif // JRD_ATTACHMENT_H

View File

@ -70,8 +70,8 @@ void VirtualTable::erase(thread_db* tdbb, record_param* rpb)
}
else if (relation->rel_id == rel_mon_statements)
{
// Get transaction id
if (!EVL_field(relation, rpb->rpb_record, f_mon_stmt_tra_id, &desc))
// Get attachment id
if (!EVL_field(relation, rpb->rpb_record, f_mon_stmt_att_id, &desc))
return;
lock_type = LCK_cancel;
}

View File

@ -1146,7 +1146,7 @@ static void execute_looper(thread_db* tdbb,
// Ensure the cancellation lock can be triggered
Lock* const lock = transaction->tra_cancel_lock;
Lock* const lock = attachment->att_cancel_lock;
if (lock && lock->lck_logical == LCK_none)
LCK_lock(tdbb, lock, LCK_SR, LCK_WAIT);

View File

@ -796,12 +796,7 @@ private:
UserId m_id;
};
namespace {
const unsigned CHECK_ASYNC = 1;
const unsigned CHECK_DISCONNECT = 2;
}
static void check_database(thread_db* tdbb, unsigned flags = 0);
static void check_transaction(thread_db*, jrd_tra*);
static void check_database(thread_db* tdbb, bool async = false);
static void commit(thread_db*, jrd_tra*, const bool);
static bool drop_files(const jrd_file*);
static void find_intl_charset(thread_db*, Jrd::Attachment*, const DatabaseOptions*);
@ -832,7 +827,6 @@ static bool unlink_database(Database*);
static void shutdown_database(Database*, const bool);
static void strip_quotes(string&);
static void purge_attachment(thread_db*, Jrd::Attachment*, const bool);
static void terminate_attachment(thread_db* tdbb, Attachment* attachment);
static void getUserInfo(UserId&, const DatabaseOptions&, const RefPtr<Config>*);
static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM);
@ -2617,7 +2611,6 @@ void JAttachment::freeEngineData(IStatus* user_status)
try
{
EngineContextHolder tdbb(user_status, this, FB_FUNCTION, AttachmentHolder::ATT_LOCK_ASYNC);
check_database(tdbb, CHECK_DISCONNECT);
try
{
@ -2625,7 +2618,7 @@ void JAttachment::freeEngineData(IStatus* user_status)
if (attachment->att_in_use)
status_exception::raise(Arg::Gds(isc_attachment_in_use));
terminate_attachment(tdbb, attachment);
attachment->signalShutdown(tdbb);
purge_attachment(tdbb, attachment, false);
att = NULL;
@ -2719,7 +2712,7 @@ void JAttachment::dropDatabase(IStatus* user_status)
// Forced release of all transactions
purge_transactions(tdbb, attachment, true, attachment->att_flags);
attachment->att_flags |= ATT_cancel_disable;
tdbb->tdbb_flags |= TDBB_detaching;
// Here we have database locked in exclusive mode.
// Just mark the header page with an 0 ods version so that no other
@ -4683,7 +4676,7 @@ void JAttachment::ping(IStatus* user_status)
try
{
EngineContextHolder tdbb(user_status, this, FB_FUNCTION);
check_database(tdbb);
check_database(tdbb, true);
}
catch (const Exception& ex)
{
@ -4869,7 +4862,7 @@ void jrd_vtof(const char* string, char* field, SSHORT length)
}
static void check_database(thread_db* tdbb, unsigned flags)
static void check_database(thread_db* tdbb, bool async)
{
/**************************************
*
@ -4883,45 +4876,50 @@ static void check_database(thread_db* tdbb, unsigned flags)
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
Jrd::Attachment* attachment = tdbb->getAttachment();
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const attachment = tdbb->getAttachment();
if (!(flags & CHECK_DISCONNECT))
// Test for persistent errors
if (dbb->dbb_flags & DBB_bugcheck)
{
if (dbb->dbb_flags & DBB_bugcheck)
{
static const char string[] = "can't continue after bugcheck";
status_exception::raise(Arg::Gds(isc_bug_check) << Arg::Str(string));
}
static const char string[] = "can't continue after bugcheck";
status_exception::raise(Arg::Gds(isc_bug_check) << Arg::Str(string));
}
if ((attachment->att_flags & ATT_shutdown) ||
((dbb->dbb_ast_flags & DBB_shutdown) &&
((dbb->dbb_ast_flags & DBB_shutdown_full) || !attachment->locksmith())))
if ((attachment->att_flags & ATT_shutdown) ||
((dbb->dbb_ast_flags & DBB_shutdown) &&
((dbb->dbb_ast_flags & DBB_shutdown_full) || !attachment->locksmith())))
{
if (dbb->dbb_ast_flags & DBB_shutdown)
{
if (dbb->dbb_ast_flags & DBB_shutdown)
{
const PathName& filename = attachment->att_filename;
status_exception::raise(Arg::Gds(isc_shutdown) << Arg::Str(filename));
}
else
{
status_exception::raise(Arg::Gds(isc_att_shutdown));
}
const PathName& filename = attachment->att_filename;
status_exception::raise(Arg::Gds(isc_shutdown) << Arg::Str(filename));
}
else
{
status_exception::raise(Arg::Gds(isc_att_shutdown));
}
}
// do not use cancelRaise() here - we do not care about internal flags
if ((!(flags & CHECK_ASYNC)) && (attachment->att_flags & ATT_cancel_raise)
&& !(attachment->att_flags & ATT_cancel_disable))
{
attachment->att_flags &= ~ATT_cancel_raise;
status_exception::raise(Arg::Gds(isc_cancelled));
}
// No further checks for the async calls
if (async)
return;
// Test for temporary errors
if ((attachment->att_flags & ATT_cancel_raise)
&& !(attachment->att_flags & ATT_cancel_disable))
{
attachment->att_flags &= ~ATT_cancel_raise;
status_exception::raise(Arg::Gds(isc_cancelled));
}
// Enable signal handler for the monitoring stuff.
// See also comments in JRD_reshedule.
if (dbb->dbb_ast_flags & DBB_monitor_off && !(flags & CHECK_ASYNC))
if (dbb->dbb_ast_flags & DBB_monitor_off)
{
SyncLockGuard monGuard(&dbb->dbb_mon_sync, SYNC_EXCLUSIVE, "check_database");
@ -4937,29 +4935,6 @@ static void check_database(thread_db* tdbb, unsigned flags)
}
static void check_transaction(thread_db* tdbb, jrd_tra* transaction)
{
/**************************************
*
* c h e c k _ t r a n s a c t i o n
*
**************************************
*
* Functional description
* Check transaction for not being interrupted
* in the meantime.
*
**************************************/
SET_TDBB(tdbb);
if (transaction && (transaction->tra_flags & TRA_cancel_request))
{
transaction->tra_flags &= ~TRA_cancel_request;
status_exception::raise(Arg::Gds(isc_cancelled));
}
}
static void commit(thread_db* tdbb, jrd_tra* transaction, const bool retaining_flag)
{
/**************************************
@ -6291,8 +6266,6 @@ static void purge_attachment(thread_db* tdbb, Jrd::Attachment* attachment, const
THD_sleep(1);
}
attachment->att_flags |= ATT_protected;
Database* const dbb = attachment->att_database;
tdbb->tdbb_flags |= TDBB_detaching;
@ -6679,25 +6652,6 @@ static void unwindAttach(thread_db* tdbb, const Exception& ex, Firebird::IStatus
}
static void terminate_attachment(thread_db* tdbb, Attachment* attachment)
{
/********************************************
*
* t e r m i n a t e _ a t t a c h m e n t
*
********************************************
*
* Functional description
* Set terminate flag on attachment and
* call required subsytems to help wakeup it.
*
**************************************/
attachment->att_flags |= ATT_terminate;
attachment->cancelExternalConnection(tdbb);
LCK_cancel_wait(attachment);
}
namespace
{
@ -6739,7 +6693,7 @@ namespace
tdbb->setAttachment(attachment);
tdbb->setDatabase(attachment->att_database);
terminate_attachment(tdbb, attachment);
attachment->signalShutdown(tdbb);
}
}
@ -6945,7 +6899,8 @@ bool thread_db::checkCancelState(bool punt)
// when executing in the context of an internal request or
// the system transaction.
if (attachment->cancelRaise())
if ((attachment->att_flags & ATT_cancel_raise) &&
!(attachment->att_flags & ATT_cancel_disable))
{
if ((!request ||
!(request->getStatement()->flags &
@ -6959,24 +6914,9 @@ bool thread_db::checkCancelState(bool punt)
attachment->att_flags &= ~ATT_cancel_raise;
status_exception::raise(Arg::Gds(isc_cancelled));
}
/* fprintf(stderr, "req %p flags %x tra %p flags %x\n", request, request ? (request->getStatement()->flags &
(JrdStatement::FLAG_INTERNAL | JrdStatement::FLAG_SYS_TRIGGER)) : 0,
transaction, transaction ? (transaction->tra_flags & TRA_system) : 0);
abort(); */
}
}
// Handle request cancellation
if (transaction && (transaction->tra_flags & TRA_cancel_request))
{
if (!punt)
return true;
transaction->tra_flags &= ~TRA_cancel_request;
status_exception::raise(Arg::Gds(isc_cancelled));
}
// Check the thread state for already posted system errors. If any still persists,
// then someone tries to ignore our attempts to interrupt him. Let's insist.
@ -7057,8 +6997,6 @@ void JRD_receive(thread_db* tdbb, jrd_req* request, USHORT msg_type, ULONG msg_l
* Get a record from the host program.
*
**************************************/
check_transaction(tdbb, request->req_transaction);
EXE_receive(tdbb, request, msg_type, msg_length, msg, true);
check_autocommit(request, tdbb);
@ -7083,8 +7021,6 @@ void JRD_send(thread_db* tdbb, jrd_req* request, USHORT msg_type, ULONG msg_leng
* Get a record from the host program.
*
**************************************/
check_transaction(tdbb, request->req_transaction);
EXE_send(tdbb, request, msg_type, msg_length, msg);
check_autocommit(request, tdbb);
@ -7109,8 +7045,6 @@ void JRD_start(Jrd::thread_db* tdbb, jrd_req* request, jrd_tra* transaction)
* Get a record from the host program.
*
**************************************/
check_transaction(tdbb, transaction);
EXE_unwind(tdbb, request);
EXE_start(tdbb, request, transaction);
@ -7201,8 +7135,6 @@ void JRD_start_and_send(thread_db* tdbb, jrd_req* request, jrd_tra* transaction,
* Get a record from the host program.
*
**************************************/
check_transaction(tdbb, transaction);
EXE_unwind(tdbb, request);
EXE_start(tdbb, request, transaction);
EXE_send(tdbb, request, msg_type, msg_length, msg);
@ -7462,11 +7394,7 @@ void JRD_cancel_operation(thread_db* tdbb, Jrd::Attachment* attachment, int opti
case fb_cancel_raise:
if (!(attachment->att_flags & ATT_cancel_disable))
{
attachment->att_flags |= ATT_cancel_raise;
attachment->cancelExternalConnection(tdbb);
LCK_cancel_wait(attachment);
}
attachment->signalCancel(tdbb);
break;
default:

View File

@ -109,7 +109,8 @@ using namespace Firebird;
static void add_clump(thread_db* tdbb, USHORT type, USHORT len, const UCHAR* entry, ClumpOper mode);
static void attach_temp_pages(thread_db* tdbb, USHORT pageSpaceID);
static int blocking_ast_attachment(void*);
static int blocking_ast_shutdown_attachment(void*);
static int blocking_ast_cancel_attachment(void*);
static void find_clump_space(thread_db* tdbb, WIN*, pag**, USHORT, USHORT, const UCHAR*);
static bool find_type(thread_db* tdbb, WIN*, pag**, USHORT, USHORT, UCHAR**, const UCHAR**);
@ -764,12 +765,19 @@ SLONG PAG_attachment_id(thread_db* tdbb)
// Take out lock on attachment id
Lock* const lock = FB_NEW_RPT(*attachment->att_pool, sizeof(SLONG))
Lock(tdbb, sizeof(SLONG), LCK_attachment, attachment, blocking_ast_attachment);
Lock* lock = FB_NEW_RPT(*attachment->att_pool, sizeof(SLONG))
Lock(tdbb, sizeof(SLONG), LCK_attachment, attachment, blocking_ast_shutdown_attachment);
attachment->att_id_lock = lock;
lock->lck_key.lck_long = attachment->att_attachment_id;
LCK_lock(tdbb, lock, LCK_EX, LCK_WAIT);
// Allocate the cancellation lock
lock = FB_NEW_RPT(*attachment->att_pool, sizeof(SLONG))
Lock(tdbb, sizeof(SLONG), LCK_cancel, attachment, blocking_ast_cancel_attachment);
attachment->att_cancel_lock = lock;
lock->lck_key.lck_long = attachment->att_attachment_id;
return attachment->att_attachment_id;
}
@ -1696,7 +1704,7 @@ void PAG_sweep_interval(thread_db* tdbb, SLONG interval)
}
static int blocking_ast_attachment(void* ast_object)
static int blocking_ast_shutdown_attachment(void* ast_object)
{
Jrd::Attachment* const attachment = static_cast<Jrd::Attachment*>(ast_object);
@ -1706,9 +1714,7 @@ static int blocking_ast_attachment(void* ast_object)
AsyncContextHolder tdbb(dbb, FB_FUNCTION, attachment->att_id_lock);
attachment->att_flags |= ATT_shutdown;
attachment->cancelExternalConnection(tdbb);
LCK_cancel_wait(attachment);
attachment->signalShutdown(tdbb);
JRD_shutdown_attachments(dbb);
@ -1721,6 +1727,27 @@ static int blocking_ast_attachment(void* ast_object)
}
static int blocking_ast_cancel_attachment(void* ast_object)
{
Jrd::Attachment* const attachment = static_cast<Jrd::Attachment*>(ast_object);
try
{
Database* const dbb = attachment->att_database;
AsyncContextHolder tdbb(dbb, FB_FUNCTION, attachment->att_cancel_lock);
attachment->signalCancel(tdbb);
LCK_release(tdbb, attachment->att_cancel_lock);
}
catch (const Exception&)
{} // no-op
return 0;
}
static void find_clump_space(thread_db* tdbb,
WIN* window,
PAG* ppage,

View File

@ -516,11 +516,7 @@ static void shutdown(thread_db* tdbb, SSHORT flag)
for (Jrd::Attachment* attachment = dbb->dbb_attachments; attachment; attachment = attachment->att_next)
{
if (!(attachment->att_flags & ATT_shutdown_manager))
{
attachment->att_flags |= ATT_shutdown;
attachment->cancelExternalConnection(tdbb);
LCK_cancel_wait(attachment);
}
attachment->signalShutdown(tdbb);
}
JRD_shutdown_attachments(dbb);

View File

@ -84,7 +84,6 @@ using namespace Firebird;
typedef Firebird::GenericMap<Firebird::Pair<Firebird::NonPooled<USHORT, UCHAR> > > RelationLockTypeMap;
static int blocking_ast_transaction(void*);
#ifdef SUPERSERVER_V2
static TraNumber bump_transaction_id(thread_db*, WIN*);
#else
@ -1101,9 +1100,6 @@ void TRA_release_transaction(thread_db* tdbb, jrd_tra* transaction, Jrd::TraceTr
// Release the locks associated with the transaction
if (transaction->tra_cancel_lock)
LCK_release(tdbb, transaction->tra_cancel_lock);
vec<Lock*>* vector = transaction->tra_relation_locks;
if (vector)
{
@ -1824,42 +1820,6 @@ int TRA_wait(thread_db* tdbb, jrd_tra* trans, TraNumber number, jrd_tra::wait_t
}
static int blocking_ast_transaction(void* ast_object)
{
/**************************************
*
* b l o c k i n g _ a s t _ t r a n s a c t i o n
*
**************************************
*
* Functional description
* Mark the transaction to cancel its active requests.
*
**************************************/
jrd_tra* const transaction = static_cast<jrd_tra*>(ast_object);
try
{
Database* const dbb = transaction->tra_cancel_lock->lck_dbb;
AsyncContextHolder tdbb(dbb, FB_FUNCTION, transaction->tra_cancel_lock);
if (transaction->tra_cancel_lock)
LCK_release(tdbb, transaction->tra_cancel_lock);
transaction->tra_flags |= TRA_cancel_request;
Jrd::Attachment* const att = tdbb->getAttachment();
att->cancelExternalConnection(tdbb);
LCK_cancel_wait(att);
}
catch (const Firebird::Exception&)
{} // no-op
return 0;
}
#ifdef SUPERSERVER_V2
static TraNumber bump_transaction_id(thread_db* tdbb, WIN* window)
{
@ -3264,13 +3224,6 @@ static jrd_tra* transaction_start(thread_db* tdbb, jrd_tra* temp)
trans->tra_save_point->sav_flags |= SAV_trans_level;
}
// Allocate the cancellation lock
lock = FB_NEW_RPT(*trans->tra_pool, 0)
Lock(tdbb, sizeof(SLONG), LCK_cancel, trans, blocking_ast_transaction);
trans->tra_cancel_lock = lock;
lock->lck_key.lck_long = trans->tra_number;
// if the user asked us to restart all requests in this attachment,
// do so now using the new transaction

View File

@ -245,7 +245,6 @@ public:
BlobIndexTree* tra_blobs; // pointer to actual list of active blobs
ArrayField* tra_arrays; // Linked list of active arrays
Lock* tra_lock; // lock for transaction
Lock* tra_cancel_lock; // lock to cancel the active request
vec<Lock*>* tra_relation_locks; // locks for relations
UInt32Bitmap* tra_commit_sub_trans; // commited sub-transactions
Savepoint* tra_save_point; // list of savepoints
@ -360,9 +359,8 @@ const ULONG TRA_perform_autocommit = 0x1000L; // indicates autocommit is necessa
const ULONG TRA_rec_version = 0x2000L; // don't wait for uncommitted versions
const ULONG TRA_restart_requests = 0x4000L; // restart all requests in attachment
const ULONG TRA_no_auto_undo = 0x8000L; // don't start a savepoint in TRA_start
const ULONG TRA_cancel_request = 0x10000L; // cancel active request, if any
const ULONG TRA_precommitted = 0x20000L; // transaction committed at startup
const ULONG TRA_own_interface = 0x40000L; // tra_interface was created for internal needs
const ULONG TRA_precommitted = 0x10000L; // transaction committed at startup
const ULONG TRA_own_interface = 0x20000L; // tra_interface was created for internal needs
// flags derived from TPB, see also transaction_options() at tra.cpp
const ULONG TRA_OPTIONS_MASK = (TRA_degree3 | TRA_readonly | TRA_ignore_limbo | TRA_read_committed |