1 /* $NetBSD: cdbr.c,v 1.2 2010/06/03 12:40:52 veego Exp $ */
3 * Copyright (c) 2010 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Joerg Sonnenberger.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #if HAVE_NBTOOL_CONFIG_H
35 #include "nbtool_config.h"
38 #include <sys/cdefs.h>
39 __RCSID("$NetBSD: cdbr.c,v 1.2 2010/06/03 12:40:52 veego Exp $");
41 #include "namespace.h"
43 #include <sys/bitops.h>
44 #include <sys/endian.h>
56 __weak_alias(cdbr_close
,_cdbr_close
)
57 __weak_alias(cdbr_find
,_cdbr_find
)
58 __weak_alias(cdbr_get
,_cdbr_get
)
59 __weak_alias(cdbr_open
,_cdbr_open
)
72 uint32_t entries_index
;
79 uint32_t entries_index_m
;
80 uint8_t entries_s1
, entries_s2
;
81 uint8_t entries_index_s1
, entries_index_s2
;
86 cdbr_open(const char *path
, int flags
)
93 if ((fd
= open(path
, O_RDONLY
)) == -1)
97 if (fstat(fd
, &sb
) == -1 ||
98 read(fd
, buf
, sizeof(buf
)) != sizeof(buf
) ||
99 memcmp(buf
, "NBCDB\n\0\001", 8) ||
100 (cdbr
= malloc(sizeof(*cdbr
))) == NULL
) {
105 cdbr
->data_size
= le32dec(buf
+ 24);
106 cdbr
->entries
= le32dec(buf
+ 28);
107 cdbr
->entries_index
= le32dec(buf
+ 32);
108 cdbr
->seed
= le32dec(buf
+ 36);
110 if (cdbr
->data_size
< 0x100)
111 cdbr
->offset_size
= 1;
112 else if (cdbr
->data_size
< 0x10000)
113 cdbr
->offset_size
= 2;
115 cdbr
->offset_size
= 4;
117 if (cdbr
->entries_index
< 0x100)
118 cdbr
->index_size
= 1;
119 else if (cdbr
->entries_index
< 0x10000)
120 cdbr
->index_size
= 2;
122 cdbr
->index_size
= 4;
124 cdbr
->mmap_size
= (size_t)sb
.st_size
;
126 if(!(cdbr
->mmap_base
= malloc(cdbr
->mmap_size
))) {
131 if ((size_t)read(fd
, cdbr
->mmap_base
, cdbr
->mmap_size
) != cdbr
->mmap_size
)
133 free(cdbr
->mmap_base
);
138 cdbr
->mmap_base
= mmap(NULL
, cdbr
->mmap_size
, PROT_READ
, MAP_FILE
|MAP_SHARED
, fd
, 0);
142 if (cdbr
->mmap_base
== MAP_FAILED
) {
147 cdbr
->hash_base
= cdbr
->mmap_base
+ 40;
148 cdbr
->offset_base
= cdbr
->hash_base
+ cdbr
->entries_index
* cdbr
->index_size
;
149 if (cdbr
->entries_index
* cdbr
->index_size
% cdbr
->offset_size
)
150 cdbr
->offset_base
+= cdbr
->offset_size
-
151 cdbr
->entries_index
* cdbr
->index_size
% cdbr
->offset_size
;
152 cdbr
->data_base
= cdbr
->offset_base
+ (cdbr
->entries
+ 1) * cdbr
->offset_size
;
154 if (cdbr
->hash_base
< cdbr
->mmap_base
||
155 cdbr
->offset_base
< cdbr
->mmap_base
||
156 cdbr
->data_base
< cdbr
->mmap_base
||
157 cdbr
->data_base
+ cdbr
->data_size
< cdbr
->mmap_base
||
158 cdbr
->data_base
+ cdbr
->data_size
>
159 cdbr
->mmap_base
+ cdbr
->mmap_size
||
160 cdbr
->entries
== 0 || cdbr
->entries_index
== 0) {
166 fast_divide32_prepare(cdbr
->entries
, &cdbr
->entries_m
,
167 &cdbr
->entries_s1
, &cdbr
->entries_s2
);
168 fast_divide32_prepare(cdbr
->entries_index
, &cdbr
->entries_index_m
,
169 &cdbr
->entries_index_s1
, &cdbr
->entries_index_s2
);
174 static inline uint32_t
175 get_uintX(const uint8_t *addr
, uint32_t idx
, int size
)
180 return /* LINTED */le32toh(*(const uint32_t *)addr
);
182 return /* LINTED */le16toh(*(const uint16_t *)addr
);
188 cdbr_entries(struct cdbr
*cdbr
)
191 return cdbr
->entries
;
195 cdbr_get(struct cdbr
*cdbr
, uint32_t idx
, const void **data
, size_t *data_len
)
199 if (idx
>= cdbr
->entries
) {
204 start
= get_uintX(cdbr
->offset_base
, idx
, cdbr
->offset_size
);
205 end
= get_uintX(cdbr
->offset_base
, idx
+ 1, cdbr
->offset_size
);
212 if (end
> cdbr
->data_size
) {
217 *data
= cdbr
->data_base
+ start
;
218 *data_len
= end
- start
;
224 cdbr_find(struct cdbr
*cdbr
, const void *key
, size_t key_len
,
225 const void **data
, size_t *data_len
)
227 uint32_t hashes
[3], idx
;
229 if (cdbr
->entries_index
== 0) {
234 mi_vector_hash(key
, key_len
, cdbr
->seed
, hashes
);
236 hashes
[0] = fast_remainder32(hashes
[0], cdbr
->entries_index
,
237 cdbr
->entries_index_m
, cdbr
->entries_index_s1
,
238 cdbr
->entries_index_s2
);
239 hashes
[1] = fast_remainder32(hashes
[1], cdbr
->entries_index
,
240 cdbr
->entries_index_m
, cdbr
->entries_index_s1
,
241 cdbr
->entries_index_s2
);
242 hashes
[2] = fast_remainder32(hashes
[2], cdbr
->entries_index
,
243 cdbr
->entries_index_m
, cdbr
->entries_index_s1
,
244 cdbr
->entries_index_s2
);
246 idx
= get_uintX(cdbr
->hash_base
, hashes
[0], cdbr
->index_size
);
247 idx
+= get_uintX(cdbr
->hash_base
, hashes
[1], cdbr
->index_size
);
248 idx
+= get_uintX(cdbr
->hash_base
, hashes
[2], cdbr
->index_size
);
250 return cdbr_get(cdbr
, fast_remainder32(idx
, cdbr
->entries
,
251 cdbr
->entries_m
, cdbr
->entries_s1
, cdbr
->entries_s2
), data
,
256 cdbr_close(struct cdbr
*cdbr
)
259 free(cdbr
->mmap_base
);
261 munmap(cdbr
->mmap_base
, cdbr
->mmap_size
);