#include #include #include #include #include "squarkdb.h" #define PAGE_SIZE 4096 #define ALIGN(s,a) (((s) + a - 1) & ~(a - 1)) const char *sqdb_section_names[SQDB_SECTION_MAX] = { [SQDB_SECTION_STRINGS] = "strings", [SQDB_SECTION_CATEGORIES] = "categories", [SQDB_SECTION_INDEX] = "index", [SQDB_SECTION_INDEX_MPH] = "index_mph", [SQDB_SECTION_KEYWORD] = "keyword", [SQDB_SECTION_KEYWORD_MPH] = "keyword_mph", }; static int sqdb_allocate(struct sqdb *db, size_t s) { size_t old_size, new_size; void *base; old_size = db->file_length; new_size = ALIGN(db->file_length + s, PAGE_SIZE); if (new_size == ALIGN(db->file_length, PAGE_SIZE)) { db->file_length += s; return old_size; } if (ftruncate(db->fd, new_size) < 0) return -1; if (db->mmap_base == NULL) { base = mmap(NULL, new_size, PROT_READ|PROT_WRITE, MAP_SHARED, db->fd, 0); } else { base = mremap(db->mmap_base, ALIGN(old_size, PAGE_SIZE), new_size, MREMAP_MAYMOVE); } if (base == MAP_FAILED) return -1; db->mmap_base = base; db->file_length += ALIGN(s, 16); return old_size; } int sqdb_create(struct sqdb *db, const char *fn) { struct sqdb_header *hdr; int rc; db->fd = open(fn, O_CREAT | O_TRUNC | O_RDWR, 0666); if (db->fd < 0) return -1; db->file_length = 0; db->mmap_base = NULL; rc = sqdb_allocate(db, sizeof(struct sqdb_header)); if (rc < 0) { close(db->fd); return rc; } hdr = db->mmap_base; strcpy(hdr->description, "Squark Filtering Database"); hdr->version = 1; hdr->magic = 0xdbdbdbdb; hdr->num_sections = SQDB_SECTION_MAX; return 0; } int sqdb_open(struct sqdb *db, const char *fn); void sqdb_close(struct sqdb *db) { if (db->mmap_base) munmap(db->mmap_base, ALIGN(db->file_length, PAGE_SIZE)); close(db->fd); } void *sqdb_section_create(struct sqdb *db, int id, u_int32_t size) { struct sqdb_header *hdr; size_t pos; hdr = db->mmap_base; if (hdr->section[id].offset || hdr->section[id].length) return NULL; pos = sqdb_allocate(db, size); if (pos < 0) return NULL; /* sqdb_allocate can remap mmap_base */ hdr = db->mmap_base; hdr->section[id].offset = pos; hdr->section[id].length = size; return db->mmap_base + pos; } void *sqdb_section_get(struct sqdb *db, int id, u_int32_t *size) { struct sqdb_header *hdr = db->mmap_base; if (hdr->section[id].offset == 0) return NULL; if (size) *size = hdr->section[id].length; return db->mmap_base + hdr->section[id].offset; }