2 Using tdb as a hash table
4 Copyright (C) Amitay Isaacs 2015
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "system/filesys.h"
26 #include "common/db_hash.h"
28 struct db_hash_context {
29 struct tdb_context *db;
33 static int db_hash_destructor(struct db_hash_context *dh)
42 int db_hash_init(TALLOC_CTX *mem_ctx, const char *name, int hash_size,
43 enum db_hash_type type, struct db_hash_context **result)
45 struct db_hash_context *dh;
46 int tdb_flags = TDB_INTERNAL | TDB_DISALLOW_NESTING;
48 dh = talloc_zero(mem_ctx, struct db_hash_context);
53 if (type == DB_HASH_COMPLEX) {
54 tdb_flags |= TDB_INCOMPATIBLE_HASH;
57 dh->db = tdb_open(name, hash_size, tdb_flags, O_RDWR|O_CREAT, 0);
63 talloc_set_destructor(dh, db_hash_destructor);
68 static int db_hash_map_tdb_error(struct db_hash_context *dh)
70 enum TDB_ERROR tdb_err;
73 tdb_err = tdb_error(dh->db);
91 int db_hash_insert(struct db_hash_context *dh, uint8_t *keybuf, size_t keylen,
92 uint8_t *databuf, size_t datalen)
105 data.dsize = datalen;
107 ret = tdb_store(dh->db, key, data, TDB_INSERT);
109 ret = db_hash_map_tdb_error(dh);
114 int db_hash_add(struct db_hash_context *dh, uint8_t *keybuf, size_t keylen,
115 uint8_t *databuf, size_t datalen)
128 data.dsize = datalen;
130 ret = tdb_store(dh->db, key, data, TDB_REPLACE);
132 ret = db_hash_map_tdb_error(dh);
137 int db_hash_delete(struct db_hash_context *dh, uint8_t *keybuf, size_t keylen)
149 ret = tdb_delete(dh->db, key);
151 ret = db_hash_map_tdb_error(dh);
156 struct db_hash_fetch_state {
157 db_hash_record_parser_fn parser;
161 static int db_hash_fetch_parser(TDB_DATA key, TDB_DATA data, void *private_data)
163 struct db_hash_fetch_state *state =
164 (struct db_hash_fetch_state *)private_data;
167 ret = state->parser(key.dptr, key.dsize, data.dptr, data.dsize,
168 state->private_data);
172 int db_hash_fetch(struct db_hash_context *dh, uint8_t *keybuf, size_t keylen,
173 db_hash_record_parser_fn parser, void *private_data)
175 struct db_hash_fetch_state state;
179 if (dh == NULL || parser == NULL) {
183 state.parser = parser;
184 state.private_data = private_data;
189 ret = tdb_parse_record(dh->db, key, db_hash_fetch_parser, &state);
196 int db_hash_exists(struct db_hash_context *dh, uint8_t *keybuf, size_t keylen)
208 ret = tdb_exists(dh->db, key);
213 ret = db_hash_map_tdb_error(dh);
221 struct db_hash_traverse_state {
222 db_hash_record_parser_fn parser;
226 static int db_hash_traverse_parser(struct tdb_context *tdb,
227 TDB_DATA key, TDB_DATA data,
230 struct db_hash_traverse_state *state =
231 (struct db_hash_traverse_state *)private_data;
233 return state->parser(key.dptr, key.dsize, data.dptr, data.dsize,
234 state->private_data);
237 int db_hash_traverse(struct db_hash_context *dh,
238 db_hash_record_parser_fn parser, void *private_data,
241 struct db_hash_traverse_state state;
248 /* Special case, for counting records */
249 if (parser == NULL) {
250 ret = tdb_traverse_read(dh->db, NULL, NULL);
252 state.parser = parser;
253 state.private_data = private_data;
255 ret = tdb_traverse_read(dh->db, db_hash_traverse_parser, &state);
259 ret = db_hash_map_tdb_error(dh);
270 int db_hash_traverse_update(struct db_hash_context *dh,
271 db_hash_record_parser_fn parser,
272 void *private_data, int *count)
274 struct db_hash_traverse_state state;
277 if (dh == NULL || parser == NULL) {
281 state.parser = parser;
282 state.private_data = private_data;
284 ret = tdb_traverse(dh->db, db_hash_traverse_parser, &state);
286 ret = db_hash_map_tdb_error(dh);