diff --git a/src/common/classes/DbImplementation.cpp b/src/common/classes/DbImplementation.cpp index 7c58ee9eb90..837c878a3b7 100644 --- a/src/common/classes/DbImplementation.cpp +++ b/src/common/classes/DbImplementation.cpp @@ -146,7 +146,8 @@ const UCHAR backEndianess[FB_NELEM(hardware)] = namespace Firebird { DbImplementation::DbImplementation(const Ods::header_page* h) - : di_cpu(h->hdr_cpu), di_os(h->hdr_os), di_cc(h->hdr_cc), di_flags(h->hdr_compatibility_flags) + : di_cpu(h->hdr_db_impl.hdr_cpu), di_os(h->hdr_db_impl.hdr_os), + di_cc(h->hdr_db_impl.hdr_cc), di_flags(h->hdr_db_impl.hdr_compat) { } @@ -196,10 +197,10 @@ bool DbImplementation::compatible(const DbImplementation& v) const void DbImplementation::store(Ods::header_page* h) const { - h->hdr_cpu = di_cpu; - h->hdr_os = di_os; - h->hdr_cc = di_cc; - h->hdr_compatibility_flags = di_flags; + h->hdr_db_impl.hdr_cpu = di_cpu; + h->hdr_db_impl.hdr_os = di_os; + h->hdr_db_impl.hdr_cc = di_cc; + h->hdr_db_impl.hdr_compat = di_flags; } void DbImplementation::stuff(UCHAR** info) const @@ -224,7 +225,7 @@ DbImplementation DbImplementation::fromBackwardCompatibleByte(UCHAR bcImpl) { for (UCHAR hw = 0; hw < FB_NELEM(hardware); ++hw) { - USHORT ind = USHORT(os) * FB_NELEM(hardware) + USHORT(hw); + const USHORT ind = USHORT(os) * FB_NELEM(hardware) + USHORT(hw); if (backwardTable[ind] == bcImpl) { return DbImplementation(hw, os, 0xFF, backEndianess[hw] ? EndianBig : EndianLittle); diff --git a/src/common/classes/DbImplementation.h b/src/common/classes/DbImplementation.h index 5d2a496359e..a7e12597e7a 100644 --- a/src/common/classes/DbImplementation.h +++ b/src/common/classes/DbImplementation.h @@ -38,10 +38,13 @@ class DbImplementation { public: explicit DbImplementation(const Ods::header_page* h); - DbImplementation (UCHAR p_cpu, UCHAR p_os, UCHAR p_cc, UCHAR p_flags) + + DbImplementation(UCHAR p_cpu, UCHAR p_os, UCHAR p_cc, UCHAR p_flags) : di_cpu(p_cpu), di_os(p_os), di_cc(p_cc), di_flags(p_flags) { } - ~DbImplementation() { } + + ~DbImplementation() + { } private: UCHAR di_cpu, di_os, di_cc, di_flags; diff --git a/src/jrd/CryptoManager.cpp b/src/jrd/CryptoManager.cpp index b3e17273304..9f19a30e504 100644 --- a/src/jrd/CryptoManager.cpp +++ b/src/jrd/CryptoManager.cpp @@ -54,10 +54,11 @@ using namespace Firebird; -namespace { +namespace +{ THREAD_ENTRY_DECLARE cryptThreadStatic(THREAD_ENTRY_PARAM p) { - Jrd::CryptoManager* cryptoManager = (Jrd::CryptoManager*) p; + const auto cryptoManager = (Jrd::CryptoManager*) p; cryptoManager->cryptThread(); return 0; @@ -68,12 +69,12 @@ namespace { const UCHAR CRYPT_CHANGE = LCK_PW; const UCHAR CRYPT_INIT = LCK_EX; - const int MAX_PLUGIN_NAME_LEN = 31; + constexpr int MAX_PLUGIN_NAME_LEN = sizeof(Ods::header_page::hdr_crypt_plugin) - 1; } -namespace Jrd { - +namespace Jrd +{ class Header { protected: @@ -553,10 +554,10 @@ namespace Jrd { const bool newCryptState = plugName.hasData(); - int bak_state = Ods::hdr_nbak_unknown; + auto backupState = Ods::hdr_nbak_unknown; { // scope BackupManager::StateReadGuard stateGuard(tdbb); - bak_state = dbb.dbb_backup_manager->getState(); + backupState = dbb.dbb_backup_manager->getState(); } { // window scope @@ -574,7 +575,7 @@ namespace Jrd { (Arg::Gds(isc_cp_already_crypted)).raise(); } - if (bak_state != Ods::hdr_nbak_normal) + if (backupState != Ods::hdr_nbak_normal) { (Arg::Gds(isc_wish_list) << Arg::Gds(isc_random) << "Cannot crypt: please wait for nbackup completion").raise(); @@ -625,9 +626,9 @@ namespace Jrd { void CryptoManager::changeCryptState(thread_db* tdbb, const string& plugName) { - if (plugName.length() > 31) + if (plugName.length() > MAX_PLUGIN_NAME_LEN) { - (Arg::Gds(isc_cp_name_too_long) << Arg::Num(31)).raise(); + (Arg::Gds(isc_cp_name_too_long) << Arg::Num(MAX_PLUGIN_NAME_LEN)).raise(); } const bool newCryptState = plugName.hasData(); @@ -656,8 +657,8 @@ namespace Jrd { // Nbak's lock was taken in prepareChangeCryptState() // If it was invalidated it's enough reason not to continue now - int bak_state = dbb.dbb_backup_manager->getState(); - if (bak_state != Ods::hdr_nbak_normal) + auto backupState = dbb.dbb_backup_manager->getState(); + if (backupState != Ods::hdr_nbak_normal) { (Arg::Gds(isc_wish_list) << Arg::Gds(isc_random) << "Cannot crypt: please wait for nbackup completion").raise(); @@ -669,7 +670,7 @@ namespace Jrd { (Arg::Gds(isc_cp_process_active)).raise(); } - bool headerCryptState = hdr->hdr_flags & Ods::hdr_encrypted; + const bool headerCryptState = hdr->hdr_flags & Ods::hdr_encrypted; if (headerCryptState == newCryptState) { (Arg::Gds(isc_cp_already_crypted)).raise(); @@ -1085,13 +1086,13 @@ namespace Jrd { JRD_reschedule(tdbb); // nbackup state check - int bak_state = Ods::hdr_nbak_unknown; + auto backupState = Ods::hdr_nbak_unknown; { // scope BackupManager::StateReadGuard stateGuard(tdbb); - bak_state = dbb.dbb_backup_manager->getState(); + backupState = dbb.dbb_backup_manager->getState(); } - if (bak_state != Ods::hdr_nbak_normal) + if (backupState != Ods::hdr_nbak_normal) { EngineCheckout checkout(tdbb, FB_FUNCTION); Thread::sleep(10); diff --git a/src/jrd/Database.cpp b/src/jrd/Database.cpp index c88b61171dd..265a6b3f6b5 100644 --- a/src/jrd/Database.cpp +++ b/src/jrd/Database.cpp @@ -252,7 +252,7 @@ namespace Jrd while (true) { AtomicCounter::counter_type old = dbb_flags; - if ((old & (DBB_sweep_in_progress | DBB_sweep_starting)) || (dbb_ast_flags & DBB_shutdown)) + if ((old & (DBB_sweep_in_progress | DBB_sweep_starting)) || isShutdown()) { dbb_thread_mutex.leave(); return false; diff --git a/src/jrd/Database.h b/src/jrd/Database.h index b8ef78e878a..3e145b5fd57 100644 --- a/src/jrd/Database.h +++ b/src/jrd/Database.h @@ -237,12 +237,9 @@ const ULONG DBB_shared = 0x100000L; // Database object is shared among conne const ULONG DBB_blocking = 0x1L; // Exclusive mode is blocking const ULONG DBB_get_shadows = 0x2L; // Signal received to check for new shadows const ULONG DBB_assert_locks = 0x4L; // Locks are to be asserted -const ULONG DBB_shutdown = 0x8L; // Database is shutdown -const ULONG DBB_shut_attach = 0x10L; // no new attachments accepted -const ULONG DBB_shut_tran = 0x20L; // no new transactions accepted -const ULONG DBB_shut_force = 0x40L; // forced shutdown in progress -const ULONG DBB_shutdown_full = 0x80L; // Database fully shut down -const ULONG DBB_shutdown_single = 0x100L; // Database is in single-user maintenance mode +const ULONG DBB_shut_attach = 0x8L; // No new attachments accepted +const ULONG DBB_shut_tran = 0x10L; // No new transactions accepted +const ULONG DBB_shut_force = 0x20L; // Forced shutdown in progress class Database : public pool_alloc { @@ -472,6 +469,7 @@ class Database : public pool_alloc Firebird::RWLock dbb_ast_lock; // avoids delivering AST to going away database Firebird::AtomicCounter dbb_ast_flags; // flags modified at AST level Firebird::AtomicCounter dbb_flags; + std::atomic dbb_shutdown_mode; // shutdown mode USHORT dbb_ods_version; // major ODS version number USHORT dbb_minor_version; // minor ODS version number USHORT dbb_page_size; // page size @@ -540,7 +538,7 @@ class Database : public pool_alloc Lock* dbb_repl_lock; // replication state lock Firebird::SyncObject dbb_repl_sync; FB_UINT64 dbb_repl_sequence; // replication sequence - ReplicaMode dbb_replica_mode; // replica access mode + std::atomic dbb_replica_mode; // replica access mode unsigned dbb_compatibility_index; // datatype backward compatibility level Dictionary dbb_dic; // metanames dictionary @@ -576,14 +574,24 @@ class Database : public pool_alloc void registerModule(Module&); + bool isShutdown() const + { + return (dbb_shutdown_mode.load(std::memory_order_relaxed) != shut_mode_online); + } + + bool isShutdown(shut_mode_t mode) const + { + return (dbb_shutdown_mode.load(std::memory_order_relaxed) == mode); + } + bool isReplica() const { - return (dbb_replica_mode != REPLICA_NONE); + return (dbb_replica_mode.load(std::memory_order_relaxed) != REPLICA_NONE); } bool isReplica(ReplicaMode mode) const { - return (dbb_replica_mode == mode); + return (dbb_replica_mode.load(std::memory_order_relaxed) == mode); } USHORT getEncodedOdsVersion() const @@ -605,6 +613,7 @@ class Database : public pool_alloc dbb_modules(*p), dbb_extManager(nullptr), dbb_flags(shared ? DBB_shared : 0), + dbb_shutdown_mode(shut_mode_online), dbb_filename(*p), dbb_database_name(*p), #ifdef HAVE_ID_BY_NAME diff --git a/src/jrd/Monitoring.cpp b/src/jrd/Monitoring.cpp index 704c1168654..dd64c4199f0 100644 --- a/src/jrd/Monitoring.cpp +++ b/src/jrd/Monitoring.cpp @@ -837,9 +837,9 @@ void Monitoring::putDatabase(thread_db* tdbb, SnapshotData::DumpRecord& record) record.reset(rel_mon_database); // Determine the backup state - int backup_state = backup_state_unknown; + int backupState = backup_state_unknown; - BackupManager* const bm = dbb->dbb_backup_manager; + const auto bm = dbb->dbb_backup_manager; if (bm && !bm->isShutDown()) { @@ -848,14 +848,16 @@ void Monitoring::putDatabase(thread_db* tdbb, SnapshotData::DumpRecord& record) switch (bm->getState()) { case Ods::hdr_nbak_normal: - backup_state = backup_state_normal; + backupState = backup_state_normal; break; case Ods::hdr_nbak_stalled: - backup_state = backup_state_stalled; + backupState = backup_state_stalled; break; case Ods::hdr_nbak_merge: - backup_state = backup_state_merge; + backupState = backup_state_merge; break; + default: + fb_assert(false); } } @@ -886,18 +888,8 @@ void Monitoring::putDatabase(thread_db* tdbb, SnapshotData::DumpRecord& record) // SQL dialect temp = (dbb->dbb_flags & DBB_DB_SQL_dialect_3) ? 3 : 1; record.storeInteger(f_mon_db_dialect, temp); - // shutdown mode - if (dbb->dbb_ast_flags & DBB_shutdown_full) - temp = shut_mode_full; - else if (dbb->dbb_ast_flags & DBB_shutdown_single) - temp = shut_mode_single; - else if (dbb->dbb_ast_flags & DBB_shutdown) - temp = shut_mode_multi; - else - temp = shut_mode_online; - record.storeInteger(f_mon_db_shut_mode, temp); - + record.storeInteger(f_mon_db_shut_mode, dbb->dbb_shutdown_mode); // sweep interval record.storeInteger(f_mon_db_sweep_int, dbb->dbb_sweep_interval); // read only flag @@ -914,7 +906,7 @@ void Monitoring::putDatabase(thread_db* tdbb, SnapshotData::DumpRecord& record) // database size record.storeInteger(f_mon_db_pages, PageSpace::actAlloc(dbb)); // database backup state - record.storeInteger(f_mon_db_backup_state, backup_state); + record.storeInteger(f_mon_db_backup_state, backupState); // crypt thread status if (dbb->dbb_crypto_manager) diff --git a/src/jrd/SysFunction.cpp b/src/jrd/SysFunction.cpp index 027fa1a1aee..54c12fda6a1 100644 --- a/src/jrd/SysFunction.cpp +++ b/src/jrd/SysFunction.cpp @@ -4611,13 +4611,13 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar } else if (nameStr == REPLICA_MODE) { - if (dbb->dbb_replica_mode == REPLICA_READ_ONLY) + if (dbb->isReplica(REPLICA_READ_ONLY)) resultStr = RO_VALUE; - else if (dbb->dbb_replica_mode == REPLICA_READ_WRITE) + else if (dbb->isReplica(REPLICA_READ_WRITE)) resultStr = RW_VALUE; else { - fb_assert(dbb->dbb_replica_mode == REPLICA_NONE); + fb_assert(!dbb->isReplica()); return NULL; } } @@ -4997,8 +4997,8 @@ dsc* evlGetTranCN(thread_db* tdbb, const SysFunction* function, const NestValueA if ((traNum > traMax) && !(dbb->dbb_flags & DBB_shared)) { WIN window(HEADER_PAGE_NUMBER); - const Ods::header_page* header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header); - traMax = Ods::getNT(header); + const auto header = (const Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header); + traMax = header->hdr_next_transaction; CCH_RELEASE(tdbb, &window); } diff --git a/src/jrd/cch.cpp b/src/jrd/cch.cpp index 6f097e8e542..b9378d4f129 100644 --- a/src/jrd/cch.cpp +++ b/src/jrd/cch.cpp @@ -414,7 +414,7 @@ int CCH_down_grade_dbb(void* ast_object) // If we are supposed to be exclusive, stay exclusive - if ((dbb->dbb_flags & DBB_exclusive) || (dbb->dbb_ast_flags & DBB_shutdown_single)) + if ((dbb->dbb_flags & DBB_exclusive) || dbb->isShutdown(shut_mode_single)) return 0; // Assert any page locks that have been requested, but not asserted @@ -602,9 +602,9 @@ bool CCH_exclusive_attachment(thread_db* tdbb, USHORT level, SSHORT wait_flag, S found = true; break; } + // Forbid multiple attachments in single-user maintenance mode - if (other_attachment != attachment && - (dbb->dbb_ast_flags & DBB_shutdown_single)) + if (other_attachment != attachment && dbb->isShutdown(shut_mode_single)) { found = true; break; @@ -622,6 +622,7 @@ bool CCH_exclusive_attachment(thread_db* tdbb, USHORT level, SSHORT wait_flag, S attachment->att_flags &= ~ATT_exclusive_pending; return false; } + break; } } @@ -992,27 +993,27 @@ void CCH_fetch_page(thread_db* tdbb, WIN* window, const bool read_shadow) PageSpace* pageSpace; }; - BackupManager* bm = dbb->dbb_backup_manager; + const auto bm = dbb->dbb_backup_manager; BackupManager::StateReadGuard stateGuard(tdbb); - const int bak_state = bm->getState(); - fb_assert(bak_state != Ods::hdr_nbak_unknown); + const auto backupState = bm->getState(); + fb_assert(backupState != Ods::hdr_nbak_unknown); ULONG diff_page = 0; - if (!isTempPage && bak_state != Ods::hdr_nbak_normal) + if (!isTempPage && backupState != Ods::hdr_nbak_normal) { diff_page = bm->getPageIndex(tdbb, bdb->bdb_page.getPageNum()); NBAK_TRACE(("Reading page %d:%06d, state=%d, diff page=%d", - bdb->bdb_page.getPageSpaceID(), bdb->bdb_page.getPageNum(), bak_state, diff_page)); + bdb->bdb_page.getPageSpaceID(), bdb->bdb_page.getPageNum(), (int) backupState, diff_page)); } // In merge mode, if we are reading past beyond old end of file and page is in .delta file // then we maintain actual page in difference file. Always read it from there. - if (isTempPage || bak_state == Ods::hdr_nbak_normal || !diff_page) + if (isTempPage || backupState == Ods::hdr_nbak_normal || !diff_page) { fb_assert(bdb->bdb_page == window->win_page); NBAK_TRACE(("Reading page %d:%06d, state=%d, diff page=%d from DISK", - bdb->bdb_page.getPageSpaceID(), bdb->bdb_page.getPageNum(), bak_state, diff_page)); + bdb->bdb_page.getPageSpaceID(), bdb->bdb_page.getPageNum(), (int) backupState, diff_page)); // Read page from disk as normal Pio io(file, bdb, isTempPage, read_shadow, pageSpace); @@ -1049,7 +1050,7 @@ void CCH_fetch_page(thread_db* tdbb, WIN* window, const bool read_shadow) // Engine is not supposed to read a page which was never written unless // this is a merge process. NBAK_TRACE(("Re-reading page %d, state=%d, diff page=%d from DISK", - bdb->bdb_page, bak_state, diff_page)); + bdb->bdb_page, (int) backupState, diff_page)); Pio io(file, bdb, false, read_shadow, pageSpace); if (!dbb->dbb_crypto_manager->read(tdbb, status, page, &io)) @@ -1239,8 +1240,7 @@ void CCH_flush(thread_db* tdbb, USHORT flush_flag, TraNumber tra_number) const Jrd::Attachment* att = tdbb->getAttachment(); const bool dontFlush = (dbb->dbb_flags & DBB_creating) || - ((dbb->dbb_ast_flags & DBB_shutdown) && - att && (att->att_flags & (ATT_creator | ATT_system))); + (dbb->isShutdown() && att && (att->att_flags & (ATT_creator | ATT_system))); if (!(main_file->fil_flags & FIL_force_write) && (max_num || max_time) && !dontFlush) { @@ -1281,8 +1281,8 @@ void CCH_flush(thread_db* tdbb, USHORT flush_flag, TraNumber tra_number) if (bm && !bm->isShutDown()) { BackupManager::StateReadGuard stateGuard(tdbb); - const int backup_state = bm->getState(); - if (backup_state == Ods::hdr_nbak_stalled || backup_state == Ods::hdr_nbak_merge) + const auto backupState = bm->getState(); + if (backupState == Ods::hdr_nbak_stalled || backupState == Ods::hdr_nbak_merge) bm->flushDifference(tdbb); } } @@ -1978,21 +1978,20 @@ bool set_diff_page(thread_db* tdbb, BufferDesc* bdb) // Determine location of the page in difference file and write destination // so BufferDesc AST handlers and write_page routine can safely use this information - const int backup_state = bm->getState(); + const auto backupState = bm->getState(); - if (backup_state == Ods::hdr_nbak_normal) + if (backupState == Ods::hdr_nbak_normal) return true; - switch (backup_state) + switch (backupState) { case Ods::hdr_nbak_stalled: bdb->bdb_difference_page = bm->getPageIndex(tdbb, bdb->bdb_page.getPageNum()); if (!bdb->bdb_difference_page) { bdb->bdb_difference_page = bm->allocateDifferencePage(tdbb, bdb->bdb_page.getPageNum()); - if (!bdb->bdb_difference_page) { + if (!bdb->bdb_difference_page) return false; - } NBAK_TRACE(("Allocate difference page %d for database page %d", bdb->bdb_difference_page, bdb->bdb_page)); } @@ -4880,19 +4879,19 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s // the next_transaction > oldest_active transaction if (bdb->bdb_page == HEADER_PAGE_NUMBER) { - const header_page* const header = (header_page*) page; + const auto header = (const header_page*) page; - const TraNumber next_transaction = Ods::getNT(header); - const TraNumber oldest_active = Ods::getOAT(header); - const TraNumber oldest_transaction = Ods::getOIT(header); + const TraNumber next_transaction = header->hdr_next_transaction; + const TraNumber oldest_transaction = header->hdr_oldest_transaction; + const TraNumber oldest_active = header->hdr_oldest_active; if (next_transaction) { - if (oldest_active > next_transaction) - BUGCHECK(266); // next transaction older than oldest active - if (oldest_transaction > next_transaction) BUGCHECK(267); // next transaction older than oldest transaction + + if (oldest_active > next_transaction) + BUGCHECK(266); // next transaction older than oldest active } } @@ -4909,11 +4908,11 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s // write out page to main database file, and to any // shadows, making a special case of the header page BackupManager* bm = dbb->dbb_backup_manager; - const int backup_state = bm->getState(); + const auto backupState = bm->getState(); /// ASF: Always true: if (bdb->bdb_page.getPageNum() >= 0) { - fb_assert(backup_state != Ods::hdr_nbak_unknown); + fb_assert(backupState != Ods::hdr_nbak_unknown); page->pag_pageno = bdb->bdb_page.getPageNum(); #ifdef NBAK_DEBUG @@ -4927,7 +4926,7 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s strcpy(ptr, ", backup_state="); ptr += strlen(ptr); - gds__ulstr(ptr, backup_state, 0, 0); + gds__ulstr(ptr, backupState, 0, 0); ptr += strlen(ptr); strcpy(ptr, ", diff="); @@ -4948,8 +4947,8 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s const bool isTempPage = pageSpace->isTemporary(); if (!isTempPage && - (backup_state == Ods::hdr_nbak_stalled || - (backup_state == Ods::hdr_nbak_merge && bdb->bdb_difference_page))) + (backupState == Ods::hdr_nbak_stalled || + (backupState == Ods::hdr_nbak_merge && bdb->bdb_difference_page))) { if (!dbb->dbb_backup_manager->writeDifference(tdbb, status, bdb->bdb_difference_page, bdb->bdb_buffer)) @@ -4960,11 +4959,14 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s } } - if (!isTempPage && backup_state == Ods::hdr_nbak_stalled) + if (!isTempPage && backupState == Ods::hdr_nbak_stalled) { // We finished. Adjust transaction accounting and get ready for exit if (bdb->bdb_page == HEADER_PAGE_NUMBER) - dbb->dbb_last_header_write = Ods::getNT((header_page*) page); + { + const auto header = (const header_page*) page; + dbb->dbb_last_header_write = header->hdr_next_transaction; + } } else { @@ -4994,7 +4996,10 @@ static bool write_page(thread_db* tdbb, BufferDesc* bdb, FbStatusVector* const s } if (bdb->bdb_page == HEADER_PAGE_NUMBER) - dbb->dbb_last_header_write = Ods::getNT((header_page*) page); + { + const auto header = (const header_page*) page; + dbb->dbb_last_header_write = header->hdr_next_transaction; + } if (dbb->dbb_shadow && !isTempPage) return CCH_write_all_shadows(tdbb, 0, bdb, page, status, inAst); diff --git a/src/jrd/constants.h b/src/jrd/constants.h index ce322ee78d6..42d1251181d 100644 --- a/src/jrd/constants.h +++ b/src/jrd/constants.h @@ -247,7 +247,7 @@ enum mon_state_t { mon_state_stalled = 2 }; -// shutdown modes +// shutdown modes (match hdr_nbak_* in ods.h) enum shut_mode_t { shut_mode_online = 0, @@ -256,7 +256,7 @@ enum shut_mode_t { shut_mode_full = 3 }; -// backup states +// backup states (match hdr_backup_* in ods.h) enum backup_state_t { backup_state_unknown = -1, @@ -301,13 +301,17 @@ enum InfoType MAX_INFO_TYPE }; -enum ReplicaMode { +// Replica modes (match hdr_replica_* in ods.h) + +enum ReplicaMode +{ REPLICA_NONE = 0, REPLICA_READ_ONLY = 1, REPLICA_READ_WRITE = 2 }; -enum TriggerType { +enum TriggerType +{ PRE_STORE_TRIGGER = 1, POST_STORE_TRIGGER = 2, PRE_MODIFY_TRIGGER = 3, @@ -316,7 +320,8 @@ enum TriggerType { POST_ERASE_TRIGGER = 6 }; -enum TriggerAction { +enum TriggerAction +{ // Order should be maintained because the numbers are stored in BLR // and should be in sync with IExternalTrigger::ACTION_* . TRIGGER_INSERT = 1, diff --git a/src/jrd/idx.cpp b/src/jrd/idx.cpp index 5c22b9b1862..86298ee0699 100644 --- a/src/jrd/idx.cpp +++ b/src/jrd/idx.cpp @@ -236,7 +236,7 @@ class IndexCreateTask : public Task workers = att->att_parallel_workers; // Classic in single-user shutdown mode can't create additional worker attachments - if ((m_dbb->dbb_ast_flags & DBB_shutdown_single) && !(m_dbb->dbb_flags & DBB_shared)) + if (m_dbb->isShutdown(shut_mode_single) && !(m_dbb->dbb_flags & DBB_shared)) workers = 1; for (int i = 0; i < workers; i++) diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 2d0fea95639..bff9736b470 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -1986,7 +1986,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch if (!options.dpb_sec_attach) { bool attachment_succeeded = true; - if (dbb->dbb_ast_flags & DBB_shutdown_single) + if (dbb->isShutdown(shut_mode_single)) attachment_succeeded = CCH_exclusive_attachment(tdbb, LCK_none, -1, NULL); else CCH_exclusive_attachment(tdbb, LCK_none, LCK_WAIT, NULL); @@ -1995,7 +1995,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch { const ISC_STATUS err = jAtt->getStable()->getShutError(); - if (dbb->dbb_ast_flags & DBB_shutdown) + if (dbb->isShutdown()) ERR_post(Arg::Gds(isc_shutdown) << Arg::Str(org_filename)); if (err) @@ -2013,19 +2013,19 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch if (dbb->dbb_ast_flags & (DBB_shut_attach | DBB_shut_tran)) ERR_post(Arg::Gds(isc_shutinprog) << Arg::Str(org_filename)); - if (dbb->dbb_ast_flags & DBB_shutdown) + if (dbb->isShutdown()) { // Allow only SYSDBA/owner to access database that is shut down bool allow_access = attachment->locksmith(tdbb, ACCESS_SHUTDOWN_DATABASE); // Handle special shutdown modes if (allow_access) { - if (dbb->dbb_ast_flags & DBB_shutdown_full) + if (dbb->isShutdown(shut_mode_full)) { // Full shutdown. Deny access always allow_access = false; } - else if (dbb->dbb_ast_flags & DBB_shutdown_single) + else if (dbb->isShutdown(shut_mode_single)) { // Single user maintenance. Allow access only if we were able to take exclusive lock // Note that logic below this exclusive lock differs for SS and CS builds: @@ -3362,7 +3362,7 @@ void JAttachment::freeEngineData(CheckStatusWrapper* user_status, bool forceFree flags |= PURGE_FORCE; if (forceFree || - (dbb->dbb_ast_flags & DBB_shutdown) || + dbb->isShutdown() || (attachment->att_flags & ATT_shutdown)) { flags |= PURGE_NOCHECK; @@ -3373,7 +3373,7 @@ void JAttachment::freeEngineData(CheckStatusWrapper* user_status, bool forceFree reason = 0; else if (engineShutdown) reason = isc_att_shut_engine; - else if (dbb->dbb_ast_flags & DBB_shutdown) + else if (dbb->isShutdown()) reason = isc_att_shut_db_down; attachment->signalShutdown(reason); @@ -3467,7 +3467,7 @@ void JAttachment::internalDropDatabase(CheckStatusWrapper* user_status) { const ISC_STATUS err = getStable()->getShutError(); - if (dbb->dbb_ast_flags & DBB_shutdown) + if (dbb->isShutdown()) ERR_post(Arg::Gds(isc_shutdown) << Arg::Str(file_name)); if (err) @@ -6730,10 +6730,11 @@ static void check_database(thread_db* tdbb, bool async) if ((attachment->att_flags & ATT_shutdown) && (attachment->att_purge_tid != Thread::getId()) || - ((dbb->dbb_ast_flags & DBB_shutdown) && - ((dbb->dbb_ast_flags & DBB_shutdown_full) || !attachment->locksmith(tdbb, ACCESS_SHUTDOWN_DATABASE)))) + (dbb->isShutdown() && + (dbb->isShutdown(shut_mode_full) || + !attachment->locksmith(tdbb, ACCESS_SHUTDOWN_DATABASE)))) { - if (dbb->dbb_ast_flags & DBB_shutdown) + if (dbb->isShutdown()) { const PathName& filename = attachment->att_filename; status_exception::raise(Arg::Gds(isc_shutdown) << Arg::Str(filename)); @@ -7597,10 +7598,8 @@ static void check_single_maintenance(thread_db* tdbb) PIO_header(tdbb, header_page_buffer, headerSize); - if ((header_page->hdr_flags & Ods::hdr_shutdown_mask) == Ods::hdr_shutdown_single) - { + if (header_page->hdr_shutdown_mode == Ods::hdr_shutdown_single) ERR_post(Arg::Gds(isc_shutdown) << Arg::Str(tdbb->getAttachment()->att_filename)); - } } @@ -7964,7 +7963,7 @@ bool JRD_shutdown_database(Database* dbb, const unsigned flags) // Database linger if ((flags & SHUT_DBB_LINGER) && - (!(engineShutdown || (dbb->dbb_ast_flags & DBB_shutdown))) && + (!(engineShutdown || dbb->isShutdown())) && (dbb->dbb_linger_seconds > 0) && (dbb->dbb_config->getServerMode() != MODE_CLASSIC) && (dbb->dbb_flags & DBB_shared)) @@ -9201,7 +9200,7 @@ ISC_STATUS thread_db::getCancelState(ISC_STATUS* secondary) { if (attachment->att_flags & ATT_shutdown) { - if (database->dbb_ast_flags & DBB_shutdown) + if (database->isShutdown()) return isc_shutdown; if (secondary) diff --git a/src/jrd/nbak.cpp b/src/jrd/nbak.cpp index 2820163767f..fa1314d327d 100644 --- a/src/jrd/nbak.cpp +++ b/src/jrd/nbak.cpp @@ -332,8 +332,8 @@ void BackupManager::beginBackup(thread_db* tdbb) // Set state in database header page. All changes are written to main database file yet. CCH_MARK_MUST_WRITE(tdbb, &window); - const int newState = Ods::hdr_nbak_stalled; // Should be USHORT? - header->hdr_flags = (header->hdr_flags & ~Ods::hdr_backup_mask) | newState; + const auto newState = Ods::hdr_nbak_stalled; + header->hdr_backup_mode = newState; const ULONG adjusted_scn = ++header->hdr_header.pag_scn; // Generate new SCN PAG_replace_entry_first(tdbb, header, Ods::HDR_backup_guid, Guid::SIZE, Guid::generate().getData()); @@ -354,14 +354,9 @@ void BackupManager::beginBackup(thread_db* tdbb) // Determine actual DB size (raw devices support) ULONG BackupManager::getPageCount(thread_db* tdbb) { - if (backup_state != Ods::hdr_nbak_stalled) - { - // calculate pages only when database is locked for backup: - // other case such service is just dangerous - return 0; - } - - return PAG_page_count(tdbb); + // Calculate pages only when database is locked for backup, + // otherwise it's just dangerous + return (backup_state == Ods::hdr_nbak_stalled) ? PAG_page_count(tdbb) : 0; } @@ -493,7 +488,7 @@ void BackupManager::endBackup(thread_db* tdbb, bool recover) header->hdr_header.pag_scn = current_scn; NBAK_TRACE(("new SCN=%d is getting written to header", header->hdr_header.pag_scn)); // Adjust state - header->hdr_flags = (header->hdr_flags & ~Ods::hdr_backup_mask) | backup_state; + header->hdr_backup_mode = backup_state; NBAK_TRACE(("Setting state %d in header page is over", backup_state)); stateGuard.setSuccess(); } @@ -579,7 +574,7 @@ void BackupManager::endBackup(thread_db* tdbb, bool recover) backup_state = Ods::hdr_nbak_normal; CCH_MARK_MUST_WRITE(tdbb, &window); // Adjust state - header->hdr_flags = (header->hdr_flags & ~Ods::hdr_backup_mask) | backup_state; + header->hdr_backup_mode = backup_state; NBAK_TRACE(("Set state %d in header page", backup_state)); // Generate new SCN header->hdr_header.pag_scn = ++current_scn; @@ -984,7 +979,7 @@ bool BackupManager::actualizeState(thread_db* tdbb) } } - const int new_backup_state = header->hdr_flags & Ods::hdr_backup_mask; + const auto new_backup_state = header->hdr_backup_mode; NBAK_TRACE(("backup state read from header is %d", new_backup_state)); // Check is we missed lock/unlock cycle and need to invalidate // our allocation table and file handle diff --git a/src/jrd/nbak.h b/src/jrd/nbak.h index eb2ed9f7e95..cd25c866445 100644 --- a/src/jrd/nbak.h +++ b/src/jrd/nbak.h @@ -362,12 +362,12 @@ class BackupManager void setDifference(thread_db* tdbb, const char* filename); // Return current backup state - USHORT getState() const + UCHAR getState() const { return backup_state; } - void setState(const USHORT newState) + void setState(const UCHAR newState) { backup_state = newState; } @@ -499,7 +499,7 @@ class BackupManager Database* database; jrd_file* diff_file; AllocItemTree* alloc_table; // Cached allocation table of pages in difference file - USHORT backup_state; + UCHAR backup_state; ULONG last_allocated_page; // Last physical page allocated in the difference file Firebird::Array temp_buffers_space; ULONG *alloc_buffer, *empty_buffer, *spare_buffer; diff --git a/src/jrd/ods.cpp b/src/jrd/ods.cpp index 3593d7eec1a..79092e6c69d 100644 --- a/src/jrd/ods.cpp +++ b/src/jrd/ods.cpp @@ -162,58 +162,6 @@ Firebird::string pagtype(UCHAR type) return rc; } -TraNumber getNT(const header_page* page) -{ - return (TraNumber) page->hdr_tra_high[NEXT_INDEX] << BITS_PER_LONG | page->hdr_next_transaction; -} - -TraNumber getOIT(const header_page* page) -{ - return (TraNumber) page->hdr_tra_high[OIT_INDEX] << BITS_PER_LONG | page->hdr_oldest_transaction; -} - -TraNumber getOAT(const header_page* page) -{ - return (TraNumber) page->hdr_tra_high[OAT_INDEX] << BITS_PER_LONG | page->hdr_oldest_active; -} - -TraNumber getOST(const header_page* page) -{ - return (TraNumber) page->hdr_tra_high[OST_INDEX] << BITS_PER_LONG | page->hdr_oldest_snapshot; -} - -void writeNT(header_page* page, TraNumber number) -{ - page->hdr_next_transaction = (ULONG) (number & MAX_ULONG); - const SLONG high_word = number >> BITS_PER_LONG; - fb_assert(high_word <= MAX_USHORT); - page->hdr_tra_high[NEXT_INDEX] = (USHORT) high_word; -} - -void writeOIT(header_page* page, TraNumber number) -{ - page->hdr_oldest_transaction = (ULONG) (number & MAX_ULONG); - const SLONG high_word = number >> BITS_PER_LONG; - fb_assert(high_word <= MAX_USHORT); - page->hdr_tra_high[OIT_INDEX] = (USHORT) high_word; -} - -void writeOAT(header_page* page, TraNumber number) -{ - page->hdr_oldest_active = (ULONG) (number & MAX_ULONG); - const SLONG high_word = number >> BITS_PER_LONG; - fb_assert(high_word <= MAX_USHORT); - page->hdr_tra_high[OAT_INDEX] = (USHORT) high_word; -} - -void writeOST(header_page* page, TraNumber number) -{ - page->hdr_oldest_snapshot = (ULONG) (number & MAX_ULONG); - const SLONG high_word = number >> BITS_PER_LONG; - fb_assert(high_word <= MAX_USHORT); - page->hdr_tra_high[OST_INDEX] = (USHORT) high_word; -} - TraNumber getTraNum(const void* ptr) { rhd* const record = (rhd*) ptr; @@ -255,17 +203,6 @@ void writeTraNum(void* ptr, TraNumber number, FB_SIZE_T header_size) } } -AttNumber getAttID(const header_page* page) -{ - return ((AttNumber)page->hdr_att_high << BITS_PER_LONG | page->hdr_attachment_id); -} - -void writeAttID(header_page* page, AttNumber number) -{ - page->hdr_att_high = number >> BITS_PER_LONG; - page->hdr_attachment_id = (ULONG) (number & MAX_ULONG); -} - } // namespace diff --git a/src/jrd/ods.h b/src/jrd/ods.h index 18ad4824e6f..1c73f12b77f 100644 --- a/src/jrd/ods.h +++ b/src/jrd/ods.h @@ -35,6 +35,7 @@ #include "../jrd/RecordNumber.h" #include "../common/classes/fb_string.h" +#include "../common/classes/Uuid.h" // This macro enables the ability of the engine to connect to databases // from ODS 8 up to the latest. If this macro is undefined, the engine @@ -464,62 +465,62 @@ inline constexpr ULONG END_BUCKET = (~0u) << 1; struct header_page { pag hdr_header; - USHORT hdr_page_size; // Page size of database - USHORT hdr_ods_version; // Version of on-disk structure - ULONG hdr_PAGES; // Page number of PAGES relation - ULONG hdr_unused; // Unused (was: Page number of next hdr page) - ULONG hdr_oldest_transaction; // Oldest interesting transaction - ULONG hdr_oldest_active; // Oldest transaction thought active - ULONG hdr_next_transaction; // Next transaction id - USHORT hdr_sequence; // sequence number of file - USHORT hdr_flags; // Flag settings, see below - SLONG hdr_creation_date[2]; // Date/time of creation - ULONG hdr_attachment_id; // Next attachment id - SLONG hdr_shadow_count; // Event count for shadow synchronization - UCHAR hdr_cpu; // CPU database was created on - UCHAR hdr_os; // OS database was created under - UCHAR hdr_cc; // Compiler of engine on which database was created - UCHAR hdr_compatibility_flags; // Cross-platform database transfer compatibility flags - USHORT hdr_ods_minor; // Update version of ODS - USHORT hdr_end; // offset of HDR_end in page - ULONG hdr_page_buffers; // Page buffers for database cache - ULONG hdr_oldest_snapshot; // Oldest snapshot of active transactions - SLONG hdr_backup_pages; // The amount of pages in files locked for backup - ULONG hdr_crypt_page; // Page at which processing is in progress - TEXT hdr_crypt_plugin[32]; // Name of plugin used to crypt this DB - SLONG hdr_att_high; // High word of the next attachment counter - USHORT hdr_tra_high[4]; // High words of the transaction counters - UCHAR hdr_data[1]; // Misc data + USHORT hdr_page_size; // Page size of database + USHORT hdr_ods_version; // Version of on-disk structure + USHORT hdr_ods_minor; // Update version of ODS + USHORT hdr_flags; // Flag settings, see below + UCHAR hdr_backup_mode; + UCHAR hdr_shutdown_mode; + UCHAR hdr_replica_mode; + ULONG hdr_PAGES; // Page number of PAGES relation + ULONG hdr_page_buffers; // Page buffers for database cache + USHORT hdr_end; // Offset of HDR_end in page + FB_UINT64 hdr_next_transaction; // Next transaction id + FB_UINT64 hdr_oldest_transaction; // Oldest interesting transaction + FB_UINT64 hdr_oldest_active; // Oldest transaction thought active + FB_UINT64 hdr_oldest_snapshot; // Oldest snapshot of active transactions + FB_UINT64 hdr_attachment_id; // Next attachment id + struct + { + UCHAR hdr_cpu; // CPU database was created on + UCHAR hdr_os; // OS database was created under + UCHAR hdr_cc; // Compiler of engine on which database was created + UCHAR hdr_compat; // Cross-platform database transfer compatibility flags + } hdr_db_impl; + UCHAR hdr_guid[16]; // Database GUID + SLONG hdr_creation_date[2]; // Date/time of creation + SLONG hdr_shadow_count; // Event count for shadow synchronization + ULONG hdr_crypt_page; // Page at which processing is in progress + TEXT hdr_crypt_plugin[32]; // Name of plugin used to crypt this DB + UCHAR hdr_data[1]; // Misc data }; -static_assert(sizeof(struct header_page) == 132, "struct header_page size mismatch"); +static_assert(sizeof(struct header_page) == 152, "struct header_page size mismatch"); static_assert(offsetof(struct header_page, hdr_header) == 0, "hdr_header offset mismatch"); static_assert(offsetof(struct header_page, hdr_page_size) == 16, "hdr_page_size offset mismatch"); static_assert(offsetof(struct header_page, hdr_ods_version) == 18, "hdr_ods_version offset mismatch"); -static_assert(offsetof(struct header_page, hdr_PAGES) == 20, "hdr_PAGES offset mismatch"); -static_assert(offsetof(struct header_page, hdr_unused) == 24, "hdr_unused offset mismatch"); -static_assert(offsetof(struct header_page, hdr_oldest_transaction) == 28, "hdr_oldest_transaction offset mismatch"); -static_assert(offsetof(struct header_page, hdr_oldest_active) == 32, "hdr_oldest_active offset mismatch"); -static_assert(offsetof(struct header_page, hdr_next_transaction) == 36, "hdr_next_transaction offset mismatch"); -static_assert(offsetof(struct header_page, hdr_sequence) == 40, "hdr_sequence offset mismatch"); -static_assert(offsetof(struct header_page, hdr_flags) == 42, "hdr_flags offset mismatch"); -static_assert(offsetof(struct header_page, hdr_creation_date) == 44, "hdr_creation_date offset mismatch"); -static_assert(offsetof(struct header_page, hdr_attachment_id) == 52, "hdr_attachment_id offset mismatch"); -static_assert(offsetof(struct header_page, hdr_shadow_count) == 56, "hdr_shadow_count offset mismatch"); -static_assert(offsetof(struct header_page, hdr_cpu) == 60, "hdr_cpu offset mismatch"); -static_assert(offsetof(struct header_page, hdr_os) == 61, "hdr_os offset mismatch"); -static_assert(offsetof(struct header_page, hdr_cc) == 62, "hdr_cc offset mismatch"); -static_assert(offsetof(struct header_page, hdr_compatibility_flags) == 63, "hdr_compatibility_flags offset mismatch"); -static_assert(offsetof(struct header_page, hdr_ods_minor) == 64, "hdr_ods_minor offset mismatch"); -static_assert(offsetof(struct header_page, hdr_end) == 66, "hdr_end offset mismatch"); -static_assert(offsetof(struct header_page, hdr_page_buffers) == 68, "hdr_page_buffers offset mismatch"); -static_assert(offsetof(struct header_page, hdr_oldest_snapshot) == 72, "hdr_oldest_snapshot offset mismatch"); -static_assert(offsetof(struct header_page, hdr_backup_pages) == 76, "hdr_backup_pages offset mismatch"); -static_assert(offsetof(struct header_page, hdr_crypt_page) == 80, "hdr_crypt_page offset mismatch"); -static_assert(offsetof(struct header_page, hdr_crypt_plugin) == 84, "hdr_crypt_plugin offset mismatch"); -static_assert(offsetof(struct header_page, hdr_att_high) == 116, "hdr_att_high offset mismatch"); -static_assert(offsetof(struct header_page, hdr_tra_high) == 120, "hdr_tra_high offset mismatch"); -static_assert(offsetof(struct header_page, hdr_data) == 128, "hdr_data offset mismatch"); +static_assert(offsetof(struct header_page, hdr_ods_minor) == 20, "hdr_ods_minor offset mismatch"); +static_assert(offsetof(struct header_page, hdr_flags) == 22, "hdr_flags offset mismatch"); +static_assert(offsetof(struct header_page, hdr_backup_mode) == 24, "hdr_backup_mode offset mismatch"); +static_assert(offsetof(struct header_page, hdr_shutdown_mode) == 25, "hdr_shutdown_mode offset mismatch"); +static_assert(offsetof(struct header_page, hdr_replica_mode) == 26, "hdr_replica_mode offset mismatch"); +static_assert(offsetof(struct header_page, hdr_PAGES) == 28, "hdr_PAGES offset mismatch"); +static_assert(offsetof(struct header_page, hdr_page_buffers) == 32, "hdr_page_buffers offset mismatch"); +static_assert(offsetof(struct header_page, hdr_end) == 36, "hdr_end offset mismatch"); +static_assert(offsetof(struct header_page, hdr_next_transaction) == 40, "hdr_next_transaction offset mismatch"); +static_assert(offsetof(struct header_page, hdr_oldest_transaction) == 48, "hdr_oldest_transaction offset mismatch"); +static_assert(offsetof(struct header_page, hdr_oldest_active) == 56, "hdr_oldest_active offset mismatch"); +static_assert(offsetof(struct header_page, hdr_oldest_snapshot) == 64, "hdr_oldest_snapshot offset mismatch"); +static_assert(offsetof(struct header_page, hdr_attachment_id) == 72, "hdr_attachment_id offset mismatch"); +static_assert(offsetof(struct header_page, hdr_db_impl) == 80, "hdr_shadow_count offset mismatch"); +static_assert(offsetof(struct header_page, hdr_guid) == 84, "hdr_guid offset mismatch"); +static_assert(offsetof(struct header_page, hdr_creation_date) == 100, "hdr_creation_date offset mismatch"); +static_assert(offsetof(struct header_page, hdr_shadow_count) == 108, "hdr_shadow_count offset mismatch"); +static_assert(offsetof(struct header_page, hdr_crypt_page) == 112, "hdr_crypt_page offset mismatch"); +static_assert(offsetof(struct header_page, hdr_crypt_plugin) == 116, "hdr_crypt_plugin offset mismatch"); +static_assert(offsetof(struct header_page, hdr_data) == 148, "hdr_data offset mismatch"); + +static_assert(sizeof(header_page::hdr_guid) == Firebird::Guid::SIZE, "hdr_guid size mismatch"); #define HDR_SIZE static_cast(offsetof(Ods::header_page, hdr_data[0])) @@ -539,7 +540,7 @@ inline constexpr UCHAR HDR_difference_file = 6; // Delta file that is used duri inline constexpr UCHAR HDR_backup_guid = 7; // GUID generated on each switch into backup mode inline constexpr UCHAR HDR_crypt_key = 8; // Name of a key used to crypt database inline constexpr UCHAR HDR_crypt_hash = 9; // Validator of key correctness -inline constexpr UCHAR HDR_db_guid = 10; // Database GUID +//inline constexpr UCHAR HDR_db_guid = 10; // Database GUID inline constexpr UCHAR HDR_repl_seq = 11; // Replication changelog sequence inline constexpr UCHAR HDR_max = 11; // Maximum HDR_clump value @@ -553,26 +554,22 @@ inline constexpr USHORT hdr_SQL_dialect_3 = 0x10; // 16 database SQL dialect 3 inline constexpr USHORT hdr_read_only = 0x20; // 32 Database is ReadOnly. If not set, DB is RW inline constexpr USHORT hdr_encrypted = 0x40; // 64 Database is encrypted -inline constexpr USHORT hdr_backup_mask = 0xC00; -inline constexpr USHORT hdr_shutdown_mask = 0x1080; -inline constexpr USHORT hdr_replica_mask = 0x6000; - -// Values for backup mask -inline constexpr USHORT hdr_nbak_normal = 0x000; // Normal mode. Changes are simply written to main files -inline constexpr USHORT hdr_nbak_stalled = 0x400; // 1024 Main files are locked. Changes are written to diff file -inline constexpr USHORT hdr_nbak_merge = 0x800; // 2048 Merging changes from diff file into main files -inline constexpr USHORT hdr_nbak_unknown = USHORT(~0); // State is unknown. Needs to be read from disk - -// Values for shutdown mask -inline constexpr USHORT hdr_shutdown_none = 0x0; -inline constexpr USHORT hdr_shutdown_multi = 0x80; -inline constexpr USHORT hdr_shutdown_full = 0x1000; -inline constexpr USHORT hdr_shutdown_single = 0x1080; - -// Values for replica mask -inline constexpr USHORT hdr_replica_none = 0x0000; -inline constexpr USHORT hdr_replica_read_only = 0x2000; -inline constexpr USHORT hdr_replica_read_write = 0x4000; +// Values for backup mode +inline constexpr UCHAR hdr_nbak_normal = 0; // Normal mode. Changes are simply written to main files +inline constexpr UCHAR hdr_nbak_stalled = 1; // Main files are locked. Changes are written to diff file +inline constexpr UCHAR hdr_nbak_merge = 2; // Merging changes from diff file into main files +inline constexpr UCHAR hdr_nbak_unknown = UCHAR(~0); // State is unknown. Needs to be read from disk + +// Values for shutdown mode +inline constexpr UCHAR hdr_shutdown_none = 0; // database is online +inline constexpr UCHAR hdr_shutdown_multi = 1; // multi-user shutdown +inline constexpr UCHAR hdr_shutdown_single = 2; // single-user shutdown +inline constexpr UCHAR hdr_shutdown_full = 3; // full shutdown + +// Values for replica mode +inline constexpr UCHAR hdr_replica_none = 0; // database is not a replica +inline constexpr UCHAR hdr_replica_read_only = 1; // read-only replica +inline constexpr UCHAR hdr_replica_read_write = 2; // read-write replica // Page Inventory Page diff --git a/src/jrd/ods_proto.h b/src/jrd/ods_proto.h index a65bf4756d3..019e723ea72 100644 --- a/src/jrd/ods_proto.h +++ b/src/jrd/ods_proto.h @@ -39,22 +39,9 @@ namespace Ods { ULONG maxRecsPerDP(ULONG page_size); ULONG maxIndices(ULONG page_size); - TraNumber getNT(const header_page* page); - TraNumber getOIT(const header_page* page); - TraNumber getOAT(const header_page* page); - TraNumber getOST(const header_page* page); - - void writeNT(header_page* page, TraNumber number); - void writeOIT(header_page* page, TraNumber number); - void writeOAT(header_page* page, TraNumber number); - void writeOST(header_page* page, TraNumber number); - TraNumber getTraNum(const void* ptr); void writeTraNum(void* ptr, TraNumber number, FB_SIZE_T header_size); - AttNumber getAttID(const header_page* page); - void writeAttID(header_page* page, AttNumber number); - } // namespace #endif //ODS_PROTO_H diff --git a/src/jrd/os/posix/unix.cpp b/src/jrd/os/posix/unix.cpp index 76071238def..5d41325a480 100644 --- a/src/jrd/os/posix/unix.cpp +++ b/src/jrd/os/posix/unix.cpp @@ -1225,7 +1225,7 @@ static bool raw_devices_validate_database(int desc, const PathName& file_name) } // Validate database header. Code lifted from PAG_header. - if (hp->hdr_header.pag_type != pag_header /*|| hp->hdr_sequence*/) + if (hp->hdr_header.pag_type != pag_header) goto quit; if (!Ods::isSupported(hp)) @@ -1240,10 +1240,8 @@ static bool raw_devices_validate_database(int desc, const PathName& file_name) quit: #ifdef DEV_BUILD - gds__log ("raw_devices_validate_database: %s -> %s%s\n", - file_name.c_str(), - retval ? "true" : "false", - retval && hp->hdr_sequence != 0 ? " (continuation file)" : ""); + gds__log ("raw_devices_validate_database: %s -> %s\n", + file_name.c_str(), retval ? "true" : "false"); #endif return retval; } diff --git a/src/jrd/pag.cpp b/src/jrd/pag.cpp index 3c7c6835171..0bac8c4f260 100644 --- a/src/jrd/pag.cpp +++ b/src/jrd/pag.cpp @@ -727,9 +727,7 @@ AttNumber PAG_attachment_id(thread_db* tdbb) CCH_MARK(tdbb, &window); - const AttNumber att_id = Ods::getAttID(header) + 1; - attachment->att_attachment_id = att_id; - Ods::writeAttID(header, att_id); + attachment->att_attachment_id = ++header->hdr_attachment_id; dbb->assignLatestAttachmentId(attachment->att_attachment_id); CCH_RELEASE(tdbb, &window); @@ -951,10 +949,10 @@ void PAG_header(thread_db* tdbb, bool info, const TriState newForceWrite) try { - const TraNumber next_transaction = Ods::getNT(header); - const TraNumber oldest_transaction = Ods::getOIT(header); - const TraNumber oldest_active = Ods::getOAT(header); - const TraNumber oldest_snapshot = Ods::getOST(header); + const TraNumber next_transaction = header->hdr_next_transaction; + const TraNumber oldest_transaction = header->hdr_oldest_transaction; + const TraNumber oldest_active = header->hdr_oldest_active; + const TraNumber oldest_snapshot = header->hdr_oldest_snapshot; if (next_transaction) { @@ -1035,26 +1033,11 @@ void PAG_header(thread_db* tdbb, bool info, const TriState newForceWrite) if (header->hdr_flags & hdr_no_reserve) dbb->dbb_flags |= DBB_no_reserve; - const USHORT sd_flags = header->hdr_flags & hdr_shutdown_mask; - if (sd_flags) - { - dbb->dbb_ast_flags |= DBB_shutdown; - if (sd_flags == hdr_shutdown_full) - dbb->dbb_ast_flags |= DBB_shutdown_full; - else if (sd_flags == hdr_shutdown_single) - dbb->dbb_ast_flags |= DBB_shutdown_single; - } + const auto shutMode = (shut_mode_t) header->hdr_shutdown_mode; + dbb->dbb_shutdown_mode.store(shutMode, std::memory_order_relaxed); - const USHORT replica_mode = header->hdr_flags & hdr_replica_mask; - if (replica_mode) - { - if (replica_mode == hdr_replica_read_only) - dbb->dbb_replica_mode = REPLICA_READ_ONLY; - else if (replica_mode == hdr_replica_read_write) - dbb->dbb_replica_mode = REPLICA_READ_WRITE; - else - fb_assert(false); - } + const auto replicaMode = (ReplicaMode) header->hdr_replica_mode; + dbb->dbb_replica_mode.store(replicaMode, std::memory_order_relaxed); // If database in backup lock state... if (!info && dbb->dbb_backup_manager->getState() != Ods::hdr_nbak_normal) @@ -1130,7 +1113,7 @@ void PAG_header_init(thread_db* tdbb) PIO_header(tdbb, temp_page, headerSize); const header_page* header = (header_page*) temp_page; - if (header->hdr_header.pag_type != pag_header || header->hdr_sequence) + if (header->hdr_header.pag_type != pag_header) ERR_post(Arg::Gds(isc_bad_db_format) << Arg::Str(attachment->att_filename)); const USHORT ods_version = header->hdr_ods_version & ~ODS_FIREBIRD_FLAG; @@ -1244,11 +1227,6 @@ void PAG_init2(thread_db* tdbb) memcpy(&dbb->dbb_sweep_interval, p + 2, sizeof(SLONG)); break; - case HDR_db_guid: - fb_assert(p[1] == Guid::SIZE); - dbb->dbb_guid = Guid(p + 2); - break; - case HDR_repl_seq: fb_assert(p[1] == sizeof(FB_UINT64)); memcpy(&dbb->dbb_repl_sequence, p + 2, sizeof(FB_UINT64)); @@ -1407,7 +1385,18 @@ void PAG_set_db_guid(thread_db* tdbb, const Guid& guid) * **************************************/ SET_TDBB(tdbb); - storeClump(tdbb, HDR_db_guid, Guid::SIZE, guid.getData()); + ensureDbWritable(tdbb); + + WIN window(HEADER_PAGE_NUMBER); + header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); + CCH_MARK_MUST_WRITE(tdbb, &window); + + const auto dbb = tdbb->getDatabase(); + + guid.copyTo(header->hdr_guid); + dbb->dbb_guid = guid; + + CCH_RELEASE(tdbb, &window); } @@ -1524,15 +1513,15 @@ void PAG_set_db_readonly(thread_db* tdbb, bool flag) // for att lock indefinitely. Attachment* att = tdbb->getAttachment(); if (att->att_attachment_id) - Ods::writeAttID(header, att->att_attachment_id); + header->hdr_attachment_id = att->att_attachment_id; // This is necessary as dbb's Next could be less than OAT. // And this is safe as we currently in exclusive attachment and // all executed transactions was read-only. - dbb->dbb_next_transaction = Ods::getNT(header); - dbb->dbb_oldest_transaction = Ods::getOIT(header); - dbb->dbb_oldest_active = Ods::getOAT(header); - dbb->dbb_oldest_snapshot = Ods::getOST(header); + dbb->dbb_next_transaction = header->hdr_next_transaction; + dbb->dbb_oldest_transaction = header->hdr_oldest_transaction; + dbb->dbb_oldest_active = header->hdr_oldest_active; + dbb->dbb_oldest_snapshot = header->hdr_oldest_snapshot; } CCH_MARK_MUST_WRITE(tdbb, &window); @@ -1569,20 +1558,18 @@ void PAG_set_db_replica(thread_db* tdbb, ReplicaMode mode) const auto dbb = tdbb->getDatabase(); - header->hdr_flags &= ~(hdr_replica_read_only | hdr_replica_read_write); - fb_assert((header->hdr_flags & hdr_replica_mask) == hdr_replica_none); - switch (mode) { case REPLICA_NONE: + header->hdr_replica_mode = hdr_replica_none; break; case REPLICA_READ_ONLY: - header->hdr_flags |= hdr_replica_read_only; + header->hdr_replica_mode = hdr_replica_read_only; break; case REPLICA_READ_WRITE: - header->hdr_flags |= hdr_replica_read_write; + header->hdr_replica_mode = hdr_replica_read_write; break; default: @@ -1591,7 +1578,7 @@ void PAG_set_db_replica(thread_db* tdbb, ReplicaMode mode) CCH_RELEASE(tdbb, &window); - dbb->dbb_replica_mode = mode; + dbb->dbb_replica_mode.store(mode, std::memory_order_relaxed); } diff --git a/src/jrd/shut.cpp b/src/jrd/shut.cpp index 3801e7055db..9264af0c28d 100644 --- a/src/jrd/shut.cpp +++ b/src/jrd/shut.cpp @@ -94,36 +94,31 @@ bool SHUT_blocking_ast(thread_db* tdbb, bool ast) const SSHORT flag = data.data_items.flag; const SSHORT delay = data.data_items.delay; - const int shut_mode = flag & isc_dpb_shut_mode_mask; - // Delay of -1 means we're going online if (delay == -1) { dbb->dbb_ast_flags &= ~(DBB_shut_attach | DBB_shut_tran | DBB_shut_force); + auto shutMode = shut_mode_online; - if (shut_mode) + switch (flag & isc_dpb_shut_mode_mask) { - dbb->dbb_ast_flags &= ~(DBB_shutdown | DBB_shutdown_single | DBB_shutdown_full); - - switch (shut_mode) - { - case isc_dpb_shut_normal: - break; - case isc_dpb_shut_multi: - dbb->dbb_ast_flags |= DBB_shutdown; - break; - case isc_dpb_shut_single: - dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_single; - break; - case isc_dpb_shut_full: - dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_full; - break; - default: - fb_assert(false); - } + case isc_dpb_shut_normal: + break; + case isc_dpb_shut_multi: + shutMode = shut_mode_multi; + break; + case isc_dpb_shut_single: + shutMode = shut_mode_single; + break; + case isc_dpb_shut_full: + shutMode = shut_mode_full; + break; + default: + fb_assert(false); } + dbb->dbb_shutdown_mode.store(shutMode, std::memory_order_relaxed); return false; } @@ -167,7 +162,7 @@ void SHUT_database(thread_db* tdbb, SSHORT flag, SSHORT delay, Sync* guard) ERR_punt(); } - const int shut_mode = flag & isc_dpb_shut_mode_mask; + const int shut_mode = (flag & isc_dpb_shut_mode_mask); // Check if requested shutdown mode is valid // Note that if we are already in requested mode we just return true. @@ -176,36 +171,36 @@ void SHUT_database(thread_db* tdbb, SSHORT flag, SSHORT delay, Sync* guard) switch (shut_mode) { case isc_dpb_shut_full: - if (dbb->dbb_ast_flags & DBB_shutdown_full) + if (dbb->isShutdown(shut_mode_full)) { same_mode(dbb); return; } break; - case isc_dpb_shut_multi: - if (dbb->dbb_ast_flags & (DBB_shutdown_full | DBB_shutdown_single)) + case isc_dpb_shut_single: + if (dbb->isShutdown(shut_mode_full)) { bad_mode(dbb); } - if (dbb->dbb_ast_flags & DBB_shutdown) + if (dbb->isShutdown(shut_mode_single)) { same_mode(dbb); return; } break; - case isc_dpb_shut_single: - if (dbb->dbb_ast_flags & DBB_shutdown_full) + case isc_dpb_shut_multi: + if (dbb->isShutdown(shut_mode_full) || dbb->isShutdown(shut_mode_single)) { bad_mode(dbb); } - if (dbb->dbb_ast_flags & DBB_shutdown_single) + if (dbb->isShutdown(shut_mode_multi)) { same_mode(dbb); return; } break; case isc_dpb_shut_normal: - if (!(dbb->dbb_ast_flags & DBB_shutdown)) + if (!dbb->isShutdown()) { same_mode(dbb); return; @@ -237,7 +232,6 @@ void SHUT_database(thread_db* tdbb, SSHORT flag, SSHORT delay, Sync* guard) if (exclusive) { - // Ensure we have the proper DBB_shutdown_* flags in place shutdown(tdbb, flag, false); } else @@ -286,22 +280,22 @@ void SHUT_database(thread_db* tdbb, SSHORT flag, SSHORT delay, Sync* guard) dbb->dbb_ast_flags &= ~(DBB_shut_force | DBB_shut_attach | DBB_shut_tran); WIN window(HEADER_PAGE_NUMBER); - Ods::header_page* const header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); + const auto header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); CCH_MARK_MUST_WRITE(tdbb, &window); // Set appropriate shutdown mode in database header - header->hdr_flags &= ~Ods::hdr_shutdown_mask; switch (shut_mode) { case isc_dpb_shut_normal: + header->hdr_shutdown_mode = Ods::hdr_shutdown_none; break; case isc_dpb_shut_multi: - header->hdr_flags |= Ods::hdr_shutdown_multi; + header->hdr_shutdown_mode = Ods::hdr_shutdown_multi; break; case isc_dpb_shut_single: - header->hdr_flags |= Ods::hdr_shutdown_single; + header->hdr_shutdown_mode = Ods::hdr_shutdown_single; break; case isc_dpb_shut_full: - header->hdr_flags |= Ods::hdr_shutdown_full; + header->hdr_shutdown_mode = Ods::hdr_shutdown_full; break; default: fb_assert(false); @@ -362,42 +356,42 @@ void SHUT_online(thread_db* tdbb, SSHORT flag, Sync* guard) switch (shut_mode) { case isc_dpb_shut_normal: - if (!(dbb->dbb_ast_flags & DBB_shutdown)) + if (!dbb->isShutdown()) { same_mode(dbb); // normal -> normal return; } break; case isc_dpb_shut_multi: - if (!(dbb->dbb_ast_flags & DBB_shutdown)) + if (!dbb->isShutdown()) { bad_mode(dbb); // normal -> multi } - if (!(dbb->dbb_ast_flags & DBB_shutdown_full) && !(dbb->dbb_ast_flags & DBB_shutdown_single)) + if (dbb->isShutdown(shut_mode_multi)) { same_mode(dbb); // multi -> multi return; } break; case isc_dpb_shut_single: - if (dbb->dbb_ast_flags & DBB_shutdown_single) + if (dbb->isShutdown(shut_mode_single)) { - same_mode(dbb); //single -> single + same_mode(dbb); // single -> single return; } - if (!(dbb->dbb_ast_flags & DBB_shutdown_full)) + if (!dbb->isShutdown(shut_mode_full)) { bad_mode(dbb); // !full -> single } break; case isc_dpb_shut_full: - if (dbb->dbb_ast_flags & DBB_shutdown_full) + if (dbb->isShutdown(shut_mode_full)) { same_mode(dbb); // full -> full return; } bad_mode(dbb); - default: // isc_dpb_shut_full + default: bad_mode(dbb); // unexpected mode } @@ -415,22 +409,22 @@ void SHUT_online(thread_db* tdbb, SSHORT flag, Sync* guard) // Reset shutdown flag on database header page WIN window(HEADER_PAGE_NUMBER); - Ods::header_page* const header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); + const auto header = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); CCH_MARK_MUST_WRITE(tdbb, &window); // Set appropriate shutdown mode in database header - header->hdr_flags &= ~Ods::hdr_shutdown_mask; switch (shut_mode) { case isc_dpb_shut_normal: + header->hdr_shutdown_mode = Ods::hdr_shutdown_none; break; case isc_dpb_shut_multi: - header->hdr_flags |= Ods::hdr_shutdown_multi; + header->hdr_shutdown_mode = Ods::hdr_shutdown_multi; break; case isc_dpb_shut_single: - header->hdr_flags |= Ods::hdr_shutdown_single; + header->hdr_shutdown_mode = Ods::hdr_shutdown_single; break; case isc_dpb_shut_full: - header->hdr_flags |= Ods::hdr_shutdown_full; + header->hdr_shutdown_mode = Ods::hdr_shutdown_full; break; default: fb_assert(false); @@ -446,7 +440,7 @@ void SHUT_online(thread_db* tdbb, SSHORT flag, Sync* guard) static void check_backup_state(thread_db* tdbb) { - Database* const dbb = tdbb->getDatabase(); + const auto dbb = tdbb->getDatabase(); BackupManager::StateReadGuard stateGuard(tdbb); @@ -472,7 +466,7 @@ static bool notify_shutdown(thread_db* tdbb, SSHORT flag, SSHORT delay, Sync* gu * flags and delay via lock data. * **************************************/ - Database* const dbb = tdbb->getDatabase(); + const auto dbb = tdbb->getDatabase(); shutdown_data data; data.data_items.flag = flag; @@ -506,29 +500,31 @@ static bool shutdown(thread_db* tdbb, SSHORT flag, bool force) * Initiate database shutdown. * **************************************/ - Database* const dbb = tdbb->getDatabase(); + const auto dbb = tdbb->getDatabase(); // Mark database and all active attachments as shutdown - dbb->dbb_ast_flags &= ~(DBB_shutdown | DBB_shutdown_single | DBB_shutdown_full); + auto shutMode = shut_mode_online; switch (flag & isc_dpb_shut_mode_mask) { case isc_dpb_shut_normal: break; case isc_dpb_shut_multi: - dbb->dbb_ast_flags |= DBB_shutdown; + shutMode = shut_mode_multi; break; case isc_dpb_shut_single: - dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_single; + shutMode = shut_mode_single; break; case isc_dpb_shut_full: - dbb->dbb_ast_flags |= DBB_shutdown | DBB_shutdown_full; + shutMode = shut_mode_full; break; default: fb_assert(false); } + dbb->dbb_shutdown_mode.store(shutMode, std::memory_order_relaxed); + if (force) { JRD_shutdown_attachments(dbb); diff --git a/src/jrd/tpc.cpp b/src/jrd/tpc.cpp index 79a5115055b..01625cba4a0 100644 --- a/src/jrd/tpc.cpp +++ b/src/jrd/tpc.cpp @@ -303,16 +303,16 @@ void TipCache::loadInventoryPages(thread_db* tdbb, GlobalTpcHeader* header) const TraNumber hdr_oldest = dbb->dbb_oldest_transaction; #else WIN window(HEADER_PAGE_NUMBER); - const Ods::header_page* header_page = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header); - const TraNumber hdr_oldest_transaction = Ods::getOIT(header_page); - const TraNumber hdr_next_transaction = Ods::getNT(header_page); - const AttNumber hdr_attachment_id = Ods::getAttID(header_page); + const auto header_page = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header); + const TraNumber hdr_next_transaction = header_page->hdr_next_transaction; + const TraNumber hdr_oldest_transaction = header_page->hdr_oldest_transaction; + const AttNumber hdr_attachment_id = header_page->hdr_attachment_id; CCH_RELEASE(tdbb, &window); #endif + header->latest_transaction_id.store(hdr_next_transaction, std::memory_order_relaxed); header->oldest_transaction.store(hdr_oldest_transaction, std::memory_order_relaxed); header->latest_attachment_id.store(hdr_attachment_id, std::memory_order_relaxed); - header->latest_transaction_id.store(hdr_next_transaction, std::memory_order_relaxed); // Check if TIP has any interesting transactions. // At database creation time, it doesn't and the code below breaks @@ -447,8 +447,8 @@ void TipCache::StatusBlockData::clear(thread_db* tdbb) else { WIN window(HEADER_PAGE_NUMBER); - const Ods::header_page* header_page = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header); - oldest = Ods::getOIT(header_page); + const auto header_page = (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header); + oldest = header_page->hdr_oldest_transaction; CCH_RELEASE(tdbb, &window); } } diff --git a/src/jrd/tra.cpp b/src/jrd/tra.cpp index a8149d79889..293010812d2 100644 --- a/src/jrd/tra.cpp +++ b/src/jrd/tra.cpp @@ -331,8 +331,8 @@ bool TRA_cleanup(thread_db* tdbb) WIN window(HEADER_PAGE_NUMBER); const header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header); - const TraNumber ceiling = Ods::getNT(header); - const TraNumber active = Ods::getOAT(header); + const TraNumber ceiling = header->hdr_next_transaction; + const TraNumber active = header->hdr_oldest_active; CCH_RELEASE(tdbb, &window); if (ceiling == 0) @@ -754,12 +754,12 @@ void TRA_header_write(thread_db* tdbb, Database* dbb, TraNumber number) if (!number || dbb->dbb_last_header_write < number) { WIN window(HEADER_PAGE_NUMBER); - header_page* header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); + const auto header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); - const TraNumber next_transaction = Ods::getNT(header); - const TraNumber oldest_active = Ods::getOAT(header); - const TraNumber oldest_transaction = Ods::getOIT(header); - const TraNumber oldest_snapshot = Ods::getOST(header); + const TraNumber next_transaction = header->hdr_next_transaction; + const TraNumber oldest_transaction = header->hdr_oldest_transaction; + const TraNumber oldest_active = header->hdr_oldest_active; + const TraNumber oldest_snapshot = header->hdr_oldest_snapshot; if (next_transaction) { @@ -779,16 +779,16 @@ void TRA_header_write(thread_db* tdbb, Database* dbb, TraNumber number) CCH_MARK_MUST_WRITE(tdbb, &window); if (dbb->dbb_next_transaction > next_transaction) - Ods::writeNT(header, dbb->dbb_next_transaction); - - if (dbb->dbb_oldest_active > oldest_active) - Ods::writeOAT(header, dbb->dbb_oldest_active); + header->hdr_next_transaction = dbb->dbb_next_transaction; if (dbb->dbb_oldest_transaction > oldest_transaction) - Ods::writeOIT(header, dbb->dbb_oldest_transaction); + header->hdr_oldest_transaction = dbb->dbb_oldest_transaction; + + if (dbb->dbb_oldest_active > oldest_active) + header->hdr_oldest_active = dbb->dbb_oldest_active; if (dbb->dbb_oldest_snapshot > oldest_snapshot) - Ods::writeOST(header, dbb->dbb_oldest_snapshot); + header->hdr_oldest_snapshot = dbb->dbb_oldest_snapshot; } CCH_RELEASE(tdbb, &window); @@ -915,12 +915,12 @@ void TRA_update_counters(thread_db* tdbb, Database* dbb) } WIN window(HEADER_PAGE_NUMBER); - header_page* header = (header_page*)CCH_FETCH(tdbb, &window, LCK_write, pag_header); + const auto header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); - const TraNumber next_transaction = Ods::getNT(header); - const TraNumber oldest_transaction = Ods::getOIT(header); - const TraNumber oldest_active = Ods::getOAT(header); - const TraNumber oldest_snapshot = Ods::getOST(header); + const TraNumber next_transaction = header->hdr_next_transaction; + const TraNumber oldest_transaction = header->hdr_oldest_transaction; + const TraNumber oldest_active = header->hdr_oldest_active; + const TraNumber oldest_snapshot = header->hdr_oldest_snapshot; fb_assert(dbb->dbb_next_transaction <= next_transaction); @@ -931,17 +931,17 @@ void TRA_update_counters(thread_db* tdbb, Database* dbb) { CCH_MARK_MUST_WRITE(tdbb, &window); - if (dbb->dbb_oldest_active > oldest_active) - Ods::writeOAT(header, dbb->dbb_oldest_active); + if (dbb->dbb_next_transaction > next_transaction) + header->hdr_next_transaction = dbb->dbb_next_transaction; if (dbb->dbb_oldest_transaction > oldest_transaction) - Ods::writeOIT(header, dbb->dbb_oldest_transaction); + header->hdr_oldest_transaction = dbb->dbb_oldest_transaction; - if (dbb->dbb_oldest_snapshot > oldest_snapshot) - Ods::writeOST(header, dbb->dbb_oldest_snapshot); + if (dbb->dbb_oldest_active > oldest_active) + header->hdr_oldest_active = dbb->dbb_oldest_active; - if (dbb->dbb_next_transaction > next_transaction) - Ods::writeNT(header, dbb->dbb_next_transaction); + if (dbb->dbb_oldest_snapshot > oldest_snapshot) + header->hdr_oldest_snapshot = dbb->dbb_oldest_snapshot; } CCH_RELEASE(tdbb, &window); @@ -1920,10 +1920,10 @@ void TRA_sweep(thread_db* tdbb) WIN window(HEADER_PAGE_NUMBER); header_page* const header = (header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header); - if (Ods::getOIT(header) < --transaction_oldest_active) + if (header->hdr_oldest_transaction < --transaction_oldest_active) { CCH_MARK_MUST_WRITE(tdbb, &window); - Ods::writeOIT(header, MIN(active, transaction_oldest_active)); + header->hdr_oldest_transaction = MIN(active, transaction_oldest_active); } traceSweep.update(header); @@ -2102,10 +2102,10 @@ static header_page* bump_transaction_id(thread_db* tdbb, WIN* window, bool dontW window->win_page = HEADER_PAGE_NUMBER; header_page* header = (header_page*) CCH_FETCH(tdbb, window, LCK_write, pag_header); - const TraNumber next_transaction = Ods::getNT(header); - const TraNumber oldest_active = Ods::getOAT(header); - const TraNumber oldest_transaction = Ods::getOIT(header); - const TraNumber oldest_snapshot = Ods::getOST(header); + const TraNumber next_transaction = header->hdr_next_transaction; + const TraNumber oldest_transaction = header->hdr_oldest_transaction; + const TraNumber oldest_active = header->hdr_oldest_active; + const TraNumber oldest_snapshot = header->hdr_oldest_snapshot; // Before incrementing the next transaction Id, make sure the current one is valid if (next_transaction) @@ -2154,17 +2154,16 @@ static header_page* bump_transaction_id(thread_db* tdbb, WIN* window, bool dontW //dbb->assignLatestTransactionId(number); dbb->dbb_next_transaction = number; + header->hdr_next_transaction = number; - Ods::writeNT(header, number); + if (dbb->dbb_oldest_transaction > oldest_transaction) + header->hdr_oldest_transaction = dbb->dbb_oldest_transaction; if (dbb->dbb_oldest_active > oldest_active) - Ods::writeOAT(header, dbb->dbb_oldest_active); - - if (dbb->dbb_oldest_transaction > oldest_transaction) - Ods::writeOIT(header, dbb->dbb_oldest_transaction); + header->hdr_oldest_active = dbb->dbb_oldest_active; if (dbb->dbb_oldest_snapshot > oldest_snapshot) - Ods::writeOST(header, dbb->dbb_oldest_snapshot); + header->hdr_oldest_snapshot = dbb->dbb_oldest_snapshot; return header; } @@ -2625,8 +2624,8 @@ static void retain_context(thread_db* tdbb, jrd_tra* transaction, bool commit, i const bool dontWrite = (dbb->dbb_flags & DBB_shared) && (transaction->tra_flags & TRA_readonly); - const header_page* const header = bump_transaction_id(tdbb, &window, dontWrite); - new_number = Ods::getNT(header); + const auto header = bump_transaction_id(tdbb, &window, dontWrite); + new_number = header->hdr_next_transaction; } #endif @@ -3527,10 +3526,10 @@ static void transaction_start(thread_db* tdbb, jrd_tra* trans) const bool dontWrite = (dbb->dbb_flags & DBB_shared) && (trans->tra_flags & TRA_readonly); - const header_page* header = bump_transaction_id(tdbb, &window, dontWrite); - number = Ods::getNT(header); - oldest = Ods::getOIT(header); - oldest_active = Ods::getOAT(header); + const auto header = bump_transaction_id(tdbb, &window, dontWrite); + number = header->hdr_next_transaction; + oldest = header->hdr_oldest_transaction; + oldest_active = header->hdr_oldest_active; } // oldest (OIT) > oldest_active (OAT) if OIT was advanced by sweep diff --git a/src/jrd/trace/TraceObjects.h b/src/jrd/trace/TraceObjects.h index 31c70778482..e24ef464ceb 100644 --- a/src/jrd/trace/TraceObjects.h +++ b/src/jrd/trace/TraceObjects.h @@ -771,10 +771,10 @@ class TraceSweepImpl : void update(const Ods::header_page* header) { - m_oit = Ods::getOIT(header); - m_ost = Ods::getOST(header); - m_oat = Ods::getOAT(header); - m_next = Ods::getNT(header); + m_oit = header->hdr_oldest_transaction; + m_ost = header->hdr_oldest_snapshot; + m_oat = header->hdr_oldest_active; + m_next = header->hdr_next_transaction; } void setPerf(Firebird::PerformanceInfo* perf) diff --git a/src/jrd/validation.cpp b/src/jrd/validation.cpp index ec0f4981771..e441b0246fd 100644 --- a/src/jrd/validation.cpp +++ b/src/jrd/validation.cpp @@ -1615,11 +1615,10 @@ void Validation::walk_database() WIN window(DB_PAGE_SPACE, -1); header_page* page = 0; fetch_page(true, HEADER_PAGE, pag_header, &window, &page); - TraNumber next = vdr_max_transaction = Ods::getNT(page); + const TraNumber next = vdr_max_transaction = page->hdr_next_transaction; - if (vdr_flags & VDR_online) { + if (vdr_flags & VDR_online) release_page(&window); - } if (!(vdr_flags & VDR_partial)) { @@ -3071,7 +3070,7 @@ Validation::RTN Validation::walk_relation(jrd_rel* relation) WIN window(DB_PAGE_SPACE, -1); header_page* page = NULL; fetch_page(false, HEADER_PAGE, pag_header, &window, &page); - vdr_max_transaction = Ods::getNT(page); + vdr_max_transaction = page->hdr_next_transaction; release_page(&window); } diff --git a/src/utilities/gstat/ppg.cpp b/src/utilities/gstat/ppg.cpp index 40b773e03eb..1ca5dc96f22 100644 --- a/src/utilities/gstat/ppg.cpp +++ b/src/utilities/gstat/ppg.cpp @@ -62,12 +62,11 @@ void PPG_print_header(const header_page* header, bool nocreation, Firebird::Util uSvc->printf(false, "\tPage size\t\t%d\n", header->hdr_page_size); uSvc->printf(false, "\tODS version\t\t%d.%d\n", header->hdr_ods_version & ~ODS_FIREBIRD_FLAG, header->hdr_ods_minor); - uSvc->printf(false, "\tOldest transaction\t%" SQUADFORMAT"\n", Ods::getOIT(header)); - uSvc->printf(false, "\tOldest active\t\t%" SQUADFORMAT"\n", Ods::getOAT(header)); - uSvc->printf(false, "\tOldest snapshot\t\t%" SQUADFORMAT"\n", Ods::getOST(header)); - uSvc->printf(false, "\tNext transaction\t%" SQUADFORMAT"\n", Ods::getNT(header)); - uSvc->printf(false, "\tSequence number\t\t%d\n", header->hdr_sequence); - uSvc->printf(false, "\tNext attachment ID\t%" SQUADFORMAT"\n", Ods::getAttID(header)); + uSvc->printf(false, "\tOldest transaction\t%" SQUADFORMAT"\n", header->hdr_oldest_transaction); + uSvc->printf(false, "\tOldest active\t\t%" SQUADFORMAT"\n", header->hdr_oldest_active); + uSvc->printf(false, "\tOldest snapshot\t\t%" SQUADFORMAT"\n", header->hdr_oldest_snapshot); + uSvc->printf(false, "\tNext transaction\t%" SQUADFORMAT"\n", header->hdr_next_transaction); + uSvc->printf(false, "\tNext attachment ID\t%" SQUADFORMAT"\n", header->hdr_attachment_id); Firebird::DbImplementation imp(header); uSvc->printf(false, "\tImplementation\t\tHW=%s %s-endian OS=%s CC=%s\n", @@ -89,6 +88,9 @@ void PPG_print_header(const header_page* header, bool nocreation, Firebird::Util if (!nocreation) { + const Guid guid(header->hdr_guid); + uSvc->printf(false, "\tDatabase GUID:\t%s\n", guid.toString().c_str()); + struct tm time; isc_decode_timestamp(reinterpret_cast(header->hdr_creation_date), &time); @@ -97,63 +99,70 @@ void PPG_print_header(const header_page* header, bool nocreation, Firebird::Util time.tm_hour, time.tm_min, time.tm_sec); } - if (const auto flags = header->hdr_flags) + uSvc->printf(false, "\tAttributes\t\t"); + const auto flags = header->hdr_flags; + const auto nbakMode = header->hdr_backup_mode; + const auto shutMode = header->hdr_shutdown_mode; + const auto replMode = header->hdr_replica_mode; + + if (flags || nbakMode || shutMode || replMode) { - int flag_count = 0; + int count = 0; - uSvc->printf(false, "\tAttributes\t\t"); if (flags & hdr_force_write) { uSvc->printf(false, "force write"); - flag_count++; + count++; } + if (flags & hdr_no_reserve) { - if (flag_count++) + if (count++) uSvc->printf(false, ", "); uSvc->printf(false, "no reserve"); } -/* - if (flags & hdr_disable_cache) - { - if (flag_count++) - uSvc->printf(false, ", "); - uSvc->printf(false, "shared cache disabled"); - } -*/ + if (flags & hdr_active_shadow) { - if (flag_count++) + if (count++) uSvc->printf(false, ", "); uSvc->printf(false, "active shadow"); } if (flags & hdr_encrypted) { - if (flag_count++) + if (count++) uSvc->printf(false, ", "); uSvc->printf(false, "encrypted"); } if (flags & hdr_crypt_process) { - if (flag_count++) + if (count++) uSvc->printf(false, ", "); uSvc->printf(false, "crypt process"); } if (flags & (hdr_encrypted | hdr_crypt_process)) { - if (flag_count++) + if (count++) uSvc->printf(false, ", "); uSvc->printf(false, "plugin %s", header->hdr_crypt_plugin); } - if (flags & hdr_shutdown_mask) + if (flags & hdr_read_only) + { + if (count++) + uSvc->printf(false, ", "); + uSvc->printf(false, "read only"); + } + + if (shutMode) { - if (flag_count++) + if (count++) uSvc->printf(false, ", "); - switch (flags & hdr_shutdown_mask) + + switch (shutMode) { case hdr_shutdown_multi: uSvc->printf(false, "multi-user maintenance"); @@ -165,22 +174,16 @@ void PPG_print_header(const header_page* header, bool nocreation, Firebird::Util uSvc->printf(false, "full shutdown"); break; default: - uSvc->printf(false, "wrong shutdown state %d", flags & hdr_shutdown_mask); + uSvc->printf(false, "wrong shutdown state %d", (int) shutMode); } } - if (flags & hdr_read_only) + if (nbakMode) { - if (flag_count++) + if (count++) uSvc->printf(false, ", "); - uSvc->printf(false, "read only"); - } - if (flags & hdr_backup_mask) - { - if (flag_count++) - uSvc->printf(false, ", "); - switch (flags & hdr_backup_mask) + switch (nbakMode) { case Ods::hdr_nbak_stalled: uSvc->printf(false, "backup lock"); @@ -189,15 +192,16 @@ void PPG_print_header(const header_page* header, bool nocreation, Firebird::Util uSvc->printf(false, "backup merge"); break; default: - uSvc->printf(false, "wrong backup state %d", flags & hdr_backup_mask); + uSvc->printf(false, "wrong backup state %d", (int) nbakMode); } } - if (flags & hdr_replica_mask) + if (replMode) { - if (flag_count++) + if (count++) uSvc->printf(false, ", "); - switch (flags & hdr_replica_mask) + + switch (replMode) { case Ods::hdr_replica_read_only: uSvc->printf(false, "read-only replica"); @@ -206,7 +210,7 @@ void PPG_print_header(const header_page* header, bool nocreation, Firebird::Util uSvc->printf(false, "read-write replica"); break; default: - uSvc->printf(false, "wrong replica state %d", flags & hdr_replica_mask); + uSvc->printf(false, "wrong replica state %d", (int) replMode); } } @@ -262,14 +266,6 @@ void PPG_print_header(const header_page* header, bool nocreation, Firebird::Util uSvc->printf(false, "\tCrypt checksum:\t%*.*s\n", p[1], p[1], p + 2); break; - case HDR_db_guid: - { - fb_assert(p[1] == Guid::SIZE); - const Guid guid(p + 2); - uSvc->printf(false, "\tDatabase GUID:\t%s\n", guid.toString().c_str()); - break; - } - case HDR_repl_seq: { FB_UINT64 sequence; diff --git a/src/utilities/nbackup/nbackup.cpp b/src/utilities/nbackup/nbackup.cpp index 42ee84996f0..2038c663192 100644 --- a/src/utilities/nbackup/nbackup.cpp +++ b/src/utilities/nbackup/nbackup.cpp @@ -849,11 +849,9 @@ void NBackup::fixup_database(bool repl_seq, bool set_readonly) if (read_file(dbase, header, size) != size) status_exception::raise(Arg::Gds(isc_nbackup_err_eofdb) << dbname.c_str()); - const auto org_flags = header->hdr_flags; const auto page_size = header->hdr_page_size; - const int backup_state = org_flags & Ods::hdr_backup_mask; - if (backup_state != Ods::hdr_nbak_stalled) + if (header->hdr_backup_mode != Ods::hdr_nbak_stalled) { status_exception::raise(Arg::Gds(isc_nbackup_fixup_wrongstate) << dbname.c_str() << Arg::Num(Ods::hdr_nbak_stalled)); @@ -861,6 +859,9 @@ void NBackup::fixup_database(bool repl_seq, bool set_readonly) if (!repl_seq) { + // Replace existing database GUID with a regenerated one + Guid::generate().copyTo(header->hdr_guid); + size = page_size; header = reinterpret_cast(header_buffer.getBuffer(size)); @@ -873,31 +874,25 @@ void NBackup::fixup_database(bool repl_seq, bool set_readonly) const auto end = (UCHAR*) header + header->hdr_page_size; while (p < end && *p != Ods::HDR_end) { - if (*p == Ods::HDR_db_guid) - { - // Replace existing database GUID with a regenerated one - fb_assert(p[1] == Guid::SIZE); - Guid::generate().copyTo(p + 2); - } - else if (*p == Ods::HDR_repl_seq) + if (*p == Ods::HDR_repl_seq) { // Reset the sequence counter const FB_UINT64 sequence = 0; fb_assert(p[1] == sizeof(sequence)); memcpy(p + 2, &sequence, sizeof(sequence)); + break; } p += p[1] + 2; } } - // Update the flags and write the header page back + // Update the backup mode and flags, write the header page back - const auto new_flags = - (org_flags & ~Ods::hdr_backup_mask) | Ods::hdr_nbak_normal | - (set_readonly ? Ods::hdr_read_only : 0); + header->hdr_backup_mode = Ods::hdr_nbak_normal; - header->hdr_flags = new_flags; + if (set_readonly) + header->hdr_flags |= Ods::hdr_read_only; seek_file(dbase, 0); write_file(dbase, header, size); @@ -1364,7 +1359,7 @@ void NBackup::backup_database(int level, const string& guidStr, const PathName& Arg::Num(ODS_CURRENT)); } - if ((header->hdr_flags & Ods::hdr_backup_mask) != Ods::hdr_nbak_stalled) + if (header->hdr_backup_mode != Ods::hdr_nbak_stalled) status_exception::raise(Arg::Gds(isc_nbackup_db_notlock) << Arg::Num(header->hdr_flags)); Array page_buffer; diff --git a/src/utilities/rebuild/rebuild.cpp b/src/utilities/rebuild/rebuild.cpp index 8d8d1cadb2f..48dbd97967f 100644 --- a/src/utilities/rebuild/rebuild.cpp +++ b/src/utilities/rebuild/rebuild.cpp @@ -924,7 +924,6 @@ static void print_db_header( FILE* file, const header_page* header) fprintf(file, " Data pages per pointer page\t%ld\n", gdbb->tdbb_database->dbb_dp_per_pp); fprintf(file, " Max records per page\t%ld\n", gdbb->tdbb_database->dbb_max_records); - //fprintf (" Sequence number %d\n", header->hdr_sequence); //fprintf (" Creation date \n", header->hdr_creation_date); fprintf(file, " Next attachment ID\t\t%ld\n", header->hdr_attachment_id); @@ -953,50 +952,12 @@ static void print_db_header( FILE* file, const header_page* header) case HDR_root_file_name: fprintf(file, "\tRoot file name: %*s\n", p[1], p + 2); break; -/* - case HDR_journal_server: - fprintf(file, "\tJournal server: %*s\n", p[1], p + 2); - break; -*/ - case HDR_file: - fprintf(file, "\tContinuation file: %*s\n", p[1], p + 2); - break; - case HDR_last_page: - memcpy(&number, p + 2, sizeof(number)); - fprintf(file, "\tLast logical page: %ld\n", number); - break; -/* - case HDR_unlicensed: - memcpy(&number, p + 2, sizeof(number)); - fprintf(file, "\tUnlicensed accesses: %ld\n", number); - break; -*/ case HDR_sweep_interval: memcpy(&number, p + 2, sizeof(number)); fprintf(file, "\tSweep interval: %ld\n", number); break; -/* - case HDR_log_name: - fprintf(file, "\tReplay logging file: %*s\n", p[1], p + 2); - break; - - case HDR_journal_file: - fprintf(file, "\tJournal file: %*s\n", p[1], p + 2); - break; -*/ - case HDR_password_file_key: - fprintf(file, "\tPassword file key: (can't print)\n"); - break; -/* - case HDR_backup_info: - fprintf(file, "\tBackup info: (can't print)\n"); - break; - case HDR_cache_file: - fprintf(file, "\tShared cache file: %*s\n", p[1], p + 2); - break; -*/ default: fprintf(file, "\tUnrecognized option %d, length %d\n", p[0], p[1]); }