don't start the transport connecting to the other nodes until after the startup event...
authorAndrew Tridgell <tridge@samba.org>
Wed, 30 May 2007 03:26:50 +0000 (13:26 +1000)
committerAndrew Tridgell <tridge@samba.org>
Wed, 30 May 2007 03:26:50 +0000 (13:26 +1000)
common/ctdb_daemon.c
common/ctdb_recoverd.c
ib/ibw_ctdb_init.c
include/ctdb_private.h
takeover/system.c
tcp/tcp_init.c

index 015b8a186812b5d9df3aa5e22fb679da5b1a90d6..1ffd70f61fe23e823c6d03cb95a5c19d87d61cf9 100644 (file)
 
 static void daemon_incoming_packet(void *, struct ctdb_req_header *);
 
+/* called when the "startup" event script has finished */
+static void ctdb_start_transport(struct ctdb_context *ctdb, int status)
+{
+       if (status != 0) {
+               DEBUG(0,("startup event failed!\n"));
+               ctdb_fatal(ctdb, "startup event script failed");                
+       }
+
+       /* start the transport running */
+       if (ctdb->methods->start(ctdb) != 0) {
+               DEBUG(0,("transport failed to start!\n"));
+               ctdb_fatal(ctdb, "transport failed to start");
+       }
+
+       /* start the recovery daemon process */
+       if (ctdb_start_recoverd(ctdb) != 0) {
+               DEBUG(0,("Failed to start recovery daemon\n"));
+               exit(11);
+       }
+}
+
+/* go into main ctdb loop */
 static void ctdb_main_loop(struct ctdb_context *ctdb)
 {
        int ret = -1;
@@ -50,16 +72,10 @@ static void ctdb_main_loop(struct ctdb_context *ctdb)
                return;
        }
 
-       ret = ctdb_event_script(ctdb, "startup");
-       if (ret != 0) {
-               DEBUG(0,("Failed startup event script\n"));
-               return;
-       }
-
-       /* start the transport running */
-       if (ctdb->methods->start(ctdb) != 0) {
-               DEBUG(0,("transport failed to start!\n"));
-               ctdb_fatal(ctdb, "transport failed to start");
+       /* initialise the transport  */
+       if (ctdb->methods->initialise(ctdb) != 0) {
+               DEBUG(0,("transport failed to initialise!\n"));
+               ctdb_fatal(ctdb, "transport failed to initialise");
        }
 
        /* tell all other nodes we've just started up */
@@ -68,6 +84,12 @@ static void ctdb_main_loop(struct ctdb_context *ctdb)
                                 CTDB_CTRL_FLAG_NOREPLY,
                                 tdb_null, NULL, NULL);
 
+       ret = ctdb_event_script_callback(ctdb, ctdb_start_transport, "startup");
+       if (ret != 0) {
+               DEBUG(0,("Failed startup event script\n"));
+               return;
+       }
+
        /* go into a wait loop to allow other nodes to complete */
        event_loop_wait(ctdb->ev);
 
@@ -744,12 +766,6 @@ int ctdb_start_daemon(struct ctdb_context *ctdb, bool do_fork)
        /* try to set us up as realtime */
        ctdb_set_realtime();
 
-       /* start the recovery daemon process */
-       if (ctdb_start_recoverd(ctdb) != 0) {
-               DEBUG(0,("Failed to start recovery daemon\n"));
-               exit(11);
-       }
-
        /* ensure the socket is deleted on exit of the daemon */
        domain_socket_name = talloc_strdup(talloc_autofree_context(), ctdb->daemon.name);
        talloc_set_destructor(domain_socket_name, unlink_destructor);   
index dca340bff2ebeda1d2f703c2741528edf52295c2..b05b02050ff056e270efc63bcc0123f91ca6a54f 100644 (file)
@@ -972,6 +972,10 @@ int ctdb_start_recoverd(struct ctdb_context *ctdb)
 
        close(fd[1]);
 
+       /* we need a new event context */
+       talloc_free(ctdb->ev);
+       ctdb->ev = event_context_init(ctdb);
+
        event_add_fd(ctdb->ev, ctdb, fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE, 
                     ctdb_recoverd_parent, &fd[0]);     
 
index 66919568df50287e297866ccf2c8b2401c88a076..b41c61687bc6de87aab56c9f609ab7276805d858 100644 (file)
@@ -70,9 +70,9 @@ static int ctdb_ibw_add_node(struct ctdb_node *node)
 }
 
 /*
- * Start infiniband
+ * initialise infiniband
  */
-static int ctdb_ibw_start(struct ctdb_context *ctdb)
+static int ctdb_ibw_initialise(struct ctdb_context *ctdb)
 {
        int i, ret;
 
@@ -88,6 +88,17 @@ static int ctdb_ibw_start(struct ctdb_context *ctdb)
                }
        }
 
+       return 0;
+}
+
+
+/*
+ * Start infiniband
+ */
+static int ctdb_ibw_start(struct ctdb_context *ctdb)
+{
+       int i, ret;
+
        /* listen on our own address */
        if (ctdb_ibw_listen(ctdb, 10)) /* TODO: backlog as param */
                return -1;
@@ -190,6 +201,7 @@ static int ctdb_ibw_stop(struct ctdb_context *cctx)
 #endif /* __NOTDEF__ */
 
 static const struct ctdb_methods ctdb_ibw_methods = {
+       .initialise= ctdb_ibw_initialise,
        .start     = ctdb_ibw_start,
        .queue_pkt = ctdb_ibw_queue_pkt,
        .add_node = ctdb_ibw_add_node,
index 37176748e98c7b544f28e0048444607b1797894c..92cc1a42636c65078de3194e3081bbb52be45dcf 100644 (file)
@@ -129,6 +129,7 @@ struct ctdb_node {
   transport specific methods
 */
 struct ctdb_methods {
+       int (*initialise)(struct ctdb_context *); /* initialise transport structures */ 
        int (*start)(struct ctdb_context *); /* start protocol processing */    
        int (*add_node)(struct ctdb_node *); /* setup a new node */     
        int (*queue_pkt)(struct ctdb_node *, uint8_t *data, uint32_t length);
@@ -949,6 +950,9 @@ int32_t ctdb_control_startup(struct ctdb_context *ctdb, uint32_t vnn);
 
 void ctdb_takeover_client_destructor_hook(struct ctdb_client *client);
 int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
+int ctdb_event_script_callback(struct ctdb_context *ctdb, 
+                              void (*callback)(struct ctdb_context *, int),
+                              const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
 void ctdb_release_all_ips(struct ctdb_context *ctdb);
 
 
index c6624f24857e681f5db52b7507d51f1910a05d4a..a1b6da6cf54ba82bb37331c2979f04292e6c6cfa 100644 (file)
@@ -24,6 +24,7 @@
 #include "system/filesys.h"
 #include "system/wait.h"
 #include "../include/ctdb_private.h"
+#include "lib/events/events.h"
 #include <net/ethernet.h>
 #include <net/if_arp.h>
 
@@ -258,17 +259,24 @@ bool ctdb_sys_have_ip(const char *ip)
 }
 
 /*
-  run the event script
+  run the event script - varargs version
  */
-int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...)
+static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_list ap)
 {
-       va_list ap;
        char *options, *cmdstr;
        int ret;
+       va_list ap2;
+       struct stat st;
 
-       va_start(ap, fmt);
-       options  = talloc_vasprintf(ctdb, fmt, ap);
-       va_end(ap);
+       if (stat(ctdb->takeover.event_script, &st) != 0 && 
+           errno == ENOENT) {
+               DEBUG(0,("No event script found at '%s'\n", ctdb->takeover.event_script));
+               return 0;
+       }
+
+       va_copy(ap2, ap);
+       options  = talloc_vasprintf(ctdb, fmt, ap2);
+       va_end(ap2);
        CTDB_NO_MEMORY(ctdb, options);
 
        cmdstr = talloc_asprintf(ctdb, "%s %s", ctdb->takeover.event_script, options);
@@ -285,3 +293,90 @@ int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...)
        return ret;
 }
 
+/*
+  run the event script
+ */
+int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+
+       va_start(ap, fmt);
+       ret = ctdb_event_script_v(ctdb, fmt, ap);
+       va_end(ap);
+
+       return ret;
+}
+
+
+struct ctdb_event_script_state {
+       struct ctdb_context *ctdb;
+       pid_t child;
+       void (*callback)(struct ctdb_context *, int);
+       int fd[2];
+};
+
+/* called when child is finished */
+static void ctdb_event_script_handler(struct event_context *ev, struct fd_event *fde, 
+                                     uint16_t flags, void *p)
+{
+       struct ctdb_event_script_state *state = 
+               talloc_get_type(p, struct ctdb_event_script_state);
+       int status = -1;
+       waitpid(state->child, &status, 0);
+       if (status != -1) {
+               status = WEXITSTATUS(status);
+       }
+       state->callback(state->ctdb, status);
+       talloc_free(state);
+}
+
+
+/*
+  run the event script in the background, calling the callback when 
+  finished
+ */
+int ctdb_event_script_callback(struct ctdb_context *ctdb, 
+                              void (*callback)(struct ctdb_context *, int),
+                              const char *fmt, ...)
+{
+       struct ctdb_event_script_state *state;
+       va_list ap;
+       int ret;
+
+       state = talloc(ctdb, struct ctdb_event_script_state);
+       CTDB_NO_MEMORY(ctdb, state);
+
+       state->ctdb = ctdb;
+       state->callback = callback;
+       
+       ret = pipe(state->fd);
+       if (ret != 0) {
+               talloc_free(state);
+               return -1;
+       }
+
+       state->child = fork();
+
+       if (state->child == (pid_t)-1) {
+               close(state->fd[0]);
+               close(state->fd[1]);
+               talloc_free(state);
+               return -1;
+       }
+
+       if (state->child == 0) {
+               close(state->fd[0]);
+               va_start(ap, fmt);
+               ret = ctdb_event_script_v(ctdb, fmt, ap);
+               va_end(ap);
+               _exit(ret);
+       }
+
+       close(state->fd[1]);
+
+       event_add_fd(ctdb->ev, state, state->fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE,
+                    ctdb_event_script_handler, state);
+
+       return 0;
+}
index 35b43bd5e2969a77772e67a0e7dac650972cb583..665336e947e33c5f2d64fc29f3f623098ae23c3a 100644 (file)
@@ -46,9 +46,9 @@ static int ctdb_tcp_add_node(struct ctdb_node *node)
 }
 
 /*
-  start the protocol going
+  initialise transport structures
 */
-static int ctdb_tcp_start(struct ctdb_context *ctdb)
+static int ctdb_tcp_initialise(struct ctdb_context *ctdb)
 {
        int i;
 
@@ -59,6 +59,16 @@ static int ctdb_tcp_start(struct ctdb_context *ctdb)
                }
        }
        
+       return 0;
+}
+
+/*
+  start the protocol going
+*/
+static int ctdb_tcp_start(struct ctdb_context *ctdb)
+{
+       int i;
+
        /* listen on our own address */
        if (ctdb_tcp_listen(ctdb) != 0) return -1;
 
@@ -90,6 +100,7 @@ static void *ctdb_tcp_allocate_pkt(TALLOC_CTX *mem_ctx, size_t size)
 
 
 static const struct ctdb_methods ctdb_tcp_methods = {
+       .initialise   = ctdb_tcp_initialise,
        .start        = ctdb_tcp_start,
        .queue_pkt    = ctdb_tcp_queue_pkt,
        .add_node     = ctdb_tcp_add_node,