s3:torture:delete: really fail the test in a failure case
[kai/samba.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 #include "ctdb_protocol.h"
29 #include "messages.h"
30
31 struct ctdb_conn_test_state {
32         struct tevent_context *ev;
33         struct ctdb_conn *conn;
34         struct ctdb_msg_channel *channel;
35         int msgno;
36 };
37
38 static void ctdb_conn_test_got_conn(struct tevent_req *subreq);
39 static void ctdb_conn_test_got_pnn(struct tevent_req *subreq);
40 static void ctdb_conn_test_got_channel(struct tevent_req *subreq);
41 static void ctdb_conn_test_got_msg(struct tevent_req *subreq);
42 static void ctdb_conn_test_msg_sent(struct tevent_req *subreq);
43
44 static struct tevent_req *ctdb_conn_test_send(TALLOC_CTX *mem_ctx,
45                                               struct tevent_context *ev)
46 {
47         struct tevent_req *req, *subreq;
48         struct ctdb_conn_test_state *state;
49
50         req = tevent_req_create(mem_ctx, &state, struct ctdb_conn_test_state);
51         if (req == NULL) {
52                 return NULL;
53         }
54         state->ev = ev;
55
56         subreq = ctdb_conn_init_send(mem_ctx, ev, lp_ctdbd_socket());
57         if (tevent_req_nomem(subreq, req)) {
58                 return tevent_req_post(req, ev);
59         }
60         tevent_req_set_callback(subreq, ctdb_conn_test_got_conn, req);
61         return req;
62 }
63
64 static void ctdb_conn_test_got_conn(struct tevent_req *subreq)
65 {
66         struct tevent_req *req = tevent_req_callback_data(
67                 subreq, struct tevent_req);
68         struct ctdb_conn_test_state *state = tevent_req_data(
69                 req, struct ctdb_conn_test_state);
70         uint64_t ret;
71
72         ret = ctdb_conn_init_recv(subreq, state, &state->conn);
73         TALLOC_FREE(subreq);
74         if (tevent_req_error(req, ret)) {
75                 return;
76         }
77         subreq = ctdb_conn_control_send(state, state->ev, state->conn,
78                                         CTDB_CURRENT_NODE,
79                                         CTDB_CONTROL_GET_PNN, 0, 0, NULL, 0);
80         if (tevent_req_nomem(subreq, req)) {
81                 return;
82         }
83         tevent_req_set_callback(subreq, ctdb_conn_test_got_pnn, req);
84 }
85
86 static void ctdb_conn_test_got_pnn(struct tevent_req *subreq)
87 {
88         struct tevent_req *req = tevent_req_callback_data(
89                 subreq, struct tevent_req);
90         struct ctdb_conn_test_state *state = tevent_req_data(
91                 req, struct ctdb_conn_test_state);
92         int ret;
93         struct ctdb_reply_control *reply;
94
95         ret = ctdb_conn_control_recv(subreq, talloc_tos(), &reply);
96         TALLOC_FREE(subreq);
97         if (tevent_req_error(req, ret)) {
98                 return;
99         }
100         printf("vnn=%d\n", (int)reply->status);
101
102         subreq = ctdb_msg_channel_init_send(
103                 state, state->ev, lp_ctdbd_socket(), 999999);
104         if (tevent_req_nomem(subreq, req)) {
105                 return;
106         }
107         tevent_req_set_callback(subreq, ctdb_conn_test_got_channel, req);
108 }
109
110 static void ctdb_conn_test_got_channel(struct tevent_req *subreq)
111 {
112         struct tevent_req *req = tevent_req_callback_data(
113                 subreq, struct tevent_req);
114         struct ctdb_conn_test_state *state = tevent_req_data(
115                 req, struct ctdb_conn_test_state);
116         int ret;
117
118         ret = ctdb_msg_channel_init_recv(subreq, state, &state->channel);
119         TALLOC_FREE(subreq);
120         if (tevent_req_error(req, ret)) {
121                 return;
122         }
123
124         subreq = ctdb_msg_read_send(state, state->ev, state->channel);
125         if (tevent_req_nomem(subreq, req)) {
126                 return;
127         }
128         tevent_req_set_callback(subreq, ctdb_conn_test_got_msg, req);
129
130         state->msgno += 1;
131
132         subreq = ctdb_conn_msg_write_send(
133                 state, state->ev, state->conn, CTDB_CURRENT_NODE, 999999,
134                 (uint8_t *)&state->msgno, sizeof(state->msgno));
135         if (tevent_req_nomem(subreq, req)) {
136                 return;
137         }
138         tevent_req_set_callback(subreq, ctdb_conn_test_msg_sent, req);
139 }
140
141 static void ctdb_conn_test_got_msg(struct tevent_req *subreq)
142 {
143         struct tevent_req *req = tevent_req_callback_data(
144                 subreq, struct tevent_req);
145         struct ctdb_conn_test_state *state = tevent_req_data(
146                 req, struct ctdb_conn_test_state);
147         uint8_t *buf;
148         size_t buf_len;
149         int ret;
150
151         ret = ctdb_msg_read_recv(subreq, talloc_tos(), &buf, &buf_len);
152         TALLOC_FREE(subreq);
153         if (tevent_req_error(req, ret)) {
154                 return;
155         }
156         if (buf_len != sizeof(int)) {
157                 printf("got invalid msg\n");
158                 tevent_req_error(req, EINVAL);
159                 return;
160         }
161         memcpy(&ret, buf, buf_len);
162         printf("got msg %d\n", ret);
163         if (ret == 5) {
164                 tevent_req_done(req);
165                 return;
166         }
167
168         subreq = ctdb_msg_read_send(state, state->ev, state->channel);
169         if (tevent_req_nomem(subreq, req)) {
170                 return;
171         }
172         tevent_req_set_callback(subreq, ctdb_conn_test_got_msg, req);
173 }
174
175 static void ctdb_conn_test_msg_sent(struct tevent_req *subreq)
176 {
177         struct tevent_req *req = tevent_req_callback_data(
178                 subreq, struct tevent_req);
179         struct ctdb_conn_test_state *state = tevent_req_data(
180                 req, struct ctdb_conn_test_state);
181         int ret;
182
183         ret = ctdb_conn_msg_write_recv(subreq);
184         TALLOC_FREE(subreq);
185         if (tevent_req_error(req, ret)) {
186                 return;
187         }
188         state->msgno += 1;
189
190         if (state->msgno >= 10) {
191                 return;
192         }
193
194         subreq = ctdb_conn_msg_write_send(
195                 state, state->ev, state->conn, CTDB_CURRENT_NODE, 999999,
196                 (uint8_t *)&state->msgno, sizeof(state->msgno));
197         if (tevent_req_nomem(subreq, req)) {
198                 return;
199         }
200         tevent_req_set_callback(subreq, ctdb_conn_test_msg_sent, req);
201 }
202
203 static int ctdb_conn_test_recv(struct tevent_req *req)
204 {
205         int err;
206         if (tevent_req_is_unix_error(req, &err)) {
207                 return err;
208         }
209         return 0;
210 }
211
212 bool run_ctdb_conn(int dummy)
213 {
214         struct tevent_context *ev;
215         struct tevent_req *req;
216         int ret;
217
218         ev = tevent_context_init(talloc_tos());
219         if (ev == NULL) {
220                 fprintf(stderr, "tevent_context_init failed\n");
221                 return false;
222         }
223         req = ctdb_conn_test_send(ev, ev);
224         if (req == NULL) {
225                 fprintf(stderr, "ctdb_conn_test_send failed\n");
226                 return false;
227         }
228         if (!tevent_req_poll(req, ev)) {
229                 fprintf(stderr, "tevent_req_poll failed\n");
230                 return false;
231         }
232         ret = ctdb_conn_test_recv(req);
233         TALLOC_FREE(req);
234         printf("ctdb_conn_test returned %s\n",
235                ret ? strerror(ret) : "success");
236         TALLOC_FREE(ev);
237         return (ret == 0);
238 }
239
240 #else /* CLUSTER_SUPPORT */
241
242 bool run_ctdb_conn(int dummy)
243 {
244         return true;
245 }
246
247 #endif