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

Merge pull request #7975 from FirebirdSQL/cleanup-multi-page-header

Get rid of the overflow header pages
This commit is contained in:
Dmitry Yemanov 2024-01-31 09:14:33 +03:00 committed by GitHub
commit c950f7fb7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 464 additions and 735 deletions

View File

@ -2485,7 +2485,6 @@ bool CCH_write_all_shadows(thread_db* tdbb, Shadow* shadow, BufferDesc* bdb, Ods
const UCHAR* q = (UCHAR *) pageSpaceID->file->fil_string;
header->hdr_data[0] = HDR_end;
header->hdr_end = HDR_SIZE;
header->hdr_next_page = 0;
PAG_add_header_entry(tdbb, header, HDR_root_file_name,
(USHORT) strlen((const char*) q), q);

View File

@ -460,7 +460,7 @@ struct header_page
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_next_page; // Page number of next hdr page
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
@ -490,7 +490,7 @@ static_assert(offsetof(struct header_page, hdr_header) == 0, "hdr_header offset
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_next_page) == 24, "hdr_next_page 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");

File diff suppressed because it is too large Load Diff

View File

@ -31,19 +31,15 @@ namespace Jrd {
class PageSpace;
struct win;
}
namespace Ods {
struct pag;
struct header_page;
//enum ClumpOper { CLUMP_ADD, CLUMP_REPLACE, CLUMP_REPLACE_ONLY };
}
//void PAG_add_clump(Jrd::thread_db* tdbb, SLONG, USHORT, USHORT, const UCHAR*, Ods::ClumpOper);
USHORT PAG_add_file(Jrd::thread_db* tdbb, const TEXT*, SLONG);
bool PAG_add_header_entry(Jrd::thread_db* tdbb, Ods::header_page*, USHORT, USHORT, const UCHAR*);
//void PAG_attach_temp_pages(Jrd::thread_db*, USHORT pageSpaceID);
void PAG_add_header_entry(Jrd::thread_db* tdbb, Ods::header_page*, USHORT, USHORT, const UCHAR*);
bool PAG_replace_entry_first(Jrd::thread_db* tdbb, Ods::header_page*, USHORT, USHORT, const UCHAR*);
Ods::pag* PAG_allocate(Jrd::thread_db* tdbb, Jrd::win*);
Ods::pag* PAG_allocate_pages(Jrd::thread_db* tdbb, Jrd::win* window, unsigned cntAlloc, bool aligned);
AttNumber PAG_attachment_id(Jrd::thread_db*);
bool PAG_delete_clump_entry(Jrd::thread_db* tdbb, USHORT);
@ -70,4 +66,9 @@ void PAG_set_repl_sequence(Jrd::thread_db* tdbb, FB_UINT64);
void PAG_set_sweep_interval(Jrd::thread_db* tdbb, SLONG);
ULONG PAG_page_count(Jrd::thread_db*);
inline Ods::pag* PAG_allocate(Jrd::thread_db* tdbb, Jrd::win* window)
{
return PAG_allocate_pages(tdbb, window, 1, false);
}
#endif // JRD_PAG_PROTO_H

View File

@ -197,7 +197,6 @@ int SDW_add_file(thread_db* tdbb, const TEXT* file_name, SLONG start, USHORT sha
header->hdr_page_size = dbb->dbb_page_size;
header->hdr_data[0] = HDR_end;
header->hdr_end = HDR_SIZE;
header->hdr_next_page = 0;
// fool PIO_write into writing the scratch page into the correct place
BufferDesc temp_bdb(dbb->dbb_bcb);
@ -240,7 +239,6 @@ int SDW_add_file(thread_db* tdbb, const TEXT* file_name, SLONG start, USHORT sha
--start;
header->hdr_data[0] = HDR_end;
header->hdr_end = HDR_SIZE;
header->hdr_next_page = 0;
PAG_add_header_entry(tdbb, header, HDR_file, static_cast<USHORT>(strlen(file_name)),
reinterpret_cast<const UCHAR*>(file_name));

View File

@ -218,9 +218,9 @@ V. WALK-THROUGH PHASE
In order to ensure that all pages are fetched during validation, the
following pages are fetched just for the most basic validation:
1. The header page (and for 4.0 any overflow header pages).
2. Log pages for after-image journalling (4.0 only).
3. Page Inventory pages.
1. The header page.
2. Page Inventory pages.
3. System Change Number pages.
4. Transaction Inventory pages
If the system relation RDB$PAGES could not be read or did not
@ -1623,7 +1623,6 @@ void Validation::walk_database()
if (!(vdr_flags & VDR_partial))
{
walk_header(page->hdr_next_page);
walk_pip();
walk_scns();
walk_tip(next);
@ -1959,33 +1958,6 @@ void Validation::walk_generators()
}
}
void Validation::walk_header(ULONG page_num)
{
/**************************************
*
* w a l k _ h e a d e r
*
**************************************
*
* Functional description
* Walk the overflow header pages
*
**************************************/
while (page_num)
{
#ifdef DEBUG_VAL_VERBOSE
if (VAL_debug_level)
fprintf(stdout, "walk_header: page %d\n", page_num);
#endif
WIN window(DB_PAGE_SPACE, -1);
header_page* page = 0;
fetch_page(true, page_num, pag_header, &window, &page);
page_num = page->hdr_next_page;
release_page(&window);
}
}
Validation::RTN Validation::walk_index(jrd_rel* relation, index_root_page& root_page, USHORT id)
{
/**************************************

View File

@ -213,7 +213,6 @@ private:
RTN walk_data_page(jrd_rel*, ULONG, ULONG, UCHAR&);
void walk_database();
void walk_generators();
void walk_header(ULONG);
RTN walk_index(jrd_rel*, Ods::index_root_page&, USHORT);
void walk_pip();
RTN walk_pointer_page(jrd_rel*, ULONG);

View File

@ -652,46 +652,47 @@ int gstat(Firebird::UtilSvc* uSvc)
}
tddba->page_number = -1;
// gather continuation files
ULONG page = HEADER_PAGE;
do {
if (page != HEADER_PAGE)
current = db_open(file_name, static_cast<USHORT>(strlen(file_name)));
do {
header = (const header_page*) db_read(page);
if (current != tddba->files)
current->fil_fudge = 1; // ignore header page once read it
*file_name = '\0';
const UCHAR* vp = header->hdr_data;
for (const UCHAR* const vend = reinterpret_cast<const UCHAR*>(header) + header->hdr_page_size;
vp < vend && *vp != HDR_end; vp += 2 + vp[1])
{
if (*vp == HDR_file)
{
memcpy(file_name, vp + 2, vp[1]);
*(file_name + vp[1]) = '\0';
}
if (*vp == HDR_last_page) {
memcpy(&current->fil_max_page, vp + 2, sizeof(current->fil_max_page));
}
}
} while (page = header->hdr_next_page);
page = current->fil_max_page + 1; // first page of next file
} while (*file_name);
// Print header page
page = HEADER_PAGE;
do {
header = (const header_page*) db_read(page);
PPG_print_header(header, page, sw_nocreation, uSvc);
page = header->hdr_next_page;
} while (page);
ULONG page = HEADER_PAGE;
header = (const header_page*) db_read(page);
PPG_print_header(header, sw_nocreation, uSvc);
if (sw_header)
dba_exit(FINI_OK, tddba);
// gather continuation files
while (true)
{
if (page != HEADER_PAGE)
{
current = db_open(file_name, static_cast<USHORT>(strlen(file_name)));
header = (const header_page*) db_read(page);
}
if (current != tddba->files)
current->fil_fudge = 1; // ignore header page once read it
PathName nextFileName;
const UCHAR* vp = header->hdr_data;
for (const auto vend = reinterpret_cast<const UCHAR*>(header) + header->hdr_page_size;
vp < vend && *vp != HDR_end; vp += 2 + vp[1])
{
if (*vp == HDR_file)
nextFileName.assign(vp + 2, vp[1]);
if (*vp == HDR_last_page)
memcpy(&current->fil_max_page, vp + 2, sizeof(current->fil_max_page));
}
if (nextFileName.isEmpty())
break;
page = current->fil_max_page + 1; // first page of next file
}
if (sw_enc)
{
class Statist

View File

@ -41,8 +41,7 @@
using namespace Ods;
using Firebird::Guid;
void PPG_print_header(const header_page* header, ULONG page,
bool nocreation, Firebird::UtilSvc* uSvc)
void PPG_print_header(const header_page* header, bool nocreation, Firebird::UtilSvc* uSvc)
{
/**************************************
*
@ -54,63 +53,51 @@ void PPG_print_header(const header_page* header, ULONG page,
* Print database header page.
*
**************************************/
if (page == HEADER_PAGE)
uSvc->printf(false, "Database header page information:\n");
else
uSvc->printf(false, "Database overflow header page information:\n");
uSvc->printf(false, "Database header page information:\n");
if (page == HEADER_PAGE)
{
uSvc->printf(false, "\tFlags\t\t\t%d\n", header->hdr_header.pag_flags);
//uSvc->printf("\tChecksum\t\t%d\n", header->hdr_header.pag_checksum);
uSvc->printf(false, "\tGeneration\t\t%" ULONGFORMAT"\n", header->hdr_header.pag_generation);
uSvc->printf(false, "\tSystem Change Number\t%" ULONGFORMAT"\n", header->hdr_header.pag_scn);
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, "\tFlags\t\t\t%d\n", header->hdr_header.pag_flags);
//uSvc->printf("\tChecksum\t\t%d\n", header->hdr_header.pag_checksum);
uSvc->printf(false, "\tGeneration\t\t%" ULONGFORMAT"\n", header->hdr_header.pag_generation);
uSvc->printf(false, "\tSystem Change Number\t%" ULONGFORMAT"\n", header->hdr_header.pag_scn);
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));
Firebird::DbImplementation imp(header);
uSvc->printf(false, "\tImplementation\t\tHW=%s %s-endian OS=%s CC=%s\n",
imp.cpu(), imp.endianess(), imp.os(), imp.cc());
uSvc->printf(false, "\tShadow count\t\t%" SLONGFORMAT"\n", header->hdr_shadow_count);
uSvc->printf(false, "\tPage buffers\t\t%" ULONGFORMAT"\n", header->hdr_page_buffers);
}
Firebird::DbImplementation imp(header);
uSvc->printf(false, "\tImplementation\t\tHW=%s %s-endian OS=%s CC=%s\n",
imp.cpu(), imp.endianess(), imp.os(), imp.cc());
uSvc->printf(false, "\tShadow count\t\t%" SLONGFORMAT"\n", header->hdr_shadow_count);
uSvc->printf(false, "\tPage buffers\t\t%" ULONGFORMAT"\n", header->hdr_page_buffers);
uSvc->printf(false, "\tNext header page\t%" ULONGFORMAT"\n", header->hdr_next_page);
#ifdef DEV_BUILD
uSvc->printf(false, "\tClumplet End\t\t%d\n", header->hdr_end);
#endif
if (page == HEADER_PAGE)
// If the database dialect is not set to 3, then we need to
// assume it was set to 1. The reason for this is that a dialect
// 1 database has no dialect information written to the header.
if (header->hdr_flags & hdr_SQL_dialect_3)
uSvc->printf(false, "\tDatabase dialect\t3\n");
else
uSvc->printf(false, "\tDatabase dialect\t1\n");
if (!nocreation)
{
// If the database dialect is not set to 3, then we need to
// assume it was set to 1. The reason for this is that a dialect
// 1 database has no dialect information written to the header.
if (header->hdr_flags & hdr_SQL_dialect_3)
uSvc->printf(false, "\tDatabase dialect\t3\n");
else
uSvc->printf(false, "\tDatabase dialect\t1\n");
if (!nocreation)
{
struct tm time;
isc_decode_timestamp(reinterpret_cast<const ISC_TIMESTAMP*>(header->hdr_creation_date),
&time);
uSvc->printf(false, "\tCreation date\t\t%s %d, %d %d:%02d:%02d\n",
FB_SHORT_MONTHS[time.tm_mon], time.tm_mday, time.tm_year + 1900,
time.tm_hour, time.tm_min, time.tm_sec);
}
struct tm time;
isc_decode_timestamp(reinterpret_cast<const ISC_TIMESTAMP*>(header->hdr_creation_date),
&time);
uSvc->printf(false, "\tCreation date\t\t%s %d, %d %d:%02d:%02d\n",
FB_SHORT_MONTHS[time.tm_mon], time.tm_mday, time.tm_year + 1900,
time.tm_hour, time.tm_min, time.tm_sec);
}
ULONG flags;
if ((page == HEADER_PAGE) && (flags = header->hdr_flags))
if (const auto flags = header->hdr_flags)
{
int flag_count = 0;
@ -231,7 +218,8 @@ void PPG_print_header(const header_page* header, ULONG page,
TEXT temp[257];
const UCHAR* p = header->hdr_data;
for (const UCHAR* const end = reinterpret_cast<const UCHAR*>(header) + header->hdr_page_size; p < end && *p != HDR_end; p += 2 + p[1])
for (const auto end = reinterpret_cast<const UCHAR*>(header) + header->hdr_page_size;
p < end && *p != HDR_end; p += 2 + p[1])
{
SLONG number;

View File

@ -26,7 +26,7 @@
#include "../common/UtilSvc.h"
void PPG_print_header (const Ods::header_page*, ULONG, bool, Firebird::UtilSvc*);
void PPG_print_header(const Ods::header_page*, bool, Firebird::UtilSvc*);
int gstat(Firebird::UtilSvc*);
#endif // UTILITIES_PPG_PROTO_H

View File

@ -952,7 +952,6 @@ static void print_db_header( FILE* file, const header_page* header)
header->hdr_ods_version & ~ODS_TYPE_MASK,
header->hdr_ods_version & ODS_TYPE_MASK);
fprintf(file, " PAGES\t\t\t%d\n", header->hdr_PAGES);
fprintf(file, " next page\t\t\t%d\n", header->hdr_next_page);
fprintf(file, " Oldest transaction\t\t%lu\n", header->hdr_oldest_transaction);
fprintf(file, " Oldest active\t\t%lu\n", header->hdr_oldest_active);
fprintf(file, " Oldest snapshot\t\t%lu\n", header->hdr_oldest_snapshot);