#define _GNU_SOURCE // SPDX-FileCopyrightText: © 2026 Vladimir Zorin // SPDX-License-Identifier: LicenseRef-OWL-1.0-or-later // Licensed under OWL v1.0+. See LICENSE. #include "mneme.h" #include #include #include #include #include #include #include uint32_t mneme_checksum(const void *data, size_t len) { const uint8_t *p = (const uint8_t *)data; uint32_t h = 2166136261u; for (size_t i = 0; i < len; i++) { h ^= p[i]; h *= 16777619u; } return h; } static uint32_t meta_compute_checksum(const mneme_meta_t *m) { return mneme_checksum(m, offsetof(mneme_meta_t, checksum)); } int mneme_meta_validate(const mneme_meta_t *m) { if (memcmp(m->magic, MNEME_MAGIC, MNEME_MAGIC_LEN) != 0) return 0; if (m->version != MNEME_VERSION) return 0; if (m->page_size != MNEME_PAGE_SIZE) return 0; if (m->checksum != meta_compute_checksum(m)) return 0; return 1; } static void meta_init(mneme_meta_t *m, uint64_t page_count, uint32_t ks_root, uint64_t txn_id) { memset(m, 0, sizeof(*m)); memcpy(m->magic, MNEME_MAGIC, MNEME_MAGIC_LEN); m->version = MNEME_VERSION; m->page_size = MNEME_PAGE_SIZE; m->page_count = page_count; m->retired_root_pgno = 0; m->keyspace_root_pgno = ks_root; m->txn_id = txn_id; m->retired_page_count = 0; m->checksum = meta_compute_checksum(m); } static int meta_write(int fd, uint32_t pgno, const mneme_meta_t *m) { uint8_t page[MNEME_PAGE_SIZE]; memset(page, 0, MNEME_PAGE_SIZE); memcpy(page, m, sizeof(*m)); return pwrite(fd, page, MNEME_PAGE_SIZE, (off_t)pgno * MNEME_PAGE_SIZE) == MNEME_PAGE_SIZE ? 0 : -1; } int mneme_mmap_refresh(mneme_db_t *db) { size_t new_size = (size_t)db->page_count * MNEME_PAGE_SIZE; if (new_size == db->map_size) return 0; if (new_size == 0) { if (db->map != NULL) { munmap(db->map, db->map_size); db->map = NULL; db->map_size = 0; } return 0; } uint8_t *m = (uint8_t *)mmap(NULL, new_size, PROT_READ, MAP_SHARED, db->fd, 0); if (m == MAP_FAILED) return -1; madvise(m, new_size, MADV_RANDOM); if (db->map != NULL) munmap(db->map, db->map_size); db->map = m; db->map_size = new_size; return 0; } static int meta_read_from_fd(int fd, uint32_t pgno, mneme_meta_t *out) { uint8_t page[MNEME_PAGE_SIZE]; if (pread(fd, page, MNEME_PAGE_SIZE, (off_t)pgno * MNEME_PAGE_SIZE) != MNEME_PAGE_SIZE) return -1; memcpy(out, page, sizeof(*out)); return 0; } int mneme_meta_refresh(mneme_db_t *db) { mneme_meta_t meta_a, meta_b; int a_ok = (meta_read_from_fd(db->fd, 0, &meta_a) == 0) && mneme_meta_validate(&meta_a); int b_ok = (meta_read_from_fd(db->fd, 1, &meta_b) == 0) && mneme_meta_validate(&meta_b); if (!a_ok && !b_ok) return -1; mneme_meta_t *chosen; if (a_ok && b_ok) chosen = (meta_a.txn_id >= meta_b.txn_id) ? &meta_a : &meta_b; else if (a_ok) chosen = &meta_a; else chosen = &meta_b; db->meta = *chosen; if (chosen->page_count != db->page_count) { db->page_count = chosen->page_count; if (mneme_mmap_refresh(db) < 0) return -1; } return 0; } int mneme_db_open(const char *path, uint32_t flags, mneme_db_t **out) { int oflags = ((flags & MNEME_OPEN_READONLY) ? O_RDONLY : O_RDWR) | O_CLOEXEC; int created = 0; int fd = open(path, oflags); if (fd < 0) { if (errno != ENOENT || !(flags & MNEME_OPEN_CREATE)) return -1; fd = open(path, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0644); if (fd < 0) return -1; created = 1; } if (created) { uint8_t leaf_page[MNEME_PAGE_SIZE]; memset(leaf_page, 0, MNEME_PAGE_SIZE); mneme_page_hdr_t *hdr = (mneme_page_hdr_t *)leaf_page; hdr->page_type = MNEME_PAGE_LEAF; hdr->free_offset = MNEME_PAGE_HDR_SIZE; hdr->cell_area_end = MNEME_PAGE_SIZE; if (pwrite(fd, leaf_page, MNEME_PAGE_SIZE, 2 * MNEME_PAGE_SIZE) != MNEME_PAGE_SIZE) { close(fd); unlink(path); return -1; } mneme_meta_t meta_a; meta_init(&meta_a, 3, 2, 0); if (meta_write(fd, 0, &meta_a) < 0) { close(fd); unlink(path); return -1; } mneme_meta_t meta_b; memset(&meta_b, 0, sizeof(meta_b)); if (meta_write(fd, 1, &meta_b) < 0) { close(fd); unlink(path); return -1; } if (fdatasync(fd) < 0) { close(fd); unlink(path); return -1; } } mneme_meta_t meta_a, meta_b; int a_read = meta_read_from_fd(fd, 0, &meta_a) == 0; int b_read = meta_read_from_fd(fd, 1, &meta_b) == 0; int a_ok = a_read && mneme_meta_validate(&meta_a); int b_ok = b_read && mneme_meta_validate(&meta_b); if (!a_ok && !b_ok) { /* Distinguish a real MNEME file in an unsupported format version (correct magic, wrong version) from corruption/not-a-database, so the caller can report something actionable. */ int version_mismatch = (a_read && memcmp(meta_a.magic, MNEME_MAGIC, MNEME_MAGIC_LEN) == 0 && meta_a.version != MNEME_VERSION) || (b_read && memcmp(meta_b.magic, MNEME_MAGIC, MNEME_MAGIC_LEN) == 0 && meta_b.version != MNEME_VERSION); close(fd); return version_mismatch ? -2 : -1; } mneme_meta_t *active; if (a_ok && b_ok) active = (meta_a.txn_id >= meta_b.txn_id) ? &meta_a : &meta_b; else if (a_ok) active = &meta_a; else active = &meta_b; mneme_db_t *db = (mneme_db_t *)calloc(1, sizeof(*db)); if (!db) { close(fd); return -1; } db->path = strdup(path); db->fd = fd; db->probe_fd = -1; db->flags = flags; db->page_count = active->page_count; db->meta = *active; if (!db->path) { close(fd); free(db); return -1; } db->probe_fd = open(path, (flags & MNEME_OPEN_READONLY) ? O_RDONLY | O_CLOEXEC : O_RDWR | O_CLOEXEC); if (db->probe_fd < 0 || mneme_ofd_lock_probe(db->probe_fd) < 0) { if (db->probe_fd >= 0) close(db->probe_fd); close(fd); free(db->path); free(db); return -1; } if (mneme_mmap_refresh(db) < 0) { close(db->probe_fd); close(fd); free(db->path); free(db); return -1; } *out = db; return 0; } void mneme_db_close(mneme_db_t *db) { if (!db || db->closed) return; if (db->map && db->map_size > 0) munmap(db->map, db->map_size); if (db->probe_fd >= 0) close(db->probe_fd); if (db->fd >= 0) close(db->fd); free(db->path); db->closed = 1; } int mneme_db_sync(mneme_db_t *db) { if (!db || db->closed) return -1; return fdatasync(db->fd); }