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

Fixed bug CORE-4444 : Engine could hung and block all attachments in out of disk space condition during physical backup

Improvement CORE-4445 : Extend main database file faster when physical backup state changed from stalled to merge
This commit is contained in:
hvlad 2014-05-29 07:54:15 +00:00
parent 97ff4dee5b
commit 9612a8600b
4 changed files with 57 additions and 7 deletions

View File

@ -188,7 +188,7 @@ bool GlobalRWLock::lockWrite(thread_db* tdbb, SSHORT wait)
}
}
void GlobalRWLock::unlockWrite(thread_db* tdbb)
void GlobalRWLock::unlockWrite(thread_db* tdbb, const bool release)
{
SET_TDBB(tdbb);
@ -201,13 +201,12 @@ void GlobalRWLock::unlockWrite(thread_db* tdbb)
currentWriter = false;
if (!lockCaching)
if (!lockCaching || release)
LCK_release(tdbb, cachedLock);
else if (blocking)
{
LCK_downgrade(tdbb, cachedLock);
blocking = false;
}
blocking = false;
if (cachedLock->lck_physical < LCK_read)
invalidate(tdbb);

View File

@ -65,7 +65,7 @@ public:
// This function returns false if it cannot take the lock
bool lockWrite(thread_db* tdbb, SSHORT wait);
void unlockWrite(thread_db* tdbb);
void unlockWrite(thread_db* tdbb, const bool release = false);
bool lockRead(thread_db* tdbb, SSHORT wait, const bool queueJump = false);
void unlockRead(thread_db* tdbb);
bool tryReleaseLock(thread_db* tdbb);

View File

@ -360,6 +360,46 @@ ULONG BackupManager::getPageCount()
}
bool BackupManager::extendDatabase(thread_db* tdbb)
{
ULONG maxPage = 0;
{
LocalAllocReadGuard localAllocGuard(this);
AllocItemTree::Accessor all(alloc_table);
if (all.getFirst()) {
do
{
const ULONG pg = all.current().db_page;
if (maxPage < pg)
maxPage = pg;
} while (all.getNext());
}
}
PageSpace *pgSpace = database->dbb_page_manager.findPageSpace(DB_PAGE_SPACE);
ULONG maxAllocPage = pgSpace->maxAlloc(database->dbb_page_size);
if (maxAllocPage >= maxPage)
return true;
if (!pgSpace->extend(tdbb, maxPage, true))
return false;
maxAllocPage = pgSpace->maxAlloc(database->dbb_page_size);
while (maxAllocPage < maxPage)
{
const USHORT ret = PIO_init_data(database, pgSpace->file, tdbb->tdbb_status_vector,
maxAllocPage, 256);
if (ret != 256)
return false;
maxAllocPage += ret;
}
return true;
}
// Merge difference file to main files (if needed) and unlink() difference
// file then. If merge is already in progress method silently returns and
// does nothing (so it can be used for recovery on database startup).
@ -398,6 +438,9 @@ void BackupManager::endBackup(thread_db* tdbb, bool recover)
endLock.unlockWrite(tdbb);
return;
}
if (backup_state == nbak_state_stalled && !extendDatabase(tdbb))
status_exception::raise(tdbb->tdbb_status_vector);
}
// Here backup state can be changed. Need to check it again after lock
@ -410,6 +453,13 @@ void BackupManager::endBackup(thread_db* tdbb, bool recover)
endLock.unlockWrite(tdbb);
return;
}
if (!extendDatabase(tdbb))
{
stateGuard.setSuccess();
status_exception::raise(tdbb->tdbb_status_vector);
}
header = (Ods::header_page*) window.win_buffer;
NBAK_TRACE(("difference file %s, current backup state is %d", diff_name.c_str(), backup_state));

View File

@ -365,7 +365,7 @@ public:
void unlockStateWrite(thread_db* tdbb)
{
tdbb->tdbb_flags &= ~TDBB_backup_write_locked;
stateLock->unlockWrite(tdbb);
stateLock->unlockWrite(tdbb, backup_state == nbak_state_unknown);
}
bool lockStateRead(thread_db* tdbb, SSHORT wait)
@ -464,6 +464,7 @@ private:
ULONG findPageIndex(thread_db* tdbb, ULONG db_page);
void generateFilename();
bool extendDatabase(thread_db* tdbb);
void lockAllocWrite(thread_db* tdbb)
{