Function: writemeta in b-tree-storage-engine/btree.py

Date: 2026-05-29

Time: 10:58

writemeta — PageManager metadata page writer

Purpose

writemeta serializes the B-tree's global metadata into page 0 of the data file. Page 0 is reserved as the "superblock" — it holds the five integers that define the tree's current state. Every structural mutation (insert, delete, split, page allocation, page free) eventually calls this to persist the updated tree shape.

Contract

Preconditions:

Postconditions:

Invariant: Page 0 is always pagesize bytes and always starts with a valid METAFMT header.

Parameters

| Parameter | Type | Meaning |

|-----------|------|---------|

| root | int | Page number of the current root node. Starts at 1 (page 0 is metadata). |

| height | int | Tree height: 1 means the root is a leaf, 2+ means internal nodes exist above leaves. |

| total_keys | int | Total key-value pairs stored across all leaves. Maintained manually by callers. |

| next_free | int | Next page number to allocate when the free list is empty. Monotonically increases. |

| freehead | int | Head of the intrusive free list (a singly-linked list of deallocated pages). NOSIBLING (0xFFFFFFFF) means the list is empty. |

Return Value

None. This is a pure side-effect method.

Algorithm

1. Pack the five integers into 20 bytes using big-endian unsigned format ('>5I').

2. Pad to pagesize with null bytes via ljust. This ensures page 0 occupies exactly one page — the same size as every data page — so page arithmetic (pagenum * page_size) remains valid.

3. Seek to offset 0 — page 0 always lives at the start of the file.

4. Write the padded buffer.

5. Flush the Python-level buffer to the OS. This calls fflush semantics, pushing data out of Python's io.BufferedWriter into the kernel's page cache.

Side Effects

Error Handling

No explicit error handling. Possible exceptions:

Both propagate uncaught to the caller.

Usage Patterns

Two distinct call sites with different safety profiles:

1. PageManager._init_ — called directly during first-time file creation. No WAL protection exists yet; a crash here leaves a partially-initialized file. Acceptable because there's no data to lose.

2. PageManager.writemeta / BTree.writemeta — the public wrapper delegates here. The BTree class's walwritemeta logs to the WAL *before* calling this, providing crash recovery. allocatepage and freepage call write_meta directly (not through WAL), which is a durability gap — though these are always followed by WAL-protected writes in the put/delete paths.

Dependencies

Assumptions not enforced by types

Beliefs