ctdb-client: Do not use sync functions in async computation
authorAmitay Isaacs <amitay@gmail.com>
Fri, 6 Nov 2015 06:08:48 +0000 (17:08 +1100)
committerMartin Schwenke <martins@samba.org>
Wed, 24 Feb 2016 07:44:37 +0000 (08:44 +0100)
This leads to nested event loops.

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
ctdb/client/client_db.c

index 287efd6cad881fa9f7c8120ef41e8934b47fa410..bee148be61dce901be255a390ec0ee5709c6eacd 100644 (file)
@@ -1942,8 +1942,10 @@ struct ctdb_transaction_commit_state {
        uint64_t seqnum;
 };
 
-static void ctdb_transaction_commit_done(struct tevent_req *subreq);
+static void ctdb_transaction_commit_seqnum_done(struct tevent_req *subreq);
 static void ctdb_transaction_commit_try(struct tevent_req *subreq);
+static void ctdb_transaction_commit_done(struct tevent_req *subreq);
+static void ctdb_transaction_commit_seqnum2_done(struct tevent_req *subreq);
 
 struct tevent_req *ctdb_transaction_commit_send(
                                        TALLOC_CTX *mem_ctx,
@@ -1952,7 +1954,7 @@ struct tevent_req *ctdb_transaction_commit_send(
 {
        struct tevent_req *req, *subreq;
        struct ctdb_transaction_commit_state *state;
-       int ret;
+       struct ctdb_req_control request;
 
        req = tevent_req_create(mem_ctx, &state,
                                struct ctdb_transaction_commit_state);
@@ -1963,27 +1965,53 @@ struct tevent_req *ctdb_transaction_commit_send(
        state->ev = ev;
        state->h = h;
 
-       ret = ctdb_ctrl_get_db_seqnum(state, ev, h->client,
-                                     h->client->pnn, tevent_timeval_zero(),
-                                     h->db->db_id, &state->seqnum);
+       ctdb_req_control_get_db_seqnum(&request, h->db->db_id);
+       subreq = ctdb_client_control_send(state, ev, h->client,
+                                         h->client->pnn,
+                                         tevent_timeval_zero(), &request);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, ctdb_transaction_commit_seqnum_done,
+                               req);
+
+       return req;
+}
+
+static void ctdb_transaction_commit_seqnum_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct ctdb_transaction_commit_state *state = tevent_req_data(
+               req, struct ctdb_transaction_commit_state);
+       struct ctdb_reply_control *reply;
+       int ret;
+       bool status;
+
+       status = ctdb_client_control_recv(subreq, &ret, state, &reply);
+       TALLOC_FREE(subreq);
+       if (! status) {
+               tevent_req_error(req, ret);
+               return;
+       }
+
+       ret = ctdb_reply_control_get_db_seqnum(reply, &state->seqnum);
        if (ret != 0) {
                tevent_req_error(req, ret);
-               return tevent_req_post(req, ev);
+               return;
        }
 
-       ret = ctdb_transaction_store_db_seqnum(h, state->seqnum+1);
+       ret = ctdb_transaction_store_db_seqnum(state->h, state->seqnum+1);
        if (ret != 0) {
                tevent_req_error(req, ret);
-               return tevent_req_post(req, ev);
+               return;
        }
 
-       subreq = ctdb_recovery_wait_send(state, ev, h->client);
+       subreq = ctdb_recovery_wait_send(state, state->ev, state->h->client);
        if (tevent_req_nomem(subreq, req)) {
-               return tevent_req_post(req, ev);
+               return;
        }
        tevent_req_set_callback(subreq, ctdb_transaction_commit_try, req);
-
-       return req;
 }
 
 static void ctdb_transaction_commit_try(struct tevent_req *subreq)
@@ -2020,7 +2048,7 @@ static void ctdb_transaction_commit_done(struct tevent_req *subreq)
        struct ctdb_transaction_commit_state *state = tevent_req_data(
                req, struct ctdb_transaction_commit_state);
        struct ctdb_reply_control *reply;
-       uint64_t seqnum;
+       struct ctdb_req_control request;
        int ret;
        bool status;
 
@@ -2044,10 +2072,36 @@ static void ctdb_transaction_commit_done(struct tevent_req *subreq)
                return;
        }
 
-       ret = ctdb_ctrl_get_db_seqnum(state, state->ev, state->h->client,
-                                     state->h->client->pnn,
-                                     tevent_timeval_zero(),
-                                     state->h->db->db_id, &seqnum);
+       ctdb_req_control_get_db_seqnum(&request, state->h->db->db_id);
+       subreq = ctdb_client_control_send(state, state->ev, state->h->client,
+                                         state->h->client->pnn,
+                                         tevent_timeval_zero(), &request);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, ctdb_transaction_commit_seqnum2_done,
+                               req);
+}
+
+static void ctdb_transaction_commit_seqnum2_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct ctdb_transaction_commit_state *state = tevent_req_data(
+               req, struct ctdb_transaction_commit_state);
+       struct ctdb_reply_control *reply;
+       uint64_t seqnum;
+       int ret;
+       bool status;
+
+       status = ctdb_client_control_recv(subreq, &ret, state, &reply);
+       TALLOC_FREE(subreq);
+       if (! status) {
+               tevent_req_error(req, ret);
+               return;
+       }
+
+       ret = ctdb_reply_control_get_db_seqnum(reply, &seqnum);
        if (ret != 0) {
                tevent_req_error(req, ret);
                return;
@@ -2074,19 +2128,15 @@ static void ctdb_transaction_commit_done(struct tevent_req *subreq)
 
 bool ctdb_transaction_commit_recv(struct tevent_req *req, int *perr)
 {
-       struct ctdb_transaction_commit_state *state = tevent_req_data(
-               req, struct ctdb_transaction_commit_state);
        int err;
 
        if (tevent_req_is_unix_error(req, &err)) {
                if (perr != NULL) {
                        *perr = err;
                }
-               TALLOC_FREE(state->h);
                return false;
        }
 
-       TALLOC_FREE(state->h);
        return true;
 }