Step 1 of 3 · Reading · ~3 min
Serializing Pages to Disk
Page-Based Storage
Everything so far has lived in RAM
Every lesson up to now — the B-tree, slotted pages, the buffer pool, overflow chains — has built structures that vanish the moment the process exits. A database that can't survive a restart isn't a database, it's a cache. This lesson closes that gap conceptually: serialization is the process of turning your in-memory structures into a flat byte stream that can be written to a file, and deserialization is reading that stream back and reconstructing the exact same structures.
What "serialize a page" actually means
Because you already built pages as fixed-size, self-contained byte layouts (the Slotted Pages lesson), serializing one is almost free: a page is already a byte array by construction. Serializing the whole database is mostly bookkeeping:
DB SAVE:
for each allocated page, in page-id order:
append page.raw_bytes (exactly PAGE_SIZE bytes) to the output stream
encode the output stream as hex text (so it's safe to print/transport as a string)
DB LOAD <hex>:
decode hex back into raw bytes
split the byte stream into PAGE_SIZE-byte chunks, page 0, page 1, page 2, ...
reconstruct each page object from its chunk (parse header, slot array, cells)
Hex encoding (each byte → two hex characters, e.g. 0xFF → "ff") is a common, simple way to represent arbitrary binary data as text — useful here so a "file" can just be a string in your REPL rather than requiring real filesystem I/O. Real databases write raw bytes directly to a file with fixed-offset seeks (page_id * PAGE_SIZE tells you exactly where to read/write, no scanning needed) — hex-as-a-string is a stand-in for that same idea in a testable, in-memory exercise.
Keeping the REPL surface intact
This lesson's exercise is explicit that the SQL-ish surface from earlier lessons must keep working exactly as before:
CREATE TABLE <name> (<col> <type>, ...)→OKINSERT INTO <table> VALUES (...)→OKSELECT * FROM <table>→ prints matching rows.count <table>→ row count.dump <table>→ full contents
Don't let the serialization work regress any of this — it's easy to refactor "how a table stores its rows" while adding DB SAVE/DB LOAD and accidentally break INSERT/SELECT. Keep the table layer's tests green before and after this change.
DB PAGES — an honest seam, not a shortcut
The new command in this lesson, DB PAGES, reports how many pages the low-level page allocator you built in the Slotted Pages / Page Cache lessons currently has allocated. Read that carefully: it's asking about the page subsystem, not about tables. In this simplified engine, ordinary table rows (INSERT INTO ...) are not required to be routed through that page allocator — they can keep using whatever simple in-memory row storage you already have from earlier chapters. That means DB PAGES legitimately reports 0 for a database that only ever used CREATE TABLE/INSERT INTO, because no calls into the page allocator happened at all.
This is intentional, not a bug to work around: the exercise is testing that you understand which subsystem owns which data, and that you don't fake a nonzero page count just to make the output "look more real." If you choose to additionally wire table storage through your page allocator (optional, more ambitious), DB PAGES should then reflect the true count of pages your allocator handed out — but the baseline, correct behavior for the given example is simply 0.
Edge cases
DB SAVE/DB LOADround-tripping an empty database (zero pages) — should produce an empty (or minimal-header) hex string, and loading it back should leave you with zero pages, not an error.- Hex decoding malformed input (odd-length string, non-hex characters) — decide on and document a clear error rather than crashing.
- Make sure
.count/.dump/SELECTstill reflect table state correctly after aDB LOAD, if your design has tables persist through save/load at all — or clearly scopeDB SAVE/LOADto the page subsystem only, matching howDB PAGESis scoped.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…