[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-tools] [PATCH 1/3] Recover transaction on restart, give transactions IDs
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |