9d2a6585cfd15ce6deae0efa0f12f71d2a6f8d85
[vlendec/samba-autobuild/.git] / ctdb / common / ctdb.c
1 /* 
2    ctdb over TCP
3
4    Copyright (C) Andrew Tridgell  2006
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10
11    This library 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 GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "includes.h"
22 #include "lib/events/events.h"
23 #include "system/network.h"
24 #include "system/filesys.h"
25 #include "ctdb_private.h"
26
27 /*
28   initialise the ctdb daemon. 
29
30   if the ctdb dispatcher daemon has already been started then this
31   does nothing. Otherwise it forks the ctdb dispatcher daemon and
32   starts the daemons connecting to each other
33   
34   NOTE: In current code the daemon does not fork. This is for testing purposes only
35   and to simplify the code.
36 */
37
38 struct ctdb_context *ctdb_init(struct event_context *ev)
39 {
40         struct ctdb_context *ctdb;
41
42         ctdb = talloc_zero(ev, struct ctdb_context);
43         ctdb->ev = ev;
44
45         return ctdb;
46 }
47
48 const char *ctdb_errstr(struct ctdb_context *ctdb)
49 {
50         return ctdb->err_msg;
51 }
52
53
54 /*
55   remember an error message
56 */
57 void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...)
58 {
59         va_list ap;
60         talloc_free(ctdb->err_msg);
61         va_start(ap, fmt);
62         ctdb->err_msg = talloc_vasprintf(ctdb, fmt, ap);
63         va_end(ap);
64 }
65
66 /*
67   choose the transport we will use
68 */
69 int ctdb_set_transport(struct ctdb_context *ctdb, const char *transport)
70 {
71         int ctdb_tcp_init(struct ctdb_context *ctdb);
72
73         if (strcmp(transport, "tcp") == 0) {
74                 return ctdb_tcp_init(ctdb);
75         }
76         ctdb_set_error(ctdb, "Unknown transport '%s'\n", transport);
77         return -1;
78 }
79
80
81 /*
82   parse a IP:port pair
83 */
84 static int ctdb_parse_address(struct ctdb_context *ctdb,
85                              TALLOC_CTX *mem_ctx, const char *str,
86                              struct ctdb_address *address)
87 {
88         char *p;
89         p = strchr(str, ':');
90         if (p == NULL) {
91                 ctdb_set_error(ctdb, "Badly formed node '%s'\n", str);
92                 return -1;
93         }
94         
95         address->address = talloc_strndup(mem_ctx, str, p-str);
96         address->port = strtoul(p+1, NULL, 0);
97         return 0;
98 }
99
100
101 /*
102   add a node to the list of active nodes
103 */
104 static int ctdb_add_node(struct ctdb_context *ctdb, char *nstr)
105 {
106         struct ctdb_node *node;
107
108         node = talloc(ctdb, struct ctdb_node);
109         if (ctdb_parse_address(ctdb, node, nstr, &node->address) != 0) {
110                 return -1;
111         }
112         node->ctdb = ctdb;
113
114         if (ctdb->methods->add_node(node) != 0) {
115                 talloc_free(node);
116                 return -1;
117         }
118
119         DLIST_ADD(ctdb->nodes, node);   
120         return 0;
121 }
122
123 /*
124   setup the node list from a file
125 */
126 int ctdb_set_nlist(struct ctdb_context *ctdb, const char *nlist)
127 {
128         char **lines;
129         int nlines;
130         int i;
131
132         lines = file_lines_load(nlist, &nlines, ctdb);
133         if (lines == NULL) {
134                 ctdb_set_error(ctdb, "Failed to load nlist '%s'\n", nlist);
135                 return -1;
136         }
137
138         for (i=0;i<nlines;i++) {
139                 if (ctdb_add_node(ctdb, lines[i]) != 0) {
140                         talloc_free(lines);
141                         return -1;
142                 }
143         }
144         
145         talloc_free(lines);
146         return 0;
147 }
148
149 /*
150   setup the local node address
151 */
152 int ctdb_set_address(struct ctdb_context *ctdb, const char *address)
153 {
154         return ctdb_parse_address(ctdb, ctdb, address, &ctdb->address);
155 }
156
157 /*
158   add a node to the list of active nodes
159 */
160 int ctdb_set_call(struct ctdb_context *ctdb, ctdb_fn_t fn, int id)
161 {
162         struct ctdb_registered_call *call;
163
164         call = talloc(ctdb, struct ctdb_registered_call);
165         call->fn = fn;
166         call->id = id;
167
168         DLIST_ADD(ctdb->calls, call);   
169         return 0;
170 }
171
172 /*
173   attach to a specific database
174 */
175 int ctdb_attach(struct ctdb_context *ctdb, const char *name, int tdb_flags, 
176                 int open_flags, mode_t mode)
177 {
178         /* when we have a separate daemon this will need to be a real
179            file, not a TDB_INTERNAL, so the parent can access it to
180            for ltdb bypass */
181         ctdb->ltdb = tdb_open(name, 0, TDB_INTERNAL, 0, 0);
182         if (ctdb->ltdb == NULL) {
183                 ctdb_set_error(ctdb, "Failed to open tdb %s\n", name);
184                 return -1;
185         }
186         return 0;
187 }
188
189 /*
190   start the protocol going
191 */
192 int ctdb_start(struct ctdb_context *ctdb)
193 {
194         return ctdb->methods->start(ctdb);
195 }
196
197 /*
198   make a remote ctdb call
199 */
200 int ctdb_call(struct ctdb_context *ctdb, TDB_DATA key, int call_id, 
201               TDB_DATA *call_data, TDB_DATA *reply_data)
202 {
203         printf("ctdb_call not implemented\n");
204         return -1;
205 }
206
207 /*
208   check if two addresses are the same
209 */
210 bool ctdb_same_address(struct ctdb_address *a1, struct ctdb_address *a2)
211 {
212         return strcmp(a1->address, a2->address) == 0 && a1->port == a2->port;
213 }
214