diff options
Diffstat (limited to 'squarkdb.c')
-rw-r--r-- | squarkdb.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/squarkdb.c b/squarkdb.c new file mode 100644 index 0000000..a62ea61 --- /dev/null +++ b/squarkdb.c @@ -0,0 +1,121 @@ +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <sys/mman.h> + +#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; +} + |