4 Copyright (C) Amitay Isaacs 2015
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.
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.
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/>.
21 #include "system/network.h"
23 #include "lib/util/tevent_unix.h"
25 #include "client/client.h"
26 #include "tests/src/test_options.h"
27 #include "tests/src/cluster_wait.h"
29 #define TESTDB "fetch_readonly_loop.tdb"
30 #define TESTKEY "testkey"
32 struct fetch_loop_state {
33 struct tevent_context *ev;
34 struct ctdb_client_context *client;
35 struct ctdb_db_context *ctdb_db;
42 static void fetch_loop_start(struct tevent_req *subreq);
43 static void fetch_loop_next(struct tevent_req *subreq);
44 static void fetch_loop_each_second(struct tevent_req *subreq);
45 static void fetch_loop_finish(struct tevent_req *subreq);
47 static struct tevent_req *fetch_loop_send(TALLOC_CTX *mem_ctx,
48 struct tevent_context *ev,
49 struct ctdb_client_context *client,
50 struct ctdb_db_context *ctdb_db,
51 int num_nodes, int timelimit)
53 struct tevent_req *req, *subreq;
54 struct fetch_loop_state *state;
56 req = tevent_req_create(mem_ctx, &state, struct fetch_loop_state);
62 state->client = client;
63 state->ctdb_db = ctdb_db;
64 state->num_nodes = num_nodes;
65 state->timelimit = timelimit;
66 state->key.dptr = discard_const(TESTKEY);
67 state->key.dsize = strlen(TESTKEY);
69 subreq = cluster_wait_send(state, state->ev, state->client,
71 if (tevent_req_nomem(subreq, req)) {
72 return tevent_req_post(req, ev);
74 tevent_req_set_callback(subreq, fetch_loop_start, req);
79 static void fetch_loop_start(struct tevent_req *subreq)
81 struct tevent_req *req = tevent_req_callback_data(
82 subreq, struct tevent_req);
83 struct fetch_loop_state *state = tevent_req_data(
84 req, struct fetch_loop_state);
88 status = cluster_wait_recv(subreq, &ret);
91 tevent_req_error(req, ret);
95 subreq = ctdb_fetch_lock_send(state, state->ev, state->client,
96 state->ctdb_db, state->key, true);
97 if (tevent_req_nomem(subreq, req)) {
100 tevent_req_set_callback(subreq, fetch_loop_next, req);
102 if (ctdb_client_pnn(state->client) == 0) {
103 subreq = tevent_wakeup_send(state, state->ev,
104 tevent_timeval_current_ofs(1, 0));
105 if (tevent_req_nomem(subreq, req)) {
108 tevent_req_set_callback(subreq, fetch_loop_each_second, req);
111 subreq = tevent_wakeup_send(state, state->ev,
112 tevent_timeval_current_ofs(
113 state->timelimit, 0));
114 if (tevent_req_nomem(subreq, req)) {
117 tevent_req_set_callback(subreq, fetch_loop_finish, req);
120 static void fetch_loop_next(struct tevent_req *subreq)
122 struct tevent_req *req = tevent_req_callback_data(
123 subreq, struct tevent_req);
124 struct fetch_loop_state *state = tevent_req_data(
125 req, struct fetch_loop_state);
126 struct ctdb_record_handle *h;
129 h = ctdb_fetch_lock_recv(subreq, NULL, state, NULL, &ret);
132 tevent_req_error(req, ret);
136 state->locks_count += 1;
139 subreq = ctdb_fetch_lock_send(state, state->ev, state->client,
140 state->ctdb_db, state->key, true);
141 if (tevent_req_nomem(subreq, req)) {
144 tevent_req_set_callback(subreq, fetch_loop_next, req);
147 static void fetch_loop_each_second(struct tevent_req *subreq)
149 struct tevent_req *req = tevent_req_callback_data(
150 subreq, struct tevent_req);
151 struct fetch_loop_state *state = tevent_req_data(
152 req, struct fetch_loop_state);
155 status = tevent_wakeup_recv(subreq);
158 tevent_req_error(req, EIO);
162 printf("Locks:%d\r", state->locks_count);
165 subreq = tevent_wakeup_send(state, state->ev,
166 tevent_timeval_current_ofs(1, 0));
167 if (tevent_req_nomem(subreq, req)) {
170 tevent_req_set_callback(subreq, fetch_loop_each_second, req);
173 static void fetch_loop_finish(struct tevent_req *subreq)
175 struct tevent_req *req = tevent_req_callback_data(
176 subreq, struct tevent_req);
177 struct fetch_loop_state *state = tevent_req_data(
178 req, struct fetch_loop_state);
181 status = tevent_wakeup_recv(subreq);
184 tevent_req_error(req, EIO);
188 printf("Locks:%d\n", state->locks_count);
190 tevent_req_done(req);
193 static bool fetch_loop_recv(struct tevent_req *req, int *perr)
197 if (tevent_req_is_unix_error(req, &err)) {
206 int main(int argc, const char *argv[])
208 const struct test_options *opts;
210 struct tevent_context *ev;
211 struct ctdb_client_context *client;
212 struct ctdb_db_context *ctdb_db;
213 struct tevent_req *req;
217 status = process_options_basic(argc, argv, &opts);
222 mem_ctx = talloc_new(NULL);
223 if (mem_ctx == NULL) {
224 fprintf(stderr, "Memory allocation error\n");
228 ev = tevent_context_init(mem_ctx);
230 fprintf(stderr, "Memory allocation error\n");
234 ret = ctdb_client_init(mem_ctx, ev, opts->socket, &client);
236 fprintf(stderr, "Failed to initialize client, ret=%d\n", ret);
240 if (! ctdb_recovery_wait(ev, client)) {
241 fprintf(stderr, "Memory allocation error\n");
245 ret = ctdb_attach(ev, client, tevent_timeval_zero(), TESTDB, 0,
248 fprintf(stderr, "Failed to attach to DB %s\n", TESTDB);
252 req = fetch_loop_send(mem_ctx, ev, client, ctdb_db,
253 opts->num_nodes, opts->timelimit);
255 fprintf(stderr, "Memory allocation error\n");
259 tevent_req_poll(req, ev);
261 status = fetch_loop_recv(req, &ret);
263 fprintf(stderr, "fetch readonly loop test failed\n");
267 talloc_free(mem_ctx);