X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fovsdb-idl.c;h=19ae16fe54d0282b6bf3ae249dea6cbbce60db8e;hb=fe13b0e71752a5eb30b21e7a09d2f9370bc02387;hp=2ac6c2f14cdb59b270ea73ee226ab7d7f8cb7542;hpb=06b6d65132e54582031c8166c74725fc90239588;p=openvswitch diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index 2ac6c2f1..19ae16fe 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -91,6 +91,7 @@ struct ovsdb_idl_txn { char *error; bool dry_run; struct ds comment; + unsigned int commit_seqno; /* Increments. */ char *inc_table; @@ -100,7 +101,7 @@ struct ovsdb_idl_txn { 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 { @@ -320,10 +321,10 @@ ovsdb_idl_run(struct ovsdb_idl *idl) } 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 @@ -1111,8 +1112,13 @@ const struct ovsdb_datum * 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); @@ -1173,8 +1179,10 @@ ovsdb_idl_txn_status_to_string(enum ovsdb_idl_txn_status status) 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: @@ -1197,6 +1205,7 @@ ovsdb_idl_txn_create(struct ovsdb_idl *idl) 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; @@ -1458,9 +1467,7 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn) 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"); @@ -1471,7 +1478,7 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn) } 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; @@ -1589,7 +1596,7 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn) 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); @@ -1707,8 +1714,15 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_, 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); @@ -1757,7 +1771,9 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_, * 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 @@ -1784,8 +1800,15 @@ ovsdb_idl_txn_verify(const struct ovsdb_idl_row *row_, 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 || @@ -1817,6 +1840,10 @@ ovsdb_idl_txn_delete(const struct ovsdb_idl_row *row_) { 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); @@ -1874,7 +1901,7 @@ ovsdb_idl_txn_abort_all(struct ovsdb_idl *idl) 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); } } @@ -2075,7 +2102,9 @@ ovsdb_idl_txn_process_reply(struct ovsdb_idl *idl, 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); }