sflow_agent: Use snprintf() in place of sprintf().
[openvswitch] / lib / ovsdb-idl.c
index 2ac6c2f14cdb59b270ea73ee226ab7d7f8cb7542..19ae16fe54d0282b6bf3ae249dea6cbbce60db8e 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;
@@ -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);
     }