WinTarif
|
|
|||||||
|
see FbOdsViewer
Standard Database Page HeaderPag_type: One byte, signed. Byte 0x00 on the page. This byte defines the page type for the page. Valid page types are:
Pag_flags: One byte, unsigned. Byte 0x01 on the page. This byte holds various flags for the page. Pag_checksum: Two bytes, unsigned. Bytes 0x02 - 0x03. Checksum for the whole page. No longer used, always 12345, 0x3039. Databases using ODS8 on Windows NT do have a valid checksum here. Pag_generation: Four bytes, unsigned. Bytes 0x04 - 0x07. The page generation number. Increments each time the page is written back to disc. Pag_scn: Four bytes, unsigned. Bytes 0x08 - 0x0b. Originally used as the sequence number in the Write Ahead Log, but WAL is no longer used. The field was converted to be the SCN number to avoid an ODS change and is now used by nbackup. Pag_reserved: Four bytes, unsigned. Bytes 0x0c - 0x0f. Reserved for future use. It was originally used for the offset of a page's entry in the Write Ahead Log (WAL), but this is no longer in use. Database Header pageHdr_header: The database header page has a standard page header, as do all pages.Hdr_page_size: Two bytes, unsigned. Bytes 0x10 - 0x11 on the page. This is the page size, in bytes, for each and every page in the database. Hds_ods_version: Two bytes, unsigned. Bytes 0x12 and 0x13 on the page. The ODS major version for the database. The format of this word is the ODS major version ANDed with the Firebird flag of 0x8000. In the example below, the value is 0x800b for ODS version 11. The minor ODS version is held elsewhere in the header page - see hdr_ods_minor below. Hdr_pages: Four bytes, signed. Bytes 0x14 - 0x17 on the page. This is the page number of the first pointer page for the table named RDB$PAGES. When this location is known, the database engine uses it to determine the locations of all other matadata pages in the database. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero. Hdr_next_page: Four bytes, unsigned. Bytes 0x18 - 0x1b on the page. The page number of the header page in the next file of the database - if this is a multi-file database. Zero otherwise. Hdr_oldest_transaction: Four bytes, signed. Bytes 0x1c - 0x1f on the page. The transaction id of the oldest active (ie, uncommitted - but may be in limbo or rolled back) transaction against this database. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero. Hdr_oldest_active: Four bytes, signed. Bytes 0x20 - 0x23 on the page. The transaction id of the oldest active transaction against this database, when any active transaction started. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero. Hdr_next_transaction: Four bytes, signed. Bytes 0x24 - 0x27 on the page. The transaction id that will be assigned to the next transaction against this database. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero. Hdr_sequence: Two bytes, unsigned. Bytes 0x28 and 0x29 on the page. The sequence number of this file within the database. Hdr_flags: Two bytes, unsigned. Bytes 0x2a and 0x2b on the page. The database flags. The bits in the flag bytes are used as follows:
The final two database flags use a pair of bits to indicate various states of backup and shutdown. Hdr_backup_mask: These two bits determine the current database backup mode, as follows:
Hdr_shutdown_mask: The shutdown mask uses two bits to indicate the current database shutdown status, as follows:
Hdr_creation_date: Eight bytes, signed. Bytes 0x2c - 0x33 on the page. The data and time (in Firebird's own internal format) that the database was either originally created/rewritten or created from a backup. Hdr_attachment_id: Four bytes, signed. Bytes 0x34 - 0x37 on the page. The id number that will be assigned to the next connection to this database. As this is signed, the maximum value here is 232-1 and any database which reaches this maximum value must be backed up and restored in order to allow new connections. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero. Hdr_shadow_count: Four bytes, signed. Bytes 0x38 - 0x3c on the page. Holds the event count for shadow file synchronisation for this database. The remaining files in the database have this field set to zero. Hdr_implementation: Two bytes, signed. Bytes 0x3c and 0x3d on the page. This is a number which indicates the environment on which the database was originally created. It is used to determine if the database file can be used sucessfully on the current hardware. This avoids problems caused by little-endian numerical values as compared with big-endian, for example. Hdr_ods_minor: Two bytes, unsigned. Bytes 0x3e and 0x3f on the page. The current ODS minor version. Hdr_ods_minor_original: Two bytes, unsigned. Bytes 0x40 and 0x41 on the page. The ODS minor version when the database was originally created. Hdr_end: Two bytes, unsigned. Bytes 0x42 and 0x43 on the page. The offset on the page where the hdr_data finishes. In other words, where a new clumplet will be stored if required. This is effectively a pointer to the current location of HDR_end (see clumplet details below) on this page. Hdr_page_buffers: Four bytes, unsigned. Bytes 0x44 - 0x47 on the page. Holds the number of buffers to be used for the database cache, or zero to indicate that the default value should be used. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero. Hdr_bumped_transaction: Four bytes, signed. Bytes 0x48 - 0x4b on the page. Used to be used for the bumped transaction id for log optimisation, but is currently always set to 0x01. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero. Hdr_oldest_snapshot: Four bytes, signed. Bytes 0x4c - 0x4f on the page. Holds the transaction number for the oldest snapshot of active transactions. This is also documented as the confusing and redundant variant of Oldest Active Transaction. Hdr_backup_pages: Four bytes, signed. Bytes 0x50 - 0x53 on the page. Holds the number of pages in the database currently locked for a backup using nbackup. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero. Hdr_misc: Twelve bytes. Bytes 0x54 - 0x5f on the page. Set to zero. These 12 bytes
are currently unused. Hdr_data: The variable data area on the header page begins at offset 0x60. Data stored here is held in clumplets and there are a number of different clumplet types, see below. This area is used to store filenames for the next file and other miscellaneous pieces of data relating to the database. The format of each clumplet is as follows: Type_byte: The first byte - unsigned - in each clumplet determines the type of data stored within the clumplet. There are a number of different clumplet types:
Length_byte: The second byte - again unsigned - in each clumplet specifies the size of the data that follows. Page Inventory PageEvery database has at least one Page Inventory Page (PIP) with the first one always being page 1, just after the database header page. If more are required, the current PIP points to the next PIP by way of the very last bit on the page itself. The C code representation of the PIP page is: Pip_header: The PIP starts off with a standard page header.Pip_min: Four bytes, signed. Bytes 0x10 - 0x13 on the page. This is the bit number of the first page, on this PIP, which is currently free for use. Pip_bits: Bytes 0x14 onwards. The remainder of the page, is an array of single bits where each bit represents a page in the database. If the bit is set (1) then that page is free for use. If the bit is unset (0) then the page has been used. If the database is large, and requires another PIP elsewhere in the database, then the last bit on this PIP represents the page number for the next PIP. For example, on a 4,096 byte page we have a total of 4,076 bytes to represent different pages in the database. As each byte has 8 bits, we have a total of 32,608 pages before we need a new PIP. Transaction Inventory PageEvery database has at least one Transaction Inventory Page (TIP). The highest possible transaction number is 2,147,483,647 or 0x7fffffff in a 32 bit system. Once you hit this transaction, no more can be created and the database needs to be shutdown, backed up and then restored to reset the transaction numbers back to zero. The reason it has this maximum value is simply because the code for allocating transaction numbers uses a signed value. Tip_header: The TIP starts off with a standard page header.Tip_next: Four bytes, signed. Bytes 0x10 - 0x13 on the page. This is the page number of the next TIP page, if one exists, within the database. Zero here indicates that the current TIP page is the last TIP page. Tip_transactions: Bytes 0x14 onwards. The remainder of the page, is an array of two bit values where each pair of bits represents a transaction and its status. Each transaction can have one of 4 status values:
Pointer PageA pointer page is used internally to hold a list of all - or as may will fit on one pointer page - data pages (see below) that make up a single table. Large tables may have more than one pointer page but every table, system or user, will have a minimum of one pointer page. The RDB$PAGES table is where the Firebird engine looks to find out where a table is located within the physical database, however, RDB$PAGES is itself a table, and when the database is running, how exactly can it find the start page for RDB$PAGES in order to look it up? The database header page contains the page number for RDB$PAGES at bytes 0x14 - 0x17 on the page. From experimentation, it appears as if this is always page 0x03, however, this cannot be relied upon and if you need to do this, you should always check the database header page to determine where RDB$PAGES is to be found. Ppg_header: A pointer page starts with a standard page header. In the header, the pag_flags field is used and is set to the value 1 if this is the final pointer page for the relation.Ppg_sequence: Four bytes, signed. Offset 0x10 to 0x13 on the page. The sequence number of this pointer page in the list of pointer pages for the table. Starts at zero. Ppg_next: Four bytes, signed. Offset 0x14 to 0x17 on the page. The page number of the next pointer page for this table. Zero indicates that this is the final pointer page. Ppg_count: Two bytes, unsigned. Offset 0x18 and 0x19 on the page. This field holds the count of active slots (in the ppg_page[] array) on this pointer page, that are in use. As the array starts at zero, this is also the index of the first free slot on this pointer page. Ppg_relation: Two bytes, unsigned. Offset 0x1a and 0x1b on the page. This field holds the RDB$RELATIONS.RDB$REALTION_ID for the table that this pointer page represents. Ppg_min_space: Two bytes, unsigned. Offset 0x1c and 0x1d on the page. This indicates the first entry in the ppg_page array holding a page number which has free space in the page. Ppg_max_space: Two bytes, unsigned. Offset 0x1e and 0x1f on the page. This was intended to indicate the last entry in the ppg_page array holding a page number which has free space in the page, but it has never been used. These two bytes are invariably set to zero. Ppg_page: An array of four byte signed values, starting at offset 0x20. Each value in this array represents a page number where a part of the current table is to be found. A value of zero in a slot indicates that the slot is not in use. Deleting all the data from a table will result in all slots being set to zero. Page fill bitmaps: At the end of each pointer page is a bitmap array of two bit entries which is indexed by the same index as the ppg_page array. These bitmaps indicate that the page is available for use in storing records (or record versions) or not. The two bits in the bitmap indicate whether a large object (BLOB?) is on this page and the other bit indicates that the page is full. If either bit is set (page has a large object or page is full, then the page is not used for new records or record versions. The location of the bitmaps on each page is dependent on the page size. The bigger the page, the more slots in the ppg_page array it can hold and so the bitmap is bigger. A bigger bitmap starts at a lower address in the page and so on. From looking inside a few databases with a 4Kb page size, the bitmaps begin at offset 0x0f10 on the page. Data pageA data page belongs exclusively to a single table. The page starts off, as usual, with the standard page header and is followed by an array of pairs of unsigned two byte values representing the 'table of contents' for this page. This array fills from the top of the page (lowest address, increasing) while the actual data it points to is stored on the page and fills from the bottom of the page (highest address, descending). Dpg_header: The page starts with a standard page header. In this page type, the pag_flags byte is used as follows:
Dpg_sequence: Four bytes, signed. Offset 0x10 on the page. This field holds the sequence number for this page in the list of pages assigned to this table within the database. The first page of any table has sequence zero. Dpg_relation: Two bytes, unsigned. Offset 0x12 on the page. The relation number for this table. This corresponds to RDB$RELATIONS.RDB$RELATION_ID. Dpg_count: Two bytes, unsigned. Offset 0x14 on the page. The number of records (or record fragments) on this page. In other words, the number of entries in the dpg_rpt array. Dpg_rpt: This is an array of two byte unsigned values. The array begins at offset 0x18 on the page and counts upwards from the low address to the higher address as each new record fragment is added. The two fields in this array are: Dpg_offset: Two bytes, unsigned. The offset on the page where the record fragment starts. If the value here is zero and the length is zero, then this is an unused array entry. The offset is from the start address of the page. For example, if the offset is 0x0fc8 and this is a database with a 4Kb page size, and the page in question is page 0xcd (205 decimal) then we have the offset of 0xcdfc8 because 0xcd000 is the actual address (in the database file) of the start of the page. Dpg_length: Two bytes, unsigned. The length of this record fragment in bytes. The raw record data is structured into a header and the data. Each record's data is preceeded by a record header. The format of the header is shown below. Note that there are two different record headers, one for fragmented records and the other for unfragmented records. Both headers are identical up to the rhd_format field. In the case of an unfragmented record there are no more fields in the header while the header for a fragmented record has a few more fields. How to tell the difference? See the details of the rdf_flags field below.Rhd_transaction: Four bytes, signed. Offset 0x00 in the header. This is the id of the transaction that created this record. Rhd_b_page: Four bytes, signed. Offset 0x04 in the header. This is the record's back pointer page. Rhd_b_line: Two bytes, unsigned. Offset 0x08 in the header. This is the record's back line pointer. Rhd_flags: Two bytes, unsigned. Offset 0x0a in the header. The flags for this record or record fragment. The flags are discussed below.
Rhd_format: One byte, unsigned. Offset 0x0c in the header. The record format version. Rhd_data: Unsigned byte data. Offset 0x0d in the header. This is the start of the compressed data. For a fragmented record header, this field is not applicable. The following only apply to the fragmented record header. For an unfragmented record, the data begins at offset 0x0d. Fragmented records store their data at offset 0x16. Rhdf_f_page: Four bytes, signed. Offset 0x10 (Padding bytes inserted). The page number on which the next fragment of this record can be found. Rhdf_f_line: Two bytes, unsigned. Offset 0x14. The line number on which the next fragment for this record can be found. Rhdf_data: Unsigned byte data. Offset 0x16 in the header. This is the start of the compressed data for this record fragment. Record data is always stored in a compressed format, even if the data itself cannot be compressed. The compression is a type known as Run Length Encoding (RLE) where a sequence of repeating characters is reduced to a control byte that determines the repeat count followed by the actual byte to be repeated. Where data cannot be compressed, the control byte indicates that "the next 'n' characters are to be output unchanged". The usage of a control byte is as follows:
The data in a record is not compressed based on data found in a previously inserted record - it cannot be. If you have the word 'Firebird' in two records, it will be stored in full in both. The same applies to fields in the same record - all storage compression is done within each individual field and previously compressed fields have no effect on the current one. (In other words, Firebird doesn't use specialised 'dictionary' based compression routines such as LHZ, ZIP, GZ etc) Repeating short strings such as 'abcabcabc' are also not compressed. Once the compression of the data in a column has been expanded, the data consists of three parts - a field header, the actual data and, if necessary, some padding bytes. Obviously, when decompressing the data, the decompression code needs to be able to know which bytes in the data are control bytes. This is done by making the first byte a control byte. Knowing this, the decompression code is easily able to convert the stored data back to the uncompressed state. Index Root PageEvery table in the database has an Index Root Page which holds data that describes the indexes for that table. Even tables that have no indices defined have an index root page. Irt_header: The page starts with a standard page header. The flags byte - pag_flags - is not used on this page type.Irt_relation: Two bytes, unsigned. Offset 0x10 on the page. The relation id. This is the value of RDB$RELATIONS.RDB$RELATION_ID. Irt_count: Two bytes, unsigned. Offset 0x12 on the page. The number of indices defined for this table. If there are no indices defined this counter will show the value zero. (Every table in the database has an Index Root Page regardless of whether or not it has any indices defined.) Irt_rpt: This is an array of index descriptors. The array begins at offset 0x14 on the page with the descriptor for the first index defined for the table. Descriptors are added to the 'top' of the array so the next index defined will have its descriptor at a higher page address than the previous descriptor. The descriptor entries consist of the following 6 fields (irt_root through irt_flags). Each descriptor is 0x0b bytes long. Irt_root: Four bytes, signed. Offset 0x00 in each descriptor array entry. This field is the page number where the root page for the individual index (page type 0x07) is located. Irt_selectivity: Four bytes, signed floating point. Offset 0x04 in each descriptor array entry. This is the same offset as for irt_transaction below. In ODS versions previous to 11.0 this field holds the index selectivity in floating point format. Irt_transaction: Four bytes, signed. Offset 0x04 in each descriptor array entry - the same offset as irt_selectivity above. Normally this field will be zero but if an index is in the process of being created, the transaction id will be found here.Irt_desc: Two bytes, unsigned. Offset 0x08 in each descriptor array entry. This field holds the offset, from the start of the page, to the index field descriptors which are located at the bottom end (ie, highest addresses) of the page. To calculate the starting address, add the value in this field to the address of the start of the page. Irt_keys: One byte, unsigned. Offset 0x0a in each descriptor array entry. This defines the number of keys (columns) in this index. Irt_flags: One byte, unsigned. Offset 0x0b in each descriptor array entry. The flags define various attributes for this index, these are encoded into various bits in the field, as follows:
Each descriptor entry in the array holds an offset to a list of key descriptors. These start at the highest address on the page and extend towards the lowest address. (The array of index descriptors (irt_rpt) starts at a low address on the page and increases upwards. At some point, they will meet and the page will be full. The index field descriptors are defined as follows: Irtd_field: Two bytes, unsigned. Offset 0x00 in each field descriptor. This field defines the field number of the table that makes up 'this' field in the index. This number is equivalent to RDB$RELATION_FIELDS.RDB$FIELD_ID. Irtd_itype: Two bytes, unsigned. Offset 0x02 in each field descriptor. This determines the data type of the appropriate field in the index. The allowed values in this field are:
You may note from the above that an irtd_itype with value 2 is not permitted. Irtd_selectivity: Four bytes, floating point format. Offset 0x04 in each field descriptor. This field holds the selectivity of this particular column in the index. This applies to ODS 11.0 onwards. In pre ODS 11.0 databases, this field is not part of the index field descriptors and selectivity is applied to the index as a whole. See irt_selectivity above. Index B-Tree PageB-Tree HeaderBtr_header: The page starts off with a standard page header. The pag_flags byte is used on these pages. The bits used and why are:
Btr_sibling: Four bytes, signed. Bytes 0x10 - 0x13 on the page. This is the page number of the next page of this index. The values on the next page are higher than all of those on this page. A value of zero here indicates that this is the final page in the index. Btr_left_sibling: Four bytes, signed. Bytes 0x14 - 0x17 on the page. This is the page number of the previous page of this index. The values on the previous page are lower than all of those on this page. A value of zero here indicates that this is the first page in the index. Btr_prefix_total: Four bytes, signed. Bytes 0x18 - 0x1b on the page. The sum of all the bytes saved on this page by using prefix compression. Btr_relation: Two bytes, unsigned. Bytes 0x1c and 0x1d on the page. The relation id (RDB$RELATION_ID in RDB$RELATIONS) for the table that this index applies to. Btr_length: Two bytes, unsigned. Bytes 0x1e and 0x1f on the page. The number of bytes used, for data, on this page. Acts as an offste to the first unused byte on the page. Btr_id: One byte, unsigned. Byte 0x20 on the page. The index id (RDB$INDEX_ID in RDB$INDICES) for this index. Btr_level: One byte, unsigned. Byte 0x21 on the page. The index level. Level zero indicates a leaf node.
FirstNodeOffset: Two bytes, unsigned. Offset 0x00 in the structure. This is the
offset, in bytes, to the first of the Index Nodes (see below) on this
page.
JumpAreaSize: Two bytes, unsigned. Offset 0x02 in the structure. The value here is the number of bytes left to be used before we have to create a new jump node. Jumpers: One byte, unsigned. Offset 0x05 in the structure. The running total of the current number of Jump Nodes on this page. There can be a maximum of 255 Index Jump Nodes on a page. The Index Jump Info structure described above is followed by zero or more Index Jump Nodes. The number to be found is determined by the jumpers value in the Index Jump Info structure. Btr_nodes: Index nodes are described below and are used to hold the data for one entry in this index. Btn_prefix: One byte, unsigned. Byte 0x00 in the node. This is the size of the compressed prefix. Btn_length: One byte, unsigned. Byte 0x01 in the node. This is the size of the data in the index entry. Btn_number: Four bytes, unsigned. Bytes 0x02 - 0x05 in the node. The page number (or record number) where the data that this index entry represents, is to be found. Btn_data: The data that makes up the index entry is found at bytes 0x06 onwards in the node. Blob Data PageBlp_header: The blob page starts off with a standard page header. Blp_lead_page: Four bytes, signed. Bytes 0x10 - 0x13. This field holds the page number for the first page for this blob. Blp_sequence: Four bytes, signed. Bytes 0x14 - 0x17. The sequence number of this page within the page range for this blob. Blp_length: Two bytes, unsigned. Bytes 0x18 and 0x19. The length of the blob data on this page, in bytes. Blp_pad: Two bytes, unsigned. Bytes 0x1a and 0x1b. Not used for any data, used as padding. Blp_page: This location in the page is at byte 0x1c. It has two purposes:
If the flag byte in the standard page header (pag_flags) is set to 1, this blob page contains no data but acts as a pointer page to all the other blob pages for this particular blob. Generator PageEvery database has at least one Generator Page, even if no generators (also known as sequences in Firebird 2.x) have been defined by the user. A blank database consisting only of system tables and indices already has a number of generators created for use in naming constraints, indices, etc. Gpg_header: The generator page starts off with a standard page header. Gpg_sequence: Four bytes, signed. Bytes 0x10 - 0x13. The sequence number of this generator page, starting from zero. If so many generators have been created that new generator pages are required, the sequence number will be incremented for each one. Gpg_waste: Twelve bytes. Bytes 0x14 to 0x1f. To quote the source code, these values are overhead carried forward for backward compatibility. In other words, most likely unused. Gpg_values: An array of 64 bit values, one for each generator in the database. |
© 2024 Vladimir Klimov WinTarif@narod.ru |