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 1/3] Recover transaction on restart, give transaction

To: Xen Tools <xen-tools@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-tools] [PATCH 1/3] Recover transaction on restart, give transactions IDs
From: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
Date: Mon, 26 Sep 2005 21:30:18 +1000
Cc: Keir Fraser <Keir.Fraser@xxxxxxxxxxxx>
Delivery-date: Mon, 26 Sep 2005 11:27:46 +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 6d2f8b0a18c4713286a16d22fd2a11d7ab4525b4
# Parent  5ea81e6405097b7ac25901ecdcd5fb19475508d8
Recover transactions on restart.
Give an ID to each transaction, and return that to client (they can use this to 
get it back).

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

diff -r 5ea81e640509 -r 6d2f8b0a18c4 tools/xenstore/xenstored_core.c
--- a/tools/xenstore/xenstored_core.c   Sun Sep 25 10:47:22 2005
+++ b/tools/xenstore/xenstored_core.c   Mon Sep 26 04:30:14 2005
@@ -1409,9 +1409,10 @@
                manual_node("/", "tool");
                manual_node("/tool", "xenstored");
                manual_node("/tool/xenstored", NULL);
-       }
-
-       /* FIXME: Fsck */
+       } else {
+               /* FIXME: Fsck */
+               recover_transactions();
+       }
 }
 
 static void write_pidfile(const char *pidfile)
diff -r 5ea81e640509 -r 6d2f8b0a18c4 tools/xenstore/xenstored_transaction.c
--- a/tools/xenstore/xenstored_transaction.c    Sun Sep 25 10:47:22 2005
+++ b/tools/xenstore/xenstored_transaction.c    Mon Sep 26 04:30:14 2005
@@ -55,10 +55,11 @@
        /* Generation when transaction started. */
        unsigned int generation;
 
-       /* My owner (conn->transaction == me). */
+       /* My owner (conn->transaction == me).  NULL if unclaimed. */
        struct connection *conn;
 
        /* TDB to work on, and filename */
+       int id;
        TDB_CONTEXT *tdb;
        char *tdb_name;
 
@@ -108,35 +109,90 @@
        return 0;
 }
 
+/* Very dumb algorithm to get unique transaction id */
+static int get_transaction_id(void)
+{
+       int i = 0;
+       struct transaction *trans;
+
+again:
+       list_for_each_entry(trans, &transactions, list) {
+               if (trans->id == i) {
+                       i++;
+                       goto again;
+               }
+       }
+       return i;
+}
+
+static struct transaction *get_trans_by_id(int id)
+{
+       struct transaction *trans;
+
+       list_for_each_entry(trans, &transactions, list)
+               if (trans->id == id)
+                       return trans;
+       return NULL;
+}
+
+/* Caller fills in ->conn and ->tdb. */
+static struct transaction *new_trans(void *ctx, unsigned int gen, int id)
+{
+       struct transaction *trans;
+
+       trans = talloc(ctx, struct transaction);
+       INIT_LIST_HEAD(&trans->changes);
+       trans->generation = gen;
+       trans->id = id;
+       trans->tdb_name = talloc_asprintf(trans, "%s.%i", xs_daemon_tdb(), id);
+       list_add_tail(&trans->list, &transactions);
+       talloc_set_destructor(trans, destroy_transaction);
+       return trans;
+}
+
 void do_transaction_start(struct connection *conn, struct buffered_data *in)
 {
        struct transaction *trans;
+       char *vec[1];
+       char id[MAX_STRLEN(trans->id)];
+
+       if (get_strings(in, vec, ARRAY_SIZE(vec)) != ARRAY_SIZE(vec)) {
+               send_error(conn, EINVAL);
+               return;
+       }
 
        if (conn->transaction) {
                send_error(conn, EBUSY);
                return;
        }
 
-       /* Attach transaction to input for autofree until it's complete */
-       trans = talloc(in, struct transaction);
-       INIT_LIST_HEAD(&trans->changes);
+       /* If given a name, they want transaction back. */
+       if (!streq(vec[0], "")) {
+               trans = get_trans_by_id(atoi(vec[0]));
+               if (!trans || trans->conn) {
+                       send_error(conn, ENOENT);
+                       return;
+               }
+       } else {
+               /* Attach transaction to input for autofree until complete */
+               trans = new_trans(in, generation, get_transaction_id());
+
+               trans->tdb = tdb_copy(tdb_context(conn), trans->tdb_name);
+               if (!trans->tdb) {
+                       send_error(conn, errno);
+                       return;
+               }
+               /* TDB lifetime is that of transaction */
+               talloc_steal(trans, trans->tdb);
+       }
+
+       /* Now we own it. */
        trans->conn = conn;
-       trans->generation = generation;
-       trans->tdb_name = talloc_asprintf(trans, "%s.%p",
-                                         xs_daemon_tdb(), trans);
-       trans->tdb = tdb_copy(tdb_context(conn), trans->tdb_name);
-       if (!trans->tdb) {
-               send_error(conn, errno);
-               return;
-       }
-       /* Make it close if we go away. */
-       talloc_steal(trans, trans->tdb);
-
-       /* Now we own it. */
        conn->transaction = talloc_steal(conn, trans);
-       list_add_tail(&trans->list, &transactions);
-       talloc_set_destructor(trans, destroy_transaction);
-       send_ack(conn, XS_TRANSACTION_START);
+
+       /* We return the transaction id as a string. */
+       sprintf(id, "%i", trans->id);
+       send_reply(conn, XS_TRANSACTION_START, id, strlen(id));
 }
 
 void do_transaction_end(struct connection *conn, const char *arg)
@@ -181,3 +237,37 @@
        send_ack(conn, XS_TRANSACTION_END);
 }
 
+/* Transactions sit in files: recover them. */
+void recover_transactions(void)
+{
+       DIR *dir;
+       struct dirent *dirent;
+       int id;
+       struct transaction *trans;
+       char *transdir;
+
+       transdir = talloc_strdup(talloc_autofree_context(), xs_daemon_tdb());
+       if (strrchr(transdir, '/'))
+               *strchr(transdir, '/') = '\0';
+       else
+               transdir = talloc_strdup(transdir, ".");
+
+       dir = opendir(transdir);
+       if (!dir)
+               barf_perror("Could not open %s", transdir);
+
+       while ((dirent = readdir(dir)) != NULL) {
+               if (!strstarts(dirent->d_name, "tdb."))
+                       continue;
+
+               id = atoi(dirent->d_name + strlen("tdb."));
+               trans = new_trans(transdir, -1, id);
+               trans->conn = NULL;
+               trans->tdb = tdb_open(trans->tdb_name, 0, 0, O_RDWR, 0);
+               if (!trans->tdb) {
+                       eprintf("Could not reopen transaction %i: corrupt?",
+                               id);
+                       talloc_free(trans);
+               }
+       }
+}
diff -r 5ea81e640509 -r 6d2f8b0a18c4 tools/xenstore/xenstored_transaction.h
--- a/tools/xenstore/xenstored_transaction.h    Sun Sep 25 10:47:22 2005
+++ b/tools/xenstore/xenstored_transaction.h    Mon Sep 26 04:30:14 2005
@@ -32,4 +32,6 @@
 
 /* Return tdb context to use for this connection. */
 TDB_CONTEXT *tdb_transaction_context(struct transaction *trans);
+
+void recover_transactions(void);
 #endif /* _XENSTORED_TRANSACTION_H */

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


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