119 lines
2.6 KiB
C
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;
|
|
}
|