Files
PaulDB/src/storage/page.c
T

119 lines
2.6 KiB
C

/* 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#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;
}