Dont set next_interval to 0.
[metze/ctdb/wip.git] / server / ctdb_control.c
index 15f5000ee14b99d92b745fafcb08f23200f27524..bfb7bd1c29e6c7620b7b8b096d203b8f93256d97 100644 (file)
@@ -17,7 +17,7 @@
    along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
 #include "includes.h"
-#include "lib/events/events.h"
+#include "lib/tevent/tevent.h"
 #include "lib/tdb/include/tdb.h"
 #include "system/network.h"
 #include "system/filesys.h"
@@ -81,7 +81,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
        switch (opcode) {
        case CTDB_CONTROL_PROCESS_EXISTS: {
                CHECK_CONTROL_DATA_SIZE(sizeof(pid_t));
-               return kill(*(pid_t *)indata.dptr, 0);
+               return ctdb_control_process_exists(ctdb, *(pid_t *)indata.dptr);
        }
 
        case CTDB_CONTROL_SET_DEBUG: {
@@ -98,10 +98,18 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
        }
 
        case CTDB_CONTROL_STATISTICS: {
+               int i;
                CHECK_CONTROL_DATA_SIZE(0);
                ctdb->statistics.memory_used = talloc_total_size(NULL);
-               ctdb->statistics.frozen = (ctdb->freeze_mode == CTDB_FREEZE_FROZEN);
+               ctdb->statistics.frozen = 0;
+               for (i=1; i<= NUM_DB_PRIORITIES; i++) {
+                       if (ctdb->freeze_mode[i] == CTDB_FREEZE_FROZEN) {
+                               ctdb->statistics.frozen = 1;
+                       }
+               }
                ctdb->statistics.recovering = (ctdb->recovery_mode == CTDB_RECOVERY_ACTIVE);
+               ctdb->statistics.statistics_current_time = timeval_current();
+
                outdata->dptr = (uint8_t *)&ctdb->statistics;
                outdata->dsize = sizeof(ctdb->statistics);
                return 0;
@@ -122,6 +130,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
        case CTDB_CONTROL_STATISTICS_RESET: {
                CHECK_CONTROL_DATA_SIZE(0);
                ZERO_STRUCT(ctdb->statistics);
+               ctdb->statistics.statistics_start_time = timeval_current();
                return 0;
        }
 
@@ -156,7 +165,16 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
                return ctdb_control_push_db(ctdb, indata);
 
        case CTDB_CONTROL_GET_RECMODE: {
-               return ctdb->recovery_mode;
+               int i;
+               if (ctdb->recovery_mode == CTDB_RECOVERY_ACTIVE) {
+                       return CTDB_RECOVERY_ACTIVE;
+               }                 
+               for (i=1; i<=NUM_DB_PRIORITIES; i++) {
+                       if (ctdb->freeze_mode[i] == CTDB_FREEZE_FROZEN) {
+                               return CTDB_RECOVERY_ACTIVE;
+                       }
+               }
+               return CTDB_RECOVERY_NORMAL;
        }
 
        case CTDB_CONTROL_SET_RECMASTER: {
@@ -217,7 +235,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
 
        case CTDB_CONTROL_TRAVERSE_START:
                CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_traverse_start));
-               return ctdb_control_traverse_start(ctdb, indata, outdata, srcnode);
+               return ctdb_control_traverse_start(ctdb, indata, outdata, srcnode, client_id);
 
        case CTDB_CONTROL_TRAVERSE_ALL:
                return ctdb_control_traverse_all(ctdb, indata, outdata);
@@ -225,6 +243,10 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
        case CTDB_CONTROL_TRAVERSE_DATA:
                return ctdb_control_traverse_data(ctdb, indata, outdata);
 
+       case CTDB_CONTROL_TRAVERSE_KILL:
+               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_traverse_start));
+               return ctdb_control_traverse_kill(ctdb, indata, outdata, srcnode);
+
        case CTDB_CONTROL_REGISTER_SRVID:
                return daemon_register_message_handler(ctdb, client_id, srvid);
 
@@ -245,7 +267,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
 
        case CTDB_CONTROL_THAW:
                CHECK_CONTROL_DATA_SIZE(0);
-               return ctdb_control_thaw(ctdb);
+               return ctdb_control_thaw(ctdb, (uint32_t)c->srvid);
 
        case CTDB_CONTROL_SET_RECMODE:
                CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));              
@@ -276,7 +298,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
                if (ctdb->methods != NULL) {
                        ctdb->methods->shutdown(ctdb);
                }
-               ctdb_event_script(ctdb, "shutdown");
+               ctdb_event_script(ctdb, CTDB_EVENT_SHUTDOWN);
                DEBUG(DEBUG_NOTICE,("Received SHUTDOWN command. Stopping CTDB daemon.\n"));
                exit(0);
 
@@ -305,7 +327,6 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
                return ctdb_control_get_public_ips(ctdb, c, outdata);
 
        case CTDB_CONTROL_TCP_CLIENT: 
-               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_tcp));
                return ctdb_control_tcp_client(ctdb, client_id, indata);
 
        case CTDB_CONTROL_STARTUP: 
@@ -313,8 +334,16 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
                return ctdb_control_startup(ctdb, srcnode);
 
        case CTDB_CONTROL_TCP_ADD: 
-               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_tcp_vnn));
-               return ctdb_control_tcp_add(ctdb, indata);
+               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_tcp_connection));
+               return ctdb_control_tcp_add(ctdb, indata, false);
+
+       case CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE: 
+               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_tcp_connection));
+               return ctdb_control_tcp_add(ctdb, indata, true);
+
+       case CTDB_CONTROL_TCP_REMOVE: 
+               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_tcp_connection));
+               return ctdb_control_tcp_remove(ctdb, indata);
 
        case CTDB_CONTROL_SET_TUNABLE:
                return ctdb_control_set_tunable(ctdb, indata);
@@ -415,10 +444,162 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
        case CTDB_CONTROL_TRANS2_FINISHED:
                return ctdb_control_trans2_finished(ctdb, c);
 
+       case CTDB_CONTROL_TRANS2_ACTIVE:
+               CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
+               return ctdb_control_trans2_active(ctdb, c, *(uint32_t *)indata.dptr);
+
+       case CTDB_CONTROL_TRANS3_COMMIT:
+               return ctdb_control_trans3_commit(ctdb, c, indata, async_reply);
+
        case CTDB_CONTROL_RECD_PING:
                CHECK_CONTROL_DATA_SIZE(0);
                return ctdb_control_recd_ping(ctdb);
 
+       case CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS:
+               CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
+               return ctdb_control_get_event_script_status(ctdb, *(uint32_t *)indata.dptr, outdata);
+
+       case CTDB_CONTROL_RECD_RECLOCK_LATENCY:
+               CHECK_CONTROL_DATA_SIZE(sizeof(double));
+               ctdb_reclock_latency(ctdb, "recd reclock", &ctdb->statistics.reclock.recd, *((double *)indata.dptr));
+               return 0;
+       case CTDB_CONTROL_GET_RECLOCK_FILE:
+               CHECK_CONTROL_DATA_SIZE(0);
+               if (ctdb->recovery_lock_file != NULL) {
+                       outdata->dptr  = discard_const(ctdb->recovery_lock_file);
+                       outdata->dsize = strlen(ctdb->recovery_lock_file) + 1;
+               }
+               return 0;
+       case CTDB_CONTROL_SET_RECLOCK_FILE:
+               ctdb->tunable.verify_recovery_lock = 0;
+               if (ctdb->recovery_lock_file != NULL) {
+                       talloc_free(ctdb->recovery_lock_file);
+                       ctdb->recovery_lock_file = NULL;
+               }
+               if (indata.dsize > 0) {
+                       ctdb->recovery_lock_file = talloc_strdup(ctdb, discard_const(indata.dptr));
+                       ctdb->tunable.verify_recovery_lock = 1;
+               }
+               return 0;
+
+       case CTDB_CONTROL_STOP_NODE:
+               CHECK_CONTROL_DATA_SIZE(0);
+               return ctdb_control_stop_node(ctdb, c, async_reply);
+
+       case CTDB_CONTROL_CONTINUE_NODE:
+               CHECK_CONTROL_DATA_SIZE(0);
+               return ctdb_control_continue_node(ctdb);
+
+       case CTDB_CONTROL_SET_NATGWSTATE: {
+               uint32_t natgwstate;
+
+               CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));              
+               natgwstate = *(uint32_t *)indata.dptr;
+               if (natgwstate == 0) {
+                       ctdb->capabilities &= ~CTDB_CAP_NATGW;
+               } else {
+                       ctdb->capabilities |= CTDB_CAP_NATGW;
+               }
+               return 0;
+       }
+
+       case CTDB_CONTROL_SET_LMASTERROLE: {
+               uint32_t lmasterrole;
+
+               CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));              
+               lmasterrole = *(uint32_t *)indata.dptr;
+               if (lmasterrole == 0) {
+                       ctdb->capabilities &= ~CTDB_CAP_LMASTER;
+               } else {
+                       ctdb->capabilities |= CTDB_CAP_LMASTER;
+               }
+               return 0;
+       }
+
+       case CTDB_CONTROL_SET_RECMASTERROLE: {
+               uint32_t recmasterrole;
+
+               CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));              
+               recmasterrole = *(uint32_t *)indata.dptr;
+               if (recmasterrole == 0) {
+                       ctdb->capabilities &= ~CTDB_CAP_RECMASTER;
+               } else {
+                       ctdb->capabilities |= CTDB_CAP_RECMASTER;
+               }
+               return 0;
+       }
+
+       case CTDB_CONTROL_ENABLE_SCRIPT:
+               return ctdb_control_enable_script(ctdb, indata);
+
+       case CTDB_CONTROL_DISABLE_SCRIPT:
+               return ctdb_control_disable_script(ctdb, indata);
+
+       case CTDB_CONTROL_SET_BAN_STATE:
+               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_ban_time));
+               return ctdb_control_set_ban_state(ctdb, indata);
+
+       case CTDB_CONTROL_GET_BAN_STATE:
+               CHECK_CONTROL_DATA_SIZE(0);
+               return ctdb_control_get_ban_state(ctdb, outdata);
+
+       case CTDB_CONTROL_SET_DB_PRIORITY:
+               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_db_priority));
+               return ctdb_control_set_db_priority(ctdb, indata);
+
+       case CTDB_CONTROL_GET_DB_PRIORITY: {
+               uint32_t db_id;
+               struct ctdb_db_context *ctdb_db;
+
+               CHECK_CONTROL_DATA_SIZE(sizeof(db_id));
+               db_id = *(uint32_t *)indata.dptr;
+               ctdb_db = find_ctdb_db(ctdb, db_id);
+               if (ctdb_db == NULL) return -1;
+               return ctdb_db->priority;
+       }
+
+       case CTDB_CONTROL_TRANSACTION_CANCEL:
+               CHECK_CONTROL_DATA_SIZE(0);
+               return ctdb_control_transaction_cancel(ctdb);
+
+       case CTDB_CONTROL_REGISTER_NOTIFY:
+               return ctdb_control_register_notify(ctdb, client_id, indata);
+
+       case CTDB_CONTROL_DEREGISTER_NOTIFY:
+               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_client_notify_deregister));
+               return ctdb_control_deregister_notify(ctdb, client_id, indata);
+
+       case CTDB_CONTROL_GET_LOG:
+               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_get_log_addr));
+               return ctdb_control_get_log(ctdb, indata);
+
+       case CTDB_CONTROL_CLEAR_LOG:
+               return ctdb_control_clear_log(ctdb);
+
+       case CTDB_CONTROL_GET_DB_SEQNUM:
+               CHECK_CONTROL_DATA_SIZE(sizeof(uint64_t));
+               return ctdb_control_get_db_seqnum(ctdb, indata, outdata);
+
+       case CTDB_CONTROL_DB_SET_HEALTHY:
+               CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
+               return ctdb_control_db_set_healthy(ctdb, indata);
+
+       case CTDB_CONTROL_DB_GET_HEALTH:
+               CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
+               return ctdb_control_db_get_health(ctdb, indata, outdata);
+
+       case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
+               CHECK_CONTROL_DATA_SIZE(sizeof(ctdb_sock_addr));
+               return ctdb_control_get_public_ip_info(ctdb, c, indata, outdata);
+
+       case CTDB_CONTROL_GET_IFACES:
+               CHECK_CONTROL_DATA_SIZE(0);
+               return ctdb_control_get_ifaces(ctdb, c, outdata);
+
+       case CTDB_CONTROL_SET_IFACE_LINK_STATE:
+               CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_iface_info));
+               return ctdb_control_set_iface_link(ctdb, c, indata);
+
        default:
                DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode));
                return -1;
@@ -564,6 +745,11 @@ int ctdb_daemon_send_control(struct ctdb_context *ctdb, uint32_t destnode,
        struct ctdb_control_state *state;
        size_t len;
 
+       if (ctdb->methods == NULL) {
+               DEBUG(DEBUG_ERR,(__location__ " Failed to send control. Transport is DOWN\n"));
+               return -1;
+       }
+
        if (((destnode == CTDB_BROADCAST_VNNMAP) || 
             (destnode == CTDB_BROADCAST_ALL) ||
             (destnode == CTDB_BROADCAST_CONNECTED)) &&