From 8e3ed87cacca41f113072d9b8eb6ff328ee73ba1 Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Tue, 18 Apr 2017 16:44:29 +1000 Subject: [PATCH] ctdb-client: Add async api for detaching a database Signed-off-by: Amitay Isaacs Reviewed-by: Martin Schwenke --- ctdb/client/client.h | 9 ++- ctdb/client/client_db.c | 161 +++++++++++++++++++++++++++++++++++++--- ctdb/tools/ctdb.c | 3 +- 3 files changed, 160 insertions(+), 13 deletions(-) diff --git a/ctdb/client/client.h b/ctdb/client/client.h index 928fcd52d29..64fe75da5a0 100644 --- a/ctdb/client/client.h +++ b/ctdb/client/client.h @@ -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); diff --git a/ctdb/client/client_db.c b/ctdb/client/client_db.c index 604034335a1..a0a884ff183 100644 --- a/ctdb/client/client_db.c +++ b/ctdb/client/client_db.c @@ -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; } diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c index 4a255be289d..e8a128e9ae2 100644 --- a/ctdb/tools/ctdb.c +++ b/ctdb/tools/ctdb.c @@ -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; -- 2.47.2