char *error;
bool dry_run;
struct ds comment;
+ unsigned int commit_seqno;
/* Increments. */
char *inc_table;
int64_t inc_new_value;
/* Inserted rows. */
- struct hmap inserted_rows;
+ struct hmap inserted_rows; /* Contains "struct ovsdb_idl_txn_insert"s. */
};
struct ovsdb_idl_txn_insert {
}
if (msg->type == JSONRPC_NOTIFY
- && !strcmp(msg->method, "update")
- && msg->params->type == JSON_ARRAY
- && msg->params->u.array.n == 2
- && msg->params->u.array.elems[0]->type == JSON_NULL) {
+ && !strcmp(msg->method, "update")
+ && msg->params->type == JSON_ARRAY
+ && msg->params->u.array.n == 2
+ && msg->params->u.array.elems[0]->type == JSON_NULL) {
/* Database contents changed. */
ovsdb_idl_parse_update(idl, msg->params->u.array.elems[1]);
} else if (msg->type == JSONRPC_REPLY
ovsdb_idl_read(const struct ovsdb_idl_row *row,
const struct ovsdb_idl_column *column)
{
- const struct ovsdb_idl_table_class *class = row->table->class;
- size_t column_idx = column - class->columns;
+ const struct ovsdb_idl_table_class *class;
+ size_t column_idx;
+
+ assert(!ovsdb_idl_row_is_synthetic(row));
+
+ class = row->table->class;
+ column_idx = column - class->columns;
assert(row->new != NULL);
assert(column_idx < class->n_columns);
return "aborted";
case TXN_SUCCESS:
return "success";
- case TXN_TRY_AGAIN:
- return "try again";
+ case TXN_AGAIN_WAIT:
+ return "wait then try again";
+ case TXN_AGAIN_NOW:
+ return "try again now";
case TXN_NOT_LOCKED:
return "not locked";
case TXN_ERROR:
txn->error = NULL;
txn->dry_run = false;
ds_init(&txn->comment);
+ txn->commit_seqno = txn->idl->change_seqno;
txn->inc_table = NULL;
txn->inc_column = NULL;
HMAP_FOR_EACH (row, txn_node, &txn->txn_rows) {
const struct ovsdb_idl_table_class *class = row->table->class;
- if (row->old == row->new) {
- continue;
- } else if (!row->new) {
+ if (!row->new) {
if (class->is_root) {
struct json *op = json_object_create();
json_object_put_string(op, "op", "delete");
} else {
/* Let ovsdb-server decide whether to really delete it. */
}
- } else {
+ } else if (row->old != row->new) {
struct json *row_json;
struct json *op;
size_t idx;
json_hash(txn->request_id, 0));
txn->status = TXN_INCOMPLETE;
} else {
- txn->status = TXN_TRY_AGAIN;
+ txn->status = TXN_AGAIN_WAIT;
}
ovsdb_idl_txn_disassemble(txn);
struct ovsdb_datum *datum)
{
struct ovsdb_idl_row *row = (struct ovsdb_idl_row *) row_;
- const struct ovsdb_idl_table_class *class = row->table->class;
- size_t column_idx = column - class->columns;
+ const struct ovsdb_idl_table_class *class;
+ size_t column_idx;
+
+ if (ovsdb_idl_row_is_synthetic(row)) {
+ return;
+ }
+
+ class = row->table->class;
+ column_idx = column - class->columns;
assert(row->new != NULL);
assert(column_idx < class->n_columns);
* prerequisite to completing the transaction. That is, if 'column' in 'row_'
* changed (or if 'row_' was deleted) between the time that the IDL originally
* read its contents and the time that the transaction commits, then the
- * transaction aborts and ovsdb_idl_txn_commit() returns TXN_TRY_AGAIN.
+ * transaction aborts and ovsdb_idl_txn_commit() returns TXN_AGAIN_WAIT or
+ * TXN_AGAIN_NOW (depending on whether the database change has already been
+ * received).
*
* The intention is that, to ensure that no transaction commits based on dirty
* reads, an application should call ovsdb_idl_txn_verify() on each data item
const struct ovsdb_idl_column *column)
{
struct ovsdb_idl_row *row = (struct ovsdb_idl_row *) row_;
- const struct ovsdb_idl_table_class *class = row->table->class;
- size_t column_idx = column - class->columns;
+ const struct ovsdb_idl_table_class *class;
+ size_t column_idx;
+
+ if (ovsdb_idl_row_is_synthetic(row)) {
+ return;
+ }
+
+ class = row->table->class;
+ column_idx = column - class->columns;
assert(row->new != NULL);
assert(row->old == NULL ||
{
struct ovsdb_idl_row *row = (struct ovsdb_idl_row *) row_;
+ if (ovsdb_idl_row_is_synthetic(row)) {
+ return;
+ }
+
assert(row->new != NULL);
if (!row->old) {
ovsdb_idl_row_unparse(row);
struct ovsdb_idl_txn *txn;
HMAP_FOR_EACH (txn, hmap_node, &idl->outstanding_txns) {
- ovsdb_idl_txn_complete(txn, TXN_TRY_AGAIN);
+ ovsdb_idl_txn_complete(txn, TXN_AGAIN_WAIT);
}
}
status = (hard_errors ? TXN_ERROR
: lock_errors ? TXN_NOT_LOCKED
- : soft_errors ? TXN_TRY_AGAIN
+ : soft_errors ? (txn->commit_seqno == idl->change_seqno
+ ? TXN_AGAIN_WAIT
+ : TXN_AGAIN_NOW)
: TXN_SUCCESS);
}