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