diff --git a/src/jrd/btr.cpp b/src/jrd/btr.cpp index 71d5e6224cd..6e490f8365e 100644 --- a/src/jrd/btr.cpp +++ b/src/jrd/btr.cpp @@ -924,12 +924,11 @@ bool BTR_delete_index(thread_db* tdbb, WIN* window, USHORT id) { index_root_page::irt_repeat* irt_desc = root->irt_rpt + id; CCH_MARK(tdbb, window); - const PageNumber next(window->win_page.getPageSpaceID(), irt_desc->getRoot()); - tree_exists = (irt_desc->getRoot() != 0); + const PageNumber next(window->win_page.getPageSpaceID(), irt_desc->irt_root); + tree_exists = !irt_desc->isEmpty(); // remove the pointer to the top-level index page before we delete it - irt_desc->setRoot(0); - irt_desc->irt_flags = 0; + irt_desc->setEmpty(); const PageNumber prior = window->win_page; const USHORT relation_id = root->irt_relation; @@ -962,11 +961,11 @@ bool BTR_description(thread_db* tdbb, jrd_rel* relation, index_root_page* root, const index_root_page::irt_repeat* irt_desc = &root->irt_rpt[id]; - if (irt_desc->getRoot() == 0) + if (irt_desc->isEmpty()) return false; idx->idx_id = id; - idx->idx_root = irt_desc->getRoot(); + idx->idx_root = irt_desc->irt_root; idx->idx_count = irt_desc->irt_keys; idx->idx_flags = irt_desc->irt_flags; idx->idx_runtime_flags = 0; @@ -1451,7 +1450,7 @@ void BTR_insert(thread_db* tdbb, WIN* root_window, index_insertion* insertion) // update the index root page. Oh boy. index_root_page* root = (index_root_page*) CCH_FETCH(tdbb, root_window, LCK_write, pag_root); - window.win_page = root->irt_rpt[idx->idx_id].getRoot(); + window.win_page = root->irt_rpt[idx->idx_id].irt_root; bucket = (btree_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_index); if (window.win_page.getPageNum() != idx->idx_root) @@ -1501,7 +1500,7 @@ void BTR_insert(thread_db* tdbb, WIN* root_window, index_insertion* insertion) BUGCHECK(204); // msg 204 index inconsistent } - window.win_page = root->irt_rpt[idx->idx_id].getRoot(); + window.win_page = root->irt_rpt[idx->idx_id].irt_root; bucket = (btree_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_index); key.key_length = ret_key.key_length; memcpy(key.key_data, ret_key.key_data, ret_key.key_length); @@ -2124,18 +2123,18 @@ bool BTR_next_index(thread_db* tdbb, jrd_rel* relation, jrd_tra* transaction, in for (; id < root->irt_count; ++id) { const index_root_page::irt_repeat* irt_desc = root->irt_rpt + id; - if (irt_desc->getTransaction() && transaction) + const TraNumber inProgressTrans = irt_desc->inProgress(); + if (inProgressTrans && transaction) { - const TraNumber trans = irt_desc->getTransaction(); CCH_RELEASE(tdbb, window); - const int trans_state = TRA_wait(tdbb, transaction, trans, jrd_tra::tra_wait); + const int trans_state = TRA_wait(tdbb, transaction, inProgressTrans, jrd_tra::tra_wait); if ((trans_state == tra_dead) || (trans_state == tra_committed)) { // clean up this left-over index root = (index_root_page*) CCH_FETCH(tdbb, window, LCK_write, pag_root); irt_desc = root->irt_rpt + id; - if (irt_desc->getTransaction() == trans) + if (irt_desc->inProgress() == inProgressTrans) BTR_delete_index(tdbb, window, id); else CCH_RELEASE(tdbb, window); @@ -2359,7 +2358,7 @@ void BTR_reserve_slot(thread_db* tdbb, IndexCreation& creation) fb_assert(idx->idx_count <= MAX_UCHAR); slot->irt_keys = (UCHAR) idx->idx_count; slot->irt_flags = idx->idx_flags; - slot->setTransaction(transaction->tra_number); + slot->setInProgress(transaction->tra_number); // Exploit the fact idx_repeat structure matches ODS IRTD one memcpy(desc, idx->idx_rpt, len); @@ -2393,13 +2392,15 @@ void BTR_selectivity(thread_db* tdbb, jrd_rel* relation, USHORT id, SelectivityL if (!root) return; - ULONG page; - if (id >= root->irt_count || !(page = root->irt_rpt[id].getRoot())) + if (id >= root->irt_count || root->irt_rpt[id].isEmpty()) { CCH_RELEASE(tdbb, &window); return; } + ULONG page = root->irt_rpt[id].irt_root; + fb_assert(page); + const bool descending = (root->irt_rpt[id].irt_flags & irt_descending); const ULONG segments = root->irt_rpt[id].irt_keys; @@ -3334,7 +3335,7 @@ static USHORT compress_root(thread_db* tdbb, index_root_page* page) for (const index_root_page::irt_repeat* const end = root_idx + page->irt_count; root_idx < end; root_idx++) { - if (root_idx->getRoot()) + if (!root_idx->isEmpty()) { const USHORT len = root_idx->irt_keys * sizeof(irtd); p -= len; diff --git a/src/jrd/btr.h b/src/jrd/btr.h index 7f1bc99303e..7a636e866f4 100644 --- a/src/jrd/btr.h +++ b/src/jrd/btr.h @@ -58,7 +58,7 @@ struct index_desc ULONG idx_root; // Index root float idx_selectivity; // selectivity of index USHORT idx_id; - UCHAR idx_flags; + USHORT idx_flags; UCHAR idx_runtime_flags; // flags used at runtime, not stored on disk USHORT idx_primary_index; // id for primary key partner index USHORT idx_primary_relation; // id for primary key partner relation diff --git a/src/jrd/idx.h b/src/jrd/idx.h index 3fd62251440..dd094798182 100644 --- a/src/jrd/idx.h +++ b/src/jrd/idx.h @@ -36,7 +36,7 @@ struct ini_idx_t { UCHAR ini_idx_index_id; UCHAR ini_idx_relid; - UCHAR ini_idx_flags; + USHORT ini_idx_flags; UCHAR ini_idx_segment_count; USHORT ini_idx_ods; struct ini_idx_segment_t diff --git a/src/jrd/ini.epp b/src/jrd/ini.epp index d0d6527971b..cba8b9d83d5 100644 --- a/src/jrd/ini.epp +++ b/src/jrd/ini.epp @@ -1636,7 +1636,7 @@ static void store_indices(thread_db* tdbb, USHORT odsVersion) PAD(relation->rel_name, X.RDB$RELATION_NAME); PAD(indexName, X.RDB$INDEX_NAME); - X.RDB$UNIQUE_FLAG = index->ini_idx_flags & idx_unique; + X.RDB$UNIQUE_FLAG = (index->ini_idx_flags & idx_unique) ? 1 : 0; X.RDB$SEGMENT_COUNT = index->ini_idx_segment_count; if (index->ini_idx_flags & idx_descending) diff --git a/src/jrd/ods.h b/src/jrd/ods.h index 12d40717108..1d57c1aa4c7 100644 --- a/src/jrd/ods.h +++ b/src/jrd/ods.h @@ -368,39 +368,39 @@ struct index_root_page USHORT irt_count; // Number of indices struct irt_repeat { - private: - friend struct index_root_page; // to allow offset check for private members - ULONG irt_root; // page number of index root if irt_in_progress is NOT set, or - // highest 32 bit of transaction if irt_in_progress is set - ULONG irt_transaction; // transaction in progress (lowest 32 bits) - public: - USHORT irt_desc; // offset to key descriptions - UCHAR irt_keys; // number of keys in index - UCHAR irt_flags; - - ULONG getRoot() const; - void setRoot(ULONG root_page); - - TraNumber getTransaction() const; - void setTransaction(TraNumber traNumber); - + union + { + FB_UINT64 irt_transaction; // transaction in progress + ULONG irt_root; // page number of index root + }; + USHORT irt_desc; // offset to key descriptions + USHORT irt_flags; // index flags + UCHAR irt_keys; // number of keys in index + + TraNumber inProgress() const; + bool isEmpty() const; bool isUsed() const; + void setEmpty(); + void setInProgress(TraNumber traNumber); + void clearInProgress(ULONG rootPage); + void setRoot(ULONG rootPage); + } irt_rpt[1]; - static_assert(sizeof(struct irt_repeat) == 12, "struct irt_repeat size mismatch"); + static_assert(sizeof(struct irt_repeat) == 16, "struct irt_repeat size mismatch"); + static_assert(offsetof(struct irt_repeat, irt_transaction) == 0, "irt_transaction offset mismatch"); static_assert(offsetof(struct irt_repeat, irt_root) == 0, "irt_root offset mismatch"); - static_assert(offsetof(struct irt_repeat, irt_transaction) == 4, "irt_transaction offset mismatch"); static_assert(offsetof(struct irt_repeat, irt_desc) == 8, "irt_desc offset mismatch"); - static_assert(offsetof(struct irt_repeat, irt_keys) == 10, "irt_keys offset mismatch"); - static_assert(offsetof(struct irt_repeat, irt_flags) == 11, "irt_flags offset mismatch"); + static_assert(offsetof(struct irt_repeat, irt_flags) == 10, "irt_flags offset mismatch"); + static_assert(offsetof(struct irt_repeat, irt_keys) == 12, "irt_keys offset mismatch"); }; -static_assert(sizeof(struct index_root_page) == 32, "struct index_root_page size mismatch"); +static_assert(sizeof(struct index_root_page) == 40, "struct index_root_page size mismatch"); static_assert(offsetof(struct index_root_page, irt_header) == 0, "irt_header offset mismatch"); static_assert(offsetof(struct index_root_page, irt_relation) == 16, "irt_relation offset mismatch"); static_assert(offsetof(struct index_root_page, irt_count) == 18, "irt_count offset mismatch"); -static_assert(offsetof(struct index_root_page, irt_rpt) == 20, "irt_rpt offset mismatch"); +static_assert(offsetof(struct index_root_page, irt_rpt) == 24, "irt_rpt offset mismatch"); // key descriptor @@ -425,32 +425,37 @@ inline constexpr USHORT irt_primary = 16; inline constexpr USHORT irt_expression = 32; inline constexpr USHORT irt_condition = 64; -inline ULONG index_root_page::irt_repeat::getRoot() const +inline TraNumber index_root_page::irt_repeat::inProgress() const { - return (irt_flags & irt_in_progress) ? 0 : irt_root; + return (irt_flags & irt_in_progress) ? irt_transaction : 0; } -inline void index_root_page::irt_repeat::setRoot(ULONG root_page) +inline bool index_root_page::irt_repeat::isEmpty() const { - irt_root = root_page; - irt_flags &= ~irt_in_progress; + return (irt_flags & irt_in_progress) || (irt_root == 0); } -inline TraNumber index_root_page::irt_repeat::getTransaction() const +inline bool index_root_page::irt_repeat::isUsed() const { - return (irt_flags & irt_in_progress) ? ((TraNumber) irt_root << BITS_PER_LONG) | irt_transaction : 0; + return (irt_flags & irt_in_progress) || (irt_root != 0); } -inline void index_root_page::irt_repeat::setTransaction(TraNumber traNumber) +inline void index_root_page::irt_repeat::setEmpty() { - irt_root = ULONG(traNumber >> BITS_PER_LONG); - irt_transaction = ULONG(traNumber); + irt_transaction = 0; + irt_flags = 0; +} + +inline void index_root_page::irt_repeat::setInProgress(TraNumber traNumber) +{ + irt_transaction = traNumber; irt_flags |= irt_in_progress; } -inline bool index_root_page::irt_repeat::isUsed() const +inline void index_root_page::irt_repeat::setRoot(ULONG rootPage) { - return (irt_flags & irt_in_progress) || (irt_root != 0); + irt_root = rootPage; + irt_flags &= ~irt_in_progress; } diff --git a/src/jrd/validation.cpp b/src/jrd/validation.cpp index ec0f4981771..e679a42cc4f 100644 --- a/src/jrd/validation.cpp +++ b/src/jrd/validation.cpp @@ -1956,7 +1956,7 @@ void Validation::walk_generators() } } -Validation::RTN Validation::walk_index(jrd_rel* relation, index_root_page& root_page, USHORT id) +Validation::RTN Validation::walk_index(jrd_rel* relation, index_root_page* root_page, USHORT id) { /************************************** * @@ -1976,25 +1976,26 @@ Validation::RTN Validation::walk_index(jrd_rel* relation, index_root_page& root_ **************************************/ Database* dbb = vdr_tdbb->getDatabase(); - const ULONG page_number = root_page.irt_rpt[id].getRoot(); - if (!page_number) { + if (root_page->irt_rpt[id].isEmpty()) return rtn_ok; - } - const bool unique = (root_page.irt_rpt[id].irt_flags & (irt_unique | idx_primary)); - const bool descending = (root_page.irt_rpt[id].irt_flags & irt_descending); - const bool condition = (root_page.irt_rpt[id].irt_flags & irt_condition); + const ULONG page_number = root_page->irt_rpt[id].irt_root; + fb_assert(page_number); + + const bool unique = (root_page->irt_rpt[id].irt_flags & (irt_unique | idx_primary)); + const bool descending = (root_page->irt_rpt[id].irt_flags & irt_descending); + const bool condition = (root_page->irt_rpt[id].irt_flags & irt_condition); - temporary_key nullKey, *null_key = 0; + temporary_key nullKey, *null_key = nullptr; if (unique) { index_desc idx; { // No need to evaluate index expression and/or condition - AutoSetRestoreFlag flags(&root_page.irt_rpt[id].irt_flags, + AutoSetRestoreFlag flags(&root_page->irt_rpt[id].irt_flags, irt_expression | irt_condition, false); - BTR_description(vdr_tdbb, relation, &root_page, &idx, id); + BTR_description(vdr_tdbb, relation, root_page, &idx, id); } null_key = &nullKey; @@ -3216,7 +3217,7 @@ Validation::RTN Validation::walk_root(jrd_rel* relation, bool getInfo) for (USHORT i = 0; i < page->irt_count; i++) { - if (page->irt_rpt[i].getRoot() == 0) + if (page->irt_rpt[i].isEmpty()) continue; MetaName index; @@ -3242,7 +3243,7 @@ Validation::RTN Validation::walk_root(jrd_rel* relation, bool getInfo) if (page->irt_rpt[i].irt_flags & irt_condition) { // No need to evaluate index expression - AutoSetRestoreFlag flag(&page->irt_rpt[i].irt_flags, irt_expression, false); + AutoSetRestoreFlag flag(&page->irt_rpt[i].irt_flags, irt_expression, false); IdxInfo info; if (BTR_description(vdr_tdbb, relation, page, &info.m_desc, i)) @@ -3252,7 +3253,7 @@ Validation::RTN Validation::walk_root(jrd_rel* relation, bool getInfo) } output("Index %d (%s)\n", i + 1, index.c_str()); - walk_index(relation, *page, i); + walk_index(relation, page, i); } release_page(&window); diff --git a/src/jrd/validation.h b/src/jrd/validation.h index 971e0617948..3a9e0e51ed3 100644 --- a/src/jrd/validation.h +++ b/src/jrd/validation.h @@ -213,7 +213,7 @@ class Validation RTN walk_data_page(jrd_rel*, ULONG, ULONG, UCHAR&); void walk_database(); void walk_generators(); - RTN walk_index(jrd_rel*, Ods::index_root_page&, USHORT); + RTN walk_index(jrd_rel*, Ods::index_root_page*, USHORT); void walk_pip(); RTN walk_pointer_page(jrd_rel*, ULONG); RTN walk_record(jrd_rel*, const Ods::rhd*, USHORT, RecordNumber, bool); diff --git a/src/utilities/gstat/dba.epp b/src/utilities/gstat/dba.epp index 44c0ac4277e..e89d8471b68 100644 --- a/src/utilities/gstat/dba.epp +++ b/src/utilities/gstat/dba.epp @@ -195,7 +195,7 @@ static void db_error(int); static USHORT get_format_length(ISC_STATUS*, isc_db_handle, isc_tr_handle, ISC_QUAD&); static dba_fil* db_open(const char*, USHORT); -static const pag* db_read(SLONG page_number, bool ok_enc = false); +static const pag* db_read(ULONG page_number, bool ok_enc = false); #ifdef WIN_NT static void db_close(void* file_desc); #else @@ -264,7 +264,7 @@ public: USHORT page_size; USHORT dp_per_pp; USHORT max_records; - SLONG page_number; + ULONG page_number; pag* buffer1; pag* buffer2; pag* global_buffer; @@ -619,7 +619,7 @@ int gstat(Firebird::UtilSvc* uSvc) tddba->page_size = MAX(RAW_HEADER_SIZE, DIRECT_IO_BLOCK_SIZE); tddba->global_buffer = (pag*) temp; tddba->page_number = -1; - const header_page* header = (const header_page*) db_read((SLONG) 0); + const header_page* header = (const header_page*) db_read(HEADER_PAGE); if (!Ods::isSupported(header)) { @@ -1342,7 +1342,7 @@ static void analyze_data( dba_rel* relation, bool sw_record) pointer_page* ptr_page = (pointer_page*) tddba->buffer1; - for (SLONG next_pp = relation->rel_pointer_page; next_pp; next_pp = ptr_page->ppg_next) + for (ULONG next_pp = relation->rel_pointer_page; next_pp; next_pp = ptr_page->ppg_next) { ++relation->rel_pointer_pages; memcpy(ptr_page, (const SCHAR*) db_read(next_pp), tddba->page_size); @@ -1478,7 +1478,7 @@ static void analyze_blob(dba_rel* relation, const blh* blob, int length) } else { - const int slots = (length - BLH_SIZE) / static_cast(sizeof(SLONG)); + const int slots = (length - BLH_SIZE) / static_cast(sizeof(ULONG)); relation->rel_blob_pages += slots; if (blob->blh_level == 1) { @@ -1488,13 +1488,13 @@ static void analyze_blob(dba_rel* relation, const blh* blob, int length) { relation->rel_blobs_level_2++; - SLONG pages[MAX_PAGE_SIZE / sizeof(SLONG)]; - memcpy(pages, blob->blh_page, slots * sizeof(SLONG)); + ULONG pages[MAX_PAGE_SIZE / sizeof(ULONG)]; + memcpy(pages, blob->blh_page, slots * sizeof(ULONG)); for (int i = 0; i < slots; i++) { const blob_page* bpage = (const blob_page*) db_read(pages[i]); - relation->rel_blob_pages += bpage->blp_length / sizeof(SLONG); + relation->rel_blob_pages += bpage->blp_length / sizeof(ULONG); } } } @@ -1518,7 +1518,7 @@ static ULONG analyze_fragments(dba_rel* relation, const rhdf* header) while (header->rhdf_flags & rhd_incomplete) { - const SLONG f_page = header->rhdf_f_page; + const ULONG f_page = header->rhdf_f_page; const USHORT f_line = header->rhdf_f_line; const data_page* page = (const data_page*) db_read(f_page); if (page->dpg_header.pag_type != pag_data || page->dpg_relation != relation->rel_id || @@ -1566,12 +1566,11 @@ static void analyze_index( const dba_rel* relation, dba_idx* index) const index_root_page* index_root = (const index_root_page*) db_read(relation->rel_index_root); - SLONG page; - if (index_root->irt_count <= index->idx_id || - !(page = index_root->irt_rpt[index->idx_id].getRoot())) - { + if (index_root->irt_count <= index->idx_id || index_root->irt_rpt[index->idx_id].isEmpty()) return; - } + + ULONG page = index_root->irt_rpt[index->idx_id].irt_root; + fb_assert(page); // CVC: The two const_cast's for bucket can go away if BTreeNode's functions // are overloaded for constness. They don't modify bucket and pointer's contents. @@ -1589,7 +1588,7 @@ static void analyze_index( const dba_rel* relation, dba_idx* index) } bool firstLeafNode = true; - SLONG number; + ULONG number; FB_UINT64 duplicates = 0; // Maximum key length is 1/4 of the used page-size @@ -1712,7 +1711,7 @@ static ULONG analyze_versions( dba_rel* relation, const rhdf* header) **************************************/ //tdba* tddba = tdba::getSpecific(); ULONG space = 0, versions = 0; - SLONG b_page = header->rhdf_b_page; + ULONG b_page = header->rhdf_b_page; USHORT b_line = header->rhdf_b_line; while (b_page) @@ -1923,7 +1922,7 @@ static dba_fil* db_open(const char* file_name, USHORT file_length) } -static const pag* db_read( SLONG page_number, bool ok_enc) +static const pag* db_read( ULONG page_number, bool ok_enc) { /************************************** * @@ -1946,10 +1945,8 @@ static const pag* db_read( SLONG page_number, bool ok_enc) tddba->page_number = page_number; dba_fil* fil; - for (fil = tddba->files; page_number > (SLONG) fil->fil_max_page && fil->fil_next;) - { + for (fil = tddba->files; page_number > fil->fil_max_page && fil->fil_next;) fil = fil->fil_next; - } page_number -= fil->fil_min_page - fil->fil_fudge; @@ -2108,7 +2105,7 @@ static dba_fil* db_open(const char* file_name, USHORT file_length) } -static const pag* db_read( SLONG page_number, bool ok_enc) +static const pag* db_read( ULONG page_number, bool ok_enc) { /************************************** * @@ -2128,10 +2125,8 @@ static const pag* db_read( SLONG page_number, bool ok_enc) tddba->page_number = page_number; dba_fil* fil; - for (fil = tddba->files; page_number > (SLONG) fil->fil_max_page && fil->fil_next;) - { + for (fil = tddba->files; page_number > fil->fil_max_page && fil->fil_next;) fil = fil->fil_next; - } page_number -= fil->fil_min_page - fil->fil_fudge; const FB_UINT64 offset = ((FB_UINT64) page_number) * ((FB_UINT64) tddba->page_size);