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