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

Refactored cache shutdown. This should also fix CORE-4568: Server may crash while disconnecting from the database under load.

This commit is contained in:
dimitr 2014-10-04 20:10:14 +00:00
parent 57d611b79a
commit 7ad1fa43a3
4 changed files with 89 additions and 118 deletions

View File

@ -957,79 +957,15 @@ void CCH_fini(thread_db* tdbb)
*
**************************************/
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
BufferControl* bcb = dbb->dbb_bcb;
Database* const dbb = tdbb->getDatabase();
BufferControl* const bcb = dbb->dbb_bcb;
if (!bcb)
return;
bool flush_error = false;
bcb_repeat* tail = bcb->bcb_rpt;
const bcb_repeat* const end = tail + bcb->bcb_count;
// CVC: Patching a conversion error FB1->FB2 with crude logic
for (int i = 0; i < 2; ++i)
{
try {
// If we've been initialized, either flush buffers
// or release locks, depending on where we've been
// bug-checked; as a defensive programming measure,
// make sure that the buffers were actually allocated.
bcb_repeat* tail;
if ((tail = bcb->bcb_rpt) && (tail->bcb_bdb))
{
if (dbb->dbb_flags & DBB_bugcheck || flush_error)
{
for (const bcb_repeat* const end = bcb->bcb_rpt + bcb->bcb_count; tail < end; tail++)
{
BufferDesc* bdb = tail->bcb_bdb;
PAGE_LOCK_RELEASE(tdbb, bcb, bdb->bdb_lock);
}
}
else
CCH_flush(tdbb, FLUSH_FINI, 0);
}
#ifdef CACHE_READER
// Shutdown the dedicated cache reader for this database.
if ((bcb = dbb->dbb_bcb) && (bcb->bcb_flags & BCB_cache_reader))
{
bcb->bcb_flags &= ~BCB_cache_reader;
dbb->dbb_reader_sem.release();
{ // scope
Database::Checkout dcoHolder(dbb, FB_FUNCTION);
dbb->dbb_reader_fini.enter();
}
}
#endif
// Wait for cache writer startup to complete.
while (bcb->bcb_flags & BCB_writer_start)
{
Thread::yield();
}
// Shutdown the dedicated cache writer for this database.
if (bcb->bcb_flags & BCB_cache_writer)
{
bcb->bcb_flags &= ~BCB_cache_writer;
bcb->bcb_writer_sem.release(); // Wake up running thread
bcb->bcb_writer_fini.enter();
}
// close the database file and all associated shadow files
dbb->dbb_page_manager.closeAll();
SDW_close();
tail = bcb->bcb_rpt;
if (tail)
{
const bcb_repeat* const end = bcb->bcb_rpt + bcb->bcb_count;
for (; tail < end; tail++)
{
if (tail->bcb_bdb)
@ -1038,29 +974,14 @@ void CCH_fini(thread_db* tdbb)
tail->bcb_bdb = NULL;
}
}
}
delete[] bcb->bcb_rpt;
bcb->bcb_rpt = NULL; // Just in case we exit with failure
bcb->bcb_rpt = NULL;
bcb->bcb_count = 0;
while (bcb->bcb_memory.hasData())
bcb->bcb_bufferpool->deallocate(bcb->bcb_memory.pop());
} // try
catch (const Firebird::Exception& ex)
{
ex.stuff_exception(tdbb->tdbb_status_vector);
if (!flush_error)
flush_error = true;
else
ERR_punt();
}
if (!flush_error)
break; // wasn't set in the catch => no failure, just exit
} // for
BufferControl::destroy(bcb);
dbb->dbb_bcb = NULL;
}
@ -2045,11 +1966,11 @@ bool CCH_rollover_to_shadow(thread_db* tdbb, Database* dbb, jrd_file* file, cons
}
void CCH_shutdown_database(Database* dbb)
void CCH_shutdown(thread_db* tdbb)
{
/**************************************
*
* C C H _ s h u t d o w n _ d a t a b a s e
* C C H _ s h u t d o w n
*
**************************************
*
@ -2057,28 +1978,75 @@ void CCH_shutdown_database(Database* dbb)
* Shutdown database physical page locks.
*
**************************************/
bcb_repeat* tail;
BufferControl* bcb = dbb->dbb_bcb;
SyncLockGuard bcbSync(&bcb->bcb_syncObject, SYNC_EXCLUSIVE, "CCH_shutdown_database");
Database* const dbb = tdbb->getDatabase();
BufferControl* const bcb = dbb->dbb_bcb;
if (bcb && (tail = bcb->bcb_rpt) && (tail->bcb_bdb))
if (!bcb)
return;
SyncLockGuard bcbSync(&bcb->bcb_syncObject, SYNC_EXCLUSIVE, "CCH_shutdown");
// Flush and release page buffers
bcb_repeat* tail = bcb->bcb_rpt;
const bcb_repeat* const end = tail + bcb->bcb_count;
if (tail && tail->bcb_bdb)
{
thread_db* tdbb = JRD_get_thread_data();
for (const bcb_repeat* const end = tail + bcb->bcb_count; tail < end; tail++)
try
{
if (dbb->dbb_flags & DBB_bugcheck)
LongJump::raise();
CCH_flush(tdbb, FLUSH_FINI, 0);
}
catch (const Exception&)
{
for (; tail < end; tail++)
{
BufferDesc* const bdb = tail->bcb_bdb;
if (dbb->dbb_flags & DBB_bugcheck)
{
BufferDesc* bdb = tail->bcb_bdb;
bdb->bdb_flags &= ~BDB_db_dirty;
clear_dirty_flag(tdbb, bdb);
}
PAGE_LOCK_RELEASE(tdbb, bcb, bdb->bdb_lock);
}
}
///if (!(bcb->bcb_flags & BCB_exclusive))
{
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
PIO_close(pageSpace->file);
SDW_close();
}
#ifdef CACHE_READER
// Shutdown the dedicated cache reader for this database
if (bcb->bcb_flags & BCB_cache_reader)
{
bcb->bcb_flags &= ~BCB_cache_reader;
dbb->dbb_reader_sem.release();
dbb->dbb_reader_fini.enter();
}
#endif
// Wait for cache writer startup to complete
while (bcb->bcb_flags & BCB_writer_start)
Thread::yield();
// Shutdown the dedicated cache writer for this database
if (bcb->bcb_flags & BCB_cache_writer)
{
bcb->bcb_flags &= ~BCB_cache_writer;
bcb->bcb_writer_sem.release(); // Wake up running thread
bcb->bcb_writer_fini.enter();
}
// close the database file and all associated shadow files
dbb->dbb_page_manager.closeAll();
SDW_close();
}
void CCH_unwind(thread_db* tdbb, const bool punt)

View File

@ -40,8 +40,6 @@ enum LockState {
lsError
};
void CCH_shutdown_database(Jrd::Database*);
int CCH_down_grade_dbb(void*);
bool CCH_exclusive(Jrd::thread_db*, USHORT, SSHORT, Firebird::Sync*);
bool CCH_exclusive_attachment(Jrd::thread_db*, USHORT, SSHORT, Firebird::Sync*);
@ -71,6 +69,7 @@ bool CCH_prefetch_pages(Jrd::thread_db*);
void CCH_release(Jrd::thread_db*, Jrd::win*, const bool);
void CCH_release_exclusive(Jrd::thread_db*);
bool CCH_rollover_to_shadow(Jrd::thread_db* tdbb, Jrd::Database* dbb, Jrd::jrd_file*, const bool);
void CCH_shutdown(Jrd::thread_db*);
void CCH_unwind(Jrd::thread_db*, const bool);
bool CCH_validate(Jrd::win*);
void CCH_flush_ast(Jrd::thread_db*);

View File

@ -69,10 +69,11 @@ void ERR_bugcheck(int number, const TEXT* file, int line)
* Things seem to be going poorly today.
*
**************************************/
Database* dbb = GET_DBB();
dbb->dbb_flags |= DBB_bugcheck;
thread_db* const tdbb = JRD_get_thread_data();
Database* const dbb = tdbb->getDatabase();
CCH_shutdown_database(dbb);
dbb->dbb_flags |= DBB_bugcheck;
CCH_shutdown(tdbb);
internal_error(isc_bug_check, number, file, line);
}
@ -90,11 +91,12 @@ void ERR_bugcheck_msg(const TEXT* msg)
* Things seem to be going poorly today.
*
**************************************/
Database* dbb = GET_DBB();
thread_db* const tdbb = JRD_get_thread_data();
Database* const dbb = tdbb->getDatabase();
dbb->dbb_flags |= DBB_bugcheck;
DEBUG;
CCH_shutdown_database(dbb);
CCH_shutdown(tdbb);
ERR_post(Arg::Gds(isc_bug_check) << Arg::Str(msg));
}

View File

@ -6515,7 +6515,7 @@ bool JRD_shutdown_database(Database* dbb, const unsigned flags)
if (dbb->dbb_crypto_manager)
dbb->dbb_crypto_manager->terminateCryptThread(tdbb);
CCH_fini(tdbb);
CCH_shutdown(tdbb);
if (dbb->dbb_backup_manager)
dbb->dbb_backup_manager->shutdown(tdbb);
@ -6539,6 +6539,8 @@ bool JRD_shutdown_database(Database* dbb, const unsigned flags)
LCK_fini(tdbb, LCK_OWNER_database);
CCH_fini(tdbb);
{ // scope
MutexLockGuard listGuard2(databases_mutex, FB_FUNCTION);