8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 13:23:02 +01:00

Fixed possible server crash + minor refactoring.

This commit is contained in:
dimitr 2013-11-17 14:24:17 +00:00
parent 73dc69f655
commit 8033131d18
3 changed files with 82 additions and 53 deletions

View File

@ -384,6 +384,66 @@ int DatabaseSnapshot::blockingAst(void* ast_object)
}
void DatabaseSnapshot::initialize(thread_db* tdbb)
{
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
fb_assert(dbb);
if (!dbb->dbb_monitor_lock)
{
dbb->dbb_monitor_lock = FB_NEW_RPT(*dbb->dbb_permanent, 0)
Lock(tdbb, 0, LCK_monitor, dbb, DatabaseSnapshot::blockingAst);
LCK_lock(tdbb, dbb->dbb_monitor_lock, LCK_SR, LCK_WAIT);
}
}
void DatabaseSnapshot::shutdown(thread_db* tdbb)
{
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
fb_assert(dbb);
if (dbb->dbb_monitor_lock)
LCK_release(tdbb, dbb->dbb_monitor_lock);
}
void DatabaseSnapshot::activate(thread_db* tdbb)
{
SET_TDBB(tdbb);
Database* const dbb = tdbb->getDatabase();
fb_assert(dbb);
Jrd::Attachment* const attachment = tdbb->getAttachment();
fb_assert(attachment);
if (dbb->dbb_ast_flags & DBB_monitor_off)
{
// Enable signal handler for the monitoring stuff
Attachment::CheckoutSyncGuard monGuard(attachment, dbb->dbb_mon_sync,
SYNC_EXCLUSIVE, FB_FUNCTION);
if (dbb->dbb_ast_flags & DBB_monitor_off)
{
dbb->dbb_ast_flags &= ~DBB_monitor_off;
LCK_lock(tdbb, dbb->dbb_monitor_lock, LCK_SR, LCK_WAIT);
fb_assert(!(dbb->dbb_ast_flags & DBB_monitor_off));
// While waiting for return from LCK_lock call above, the blocking AST (see
// DatabaseSnapshot::blockingAst) was called and set DBB_monitor_off flag
// again. But it do not released lock as lck_id was unknown at that moment.
// Do it now to not block another process waiting for a monitoring lock.
if (dbb->dbb_ast_flags & DBB_monitor_off)
LCK_release(tdbb, dbb->dbb_monitor_lock);
}
}
}
DatabaseSnapshot::DatabaseSnapshot(thread_db* tdbb, MemoryPool& pool)
: DataDump(pool), snapshot(pool)
{

View File

@ -337,6 +337,9 @@ public:
static DatabaseSnapshot* create(thread_db*);
static int blockingAst(void*);
static void initialize(thread_db*);
static void shutdown(thread_db*);
static void activate(thread_db*);
static bool getRecord(thread_db* tdbb, jrd_rel* relation, FB_UINT64 position, Record* record);
protected:

View File

@ -932,10 +932,9 @@ private:
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 enable_monitoring(thread_db* tdbb);
static void find_intl_charset(thread_db*, Jrd::Attachment*, const DatabaseOptions*);
static jrd_tra* find_transaction(thread_db*);
static void init_database_locks(thread_db*);
static void init_database_lock(thread_db*);
static void run_commit_triggers(thread_db* tdbb, jrd_tra* transaction);
static jrd_req* verify_request_synchronization(JrdStatement* statement, USHORT level);
static void purge_transactions(thread_db*, Jrd::Attachment*, const bool);
@ -1390,11 +1389,11 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
// Initialize the lock manager
dbb->dbb_lock_mgr = LockManager::create(dbb->getUniqueFileId(), dbb->dbb_config);
// Initialize locks
LCK_init(tdbb, LCK_OWNER_database);
LCK_init(tdbb, LCK_OWNER_attachment);
init_database_lock(tdbb);
// Initialize locks
init_database_locks(tdbb);
jAtt->manualAsyncUnlock(attachment->att_flags);
INI_init(tdbb);
@ -1428,6 +1427,9 @@ JAttachment* FB_CARG JProvider::attachDatabase(IStatus* user_status, const char*
dbb->dbb_crypto_manager = FB_NEW(*dbb->dbb_permanent) CryptoManager(tdbb);
dbb->dbb_crypto_manager->attach(tdbb, attachment);
// initialize monitoring
DatabaseSnapshot::initialize(tdbb);
// initialize shadowing as soon as the database is ready for it
// but before any real work is done
SDW_init(tdbb, options.dpb_activate_shadow, options.dpb_delete_shadow);
@ -2555,11 +2557,11 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
// Initialize the lock manager
dbb->dbb_lock_mgr = LockManager::create(dbb->getUniqueFileId(), dbb->dbb_config);
// Initialize locks
LCK_init(tdbb, LCK_OWNER_database);
LCK_init(tdbb, LCK_OWNER_attachment);
init_database_lock(tdbb);
// Initialize locks
init_database_locks(tdbb);
jAtt->manualAsyncUnlock(attachment->att_flags);
INI_init(tdbb);
@ -2598,6 +2600,9 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
dbb->dbb_crypto_manager = FB_NEW(*dbb->dbb_permanent) CryptoManager(tdbb);
// initialize monitoring
DatabaseSnapshot::initialize(tdbb);
if (options.dpb_set_page_buffers)
PAG_set_page_buffers(tdbb, options.dpb_page_buffers);
@ -2637,7 +2642,7 @@ JAttachment* FB_CARG JProvider::createDatabase(IStatus* user_status, const char*
if (options.dpb_set_db_readonly)
{
if (!CCH_exclusive (tdbb, LCK_EX, WAIT_PERIOD, &dbbGuard))
if (!CCH_exclusive(tdbb, LCK_EX, WAIT_PERIOD, &dbbGuard))
{
ERR_post(Arg::Gds(isc_lock_timeout) <<
Arg::Gds(isc_obj_in_use) << Arg::Str(org_filename));
@ -5201,7 +5206,7 @@ bool JRD_reschedule(thread_db* tdbb, SLONG quantum, bool punt)
}
}
enable_monitoring(tdbb);
DatabaseSnapshot::activate(tdbb);
tdbb->tdbb_quantum = (tdbb->tdbb_quantum <= 0) ?
(quantum ? quantum : QUANTUM) : tdbb->tdbb_quantum;
@ -5299,7 +5304,7 @@ static void check_database(thread_db* tdbb, bool async)
status_exception::raise(Arg::Gds(isc_cancelled));
}
enable_monitoring(tdbb);
DatabaseSnapshot::activate(tdbb);
}
@ -5366,36 +5371,6 @@ static bool drop_files(const jrd_file* file)
}
static void enable_monitoring(thread_db* tdbb)
{
Database* const dbb = tdbb->getDatabase();
Jrd::Attachment* const attachment = tdbb->getAttachment();
// Enable signal handler for the monitoring stuff
if (dbb->dbb_ast_flags & DBB_monitor_off)
{
Attachment::CheckoutSyncGuard monGuard(attachment, dbb->dbb_mon_sync,
SYNC_EXCLUSIVE, FB_FUNCTION);
if (dbb->dbb_ast_flags & DBB_monitor_off)
{
dbb->dbb_ast_flags &= ~DBB_monitor_off;
LCK_lock(tdbb, dbb->dbb_monitor_lock, LCK_SR, LCK_WAIT);
fb_assert(!(dbb->dbb_ast_flags & DBB_monitor_off));
// While waiting for return from LCK_lock call above, the blocking AST (see
// DatabaseSnapshot::blockingAst) was called and set DBB_monitor_off flag
// again. But it do not released lock as lck_id was unknown at that moment.
// Do it now to not block another process waiting for a monitoring lock.
if (dbb->dbb_ast_flags & DBB_monitor_off)
LCK_release(tdbb, dbb->dbb_monitor_lock);
}
}
}
static jrd_tra* find_transaction(thread_db* tdbb)
{
/**************************************
@ -6096,16 +6071,16 @@ static JAttachment* create_attachment(const PathName& alias_name,
}
static void init_database_locks(thread_db* tdbb)
static void init_database_lock(thread_db* tdbb)
{
/**************************************
*
* i n i t _ d a t a b a s e _ l o c k s
* i n i t _ d a t a b a s e _ l o c k
*
**************************************
*
* Functional description
* Initialize database locks.
* Initialize the main database lock.
*
**************************************/
SET_TDBB(tdbb);
@ -6146,14 +6121,6 @@ static void init_database_locks(thread_db* tdbb)
}
}
}
// Lock shared by all dbb owners, used to signal other processes
// to dump their monitoring data and synchronize operations
lock = FB_NEW_RPT(*dbb->dbb_permanent, 0)
Lock(tdbb, 0, LCK_monitor, dbb, DatabaseSnapshot::blockingAst);
dbb->dbb_monitor_lock = lock;
LCK_lock(tdbb, lock, LCK_SR, LCK_WAIT);
}
@ -6475,6 +6442,8 @@ bool JRD_shutdown_database(Database* dbb, const unsigned flags)
TRA_header_write(tdbb, dbb, 0); // Update transaction info on header page.
#endif
DatabaseSnapshot::shutdown(tdbb);
VIO_fini(tdbb);
if (dbb->dbb_crypto_manager)
@ -6488,9 +6457,6 @@ bool JRD_shutdown_database(Database* dbb, const unsigned flags)
if (dbb->dbb_crypto_manager)
dbb->dbb_crypto_manager->shutdown(tdbb);
if (dbb->dbb_monitor_lock)
LCK_release(tdbb, dbb->dbb_monitor_lock);
if (dbb->dbb_shadow_lock)
LCK_release(tdbb, dbb->dbb_shadow_lock);