From 91e310a5c24a8f5741f04900ea24154acc695c7b Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 5 Feb 2010 14:11:12 -0800 Subject: [PATCH] ovsdb-idl: On transaction hard failure make a reason available to client. This make ovs-vsctl able to report problems that occur in better detail. --- lib/ovsdb-idl.c | 27 +++++++++++++++++++++++++++ lib/ovsdb-idl.h | 2 ++ utilities/ovs-vsctl.c | 6 +++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index 2051000fd..a0b0cc940 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -81,6 +81,7 @@ struct ovsdb_idl_txn { struct ovsdb_idl *idl; struct hmap txn_rows; enum ovsdb_idl_txn_status status; + char *error; bool dry_run; struct ds comment; @@ -867,6 +868,7 @@ ovsdb_idl_txn_create(struct ovsdb_idl *idl) txn->idl = idl; hmap_init(&txn->txn_rows); txn->status = TXN_INCOMPLETE; + txn->error = NULL; txn->dry_run = false; ds_init(&txn->comment); @@ -915,6 +917,7 @@ ovsdb_idl_txn_destroy(struct ovsdb_idl_txn *txn) } ovsdb_idl_txn_abort(txn); ds_destroy(&txn->comment); + free(txn->error); free(txn->inc_table); free(txn->inc_column); json_destroy(txn->inc_where); @@ -1253,6 +1256,27 @@ ovsdb_idl_txn_abort(struct ovsdb_idl_txn *txn) } } +const char * +ovsdb_idl_txn_get_error(const struct ovsdb_idl_txn *txn) +{ + if (txn->status != TXN_ERROR) { + return ovsdb_idl_txn_status_to_string(txn->status); + } else if (txn->error) { + return txn->error; + } else { + return "no error details available"; + } +} + +static void +ovsdb_idl_txn_set_error_json(struct ovsdb_idl_txn *txn, + const struct json *json) +{ + if (txn->error == NULL) { + txn->error = json_to_string(json, JSSF_SORT); + } +} + /* For transaction 'txn' that completed successfully, finds and returns the * permanent UUID that the database assigned to a newly inserted row, given the * 'uuid' that ovsdb_idl_txn_insert() assigned locally to that row. @@ -1566,15 +1590,18 @@ ovsdb_idl_txn_process_reply(struct ovsdb_idl *idl, soft_errors++; } else if (strcmp(error->u.string, "aborted")) { hard_errors++; + ovsdb_idl_txn_set_error_json(txn, op); } } else { hard_errors++; + ovsdb_idl_txn_set_error_json(txn, op); VLOG_WARN_RL(&syntax_rl, "\"error\" in reply is not JSON string"); } } } else { hard_errors++; + ovsdb_idl_txn_set_error_json(txn, op); VLOG_WARN_RL(&syntax_rl, "operation reply is not JSON null or object"); } diff --git a/lib/ovsdb-idl.h b/lib/ovsdb-idl.h index 3b8582d0d..d45142727 100644 --- a/lib/ovsdb-idl.h +++ b/lib/ovsdb-idl.h @@ -67,6 +67,8 @@ void ovsdb_idl_txn_wait(const struct ovsdb_idl_txn *); enum ovsdb_idl_txn_status ovsdb_idl_txn_commit(struct ovsdb_idl_txn *); void ovsdb_idl_txn_abort(struct ovsdb_idl_txn *); +const char *ovsdb_idl_txn_get_error(const struct ovsdb_idl_txn *); + int64_t ovsdb_idl_txn_get_increment_new_value(const struct ovsdb_idl_txn *); const struct uuid *ovsdb_idl_txn_get_insert_uuid(const struct ovsdb_idl_txn *, const struct uuid *); diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index 8ee18d78e..af901006e 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -2479,6 +2479,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands, struct vsctl_command *c; int64_t next_cfg = 0; char *comment; + char *error; txn = the_idl_txn = ovsdb_idl_txn_create(idl); if (dry_run) { @@ -2528,6 +2529,7 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands, vsctl_context_done(&ctx, c); } } + error = xstrdup(ovsdb_idl_txn_get_error(txn)); ovsdb_idl_txn_destroy(txn); the_idl_txn = NULL; @@ -2547,14 +2549,16 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands, for (c = commands; c < &commands[n_commands]; c++) { ds_destroy(&c->output); } + free(error); return; case TXN_ERROR: - vsctl_fatal("transaction error"); + vsctl_fatal("transaction error: %s", error); default: NOT_REACHED(); } + free(error); for (c = commands; c < &commands[n_commands]; c++) { struct ds *ds = &c->output; -- 2.43.0