summaryrefslogtreecommitdiffstats
path: root/src/filterdb.c
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2010-11-07 00:47:39 +0200
committerTimo Teräs <timo.teras@iki.fi>2010-11-07 00:47:39 +0200
commit25593b5e6fea76ed7c08db586924032c0810c27e (patch)
treeb632534eb96978ad620fee1e5a9a5d280e0b191e /src/filterdb.c
parente0450bd60a30ca944c16f84ee195463fd4aab653 (diff)
downloadsquark-25593b5e6fea76ed7c08db586924032c0810c27e.tar.bz2
squark-25593b5e6fea76ed7c08db586924032c0810c27e.tar.xz
squark: reorganize sources to src directory
Diffstat (limited to 'src/filterdb.c')
-rw-r--r--src/filterdb.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/filterdb.c b/src/filterdb.c
new file mode 100644
index 0000000..d3f4c6a
--- /dev/null
+++ b/src/filterdb.c
@@ -0,0 +1,157 @@
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include "filterdb.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, int wr)
+{
+ size_t old_size, new_size;
+ void *base;
+ int prot = PROT_READ;
+
+ 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 (wr && ftruncate(db->fd, new_size) < 0)
+ return -1;
+
+ if (db->mmap_base == NULL) {
+ if (wr)
+ prot |= PROT_WRITE;
+ base = mmap(NULL, new_size, prot, 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_open(struct sqdb *db, const char *fn)
+{
+ struct stat st;
+
+ db->fd = open(fn, O_RDONLY);
+ if (db->fd < 0)
+ return -1;
+
+ fstat(db->fd, &st);
+
+ db->file_length = 0;
+ db->mmap_base = NULL;
+ sqdb_allocate(db, st.st_size, 0);
+
+ return 0;
+}
+
+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), 1);
+ 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, uint32_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, 1);
+ 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, uint32_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;
+}
+
+blob_t sqdb_get_string_literal(struct sqdb *db, uint32_t encoded_ptr)
+{
+ unsigned char *ptr;
+ unsigned int len, off;
+
+ ptr = sqdb_section_get(db, SQDB_SECTION_STRINGS, NULL);
+ if (ptr == NULL)
+ return BLOB_NULL;
+
+ off = encoded_ptr >> SQDB_LENGTH_BITS;
+ len = encoded_ptr & ((1 << SQDB_LENGTH_BITS) - 1);
+ if (len == 0)
+ len = ptr[off++];
+
+ return BLOB_PTR_LEN(ptr + off, len);
+}