2 * Map names to server_ids
4 * Copyright Volker Lendecke <vl@samba.org> 2014
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"
22 #include "lib/util/server_id.h"
23 #include "lib/util/server_id_db.h"
24 #include "lib/tdb_wrap/tdb_wrap.h"
25 #include "lib/util/strv.h"
26 #include "lib/util/util_tdb.h"
27 #include "lib/util/samba_util.h"
29 static TDB_DATA talloc_tdb_data(void *ptr)
31 return (TDB_DATA) { .dptr = ptr, .dsize = talloc_get_size(ptr) };
40 static int server_id_db_destructor(struct server_id_db *db);
42 struct server_id_db *server_id_db_init(TALLOC_CTX *mem_ctx,
44 const char *base_path,
45 int hash_size, int tdb_flags)
47 struct server_id_db *db;
48 size_t pathlen = strlen(base_path) + 11;
51 db = talloc(mem_ctx, struct server_id_db);
58 snprintf(path, pathlen, "%s/names.tdb", base_path);
60 db->tdb = tdb_wrap_open(db, path, hash_size, tdb_flags,
61 O_RDWR|O_CREAT, 0660);
62 if (db->tdb == NULL) {
67 talloc_set_destructor(db, server_id_db_destructor);
72 void server_id_db_reinit(struct server_id_db *db, struct server_id pid)
75 TALLOC_FREE(db->names);
78 struct server_id server_id_db_pid(struct server_id_db *db)
83 static int server_id_db_destructor(struct server_id_db *db)
87 while ((name = strv_next(db->names, name)) != NULL) {
88 server_id_db_remove(db, name);
94 int server_id_db_add(struct server_id_db *db, const char *name)
96 struct tdb_context *tdb = db->tdb->tdb;
101 n = strv_find(db->names, name);
106 ret = strv_add(db, &db->names, name);
111 key = string_term_tdb_data(name);
114 size_t idlen = server_id_str_buf_unique(db->pid, NULL, 0);
117 server_id_str_buf_unique(db->pid, idbuf, idlen);
121 (TDB_DATA) { .dptr = (uint8_t *)idbuf, .dsize = idlen });
125 enum TDB_ERROR err = tdb_error(tdb);
126 strv_delete(&db->names, strv_find(db->names, name));
127 return map_unix_error_from_tdb(err);
133 int server_id_db_prune_name(struct server_id_db *db, const char *name,
134 struct server_id server)
136 struct tdb_context *tdb = db->tdb->tdb;
137 size_t idbuf_len = server_id_str_buf_unique(server, NULL, 0);
138 char idbuf[idbuf_len];
144 key = string_term_tdb_data(name);
145 server_id_str_buf_unique(server, idbuf, idbuf_len);
147 ret = tdb_chainlock(tdb, key);
149 enum TDB_ERROR err = tdb_error(tdb);
150 return map_unix_error_from_tdb(err);
153 ret = tdb_fetch_talloc(tdb, key, db, &data);
155 tdb_chainunlock(tdb, key);
161 id = strv_find(ids, idbuf);
163 tdb_chainunlock(tdb, key);
168 strv_delete(&ids, id);
169 ret = tdb_store(tdb, key, talloc_tdb_data(ids), TDB_MODIFY);
172 tdb_chainunlock(tdb, key);
177 int server_id_db_remove(struct server_id_db *db, const char *name)
182 n = strv_find(db->names, name);
187 ret = server_id_db_prune_name(db, name, db->pid);
192 strv_delete(&db->names, n);
196 int server_id_db_lookup(struct server_id_db *db, const char *name,
197 TALLOC_CTX *mem_ctx, unsigned *pnum_servers,
198 struct server_id **pservers)
200 struct tdb_context *tdb = db->tdb->tdb;
204 unsigned num_servers;
205 struct server_id *servers;
208 key = string_term_tdb_data(name);
210 ret = tdb_fetch_talloc(tdb, key, mem_ctx, &data);
216 num_servers = strv_count(ids);
218 servers = talloc_array(mem_ctx, struct server_id, num_servers);
219 if (servers == NULL) {
226 for (id = ids; id != NULL; id = strv_next(ids, id)) {
227 servers[i++] = server_id_from_string(NONCLUSTER_VNN, id);
232 *pnum_servers = num_servers;
238 bool server_id_db_lookup_one(struct server_id_db *db, const char *name,
239 struct server_id *server)
242 unsigned num_servers;
243 struct server_id *servers;
245 ret = server_id_db_lookup(db, name, db, &num_servers, &servers);
249 if (num_servers == 0) {
250 TALLOC_FREE(servers);
253 *server = servers[0];
254 TALLOC_FREE(servers);
258 struct server_id_db_traverse_state {
260 int (*fn)(const char *name,
261 unsigned num_servers,
262 const struct server_id *servers,
267 static int server_id_db_traverse_fn(struct tdb_context *tdb,
268 TDB_DATA key, TDB_DATA data,
271 struct server_id_db_traverse_state *state = private_data;
274 unsigned num_servers;
275 struct server_id *servers;
278 if (key.dsize == 0) {
281 if (key.dptr[key.dsize-1] != '\0') {
284 name = (const char *)key.dptr;
286 ids = (char *)talloc_memdup(state->mem_ctx, data.dptr, data.dsize);
291 num_servers = strv_count(ids);
292 servers = talloc_array(ids, struct server_id, num_servers);
296 for (id = ids; id != NULL; id = strv_next(ids, id)) {
297 servers[i++] = server_id_from_string(NONCLUSTER_VNN, id);
300 ret = state->fn(name, num_servers, servers, state->private_data);
307 int server_id_db_traverse_read(struct server_id_db *db,
308 int (*fn)(const char *name,
309 unsigned num_servers,
310 const struct server_id *servers,
314 struct server_id_db_traverse_state state;
317 state = (struct server_id_db_traverse_state) {
318 .fn = fn, .private_data = private_data,
319 .mem_ctx = talloc_new(db)
322 if (state.mem_ctx == NULL) {
326 ret = tdb_traverse_read(db->tdb->tdb, server_id_db_traverse_fn,
328 TALLOC_FREE(state.mem_ctx);