Skip to content

Page trailer 0xFF4..0xFF8 is a 32-bit LSN, not reserved-zero metadata #7

Description

@pete-green

Following up on the OpenSQLAnywhere item discussed in OpenQBW #15.

This report is based only on byte-level analysis of QBW files owned by the contributor and self-consistency relationships inside those files. No vendor SDK, documentation, disassembly, or proprietary reader was used to derive or validate it.

Current behavior

PageTrailer currently treats:

  • 0xFF4 and 0xFF5 as two loose metadata bytes;
  • 0xFF6..0xFFB as six reserved zero bytes.

Consequently, verify_trailer rejects valid pages once the value spanning 0xFF4..0xFF7 exceeds 16 bits.

Observed layout

The trailer is instead:

offset size interpretation
0xFF4 4 little-endian page log sequence number
0xFF8 4 reserved zero bytes

The field must be 32 bits wide: on the largest file in the three-file corpus, observed values exceed 0xFFFF, and bytes 0xFF6..0xFF7 carry their high half. Bytes 0xFF8..0xFFB remain zero.

In-file controls

Three independent relationships support the interpretation:

  1. On all three files, the maximum page value is exactly ten less than the little-endian u32 at superblock offset 0x08:

    file superblock 0x08 max page 0xFF4 difference
    sample A 35,800 35,790 10
    sample B 1,848,242 1,848,232 10
    production corpus file 747,273,956 747,273,946 10
  2. The four bytes at superblock 0x0C, which would be needed if 0x08 were the low half of a 64-bit file identifier, are zero in all three files. The 0x08 value behaves as the current write counter instead.

  3. Pages carrying the 0x20 case bit in their page-type byte have a substantially newer LSN distribution than pages without it. That is consistent with the case bit marking pages written after a checkpoint.

Proposed API correction

  • Replace PageTrailer::meta_ff4, meta_ff5, and zero_ff6 with lsn: u32 and zero_ff8: [u8; 4].
  • Expose Page::lsn().
  • Rename Superblock::file_id_lo to current_lsn.
  • Make verify_trailer validate zero_ff3 and zero_ff8, not the high half of the LSN.
  • Update the specification, CLI output, changelog, and synthetic tests.

This changes public fields, so it is a breaking API correction under the crate's current 0.x versioning.

I have a focused patch with synthetic coverage prepared locally and can open it as a draft PR once the contributor-side fork/push path is configured. I kept lowercase page-type normalization out of this issue so it can be reviewed as a separate logical change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions