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;
}
|