dpif: Factor 'type' and 'error' out of individual dpif_op members.
[sliver-openvswitch.git] / lib / ovsdb-idl.c
index 11ca6b9..19ae16f 100644 (file)
@@ -91,6 +91,7 @@ struct ovsdb_idl_txn {
     char *error;
     bool dry_run;
     struct ds comment;
+    unsigned int commit_seqno;
 
     /* Increments. */
     char *inc_table;
@@ -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;
@@ -1587,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);
@@ -1705,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);
@@ -1755,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
@@ -1782,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 ||
@@ -1815,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);
@@ -1872,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);
     }
 }
 
@@ -2073,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);
     }