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

Restored some of the old logic. The change was experimental and it doesn't look safe to me anymore.

This commit is contained in:
dimitr 2007-02-06 07:45:46 +00:00
parent fa80ab814d
commit 8ac82bde83

View File

@ -537,10 +537,10 @@ void BackupManager::begin_backup(thread_db* tdbb)
{ {
NBAK_TRACE(("begin_backup")); NBAK_TRACE(("begin_backup"));
// Lock header page first to prevent possible deadlock
WIN window(HEADER_PAGE); WIN window(HEADER_PAGE);
Ods::header_page* header = NULL; Ods::header_page* header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
bool state_locked = false, database_locked = false; bool state_locked = false, header_locked = true, database_locked = false;
try { try {
#ifndef SUPERSERVER #ifndef SUPERSERVER
// Send AST's to flush other caches. While this lock is taken no pages may have // Send AST's to flush other caches. While this lock is taken no pages may have
@ -562,6 +562,7 @@ void BackupManager::begin_backup(thread_db* tdbb)
if (backup_state != nbak_state_normal) { if (backup_state != nbak_state_normal) {
NBAK_TRACE(("end backup - invalid state %d", backup_state)); NBAK_TRACE(("end backup - invalid state %d", backup_state));
unlock_state_write(tdbb); unlock_state_write(tdbb);
CCH_RELEASE(tdbb, &window);
return; return;
} }
// Create file // Create file
@ -601,8 +602,6 @@ void BackupManager::begin_backup(thread_db* tdbb)
GenerateGuid(&guid); GenerateGuid(&guid);
tdbb->tdbb_flags |= TDBB_set_backup_state; tdbb->tdbb_flags |= TDBB_set_backup_state;
// Set state in database header page. All changes are written to main database file yet. // Set state in database header page. All changes are written to main database file yet.
Ods::header_page* header =
(Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
CCH_MARK_MUST_WRITE(tdbb, &window); CCH_MARK_MUST_WRITE(tdbb, &window);
int newState = nbak_state_stalled; int newState = nbak_state_stalled;
header->hdr_flags = (header->hdr_flags & ~Ods::hdr_backup_mask) | newState; header->hdr_flags = (header->hdr_flags & ~Ods::hdr_backup_mask) | newState;
@ -613,10 +612,10 @@ void BackupManager::begin_backup(thread_db* tdbb)
PAG_replace_entry_first(header, Ods::HDR_backup_guid, sizeof(guid), PAG_replace_entry_first(header, Ods::HDR_backup_guid, sizeof(guid),
reinterpret_cast<const UCHAR*>(&guid)); reinterpret_cast<const UCHAR*>(&guid));
header = NULL; header_locked = false;
CCH_RELEASE(tdbb, &window); CCH_RELEASE(tdbb, &window);
tdbb->tdbb_flags &= ~TDBB_set_backup_state; tdbb->tdbb_flags &= ~TDBB_set_backup_state;
backup_state = newState; backup_state = newState;
current_scn = adjusted_scn; current_scn = adjusted_scn;
// This is essential for SuperServer to prevent multi-threading issues // This is essential for SuperServer to prevent multi-threading issues
@ -632,7 +631,7 @@ void BackupManager::begin_backup(thread_db* tdbb)
tdbb->tdbb_flags &= ~TDBB_set_backup_state; tdbb->tdbb_flags &= ~TDBB_set_backup_state;
if (state_locked) if (state_locked)
unlock_state_write(tdbb); unlock_state_write(tdbb);
if (header) if (header_locked)
CCH_RELEASE(tdbb, &window); CCH_RELEASE(tdbb, &window);
#ifndef SUPERSERVER #ifndef SUPERSERVER
if (database_locked) if (database_locked)
@ -667,13 +666,15 @@ void BackupManager::end_backup(thread_db* tdbb, bool recover)
// for some instants and anything is possible at // for some instants and anything is possible at
// that times. // that times.
// Lock header page first to prevent possible deadlock
WIN window(HEADER_PAGE); WIN window(HEADER_PAGE);
Ods::header_page* header = NULL; Ods::header_page* header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
bool state_locked = false; bool state_locked = false, header_locked = true;
try { try {
if (recover) { if (recover) {
if (!try_lock_state_write(tdbb)) { if (!try_lock_state_write(tdbb)) {
CCH_RELEASE(tdbb, &window);
return; return;
} }
} }
@ -687,6 +688,7 @@ void BackupManager::end_backup(thread_db* tdbb, bool recover)
{ {
NBAK_TRACE(("invalid state %d", backup_state)); NBAK_TRACE(("invalid state %d", backup_state));
unlock_state_write(tdbb); unlock_state_write(tdbb);
CCH_RELEASE(tdbb, &window);
return; return;
} }
NBAK_TRACE(("difference file %s", diff_name)); NBAK_TRACE(("difference file %s", diff_name));
@ -696,7 +698,6 @@ void BackupManager::end_backup(thread_db* tdbb, bool recover)
backup_state = nbak_state_merge; backup_state = nbak_state_merge;
adjusted_scn = ++current_scn; adjusted_scn = ++current_scn;
NBAK_TRACE(("New state is getting to become %d", backup_state)); NBAK_TRACE(("New state is getting to become %d", backup_state));
header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
CCH_MARK_MUST_WRITE(tdbb, &window); CCH_MARK_MUST_WRITE(tdbb, &window);
NBAK_TRACE(("New state is getting to become after fetches %d", backup_state)); NBAK_TRACE(("New state is getting to become after fetches %d", backup_state));
// Generate new SCN // Generate new SCN
@ -704,7 +705,7 @@ void BackupManager::end_backup(thread_db* tdbb, bool recover)
NBAK_TRACE(("new SCN=%d is getting written to header", header->hdr_header.pag_scn)); NBAK_TRACE(("new SCN=%d is getting written to header", header->hdr_header.pag_scn));
// Adjust state // Adjust state
header->hdr_flags = (header->hdr_flags & ~Ods::hdr_backup_mask) | backup_state; header->hdr_flags = (header->hdr_flags & ~Ods::hdr_backup_mask) | backup_state;
header = NULL; header_locked = false;
CCH_RELEASE(tdbb, &window); CCH_RELEASE(tdbb, &window);
tdbb->tdbb_flags &= ~TDBB_set_backup_state; tdbb->tdbb_flags &= ~TDBB_set_backup_state;
NBAK_TRACE(("Set state %d in header page", backup_state)); NBAK_TRACE(("Set state %d in header page", backup_state));
@ -713,14 +714,14 @@ void BackupManager::end_backup(thread_db* tdbb, bool recover)
tdbb->tdbb_flags &= ~TDBB_set_backup_state; tdbb->tdbb_flags &= ~TDBB_set_backup_state;
if (state_locked) if (state_locked)
unlock_state_write(tdbb); unlock_state_write(tdbb);
if (header) if (header_locked)
CCH_RELEASE(tdbb, &window); CCH_RELEASE(tdbb, &window);
throw; throw;
} }
// Here comes the dirty work. We need to reapply all changes from difference file to database // Here comes the dirty work. We need to reapply all changes from difference file to database
// Release write state lock and get read lock. // Release write state lock and get read lock.
// Merge process should not inhibit normal operations. // Merge process should not inhibit normal operations.
tdbb->tdbb_flags &= ~TDBB_set_backup_state; tdbb->tdbb_flags &= ~TDBB_set_backup_state;
@ -740,9 +741,9 @@ void BackupManager::end_backup(thread_db* tdbb, bool recover)
ERR_punt(); ERR_punt();
NBAK_TRACE(("Allocation table %p is current.", alloc_table)); NBAK_TRACE(("Allocation table %p is current.", alloc_table));
AllocItemTree::Accessor all(alloc_table); AllocItemTree::Accessor all(alloc_table);
tdbb->tdbb_flags |= TDBB_set_backup_state | TDBB_backup_merge; tdbb->tdbb_flags |= TDBB_set_backup_state | TDBB_backup_merge;
if (all.getFirst()) { if (all.getFirst()) {
do { do {
WIN window2(all.current().db_page); WIN window2(all.current().db_page);
@ -754,21 +755,22 @@ void BackupManager::end_backup(thread_db* tdbb, bool recover)
} while (all.getNext()); } while (all.getNext());
} }
CCH_flush(tdbb, FLUSH_ALL, 0); // Really write changes to main database file CCH_flush(tdbb, FLUSH_ALL, 0); // Really write changes to main database file
tdbb->tdbb_flags &= ~(TDBB_set_backup_state | TDBB_backup_merge); tdbb->tdbb_flags &= ~(TDBB_set_backup_state | TDBB_backup_merge);
unlock_state(tdbb); unlock_state(tdbb);
} catch(const std::exception&) { } catch(const std::exception&) {
tdbb->tdbb_flags &= ~(TDBB_set_backup_state | TDBB_backup_merge); tdbb->tdbb_flags &= ~(TDBB_set_backup_state | TDBB_backup_merge);
unlock_state(tdbb); unlock_state(tdbb);
throw; throw;
} }
// We finished. We need to reflect it in our database header page // We finished. We need to reflect it in our database header page
window.win_page = HEADER_PAGE; window.win_page = HEADER_PAGE;
window.win_flags = 0; window.win_flags = 0;
header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
state_locked = false; state_locked = false;
header_locked = true;
try { try {
lock_state_write(tdbb, true); lock_state_write(tdbb, true);
state_locked = true; state_locked = true;
@ -789,15 +791,15 @@ void BackupManager::end_backup(thread_db* tdbb, bool recover)
// Generate new SCN // Generate new SCN
header->hdr_header.pag_scn = ++current_scn; header->hdr_header.pag_scn = ++current_scn;
NBAK_TRACE(("new SCN=%d is getting written to header", header->hdr_header.pag_scn)); NBAK_TRACE(("new SCN=%d is getting written to header", header->hdr_header.pag_scn));
header = NULL; header_locked = false;
CCH_RELEASE(tdbb, &window); CCH_RELEASE(tdbb, &window);
tdbb->tdbb_flags &= ~TDBB_set_backup_state; tdbb->tdbb_flags &= ~TDBB_set_backup_state;
// Page allocation table cache is no longer valid // Page allocation table cache is no longer valid
delete alloc_table; delete alloc_table;
alloc_table = NULL; alloc_table = NULL;
last_allocated_page = 0; last_allocated_page = 0;
if (diff_file) { if (diff_file) {
#ifndef SUPERSERVER #ifndef SUPERSERVER
diff_generation++; diff_generation++;
@ -806,7 +808,7 @@ void BackupManager::end_backup(thread_db* tdbb, bool recover)
diff_file = NULL; diff_file = NULL;
} }
unlink(diff_name.c_str()); unlink(diff_name.c_str());
unlock_state_write(tdbb); unlock_state_write(tdbb);
NBAK_TRACE(("backup ended")); NBAK_TRACE(("backup ended"));
} catch (const std::exception&) { } catch (const std::exception&) {
@ -814,7 +816,7 @@ void BackupManager::end_backup(thread_db* tdbb, bool recover)
tdbb->tdbb_flags &= ~TDBB_set_backup_state; tdbb->tdbb_flags &= ~TDBB_set_backup_state;
if (state_locked) if (state_locked)
unlock_state_write(tdbb); unlock_state_write(tdbb);
if (header) if (header_locked)
CCH_RELEASE(tdbb, &window); CCH_RELEASE(tdbb, &window);
throw; throw;
} }
@ -1083,9 +1085,9 @@ bool BackupManager::actualize_state(thread_db* tdbb) throw()
// State is unknown. We need to read it from the disk. // State is unknown. We need to read it from the disk.
// We cannot use CCH for this because of likely recursion. // We cannot use CCH for this because of likely recursion.
NBAK_TRACE(("actualize_state")); NBAK_TRACE(("actualize_state"));
ISC_STATUS *status = tdbb->tdbb_status_vector; ISC_STATUS *status = tdbb->tdbb_status_vector;
// Read original page from database file or shadows. // Read original page from database file or shadows.
SSHORT retryCount = 0; SSHORT retryCount = 0;
Ods::header_page* header = reinterpret_cast<Ods::header_page*>(spare_buffer); Ods::header_page* header = reinterpret_cast<Ods::header_page*>(spare_buffer);
@ -1136,7 +1138,7 @@ bool BackupManager::actualize_state(thread_db* tdbb) throw()
} }
if (!fname_found) if (!fname_found)
generate_filename(); generate_filename();
if (new_backup_state == nbak_state_normal || missed_cycle) { if (new_backup_state == nbak_state_normal || missed_cycle) {
if (diff_file) if (diff_file)
diff_pending_close = true; diff_pending_close = true;