Only a few small comments in line. On Wed, Feb 3, 2016 at 5:53 AM, Liran Schour <lir...@il.ibm.com> wrote:
> Hold session's conditions in ovsdb_monitor_session_condition. Pass it > to ovsdb_monitor for generating "update2" notifications. > Add functions that can generate "update2" notification for a > "monitor_cond" session. > json_cache is enabled only for session's with nulled or empty condition. > "monitor_cond" and "monitor_cond_change" are RFC 7047 extensions > described by ovsdb-server(1) manpage. > > Signed-off-by: Liran Schour <lir...@il.ibm.com> > > --- > v2->v3: > * Document monitor_cond_update receives a single json condition > * Pass session's condition down to row_update function > * Do not classify modify as delete or insert since we send update > due to cond_update with empty changes list > * Allow conditions with non-monitored columns > * Bug fix: allow json cache when session's condition is NULL > * Bug fix: allow json cahce when all table's conditions are empty > --- > ovsdb/condition.c | 21 ++++ > ovsdb/condition.h | 4 + > ovsdb/jsonrpc-server.c | 37 ++++++- > ovsdb/monitor.c | 261 > ++++++++++++++++++++++++++++++++++++++++++++---- > ovsdb/monitor.h | 40 +++++++- > ovsdb/ovsdb-server.1.in | 230 +++++++++++++++++++++++++++++++++++++++--- > 6 files changed, 551 insertions(+), 42 deletions(-) > > diff --git a/ovsdb/condition.c b/ovsdb/condition.c > index 7321640..5edee5b 100644 > --- a/ovsdb/condition.c > +++ b/ovsdb/condition.c > @@ -444,3 +444,24 @@ ovsdb_condition_clone(struct ovsdb_condition *to, > } > to->n_clauses = from->n_clauses; > } > + > +const struct ovsdb_column ** > +ovsdb_condition_get_columns(const struct ovsdb_condition *cond, > + size_t *n_columns) > +{ > + const struct ovsdb_column **columns; > + size_t i; > + > + if (!cond->n_clauses) { > + *n_columns = 0; > + return NULL; > + } > + > + columns = xmalloc(cond->n_clauses * sizeof *columns); > + for (i = 0; i < cond->n_clauses; i++) { > + columns[i] = cond->clauses[i].column; > + } > + *n_columns = i; > + > + return columns; > +} > diff --git a/ovsdb/condition.h b/ovsdb/condition.h > index 318efba..e65b8c3 100644 > --- a/ovsdb/condition.h > +++ b/ovsdb/condition.h > @@ -82,4 +82,8 @@ int ovsdb_condition_cmp(const struct ovsdb_condition *a, > void ovsdb_condition_clone(struct ovsdb_condition *to, > const struct ovsdb_condition *from); > > +const struct ovsdb_column ** > +ovsdb_condition_get_columns(const struct ovsdb_condition *cond, > + size_t *n_columns); > + > #endif /* ovsdb/condition.h */ > diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c > index fcda8dc..fa5d5c4 100644 > --- a/ovsdb/jsonrpc-server.c > +++ b/ovsdb/jsonrpc-server.c > @@ -28,6 +28,7 @@ > #include "ovsdb-error.h" > #include "ovsdb-parser.h" > #include "ovsdb.h" > +#include "condition.h" > #include "poll-loop.h" > #include "reconnect.h" > #include "row.h" > @@ -849,14 +850,16 @@ ovsdb_jsonrpc_session_got_request(struct > ovsdb_jsonrpc_session *s, > reply = execute_transaction(s, db, request); > } > } else if (!strcmp(request->method, "monitor") || > - (monitor2_enable__ && !strcmp(request->method, > "monitor2"))) { > + (monitor2_enable__ && !strcmp(request->method, > "monitor2")) || > + !strcmp(request->method, "monitor_cond")) { > struct ovsdb *db = ovsdb_jsonrpc_lookup_db(s, request, &reply); > if (!reply) { > int l = strlen(request->method) - strlen("monitor"); > enum ovsdb_monitor_version version = l ? OVSDB_MONITOR_V2 > : OVSDB_MONITOR_V1; > reply = ovsdb_jsonrpc_monitor_create(s, db, request->params, > - version, request->id); > + version, > + request->id); > Is this change intentional? > } > } else if (!strcmp(request->method, "monitor_cancel")) { > reply = ovsdb_jsonrpc_monitor_cancel(s, > json_array(request->params), > @@ -1048,6 +1051,7 @@ struct ovsdb_jsonrpc_monitor { > uint64_t unflushed; /* The first transaction that has not been > flushed to the jsonrpc remote > client. */ > enum ovsdb_monitor_version version; > + struct ovsdb_monitor_session_condition *condition;/* Session's > condition */ > }; > > static struct ovsdb_jsonrpc_monitor * > @@ -1077,18 +1081,24 @@ parse_bool(struct ovsdb_parser *parser, const char > *name, bool default_value) > static struct ovsdb_error * OVS_WARN_UNUSED_RESULT > ovsdb_jsonrpc_parse_monitor_request(struct ovsdb_monitor *dbmon, > const struct ovsdb_table *table, > + struct > ovsdb_monitor_session_condition *cond, > const struct json *monitor_request) > { > const struct ovsdb_table_schema *ts = table->schema; > enum ovsdb_monitor_selection select; > - const struct json *columns, *select_json; > + const struct json *columns, *select_json, *where = NULL; > struct ovsdb_parser parser; > struct ovsdb_error *error; > > ovsdb_parser_init(&parser, monitor_request, "table %s", ts->name); > + if (cond) { > + where = ovsdb_parser_member(&parser, "where", OP_ARRAY | > OP_OPTIONAL); > + } > columns = ovsdb_parser_member(&parser, "columns", OP_ARRAY | > OP_OPTIONAL); > + > select_json = ovsdb_parser_member(&parser, "select", > OP_OBJECT | OP_OPTIONAL); > + > error = ovsdb_parser_finish(&parser); > if (error) { > return error; > @@ -1155,6 +1165,12 @@ ovsdb_jsonrpc_parse_monitor_request(struct > ovsdb_monitor *dbmon, > } > } > } > + if (cond) { > + error = ovsdb_monitor_table_condition_add(cond, table, where); > + if (error) { > + return error; > + } > + } > > return NULL; > } > @@ -1193,6 +1209,9 @@ ovsdb_jsonrpc_monitor_create(struct > ovsdb_jsonrpc_session *s, struct ovsdb *db, > m->session = s; > m->db = db; > m->dbmon = ovsdb_monitor_create(db, m); > + if (version == OVSDB_MONITOR_V2) { > + m->condition = ovsdb_monitor_session_condition_create(); > + } > m->unflushed = 0; > m->version = version; > hmap_insert(&s->monitors, &m->node, json_hash(monitor_id, 0)); > @@ -1221,6 +1240,7 @@ ovsdb_jsonrpc_monitor_create(struct > ovsdb_jsonrpc_session *s, struct ovsdb *db, > for (i = 0; i < array->n; i++) { > error = ovsdb_jsonrpc_parse_monitor_request(m->dbmon, > table, > + m->condition, > > array->elems[i]); > if (error) { > goto error; > @@ -1229,6 +1249,7 @@ ovsdb_jsonrpc_monitor_create(struct > ovsdb_jsonrpc_session *s, struct ovsdb *db, > } else { > error = ovsdb_jsonrpc_parse_monitor_request(m->dbmon, > table, > + m->condition, > mr_value); > if (error) { > goto error; > @@ -1253,6 +1274,11 @@ ovsdb_jsonrpc_monitor_create(struct > ovsdb_jsonrpc_session *s, struct ovsdb *db, > m->dbmon = dbmon; > } > > + /* We only add conditions columns here to simplify ovsdb_monitor_add > */ > + if (m->condition) { > + ovsdb_monitor_add_all_condition_columns(m->dbmon, m->condition); > + } > + > ovsdb_monitor_get_initial(m->dbmon); > json = ovsdb_jsonrpc_monitor_compose_update(m, true); > json = json ? json : json_object_create(); > @@ -1305,7 +1331,7 @@ ovsdb_jsonrpc_monitor_compose_update(struct > ovsdb_jsonrpc_monitor *m, > bool initial) > { > return ovsdb_monitor_get_update(m->dbmon, initial, &m->unflushed, > - m->version); > + m->condition, m->version); > } > > static bool > @@ -1328,6 +1354,9 @@ ovsdb_jsonrpc_monitor_destroy(struct > ovsdb_jsonrpc_monitor *m) > json_destroy(m->monitor_id); > hmap_remove(&m->session->monitors, &m->node); > ovsdb_monitor_remove_jsonrpc_monitor(m->dbmon, m); > + if (m->condition) { > + ovsdb_monitor_session_condition_destroy(m->condition); > + } > free(m); > } > > diff --git a/ovsdb/monitor.c b/ovsdb/monitor.c > index 7802560..1614d67 100644 > --- a/ovsdb/monitor.c > +++ b/ovsdb/monitor.c > @@ -27,6 +27,7 @@ > #include "ovsdb-parser.h" > #include "ovsdb.h" > #include "row.h" > +#include "condition.h" > #include "simap.h" > #include "hash.h" > #include "table.h" > @@ -41,6 +42,20 @@ > static const struct ovsdb_replica_class ovsdb_jsonrpc_replica_class; > static struct hmap ovsdb_monitors = HMAP_INITIALIZER(&ovsdb_monitors); > > +/* Keep state of session's conditions */ > +struct ovsdb_monitor_session_condition { > + size_t n_empty_cnd; > + struct shash tables; /* Contains > + * "struct ovsdb_monitor_table_condition > *"s. */ > +}; > + > +/* Monitored table session's conditions */ > +struct ovsdb_monitor_table_condition { > + const struct ovsdb_table *table; > + struct ovsdb_condition old_condition; > + struct ovsdb_condition new_condition; > +}; > + > /* Backend monitor. > * > * ovsdb_monitor keep track of the ovsdb changes. > @@ -108,6 +123,7 @@ struct ovsdb_monitor_changes { > /* A particular table being monitored. */ > struct ovsdb_monitor_table { > const struct ovsdb_table *table; > + const struct ovsdb_monitor *dbmon; > > /* This is the union (bitwise-OR) of the 'select' values in all of the > * members of 'columns' below. */ > @@ -129,9 +145,11 @@ struct ovsdb_monitor_table { > }; > > typedef struct json * > -(*compose_row_update_cb_func)(const struct ovsdb_monitor_table *mt, > - const struct ovsdb_monitor_row *row, > - bool initial, unsigned long int *changed); > +(*compose_row_update_cb_func) > + (const struct ovsdb_monitor_table *mt, > + const struct ovsdb_monitor_session_condition * condition, > + const struct ovsdb_monitor_row *row, > + bool initial, unsigned long int *changed); > > static void ovsdb_monitor_destroy(struct ovsdb_monitor *dbmon); > static struct ovsdb_monitor_changes * ovsdb_monitor_table_add_changes( > @@ -372,6 +390,7 @@ ovsdb_monitor_add_table(struct ovsdb_monitor *m, > > mt = xzalloc(sizeof *mt); > mt->table = table; > + mt->dbmon = m; > shash_add(&m->tables, table->schema->name, mt); > hmap_init(&mt->changes); > mt->columns_index_map = > @@ -390,9 +409,20 @@ ovsdb_monitor_add_column(struct ovsdb_monitor *dbmon, > { > struct ovsdb_monitor_table *mt; > struct ovsdb_monitor_column *c; > + int i; > > mt = shash_find_data(&dbmon->tables, table->schema->name); > > + /* Check duplication only for non-monitored columns */ > + if (!monitored) { > + for (i = 0; i < mt->n_columns; i++) { > + if (mt->columns[i].column == column) { > + /* column exists */ > + return; > + } > + } > + } > + > if (mt->n_columns >= mt->allocated_columns) { > mt->columns = x2nrealloc(mt->columns, &mt->allocated_columns, > sizeof *mt->columns); > @@ -409,6 +439,39 @@ ovsdb_monitor_add_column(struct ovsdb_monitor *dbmon, > } > } > > +static void > +ovsdb_monitor_condition_add_columns(struct ovsdb_monitor *dbmon, > + const struct ovsdb_table *table, > + struct ovsdb_condition *condition) > +{ > + size_t n_columns; > + int i; > + const struct ovsdb_column **columns = > + ovsdb_condition_get_columns(condition, &n_columns); > + > + for (i = 0; i < n_columns; i++) { > + ovsdb_monitor_add_column(dbmon, table, columns[i], > + OJMS_NONE, false); > + } > + if (n_columns) { > + free(columns); > + } > +} > + > +void > +ovsdb_monitor_add_all_condition_columns( > + struct ovsdb_monitor *dbmon, > + struct ovsdb_monitor_session_condition *cond) > +{ > + struct shash_node *node; > + > + SHASH_FOR_EACH(node, &cond->tables) { > + struct ovsdb_monitor_table_condition *mtc = node->data; > + > + ovsdb_monitor_condition_add_columns(dbmon, mtc->table, > &mtc->new_condition); > + } > +} > + > /* Check for duplicated column names. Return the first > * duplicated column's name if found. Otherwise return > * NULL. */ > @@ -519,6 +582,153 @@ ovsdb_monitor_row_update_type(bool initial, const > bool old, const bool new) > : !new ? OJMS_DELETE > : OJMS_MODIFY; > } > + > +/* Returnes an empty allocated session's condition state holder */ > +struct ovsdb_monitor_session_condition * > +ovsdb_monitor_session_condition_create(void) > +{ > + struct ovsdb_monitor_session_condition *condition; > + > + condition = xzalloc(sizeof *condition); > + shash_init(&condition->tables); > + > + return condition; > +} > + > +void > +ovsdb_monitor_session_condition_destroy( > + struct ovsdb_monitor_session_condition > *condition) > +{ > + struct shash_node *node, *next; > + > + SHASH_FOR_EACH_SAFE (node, next, &condition->tables) { > + struct ovsdb_monitor_table_condition *mtc = node->data; > + > + ovsdb_condition_destroy(&mtc->new_condition); > + ovsdb_condition_destroy(&mtc->old_condition); > + shash_delete(&condition->tables, node); > + free(mtc); > + } > + free(condition); > +} > + > +struct ovsdb_error * > +ovsdb_monitor_table_condition_add( > + struct ovsdb_monitor_session_condition > *condition, > + const struct ovsdb_table *table, > + const struct json *json_cnd) > +{ > + struct ovsdb_monitor_table_condition *mtc; > + struct ovsdb_error *error; > + > + mtc = xzalloc(sizeof *mtc); > + shash_add(&condition->tables, table->schema->name, mtc); > + mtc->table = table; > + ovsdb_condition_init(&mtc->old_condition); > + ovsdb_condition_init(&mtc->new_condition); > + > + if (json_cnd) { > + error = ovsdb_condition_from_json(table->schema, > + json_cnd, > + NULL, > + &mtc->old_condition); > + if (error) { > + return ovsdb_syntax_error(json_cnd, > + NULL, "array of conditions > expected"); > + } > + } > + ovsdb_condition_clone(&mtc->new_condition, &mtc->old_condition); > + if (ovsdb_condition_empty(&mtc->old_condition)) { > + condition->n_empty_cnd++; > + } > + > + return NULL; > +} > + > +static inline bool > +ovsdb_can_cache(const struct ovsdb_monitor_session_condition *condition) > +{ > + return shash_count(&condition->tables) == condition->n_empty_cnd; > +} > + > +static bool > +ovsdb_monitor_get_table_conditions( > + const struct ovsdb_monitor_table *mt, > + const struct ovsdb_monitor_session_condition > *condition, > + struct ovsdb_condition **old_condition, > + struct ovsdb_condition **new_condition) > +{ > + if (!condition) { > + return false; > + } > + > + struct ovsdb_monitor_table_condition *mtc = > + shash_find_data(&condition->tables, mt->table->schema->name); > + > + if (!mtc) { > + return false; > + } > + *old_condition = &mtc->old_condition; > + *new_condition = &mtc->new_condition; > + > + return true; > +} > + > +static enum ovsdb_monitor_selection > +ovsdb_monitor_row_update_type_condition( > + const struct ovsdb_monitor_table *mt, > + const struct ovsdb_monitor_session_condition > *condition, > + bool initial, > + const struct ovsdb_datum *old, > + const struct ovsdb_datum *new, > + const bool index_map) > +{ > + struct ovsdb_condition *old_condition, *new_condition; > + unsigned int *columns_index_map = index_map ? mt->columns_index_map > + : NULL; > + enum ovsdb_monitor_selection type = > + ovsdb_monitor_row_update_type(initial, old, new); > + > + if (ovsdb_monitor_get_table_conditions(mt, > + condition, > + &old_condition, > + &new_condition)) { > + bool old_cond = !old ? false > + : ovsdb_condition_evaluate_or_datum(old, > + old_condition, > + columns_index_map); > + bool new_cond = !new ? false > + : ovsdb_condition_evaluate_or_datum(new, > + new_condition, > + columns_index_map); > + > + if (!old_cond && !new_cond) { > + type = OJMS_NONE; > + } > + > + switch (type) { > + case OJMS_INITIAL: > + case OJMS_INSERT: > + if (!new_cond) { > + type = OJMS_NONE; > + } > + break; > + case OJMS_MODIFY: > + type = !old_cond ? OJMS_INSERT : !new_cond > + ? OJMS_DELETE : OJMS_MODIFY; > + break; > + case OJMS_DELETE: > + if (!old_cond) { > + type = OJMS_NONE; > + } > + break; > + case OJMS_NONE: > + break; > + } > + } > + return type; > +} > + > static bool > ovsdb_monitor_row_skip_update(const struct ovsdb_monitor_table *mt, > const struct ovsdb_monitor_row *row, > @@ -563,6 +773,7 @@ ovsdb_monitor_row_skip_update(const struct > ovsdb_monitor_table *mt, > static struct json * > ovsdb_monitor_compose_row_update( > const struct ovsdb_monitor_table *mt, > + const struct ovsdb_monitor_session_condition *condition OVS_UNUSED, > const struct ovsdb_monitor_row *row, > bool initial, unsigned long int *changed) > { > @@ -624,6 +835,7 @@ ovsdb_monitor_compose_row_update( > static struct json * > ovsdb_monitor_compose_row_update2( > const struct ovsdb_monitor_table *mt, > + const struct ovsdb_monitor_session_condition *condition, > const struct ovsdb_monitor_row *row, > bool initial, unsigned long int *changed) > { > @@ -631,7 +843,8 @@ ovsdb_monitor_compose_row_update2( > struct json *row_update2, *diff_json; > size_t i; > > - type = ovsdb_monitor_row_update_type(initial, row->old, row->new); > + type = ovsdb_monitor_row_update_type_condition(mt, condition, initial, > + row->old, row->new, > true); > if (ovsdb_monitor_row_skip_update(mt, row, type, changed)) { > return NULL; > } > @@ -701,9 +914,11 @@ ovsdb_monitor_max_columns(struct ovsdb_monitor *dbmon) > * RFC 7047) for all the outstanding changes within 'monitor', starting > from > * 'transaction'. */ > static struct json* > -ovsdb_monitor_compose_update(struct ovsdb_monitor *dbmon, > - bool initial, uint64_t transaction, > - compose_row_update_cb_func row_update) > +ovsdb_monitor_compose_update( > + struct ovsdb_monitor *dbmon, > + bool initial, uint64_t transaction, > + const struct ovsdb_monitor_session_condition > *condition, > + compose_row_update_cb_func row_update) > { > struct shash_node *node; > struct json *json; > @@ -725,7 +940,7 @@ ovsdb_monitor_compose_update(struct ovsdb_monitor > *dbmon, > HMAP_FOR_EACH_SAFE (row, next, hmap_node, &changes->rows) { > struct json *row_json; > > - row_json = (*row_update)(mt, row, initial, changed); > + row_json = (*row_update)(mt, condition, row, initial, > changed); > if (row_json) { > char uuid[UUID_LEN + 1]; > > @@ -759,11 +974,13 @@ ovsdb_monitor_compose_update(struct ovsdb_monitor > *dbmon, > * be used as part of the initial reply to a "monitor" request, false if > it is > * going to be used as part of an "update" notification. */ > struct json * > -ovsdb_monitor_get_update(struct ovsdb_monitor *dbmon, > - bool initial, uint64_t *unflushed, > - enum ovsdb_monitor_version version) > +ovsdb_monitor_get_update( > + struct ovsdb_monitor *dbmon, > + bool initial, uint64_t *unflushed, > + const struct ovsdb_monitor_session_condition *condition, > + enum ovsdb_monitor_version version) > { > - struct ovsdb_monitor_json_cache_node *cache_node; > + struct ovsdb_monitor_json_cache_node *cache_node = NULL; > struct shash_node *node; > struct json *json; > uint64_t prev_txn = *unflushed; > @@ -771,19 +988,27 @@ ovsdb_monitor_get_update(struct ovsdb_monitor *dbmon, > > /* Return a clone of cached json if one exists. Otherwise, > * generate a new one and add it to the cache. */ > - cache_node = ovsdb_monitor_json_cache_search(dbmon, version, > prev_txn); > + if (!condition || (condition && ovsdb_can_cache(condition))) { > + cache_node = ovsdb_monitor_json_cache_search(dbmon, version, > prev_txn); > + } > if (cache_node) { > json = cache_node->json ? json_clone(cache_node->json) : NULL; > } else { > if (version == OVSDB_MONITOR_V1) { > - json = ovsdb_monitor_compose_update(dbmon, initial, prev_txn, > - ovsdb_monitor_compose_row_update); > + json = > + ovsdb_monitor_compose_update(dbmon, initial, prev_txn, > + condition, > + > ovsdb_monitor_compose_row_update); > } else { > ovs_assert(version == OVSDB_MONITOR_V2); > - json = ovsdb_monitor_compose_update(dbmon, initial, prev_txn, > - > ovsdb_monitor_compose_row_update2); > + json = > + ovsdb_monitor_compose_update(dbmon, initial, prev_txn, > + condition, > + > ovsdb_monitor_compose_row_update2); > + } > + if (!condition || (condition && ovsdb_can_cache(condition))) { > + ovsdb_monitor_json_cache_insert(dbmon, version, prev_txn, > json); > } > - ovsdb_monitor_json_cache_insert(dbmon, version, prev_txn, json); > } > > /* Maintain transaction id of 'changes'. */ > diff --git a/ovsdb/monitor.h b/ovsdb/monitor.h > index 1f3dc6e..0529e5a 100644 > --- a/ovsdb/monitor.h > +++ b/ovsdb/monitor.h > @@ -19,8 +19,11 @@ > > struct ovsdb_monitor; > struct ovsdb_jsonrpc_monitor; > +struct ovsdb_monitor_session_condition; > +struct ovsdb_condition; > > enum ovsdb_monitor_selection { > + OJMS_NONE = 0, /* None for this iteration */ > OJMS_INITIAL = 1 << 0, /* All rows when monitor is created. */ > OJMS_INSERT = 1 << 1, /* New rows. */ > OJMS_DELETE = 1 << 2, /* Deleted rows. */ > @@ -60,21 +63,50 @@ void ovsdb_monitor_add_column(struct ovsdb_monitor > *dbmon, > enum ovsdb_monitor_selection select, > bool monitored); > > +void ovsdb_monitor_add_all_condition_columns(struct ovsdb_monitor *dbmon, > + struct ovsdb_monitor_session_condition > *cond); > + > const char * OVS_WARN_UNUSED_RESULT > ovsdb_monitor_table_check_duplicates(struct ovsdb_monitor *, > const struct ovsdb_table *); > > -struct json *ovsdb_monitor_get_update(struct ovsdb_monitor *dbmon, > - bool initial, > - uint64_t *unflushed_transaction, > - enum ovsdb_monitor_version version); > +struct json *ovsdb_monitor_get_update( > + struct ovsdb_monitor *dbmon, > + bool initial, > + uint64_t *unflushed_transaction, > + const struct ovsdb_monitor_session_condition *condition, > + enum ovsdb_monitor_version version); > > void ovsdb_monitor_table_add_select(struct ovsdb_monitor *dbmon, > const struct ovsdb_table *table, > enum ovsdb_monitor_selection select); > > +struct ovsdb_condition * > +ovsdb_monitor_table_get_condition(struct ovsdb_monitor *dbmon, > + const struct ovsdb_table *table); > + > +void ovsdb_monitor_table_set_conditional(struct ovsdb_monitor *dbmon, > + const struct ovsdb_table *table); > + > bool ovsdb_monitor_needs_flush(struct ovsdb_monitor *dbmon, > uint64_t next_transaction); > > void ovsdb_monitor_get_initial(const struct ovsdb_monitor *dbmon); > + > +struct ovsdb_monitor_session_condition * > +ovsdb_monitor_session_condition_create(void); > + > +void > +ovsdb_monitor_session_condition_destroy( > + struct ovsdb_monitor_session_condition > *condition); > +struct ovsdb_error * > +ovsdb_monitor_table_condition_add( > + struct ovsdb_monitor_session_condition > *condition, > + const struct ovsdb_table *table, > + const struct json *json_cnd); > + > +void ovsdb_monitor_session_condition_bind( > + const struct ovsdb_monitor_session_condition *, > + const struct ovsdb_monitor *); > Is this function defined? > + > #endif > diff --git a/ovsdb/ovsdb-server.1.in b/ovsdb/ovsdb-server.1.in > index 6c85729..27952b6 100644 > --- a/ovsdb/ovsdb-server.1.in > +++ b/ovsdb/ovsdb-server.1.in > @@ -245,31 +245,228 @@ notifications (see below) to the request, it must > be unique among all > active monitors. \fBovsdb\-server\fR rejects attempt to create two > monitors with the same identifier. > . > -.IP "4.1.12. Monitor2" > -A new monitor method added in Open vSwitch version 2.5. Monitor2 allows > -for more efficient update notifications (described below). > +.IP "4.1.12. Monitor_cond" > +A new monitor method added in Open vSwitch version 2.5. The monitor_cond > +request enables a client to replicate subsets of tables within an OVSDB > +database by requesting notifications of changes to rows matching one of > +the conditions specified in "where" by receiving the specified contents > +of these rows when table updates occur. Monitor_cond also allows a more > +efficient update notifications by receiving table-updates2 notifications > +(described below). > +. > .IP > -The monitor method described in Section 4.1.5 also applies to > -monitor2, with the following exceptions. > +The monitor method described in Section 4.1.5 also applies to > monitor_cond, > +with the following exceptions: > . > .RS > .IP \(bu > -RPC request method becomes "monitor2". > +RPC request method becomes "monitor_cond". > .IP \(bu > -Replay result follows <table-updates2>, described in Section 4.1.13. > +Replay result follows <table-updates2>, described in Section 4.1.14. > .IP \(bu > Subsequent changes are sent to the client using the "update2" monitor > -notification, described in Section 4.1.13 > +notification, described in Section 4.1.14 > +.IP \(bu > +Update notifications are being sent only for rows matching > [<conditions>*]. > +<condition> is specified in Section 5.1 in the RFC with the following > +change: A condition can be either a 3-element JSON array as deescribed in > +the RFC or a boolean value. In case of an empty array an implicit true > +boolean value will be considered, and all rows will be monitored. > +.RE > +. > +.IP > +The request object has the following members: > +. > +.PP > +.RS > +.nf > +"method": "monitor_cond" > +"params": [<db-name>, <json-value>, <monitor-cond-requests>] > +"id": <nonnull-json-value> > +.fi > +.RE > +. > +.IP > +The <json-value> parameter is used to match subsequent update > notifications > +(see below) to this request. The <monitor-cond-requests> object maps the > name > +of the table to an array of <monitor-cond-request>. > +. > +.IP > +Each <monitor-cond-request> is an object with the following members: > +. > +.PP > +.RS > +.nf > +"columns": [<column>*] optional > +"where": [<condition>*] optional > +"select": <monitor-select> optional > +.fi > +.RE > +. > +.IP > +The "columns", if present, define the columns within the table to be > monitored > +that match conditions. If not present all columns are being monitored. > +. > +.IP > +The "where" if present is a JSON array of <condition> and boolean values. > If not > +present or condition is an empty array, implicit True will be considered > and > +updates on all rows will be sent. <condition> is specified in Section 5.1 > in > +the RFC with the following change: A condition can be either a 3-element > JSON > +array as described in the RFC or a boolean value. In case of an empty > array an > +implicit true boolean value will be considered, and all rows will be > monitored. > +. > +.IP > +<monitor-select> is an object with the following members: > +. > +.PP > +.RS > +.nf > +"initial": <boolean> optional > +"insert": <boolean> optional > +"delete": <boolean> optional > +"modify": <boolean> optional > +.fi > +.RE > +. > +.IP > +The contents of this object specify how the columns or table are to be > +monitored as explained in more detail below. > +. > +.IP > +The response object has the following members: > +. > +.PP > +.RS > +.nf > +"result": <table-updates2> > +"error": null > +"id": same "id" as request > +.fi > +.RE > +. > +.IP > +The <table-updates2> object is described in detail in Section 4.1.14. It > +contains the contents of the tables for which "initial" rows are selected. > +If no tables initial contents are requested, then "result" is an empty > object. > +, > +.IP > +Subsequently, when changes to a specified table that match one of the > conditions > +in monitor-cond-request are committed, the changes are automatically sent > to the > +client using the "update2" monitor notification (see Section 4.1.14). This > +monitoring persists until the JSON-RPC session terminates or until the > client > +sends a "monitor_cancel" JSON-RPC request. > +. > +.IP > +Each <monitor-cond-request> specifies one or more conditions and the > manner in > +which the rows that match the conditions are to be monitored. The > circumstances in > +which an "update" notification is sent for a row within the table are > determined by > +<monitor-select>: > +. > +.RS > +.IP \(bu > +If "initial" is omitted or true, every row in the original table that > matches one of > +the conditions is sent as part of the response to the "monitor_cond" > request. > +.IP \(bu > +If "insert" is omitted or true, "update" notifications are sent for rows > newly > +inserted into the table that match conditions or for rows modified in the > table > +so that their old version does not match the condition and new version > does. > +(new row in the client's replica table) > +.IP \(bu > +If "delete" is omitted or true, "update" notifications are sent for rows > deleted > +from the table that match conditions or for rows modified in the table so > that > +their old version does match the conditions and new version does not. > (deleted row > +in the client's replica) > +.IP \(bu > +If "modify" is omitted or true, "update" notifications are sent whenever > a row in > +the table that matches conditions in both old and new version is modified. > .RE > . > .IP > -Both monitor and monitor2 sessions can exist concurrently. However, > -monitor and monitor2 shares the same <json-value> parameter space; it > -must be unique among all monitor and monitor2 sessions. > +Both monitor and monitor_cond sessions can exist concurrently. However, > +monitor and monitor_cond shares the same <json-value> parameter space; it > +must be unique among all monitor and monitor_cond sessions. > +. > +.IP "4.1.13. Monitor_cond_update" > +The "monitor_cond_update" request enables a client to change an existing > +"monitor_cond" replication of the database by specifying a new condition > +and columns for each replicated table. Currently changing the columns set > +is not supported. > +. > +.IP > +The request object has the following members: > +. > +.IP > +.RS > +.nf > +"method": "monitor_cond_update" > +"params": [<json-value>, <json-value>, <monitor-cond-update-requests>] > +"id": <nonnull-json-value> > +.fi > +.RE > +. > +.IP > +The <json-value> parameter should have a value of an existing conditional > +monitoring session from this client. The second <json-value> in params > array > +is the requested value for this session. This value is valid only after > +"monitor_cond_update" is committed. A user can use these values to > distinguish > +between update messages before conditions update and after. The > +<monitor-cond-update-requests> object maps the name of the table to an > array of > +<monitor-cond-update-request>. > +. > +.IP > +Each <monitor-cond-update-request> is an object with the following > members: > +. > +.IP > +.RS > +.nf > +"columns": [<column>*] optional > +"where": [<condition>*] optional > +.fi > +.RE > +. > +.IP > +The "columns" specify a new array of columns to be monitored > +(Currently unsupported). > +. > +.IP > +The "where" specify a new array of conditions to be applied to this > monitoring > +session. > +. > +.IP > +<condition> is specified in Section 5.1 in the RFC with the following > change: > +A condition can be either a 3-element JSON array as described in the RFC > or a > +boolean value. In case of an empty array an implicit true boolean value > will be > +considered, and all rows will be monitored. > +. > +.IP > +The response object has the following members: > +. > +.IP > +.RS > +.nf > +"result": null > +"error": null > +"id": same "id" as request > +.fi > +.RE > +.IP > +Subsequent <table-updates2> notifications are described in detail in > Section > +4.1.14 in the RFC. If insert contents are requested by origin monitor_cond > +request, <table-updates2> will contain rows that match the new condition > and > +do not match the old condition. > +If deleted contents are requested by origin monitor request, > <table-updates2> > +will contain any matched rows by old condition and not matched by the new > +condition. > +. > +.IP > +Changes according to the new conditions are automatically sent to the > client > +using the "update2" monitor notification. Updates as a result of a > condition > +change, will be sent only after the client received a response to the > +"monitor_cond_update" request. > . > -.IP "4.1.13. Update2 notification" > +.IP "4.1.14. Update2 notification" > The "update2" notification is sent by the server to the client to report > -changes in tables that are being monitored following a "monitor2" request > +changes in tables that are being monitored following a "monitor_cond" > request > as described above. The notification has the following members: > . > .RS > @@ -284,7 +481,8 @@ as described above. The notification has the following > members: > The <json-value> in "params" is the same as the value passed as the > <json-value> in "params" for the corresponding "monitor" request. > <table-updates2> is an object that maps from a table name to a > <table-update2>. > -A <table-update2> is an object that maps from row's UUID to a > <row-update2> object. A <row-update2> is an object with one of the > following members: > +A <table-update2> is an object that maps from row's UUID to a > <row-update2> > +object. A <row-update2> is an object with one of the following members: > . > .RS > .IP "\(dqinitial\(dq: <row>" > @@ -326,8 +524,8 @@ elements, <row> includes the value from the new column. > . > .IP > Initial views of rows are not presented in update2 notifications, > -but in the response object to the monitor2 request. The formatting of the > -<table-updates2> object, however, is the same in either case. > +but in the response object to the monitor_cond request. The formatting > +of the <table-updates2> object, however, is the same in either case. > . > .IP "5.1. Notation" > For <condition>, RFC 7047 only allows the use of \fB!=\fR, \fB==\fR, > -- > 2.1.4 > > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev