Python implementation of a four-layer DBMS engine (Disk Space Manager,
Buffer Manager, File & Index Manager, Query Processor). Every layer is a
black-box module communicating exclusively through Result dataclasses.
Behaviour is reconfigured per run by config.json — switching the
replacement policy or index strategy never requires a code edit.
- Python 3.8+
- No third-party packages (Python standard library only).
python archive.py config.json input.txt
config.json— see Section "Configuration" below.input.txt— one command per line; supported grammar in PDF section 7.
Output files (all next to archive.py):
| File | Lifetime |
|---|---|
output.txt |
Truncated at start of each run |
stats_output.txt |
Overwritten on every stats cmd |
log.csv |
Append-only, persistent |
<type>.dat |
Relation data pages (persistent) |
<type>.idx |
Index pages (persistent) |
catalog.dat |
System catalog (persistent) |
{
"page_size": 4096,
"max_records_per_page": 10,
"buffer_pool_size": 16,
"replacement_policy": "LRU",
"index_strategy": "bplus_tree"
}| Key | Allowed values |
|---|---|
page_size |
4096 |
max_records_per_page |
up to 10 |
buffer_pool_size |
4, 8, 16, 32, 64 |
replacement_policy |
LRU or MRU |
index_strategy |
heap_scan, hash_index, or bplus_tree |
Three ready-to-use configs are bundled: config_heap.json, config_hash.json,
config_bplus.json.
archive.py # entry point (Section 3 of the spec)
config.json # default config
workload_generator.py # generates input files for experiments
run_experiments.py # harness producing the three result tables
sample_input.txt # PDF Section 9.1 input
disk_space_manager/ # Layer 1 — only file I/O
buffer_manager/ # Layer 2 — page cache with LRU/MRU
file_index_manager/ # Layer 3 — records, slotted pages, indexes
query_processor/ # Layer 4 — parser, dispatcher, output writer
Every layer exports a single class from its package and a set of
Result dataclasses. See */results.py for the inter-layer contracts.
- Each relation lives in
<type>.dat; up to 10 records per page; unpacked slotted page format with a 16-bit bitmap for occupied slots. - Fixed widths:
int = 4 bytessigned big-endian;str = 32 bytesASCII null-padded. - Type and field names allow
[A-Za-z0-9_]to match the PDF sample which usesmilitary_strengthdespite the "alphanumeric only" wording. - System catalog (
catalog.dat): page 0 is the master index of registered types; pages 1..N each hold one type's full metadata.
| Offset | Size | Field |
|---|---|---|
| 0 | 4B | page_id |
| 4 | 1B | page_type |
| 5 | 2B | record_count |
| 7 | 2B | record_size |
| 9 | 2B | slot_count |
| 11 | 2B | bitmap (16 bit) |
| 13 | 4B | next_page_id |
| 17 | 4B | prev_page_id |
| 21 | 11B | reserved |
- heap_scan — Sequential scan across all data pages. No auxiliary index.
- hash_index — Static hash on the primary key; 16 buckets fixed; DJB2
for strings,
value mod 16for ints. Equality only; range falls back to heap_scan. - bplus_tree — B+-tree on PK. Order = 8 (max keys per node) so the tree noticeably grows in depth with modest data sizes. Supports equality and (PK-only int) range; non-PK range falls back to heap_scan.
python run_experiments.py
Produces three markdown tables identical to those in report.md /
report.pdf. All RNG seeded with 42 for reproducibility.
Reproducibility commands are listed in record.txt.
All relations, indexes, the catalog, and log.csv survive process exits.
Restart archive.py with the same working directory and the engine
recovers state by re-reading catalog.dat on construction.