summaryrefslogtreecommitdiffstats
path: root/squarkdb.c
blob: 543cbb105bce6894b75c98fd0f88aac68088d291 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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, 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);
	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;
}