classifier: Rewrite.
[openvswitch] / lib / ovsdb-idl.c
index 2132f9fefb8635142ff3908d2193d7396c026ddb..46cc51ee70e3ffb06e177996fe87253ff1d7bbbf 100644 (file)
@@ -36,7 +36,7 @@
 #include "util.h"
 #include "vlog.h"
 
-VLOG_DEFINE_THIS_MODULE(ovsdb_idl)
+VLOG_DEFINE_THIS_MODULE(ovsdb_idl);
 
 /* An arc from one idl_row to another.  When row A contains a UUID that
  * references row B, this is represented by an arc from A (the source) to B
@@ -215,15 +215,13 @@ ovsdb_idl_clear(struct ovsdb_idl *idl)
         }
 
         changed = true;
-        HMAP_FOR_EACH_SAFE (row, next_row, struct ovsdb_idl_row, hmap_node,
-                            &table->rows) {
+        HMAP_FOR_EACH_SAFE (row, next_row, hmap_node, &table->rows) {
             struct ovsdb_idl_arc *arc, *next_arc;
 
             if (!ovsdb_idl_row_is_orphan(row)) {
                 ovsdb_idl_row_unparse(row);
             }
-            LIST_FOR_EACH_SAFE (arc, next_arc, struct ovsdb_idl_arc, src_node,
-                                &row->src_arcs) {
+            LIST_FOR_EACH_SAFE (arc, next_arc, src_node, &row->src_arcs) {
                 free(arc);
             }
             /* No need to do anything with dst_arcs: some node has those arcs
@@ -433,13 +431,13 @@ ovsdb_idl_send_monitor_request(struct ovsdb_idl *idl)
         const struct ovsdb_idl_table *table = &idl->tables[i];
         const struct ovsdb_idl_table_class *tc = table->class;
         struct json *monitor_request, *columns;
-        size_t i;
+        size_t j;
 
         monitor_request = json_object_create();
         columns = json_array_create_empty();
-        for (i = 0; i < tc->n_columns; i++) {
-            const struct ovsdb_idl_column *column = &tc->columns[i];
-            if (table->modes[i] != OVSDB_IDL_MODE_NONE) {
+        for (j = 0; j < tc->n_columns; j++) {
+            const struct ovsdb_idl_column *column = &tc->columns[j];
+            if (table->modes[j] != OVSDB_IDL_MODE_NONE) {
                 json_array_add(columns, json_string_create(column->name));
             }
         }
@@ -553,8 +551,7 @@ ovsdb_idl_get_row(struct ovsdb_idl_table *table, const struct uuid *uuid)
 {
     struct ovsdb_idl_row *row;
 
-    HMAP_FOR_EACH_WITH_HASH (row, struct ovsdb_idl_row, hmap_node,
-                             uuid_hash(uuid), &table->rows) {
+    HMAP_FOR_EACH_WITH_HASH (row, hmap_node, uuid_hash(uuid), &table->rows) {
         if (uuid_equals(&row->uuid, uuid)) {
             return row;
         }
@@ -771,8 +768,7 @@ ovsdb_idl_row_clear_arcs(struct ovsdb_idl_row *row, bool destroy_dsts)
 
     /* Delete all forward arcs.  If 'destroy_dsts', destroy any orphaned rows
      * that this causes to be unreferenced. */
-    LIST_FOR_EACH_SAFE (arc, next, struct ovsdb_idl_arc, src_node,
-                        &row->src_arcs) {
+    LIST_FOR_EACH_SAFE (arc, next, src_node, &row->src_arcs) {
         list_remove(&arc->dst_node);
         if (destroy_dsts
             && ovsdb_idl_row_is_orphan(arc->dst)
@@ -800,8 +796,7 @@ ovsdb_idl_row_reparse_backrefs(struct ovsdb_idl_row *row)
      * (If duplicate arcs were possible then we would need to make sure that
      * 'next' didn't also point into 'arc''s destination, but we forbid
      * duplicate arcs.) */
-    LIST_FOR_EACH_SAFE (arc, next, struct ovsdb_idl_arc, dst_node,
-                        &row->dst_arcs) {
+    LIST_FOR_EACH_SAFE (arc, next, dst_node, &row->dst_arcs) {
         struct ovsdb_idl_row *ref = arc->src;
 
         ovsdb_idl_row_unparse(ref);
@@ -1145,8 +1140,7 @@ ovsdb_idl_txn_destroy(struct ovsdb_idl_txn *txn)
     free(txn->inc_table);
     free(txn->inc_column);
     json_destroy(txn->inc_where);
-    HMAP_FOR_EACH_SAFE (insert, next, struct ovsdb_idl_txn_insert, hmap_node,
-                        &txn->inserted_rows) {
+    HMAP_FOR_EACH_SAFE (insert, next, hmap_node, &txn->inserted_rows) {
         free(insert);
     }
     hmap_destroy(&txn->inserted_rows);
@@ -1196,8 +1190,7 @@ ovsdb_idl_txn_get_row(const struct ovsdb_idl_txn *txn, const struct uuid *uuid)
 {
     const struct ovsdb_idl_row *row;
 
-    HMAP_FOR_EACH_WITH_HASH (row, struct ovsdb_idl_row, txn_node,
-                             uuid_hash(uuid), &txn->txn_rows) {
+    HMAP_FOR_EACH_WITH_HASH (row, txn_node, uuid_hash(uuid), &txn->txn_rows) {
         if (uuid_equals(&row->uuid, uuid)) {
             return row;
         }
@@ -1255,8 +1248,7 @@ ovsdb_idl_txn_disassemble(struct ovsdb_idl_txn *txn)
      * transaction and fail to update the graph.  */
     txn->idl->txn = NULL;
 
-    HMAP_FOR_EACH_SAFE (row, next, struct ovsdb_idl_row, txn_node,
-                        &txn->txn_rows) {
+    HMAP_FOR_EACH_SAFE (row, next, txn_node, &txn->txn_rows) {
         if (row->old) {
             if (row->written) {
                 ovsdb_idl_row_unparse(row);
@@ -1300,7 +1292,7 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn)
         json_string_create(txn->idl->class->database));
 
     /* Add prerequisites and declarations of new rows. */
-    HMAP_FOR_EACH (row, struct ovsdb_idl_row, txn_node, &txn->txn_rows) {
+    HMAP_FOR_EACH (row, txn_node, &txn->txn_rows) {
         /* XXX check that deleted rows exist even if no prereqs? */
         if (row->prereqs) {
             const struct ovsdb_idl_table_class *class = row->table->class;
@@ -1332,7 +1324,7 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn)
 
     /* Add updates. */
     any_updates = false;
-    HMAP_FOR_EACH (row, struct ovsdb_idl_row, txn_node, &txn->txn_rows) {
+    HMAP_FOR_EACH (row, txn_node, &txn->txn_rows) {
         const struct ovsdb_idl_table_class *class = row->table->class;
 
         if (row->old == row->new) {
@@ -1530,7 +1522,7 @@ ovsdb_idl_txn_get_insert_uuid(const struct ovsdb_idl_txn *txn,
     const struct ovsdb_idl_txn_insert *insert;
 
     assert(txn->status == TXN_SUCCESS || txn->status == TXN_UNCHANGED);
-    HMAP_FOR_EACH_IN_BUCKET (insert, struct ovsdb_idl_txn_insert, hmap_node,
+    HMAP_FOR_EACH_IN_BUCKET (insert, hmap_node,
                              uuid_hash(uuid), &txn->inserted_rows) {
         if (uuid_equals(uuid, &insert->dummy)) {
             return &insert->real;
@@ -1547,6 +1539,19 @@ ovsdb_idl_txn_complete(struct ovsdb_idl_txn *txn,
     hmap_remove(&txn->idl->outstanding_txns, &txn->hmap_node);
 }
 
+/* Writes 'datum' to the specified 'column' in 'row_'.  Updates both 'row_'
+ * itself and the structs derived from it (e.g. the "struct ovsrec_*", for
+ * ovs-vswitchd).
+ *
+ * 'datum' must have the correct type for its column.  The IDL does not check
+ * that it meets schema constraints, but ovsdb-server will do so at commit time
+ * so it had better be correct.
+ *
+ * A transaction must be in progress.  Replication of 'column' must not have
+ * been disabled (by calling ovsdb_idl_omit()).
+ *
+ * Usually this function is used indirectly through one of the "set" functions
+ * generated by ovsdb-idlc. */
 void
 ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
                     const struct ovsdb_idl_column *column,
@@ -1580,6 +1585,32 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
     (column->parse)(row, &row->new[column_idx]);
 }
 
+/* Causes the original contents of 'column' in 'row_' to be verified as a
+ * 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.
+ *
+ * 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
+ * read as part of a read-modify-write operation.
+ *
+ * In some cases ovsdb_idl_txn_verify() reduces to a no-op, because the current
+ * value of 'column' is already known:
+ *
+ *   - If 'row_' is a row created by the current transaction (returned by
+ *     ovsdb_idl_txn_insert()).
+ *
+ *   - If 'column' has already been modified (with ovsdb_idl_txn_write())
+ *     within the current transaction.
+ *
+ * Because of the latter property, always call ovsdb_idl_txn_verify() *before*
+ * ovsdb_idl_txn_write() for a given read-modify-write.
+ *
+ * A transaction must be in progress.
+ *
+ * Usually this function is used indirectly through one of the "verify"
+ * functions generated by ovsdb-idlc. */
 void
 ovsdb_idl_txn_verify(const struct ovsdb_idl_row *row_,
                      const struct ovsdb_idl_column *column)
@@ -1604,6 +1635,13 @@ ovsdb_idl_txn_verify(const struct ovsdb_idl_row *row_,
     bitmap_set1(row->prereqs, column_idx);
 }
 
+/* Deletes 'row_' from its table.  May free 'row_', so it must not be
+ * accessed afterward.
+ *
+ * A transaction must be in progress.
+ *
+ * Usually this function is used indirectly through one of the "delete"
+ * functions generated by ovsdb-idlc. */
 void
 ovsdb_idl_txn_delete(const struct ovsdb_idl_row *row_)
 {
@@ -1627,6 +1665,18 @@ ovsdb_idl_txn_delete(const struct ovsdb_idl_row *row_)
     row->new = NULL;
 }
 
+/* Inserts and returns a new row in the table with the specified 'class' in the
+ * database with open transaction 'txn'.
+ *
+ * The new row is assigned a provisional UUID.  If 'uuid' is null then one is
+ * randomly generated; otherwise 'uuid' should specify a randomly generated
+ * UUID not otherwise in use.  ovsdb-server will assign a different UUID when
+ * 'txn' is committed, but the IDL will replace any uses of the provisional
+ * UUID in the data to be to be committed by the UUID assigned by
+ * ovsdb-server.
+ *
+ * Usually this function is used indirectly through one of the "insert"
+ * functions generated by ovsdb-idlc. */
 const struct ovsdb_idl_row *
 ovsdb_idl_txn_insert(struct ovsdb_idl_txn *txn,
                      const struct ovsdb_idl_table_class *class,
@@ -1653,8 +1703,7 @@ ovsdb_idl_txn_abort_all(struct ovsdb_idl *idl)
 {
     struct ovsdb_idl_txn *txn;
 
-    HMAP_FOR_EACH (txn, struct ovsdb_idl_txn, hmap_node,
-                   &idl->outstanding_txns) {
+    HMAP_FOR_EACH (txn, hmap_node, &idl->outstanding_txns) {
         ovsdb_idl_txn_complete(txn, TXN_TRY_AGAIN);
     }
 }
@@ -1664,7 +1713,7 @@ ovsdb_idl_txn_find(struct ovsdb_idl *idl, const struct json *id)
 {
     struct ovsdb_idl_txn *txn;
 
-    HMAP_FOR_EACH_WITH_HASH (txn, struct ovsdb_idl_txn, hmap_node,
+    HMAP_FOR_EACH_WITH_HASH (txn, hmap_node,
                              json_hash(id, 0), &idl->outstanding_txns) {
         if (json_equal(id, txn->request_id)) {
             return txn;
@@ -1844,8 +1893,7 @@ ovsdb_idl_txn_process_reply(struct ovsdb_idl *idl,
                 hard_errors++;
             }
 
-            HMAP_FOR_EACH (insert, struct ovsdb_idl_txn_insert, hmap_node,
-                           &txn->inserted_rows) {
+            HMAP_FOR_EACH (insert, hmap_node, &txn->inserted_rows) {
                 if (!ovsdb_idl_txn_process_insert_reply(insert, ops)) {
                     hard_errors++;
                 }