ctdb-daemon: Add control CTDB_CONTROL_DB_DETACH
authorAmitay Isaacs <amitay@gmail.com>
Mon, 31 Mar 2014 04:44:21 +0000 (15:44 +1100)
committerMartin Schwenke <martins@samba.org>
Mon, 14 Apr 2014 01:52:39 +0000 (03:52 +0200)
This detaches specified database from all the nodes.

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
ctdb/include/ctdb_private.h
ctdb/include/ctdb_protocol.h
ctdb/server/ctdb_control.c
ctdb/server/ctdb_ltdb_server.c

index 2206f4edfd9dcf0fcbb9dbf8ed4806cba9237ea2..81759786dd136d373df2d398509341bfa2f11871 100644 (file)
@@ -900,6 +900,8 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
                               bool persistent, uint32_t client_id,
                               struct ctdb_req_control *c,
                               bool *async_reply);
+int32_t ctdb_control_db_detach(struct ctdb_context *ctdb, TDB_DATA indata,
+                              uint32_t client_id);
 
 int ctdb_daemon_set_call(struct ctdb_context *ctdb, uint32_t db_id,
                         ctdb_fn_t fn, int id);
index fa03a4b2f13f4cc035191365d8c39fc63e01e1ae..f2d68f4c3a38dd461b86b51396d58d2c35fa72e8 100644 (file)
@@ -404,6 +404,7 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS          = 0,
                    CTDB_CONTROL_RECEIVE_RECORDS         = 136,
                    CTDB_CONTROL_IPREALLOCATED           = 137,
                    CTDB_CONTROL_GET_RUNSTATE            = 138,
+                   CTDB_CONTROL_DB_DETACH               = 139,
 };
 
 /*
index b56b624f00c1123f96070cc644ebb0c4ec0587a5..b0220de15058a0e4dcc70fec81858a5c282a3fca 100644 (file)
@@ -682,6 +682,9 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
        case CTDB_CONTROL_RECEIVE_RECORDS:
                return ctdb_control_receive_records(ctdb, indata, outdata);
 
+       case CTDB_CONTROL_DB_DETACH:
+               return ctdb_control_db_detach(ctdb, indata, client_id);
+
        default:
                DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
                return -1;
index aafba42c564d1c1e940d0921b236a2b8991acd0a..3d8772fc887c8c82845b2b9a133c92a18fda11df 100644 (file)
@@ -1164,6 +1164,91 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
        return 0;
 }
 
+/*
+ * a client has asked to detach from a database
+ */
+int32_t ctdb_control_db_detach(struct ctdb_context *ctdb, TDB_DATA indata,
+                              uint32_t client_id)
+{
+       uint32_t db_id;
+       struct ctdb_db_context *ctdb_db;
+       struct ctdb_client *client = NULL;
+
+       db_id = *(uint32_t *)indata.dptr;
+       ctdb_db = find_ctdb_db(ctdb, db_id);
+       if (ctdb_db == NULL) {
+               DEBUG(DEBUG_ERR, ("Invalid dbid 0x%08x in DB detach\n",
+                                 db_id));
+               return -1;
+       }
+
+       if (ctdb->tunable.allow_client_db_attach == 0) {
+               DEBUG(DEBUG_ERR, ("DB detach from database %s denied by "
+                                 "tunable AllowClientDBAccess == 0\n",
+                                 ctdb_db->db_name));
+               return -1;
+       }
+
+       if (ctdb_db->persistent) {
+               DEBUG(DEBUG_ERR, ("DB detach from persistent database %s "
+                                 "denied\n", ctdb_db->db_name));
+               return -1;
+       }
+
+       /* Cannot detach from database when in recovery */
+       if (ctdb->recovery_mode == CTDB_RECOVERY_ACTIVE) {
+               DEBUG(DEBUG_ERR, ("DB detach denied while in recovery\n"));
+               return -1;
+       }
+
+       /* If a control comes from a client, then broadcast it to all nodes.
+        * Do the actual detach only if the control comes from other daemons.
+        */
+       if (client_id != 0) {
+               client = ctdb_reqid_find(ctdb, client_id, struct ctdb_client);
+               if (client != NULL) {
+                       /* forward the control to all the nodes */
+                       ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_ALL, 0,
+                                                CTDB_CONTROL_DB_DETACH, 0,
+                                                CTDB_CTRL_FLAG_NOREPLY,
+                                                indata, NULL, NULL);
+                       return 0;
+               }
+               DEBUG(DEBUG_ERR, ("Client has gone away. Failing DB detach "
+                                 "for database '%s'\n", ctdb_db->db_name));
+               return -1;
+       }
+
+       /* Disable vacuuming and drop all vacuuming data */
+       talloc_free(ctdb_db->vacuum_handle);
+       talloc_free(ctdb_db->delete_queue);
+
+       /* Terminate any deferred fetch */
+       talloc_free(ctdb_db->deferred_fetch);
+
+       /* Terminate any traverses */
+       while (ctdb_db->traverse) {
+               talloc_free(ctdb_db->traverse);
+       }
+
+       /* Terminate any revokes */
+       while (ctdb_db->revokechild_active) {
+               talloc_free(ctdb_db->revokechild_active);
+       }
+
+       /* Free readonly tracking database */
+       if (ctdb_db->readonly) {
+               talloc_free(ctdb_db->rottdb);
+       }
+
+       DLIST_REMOVE(ctdb->db_list, ctdb_db);
+
+       DEBUG(DEBUG_NOTICE, ("Detached from database '%s'\n",
+                            ctdb_db->db_name));
+       talloc_free(ctdb_db);
+
+       return 0;
+}
 
 /*
   attach to all existing persistent databases