#include <stdlib.h>
#include "bitmap.h"
+#include "dynamic-string.h"
#include "json.h"
#include "jsonrpc.h"
#include "ovsdb-data.h"
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);
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)
{
hmap_remove(&txn->idl->outstanding_txns, &txn->hmap_node);
}
ovsdb_idl_txn_abort(txn);
+ ds_destroy(&txn->comment);
free(txn);
}
}
}
+ 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);
+ }
+
if (txn->dry_run) {
struct json *op = json_object_create();
json_object_put_string(op, "op", "abort");
const char *ovsdb_idl_txn_status_to_string(enum ovsdb_idl_txn_status);
struct ovsdb_idl_txn *ovsdb_idl_txn_create(struct ovsdb_idl *);
+void ovsdb_idl_txn_add_comment(struct ovsdb_idl_txn *, const char *);
void ovsdb_idl_txn_set_dry_run(struct ovsdb_idl_txn *);
void ovsdb_idl_txn_destroy(struct ovsdb_idl_txn *);
void ovsdb_idl_txn_wait(const struct ovsdb_idl_txn *);
The same "uuid-name" appeared on an earlier "insert" or
"declare" operation within this transaction.
+
+comment
+.......
+
+
+Request object members:
+
+ "op": "comment" required
+ "comment": <string> required
+
+Result object members:
+
+ none
+
+Semantics:
+
+ Provides information to a database administrator on the purpose of
+ a transaction. The OVSDB server, for example, adds comments in
+ transactions that modify the database to the database journal.
static ovsdb_operation_executor ovsdb_execute_commit;
static ovsdb_operation_executor ovsdb_execute_abort;
static ovsdb_operation_executor ovsdb_execute_declare;
+static ovsdb_operation_executor ovsdb_execute_comment;
static ovsdb_operation_executor *
lookup_executor(const char *name)
{ "commit", ovsdb_execute_commit },
{ "abort", ovsdb_execute_abort },
{ "declare", ovsdb_execute_declare },
+ { "comment", ovsdb_execute_comment },
};
size_t i;
xasprintf(UUID_FMT, UUID_ARGS(&uuid))));
return NULL;
}
+
+static struct ovsdb_error *
+ovsdb_execute_comment(struct ovsdb_execution *x, struct ovsdb_parser *parser,
+ struct json *result UNUSED)
+{
+ const struct json *comment;
+
+ comment = ovsdb_parser_member(parser, "comment", OP_STRING);
+ if (!comment) {
+ return NULL;
+ }
+ ovsdb_txn_add_comment(x->txn, json_string(comment));
+
+ return NULL;
+}
#include "ovsdb-error.h"
#include "row.h"
#include "table.h"
+#include "timeval.h"
#include "transaction.h"
#include "uuid.h"
#include "util.h"
table = shash_find_data(&db->tables, table_name);
if (!table) {
+ if (!strcmp(table_name, "_date")
+ || !strcmp(table_name, "_comment")) {
+ continue;
+ }
+
error = ovsdb_syntax_error(json, "unknown table",
"No table named %s.", table_name);
goto error;
struct ovsdb_file_replica *r = ovsdb_file_replica_cast(r_);
struct ovsdb_file_replica_aux aux;
struct ovsdb_error *error;
+ const char *comment;
aux.json = NULL;
aux.table_json = NULL;
return NULL;
}
+ comment = ovsdb_txn_get_comment(txn);
+ if (comment) {
+ json_object_put_string(aux.json, "_comment", comment);
+ }
+
+ json_object_put(aux.json, "_date", json_integer_create(time_now()));
+
error = ovsdb_log_write(r->log, aux.json);
json_destroy(aux.json);
if (error) {
#include <assert.h>
+#include "dynamic-string.h"
#include "hash.h"
#include "hmap.h"
#include "json.h"
struct ovsdb_txn {
struct ovsdb *db;
struct hmap txn_tables; /* Contains "struct ovsdb_txn_table"s. */
+ struct ds comment;
};
/* A table modified by a transaction. */
struct ovsdb_txn *txn = xmalloc(sizeof *txn);
txn->db = db;
hmap_init(&txn->txn_tables);
+ ds_init(&txn->comment);
return txn;
}
free(txn_table);
}
hmap_destroy(&txn->txn_tables);
+ ds_destroy(&txn->comment);
free(txn);
}
ovsdb_row_destroy(row);
}
}
+
+void
+ovsdb_txn_add_comment(struct ovsdb_txn *txn, const char *s)
+{
+ if (txn->comment.length) {
+ ds_put_char(&txn->comment, '\n');
+ }
+ ds_put_cstr(&txn->comment, s);
+}
+
+const char *
+ovsdb_txn_get_comment(const struct ovsdb_txn *txn)
+{
+ return txn->comment.length ? ds_cstr_ro(&txn->comment) : NULL;
+}
void ovsdb_txn_for_each_change(const struct ovsdb_txn *,
ovsdb_txn_row_cb_func *, void *aux);
+void ovsdb_txn_add_comment(struct ovsdb_txn *, const char *);
+const char *ovsdb_txn_get_comment(const struct ovsdb_txn *);
+
#endif /* ovsdb/transaction.h */
AT_CLEANUP])
EXECUTION_EXAMPLES
+
+AT_SETUP([transaction comments])
+AT_KEYWORDS([ovsdb file positive])
+AT_DATA([schema], [ORDINAL_SCHEMA
+])
+touch .db.~lock~
+OVS_CHECK_LCOV([ovsdb-tool create db schema], [0], [], [ignore])
+OVS_CHECK_LCOV([[ovsdb-tool transact db '
+ [{"op": "insert",
+ "table": "ordinals",
+ "row": {"name": "five", "number": 5}},
+ {"op": "comment",
+ "comment": "add row for 5"}]']], [0], [stdout], [ignore])
+AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0],
+ [[[{"uuid":["uuid","<0>"]},{}]
+]])
+AT_CHECK([grep -q "add row for 5" db])
+AT_CLEANUP
struct ovsdb_idl_txn *txn;
const struct ovsrec_open_vswitch *ovs;
enum ovsdb_idl_txn_status status;
- struct ds *output;
+ struct ds comment, *output;
int n_output;
int i, start;
ovsdb_idl_txn_set_dry_run(txn);
}
+ ds_init(&comment);
+ ds_put_cstr(&comment, "ovs-vsctl:");
+ for (i = 0; i < argc; i++) {
+ ds_put_format(&comment, " %s", argv[i]);
+ }
+ ovsdb_idl_txn_add_comment(txn, ds_cstr(&comment));
+ ds_destroy(&comment);
+
ovs = ovsrec_open_vswitch_first(idl);
if (!ovs) {
/* XXX add verification that table is empty */