auto-determine listen address by attempting to bind to each address in the cluster...
authorAndrew Tridgell <tridge@samba.org>
Mon, 30 Apr 2007 20:34:55 +0000 (06:34 +1000)
committerAndrew Tridgell <tridge@samba.org>
Mon, 30 Apr 2007 20:34:55 +0000 (06:34 +1000)
14 files changed:
Makefile.in
common/cmdline.c
common/ctdb.c
common/ctdb_daemon.c
common/ctdb_ltdb.c
tcp/tcp_connect.c
tests/bench-ssh.sh
tests/bench.sh
tests/ctdbd.sh
tests/fetch.sh
tests/fetch1.sh
tests/messaging.sh
tests/test.sh
tests/test1.sh

index 71c45ce6b302fd4647b920ac475e661a20528fa1..9254ff8120a0866954ac53e5baa569be7c4cf2e6 100644 (file)
@@ -112,10 +112,10 @@ install: all
        rsync $(BINS) $(bindir)
        rsync $(srcdir)/include/ctdb.h $(includedir)
 
-test:
+test: all
        tests/run_tests.sh
 
-valgrindtest:
+valgrindtest: all
        VALGRIND="valgrind -q --trace-children=yes" tests/run_tests.sh
 
 
index 4ffb032ed1eb24943c483fbadaf1d693a49575ae..23c93edea12092277069022a7fe556811f70fa85 100644 (file)
@@ -71,8 +71,8 @@ struct ctdb_context *ctdb_cmdline_init(struct event_context *ev)
        struct ctdb_context *ctdb;
        int i, ret;
 
-       if (ctdb_cmdline.nlist == NULL || ctdb_cmdline.myaddress == NULL) {
-               printf("You must provide a node list with --nlist and an address with --listen\n");
+       if (ctdb_cmdline.nlist == NULL) {
+               printf("You must provide a node list with --nlist\n");
                exit(1);
        }
 
@@ -103,10 +103,12 @@ struct ctdb_context *ctdb_cmdline_init(struct event_context *ev)
        }
 
        /* tell ctdb what address to listen on */
-       ret = ctdb_set_address(ctdb, ctdb_cmdline.myaddress);
-       if (ret == -1) {
-               printf("ctdb_set_address failed - %s\n", ctdb_errstr(ctdb));
-               exit(1);
+       if (ctdb_cmdline.myaddress) {
+               ret = ctdb_set_address(ctdb, ctdb_cmdline.myaddress);
+               if (ret == -1) {
+                       printf("ctdb_set_address failed - %s\n", ctdb_errstr(ctdb));
+                       exit(1);
+               }
        }
 
        /* tell ctdb the socket address */
@@ -123,10 +125,12 @@ struct ctdb_context *ctdb_cmdline_init(struct event_context *ev)
                exit(1);
        }
 
-       ret = ctdb_set_tdb_dir(ctdb, ctdb_cmdline.db_dir);
-       if (ret == -1) {
-               printf("ctdb_set_tdb_dir failed - %s\n", ctdb_errstr(ctdb));
-               exit(1);
+       if (ctdb_cmdline.db_dir) {
+               ret = ctdb_set_tdb_dir(ctdb, ctdb_cmdline.db_dir);
+               if (ret == -1) {
+                       printf("ctdb_set_tdb_dir failed - %s\n", ctdb_errstr(ctdb));
+                       exit(1);
+               }
        }
 
        /* initialize the vnn mapping table */
index 69e69ec8ca2d9cc82b82d76f45a322f1204aac74..0e7ea3818d95ce532002fd415fbcbbcecee5f6e9 100644 (file)
@@ -86,11 +86,7 @@ void ctdb_set_max_lacount(struct ctdb_context *ctdb, unsigned count)
 */
 int ctdb_set_tdb_dir(struct ctdb_context *ctdb, const char *dir)
 {
-       if (dir == NULL) {
-               ctdb->db_directory = talloc_asprintf(ctdb, "ctdb-%u", ctdb_get_vnn(ctdb));
-       } else {
-               ctdb->db_directory = talloc_strdup(ctdb, dir);
-       }
+       ctdb->db_directory = talloc_strdup(ctdb, dir);
        if (ctdb->db_directory == NULL) {
                return -1;
        }
@@ -124,7 +120,8 @@ static int ctdb_add_node(struct ctdb_context *ctdb, char *nstr)
           will change! */
        node->vnn = ctdb->num_nodes;
 
-       if (ctdb_same_address(&ctdb->address, &node->address)) {
+       if (ctdb->address.address &&
+           ctdb_same_address(&ctdb->address, &node->address)) {
                ctdb->vnn = node->vnn;
                node->flags |= NODE_FLAGS_CONNECTED;
        }
index e994e76147eafa7c22d062550d9cd8a42fc52028..af6222b4fad36bd74cd918efd09f628570b21a98 100644 (file)
@@ -653,6 +653,7 @@ int ctdb_start(struct ctdb_context *ctdb)
                close(fd[0]);
                close(ctdb->daemon.sd);
                ctdb->daemon.sd = -1;
+               ctdb_get_config(ctdb);
                return 0;
        }
 
index 2cf90a177c86fed9b0bd988c386fa6c414c2d394..e071a20590aa25655e5effaf22baf7db60362cd2 100644 (file)
@@ -301,6 +301,8 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
        for (tmp_db=ctdb->db_list;tmp_db;tmp_db=tmp_db->next) {
                if (strcmp(db_name, tmp_db->db_name) == 0) {
                        /* this is not an error */
+                       outdata->dptr  = (uint8_t *)&tmp_db->db_id;
+                       outdata->dsize = sizeof(tmp_db->db_id);
                        return 0;
                }
        }
@@ -327,6 +329,10 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
                }
        }
 
+       if (ctdb->db_directory == NULL) {
+               ctdb->db_directory = VARDIR "/ctdb";
+       }
+
        /* make sure the db directory exists */
        if (mkdir(ctdb->db_directory, 0700) == -1 && errno != EEXIST) {
                DEBUG(0,(__location__ " Unable to create ctdb directory '%s'\n", 
@@ -336,8 +342,9 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
        }
 
        /* open the database */
-       ctdb_db->db_path = talloc_asprintf(ctdb_db, "%s/%s", 
-                                          ctdb->db_directory, db_name);
+       ctdb_db->db_path = talloc_asprintf(ctdb_db, "%s/%s.%u", 
+                                          ctdb->db_directory, 
+                                          db_name, ctdb->vnn);
 
        ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 0, 
                                      TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0666);
@@ -365,6 +372,8 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
                                 CTDB_CONTROL_DB_ATTACH, CTDB_CTRL_FLAG_NOREPLY,
                                 indata, NULL, NULL);
 
+       DEBUG(0,("Attached to database '%s'\n", ctdb_db->db_path));
+
        /* success */
        return 0;
 }
index 4d9d8e83868c05b401fe64bde88937d7208f045b..30d87001afea75eb11c5c19bdc705c70ebe508e3 100644 (file)
@@ -205,46 +205,134 @@ static void ctdb_listen_event(struct event_context *ev, struct fd_event *fde,
 
 
 /*
-  listen on our own address
+  automatically find which address to listen on
 */
-int ctdb_tcp_listen(struct ctdb_context *ctdb)
+static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb)
 {
        struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data,
                                                struct ctdb_tcp);
         struct sockaddr_in sock;
-       int one = 1;
+       int lock_fd, i;
+       const char *lock_path = "/tmp/.ctdb_socket_lock";
+       struct flock lock;
+
+       /* in order to ensure that we don't get two nodes with the
+          same adddress, we must make the bind() and listen() calls
+          atomic. The SO_REUSEADDR setsockopt only prevents double
+          binds if the first socket is in LISTEN state  */
+       lock_fd = open(lock_path, O_RDWR|O_CREAT, 0666);
+       if (lock_fd == -1) {
+               DEBUG(0,("Unable to open %s\n", lock_path));
+               return -1;
+       }
+
+       lock.l_type = F_WRLCK;
+       lock.l_whence = SEEK_SET;
+       lock.l_start = 0;
+       lock.l_len = 1;
+       lock.l_pid = 0;
 
-        sock.sin_port = htons(ctdb->address.port);
-        sock.sin_family = PF_INET;
-       if (ctdb_tcp_get_address(ctdb, ctdb->address.address, &sock.sin_addr) != 0) {
+       if (fcntl(lock_fd, F_SETLKW, &lock) != 0) {
+               DEBUG(0,("Unable to lock %s\n", lock_path));
+               close(lock_fd);
                return -1;
        }
 
-        ctcp->listen_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-        if (ctcp->listen_fd == -1) {
+       for (i=0;i<ctdb->num_nodes;i++) {
+               sock.sin_port = htons(ctdb->nodes[i]->address.port);
+               sock.sin_family = PF_INET;
+               if (ctdb_tcp_get_address(ctdb, ctdb->nodes[i]->address.address, 
+                                        &sock.sin_addr) != 0) {
+                       continue;
+               }
+               
+               if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, 
+                        sizeof(sock)) == 0) {
+                       break;
+               }
+       }
+       
+       if (i == ctdb->num_nodes) {
+               DEBUG(0,("Unable to bind to any of the node addresses - giving up\n"));
+               goto failed;
+       }
+       ctdb->address = ctdb->nodes[i]->address;
+       ctdb->name = talloc_asprintf(ctdb, "%s:%u", 
+                                    ctdb->address.address, 
+                                    ctdb->address.port);
+       ctdb->vnn = ctdb->nodes[i]->vnn;
+       ctdb->nodes[i]->flags |= NODE_FLAGS_CONNECTED;
+       DEBUG(0,("ctdb chose network address %s:%u vnn %u\n", 
+                ctdb->address.address, 
+                ctdb->address.port, 
+                ctdb->vnn));
+
+       if (listen(ctcp->listen_fd, 10) == -1) {
+               goto failed;
+       }
+
+       event_add_fd(ctdb->ev, ctdb, ctcp->listen_fd, EVENT_FD_READ, 
+                    ctdb_listen_event, ctdb);  
+
+       close(lock_fd);
+       return 0;
+       
+failed:
+       close(lock_fd);
+       close(ctcp->listen_fd);
+       ctcp->listen_fd = -1;
+       return -1;
+}
+
+
+/*
+  listen on our own address
+*/
+int ctdb_tcp_listen(struct ctdb_context *ctdb)
+{
+       struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data,
+                                               struct ctdb_tcp);
+        struct sockaddr_in sock;
+       int one = 1;
+
+       ctcp->listen_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+       if (ctcp->listen_fd == -1) {
                ctdb_set_error(ctdb, "socket failed\n");
                return -1;
-        }
+       }
 
         setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
 
-        if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sizeof(sock)) != 0) {
-               ctdb_set_error(ctdb, "bind failed\n");
-               close(ctcp->listen_fd);
-               ctcp->listen_fd = -1;
-                return -1;
-        }
+       /* we can either auto-bind to the first available address, or we can
+          use a specified address */
+       if (!ctdb->address.address) {
+               return ctdb_tcp_listen_automatic(ctdb);
+       }
+
+       sock.sin_port = htons(ctdb->address.port);
+       sock.sin_family = PF_INET;
+       
+       if (ctdb_tcp_get_address(ctdb, ctdb->address.address, 
+                                &sock.sin_addr) != 0) {
+               goto failed;
+       }
+       
+       if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sizeof(sock)) != 0) {
+               goto failed;
+       }
 
        if (listen(ctcp->listen_fd, 10) == -1) {
-               ctdb_set_error(ctdb, "listen failed\n");
-               close(ctcp->listen_fd);
-               ctcp->listen_fd = -1;
-               return -1;
+               goto failed;
        }
 
        event_add_fd(ctdb->ev, ctdb, ctcp->listen_fd, EVENT_FD_READ, 
                     ctdb_listen_event, ctdb);  
 
        return 0;
+
+failed:
+       close(ctcp->listen_fd);
+       ctcp->listen_fd = -1;
+       return -1;
 }
 
index e9b1ec28d0edc52f8e08e6aff1d027e4aef29b44..8716156e3aa23cd1f1c9fe7d861f7a294c9f07d8 100755 (executable)
@@ -33,9 +33,9 @@ echo "Starting nodes"
 i=0
 for h in $nodes; do
     if [ $i -eq `expr $count - 1` ]; then
-       ssh $h $dir/bin/ctdb_bench --nlist $dir/nodes-ssh.txt --listen $h:9001 --socket $h$options
+       ssh $h $dir/bin/ctdb_bench --nlist $dir/nodes-ssh.txt --socket $h$options
     else
-       ssh -f $h $dir/bin/ctdb_bench --nlist $dir/nodes-ssh.txt --listen $h:9001 --socket $h $options
+       ssh -f $h $dir/bin/ctdb_bench --nlist $dir/nodes-ssh.txt --socket $h $options
     fi
     i=`expr $i + 1`
 done
index eca604c2df002968ca4aeaa322648ad6c9222bf0..f9430919ea6a3aa20cc847e2cd9607c79c455c51 100755 (executable)
@@ -15,7 +15,7 @@ done
 killall -9 ctdb_bench
 echo "Trying $NUMNODES nodes"
 for i in `seq 1 $NUMNODES`; do
-  $VALGRIND bin/ctdb_bench --nlist nodes.txt --listen 127.0.0.$i:9001 --socket /tmp/ctdb.127.0.0.$i $* &
+  $VALGRIND bin/ctdb_bench --nlist nodes.txt --socket /tmp/ctdb.127.0.0.$i $* &
 done
 
 wait
index 1a719e2249d27538fdc27fa9474c4e5dfec3cb23..03897af358d34ae9936b95d587a768a9cba1eeef 100755 (executable)
@@ -3,8 +3,8 @@
 killall -q ctdbd
 
 echo "Starting 2 ctdb daemons"
-bin/ctdbd --nlist direct/nodes.txt --listen 127.0.0.2:9001
-bin/ctdbd --nlist direct/nodes.txt --listen 127.0.0.1:9001
+bin/ctdbd --nlist direct/nodes.txt
+bin/ctdbd --nlist direct/nodes.txt
 
 echo "Testing ping"
 bin/ctdb_control ping || exit 1
index 9b611013e96654ecbbe6e1648e6a9216a2b529e9..fb384e2935c25c62f5ad474320c99720fd0b144b 100755 (executable)
@@ -13,6 +13,6 @@ done
 killall -9 ctdb_fetch
 echo "Trying $NUMNODES nodes"
 for i in `seq 1 $NUMNODES`; do
-  $VALGRIND bin/ctdb_fetch --nlist nodes.txt --listen 127.0.0.$i:9001 --socket /tmp/ctdb.127.0.0.$i $* &
+  $VALGRIND bin/ctdb_fetch --nlist nodes.txt --socket /tmp/ctdb.127.0.0.$i $* &
 done
 wait
index db584ec0120407fab6ea4ca51134cb8c4fcb6bc3..0338db4f9fa343c784efaa91c73d6608f9288d9b 100755 (executable)
@@ -3,5 +3,5 @@
 killall -q ctdb_fetch1
 
 echo "Trying node"
-bin/ctdb_fetch1 --nlist tests/1node.txt --listen 127.0.0.1:9001 $* 
+bin/ctdb_fetch1 --nlist tests/1node.txt $* 
 wait
index 25f68f3bb6a08c47b06a66dd8d01f04aa0e3a82d..07ca2ca5c9130bdcf9969cbcc7360c397c4c78a9 100755 (executable)
@@ -17,7 +17,7 @@ done
 killall -9 ctdb_messaging
 echo "Trying $NUMNODES nodes"
 for i in `seq 1 $NUMNODES`; do
-  $VALGRIND bin/ctdb_messaging --nlist nodes.txt --listen 127.0.0.$i:9001 --socket /tmp/ctdb.127.0.0.$i $* &
+  $VALGRIND bin/ctdb_messaging --nlist nodes.txt --socket /tmp/ctdb.127.0.0.$i $* &
 done
 
 wait
index f95354a2d79aac0c66e134269671ca2e25f17dd2..c243dbd0327a1447cf122e7b94b56a0860cbcc6b 100755 (executable)
@@ -18,7 +18,7 @@ done
 killall -9 ctdb_test
 echo "Trying $NUMNODES nodes"
 for i in `seq 1 $NUMNODES`; do
-  $VALGRIND bin/ctdb_test --nlist nodes.txt --listen 127.0.0.$i:9001 --socket /tmp/ctdb.127.0.0.$i $* &
+  $VALGRIND bin/ctdb_test --nlist nodes.txt --socket /tmp/ctdb.127.0.0.$i $* &
 done
 
 wait
index 42256f22f9d51871b10d543055322cef1640b8c5..cca46e04c6e033a0831d57ab2fb2ad7245f06952 100755 (executable)
@@ -1,9 +1,9 @@
 #!/bin/sh
 
 echo "Testing daemon mode"
-bin/ctdb_test --nlist tests/1node.txt --listen 127.0.0.1:9001
+bin/ctdb_test --nlist tests/1node.txt
 wait
 
 echo "Testing self connect"
-bin/ctdb_test --nlist tests/1node.txt --listen 127.0.0.1:9001 --self-connect
+bin/ctdb_test --nlist tests/1node.txt --self-connect
 wait