/* src/storage/page.c * Slotted Page - Storage Engine (C) * * Layout (4 KiB): * * Byte 0 Byte 4095 * +----------+--------+--------+--- ---+------+------+ * | Header | Slot 0 | Slot 1 | free |Tuple1|Tuple0| * +----------+--------+--------+--- ---+------+------+ * slots --> <-- tuples * * Header : page_id, num_slots, free_space_offset * Slot : (offset, length) - wo im raw-Array liegt das Tuple? * free_space_offset: naechste Schreibposition fuer Tuple-Daten * startet bei PAGE_SIZE, nimmt ab */ #include "pauldb/storage.h" #include #include #include #define PAGE_SIZE 4096 /* ---- interne Typen (nur in dieser Datei sichtbar) ---- */ typedef struct { uint32_t page_id; uint16_t num_slots; uint16_t free_space_offset; } PageHeader; typedef struct { uint16_t offset; uint16_t length; } Slot; /* oeffentliche Page-Struktur (opak nach aussen) */ struct Page { uint8_t raw[PAGE_SIZE]; }; /* ---- Hilfsfunktionen ---- */ static PageHeader* header(Page* p) { return (PageHeader*) p->raw; } /* ---- API ---- */ Page* page_create(uint32_t page_id) { Page* p = malloc(sizeof(Page)); if (!p) return NULL; memset(p->raw, 0, PAGE_SIZE); PageHeader* h = header(p); h->page_id = page_id; h->num_slots = 0; h->free_space_offset = PAGE_SIZE; return p; } void page_free(Page* p) { free(p); } /* page_insert und page_get folgen im naechsten TDD-Zyklus */ int page_insert(Page* p, const void* data, size_t len) { PageHeader* h = header(p); /* Wo endet der letzte Slot? */ size_t slots_end = sizeof(PageHeader) + ((h->num_slots + 1) * sizeof(Slot)); /* Passt das neue Tuple noch rein? */ if (h->free_space_offset - len < slots_end) return -1; /* Page voll */ /* Tuple-Daten von hinten schreiben */ h->free_space_offset -= (uint16_t) len; memcpy(p->raw + h->free_space_offset, data, len); /* Neuen Slot anlegen */ Slot* s = (Slot*) (p->raw + sizeof(PageHeader)) + h->num_slots; s->offset = h->free_space_offset; s->length = (uint16_t) len; /* Slot-ID zurueckgeben, dann Counter erhoehen */ uint16_t slot_id = h->num_slots; h->num_slots++; return (int) slot_id; } void* page_get(Page* p, uint16_t slot_id, size_t* out_len) { PageHeader* h = header(p); if (slot_id >= h->num_slots) return NULL; /* Slot existiert nicht */ Slot* s = (Slot*) (p->raw + sizeof(PageHeader)) + slot_id; if (out_len) *out_len = s->length; return p->raw + s->offset; }