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
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);
}
}
/* 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 */
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 */
*/
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;
}
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;
}
close(fd[0]);
close(ctdb->daemon.sd);
ctdb->daemon.sd = -1;
+ ctdb_get_config(ctdb);
return 0;
}
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;
}
}
}
}
+ 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",
}
/* 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);
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;
}
/*
- 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;
}
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
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
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
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
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
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
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
#!/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