change the libctdb_ prefix to ctdb_
[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 "include/ctdb.h"
26 #include "include/ctdb_protocol.h"
27 #include "include/ctdb_private.h"
28
29 struct ctdb_context *ctdb_connect(const char *addr)
30 {
31         struct event_context *ev;
32         struct ctdb_context *ctdb;
33         int ret;
34
35         ev = event_context_init(NULL);
36
37         /* initialise ctdb */
38         ctdb = ctdb_init(ev);
39         if (ctdb == NULL) {
40                 fprintf(stderr, "Failed to init ctdb\n");
41                 exit(1);
42         }
43
44         ret = ctdb_set_socketname(ctdb, addr);
45         if (ret == -1) {
46                 fprintf(stderr, __location__ " ctdb_set_socketname failed - %s\n", ctdb_errstr(ctdb));
47                 talloc_free(ctdb);
48                 exit(1);
49         }
50
51         ret = ctdb_socket_connect(ctdb);
52         if (ret != 0) {
53                 fprintf(stderr, __location__ " Failed to connect to daemon\n");
54                 talloc_free(ctdb);
55                 return NULL;
56         }
57
58         return ctdb;
59 }
60
61
62 int ctdb_get_fd(struct ctdb_context *ctdb)
63 {
64         return ctdb->daemon.sd;
65 }
66
67 int ctdb_which_events(struct ctdb_context *ctdb)
68 {
69         if (ctdb_queue_length(ctdb->daemon.queue) > 0) {
70                 return POLLIN|POLLOUT;
71         }
72
73         return POLLIN;
74 }
75
76
77
78 /*
79   initialise the ctdb daemon for client applications
80 */
81 struct ctdb_context *ctdb_init(struct event_context *ev)
82 {
83         int ret;
84         struct ctdb_context *ctdb;
85
86         ctdb = talloc_zero(ev, struct ctdb_context);
87         if (ctdb == NULL) {
88                 DEBUG(DEBUG_ERR,(__location__ " talloc_zero failed.\n"));
89                 return NULL;
90         }
91         ctdb->ev  = ev;
92         ctdb->idr = idr_init(ctdb);
93         CTDB_NO_MEMORY_NULL(ctdb, ctdb->idr);
94
95         ret = ctdb_set_socketname(ctdb, CTDB_PATH);
96         if (ret != 0) {
97                 DEBUG(DEBUG_ERR,(__location__ " ctdb_set_socketname failed.\n"));
98                 talloc_free(ctdb);
99                 return NULL;
100         }
101
102
103
104         return ctdb;
105 }
106
107
108
109 /* Ouch.
110  * This is a bit hairy. due to the way ctdbd uses events.
111  * ctdbd quite frequently uses 
112  *     event_add_timed(... timeval_zero() ...)
113  *
114  * for example once it has finished reading off a full pdu off the
115  * domain socket, before calling the actual recdeive function.
116  *
117  * we probably need a new event function to handle these timed events
118  * event_loop_all_queued() or similar
119  */
120 int ctdb_service(struct ctdb_context *ctdb)
121 {
122         int ret;
123
124         ret = event_loop_once(ctdb->ev);
125         ret = event_loop_once(ctdb->ev);
126
127         return 0;
128 }
129
130
131
132 int ctdb_cancel(ctdb_handle *handle)
133 {
134         talloc_free(handle);
135         return 0;
136 }
137
138 struct ctdb_control_cb_data {
139         void *callback;
140         void *private_data;
141 };
142
143 static void
144 ctdb_getrecmaster_recv_cb(struct ctdb_client_control_state *state)
145 {
146         struct ctdb_control_cb_data *cb_data = state->async.private_data;
147         get_recmaster_cb callback = (get_recmaster_cb)cb_data->callback;
148
149         callback(0, state->status, cb_data->private_data);
150 }
151
152
153 /*
154   get the recovery master of a remote node
155  */
156 ctdb_handle *
157 ctdb_getrecmaster_send(struct ctdb_context *ctdb,
158                         uint32_t destnode,
159                         get_recmaster_cb callback,
160                         void *private_data)
161 {
162         struct ctdb_client_control_state *state;
163         struct ctdb_control_cb_data *cb_data;
164
165         state = ctdb_control_send(ctdb, destnode, 0, 
166                            CTDB_CONTROL_GET_RECMASTER, 0, tdb_null, 
167                            ctdb, NULL, NULL);
168
169         if (callback != NULL) {
170                 cb_data = talloc(state, struct ctdb_control_cb_data);
171                 cb_data->callback     = callback;
172                 cb_data->private_data = private_data;
173
174                 state->async.fn           = ctdb_getrecmaster_recv_cb;
175                 state->async.private_data = cb_data;
176         }
177
178         return (ctdb_handle *)state;
179 }
180
181 int ctdb_getrecmaster_recv(struct ctdb_context *ctdb, ctdb_handle *handle, uint32_t *recmaster)
182 {
183         struct ctdb_client_control_state *state = talloc_get_type(handle, struct ctdb_client_control_state);
184         int ret;
185         int32_t res;
186
187         ret = ctdb_control_recv(ctdb, state, state, NULL, &res, NULL);
188         if (ret != 0) {
189                 DEBUG(DEBUG_ERR,(__location__ " ctdb_getrecmaster_recv failed\n"));
190                 return -1;
191         }
192
193         if (recmaster) {
194                 *recmaster = (uint32_t)res;
195         }
196
197         return 0;
198 }
199
200 int ctdb_getrecmaster(struct ctdb_context *ctdb, uint32_t destnode, uint32_t *recmaster)
201 {
202         struct ctdb_client_control_state *state;
203         
204         state = ctdb_getrecmaster_send(ctdb, destnode, NULL, recmaster);
205         if (state == NULL) {
206                 DEBUG(DEBUG_ERR,(__location__ " ctdb_getrecmaster_send() failed.\n"));
207                 return -1;
208         }
209
210         return ctdb_getrecmaster_recv(ctdb, state, recmaster);
211 }
212
213
214