s3-torture:test_ctdbconn: fix the build against older ctdb versions
[metze/samba/wip.git] / source3 / torture / test_ctdbconn.c
1 /*
2    Unix SMB/CIFS implementation.
3    Test new ctdb API
4    Copyright (C) Volker Lendecke 2012
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program 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
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "torture/proto.h"
22
23 #ifdef CLUSTER_SUPPORT
24
25 #include "ctdb_conn.h"
26 #include "lib/util/tevent_unix.h"
27 #include "tdb.h"
28
29 #ifdef HAVE_CTDB_PROTOCOL_H
30 #include "ctdb_protocol.h"
31 #else
32 #include "ctdb_private.h"
33 #endif
34
35 #include "messages.h"
36
37 struct ctdb_conn_test_state {
38         struct tevent_context *ev;
39         struct ctdb_conn *conn;
40         struct ctdb_msg_channel *channel;
41         int msgno;
42 };
43
44 static void ctdb_conn_test_got_conn(struct tevent_req *subreq);
45 static void ctdb_conn_test_got_pnn(struct tevent_req *subreq);
46 static void ctdb_conn_test_got_channel(struct tevent_req *subreq);
47 static void ctdb_conn_test_got_msg(struct tevent_req *subreq);
48 static void ctdb_conn_test_msg_sent(struct tevent_req *subreq);
49
50 static struct tevent_req *ctdb_conn_test_send(TALLOC_CTX *mem_ctx,
51                                               struct tevent_context *ev)
52 {
53         struct tevent_req *req, *subreq;
54         struct ctdb_conn_test_state *state;
55
56         req = tevent_req_create(mem_ctx, &state, struct ctdb_conn_test_state);
57         if (req == NULL) {
58                 return NULL;
59         }
60         state->ev = ev;
61
62         subreq = ctdb_conn_init_send(mem_ctx, ev, lp_ctdbd_socket());
63         if (tevent_req_nomem(subreq, req)) {
64                 return tevent_req_post(req, ev);
65         }
66         tevent_req_set_callback(subreq, ctdb_conn_test_got_conn, req);
67         return req;
68 }
69
70 static void ctdb_conn_test_got_conn(struct tevent_req *subreq)
71 {
72         struct tevent_req *req = tevent_req_callback_data(
73                 subreq, struct tevent_req);
74         struct ctdb_conn_test_state *state = tevent_req_data(
75                 req, struct ctdb_conn_test_state);
76         uint64_t ret;
77
78         ret = ctdb_conn_init_recv(subreq, state, &state->conn);
79         TALLOC_FREE(subreq);
80         if (tevent_req_error(req, ret)) {
81                 return;
82         }
83         subreq = ctdb_conn_control_send(state, state->ev, state->conn,
84                                         CTDB_CURRENT_NODE,
85                                         CTDB_CONTROL_GET_PNN, 0, 0, NULL, 0);
86         if (tevent_req_nomem(subreq, req)) {
87                 return;
88         }
89         tevent_req_set_callback(subreq, ctdb_conn_test_got_pnn, req);
90 }
91
92 static void ctdb_conn_test_got_pnn(struct tevent_req *subreq)
93 {
94         struct tevent_req *req = tevent_req_callback_data(
95                 subreq, struct tevent_req);
96         struct ctdb_conn_test_state *state = tevent_req_data(
97                 req, struct ctdb_conn_test_state);
98         int ret;
99         struct ctdb_reply_control *reply;
100
101         ret = ctdb_conn_control_recv(subreq, talloc_tos(), &reply);
102         TALLOC_FREE(subreq);
103         if (tevent_req_error(req, ret)) {
104                 return;
105         }
106         printf("vnn=%d\n", (int)reply->status);
107
108         subreq = ctdb_msg_channel_init_send(
109                 state, state->ev, lp_ctdbd_socket(), 999999);
110         if (tevent_req_nomem(subreq, req)) {
111                 return;
112         }
113         tevent_req_set_callback(subreq, ctdb_conn_test_got_channel, req);
114 }
115
116 static void ctdb_conn_test_got_channel(struct tevent_req *subreq)
117 {
118         struct tevent_req *req = tevent_req_callback_data(
119                 subreq, struct tevent_req);
120         struct ctdb_conn_test_state *state = tevent_req_data(
121                 req, struct ctdb_conn_test_state);
122         int ret;
123
124         ret = ctdb_msg_channel_init_recv(subreq, state, &state->channel);
125         TALLOC_FREE(subreq);
126         if (tevent_req_error(req, ret)) {
127                 return;
128         }
129
130         subreq = ctdb_msg_read_send(state, state->ev, state->channel);
131         if (tevent_req_nomem(subreq, req)) {
132                 return;
133         }
134         tevent_req_set_callback(subreq, ctdb_conn_test_got_msg, req);
135
136         state->msgno += 1;
137
138         subreq = ctdb_conn_msg_write_send(
139                 state, state->ev, state->conn, CTDB_CURRENT_NODE, 999999,
140                 (uint8_t *)&state->msgno, sizeof(state->msgno));
141         if (tevent_req_nomem(subreq, req)) {
142                 return;
143         }
144         tevent_req_set_callback(subreq, ctdb_conn_test_msg_sent, req);
145 }
146
147 static void ctdb_conn_test_got_msg(struct tevent_req *subreq)
148 {
149         struct tevent_req *req = tevent_req_callback_data(
150                 subreq, struct tevent_req);
151         struct ctdb_conn_test_state *state = tevent_req_data(
152                 req, struct ctdb_conn_test_state);
153         uint8_t *buf;
154         size_t buf_len;
155         int ret;
156
157         ret = ctdb_msg_read_recv(subreq, talloc_tos(), &buf, &buf_len);
158         TALLOC_FREE(subreq);
159         if (tevent_req_error(req, ret)) {
160                 return;
161         }
162         if (buf_len != sizeof(int)) {
163                 printf("got invalid msg\n");
164                 tevent_req_error(req, EINVAL);
165                 return;
166         }
167         memcpy(&ret, buf, buf_len);
168         printf("got msg %d\n", ret);
169         if (ret == 5) {
170                 tevent_req_done(req);
171                 return;
172         }
173
174         subreq = ctdb_msg_read_send(state, state->ev, state->channel);
175         if (tevent_req_nomem(subreq, req)) {
176                 return;
177         }
178         tevent_req_set_callback(subreq, ctdb_conn_test_got_msg, req);
179 }
180
181 static void ctdb_conn_test_msg_sent(struct tevent_req *subreq)
182 {
183         struct tevent_req *req = tevent_req_callback_data(
184                 subreq, struct tevent_req);
185         struct ctdb_conn_test_state *state = tevent_req_data(
186                 req, struct ctdb_conn_test_state);
187         int ret;
188
189         ret = ctdb_conn_msg_write_recv(subreq);
190         TALLOC_FREE(subreq);
191         if (tevent_req_error(req, ret)) {
192                 return;
193         }
194         state->msgno += 1;
195
196         if (state->msgno >= 10) {
197                 return;
198         }
199
200         subreq = ctdb_conn_msg_write_send(
201                 state, state->ev, state->conn, CTDB_CURRENT_NODE, 999999,
202                 (uint8_t *)&state->msgno, sizeof(state->msgno));
203         if (tevent_req_nomem(subreq, req)) {
204                 return;
205         }
206         tevent_req_set_callback(subreq, ctdb_conn_test_msg_sent, req);
207 }
208
209 static int ctdb_conn_test_recv(struct tevent_req *req)
210 {
211         int err;
212         if (tevent_req_is_unix_error(req, &err)) {
213                 return err;
214         }
215         return 0;
216 }
217
218 bool run_ctdb_conn(int dummy)
219 {
220         struct tevent_context *ev;
221         struct tevent_req *req;
222         int ret;
223
224         ev = tevent_context_init(talloc_tos());
225         if (ev == NULL) {
226                 fprintf(stderr, "tevent_context_init failed\n");
227                 return false;
228         }
229         req = ctdb_conn_test_send(ev, ev);
230         if (req == NULL) {
231                 fprintf(stderr, "ctdb_conn_test_send failed\n");
232                 return false;
233         }
234         if (!tevent_req_poll(req, ev)) {
235                 fprintf(stderr, "tevent_req_poll failed\n");
236                 return false;
237         }
238         ret = ctdb_conn_test_recv(req);
239         TALLOC_FREE(req);
240         printf("ctdb_conn_test returned %s\n",
241                ret ? strerror(ret) : "success");
242         TALLOC_FREE(ev);
243         return (ret == 0);
244 }
245
246 #else /* CLUSTER_SUPPORT */
247
248 bool run_ctdb_conn(int dummy)
249 {
250         return true;
251 }
252
253 #endif