-/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <stdlib.h>
#include "bitmap.h"
+#include "coverage.h"
#include "dynamic-string.h"
#include "fatal-signal.h"
#include "json.h"
VLOG_DEFINE_THIS_MODULE(ovsdb_idl);
+COVERAGE_DEFINE(txn_uncommitted);
+COVERAGE_DEFINE(txn_unchanged);
+COVERAGE_DEFINE(txn_incomplete);
+COVERAGE_DEFINE(txn_aborted);
+COVERAGE_DEFINE(txn_success);
+COVERAGE_DEFINE(txn_try_again);
+COVERAGE_DEFINE(txn_not_locked);
+COVERAGE_DEFINE(txn_error);
+
/* 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
* (the destination).
char *error;
bool dry_run;
struct ds comment;
- unsigned int commit_seqno;
/* Increments. */
const char *inc_table;
* 'class'. (Ordinarily 'class' is compiled from an OVSDB schema automatically
* by ovsdb-idlc.)
*
+ * Passes 'retry' to jsonrpc_session_open(). See that function for
+ * documentation.
+ *
* If 'monitor_everything_by_default' is true, then everything in the remote
* database will be replicated by default. ovsdb_idl_omit() and
* ovsdb_idl_omit_alert() may be used to selectively drop some columns from
*/
struct ovsdb_idl *
ovsdb_idl_create(const char *remote, const struct ovsdb_idl_class *class,
- bool monitor_everything_by_default)
+ bool monitor_everything_by_default, bool retry)
{
struct ovsdb_idl *idl;
uint8_t default_mode;
idl = xzalloc(sizeof *idl);
idl->class = class;
- idl->session = jsonrpc_session_open(remote);
+ idl->session = jsonrpc_session_open(remote, retry);
shash_init(&idl->table_by_name);
idl->tables = xmalloc(class->n_tables * sizeof *idl->tables);
for (i = 0; i < class->n_tables; i++) {
&& !strcmp(msg->method, "stolen")) {
/* Someone else stole our lock. */
ovsdb_idl_parse_lock_notify(idl, msg->params, false);
- } else if (msg->type == JSONRPC_REPLY && msg->id->type == JSON_STRING
- && !strcmp(msg->id->u.string, "echo")) {
- /* Reply to our echo request. Ignore it. */
} else if ((msg->type == JSONRPC_ERROR
|| msg->type == JSONRPC_REPLY)
&& ovsdb_idl_txn_process_reply(idl, msg)) {
return ovsdb_idl_get_seqno(idl) != 0;
}
+/* Reconfigures 'idl' so that it would reconnect to the database, if
+ * connection was dropped. */
+void
+ovsdb_idl_enable_reconnect(struct ovsdb_idl *idl)
+{
+ jsonrpc_session_enable_reconnect(idl->session);
+}
+
/* Forces 'idl' to drop its connection to the database and reconnect. In the
* meantime, the contents of 'idl' will not change. */
void
{
idl->verify_write_only = true;
}
+
+bool
+ovsdb_idl_is_alive(const struct ovsdb_idl *idl)
+{
+ return jsonrpc_session_is_alive(idl->session);
+}
+
+int
+ovsdb_idl_get_last_error(const struct ovsdb_idl *idl)
+{
+ return jsonrpc_session_get_last_error(idl->session);
+}
\f
static unsigned char *
ovsdb_idl_get_mode(struct ovsdb_idl *idl,
}
}
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
static void
}
}
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
/* Turns off OVSDB_IDL_ALERT for 'column' in 'idl'.
return ovsdb_idl_read(row, column);
}
+/* Returns true if the field represented by 'column' in 'row' may be modified,
+ * false if it is immutable.
+ *
+ * Normally, whether a field is mutable is controlled by its column's schema.
+ * However, an immutable column can be set to any initial value at the time of
+ * insertion, so if 'row' is a new row (one that is being added as part of the
+ * current transaction, supposing that a transaction is in progress) then even
+ * its "immutable" fields are actually mutable. */
+bool
+ovsdb_idl_is_mutable(const struct ovsdb_idl_row *row,
+ const struct ovsdb_idl_column *column)
+{
+ return column->mutable || (row->new && !row->old);
+}
+
/* Returns false if 'row' was obtained from the IDL, true if it was initialized
* to all-zero-bits by some other entity. If 'row' was set up some other way
* then the return value is indeterminate. */
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;
bool any_updates;
if (txn != txn->idl->txn) {
- return txn->status;
+ goto coverage_out;
}
/* If we need a lock but don't have it, give up quickly. */
if (txn->idl->lock_name && !ovsdb_idl_has_lock(txn->idl)) {
txn->status = TXN_NOT_LOCKED;
- ovsdb_idl_txn_disassemble(txn);
- return txn->status;
+ goto disassemble_out;
}
operations = json_array_create_1(
txn->status = TXN_TRY_AGAIN;
}
+disassemble_out:
ovsdb_idl_txn_disassemble(txn);
+coverage_out:
+ switch (txn->status) {
+ case TXN_UNCOMMITTED: COVERAGE_INC(txn_uncommitted); break;
+ case TXN_UNCHANGED: COVERAGE_INC(txn_unchanged); break;
+ case TXN_INCOMPLETE: COVERAGE_INC(txn_incomplete); break;
+ case TXN_ABORTED: COVERAGE_INC(txn_aborted); break;
+ case TXN_SUCCESS: COVERAGE_INC(txn_success); break;
+ case TXN_TRY_AGAIN: COVERAGE_INC(txn_try_again); break;
+ case TXN_NOT_LOCKED: COVERAGE_INC(txn_not_locked); break;
+ case TXN_ERROR: COVERAGE_INC(txn_error); break;
+ }
+
return txn->status;
}
if (txn->inc_index + 2 > results->n) {
VLOG_WARN_RL(&syntax_rl, "reply does not contain enough operations "
- "for increment (has %zu, needs %u)",
+ "for increment (has %"PRIuSIZE", needs %u)",
results->n, txn->inc_index + 2);
return false;
}
return false;
}
if (rows->u.array.n != 1) {
- VLOG_WARN_RL(&syntax_rl, "\"select\" reply \"rows\" has %zu elements "
+ VLOG_WARN_RL(&syntax_rl, "\"select\" reply \"rows\" has %"PRIuSIZE" elements "
"instead of 1",
rows->u.array.n);
return false;
if (insert->op_index >= results->n) {
VLOG_WARN_RL(&syntax_rl, "reply does not contain enough operations "
- "for insert (has %zu, needs %u)",
+ "for insert (has %"PRIuSIZE", needs %u)",
results->n, insert->op_index);
return false;
}