WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-tools

[Xen-tools] [PATCH 3/3] libxenstore: reconnect on daemon restart

To: Xen Tools <xen-tools@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-tools] [PATCH 3/3] libxenstore: reconnect on daemon restart
From: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
Date: Mon, 26 Sep 2005 21:32:12 +1000
Cc: Keir Fraser <Keir.Fraser@xxxxxxxxxxxx>
Delivery-date: Mon, 26 Sep 2005 11:29:36 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-tools-request@lists.xensource.com?subject=help>
List-id: Xen control tools developers <xen-tools.lists.xensource.com>
List-post: <mailto:xen-tools@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-tools>, <mailto:xen-tools-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-tools>, <mailto:xen-tools-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-tools-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Rusty Russell <rusty@xxxxxxxxxxxxxxx>
# Node ID 6bf9c27fa43b4da8d3be9b65e1bebd0385223487
# Parent  703e0e8e7efce364f62a79b209af0d48195b6825
Handle xenstored restarting in libxenstore

Store filename, watches and transaction ID in handle, and on read/write errors 
reopen and try to reestablish watches and transaction trasparently to client.
Add reconnecting flag to handle to avoid recursion if something badly wrong.
Add committing flag: xs_transaction_end is the only operation which isn't 
simply repeatable.  If we can't re-establish the transaction, we know it has 
successfully been committed.
Add --restart test to xs_random which kills daemon partway through writes or 
reads.

Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx>

diff -r 703e0e8e7efc -r 6bf9c27fa43b tools/xenstore/Makefile
--- a/tools/xenstore/Makefile   Mon Sep 26 10:53:13 2005
+++ b/tools/xenstore/Makefile   Mon Sep 26 11:26:45 2005
@@ -49,7 +49,7 @@
        $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
 
 xs_test: xs_test.o xs_lib.o utils.o
-xs_random: xs_random.o xs_test_lib.o xs_lib.o talloc.o utils.o
+xs_random: xs_random.o xs_lib.o talloc.o utils.o
 xs_stress: xs_stress.o xs_test_lib.o xs_lib.o talloc.o utils.o
 xs_crashme: xs_crashme.o xs_lib.o talloc.o utils.o
 
@@ -84,9 +84,12 @@
 print-end:
        @echo
 
-check: print-dir testsuite-fast randomcheck-fast print-end
+check: $(XEN_LIBXC)/xen print-dir testsuite-fast randomcheck-fast print-end
 
-fullcheck: testsuite-run randomcheck stresstest
+fullcheck: $(XEN_LIBXC)/xen testsuite-run randomcheck stresstest
+
+$(XEN_LIBXC)/xen:
+       make -C $(XEN_LIBXC) mk-symlinks
 
 $(TESTDIR):
        mkdir $@
@@ -107,6 +110,7 @@
        $(TESTENV) ./xs_random --simple --fast /tmp/xs_random 200000 
$(RANDSEED) && echo
        $(TESTENV) ./xs_random --fast /tmp/xs_random 100000 $(RANDSEED) && echo
 #      $(TESTENV) ./xs_random --fail /tmp/xs_random 10000 $(RANDSEED)
+       $(TESTENV) ./xs_random --restart /tmp/xs_random 500 $(RANDSEED)
 
 crashme:  xs_crashme xenstored_test $(TESTDIR)
        rm -rf $(TESTDIR)/store $(TESTDIR)/transactions /tmp/xs_crashme.vglog* 
/tmp/trace
diff -r 703e0e8e7efc -r 6bf9c27fa43b tools/xenstore/xs.c
--- a/tools/xenstore/xs.c       Mon Sep 26 10:53:13 2005
+++ b/tools/xenstore/xs.c       Mon Sep 26 11:26:45 2005
@@ -36,12 +36,39 @@
 #include "xenstored.h"
 #include "xs_lib.h"
 #include "utils.h"
+#include "list.h"
+
+struct xs_watch
+{
+       struct list_head list;
+       char *path, *token;
+};
 
 struct xs_handle
 {
        int fd;
+       const char *connect_to;
+       struct list_head watches;
+       char *transid;
+       bool committing;
+       bool reconnecting;
 };
 
+/* free(), but don't change errno. */
+static void free_no_errno(void *p)
+{
+       int saved_errno = errno;
+       free(p);
+       errno = saved_errno;
+}
+
+static void close_no_errno(int fd)
+{
+       int saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+}
+
 /* Get the socket from the store daemon handle.
  */
 int xs_fileno(struct xs_handle *h)
@@ -49,60 +76,36 @@
        return h->fd;
 }
 
-static struct xs_handle *get_socket(const char *connect_to)
+static int get_socket(const char *connect_to)
 {
        struct sockaddr_un addr;
-       int sock, saved_errno;
-       struct xs_handle *h = NULL;
+       int sock;
 
        sock = socket(PF_UNIX, SOCK_STREAM, 0);
        if (sock < 0)
-               return NULL;
+               return sock;
 
        addr.sun_family = AF_UNIX;
        strcpy(addr.sun_path, connect_to);
 
-       if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
-               h = malloc(sizeof(*h));
-               if (h) {
-                       h->fd = sock;
-                       return h;
-               }
-       }
-
-       saved_errno = errno;
-       close(sock);
-       errno = saved_errno;
-       return NULL;
-}
-
-static struct xs_handle *get_dev(const char *connect_to)
-{
-       int fd, saved_errno;
-       struct xs_handle *h;
-
-       fd = open(connect_to, O_RDWR);
-       if (fd < 0)
-               return NULL;
-
-       h = malloc(sizeof(*h));
-       if (h) {
-               h->fd = fd;
-               return h;
-       }
-
-       saved_errno = errno;
-       close(fd);
-       errno = saved_errno;
-       return NULL;
-}
-
-static struct xs_handle *get_handle(const char *connect_to)
+       if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0)
+               return sock;
+
+       close_no_errno(sock);
+       return -1;
+}
+
+static int get_dev(const char *connect_to)
+{
+       return open(connect_to, O_RDWR);
+}
+
+static int get_handle(const char *connect_to)
 {
        struct stat buf;
 
        if (stat(connect_to, &buf) != 0)
-               return NULL;
+               return -1;
 
        if (S_ISSOCK(buf.st_mode))
                return get_socket(connect_to);
@@ -110,19 +113,71 @@
                return get_dev(connect_to);
 }
 
+static bool restore_watches(struct xs_handle *h);
+static bool restore_transaction(struct xs_handle *h);
+
+static bool recover(struct xs_handle *h)
+{
+       return restore_watches(h) && restore_transaction(h);
+}
+
+/* Don't fail easily: give 30 seconds. */
+#ifndef RECONNECT_TIME
+#define RECONNECT_TIME 30
+#endif
+
+/* Recovery: daemon can restart, so we reconnect. */
+static bool reconnect(struct xs_handle *h)
+{
+       unsigned int i;
+
+       if (h->reconnecting)
+               return 0;
+
+       h->reconnecting = true;
+       close(h->fd);
+
+       for (i = 0; i < RECONNECT_TIME; i++) {
+               h->fd = get_handle(h->connect_to);
+               if (h->fd >= 0 && recover(h)) {
+                       h->reconnecting = false;
+                       return true;
+               }
+               close_no_errno(h->fd);
+               sleep(1);
+       }
+       return false;
+}
+
+static struct xs_handle *xs_open(const char *connect_to)
+{
+       struct xs_handle *h = malloc(sizeof(*h));
+       h->fd = -1;
+       h->reconnecting = false;
+       h->connect_to = connect_to;
+       INIT_LIST_HEAD(&h->watches);
+       h->transid = NULL;
+       h->committing = false;
+       if (!reconnect(h)) {
+               free_no_errno(h);
+               h = NULL;
+       }
+       return h;
+}
+
 struct xs_handle *xs_daemon_open(void)
 {
-       return get_handle(xs_daemon_socket());
+       return xs_open(xs_daemon_socket());
 }
 
 struct xs_handle *xs_daemon_open_readonly(void)
 {
-       return get_handle(xs_daemon_socket_ro());
+       return xs_open(xs_daemon_socket_ro());
 }
 
 struct xs_handle *xs_domain_open(void)
 {
-       return get_handle(xs_domain_dev());
+       return xs_open(xs_domain_dev());
 }
 
 void xs_daemon_close(struct xs_handle *h)
@@ -175,7 +230,6 @@
 {
        struct xsd_sockmsg msg;
        void *ret;
-       int saved_errno;
 
        if (!read_all(fd, &msg, sizeof(msg)))
                return NULL;
@@ -185,9 +239,7 @@
                return NULL;
 
        if (!read_all(fd, ret, msg.len)) {
-               saved_errno = errno;
-               free(ret);
-               errno = saved_errno;
+               free_no_errno(ret);
                return NULL;
        }
 
@@ -209,22 +261,23 @@
        unsigned int i;
        struct sigaction ignorepipe, oldact;
 
+       ignorepipe.sa_handler = SIG_IGN;
+       sigemptyset(&ignorepipe.sa_mask);
+       ignorepipe.sa_flags = 0;
+       sigaction(SIGPIPE, &ignorepipe, &oldact);
+
+again:
        msg.type = type;
        msg.len = 0;
        for (i = 0; i < num_vecs; i++)
                msg.len += iovec[i].iov_len;
 
-       ignorepipe.sa_handler = SIG_IGN;
-       sigemptyset(&ignorepipe.sa_mask);
-       ignorepipe.sa_flags = 0;
-       sigaction(SIGPIPE, &ignorepipe, &oldact);
-
        if (!xs_write_all(h->fd, &msg, sizeof(msg)))
-               goto fail;
+               goto reconnect;
 
        for (i = 0; i < num_vecs; i++)
                if (!xs_write_all(h->fd, iovec[i].iov_base, iovec[i].iov_len))
-                       goto fail;
+                       goto reconnect;
 
        /* Watches can have fired before reply comes: daemon detects
         * and re-transmits, so we can ignore this. */
@@ -232,42 +285,30 @@
                free(ret);
                ret = read_reply(h->fd, &msg.type, len);
                if (!ret)
-                       goto fail;
+                       goto reconnect;
        } while (msg.type == XS_WATCH_EVENT);
 
        sigaction(SIGPIPE, &oldact, NULL);
        if (msg.type == XS_ERROR) {
-               saved_errno = get_error(ret);
-               free(ret);
-               errno = saved_errno;
+               errno = get_error(ret);
+               free_no_errno(ret);
                return NULL;
        }
 
        if (msg.type != type) {
                free(ret);
-               saved_errno = EBADF;
-               goto close_fd;
-               
+               errno = EBADF;
+               goto reconnect;
        }
        return ret;
 
-fail:
-       /* We're in a bad state, so close fd. */
+reconnect:
+       /* All operations are idempotent, so no harm in retrying. */
        saved_errno = errno;
-       sigaction(SIGPIPE, &oldact, NULL);
-close_fd:
-       close(h->fd);
-       h->fd = -1;
+       if (reconnect(h))
+               goto again;
        errno = saved_errno;
        return NULL;
-}
-
-/* free(), but don't change errno. */
-static void free_no_errno(void *p)
-{
-       int saved_errno = errno;
-       free(p);
-       errno = saved_errno;
 }
 
 /* Simplified version of xs_talkv: single message. */
@@ -428,6 +469,27 @@
        return false;
 }
 
+static bool one_watch(struct xs_handle *h, struct xs_watch *w)
+{
+       struct iovec iov[2];
+
+       iov[0].iov_base = w->path;
+       iov[0].iov_len = strlen(w->path) + 1;
+       iov[1].iov_base = w->token;
+       iov[1].iov_len = strlen(w->token) + 1;
+       return xs_bool(xs_talkv(h, XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
+}
+
+static bool restore_watches(struct xs_handle *h)
+{
+       struct xs_watch *i;
+
+       list_for_each_entry(i, &h->watches, list)
+               if (!one_watch(h, i))
+                       return false;
+       return true;
+}
+
 /* Watch a node for changes (poll on fd to detect, or call read_watch()).
  * When the node (or any child) changes, fd will become readable.
  * Token is returned when watch is read, to allow matching.
@@ -435,14 +497,23 @@
  */
 bool xs_watch(struct xs_handle *h, const char *path, const char *token)
 {
-       struct iovec iov[2];
-
-       iov[0].iov_base = (void *)path;
-       iov[0].iov_len = strlen(path) + 1;
-       iov[1].iov_base = (void *)token;
-       iov[1].iov_len = strlen(token) + 1;
-
-       return xs_bool(xs_talkv(h, XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
+       struct xs_watch *watch;
+
+       watch = malloc(sizeof (*watch) + strlen(path)+1 + strlen(token)+1);
+       if (!watch)
+               return false;
+
+       watch->path = (char *)(watch + 1);
+       strcpy(watch->path, path);
+       watch->token = watch->path + strlen(path) + 1;
+       strcpy(watch->token, token);
+
+       if (one_watch(h, watch)) {
+               list_add(&watch->list, &h->watches);
+               return true;
+       }
+       free_no_errno(watch);
+       return false;
 }
 
 /* Find out what node change was on (will block if nothing pending).
@@ -453,9 +524,11 @@
 {
        struct xsd_sockmsg msg;
        char **ret;
-
+       int saved_errno;
+
+again:
        if (!read_all(h->fd, &msg, sizeof(msg)))
-               return NULL;
+               goto reconnect;
 
        assert(msg.type == XS_WATCH_EVENT);
        ret = malloc(sizeof(char *)*2 + msg.len);
@@ -465,10 +538,17 @@
        ret[0] = (char *)(ret + 2);
        if (!read_all(h->fd, ret[0], msg.len)) {
                free_no_errno(ret);
-               return NULL;
+               goto reconnect;
        }
        ret[1] = ret[0] + strlen(ret[0]) + 1;
        return ret;
+
+reconnect:
+       saved_errno = errno;
+       if (reconnect(h))
+               goto again;
+       errno = saved_errno;
+       return NULL;
 }
 
 /* Acknowledge watch on node.  Watches must be acknowledged before
@@ -486,13 +566,36 @@
 bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
 {
        struct iovec iov[2];
-
-       iov[0].iov_base = (char *)path;
-       iov[0].iov_len = strlen(path) + 1;
-       iov[1].iov_base = (char *)token;
-       iov[1].iov_len = strlen(token) + 1;
-
-       return xs_bool(xs_talkv(h, XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
+       struct xs_watch *i;
+
+       list_for_each_entry(i, &h->watches, list) {
+               if (!streq(i->path, path) || !streq(i->token, token))
+                       continue;
+
+               iov[0].iov_base = i->path;
+               iov[0].iov_len = strlen(i->path) + 1;
+               iov[1].iov_base = i->token;
+               iov[1].iov_len = strlen(i->token) + 1;
+
+               if (!xs_bool(xs_talkv(h,XS_UNWATCH,iov,ARRAY_SIZE(iov),NULL)))
+                       return false;
+               list_del(&i->list);
+               free(i);
+               return true;
+       }
+       errno = ENOENT;
+       return false;
+}
+
+static bool restore_transaction(struct xs_handle *h)
+{
+       if (!h->transid)
+               return true;
+
+       if (xs_bool(xs_single(h, XS_TRANSACTION_START, h->transid, NULL)))
+               return true;
+       /* If we're committing and no longer exists, we succeeded. */
+       return h->committing;
 }
 
 /* Start a transaction: changes by others will not be seen during this
@@ -502,23 +605,47 @@
  */
 bool xs_transaction_start(struct xs_handle *h)
 {
-       return xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL));
+       char *transid;
+
+       transid = xs_single(h, XS_TRANSACTION_START, "", NULL);
+       if (!transid)
+               return false;
+       h->transid = transid;
+       return true;
 }
 
 /* End a transaction.
  * If abandon is true, transaction is discarded instead of committed.
- * Returns false on failure, which indicates an error: transactions will
- * not fail spuriously.
+ * Returns false on failure: if errno == EAGAIN, you have to restart
+ * transaction.
  */
 bool xs_transaction_end(struct xs_handle *h, bool abort)
 {
        char abortstr[2];
+       bool ret;
 
        if (abort)
                strcpy(abortstr, "F");
        else
                strcpy(abortstr, "T");
-       return xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL));
+
+       if (!h->transid) {
+               errno = ENOENT;
+               return false;
+       }
+
+       h->committing = true;
+       ret = xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL));
+
+       /* On re-transmission, we can get ENOENT if first one succeeded,
+        * otherwise we never should. */
+       if (!ret && errno == ENOENT)
+               ret = true;
+       free_no_errno(h->transid);
+       h->transid = NULL;
+       h->committing = false;
+
+       return ret;
 }
 
 /* Introduce a new domain.
diff -r 703e0e8e7efc -r 6bf9c27fa43b tools/xenstore/xs_random.c
--- a/tools/xenstore/xs_random.c        Mon Sep 26 10:53:13 2005
+++ b/tools/xenstore/xs_random.c        Mon Sep 26 11:26:45 2005
@@ -17,6 +17,47 @@
 #include "talloc.h"
 #include "utils.h"
 
+static bool fail_once = false;
+static unsigned int fail_len;
+
+static void restart_daemon(void);
+
+/* Override xs functions so we can fail at "random" times. */
+#define XSTEST
+static bool read_all(int fd, void *data, unsigned int len);
+static bool read_all_choice(int fd, void *data, unsigned int len)
+{
+       if (fail_once) {
+               if (len > fail_len) {
+                       fail_once = false;
+                       restart_daemon();
+                       errno = EBADF;
+                       return false;
+               }
+               fail_len -= len;
+       }
+       return read_all(fd, data, len);
+}
+
+static bool write_all_choice(int fd, const void *data, unsigned int len)
+{
+       if (fail_once) {
+               if (len > fail_len) {
+                       fail_once = false;
+                       restart_daemon();
+                       errno = EPIPE;
+                       return false;
+               }
+               fail_len -= len;
+       }
+       return xs_write_all(fd, data, len);
+}
+
+/* Fail fast, please. */
+#define RECONNECT_TIME 2
+
+#include "xs.c"
+
 struct ops
 {
        char *name;
@@ -53,6 +94,7 @@
 {
        const char *base;
        char *transact_base;
+       bool fail_transaction;
 };
 
 static void convert_to_dir(const char *dirname)
@@ -389,6 +431,17 @@
                goto success;
        }
 
+       if (info->fail_transaction) {
+               cmd = talloc_asprintf(NULL, "rm -rf %s", info->transact_base);
+               do_command(cmd);
+               info->fail_transaction = false;
+               talloc_free(cmd);
+               talloc_free(info->transact_base);
+               info->transact_base = NULL;
+               errno = EAGAIN;
+               return false;
+       }
+
        old = talloc_asprintf(NULL, "rm -rf %s", info->base);
        do_command(old);
        talloc_free(old);
@@ -410,6 +463,7 @@
 
        info->base = dir;
        info->transact_base = NULL;
+       info->fail_transaction = false;
        return info;
 }
 
@@ -962,6 +1016,14 @@
        setup_file_ops(dir);
        setup_xs_ops();
 };
+
+static void restart_daemon(void)
+{
+       kill(daemon_pid, SIGKILL);
+       waitpid(daemon_pid, NULL, 0);
+
+       setup_xs_ops();
+}
 
 struct simple_data
 {
@@ -1553,24 +1615,179 @@
        reduce_problem(try + 1, try_fail, &data);
 }
 
+struct restart_data
+{
+       unsigned int seed;
+       bool print_progress;
+       bool fast;
+       const char *dir;
+};
+
+/* Restart: try with randomly restarting daemon. */
+static unsigned int try_restart(const bool *trymap,
+                               unsigned int number,
+                               bool verbose,
+                               void *_data)
+{
+       void *fileh, *xsh;
+       bool transact = false;
+       struct ops *fail;
+       struct diff_data *data = _data;
+       unsigned int i, print;
+       int st;
+
+       cleanup(data->dir);
+       setup(data->dir);
+
+       fileh = file_handle(data->dir);
+       xsh = xs_handle(data->dir);
+
+       print = number / 76;
+       if (!print)
+               print = 1;
+
+       for (i = 0; i < number; i++) {
+               char *file, *xs;
+
+               if (data->print_progress) {
+                       if (i % print == 0) {
+                               printf(".");
+                               fflush(stdout);
+                       }
+               }
+               if (trymap && !trymap[i])
+                       continue;
+
+               fail_once = true;
+               st = i+data->seed;
+               fail_len = get_randomness(&st) % 100;
+
+               if (verbose)
+                       printf("XS: ");
+               xs = do_next_op(&xs_ops, xsh, i+data->seed, verbose);
+               if (verbose)
+                       printf("-> %.*s\n", (int)(strchr(xs, '/') - xs), xs);
+
+               /* Due to restart, transaction can return EAGAIN. */
+               if (streq(xs, "FAILED:Resource temporarily unavailable")) {
+                       ((struct file_ops_info *)fileh)->fail_transaction
+                               = true;
+                       transact = false;
+               }
+
+               if (verbose)
+                       printf("FILE: ");
+
+               file = do_next_op(&file_ops, fileh, i+data->seed, verbose);
+               if (verbose)
+                       printf("-> %.*s\n",
+                              (int)(strchr(file, '/') - file), file);
+
+               if (!streq(file, xs))
+                       goto out;
+
+               if (strstarts(file, "OK:START-TRANSACT:"))
+                       transact = true;
+               else if (streq(file, "OK:STOP-TRANSACT"))
+                       transact = false;
+
+               talloc_free(file);
+               talloc_free(xs);
+
+               if (data->fast)
+                       continue;
+
+               /* In case it didn't fail yet, we don't want that now! */
+               fail_once = false;
+               fail = NULL;
+               if (!ops_equal(&xs_ops, xsh, &file_ops, fileh, "/", &fail)) {
+                       if (fail)
+                               barf("%s failed during test\n", fail->name);
+                       if (verbose)
+                               printf("Trees differ:\nXS:%s\nFILE%s\n",
+                                      dump(&xs_ops, xsh),
+                                      dump(&file_ops, fileh));
+                       goto out;
+               }
+
+               if (transact) {
+                       void *fileh_pre = file_handle(data->dir);
+                       void *xsh_pre = xs_handle(data->dir);
+
+                       fail = NULL;
+                       if (!ops_equal(&xs_ops, xsh_pre, &file_ops, fileh_pre,
+                                      "/", &fail)) {
+                               if (fail)
+                                       barf("%s failed during transact\n",
+                                            fail->name);
+
+                               xs_daemon_close(xsh_pre);
+                               talloc_free(fileh_pre);
+                               goto out;
+                       }
+                       xs_daemon_close(xsh_pre);
+                       talloc_free(fileh_pre);
+               }
+       }
+
+       fail = NULL;
+       if (data->fast)
+               if (!ops_equal(&xs_ops, xsh, &file_ops, fileh, "/", &fail))
+                       barf("Final result not the same: try without --fast");
+out:
+       file_ops.close(fileh);  
+       xs_ops.close(xsh);      
+       return i;
+}
+
+/* Restart random test: compare results against file backend, daemon
+ * randomly restarting. */
+static void restart_test(const char *dir,
+                     unsigned int iters, unsigned int seed, bool fast, 
+                     bool verbose)
+{
+       struct restart_data data;
+       unsigned int try;
+
+       data.seed = seed;
+       data.print_progress = !verbose;
+       data.fast = fast;
+       data.dir = dir;
+
+       try = try_restart(NULL, iters, verbose, &data);
+       if (try == iters) {
+               cleanup_xs_ops();
+               exit(0);
+       }
+       printf("Failed on iteration %u of seed %u\n", try + 1, seed);
+       data.print_progress = false;
+       reduce_problem(try + 1, try_restart, &data);
+}
+
 int main(int argc, char *argv[])
 {
        bool verbose = false;
-       bool simple = false;
        bool fast = false;
-       bool fail = false;
+       void (*test)(const char *, unsigned, unsigned, bool, bool) = diff_test;
 
        if (argv[1] && streq(argv[1], "--fail")) {
-               fail = true;
+               test = fail_test;
                argv++;
                argc--;
        }
 
        if (argv[1] && streq(argv[1], "--simple")) {
-               simple = true;
+               test = simple_test;
                argv++;
                argc--;
        }
+
+       if (argv[1] && streq(argv[1], "--restart")) {
+               test = restart_test;
+               argv++;
+               argc--;
+       }
+
 
        if (argv[1] && streq(argv[1], "--fast")) {
                fast = true;
@@ -1585,15 +1802,9 @@
        }
 
        if (argc != 4)
-               barf("Usage: xs_random [--fail|--simple] [--fast] [--verbose] 
<directory> <iterations> <seed>");
+               barf("Usage: xs_random [--fail|--simple|--restart] [--fast] 
[--verbose] <directory> <iterations> <seed>");
 
        talloc_enable_null_tracking();
-
-       if (fail)
-               fail_test(argv[1], atoi(argv[2]), atoi(argv[3]), fast, verbose);
-       else if (simple)
-               simple_test(argv[1], atoi(argv[2]), atoi(argv[3]), fast, 
verbose);
-       else
-               diff_test(argv[1],  atoi(argv[2]), atoi(argv[3]), fast, 
verbose);
+       test(argv[1], atoi(argv[2]), atoi(argv[3]), fast, verbose);
        exit(2);
 }
diff -r 703e0e8e7efc -r 6bf9c27fa43b tools/xenstore/xs_test.c
--- a/tools/xenstore/xs_test.c  Mon Sep 26 10:53:13 2005
+++ b/tools/xenstore/xs_test.c  Mon Sep 26 11:26:45 2005
@@ -373,7 +373,7 @@
 
 static void do_readack(unsigned int handle)
 {
-       enum xsd_sockmsg_type type;
+       enum xsd_sockmsg_type type = XS_ERROR; /* Stupid gcc. */
        char *ret = NULL;
 
        /* Watches can have fired before reply comes: daemon detects
@@ -615,6 +615,11 @@
        /* Create new handle. */
        handles[i] = new(struct xs_handle);
        handles[i]->fd = -2;
+       handles[i]->reconnecting = false;
+       handles[i]->connect_to = NULL;
+       INIT_LIST_HEAD(&handles[i]->watches);
+       handles[i]->transid = NULL;
+       handles[i]->committing = false;
 
        /* Read in daemon pid. */
        daemon_pid = *(int *)((void *)out + 32);

-- 
A bad analogy is like a leaky screwdriver -- Richard Braakman


_______________________________________________
Xen-tools mailing list
Xen-tools@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-tools

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-tools] [PATCH 3/3] libxenstore: reconnect on daemon restart, Rusty Russell <=