python: Port ntvfs posix bindings to Python 3 compatible form
[Samba.git] / ctdb / common / srvid.c
blob33049941e69b0c7e9afa6fb1bbbde8a6c7aaad90
1 /*
2 Message handler database based on srvid
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/>.
20 #include "replace.h"
21 #include "system/filesys.h"
23 #include <tdb.h>
25 #include "lib/util/dlinklist.h"
26 #include "common/db_hash.h"
27 #include "common/srvid.h"
29 struct srvid_handler_list;
31 struct srvid_context {
32 struct db_hash_context *dh;
33 struct srvid_handler_list *list;
36 struct srvid_handler {
37 struct srvid_handler *prev, *next;
38 struct srvid_handler_list *list;
39 srvid_handler_fn handler;
40 void *private_data;
43 struct srvid_handler_list {
44 struct srvid_handler_list *prev, *next;
45 struct srvid_context *srv;
46 uint64_t srvid;
47 struct srvid_handler *h;
52 * Initialise message srvid context and database
54 int srvid_init(TALLOC_CTX *mem_ctx, struct srvid_context **result)
56 struct srvid_context *srv;
57 int ret;
59 srv = talloc_zero(mem_ctx, struct srvid_context);
60 if (srv == NULL) {
61 return ENOMEM;
64 ret = db_hash_init(srv, "messagedb", 8192, DB_HASH_SIMPLE, &srv->dh);
65 if (ret != 0) {
66 talloc_free(srv);
67 return ret;
70 *result = srv;
71 return 0;
75 * Wrapper functions to insert/delete/fetch srvid_hander_list
78 static int srvid_insert(struct srvid_context *srv, uint64_t srvid,
79 struct srvid_handler_list *list)
81 return db_hash_insert(srv->dh, (uint8_t *)&srvid, sizeof(uint64_t),
82 (uint8_t *)&list, sizeof(list));
85 static int srvid_delete(struct srvid_context *srv, uint64_t srvid)
87 return db_hash_delete(srv->dh, (uint8_t *)&srvid, sizeof(uint64_t));
90 static int srvid_fetch_parser(uint8_t *keybuf, size_t keylen,
91 uint8_t *databuf, size_t datalen,
92 void *private_data)
94 struct srvid_handler_list **list =
95 (struct srvid_handler_list **)private_data;
97 if (datalen != sizeof(*list)) {
98 return EIO;
101 *list = *(struct srvid_handler_list **)databuf;
102 return 0;
105 static int srvid_fetch(struct srvid_context *srv, uint64_t srvid,
106 struct srvid_handler_list **list)
108 return db_hash_fetch(srv->dh, (uint8_t *)&srvid, sizeof(uint64_t),
109 srvid_fetch_parser, list);
113 * When a handler is freed, remove it from the list
115 static int srvid_handler_destructor(struct srvid_handler *h)
117 struct srvid_handler_list *list = h->list;
119 DLIST_REMOVE(list->h, h);
120 if (list->h == NULL) {
121 talloc_free(list);
123 return 0;
127 * When a list is freed, remove all handlers and remove db entry
129 static int srvid_handler_list_destructor(struct srvid_handler_list *list)
131 struct srvid_handler *h;
133 while (list->h != NULL) {
134 h = list->h;
135 DLIST_REMOVE(list->h, h);
136 TALLOC_FREE(h);
139 srvid_delete(list->srv, list->srvid);
140 DLIST_REMOVE(list->srv->list, list);
141 return 0;
145 * Register a message handler
147 int srvid_register(struct srvid_context *srv, TALLOC_CTX *mem_ctx,
148 uint64_t srvid, srvid_handler_fn handler,
149 void *private_data)
151 struct srvid_handler_list *list;
152 struct srvid_handler *h;
153 int ret;
155 if (srv == NULL) {
156 return EINVAL;
159 h = talloc_zero(mem_ctx, struct srvid_handler);
160 if (h == NULL) {
161 return ENOMEM;
164 h->handler = handler;
165 h->private_data = private_data;
167 ret = srvid_fetch(srv, srvid, &list);
168 if (ret != 0) {
169 /* srvid not yet registered */
170 list = talloc_zero(srv, struct srvid_handler_list);
171 if (list == NULL) {
172 talloc_free(h);
173 return ENOMEM;
176 list->srv = srv;
177 list->srvid = srvid;
179 ret = srvid_insert(srv, srvid, list);
180 if (ret != 0) {
181 talloc_free(h);
182 talloc_free(list);
183 return ret;
186 DLIST_ADD(srv->list, list);
187 talloc_set_destructor(list, srvid_handler_list_destructor);
190 h->list = list;
191 DLIST_ADD(list->h, h);
192 talloc_set_destructor(h, srvid_handler_destructor);
193 return 0;
197 * Deregister a message handler
199 int srvid_deregister(struct srvid_context *srv, uint64_t srvid,
200 void *private_data)
202 struct srvid_handler_list *list;
203 struct srvid_handler *h;
204 int ret;
206 ret = srvid_fetch(srv, srvid, &list);
207 if (ret != 0) {
208 return ret;
211 for (h = list->h; h != NULL; h = h->next) {
212 if (h->private_data == private_data) {
213 talloc_free(h);
214 return 0;
218 return ENOENT;
222 * Check if a message handler exists
224 int srvid_exists(struct srvid_context *srv, uint64_t srvid, void *private_data)
226 struct srvid_handler_list *list;
227 struct srvid_handler *h;
228 int ret;
230 ret = srvid_fetch(srv, srvid, &list);
231 if (ret != 0) {
232 return ret;
234 if (list->h == NULL) {
235 return ENOENT;
238 if (private_data != NULL) {
239 for (h = list->h; h != NULL; h = h->next) {
240 if (h->private_data == private_data) {
241 return 0;
245 return ENOENT;
248 return 0;
252 * Send a message to registered srvid and srvid_all
254 int srvid_dispatch(struct srvid_context *srv, uint64_t srvid,
255 uint64_t srvid_all, TDB_DATA data)
257 struct srvid_handler_list *list;
258 struct srvid_handler *h;
259 int ret;
261 ret = srvid_fetch(srv, srvid, &list);
262 if (ret == 0) {
263 for (h = list->h; h != NULL; h = h->next) {
264 h->handler(srvid, data, h->private_data);
268 if (srvid_all == 0) {
269 return ret;
272 ret = srvid_fetch(srv, srvid_all, &list);
273 if (ret == 0) {
274 for (h = list->h; h != NULL; h = h->next) {
275 h->handler(srvid, data, h->private_data);
279 return ret;