source: vendor/current/ctdb/common/db_hash.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 5.2 KB
Line 
1/*
2 Using tdb as a hash table
3
4 Copyright (C) Amitay Isaacs 2015
5
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.
10
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.
15
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/>.
18*/
19
20#include "replace.h"
21#include "system/filesys.h"
22
23#include <talloc.h>
24#include <tdb.h>
25
26#include "common/db_hash.h"
27
28struct db_hash_context {
29 struct tdb_context *db;
30};
31
32
33static int db_hash_destructor(struct db_hash_context *dh)
34{
35 if (dh->db != NULL) {
36 tdb_close(dh->db);
37 dh->db = NULL;
38 }
39 return 0;
40}
41
42int db_hash_init(TALLOC_CTX *mem_ctx, const char *name, int hash_size,
43 enum db_hash_type type, struct db_hash_context **result)
44{
45 struct db_hash_context *dh;
46 int tdb_flags = TDB_INTERNAL | TDB_DISALLOW_NESTING;
47
48 dh = talloc_zero(mem_ctx, struct db_hash_context);
49 if (dh == NULL) {
50 return ENOMEM;
51 }
52
53 if (type == DB_HASH_COMPLEX) {
54 tdb_flags |= TDB_INCOMPATIBLE_HASH;
55 }
56
57 dh->db = tdb_open(name, hash_size, tdb_flags, O_RDWR|O_CREAT, 0);
58 if (dh->db == NULL) {
59 talloc_free(dh);
60 return ENOMEM;
61 }
62
63 talloc_set_destructor(dh, db_hash_destructor);
64 *result = dh;
65 return 0;
66}
67
68static int db_hash_map_tdb_error(struct db_hash_context *dh)
69{
70 enum TDB_ERROR tdb_err;
71 int ret;
72
73 tdb_err = tdb_error(dh->db);
74 switch (tdb_err) {
75 case TDB_SUCCESS:
76 ret = 0; break;
77 case TDB_ERR_OOM:
78 ret = ENOMEM; break;
79 case TDB_ERR_EXISTS:
80 ret = EEXIST; break;
81 case TDB_ERR_NOEXIST:
82 ret = ENOENT; break;
83 case TDB_ERR_EINVAL:
84 ret = EINVAL; break;
85 default:
86 ret = EIO; break;
87 }
88 return ret;
89}
90
91int db_hash_insert(struct db_hash_context *dh, uint8_t *keybuf, size_t keylen,
92 uint8_t *databuf, size_t datalen)
93{
94 TDB_DATA key, data;
95 int ret;
96
97 if (dh == NULL) {
98 return EINVAL;
99 }
100
101 key.dptr = keybuf;
102 key.dsize = keylen;
103
104 data.dptr = databuf;
105 data.dsize = datalen;
106
107 ret = tdb_store(dh->db, key, data, TDB_INSERT);
108 if (ret != 0) {
109 ret = db_hash_map_tdb_error(dh);
110 }
111 return ret;
112}
113
114int db_hash_add(struct db_hash_context *dh, uint8_t *keybuf, size_t keylen,
115 uint8_t *databuf, size_t datalen)
116{
117 TDB_DATA key, data;
118 int ret;
119
120 if (dh == NULL) {
121 return EINVAL;
122 }
123
124 key.dptr = keybuf;
125 key.dsize = keylen;
126
127 data.dptr = databuf;
128 data.dsize = datalen;
129
130 ret = tdb_store(dh->db, key, data, TDB_REPLACE);
131 if (ret != 0) {
132 ret = db_hash_map_tdb_error(dh);
133 }
134 return ret;
135}
136
137int db_hash_delete(struct db_hash_context *dh, uint8_t *keybuf, size_t keylen)
138{
139 TDB_DATA key;
140 int ret;
141
142 key.dptr = keybuf;
143 key.dsize = keylen;
144
145 if (dh == NULL) {
146 return EINVAL;
147 }
148
149 ret = tdb_delete(dh->db, key);
150 if (ret != 0) {
151 ret = db_hash_map_tdb_error(dh);
152 }
153 return ret;
154}
155
156struct db_hash_fetch_state {
157 db_hash_record_parser_fn parser;
158 void *private_data;
159};
160
161static int db_hash_fetch_parser(TDB_DATA key, TDB_DATA data, void *private_data)
162{
163 struct db_hash_fetch_state *state =
164 (struct db_hash_fetch_state *)private_data;
165 int ret;
166
167 ret = state->parser(key.dptr, key.dsize, data.dptr, data.dsize,
168 state->private_data);
169 return ret;
170}
171
172int db_hash_fetch(struct db_hash_context *dh, uint8_t *keybuf, size_t keylen,
173 db_hash_record_parser_fn parser, void *private_data)
174{
175 struct db_hash_fetch_state state;
176 TDB_DATA key;
177 int ret;
178
179 if (dh == NULL || parser == NULL) {
180 return EINVAL;
181 }
182
183 state.parser = parser;
184 state.private_data = private_data;
185
186 key.dptr = keybuf;
187 key.dsize = keylen;
188
189 ret = tdb_parse_record(dh->db, key, db_hash_fetch_parser, &state);
190 if (ret == -1) {
191 return ENOENT;
192 }
193 return ret;
194}
195
196int db_hash_exists(struct db_hash_context *dh, uint8_t *keybuf, size_t keylen)
197{
198 TDB_DATA key;
199 int ret;
200
201 if (dh == NULL) {
202 return EINVAL;
203 }
204
205 key.dptr = keybuf;
206 key.dsize = keylen;
207
208 ret = tdb_exists(dh->db, key);
209 if (ret == 1) {
210 /* Key found */
211 ret = 0;
212 } else {
213 ret = db_hash_map_tdb_error(dh);
214 if (ret == 0) {
215 ret = ENOENT;
216 }
217 }
218 return ret;
219}
220
221struct db_hash_traverse_state {
222 db_hash_record_parser_fn parser;
223 void *private_data;
224};
225
226static int db_hash_traverse_parser(struct tdb_context *tdb,
227 TDB_DATA key, TDB_DATA data,
228 void *private_data)
229{
230 struct db_hash_traverse_state *state =
231 (struct db_hash_traverse_state *)private_data;
232
233 return state->parser(key.dptr, key.dsize, data.dptr, data.dsize,
234 state->private_data);
235}
236
237int db_hash_traverse(struct db_hash_context *dh,
238 db_hash_record_parser_fn parser, void *private_data,
239 int *count)
240{
241 struct db_hash_traverse_state state;
242 int ret;
243
244 if (dh == NULL) {
245 return EINVAL;
246 }
247
248 /* Special case, for counting records */
249 if (parser == NULL) {
250 ret = tdb_traverse_read(dh->db, NULL, NULL);
251 } else {
252 state.parser = parser;
253 state.private_data = private_data;
254
255 ret = tdb_traverse_read(dh->db, db_hash_traverse_parser, &state);
256 }
257
258 if (ret == -1) {
259 ret = db_hash_map_tdb_error(dh);
260 } else {
261 if (count != NULL) {
262 *count = ret;
263 }
264 ret = 0;
265 }
266
267 return ret;
268}
Note: See TracBrowser for help on using the repository browser.