struct ovsdb_idl *idl;
struct hmap txn_rows;
enum ovsdb_idl_txn_status status;
+ char *error;
bool dry_run;
struct ds comment;
txn->idl = idl;
hmap_init(&txn->txn_rows);
txn->status = TXN_INCOMPLETE;
+ txn->error = NULL;
txn->dry_run = false;
ds_init(&txn->comment);
}
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);
}
}
+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.
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");
}
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 *);
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) {
vsctl_context_done(&ctx, c);
}
}
+ error = xstrdup(ovsdb_idl_txn_get_error(txn));
ovsdb_idl_txn_destroy(txn);
the_idl_txn = NULL;
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;