- split up tcp functions into more logical parts
[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 const char *ctdb_errstr(struct ctdb_context *ctdb)
28 {
29         return ctdb->err_msg;
30 }
31
32
33 /*
34   remember an error message
35 */
36 void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...)
37 {
38         va_list ap;
39         talloc_free(ctdb->err_msg);
40         va_start(ap, fmt);
41         ctdb->err_msg = talloc_vasprintf(ctdb, fmt, ap);
42         va_end(ap);
43 }
44
45 /*
46   choose the transport we will use
47 */
48 int ctdb_set_transport(struct ctdb_context *ctdb, const char *transport)
49 {
50         int ctdb_tcp_init(struct ctdb_context *ctdb);
51
52         if (strcmp(transport, "tcp") == 0) {
53                 return ctdb_tcp_init(ctdb);
54         }
55         ctdb_set_error(ctdb, "Unknown transport '%s'\n", transport);
56         return -1;
57 }
58
59
60 /*
61   parse a IP:port pair
62 */
63 static int ctdb_parse_address(struct ctdb_context *ctdb,
64                              TALLOC_CTX *mem_ctx, const char *str,
65                              struct ctdb_address *address)
66 {
67         char *p;
68         p = strchr(str, ':');
69         if (p == NULL) {
70                 ctdb_set_error(ctdb, "Badly formed node '%s'\n", str);
71                 return -1;
72         }
73         
74         address->address = talloc_strndup(mem_ctx, str, p-str);
75         address->port = strtoul(p+1, NULL, 0);
76         return 0;
77 }
78
79
80 /*
81   add a node to the list of active nodes
82 */
83 static int ctdb_add_node(struct ctdb_context *ctdb, char *nstr)
84 {
85         struct ctdb_node *node;
86
87         node = talloc(ctdb, struct ctdb_node);
88         if (ctdb_parse_address(ctdb, node, nstr, &node->address) != 0) {
89                 return -1;
90         }
91         node->ctdb = ctdb;
92
93         if (ctdb->methods->add_node(node) != 0) {
94                 talloc_free(node);
95                 return -1;
96         }
97
98         DLIST_ADD(ctdb->nodes, node);   
99         return 0;
100 }
101
102 /*
103   setup the node list from a file
104 */
105 int ctdb_set_nlist(struct ctdb_context *ctdb, const char *nlist)
106 {
107         char **lines;
108         int nlines;
109         int i;
110
111         lines = file_lines_load(nlist, &nlines, ctdb);
112         if (lines == NULL) {
113                 ctdb_set_error(ctdb, "Failed to load nlist '%s'\n", nlist);
114                 return -1;
115         }
116
117         for (i=0;i<nlines;i++) {
118                 if (ctdb_add_node(ctdb, lines[i]) != 0) {
119                         talloc_free(lines);
120                         return -1;
121                 }
122         }
123         
124         talloc_free(lines);
125         return 0;
126 }
127
128 /*
129   setup the local node address
130 */
131 int ctdb_set_address(struct ctdb_context *ctdb, const char *address)
132 {
133         return ctdb_parse_address(ctdb, ctdb, address, &ctdb->address);
134 }
135
136 /*
137   add a node to the list of active nodes
138 */
139 int ctdb_set_call(struct ctdb_context *ctdb, ctdb_fn_t fn, int id)
140 {
141         struct ctdb_registered_call *call;
142
143         call = talloc(ctdb, struct ctdb_registered_call);
144         call->fn = fn;
145         call->id = id;
146
147         DLIST_ADD(ctdb->calls, call);   
148         return 0;
149 }
150
151 /*
152   attach to a specific database
153 */
154 int ctdb_attach(struct ctdb_context *ctdb, const char *name, int tdb_flags, 
155                 int open_flags, mode_t mode)
156 {
157         /* when we have a separate daemon this will need to be a real
158            file, not a TDB_INTERNAL, so the parent can access it to
159            for ltdb bypass */
160         ctdb->ltdb = tdb_open(name, 0, TDB_INTERNAL, 0, 0);
161         if (ctdb->ltdb == NULL) {
162                 ctdb_set_error(ctdb, "Failed to open tdb %s\n", name);
163                 return -1;
164         }
165         return 0;
166 }
167
168 /*
169   start the protocol going
170 */
171 int ctdb_start(struct ctdb_context *ctdb)
172 {
173         return ctdb->methods->start(ctdb);
174 }
175
176 /*
177   make a remote ctdb call
178 */
179 int ctdb_call(struct ctdb_context *ctdb, TDB_DATA key, int call_id, 
180               TDB_DATA *call_data, TDB_DATA *reply_data)
181 {
182         printf("ctdb_call not implemented\n");
183         return -1;
184 }
185
186 /*
187   check if two addresses are the same
188 */
189 bool ctdb_same_address(struct ctdb_address *a1, struct ctdb_address *a2)
190 {
191         return strcmp(a1->address, a2->address) == 0 && a1->port == a2->port;
192 }
193
194 /*
195   called by the transport layer when a packet comes in
196 */
197 static void ctdb_recv_pkt(struct ctdb_node *node, uint8_t *data, uint32_t length)
198 {
199         printf("received pkt of length %d\n", length);
200 }
201
202 static const struct ctdb_upcalls ctdb_upcalls = {
203         .recv_pkt = ctdb_recv_pkt
204 };
205
206 /*
207   initialise the ctdb daemon. 
208
209   NOTE: In current code the daemon does not fork. This is for testing purposes only
210   and to simplify the code.
211 */
212 struct ctdb_context *ctdb_init(struct event_context *ev)
213 {
214         struct ctdb_context *ctdb;
215
216         ctdb = talloc_zero(ev, struct ctdb_context);
217         ctdb->ev = ev;
218         ctdb->upcalls = &ctdb_upcalls;
219
220         return ctdb;
221 }
222