X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fovsdb-idl.c;h=f72e18762f0857f6e89ed74dd4869c87c1252918;hb=6c1b89ed0e6b9934d63ae4d71ba885bfcb87891a;hp=22e20db02ccc0151ef14456215d6659979b01f8c;hpb=8bc915de7a08d5b4210ba768d56f15211927d1e7;p=openvswitch diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c index 22e20db0..f72e1876 100644 --- a/lib/ovsdb-idl.c +++ b/lib/ovsdb-idl.c @@ -23,11 +23,13 @@ #include #include "bitmap.h" +#include "dynamic-string.h" #include "json.h" #include "jsonrpc.h" #include "ovsdb-data.h" #include "ovsdb-error.h" #include "ovsdb-idl-provider.h" +#include "poll-loop.h" #include "shash.h" #include "util.h" @@ -78,6 +80,8 @@ struct ovsdb_idl_txn { struct ovsdb_idl *idl; struct hmap txn_rows; enum ovsdb_idl_txn_status status; + bool dry_run; + struct ds comment; }; static struct vlog_rate_limit syntax_rl = VLOG_RATE_LIMIT_INIT(1, 5); @@ -599,7 +603,7 @@ ovsdb_idl_row_reparse_backrefs(struct ovsdb_idl_row *row, bool destroy_dsts) static struct ovsdb_idl_row * ovsdb_idl_row_create__(const struct ovsdb_idl_table_class *class) { - struct ovsdb_idl_row *row = xmalloc(class->allocation_size); + struct ovsdb_idl_row *row = xzalloc(class->allocation_size); memset(row, 0, sizeof *row); list_init(&row->src_arcs); list_init(&row->dst_arcs); @@ -790,16 +794,45 @@ ovsdb_idl_txn_create(struct ovsdb_idl *idl) txn->idl = idl; txn->status = TXN_INCOMPLETE; hmap_init(&txn->txn_rows); + txn->dry_run = false; + ds_init(&txn->comment); return txn; } +void +ovsdb_idl_txn_add_comment(struct ovsdb_idl_txn *txn, const char *s) +{ + if (txn->comment.length) { + ds_put_char(&txn->comment, '\n'); + } + ds_put_cstr(&txn->comment, s); +} + +void +ovsdb_idl_txn_set_dry_run(struct ovsdb_idl_txn *txn) +{ + txn->dry_run = true; +} + void ovsdb_idl_txn_destroy(struct ovsdb_idl_txn *txn) { + if (txn->status == TXN_INCOMPLETE) { + hmap_remove(&txn->idl->outstanding_txns, &txn->hmap_node); + } ovsdb_idl_txn_abort(txn); + ds_destroy(&txn->comment); free(txn); } +void +ovsdb_idl_txn_wait(const struct ovsdb_idl_txn *txn) +{ + if (txn->status != TXN_INCOMPLETE) { + poll_immediate_wake(); + } +} + static struct json * where_uuid_equals(const struct uuid *uuid) { @@ -916,7 +949,6 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn) struct ovsdb_idl_row *row; struct json *operations; bool any_updates; - enum ovsdb_idl_txn_status status; if (txn != txn->idl->txn) { return txn->status; @@ -969,9 +1001,6 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn) any_updates = false; HMAP_FOR_EACH (row, struct ovsdb_idl_row, txn_node, &txn->txn_rows) { const struct ovsdb_idl_table_class *class = row->table->class; - size_t n_columns = class->n_columns; - struct json *row_json; - size_t idx; if (row->old == row->new) { continue; @@ -981,59 +1010,75 @@ ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn) json_object_put_string(op, "table", class->name); json_object_put(op, "where", where_uuid_equals(&row->uuid)); json_array_add(operations, op); + any_updates = true; } else { - row_json = NULL; - BITMAP_FOR_EACH_1 (idx, n_columns, row->written) { + struct json *row_json; + struct json *op; + size_t idx; + + op = json_object_create(); + json_object_put_string(op, "op", row->old ? "update" : "insert"); + json_object_put_string(op, "table", class->name); + if (row->old) { + json_object_put(op, "where", where_uuid_equals(&row->uuid)); + } else { + json_object_put(op, "uuid-name", + json_string_create_nocopy( + uuid_name_from_uuid(&row->uuid))); + } + row_json = json_object_create(); + json_object_put(op, "row", row_json); + + BITMAP_FOR_EACH_1 (idx, class->n_columns, row->written) { const struct ovsdb_idl_column *column = &class->columns[idx]; - if (row->old - && ovsdb_datum_equals(&row->old[idx], &row->new[idx], - &column->type)) { - continue; - } - if (!row_json) { - struct json *op = json_object_create(); - json_array_add(operations, op); - json_object_put_string(op, "op", - row->old ? "update" : "insert"); - json_object_put_string(op, "table", class->name); - if (row->old) { - json_object_put(op, "where", - where_uuid_equals(&row->uuid)); - } else { - json_object_put(op, "uuid-name", - json_string_create_nocopy( - uuid_name_from_uuid(&row->uuid))); - } - row_json = json_object_create(); - json_object_put(op, "row", row_json); - any_updates = true; + if (!row->old || !ovsdb_datum_equals(&row->old[idx], + &row->new[idx], + &column->type)) { + json_object_put(row_json, column->name, + substitute_uuids( + ovsdb_datum_to_json(&row->new[idx], + &column->type), + txn)); } - json_object_put(row_json, column->name, - substitute_uuids( - ovsdb_datum_to_json(&row->new[idx], - &column->type), - txn)); + } + + if (!row->old || !shash_is_empty(json_object(row_json))) { + json_array_add(operations, op); + any_updates = true; + } else { + json_destroy(op); } } } - status = (!any_updates ? TXN_SUCCESS - : jsonrpc_session_send( - txn->idl->session, - jsonrpc_create_request( - "transact", operations, &txn->request_id)) - ? TXN_TRY_AGAIN - : TXN_INCOMPLETE); + if (txn->comment.length) { + struct json *op = json_object_create(); + json_object_put_string(op, "op", "comment"); + json_object_put_string(op, "comment", ds_cstr(&txn->comment)); + json_array_add(operations, op); + } - hmap_insert(&txn->idl->outstanding_txns, &txn->hmap_node, - json_hash(txn->request_id, 0)); - txn->idl->txn = NULL; + if (txn->dry_run) { + struct json *op = json_object_create(); + json_object_put_string(op, "op", "abort"); + json_array_add(operations, op); + } - ovsdb_idl_txn_disassemble(txn); - if (status != TXN_INCOMPLETE) { - ovsdb_idl_txn_complete(txn, status); + if (!any_updates) { + txn->status = TXN_SUCCESS; + } else if (!jsonrpc_session_send( + txn->idl->session, + jsonrpc_create_request( + "transact", operations, &txn->request_id))) { + hmap_insert(&txn->idl->outstanding_txns, &txn->hmap_node, + json_hash(txn->request_id, 0)); + } else { + txn->status = TXN_INCOMPLETE; } + + txn->idl->txn = NULL; + ovsdb_idl_txn_disassemble(txn); return txn->status; } @@ -1119,11 +1164,8 @@ ovsdb_idl_txn_delete(struct ovsdb_idl_row *row) hmap_insert(&row->table->idl->txn->txn_rows, &row->txn_node, uuid_hash(&row->uuid)); } - if (row->new == row->old) { - row->new = NULL; - } else { - ovsdb_idl_row_clear_new(row); - } + ovsdb_idl_row_clear_new(row); + row->new = NULL; } struct ovsdb_idl_row * @@ -1201,7 +1243,7 @@ ovsdb_idl_txn_process_reply(struct ovsdb_idl *idl, if (error->type == JSON_STRING) { if (!strcmp(error->u.string, "timed out")) { soft_errors++; - } else { + } else if (strcmp(error->u.string, "aborted")) { hard_errors++; } } else { @@ -1225,3 +1267,11 @@ ovsdb_idl_txn_process_reply(struct ovsdb_idl *idl, ovsdb_idl_txn_complete(txn, status); return true; } + +struct ovsdb_idl_txn * +ovsdb_idl_txn_get(const struct ovsdb_idl_row *row) +{ + struct ovsdb_idl_txn *txn = row->table->idl->txn; + assert(txn != NULL); + return txn; +}