ctdb-daemon: Implement DB_VACUUM control
authorMartin Schwenke <martin@meltin.net>
Tue, 30 Jul 2019 04:17:11 +0000 (14:17 +1000)
committerAmitay Isaacs <amitay@samba.org>
Thu, 24 Oct 2019 04:06:43 +0000 (04:06 +0000)
Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
ctdb/include/ctdb_private.h
ctdb/server/ctdb_control.c
ctdb/server/ctdb_vacuum.c

index b42b32a3967c2bba9a42b41abbfc55430888ac55..4f36c9a44a54c85c6f4ffc63a25be61906f422dc 100644 (file)
@@ -986,6 +986,11 @@ int32_t ctdb_control_uptime(struct ctdb_context *ctdb, TDB_DATA *outdata);
 
 /* from ctdb_vacuum.c */
 
+int32_t ctdb_control_db_vacuum(struct ctdb_context *ctdb,
+                              struct ctdb_req_control_old *c,
+                              TDB_DATA indata,
+                              bool *async_reply);
+
 void ctdb_stop_vacuuming(struct ctdb_context *ctdb);
 int ctdb_vacuum_init(struct ctdb_db_context *ctdb_db);
 
index 0174f303f1410048fdbd43ab30a491ef47a5b41e..d162268a178ca2cdf41bbcaae4c3822c2e3cd361 100644 (file)
@@ -33,6 +33,8 @@
 #include "ctdb_private.h"
 #include "ctdb_client.h"
 
+#include "protocol/protocol_private.h"
+
 #include "common/reqid.h"
 #include "common/common.h"
 #include "common/logging.h"
@@ -732,6 +734,13 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
        case CTDB_CONTROL_VACUUM_FETCH:
                return ctdb_control_vacuum_fetch(ctdb, indata);
 
+       case CTDB_CONTROL_DB_VACUUM: {
+               struct ctdb_db_vacuum db_vacuum;
+
+               CHECK_CONTROL_DATA_SIZE(ctdb_db_vacuum_len(&db_vacuum));
+               return ctdb_control_db_vacuum(ctdb, c, indata, async_reply);
+       }
+
        default:
                DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
                return -1;
index 8df362be233ed0e7d3caf51022b5096ec104b100..5351a3c51756b8d83249fca007f9a6ee195464df 100644 (file)
@@ -37,6 +37,8 @@
 #include "ctdb_private.h"
 #include "ctdb_client.h"
 
+#include "protocol/protocol_private.h"
+
 #include "common/rb_tree.h"
 #include "common/common.h"
 #include "common/logging.h"
@@ -1555,6 +1557,93 @@ static void ctdb_vacuum_event(struct tevent_context *ev,
 
 }
 
+struct vacuum_control_state {
+       struct ctdb_vacuum_child_context *child_ctx;
+       struct ctdb_req_control_old *c;
+       struct ctdb_context *ctdb;
+};
+
+static int vacuum_control_state_destructor(struct vacuum_control_state *state)
+{
+       struct ctdb_vacuum_child_context *child_ctx = state->child_ctx;
+       int32_t status;
+
+       status = (child_ctx->status == VACUUM_OK ? 0 : -1);
+       ctdb_request_control_reply(state->ctdb, state->c, NULL, status, NULL);
+
+       return 0;
+}
+
+int32_t ctdb_control_db_vacuum(struct ctdb_context *ctdb,
+                              struct ctdb_req_control_old *c,
+                              TDB_DATA indata,
+                              bool *async_reply)
+{
+       struct ctdb_db_context *ctdb_db;
+       struct ctdb_vacuum_child_context *child_ctx = NULL;
+       struct ctdb_db_vacuum *db_vacuum;
+       struct vacuum_control_state *state;
+       size_t np;
+       int ret;
+
+       ret = ctdb_db_vacuum_pull(indata.dptr,
+                                 indata.dsize,
+                                 ctdb,
+                                 &db_vacuum,
+                                 &np);
+       if (ret != 0) {
+               DBG_ERR("Invalid data\n");
+               return -1;
+       }
+
+       ctdb_db = find_ctdb_db(ctdb, db_vacuum->db_id);
+       if (ctdb_db == NULL) {
+               DBG_ERR("Unknown db id 0x%08x\n", db_vacuum->db_id);
+               talloc_free(db_vacuum);
+               return -1;
+       }
+
+       state = talloc(ctdb, struct vacuum_control_state);
+       if (state == NULL) {
+               DBG_ERR("Memory allocation error\n");
+               return -1;
+       }
+
+       ret = vacuum_db_child(ctdb_db,
+                             ctdb_db,
+                             false,
+                             db_vacuum->full_vacuum_run,
+                             &child_ctx);
+
+       talloc_free(db_vacuum);
+
+       if (ret == 0) {
+               (void) talloc_steal(child_ctx, state);
+
+               state->child_ctx = child_ctx;
+               state->c = talloc_steal(state, c);
+               state->ctdb = ctdb;
+
+               talloc_set_destructor(state, vacuum_control_state_destructor);
+
+               *async_reply = true;
+               return 0;
+       }
+
+       talloc_free(state);
+
+       switch (ret) {
+       case EBUSY:
+               DBG_WARNING("Vacuuming collision\n");
+               break;
+
+       default:
+               DBG_ERR("Temporary vacuuming failure, ret=%d\n", ret);
+       }
+
+       return -1;
+}
+
 void ctdb_stop_vacuuming(struct ctdb_context *ctdb)
 {
        if (ctdb->vacuumer != NULL) {