ctdb-client: Add async api for detaching a database
authorAmitay Isaacs <amitay@gmail.com>
Tue, 18 Apr 2017 06:44:29 +0000 (16:44 +1000)
committerMartin Schwenke <martins@samba.org>
Wed, 7 Jun 2017 14:05:26 +0000 (16:05 +0200)
Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
ctdb/client/client.h
ctdb/client/client_db.c
ctdb/tools/ctdb.c

index 928fcd52d29ea6347a2a3c55fde7277c979cf609..64fe75da5a053d2f556db75ee7335d01f382a39c 100644 (file)
@@ -689,7 +689,14 @@ int ctdb_attach(struct tevent_context *ev,
                const char *db_name, uint8_t db_flags,
                struct ctdb_db_context **out);
 
-int ctdb_detach(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+struct tevent_req *ctdb_detach_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   struct ctdb_client_context *client,
+                                   struct timeval timeout, uint32_t db_id);
+
+bool ctdb_detach_recv(struct tevent_req *req, int *perr);
+
+int ctdb_detach(struct tevent_context *ev,
                struct ctdb_client_context *client,
                struct timeval timeout, uint32_t db_id);
 
index 604034335a17ddf317ab650c3fe649e716e9dec2..a0a884ff183be70e63b0b38569f2d11058344597 100644 (file)
@@ -596,26 +596,167 @@ int ctdb_attach(struct tevent_context *ev,
        return 0;
 }
 
-int ctdb_detach(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
-               struct ctdb_client_context *client,
-               struct timeval timeout, uint32_t db_id)
+struct ctdb_detach_state {
+       struct ctdb_client_context *client;
+       struct tevent_context *ev;
+       struct timeval timeout;
+       uint32_t db_id;
+       const char *db_name;
+};
+
+static void ctdb_detach_dbname_done(struct tevent_req *subreq);
+static void ctdb_detach_done(struct tevent_req *subreq);
+
+struct tevent_req *ctdb_detach_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   struct ctdb_client_context *client,
+                                   struct timeval timeout, uint32_t db_id)
+{
+       struct tevent_req *req, *subreq;
+       struct ctdb_detach_state *state;
+       struct ctdb_req_control request;
+
+       req = tevent_req_create(mem_ctx, &state, struct ctdb_detach_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       state->client = client;
+       state->ev = ev;
+       state->timeout = timeout;
+       state->db_id = db_id;
+
+       ctdb_req_control_get_dbname(&request, db_id);
+       subreq = ctdb_client_control_send(state, ev, client,
+                                         ctdb_client_pnn(client), timeout,
+                                         &request);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, ctdb_detach_dbname_done, req);
+
+       return req;
+}
+
+static void ctdb_detach_dbname_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct ctdb_detach_state *state = tevent_req_data(
+               req, struct ctdb_detach_state);
+       struct ctdb_reply_control *reply;
+       struct ctdb_req_control request;
+       int ret;
+       bool status;
+
+       status = ctdb_client_control_recv(subreq, &ret, state, &reply);
+       TALLOC_FREE(subreq);
+       if (! status) {
+               DEBUG(DEBUG_ERR, ("detach: 0x%x GET_DBNAME failed, ret=%d\n",
+                                 state->db_id, ret));
+               tevent_req_error(req, ret);
+               return;
+       }
+
+       ret = ctdb_reply_control_get_dbname(reply, state, &state->db_name);
+       if (ret != 0) {
+               DEBUG(DEBUG_ERR, ("detach: 0x%x GET_DBNAME failed, ret=%d\n",
+                                 state->db_id, ret));
+               tevent_req_error(req, ret);
+               return;
+       }
+
+       ctdb_req_control_db_detach(&request, state->db_id);
+       subreq = ctdb_client_control_send(state, state->ev, state->client,
+                                         ctdb_client_pnn(state->client),
+                                         state->timeout, &request);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, ctdb_detach_done, req);
+
+}
+
+static void ctdb_detach_done(struct tevent_req *subreq)
 {
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct ctdb_detach_state *state = tevent_req_data(
+               req, struct ctdb_detach_state);
+       struct ctdb_reply_control *reply;
        struct ctdb_db_context *db;
        int ret;
+       bool status;
 
-       ret = ctdb_ctrl_db_detach(mem_ctx, ev, client, client->pnn, timeout,
-                                 db_id);
+       status = ctdb_client_control_recv(subreq, &ret, state, &reply);
+       TALLOC_FREE(subreq);
+       if (! status) {
+               DEBUG(DEBUG_ERR, ("detach: %s DB_DETACH failed, ret=%d\n",
+                                 state->db_name, ret));
+               tevent_req_error(req, ret);
+               return;
+       }
+
+       ret = ctdb_reply_control_db_detach(reply);
        if (ret != 0) {
-               return ret;
+               DEBUG(DEBUG_ERR, ("detach: %s DB_DETACH failed, ret=%d\n",
+                                 state->db_name, ret));
+               tevent_req_error(req, ret);
+               return;
        }
 
-       for (db = client->db; db != NULL; db = db->next) {
-               if (db->db_id == db_id) {
-                       DLIST_REMOVE(client->db, db);
-                       break;
+       db = client_db_handle(state->client, state->db_name);
+       if (db != NULL) {
+               DLIST_REMOVE(state->client->db, db);
+               TALLOC_FREE(db);
+       }
+
+       tevent_req_done(req);
+}
+
+bool ctdb_detach_recv(struct tevent_req *req, int *perr)
+{
+       int ret;
+
+       if (tevent_req_is_unix_error(req, &ret)) {
+               if (perr != NULL) {
+                       *perr = ret;
                }
+               return false;
        }
 
+       return true;
+}
+
+int ctdb_detach(struct tevent_context *ev,
+               struct ctdb_client_context *client,
+               struct timeval timeout, uint32_t db_id)
+{
+       TALLOC_CTX *mem_ctx;
+       struct tevent_req *req;
+       int ret;
+       bool status;
+
+       mem_ctx = talloc_new(client);
+       if (mem_ctx == NULL) {
+               return ENOMEM;
+       }
+
+       req = ctdb_detach_send(mem_ctx, ev, client, timeout, db_id);
+       if (req == NULL) {
+               talloc_free(mem_ctx);
+               return ENOMEM;
+       }
+
+       tevent_req_poll(req, ev);
+
+       status = ctdb_detach_recv(req, &ret);
+       if (! status) {
+               talloc_free(mem_ctx);
+               return ret;
+       }
+
+       talloc_free(mem_ctx);
        return 0;
 }
 
index 4a255be289d8e035ce1d13992c02adfdb55322fa..e8a128e9ae27b4a1e0190504df8aefad816b33b5 100644 (file)
@@ -2442,8 +2442,7 @@ static int control_detach(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
                        return 1;
                }
 
-               ret = ctdb_detach(mem_ctx, ctdb->ev, ctdb->client,
-                                 TIMEOUT(), db_id);
+               ret = ctdb_detach(ctdb->ev, ctdb->client, TIMEOUT(), db_id);
                if (ret != 0) {
                        fprintf(stderr, "Database %s detach failed\n", db_name);
                        ret2 = ret;