Change the ctdb_getpnn*() functions to take a destination node parameter so we can...
[sahlberg/ctdb.git] / libctdb / libctdb.c
1 /* 
2    ctdb database library
3    Utility functions to connect to the ctdb daemon
4
5    Copyright (C) Andrew Tridgell  2006
6    Copyright (C) Ronnie sahlberg  2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <poll.h>
23 #include "includes.h"
24 #include "lib/events/events.h"
25 #include "lib/events/events_internal.h"
26 #include "include/ctdb.h"
27 #include "include/ctdb_protocol.h"
28 #include "include/ctdb_private.h"
29 #include <sys/time.h>
30
31 struct ctdb_context *ctdb_connect(const char *addr)
32 {
33         struct event_context *ev;
34         struct ctdb_context *ctdb;
35         int ret;
36
37         ev = event_context_init(NULL);
38
39         /* initialise ctdb */
40         ctdb = ctdb_init(ev);
41         if (ctdb == NULL) {
42                 fprintf(stderr, "Failed to init ctdb\n");
43                 exit(1);
44         }
45
46         ret = ctdb_set_socketname(ctdb, addr);
47         if (ret == -1) {
48                 fprintf(stderr, __location__ " ctdb_set_socketname failed - %s\n", ctdb_errstr(ctdb));
49                 talloc_free(ctdb);
50                 exit(1);
51         }
52
53         ret = ctdb_socket_connect(ctdb);
54         if (ret != 0) {
55                 fprintf(stderr, __location__ " Failed to connect to daemon\n");
56                 talloc_free(ctdb);
57                 return NULL;
58         }
59
60         return ctdb;
61 }
62
63
64 int ctdb_get_fd(struct ctdb_context *ctdb)
65 {
66         return ctdb->daemon.sd;
67 }
68
69 int ctdb_which_events(struct ctdb_context *ctdb)
70 {
71         if (ctdb_queue_length(ctdb->daemon.queue) > 0) {
72                 return POLLIN|POLLOUT;
73         }
74
75         return POLLIN;
76 }
77
78
79
80 /*
81   initialise the ctdb daemon for client applications
82 */
83 struct ctdb_context *ctdb_init(struct event_context *ev)
84 {
85         int ret;
86         struct ctdb_context *ctdb;
87
88         ctdb = talloc_zero(ev, struct ctdb_context);
89         if (ctdb == NULL) {
90                 DEBUG(DEBUG_ERR,(__location__ " talloc_zero failed.\n"));
91                 return NULL;
92         }
93         ctdb->ev  = ev;
94         ctdb->idr = idr_init(ctdb);
95         CTDB_NO_MEMORY_NULL(ctdb, ctdb->idr);
96
97         ret = ctdb_set_socketname(ctdb, CTDB_PATH);
98         if (ret != 0) {
99                 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_socketname failed.\n"));
100                 talloc_free(ctdb);
101                 return NULL;
102         }
103
104
105
106         return ctdb;
107 }
108
109
110
111 /* Ouch.
112  * This is a bit hairy. due to the way ctdbd uses events.
113  * ctdbd quite frequently uses 
114  *     event_add_timed(... timeval_zero() ...)
115  *
116  * for example once it has finished reading off a full pdu off the
117  * domain socket, before calling the actual recdeive function.
118  *
119  * we probably need a new event function to handle these timed events
120  * event_loop_all_queued() or similar
121  */
122 int ctdb_service(struct ctdb_context *ctdb)
123 {
124         int ret;
125         struct timeval t;
126
127         ret = event_loop_once(ctdb->ev);
128         do {
129                 t = common_event_loop_timer_delay(ctdb->ev);
130         } while(timeval_is_zero(&t));
131
132         return 0;
133 }
134
135
136
137 int ctdb_cancel(ctdb_handle *handle)
138 {
139         talloc_free(handle);
140         return 0;
141 }
142
143 struct ctdb_control_cb_data {
144         void *callback;
145         void *private_data;
146 };
147
148
149
150
151 /*************************
152  * GET PNN of local node *
153  *************************/
154 static void
155 ctdb_getpnn_recv_cb(struct ctdb_client_control_state *state)
156 {
157         struct ctdb_control_cb_data *cb_data = state->async.private_data;
158         ctdb_getpnn_cb callback = (ctdb_getpnn_cb)cb_data->callback;
159
160         callback(0, state->status, cb_data->private_data);
161 }
162
163 ctdb_handle *
164 ctdb_getpnn_send(struct ctdb_context *ctdb,
165                         uint32_t destnode,
166                         ctdb_getpnn_cb callback,
167                         void *private_data)
168 {
169         struct ctdb_client_control_state *state;
170         struct ctdb_control_cb_data *cb_data;
171
172         state = ctdb_control_send(ctdb, destnode, 0, 
173                            CTDB_CONTROL_GET_PNN, 0, tdb_null, 
174                            ctdb, NULL);
175
176         if (state == NULL) {
177                 DEBUG(DEBUG_ERR,(__location__ " Failed to send GET_PNN control\n"));
178                 return NULL;
179         }
180
181         if (callback != NULL) {
182                 cb_data = talloc(state, struct ctdb_control_cb_data);
183                 cb_data->callback     = callback;
184                 cb_data->private_data = private_data;
185
186                 state->async.fn           = ctdb_getpnn_recv_cb;
187                 state->async.private_data = cb_data;
188         }
189
190         return (ctdb_handle *)state;
191 }
192
193 int ctdb_getpnn_recv(struct ctdb_context *ctdb, ctdb_handle *handle, uint32_t *pnn)
194 {
195         struct ctdb_client_control_state *state = talloc_get_type(handle, struct ctdb_client_control_state);
196         int ret;
197         int32_t res;
198
199         ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
200         if (ret != 0) {
201                 DEBUG(DEBUG_ERR,(__location__ " ctdb_getpnn_recv failed\n"));
202                 return -1;
203         }
204
205         if (pnn != NULL) {
206                 *pnn = (uint32_t)res;
207         }
208
209         return state->status;
210 }
211
212 int ctdb_getpnn(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *pnn)
213 {
214         struct ctdb_client_control_state *state;
215         
216         state = ctdb_getpnn_send(ctdb, destnode, NULL, NULL);
217         if (state == NULL) {
218                 DEBUG(DEBUG_ERR,(__location__ " ctdb_getpnn_send() failed.\n"));
219                 return -1;
220         }
221
222         return ctdb_getpnn_recv(ctdb, state, pnn);
223 }
224
225
226
227 /***********************
228  * GET RECOVERY MASTER *
229  ***********************/
230 static void
231 ctdb_getrecmaster_recv_cb(struct ctdb_client_control_state *state)
232 {
233         struct ctdb_control_cb_data *cb_data = state->async.private_data;
234         ctdb_getrecmaster_cb callback = (ctdb_getrecmaster_cb)cb_data->callback;
235
236         callback(0, state->status, cb_data->private_data);
237 }
238
239 ctdb_handle *
240 ctdb_getrecmaster_send(struct ctdb_context *ctdb,
241                         uint32_t destnode,
242                         ctdb_getrecmaster_cb callback,
243                         void *private_data)
244 {
245         struct ctdb_client_control_state *state;
246         struct ctdb_control_cb_data *cb_data;
247
248         state = ctdb_control_send(ctdb, destnode, 0, 
249                            CTDB_CONTROL_GET_RECMASTER, 0, tdb_null, 
250                            ctdb, NULL);
251
252         if (state == NULL) {
253                 DEBUG(DEBUG_ERR,(__location__ " Failed to send GET_RECMASTER control\n"));
254                 return NULL;
255         }
256
257         if (callback != NULL) {
258                 cb_data = talloc(state, struct ctdb_control_cb_data);
259                 cb_data->callback     = callback;
260                 cb_data->private_data = private_data;
261
262                 state->async.fn           = ctdb_getrecmaster_recv_cb;
263                 state->async.private_data = cb_data;
264         }
265
266         return (ctdb_handle *)state;
267 }
268
269 int ctdb_getrecmaster_recv(struct ctdb_context *ctdb, ctdb_handle *handle, uint32_t *recmaster)
270 {
271         struct ctdb_client_control_state *state = talloc_get_type(handle, struct ctdb_client_control_state);
272         int ret;
273         int32_t res;
274
275         ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
276         if (ret != 0) {
277                 DEBUG(DEBUG_ERR,(__location__ " ctdb_getrecmaster_recv failed\n"));
278                 return -1;
279         }
280
281         if (recmaster != NULL) {
282                 *recmaster = (uint32_t)res;
283         }
284
285         return state->status;
286 }
287
288 int ctdb_getrecmaster(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *recmaster)
289 {
290         struct ctdb_client_control_state *state;
291         
292         state = ctdb_getrecmaster_send(ctdb, destnode, NULL, NULL);
293         if (state == NULL) {
294                 DEBUG(DEBUG_ERR,(__location__ " ctdb_getrecmaster_send() failed.\n"));
295                 return -1;
296         }
297
298         return ctdb_getrecmaster_recv(ctdb, state, recmaster);
299 }
300
301
302
303
304
305
306
307
308
309
310
311 static void
312 ctdb_set_message_handler_recv_cb(struct ctdb_client_control_state *state)
313 {
314         struct ctdb_control_cb_data *cb_data = state->async.private_data;
315         ctdb_set_message_handler_cb callback = (ctdb_set_message_handler_cb)cb_data->callback;
316
317         callback(state->status, cb_data->private_data);
318 }
319
320
321 /*
322   tell the daemon what messaging srvid we will use, and register the message
323   handler function in the client
324 */
325 ctdb_handle *
326 ctdb_set_message_handler_send(struct ctdb_context *ctdb, uint64_t srvid, 
327                              ctdb_set_message_handler_cb callback,
328                              ctdb_message_fn_t handler,
329                              void *private_data)
330                                     
331 {
332         struct ctdb_client_control_state *state;
333         struct ctdb_control_cb_data *cb_data;
334
335         if (ctdb_register_message_handler(ctdb, ctdb, srvid, handler, private_data) != 0) {
336                 return NULL;
337         }
338
339         state = ctdb_control_send(ctdb, CTDB_CURRENT_NODE, srvid, 
340                            CTDB_CONTROL_REGISTER_SRVID, 0, tdb_null, 
341                            ctdb, NULL);
342
343         if (state == NULL) {
344                 DEBUG(DEBUG_ERR,(__location__ " Failed to send REGISTER_SRVID control\n"));
345                 return NULL;
346         }
347
348         if (callback != NULL) {
349                 cb_data = talloc(state, struct ctdb_control_cb_data);
350                 cb_data->callback     = callback;
351                 cb_data->private_data = private_data;
352
353                 state->async.fn           = ctdb_set_message_handler_recv_cb;
354                 state->async.private_data = cb_data;
355         }
356
357         return (ctdb_handle *)state;
358 }
359
360 int ctdb_set_message_handler_recv(struct ctdb_context *ctdb, ctdb_handle *handle)
361 {
362         struct ctdb_client_control_state *state = talloc_get_type(handle, struct ctdb_client_control_state);
363         int ret;
364         int32_t res;
365
366         ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
367         if (ret != 0 || res != 0) {
368                 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_message_handler_recv failed\n"));
369                 return -1;
370         }
371
372         return state->status;
373 }
374
375 int ctdb_set_message_handler(struct ctdb_context *ctdb, uint64_t srvid, ctdb_message_fn_t handler, void *private_data)
376 {
377         struct ctdb_client_control_state *state;
378         
379         state = ctdb_set_message_handler_send(ctdb, srvid, NULL, handler, private_data);
380         if (state == NULL) {
381                 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_message_handler_send() failed.\n"));
382                 return -1;
383         }
384
385         return ctdb_set_message_handler_recv(ctdb, state);
386 }
387
388
389
390 static void
391 ctdb_remove_message_handler_recv_cb(struct ctdb_client_control_state *state)
392 {
393         struct ctdb_control_cb_data *cb_data = state->async.private_data;
394         ctdb_remove_message_handler_cb callback = (ctdb_remove_message_handler_cb)cb_data->callback;
395
396         callback(state->status, cb_data->private_data);
397 }
398
399
400 ctdb_handle *
401 ctdb_remove_message_handler_send(struct ctdb_context *ctdb, uint64_t srvid, 
402                              ctdb_remove_message_handler_cb callback,
403                              void *private_data)
404                                     
405 {
406         struct ctdb_client_control_state *state;
407         struct ctdb_control_cb_data *cb_data;
408
409         if (ctdb_deregister_message_handler(ctdb, srvid, private_data)) {
410                 return NULL;
411         }
412
413         state = ctdb_control_send(ctdb, CTDB_CURRENT_NODE, srvid, 
414                            CTDB_CONTROL_DEREGISTER_SRVID, 0, tdb_null, 
415                            ctdb, NULL);
416
417         if (state == NULL) {
418                 DEBUG(DEBUG_ERR,(__location__ " Failed to send DEREGISTER_SRVID control\n"));
419                 return NULL;
420         }
421
422         if (callback != NULL) {
423                 cb_data = talloc(state, struct ctdb_control_cb_data);
424                 cb_data->callback     = callback;
425                 cb_data->private_data = private_data;
426
427                 state->async.fn           = ctdb_remove_message_handler_recv_cb;
428                 state->async.private_data = cb_data;
429         }
430
431         return (ctdb_handle *)state;
432 }
433
434
435 int ctdb_remove_message_handler_recv(struct ctdb_context *ctdb, ctdb_handle *handle)
436 {
437         struct ctdb_client_control_state *state = talloc_get_type(handle, struct ctdb_client_control_state);
438         int ret;
439         int32_t res;
440
441         ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
442         if (ret != 0 || res != 0) {
443                 DEBUG(DEBUG_ERR,(__location__ " ctdb_remove_message_handler_recv failed\n"));
444                 return -1;
445         }
446
447         return state->status;
448 }
449
450 /*
451   tell the daemon we no longer want a srvid
452 */
453 int ctdb_remove_message_handler(struct ctdb_context *ctdb, uint64_t srvid, void *private_data)
454 {
455         struct ctdb_client_control_state *state;
456         
457         state = ctdb_remove_message_handler_send(ctdb, srvid, NULL, private_data);
458         if (state == NULL) {
459                 DEBUG(DEBUG_ERR,(__location__ " ctdb_remove_message_handler_send() failed.\n"));
460                 return -1;
461         }
462
463         return ctdb_remove_message_handler_recv(ctdb, state);
464 }