#include "ovsdb-idl.h"
-#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
struct json *monitor_request_id;
unsigned int last_monitor_request_seqno;
unsigned int change_seqno;
+ bool verify_write_only;
/* Database locking. */
char *lock_name; /* Name of lock we need, NULL if none. */
if (idl) {
size_t i;
- assert(!idl->txn);
+ ovs_assert(!idl->txn);
ovsdb_idl_clear(idl);
jsonrpc_session_close(idl->session);
json_destroy(idl->monitor_request_id);
free(idl->lock_name);
json_destroy(idl->lock_request_id);
+ hmap_destroy(&idl->outstanding_txns);
free(idl);
}
}
{
int i;
- assert(!idl->txn);
+ ovs_assert(!idl->txn);
jsonrpc_session_run(idl->session);
for (i = 0; jsonrpc_session_is_connected(idl->session) && i < 50; i++) {
struct jsonrpc_msg *msg;
{
jsonrpc_session_force_reconnect(idl->session);
}
+
+/* Some IDL users should only write to write-only columns. Furthermore,
+ * writing to a column which is not write-only can cause serious performance
+ * degradations for these users. This function causes 'idl' to reject writes
+ * to columns which are not marked write only using ovsdb_idl_omit_alert(). */
+void
+ovsdb_idl_verify_write_only(struct ovsdb_idl *idl)
+{
+ idl->verify_write_only = true;
+}
\f
static unsigned char *
ovsdb_idl_get_mode(struct ovsdb_idl *idl,
{
size_t i;
- assert(!idl->change_seqno);
+ ovs_assert(!idl->change_seqno);
for (i = 0; i < idl->class->n_tables; i++) {
const struct ovsdb_idl_table *table = &idl->tables[i];
static void
ovsdb_idl_row_clear_old(struct ovsdb_idl_row *row)
{
- assert(row->old == row->new);
+ ovs_assert(row->old == row->new);
if (!ovsdb_idl_row_is_orphan(row)) {
const struct ovsdb_idl_table_class *class = row->table->class;
size_t i;
const struct ovsdb_idl_table_class *class = row->table->class;
size_t i;
- assert(!row->old && !row->new);
+ ovs_assert(!row->old && !row->new);
row->old = row->new = xmalloc(class->n_columns * sizeof *row->old);
for (i = 0; i < class->n_columns; i++) {
ovsdb_datum_init_default(&row->old[i], &class->columns[i].type);
const struct ovsdb_idl_table_class *class;
size_t column_idx;
- assert(!ovsdb_idl_row_is_synthetic(row));
+ ovs_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);
+ ovs_assert(row->new != NULL);
+ ovs_assert(column_idx < class->n_columns);
if (row->written && bitmap_is_set(row->written, column_idx)) {
return &row->new[column_idx];
enum ovsdb_atomic_type key_type OVS_UNUSED,
enum ovsdb_atomic_type value_type OVS_UNUSED)
{
- assert(column->type.key.type == key_type);
- assert(column->type.value.type == value_type);
+ ovs_assert(column->type.key.type == key_type);
+ ovs_assert(column->type.value.type == value_type);
return ovsdb_idl_read(row, column);
}
{
struct ovsdb_idl_txn *txn;
- assert(!idl->txn);
+ ovs_assert(!idl->txn);
idl->txn = txn = xmalloc(sizeof *txn);
txn->request_id = NULL;
txn->idl = idl;
const struct ovsdb_idl_row *row,
const struct ovsdb_idl_column *column)
{
- assert(!txn->inc_table);
- assert(column->type.key.type == OVSDB_TYPE_INTEGER);
- assert(column->type.value.type == OVSDB_TYPE_VOID);
+ ovs_assert(!txn->inc_table);
+ ovs_assert(column->type.key.type == OVSDB_TYPE_INTEGER);
+ ovs_assert(column->type.value.type == OVSDB_TYPE_VOID);
txn->inc_table = row->table->class->name;
txn->inc_column = column->name;
int64_t
ovsdb_idl_txn_get_increment_new_value(const struct ovsdb_idl_txn *txn)
{
- assert(txn->status == TXN_SUCCESS);
+ ovs_assert(txn->status == TXN_SUCCESS);
return txn->inc_new_value;
}
{
const struct ovsdb_idl_txn_insert *insert;
- assert(txn->status == TXN_SUCCESS || txn->status == TXN_UNCHANGED);
+ ovs_assert(txn->status == TXN_SUCCESS || txn->status == TXN_UNCHANGED);
HMAP_FOR_EACH_IN_BUCKET (insert, hmap_node,
uuid_hash(uuid), &txn->inserted_rows) {
if (uuid_equals(uuid, &insert->dummy)) {
const struct ovsdb_idl_column *column,
struct ovsdb_datum *datum)
{
- struct ovsdb_idl_row *row = (struct ovsdb_idl_row *) row_;
+ struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
const struct ovsdb_idl_table_class *class;
size_t column_idx;
+ bool write_only;
if (ovsdb_idl_row_is_synthetic(row)) {
ovsdb_datum_destroy(datum, &column->type);
class = row->table->class;
column_idx = column - class->columns;
+ write_only = row->table->modes[column_idx] == OVSDB_IDL_MONITOR;
- assert(row->new != NULL);
- assert(column_idx < class->n_columns);
- assert(row->old == NULL ||
- row->table->modes[column_idx] & OVSDB_IDL_MONITOR);
+ ovs_assert(row->new != NULL);
+ ovs_assert(column_idx < class->n_columns);
+ ovs_assert(row->old == NULL ||
+ row->table->modes[column_idx] & OVSDB_IDL_MONITOR);
+
+ if (row->table->idl->verify_write_only && !write_only) {
+ VLOG_ERR("Bug: Attempt to write to a read/write column (%s:%s) when"
+ " explicitly configured not to.", class->name, column->name);
+ ovsdb_datum_destroy(datum, &column->type);
+ return;
+ }
/* If this is a write-only column and the datum being written is the same
* as the one already there, just skip the update entirely. This is worth
* transaction only does writes of existing values, without making any real
* changes, we will drop the whole transaction later in
* ovsdb_idl_txn_commit().) */
- if (row->table->modes[column_idx] == OVSDB_IDL_MONITOR
- && ovsdb_datum_equals(ovsdb_idl_read(row, column),
- datum, &column->type)) {
+ if (write_only && ovsdb_datum_equals(ovsdb_idl_read(row, column),
+ datum, &column->type)) {
ovsdb_datum_destroy(datum, &column->type);
return;
}
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_;
+ struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
const struct ovsdb_idl_table_class *class;
size_t column_idx;
class = row->table->class;
column_idx = column - class->columns;
- assert(row->new != NULL);
- assert(row->old == NULL ||
- row->table->modes[column_idx] & OVSDB_IDL_MONITOR);
+ ovs_assert(row->new != NULL);
+ ovs_assert(row->old == NULL ||
+ row->table->modes[column_idx] & OVSDB_IDL_MONITOR);
if (!row->old
|| (row->written && bitmap_is_set(row->written, column_idx))) {
return;
void
ovsdb_idl_txn_delete(const struct ovsdb_idl_row *row_)
{
- struct ovsdb_idl_row *row = (struct ovsdb_idl_row *) row_;
+ struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
if (ovsdb_idl_row_is_synthetic(row)) {
return;
}
- assert(row->new != NULL);
+ ovs_assert(row->new != NULL);
if (!row->old) {
ovsdb_idl_row_unparse(row);
ovsdb_idl_row_clear_new(row);
- assert(!row->prereqs);
+ ovs_assert(!row->prereqs);
hmap_remove(&row->table->rows, &row->hmap_node);
hmap_remove(&row->table->idl->txn->txn_rows, &row->txn_node);
free(row);
struct ovsdb_idl_row *row = ovsdb_idl_row_create__(class);
if (uuid) {
- assert(!ovsdb_idl_txn_get_row(txn, uuid));
+ ovs_assert(!ovsdb_idl_txn_get_row(txn, uuid));
row->uuid = *uuid;
} else {
uuid_generate(&row->uuid);
ovsdb_idl_txn_get(const struct ovsdb_idl_row *row)
{
struct ovsdb_idl_txn *txn = row->table->idl->txn;
- assert(txn != NULL);
+ ovs_assert(txn != NULL);
return txn;
}
void
ovsdb_idl_set_lock(struct ovsdb_idl *idl, const char *lock_name)
{
- assert(!idl->txn);
- assert(hmap_is_empty(&idl->outstanding_txns));
+ ovs_assert(!idl->txn);
+ ovs_assert(hmap_is_empty(&idl->outstanding_txns));
if (idl->lock_name && (!lock_name || strcmp(lock_name, idl->lock_name))) {
/* Release previous lock. */