]> git.proxmox.com Git - mirror_ovs.git/blob - lib/ovsdb-idl.c
dpctl: Fix dpctl process command parameter error.
[mirror_ovs.git] / lib / ovsdb-idl.c
1 /* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc.
2 * Copyright (C) 2016 Hewlett Packard Enterprise Development LP
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <config.h>
18
19 #include "ovsdb-idl.h"
20
21 #include <errno.h>
22 #include <inttypes.h>
23 #include <limits.h>
24 #include <stdlib.h>
25
26 #include "bitmap.h"
27 #include "coverage.h"
28 #include "hash.h"
29 #include "openvswitch/dynamic-string.h"
30 #include "fatal-signal.h"
31 #include "openvswitch/json.h"
32 #include "jsonrpc.h"
33 #include "ovsdb/ovsdb.h"
34 #include "ovsdb/table.h"
35 #include "ovsdb-cs.h"
36 #include "ovsdb-data.h"
37 #include "ovsdb-error.h"
38 #include "ovsdb-idl-provider.h"
39 #include "ovsdb-parser.h"
40 #include "ovsdb-server-idl.h"
41 #include "ovsdb-session.h"
42 #include "openvswitch/poll-loop.h"
43 #include "openvswitch/shash.h"
44 #include "skiplist.h"
45 #include "sset.h"
46 #include "svec.h"
47 #include "util.h"
48 #include "uuid.h"
49 #include "openvswitch/vlog.h"
50
51 VLOG_DEFINE_THIS_MODULE(ovsdb_idl);
52
53 COVERAGE_DEFINE(txn_uncommitted);
54 COVERAGE_DEFINE(txn_unchanged);
55 COVERAGE_DEFINE(txn_incomplete);
56 COVERAGE_DEFINE(txn_aborted);
57 COVERAGE_DEFINE(txn_success);
58 COVERAGE_DEFINE(txn_try_again);
59 COVERAGE_DEFINE(txn_not_locked);
60 COVERAGE_DEFINE(txn_error);
61
62 /* An arc from one idl_row to another. When row A contains a UUID that
63 * references row B, this is represented by an arc from A (the source) to B
64 * (the destination).
65 *
66 * Arcs from a row to itself are omitted, that is, src and dst are always
67 * different.
68 *
69 * Arcs are never duplicated, that is, even if there are multiple references
70 * from A to B, there is only a single arc from A to B.
71 *
72 * Arcs are directed: an arc from A to B is the converse of an an arc from B to
73 * A. Both an arc and its converse may both be present, if each row refers
74 * to the other circularly.
75 *
76 * The source and destination row may be in the same table or in different
77 * tables.
78 */
79 struct ovsdb_idl_arc {
80 struct ovs_list src_node; /* In src->src_arcs list. */
81 struct ovs_list dst_node; /* In dst->dst_arcs list. */
82 struct ovsdb_idl_row *src; /* Source row. */
83 struct ovsdb_idl_row *dst; /* Destination row. */
84 };
85
86 struct ovsdb_idl {
87 struct ovsdb_cs *cs;
88 const struct ovsdb_idl_class *class_;
89 struct shash table_by_name; /* Contains "struct ovsdb_idl_table *"s.*/
90 struct ovsdb_idl_table *tables; /* Array of ->class_->n_tables elements. */
91 unsigned int change_seqno;
92 struct ovsdb_idl_txn *txn;
93 struct hmap outstanding_txns;
94 bool verify_write_only;
95 };
96
97 static struct ovsdb_cs_ops ovsdb_idl_cs_ops;
98
99 struct ovsdb_idl_txn {
100 struct hmap_node hmap_node;
101 struct json *request_id;
102 struct ovsdb_idl *idl;
103 struct hmap txn_rows;
104 enum ovsdb_idl_txn_status status;
105 char *error;
106 bool dry_run;
107 struct ds comment;
108
109 /* Increments. */
110 const char *inc_table;
111 const char *inc_column;
112 struct uuid inc_row;
113 bool inc_force;
114 unsigned int inc_index;
115 int64_t inc_new_value;
116
117 /* Inserted rows. */
118 struct hmap inserted_rows; /* Contains "struct ovsdb_idl_txn_insert"s. */
119 };
120
121 struct ovsdb_idl_txn_insert {
122 struct hmap_node hmap_node; /* In struct ovsdb_idl_txn's inserted_rows. */
123 struct uuid dummy; /* Dummy UUID used locally. */
124 int op_index; /* Index into transaction's operation array. */
125 struct uuid real; /* Real UUID used by database server. */
126 };
127
128 static struct vlog_rate_limit syntax_rl = VLOG_RATE_LIMIT_INIT(1, 5);
129 static struct vlog_rate_limit semantic_rl = VLOG_RATE_LIMIT_INIT(1, 5);
130 static struct vlog_rate_limit other_rl = VLOG_RATE_LIMIT_INIT(1, 5);
131
132 enum update_result {
133 OVSDB_IDL_UPDATE_DB_CHANGED,
134 OVSDB_IDL_UPDATE_NO_CHANGES,
135 OVSDB_IDL_UPDATE_INCONSISTENT,
136 };
137 static void ovsdb_idl_clear(struct ovsdb_idl *);
138 static enum update_result ovsdb_idl_process_update(
139 struct ovsdb_idl_table *, const struct ovsdb_cs_row_update *);
140 static void ovsdb_idl_insert_row(struct ovsdb_idl_row *,
141 const struct shash *values);
142 static void ovsdb_idl_delete_row(struct ovsdb_idl_row *);
143 static bool ovsdb_idl_modify_row(struct ovsdb_idl_row *,
144 const struct shash *values, bool xor);
145 static void ovsdb_idl_parse_update(struct ovsdb_idl *,
146 const struct ovsdb_cs_update_event *);
147
148 static void ovsdb_idl_txn_process_reply(struct ovsdb_idl *,
149 const struct jsonrpc_msg *);
150
151 static bool ovsdb_idl_row_is_orphan(const struct ovsdb_idl_row *);
152 static struct ovsdb_idl_row *ovsdb_idl_row_create__(
153 const struct ovsdb_idl_table_class *);
154 static struct ovsdb_idl_row *ovsdb_idl_row_create(struct ovsdb_idl_table *,
155 const struct uuid *);
156 static void ovsdb_idl_row_destroy(struct ovsdb_idl_row *);
157 static void ovsdb_idl_row_destroy_postprocess(struct ovsdb_idl *);
158 static void ovsdb_idl_destroy_all_map_op_lists(struct ovsdb_idl_row *);
159 static void ovsdb_idl_destroy_all_set_op_lists(struct ovsdb_idl_row *);
160
161 static void ovsdb_idl_row_parse(struct ovsdb_idl_row *);
162 static void ovsdb_idl_row_unparse(struct ovsdb_idl_row *);
163 static void ovsdb_idl_row_clear_old(struct ovsdb_idl_row *);
164 static void ovsdb_idl_row_clear_new(struct ovsdb_idl_row *);
165 static void ovsdb_idl_row_clear_arcs(struct ovsdb_idl_row *, bool destroy_dsts);
166
167 static void ovsdb_idl_txn_abort_all(struct ovsdb_idl *);
168 static bool ovsdb_idl_txn_extract_mutations(struct ovsdb_idl_row *,
169 struct json *);
170 static void ovsdb_idl_txn_add_map_op(struct ovsdb_idl_row *,
171 const struct ovsdb_idl_column *,
172 struct ovsdb_datum *,
173 enum map_op_type);
174 static void ovsdb_idl_txn_add_set_op(struct ovsdb_idl_row *,
175 const struct ovsdb_idl_column *,
176 struct ovsdb_datum *,
177 enum set_op_type);
178
179 static struct ovsdb_idl_table *
180 ovsdb_idl_table_from_class(const struct ovsdb_idl *,
181 const struct ovsdb_idl_table_class *);
182 static struct ovsdb_idl_table *
183 ovsdb_idl_table_from_class(const struct ovsdb_idl *,
184 const struct ovsdb_idl_table_class *);
185 static bool ovsdb_idl_track_is_set(struct ovsdb_idl_table *table);
186 static void ovsdb_idl_track_clear__(struct ovsdb_idl *, bool flush_all);
187
188 static void ovsdb_idl_destroy_indexes(struct ovsdb_idl_table *);
189 static void ovsdb_idl_add_to_indexes(const struct ovsdb_idl_row *);
190 static void ovsdb_idl_remove_from_indexes(const struct ovsdb_idl_row *);
191 static int ovsdb_idl_try_commit_loop_txn(struct ovsdb_idl_loop *loop,
192 bool *may_need_wakeup);
193
194 /* Creates and returns a connection to database 'remote', which should be in a
195 * form acceptable to jsonrpc_session_open(). The connection will maintain an
196 * in-memory replica of the remote database whose schema is described by
197 * 'class'. (Ordinarily 'class' is compiled from an OVSDB schema automatically
198 * by ovsdb-idlc.)
199 *
200 * Passes 'retry' to jsonrpc_session_open(). See that function for
201 * documentation.
202 *
203 * If 'monitor_everything_by_default' is true, then everything in the remote
204 * database will be replicated by default. ovsdb_idl_omit() and
205 * ovsdb_idl_omit_alert() may be used to selectively drop some columns from
206 * monitoring.
207 *
208 * If 'monitor_everything_by_default' is false, then no columns or tables will
209 * be replicated by default. ovsdb_idl_add_column() and ovsdb_idl_add_table()
210 * must be used to choose some columns or tables to replicate.
211 */
212 struct ovsdb_idl *
213 ovsdb_idl_create(const char *remote, const struct ovsdb_idl_class *class,
214 bool monitor_everything_by_default, bool retry)
215 {
216 struct ovsdb_idl *idl = ovsdb_idl_create_unconnected(
217 class, monitor_everything_by_default);
218 ovsdb_idl_set_remote(idl, remote, retry);
219 return idl;
220 }
221
222 /* Creates and returns a connection to an in-memory replica of the remote
223 * database whose schema is described by 'class'. (Ordinarily 'class' is
224 * compiled from an OVSDB schema automatically by ovsdb-idlc.)
225 *
226 * Use ovsdb_idl_set_remote() to configure the database to which to connect.
227 * Until a remote is configured, no data can be retrieved.
228 *
229 * If 'monitor_everything_by_default' is true, then everything in the remote
230 * database will be replicated by default. ovsdb_idl_omit() and
231 * ovsdb_idl_omit_alert() may be used to selectively drop some columns from
232 * monitoring.
233 *
234 * If 'monitor_everything_by_default' is false, then no columns or tables will
235 * be replicated by default. ovsdb_idl_add_column() and ovsdb_idl_add_table()
236 * must be used to choose some columns or tables to replicate.
237 */
238 struct ovsdb_idl *
239 ovsdb_idl_create_unconnected(const struct ovsdb_idl_class *class,
240 bool monitor_everything_by_default)
241 {
242 struct ovsdb_idl *idl = xmalloc(sizeof *idl);
243 *idl = (struct ovsdb_idl) {
244 .cs = ovsdb_cs_create(class->database, 3, &ovsdb_idl_cs_ops, idl),
245 .class_ = class,
246 .table_by_name = SHASH_INITIALIZER(&idl->table_by_name),
247 .tables = xmalloc(class->n_tables * sizeof *idl->tables),
248 .change_seqno = 0,
249 .txn = NULL,
250 .outstanding_txns = HMAP_INITIALIZER(&idl->outstanding_txns),
251 .verify_write_only = false,
252 };
253
254 uint8_t default_mode = (monitor_everything_by_default
255 ? OVSDB_IDL_MONITOR | OVSDB_IDL_ALERT
256 : 0);
257 for (size_t i = 0; i < class->n_tables; i++) {
258 const struct ovsdb_idl_table_class *tc = &class->tables[i];
259 struct ovsdb_idl_table *table = &idl->tables[i];
260
261 shash_add_assert(&idl->table_by_name, tc->name, table);
262 table->class_ = tc;
263 table->modes = xmalloc(tc->n_columns);
264 memset(table->modes, default_mode, tc->n_columns);
265 table->need_table = false;
266 shash_init(&table->columns);
267 ovs_list_init(&table->indexes);
268 for (size_t j = 0; j < tc->n_columns; j++) {
269 const struct ovsdb_idl_column *column = &tc->columns[j];
270
271 shash_add_assert(&table->columns, column->name, column);
272 }
273 hmap_init(&table->rows);
274 ovs_list_init(&table->track_list);
275 table->change_seqno[OVSDB_IDL_CHANGE_INSERT]
276 = table->change_seqno[OVSDB_IDL_CHANGE_MODIFY]
277 = table->change_seqno[OVSDB_IDL_CHANGE_DELETE] = 0;
278 table->idl = idl;
279 }
280
281 return idl;
282 }
283
284 /* Changes the remote and creates a new session.
285 *
286 * If 'retry' is true, the connection to the remote will automatically retry
287 * when it fails. If 'retry' is false, the connection is one-time. */
288 void
289 ovsdb_idl_set_remote(struct ovsdb_idl *idl, const char *remote, bool retry)
290 {
291 ovsdb_cs_set_remote(idl->cs, remote, retry);
292 }
293
294 /* Set whether the order of remotes should be shuffled, when there
295 * are more than one remotes. The setting doesn't take effect
296 * until the next time when ovsdb_idl_set_remote() is called. */
297 void
298 ovsdb_idl_set_shuffle_remotes(struct ovsdb_idl *idl, bool shuffle)
299 {
300 ovsdb_cs_set_shuffle_remotes(idl->cs, shuffle);
301 }
302
303 /* Reset min_index to 0. This prevents a situation where the client
304 * thinks all databases have stale data, when they actually have all
305 * been destroyed and rebuilt from scratch.
306 */
307 void
308 ovsdb_idl_reset_min_index(struct ovsdb_idl *idl)
309 {
310 ovsdb_cs_reset_min_index(idl->cs);
311 }
312
313 /* Destroys 'idl' and all of the data structures that it manages. */
314 void
315 ovsdb_idl_destroy(struct ovsdb_idl *idl)
316 {
317 if (idl) {
318 ovs_assert(!idl->txn);
319
320 ovsdb_idl_txn_abort_all(idl);
321 hmap_destroy(&idl->outstanding_txns);
322
323 ovsdb_idl_clear(idl);
324 ovsdb_cs_destroy(idl->cs);
325 for (size_t i = 0; i < idl->class_->n_tables; i++) {
326 struct ovsdb_idl_table *table = &idl->tables[i];
327 ovsdb_idl_destroy_indexes(table);
328 shash_destroy(&table->columns);
329 hmap_destroy(&table->rows);
330 free(table->modes);
331 }
332 shash_destroy(&idl->table_by_name);
333 free(idl->tables);
334 free(idl);
335 }
336 }
337
338 /* By default, or if 'leader_only' is true, when 'idl' connects to a clustered
339 * database, the IDL will avoid servers other than the cluster leader. This
340 * ensures that any data that it reads and reports is up-to-date. If
341 * 'leader_only' is false, the IDL will accept any server in the cluster, which
342 * means that for read-only transactions it can report and act on stale data
343 * (transactions that modify the database are always serialized even with false
344 * 'leader_only'). Refer to Understanding Cluster Consistency in ovsdb(7) for
345 * more information. */
346 void
347 ovsdb_idl_set_leader_only(struct ovsdb_idl *idl, bool leader_only)
348 {
349 ovsdb_cs_set_leader_only(idl->cs, leader_only);
350 }
351
352 static void
353 ovsdb_idl_clear(struct ovsdb_idl *db)
354 {
355 for (size_t i = 0; i < db->class_->n_tables; i++) {
356 struct ovsdb_idl_table *table = &db->tables[i];
357 struct ovsdb_idl_row *row, *next_row;
358
359 if (hmap_is_empty(&table->rows)) {
360 continue;
361 }
362
363 HMAP_FOR_EACH_SAFE (row, next_row, hmap_node, &table->rows) {
364 struct ovsdb_idl_arc *arc, *next_arc;
365
366 if (!ovsdb_idl_row_is_orphan(row)) {
367 ovsdb_idl_remove_from_indexes(row);
368 ovsdb_idl_row_unparse(row);
369 }
370 LIST_FOR_EACH_SAFE (arc, next_arc, src_node, &row->src_arcs) {
371 free(arc);
372 }
373 /* No need to do anything with dst_arcs: some node has those arcs
374 * as forward arcs and will destroy them itself. */
375
376 ovsdb_idl_row_destroy(row);
377 }
378 }
379 ovsdb_idl_row_destroy_postprocess(db);
380
381 ovsdb_idl_track_clear__(db, true);
382 db->change_seqno++;
383 }
384
385 /* Processes a batch of messages from the database server on 'idl'. This may
386 * cause the IDL's contents to change. The client may check for that with
387 * ovsdb_idl_get_seqno(). */
388 void
389 ovsdb_idl_run(struct ovsdb_idl *idl)
390 {
391 ovs_assert(!idl->txn);
392
393 struct ovs_list events;
394 ovsdb_cs_run(idl->cs, &events);
395
396 struct ovsdb_cs_event *event;
397 LIST_FOR_EACH_POP (event, list_node, &events) {
398 switch (event->type) {
399 case OVSDB_CS_EVENT_TYPE_RECONNECT:
400 ovsdb_idl_txn_abort_all(idl);
401 break;
402
403 case OVSDB_CS_EVENT_TYPE_LOCKED:
404 /* If the client couldn't run a transaction because it didn't have
405 * the lock, this will encourage it to try again. */
406 idl->change_seqno++;
407 break;
408
409 case OVSDB_CS_EVENT_TYPE_UPDATE:
410 ovsdb_idl_parse_update(idl, &event->update);
411 break;
412
413 case OVSDB_CS_EVENT_TYPE_TXN_REPLY:
414 ovsdb_idl_txn_process_reply(idl, event->txn_reply);
415 break;
416 }
417 ovsdb_cs_event_destroy(event);
418 }
419
420 ovsdb_idl_row_destroy_postprocess(idl);
421 }
422
423 /* Arranges for poll_block() to wake up when ovsdb_idl_run() has something to
424 * do or when activity occurs on a transaction on 'idl'. */
425 void
426 ovsdb_idl_wait(struct ovsdb_idl *idl)
427 {
428 ovsdb_cs_wait(idl->cs);
429 }
430
431 /* Returns a "sequence number" that represents the state of 'idl'. When
432 * ovsdb_idl_run() changes the database, the sequence number changes. The
433 * initial fetch of the entire contents of the remote database is considered to
434 * be one kind of change. Successfully acquiring a lock, if one has been
435 * configured with ovsdb_idl_set_lock(), is also considered to be a change.
436 *
437 * As long as the sequence number does not change, the client may continue to
438 * use any data structures it obtains from 'idl'. But when it changes, the
439 * client must not access any of these data structures again, because they
440 * could have freed or reused for other purposes.
441 *
442 * The sequence number can occasionally change even if the database does not.
443 * This happens if the connection to the database drops and reconnects, which
444 * causes the database contents to be reloaded even if they didn't change. (It
445 * could also happen if the database server sends out a "change" that reflects
446 * what the IDL already thought was in the database. The database server is
447 * not supposed to do that, but bugs could in theory cause it to do so.) */
448 unsigned int
449 ovsdb_idl_get_seqno(const struct ovsdb_idl *idl)
450 {
451 return idl->change_seqno;
452 }
453
454 /* Returns a "sequence number" that represents the number of conditional
455 * monitoring updates successfully received by the OVSDB server of an IDL
456 * connection.
457 *
458 * ovsdb_idl_set_condition() sets a new condition that is different from
459 * the current condtion, the next expected "sequence number" is returned.
460 *
461 * Whenever ovsdb_idl_get_cond_seqno() returns a value that matches
462 * the return value of ovsdb_idl_set_condition(), The client is
463 * assured that:
464 * - The ovsdb_idl_set_condition() changes has been acknowledged by
465 * the OVSDB sever.
466 *
467 * - 'idl' now contains the content matches the new conditions. */
468 unsigned int
469 ovsdb_idl_get_condition_seqno(const struct ovsdb_idl *idl)
470 {
471 return ovsdb_cs_get_condition_seqno(idl->cs);
472 }
473
474 /* Returns true if 'idl' successfully connected to the remote database and
475 * retrieved its contents (even if the connection subsequently dropped and is
476 * in the process of reconnecting). If so, then 'idl' contains an atomic
477 * snapshot of the database's contents (but it might be arbitrarily old if the
478 * connection dropped).
479 *
480 * Returns false if 'idl' has never connected or retrieved the database's
481 * contents. If so, 'idl' is empty. */
482 bool
483 ovsdb_idl_has_ever_connected(const struct ovsdb_idl *idl)
484 {
485 return ovsdb_idl_get_seqno(idl) != 0;
486 }
487
488 /* Reconfigures 'idl' so that it would reconnect to the database, if
489 * connection was dropped. */
490 void
491 ovsdb_idl_enable_reconnect(struct ovsdb_idl *idl)
492 {
493 ovsdb_cs_enable_reconnect(idl->cs);
494 }
495
496 /* Forces 'idl' to drop its connection to the database and reconnect. In the
497 * meantime, the contents of 'idl' will not change. */
498 void
499 ovsdb_idl_force_reconnect(struct ovsdb_idl *idl)
500 {
501 ovsdb_cs_force_reconnect(idl->cs);
502 }
503
504 /* Some IDL users should only write to write-only columns. Furthermore,
505 * writing to a column which is not write-only can cause serious performance
506 * degradations for these users. This function causes 'idl' to reject writes
507 * to columns which are not marked write only using ovsdb_idl_omit_alert(). */
508 void
509 ovsdb_idl_verify_write_only(struct ovsdb_idl *idl)
510 {
511 idl->verify_write_only = true;
512 }
513
514 /* Returns true if 'idl' is currently connected or trying to connect
515 * and a negative response to a schema request has not been received */
516 bool
517 ovsdb_idl_is_alive(const struct ovsdb_idl *idl)
518 {
519 return ovsdb_cs_is_alive(idl->cs);
520 }
521
522 bool
523 ovsdb_idl_is_connected(const struct ovsdb_idl *idl)
524 {
525 return ovsdb_cs_is_connected(idl->cs);
526 }
527
528 /* Returns the last error reported on a connection by 'idl'. The return value
529 * is 0 only if no connection made by 'idl' has ever encountered an error and
530 * a negative response to a schema request has never been received. See
531 * jsonrpc_get_status() for jsonrpc_session_get_last_error() return value
532 * interpretation. */
533 int
534 ovsdb_idl_get_last_error(const struct ovsdb_idl *idl)
535 {
536 return ovsdb_cs_get_last_error(idl->cs);
537 }
538
539 /* Sets the "probe interval" for 'idl->session' to 'probe_interval', in
540 * milliseconds.
541 */
542 void
543 ovsdb_idl_set_probe_interval(const struct ovsdb_idl *idl, int probe_interval)
544 {
545 ovsdb_cs_set_probe_interval(idl->cs, probe_interval);
546 }
547
548 static size_t
549 find_uuid_in_array(const struct uuid *target,
550 const struct uuid *array, size_t n)
551 {
552 for (size_t i = 0; i < n; i++) {
553 if (uuid_equals(&array[i], target)) {
554 return i;
555 }
556 }
557 return SIZE_MAX;
558 }
559
560 static size_t
561 array_contains_uuid(const struct uuid *target,
562 const struct uuid *array, size_t n)
563 {
564 return find_uuid_in_array(target, array, n) != SIZE_MAX;
565 }
566
567 static bool
568 remove_uuid_from_array(const struct uuid *target,
569 struct uuid *array, size_t *n)
570 {
571 size_t i = find_uuid_in_array(target, array, *n);
572 if (i != SIZE_MAX) {
573 array[i] = array[--*n];
574 return true;
575 } else {
576 return false;
577 }
578 }
579
580 static void
581 add_row_references(const struct ovsdb_base_type *type,
582 const union ovsdb_atom *atoms, size_t n_atoms,
583 const struct uuid *exclude_uuid,
584 struct uuid **dstsp, size_t *n_dstsp,
585 size_t *allocated_dstsp)
586 {
587 if (type->type != OVSDB_TYPE_UUID || !type->uuid.refTableName) {
588 return;
589 }
590
591 for (size_t i = 0; i < n_atoms; i++) {
592 const struct uuid *uuid = &atoms[i].uuid;
593 if (!uuid_equals(uuid, exclude_uuid)
594 && !array_contains_uuid(uuid, *dstsp, *n_dstsp)) {
595 if (*n_dstsp >= *allocated_dstsp) {
596 *dstsp = x2nrealloc(*dstsp, allocated_dstsp,
597 sizeof **dstsp);
598
599 }
600 (*dstsp)[*n_dstsp] = *uuid;
601 ++*n_dstsp;
602 }
603 }
604 }
605
606 /* Checks for consistency in 'idl''s graph of arcs between database rows. Each
607 * reference from one row to a different row should be reflected as a "struct
608 * ovsdb_idl_arc" between those rows.
609 *
610 * This function is slow, big-O wise, and aborts if it finds an inconsistency,
611 * thus it is only for use in test programs. */
612 void
613 ovsdb_idl_check_consistency(const struct ovsdb_idl *idl)
614 {
615 /* Consistency is broken while a transaction is in progress. */
616 if (!idl->txn) {
617 return;
618 }
619
620 bool ok = true;
621
622 struct uuid *dsts = NULL;
623 size_t allocated_dsts = 0;
624
625 for (size_t i = 0; i < idl->class_->n_tables; i++) {
626 const struct ovsdb_idl_table *table = &idl->tables[i];
627 const struct ovsdb_idl_table_class *class = table->class_;
628
629 const struct ovsdb_idl_row *row;
630 HMAP_FOR_EACH (row, hmap_node, &table->rows) {
631 size_t n_dsts = 0;
632 if (row->new_datum) {
633 size_t n_columns = shash_count(&row->table->columns);
634 for (size_t j = 0; j < n_columns; j++) {
635 const struct ovsdb_type *type = &class->columns[j].type;
636 const struct ovsdb_datum *datum = &row->new_datum[j];
637 add_row_references(&type->key,
638 datum->keys, datum->n, &row->uuid,
639 &dsts, &n_dsts, &allocated_dsts);
640 add_row_references(&type->value,
641 datum->values, datum->n, &row->uuid,
642 &dsts, &n_dsts, &allocated_dsts);
643 }
644 }
645 const struct ovsdb_idl_arc *arc;
646 LIST_FOR_EACH (arc, src_node, &row->src_arcs) {
647 if (!remove_uuid_from_array(&arc->dst->uuid,
648 dsts, &n_dsts)) {
649 VLOG_ERR("unexpected arc from %s row "UUID_FMT" to %s "
650 "row "UUID_FMT,
651 table->class_->name,
652 UUID_ARGS(&row->uuid),
653 arc->dst->table->class_->name,
654 UUID_ARGS(&arc->dst->uuid));
655 ok = false;
656 }
657 }
658 for (size_t j = 0; j < n_dsts; j++) {
659 VLOG_ERR("%s row "UUID_FMT" missing arc to row "UUID_FMT,
660 table->class_->name, UUID_ARGS(&row->uuid),
661 UUID_ARGS(&dsts[j]));
662 ok = false;
663 }
664 }
665 }
666 free(dsts);
667 ovs_assert(ok);
668 }
669
670 static struct json *
671 ovsdb_idl_compose_monitor_request(const struct json *schema_json, void *idl_)
672 {
673 struct ovsdb_idl *idl = idl_;
674
675 struct shash *schema = ovsdb_cs_parse_schema(schema_json);
676 struct json *monitor_requests = json_object_create();
677
678 for (size_t i = 0; i < idl->class_->n_tables; i++) {
679 struct ovsdb_idl_table *table = &idl->tables[i];
680 const struct ovsdb_idl_table_class *tc = table->class_;
681 struct json *monitor_request;
682 const struct sset *table_schema
683 = schema ? shash_find_data(schema, table->class_->name) : NULL;
684
685 struct json *columns
686 = table->need_table ? json_array_create_empty() : NULL;
687 for (size_t j = 0; j < tc->n_columns; j++) {
688 const struct ovsdb_idl_column *column = &tc->columns[j];
689 bool idl_has_column = (table_schema &&
690 sset_contains(table_schema, column->name));
691 if (column->is_synthetic) {
692 if (idl_has_column) {
693 VLOG_WARN("%s table in %s database has synthetic "
694 "column %s", table->class_->name,
695 idl->class_->database, column->name);
696 }
697 } else if (table->modes[j] & OVSDB_IDL_MONITOR) {
698 if (table_schema && !idl_has_column) {
699 VLOG_WARN("%s table in %s database lacks %s column "
700 "(database needs upgrade?)",
701 table->class_->name, idl->class_->database,
702 column->name);
703 continue;
704 }
705 if (!columns) {
706 columns = json_array_create_empty();
707 }
708 json_array_add(columns, json_string_create(column->name));
709 }
710 }
711
712 if (columns) {
713 if (schema && !table_schema) {
714 VLOG_WARN("%s database lacks %s table "
715 "(database needs upgrade?)",
716 idl->class_->database, table->class_->name);
717 json_destroy(columns);
718 continue;
719 }
720
721 monitor_request = json_object_create();
722 json_object_put(monitor_request, "columns", columns);
723 json_object_put(monitor_requests, tc->name,
724 json_array_create_1(monitor_request));
725 }
726 }
727 ovsdb_cs_free_schema(schema);
728
729 return monitor_requests;
730 }
731
732 static struct ovsdb_cs_ops ovsdb_idl_cs_ops = {
733 ovsdb_idl_compose_monitor_request,
734 };
735 \f
736 const struct ovsdb_idl_class *
737 ovsdb_idl_get_class(const struct ovsdb_idl *idl)
738 {
739 return idl->class_;
740 }
741
742 /* Given 'column' in some table in 'class', returns the table's class. */
743 const struct ovsdb_idl_table_class *
744 ovsdb_idl_table_class_from_column(const struct ovsdb_idl_class *class,
745 const struct ovsdb_idl_column *column)
746 {
747 for (size_t i = 0; i < class->n_tables; i++) {
748 const struct ovsdb_idl_table_class *tc = &class->tables[i];
749 if (column >= tc->columns && column < &tc->columns[tc->n_columns]) {
750 return tc;
751 }
752 }
753
754 OVS_NOT_REACHED();
755 }
756
757 /* Given 'column' in some table in 'idl', returns the table. */
758 static struct ovsdb_idl_table *
759 ovsdb_idl_table_from_column(struct ovsdb_idl *idl,
760 const struct ovsdb_idl_column *column)
761 {
762 const struct ovsdb_idl_table_class *tc =
763 ovsdb_idl_table_class_from_column(idl->class_, column);
764 return &idl->tables[tc - idl->class_->tables];
765 }
766
767 static unsigned char *
768 ovsdb_idl_get_mode(struct ovsdb_idl *idl,
769 const struct ovsdb_idl_column *column)
770 {
771 ovs_assert(!idl->change_seqno);
772
773 const struct ovsdb_idl_table *table = ovsdb_idl_table_from_column(idl,
774 column);
775 return &table->modes[column - table->class_->columns];
776 }
777
778 static void
779 ovsdb_idl_set_mode(struct ovsdb_idl *idl,
780 const struct ovsdb_idl_column *column,
781 unsigned char mode)
782 {
783 const struct ovsdb_idl_table *table = ovsdb_idl_table_from_column(idl,
784 column);
785 size_t column_idx = column - table->class_->columns;
786
787 if (table->modes[column_idx] != mode) {
788 *ovsdb_idl_get_mode(idl, column) = mode;
789 }
790 }
791
792 static void
793 add_ref_table(struct ovsdb_idl *idl, const struct ovsdb_base_type *base)
794 {
795 if (base->type == OVSDB_TYPE_UUID && base->uuid.refTableName) {
796 struct ovsdb_idl_table *table;
797
798 table = shash_find_data(&idl->table_by_name, base->uuid.refTableName);
799 if (table) {
800 table->need_table = true;
801 } else {
802 VLOG_WARN("%s IDL class missing referenced table %s",
803 idl->class_->database, base->uuid.refTableName);
804 }
805 }
806 }
807
808 /* Turns on OVSDB_IDL_MONITOR and OVSDB_IDL_ALERT for 'column' in 'idl'. Also
809 * ensures that any tables referenced by 'column' will be replicated, even if
810 * no columns in that table are selected for replication (see
811 * ovsdb_idl_add_table() for more information).
812 *
813 * This function is only useful if 'monitor_everything_by_default' was false in
814 * the call to ovsdb_idl_create(). This function should be called between
815 * ovsdb_idl_create() and the first call to ovsdb_idl_run().
816 */
817 void
818 ovsdb_idl_add_column(struct ovsdb_idl *idl,
819 const struct ovsdb_idl_column *column)
820 {
821 ovsdb_idl_set_mode(idl, column, OVSDB_IDL_MONITOR | OVSDB_IDL_ALERT);
822 add_ref_table(idl, &column->type.key);
823 add_ref_table(idl, &column->type.value);
824 }
825
826 /* Ensures that the table with class 'tc' will be replicated on 'idl' even if
827 * no columns are selected for replication. Just the necessary data for table
828 * references will be replicated (the UUID of the rows, for instance), any
829 * columns not selected for replication will remain unreplicated.
830 * This can be useful because it allows 'idl' to keep track of what rows in the
831 * table actually exist, which in turn allows columns that reference the table
832 * to have accurate contents. (The IDL presents the database with references to
833 * rows that do not exist removed.)
834 *
835 * This function is only useful if 'monitor_everything_by_default' was false in
836 * the call to ovsdb_idl_create(). This function should be called between
837 * ovsdb_idl_create() and the first call to ovsdb_idl_run().
838 */
839 void
840 ovsdb_idl_add_table(struct ovsdb_idl *idl,
841 const struct ovsdb_idl_table_class *tc)
842 {
843 for (size_t i = 0; i < idl->class_->n_tables; i++) {
844 struct ovsdb_idl_table *table = &idl->tables[i];
845
846 if (table->class_ == tc) {
847 table->need_table = true;
848 return;
849 }
850 }
851
852 OVS_NOT_REACHED();
853 }
854 \f
855 /* A single clause within an ovsdb_idl_condition. */
856 struct ovsdb_idl_clause {
857 struct hmap_node hmap_node; /* In struct ovsdb_idl_condition. */
858 enum ovsdb_function function; /* Never OVSDB_F_TRUE or OVSDB_F_FALSE. */
859 const struct ovsdb_idl_column *column; /* Must be nonnull. */
860 struct ovsdb_datum arg; /* Has ovsdb_type ->column->type. */
861 };
862
863 static uint32_t
864 ovsdb_idl_clause_hash(const struct ovsdb_idl_clause *clause)
865 {
866 uint32_t hash = hash_pointer(clause->column, clause->function);
867 return ovsdb_datum_hash(&clause->arg, &clause->column->type, hash);
868 }
869
870 static int
871 ovsdb_idl_clause_equals(const struct ovsdb_idl_clause *a,
872 const struct ovsdb_idl_clause *b)
873 {
874 return (a->function == b->function
875 && a->column == b->column
876 && ovsdb_datum_equals(&a->arg, &b->arg, &a->column->type));
877 }
878
879 static struct json *
880 ovsdb_idl_clause_to_json(const struct ovsdb_idl_clause *clause)
881 {
882 const char *function = ovsdb_function_to_string(clause->function);
883 return json_array_create_3(json_string_create(clause->column->name),
884 json_string_create(function),
885 ovsdb_datum_to_json(&clause->arg,
886 &clause->column->type));
887 }
888
889 static void
890 ovsdb_idl_clause_destroy(struct ovsdb_idl_clause *clause)
891 {
892 if (clause) {
893 ovsdb_datum_destroy(&clause->arg, &clause->column->type);
894 free(clause);
895 }
896 }
897 \f
898 /* ovsdb_idl_condition. */
899
900 void
901 ovsdb_idl_condition_init(struct ovsdb_idl_condition *cnd)
902 {
903 hmap_init(&cnd->clauses);
904 cnd->is_true = false;
905 }
906
907 void
908 ovsdb_idl_condition_destroy(struct ovsdb_idl_condition *cond)
909 {
910 if (cond) {
911 ovsdb_idl_condition_clear(cond);
912 hmap_destroy(&cond->clauses);
913 }
914 }
915
916 void
917 ovsdb_idl_condition_clear(struct ovsdb_idl_condition *cond)
918 {
919 struct ovsdb_idl_clause *clause, *next;
920 HMAP_FOR_EACH_SAFE (clause, next, hmap_node, &cond->clauses) {
921 hmap_remove(&cond->clauses, &clause->hmap_node);
922 ovsdb_idl_clause_destroy(clause);
923 }
924 cond->is_true = false;
925 }
926
927 bool
928 ovsdb_idl_condition_is_true(const struct ovsdb_idl_condition *condition)
929 {
930 return condition->is_true;
931 }
932
933 static struct ovsdb_idl_clause *
934 ovsdb_idl_condition_find_clause(const struct ovsdb_idl_condition *condition,
935 const struct ovsdb_idl_clause *target,
936 uint32_t hash)
937 {
938 struct ovsdb_idl_clause *clause;
939 HMAP_FOR_EACH_WITH_HASH (clause, hmap_node, hash, &condition->clauses) {
940 if (ovsdb_idl_clause_equals(clause, target)) {
941 return clause;
942 }
943 }
944 return NULL;
945 }
946
947 static void
948 ovsdb_idl_condition_add_clause__(struct ovsdb_idl_condition *condition,
949 const struct ovsdb_idl_clause *src,
950 uint32_t hash)
951 {
952 struct ovsdb_idl_clause *clause = xmalloc(sizeof *clause);
953 clause->function = src->function;
954 clause->column = src->column;
955 ovsdb_datum_clone(&clause->arg, &src->arg, &src->column->type);
956 hmap_insert(&condition->clauses, &clause->hmap_node, hash);
957 }
958
959 /* Adds a clause to the condition for replicating the table with class 'tc' in
960 * 'idl'.
961 *
962 * The IDL replicates only rows in a table that satisfy at least one clause in
963 * the table's condition. The default condition for a table has a single
964 * clause with function OVSDB_F_TRUE, so that the IDL replicates all rows in
965 * the table. When the IDL client replaces the default condition by one of its
966 * own, the condition can have any number of clauses. If it has no conditions,
967 * then no rows are replicated.
968 *
969 * Two distinct of clauses can usefully be added:
970 *
971 * - A 'function' of OVSDB_F_TRUE. A "true" clause causes every row to be
972 * replicated, regardless of whether other clauses exist. 'column' and
973 * 'arg' are ignored.
974 *
975 * - Binary 'functions' add a clause of the form "<column> <function>
976 * <arg>", e.g. "column == 5" or "column <= 10". In this case, 'arg' must
977 * have a type that is compatible with 'column'.
978 */
979 void
980 ovsdb_idl_condition_add_clause(struct ovsdb_idl_condition *condition,
981 enum ovsdb_function function,
982 const struct ovsdb_idl_column *column,
983 const struct ovsdb_datum *arg)
984 {
985 if (condition->is_true) {
986 /* Adding a clause to an always-true condition has no effect. */
987 } else if (function == OVSDB_F_TRUE) {
988 ovsdb_idl_condition_add_clause_true(condition);
989 } else if (function == OVSDB_F_FALSE) {
990 /* Adding a "false" clause never has any effect. */
991 } else {
992 struct ovsdb_idl_clause clause = {
993 .function = function,
994 .column = column,
995 .arg = *arg,
996 };
997 uint32_t hash = ovsdb_idl_clause_hash(&clause);
998 if (!ovsdb_idl_condition_find_clause(condition, &clause, hash)) {
999 ovsdb_idl_condition_add_clause__(condition, &clause, hash);
1000 }
1001 }
1002 }
1003
1004 void
1005 ovsdb_idl_condition_add_clause_true(struct ovsdb_idl_condition *condition)
1006 {
1007 if (!condition->is_true) {
1008 ovsdb_idl_condition_clear(condition);
1009 condition->is_true = true;
1010 }
1011 }
1012
1013 static struct json *
1014 ovsdb_idl_condition_to_json(const struct ovsdb_idl_condition *cnd)
1015 {
1016 if (cnd->is_true) {
1017 return NULL;
1018 }
1019
1020 size_t n = hmap_count(&cnd->clauses);
1021 if (!n) {
1022 return json_array_create_1(json_boolean_create(false));
1023 }
1024
1025 struct json **clauses = xmalloc(n * sizeof *clauses);
1026 const struct ovsdb_idl_clause *clause;
1027 size_t i = 0;
1028 HMAP_FOR_EACH (clause, hmap_node, &cnd->clauses) {
1029 clauses[i++] = ovsdb_idl_clause_to_json(clause);
1030 }
1031 ovs_assert(i == n);
1032 return json_array_create(clauses, n);
1033 }
1034
1035 /* Sets the replication condition for 'tc' in 'idl' to 'condition' and
1036 * arranges to send the new condition to the database server.
1037 *
1038 * Return the next conditional update sequence number. When this
1039 * value and ovsdb_idl_get_condition_seqno() matches, the 'idl'
1040 * contains rows that match the 'condition'. */
1041 unsigned int
1042 ovsdb_idl_set_condition(struct ovsdb_idl *idl,
1043 const struct ovsdb_idl_table_class *tc,
1044 const struct ovsdb_idl_condition *condition)
1045 {
1046 struct json *cond_json = ovsdb_idl_condition_to_json(condition);
1047 unsigned int seqno = ovsdb_cs_set_condition(idl->cs, tc->name, cond_json);
1048 json_destroy(cond_json);
1049 return seqno;
1050 }
1051
1052 /* Turns off OVSDB_IDL_ALERT and OVSDB_IDL_TRACK for 'column' in 'idl'.
1053 *
1054 * This function should be called between ovsdb_idl_create() and the first call
1055 * to ovsdb_idl_run().
1056 */
1057 void
1058 ovsdb_idl_omit_alert(struct ovsdb_idl *idl,
1059 const struct ovsdb_idl_column *column)
1060 {
1061 *ovsdb_idl_get_mode(idl, column) &= ~(OVSDB_IDL_ALERT | OVSDB_IDL_TRACK);
1062 }
1063
1064 /* Sets the mode for 'column' in 'idl' to 0. See the big comment above
1065 * OVSDB_IDL_MONITOR for details.
1066 *
1067 * This function should be called between ovsdb_idl_create() and the first call
1068 * to ovsdb_idl_run().
1069 */
1070 void
1071 ovsdb_idl_omit(struct ovsdb_idl *idl, const struct ovsdb_idl_column *column)
1072 {
1073 *ovsdb_idl_get_mode(idl, column) = 0;
1074 }
1075
1076 /* Returns the most recent IDL change sequence number that caused a
1077 * insert, modify or delete update to the table with class 'table_class'.
1078 */
1079 unsigned int
1080 ovsdb_idl_table_get_seqno(const struct ovsdb_idl *idl,
1081 const struct ovsdb_idl_table_class *table_class)
1082 {
1083 struct ovsdb_idl_table *table
1084 = ovsdb_idl_table_from_class(idl, table_class);
1085 unsigned int max_seqno = table->change_seqno[OVSDB_IDL_CHANGE_INSERT];
1086
1087 if (max_seqno < table->change_seqno[OVSDB_IDL_CHANGE_MODIFY]) {
1088 max_seqno = table->change_seqno[OVSDB_IDL_CHANGE_MODIFY];
1089 }
1090 if (max_seqno < table->change_seqno[OVSDB_IDL_CHANGE_DELETE]) {
1091 max_seqno = table->change_seqno[OVSDB_IDL_CHANGE_DELETE];
1092 }
1093 return max_seqno;
1094 }
1095
1096 /* For each row that contains tracked columns, IDL stores the most
1097 * recent IDL change sequence numbers associateed with insert, modify
1098 * and delete updates to the table.
1099 */
1100 unsigned int
1101 ovsdb_idl_row_get_seqno(const struct ovsdb_idl_row *row,
1102 enum ovsdb_idl_change change)
1103 {
1104 return row->change_seqno[change];
1105 }
1106
1107 /* Turns on OVSDB_IDL_TRACK for 'column' in 'idl', ensuring that
1108 * all rows whose 'column' is modified are traced. Similarly, insert
1109 * or delete of rows having 'column' are tracked. Clients are able
1110 * to retrive the tracked rows with the ovsdb_idl_track_get_*()
1111 * functions.
1112 *
1113 * This function should be called between ovsdb_idl_create() and
1114 * the first call to ovsdb_idl_run(). The column to be tracked
1115 * should have OVSDB_IDL_ALERT turned on.
1116 */
1117 void
1118 ovsdb_idl_track_add_column(struct ovsdb_idl *idl,
1119 const struct ovsdb_idl_column *column)
1120 {
1121 if (!(*ovsdb_idl_get_mode(idl, column) & OVSDB_IDL_ALERT)) {
1122 ovsdb_idl_add_column(idl, column);
1123 }
1124 *ovsdb_idl_get_mode(idl, column) |= OVSDB_IDL_TRACK;
1125 }
1126
1127 void
1128 ovsdb_idl_track_add_all(struct ovsdb_idl *idl)
1129 {
1130 size_t i, j;
1131
1132 for (i = 0; i < idl->class_->n_tables; i++) {
1133 const struct ovsdb_idl_table_class *tc = &idl->class_->tables[i];
1134
1135 for (j = 0; j < tc->n_columns; j++) {
1136 const struct ovsdb_idl_column *column = &tc->columns[j];
1137 ovsdb_idl_track_add_column(idl, column);
1138 }
1139 }
1140 }
1141
1142 /* Returns true if 'table' has any tracked column. */
1143 static bool
1144 ovsdb_idl_track_is_set(struct ovsdb_idl_table *table)
1145 {
1146 size_t i;
1147
1148 for (i = 0; i < table->class_->n_columns; i++) {
1149 if (table->modes[i] & OVSDB_IDL_TRACK) {
1150 return true;
1151 }
1152 }
1153 return false;
1154 }
1155
1156 /* Returns the first tracked row in table with class 'table_class'
1157 * for the specified 'idl'. Returns NULL if there are no tracked rows.
1158 * Pure orphan rows, i.e. rows that never had any datum, are skipped. */
1159 const struct ovsdb_idl_row *
1160 ovsdb_idl_track_get_first(const struct ovsdb_idl *idl,
1161 const struct ovsdb_idl_table_class *table_class)
1162 {
1163 struct ovsdb_idl_table *table
1164 = ovsdb_idl_table_from_class(idl, table_class);
1165 struct ovsdb_idl_row *row;
1166
1167 LIST_FOR_EACH (row, track_node, &table->track_list) {
1168 if (!ovsdb_idl_row_is_orphan(row) || row->tracked_old_datum) {
1169 return row;
1170 }
1171 }
1172 return NULL;
1173 }
1174
1175 /* Returns the next tracked row in table after the specified 'row'
1176 * (in no particular order). Returns NULL if there are no tracked rows.
1177 * Pure orphan rows, i.e. rows that never had any datum, are skipped. */
1178 const struct ovsdb_idl_row *
1179 ovsdb_idl_track_get_next(const struct ovsdb_idl_row *row)
1180 {
1181 struct ovsdb_idl_table *table = row->table;
1182
1183 LIST_FOR_EACH_CONTINUE (row, track_node, &table->track_list) {
1184 if (!ovsdb_idl_row_is_orphan(row) || row->tracked_old_datum) {
1185 return row;
1186 }
1187 }
1188 return NULL;
1189 }
1190
1191 /* Returns true if a tracked 'column' in 'row' was updated by IDL, false
1192 * otherwise. The tracking data is cleared by ovsdb_idl_track_clear()
1193 *
1194 * Function returns false if 'column' is not tracked (see
1195 * ovsdb_idl_track_add_column()).
1196 */
1197 bool
1198 ovsdb_idl_track_is_updated(const struct ovsdb_idl_row *row,
1199 const struct ovsdb_idl_column *column)
1200 {
1201 const struct ovsdb_idl_table_class *class;
1202 size_t column_idx;
1203
1204 class = row->table->class_;
1205 column_idx = column - class->columns;
1206
1207 if (row->updated && bitmap_is_set(row->updated, column_idx)) {
1208 return true;
1209 } else {
1210 return false;
1211 }
1212 }
1213
1214 static void
1215 ovsdb_idl_track_clear__(struct ovsdb_idl *idl, bool flush_all)
1216 {
1217 size_t i;
1218
1219 for (i = 0; i < idl->class_->n_tables; i++) {
1220 struct ovsdb_idl_table *table = &idl->tables[i];
1221
1222 if (!ovs_list_is_empty(&table->track_list)) {
1223 struct ovsdb_idl_row *row, *next;
1224
1225 LIST_FOR_EACH_SAFE(row, next, track_node, &table->track_list) {
1226 if (row->updated) {
1227 free(row->updated);
1228 row->updated = NULL;
1229 }
1230
1231 row->change_seqno[OVSDB_IDL_CHANGE_INSERT] =
1232 row->change_seqno[OVSDB_IDL_CHANGE_MODIFY] =
1233 row->change_seqno[OVSDB_IDL_CHANGE_DELETE] = 0;
1234
1235 ovs_list_remove(&row->track_node);
1236 ovs_list_init(&row->track_node);
1237 if (ovsdb_idl_row_is_orphan(row)) {
1238 ovsdb_idl_row_unparse(row);
1239 if (row->tracked_old_datum) {
1240 const struct ovsdb_idl_table_class *class =
1241 row->table->class_;
1242 for (size_t c = 0; c < class->n_columns; c++) {
1243 ovsdb_datum_destroy(&row->tracked_old_datum[c],
1244 &class->columns[c].type);
1245 }
1246 free(row->tracked_old_datum);
1247 row->tracked_old_datum = NULL;
1248 }
1249
1250 /* Rows that were reused as orphan after being processed
1251 * for deletion are still in the table hmap and will be
1252 * cleaned up when their src arcs are removed. These rows
1253 * will not be reported anymore as "deleted" to IDL
1254 * clients.
1255 *
1256 * The exception is when 'destroy' is explicitly set to
1257 * 'true' which usually happens when the complete IDL
1258 * contents are being flushed.
1259 */
1260 if (flush_all || ovs_list_is_empty(&row->dst_arcs)) {
1261 free(row);
1262 }
1263 }
1264 }
1265 }
1266 }
1267 }
1268
1269 /* Flushes the tracked rows. Client calls this function after calling
1270 * ovsdb_idl_run() and read all tracked rows with the ovsdb_idl_track_get_*()
1271 * functions. This is usually done at the end of the client's processing
1272 * loop when it is ready to do ovsdb_idl_run() again.
1273 */
1274 void
1275 ovsdb_idl_track_clear(struct ovsdb_idl *idl)
1276 {
1277 ovsdb_idl_track_clear__(idl, false);
1278 }
1279 \f
1280 static void
1281 log_parse_update_error(struct ovsdb_error *error)
1282 {
1283 if (!VLOG_DROP_WARN(&syntax_rl)) {
1284 char *s = ovsdb_error_to_string(error);
1285 VLOG_WARN_RL(&syntax_rl, "%s", s);
1286 free(s);
1287 }
1288 ovsdb_error_destroy(error);
1289 }
1290
1291 static struct ovsdb_error *
1292 ovsdb_idl_parse_update__(struct ovsdb_idl *idl,
1293 const struct ovsdb_cs_db_update *du)
1294 {
1295 for (size_t i = 0; i < du->n; i++) {
1296 const struct ovsdb_cs_table_update *tu = &du->table_updates[i];
1297
1298 struct ovsdb_idl_table *table = shash_find_data(&idl->table_by_name,
1299 tu->table_name);
1300 if (!table) {
1301 return ovsdb_syntax_error(
1302 NULL, NULL, "update to unknown table \"%s\"", tu->table_name);
1303 }
1304
1305 for (size_t j = 0; j < tu->n; j++) {
1306 const struct ovsdb_cs_row_update *ru = &tu->row_updates[j];
1307 switch (ovsdb_idl_process_update(table, ru)) {
1308 case OVSDB_IDL_UPDATE_DB_CHANGED:
1309 idl->change_seqno++;
1310 break;
1311 case OVSDB_IDL_UPDATE_NO_CHANGES:
1312 break;
1313 case OVSDB_IDL_UPDATE_INCONSISTENT:
1314 ovsdb_cs_flag_inconsistency(idl->cs);
1315 return ovsdb_error(NULL,
1316 "row update received for inconsistent "
1317 "IDL: reconnecting IDL and resync all "
1318 "data");
1319 }
1320 }
1321 }
1322
1323 return NULL;
1324 }
1325
1326 static void
1327 ovsdb_idl_parse_update(struct ovsdb_idl *idl,
1328 const struct ovsdb_cs_update_event *update)
1329 {
1330 if (update->monitor_reply) {
1331 /* XXX This isn't semantically required, because we only need to
1332 * increment change_seqno if there's a real change, which we'll do
1333 * below, but older versions of the IDL always incremented change_seqno
1334 * when a monitor reply was received and if we don't do it then tests
1335 * will fail. */
1336 idl->change_seqno++;
1337 }
1338
1339 struct ovsdb_cs_db_update *du;
1340 struct ovsdb_error *error = ovsdb_cs_parse_db_update(
1341 update->table_updates, update->version, &du);
1342 if (!error) {
1343 if (update->clear) {
1344 ovsdb_idl_clear(idl);
1345 }
1346 error = ovsdb_idl_parse_update__(idl, du);
1347 }
1348 ovsdb_cs_db_update_destroy(du);
1349 if (error) {
1350 log_parse_update_error(error);
1351 }
1352 }
1353
1354 static struct ovsdb_idl_row *
1355 ovsdb_idl_get_row(struct ovsdb_idl_table *table, const struct uuid *uuid)
1356 {
1357 struct ovsdb_idl_row *row;
1358
1359 HMAP_FOR_EACH_WITH_HASH (row, hmap_node, uuid_hash(uuid), &table->rows) {
1360 if (uuid_equals(&row->uuid, uuid)) {
1361 return row;
1362 }
1363 }
1364 return NULL;
1365 }
1366
1367 /* Returns OVSDB_IDL_UPDATE_DB_CHANGED if a column with mode
1368 * OVSDB_IDL_MODE_RW changed.
1369 *
1370 * Some IDL inconsistencies can be detected when processing updates:
1371 * - trying to insert an already existing row
1372 * - trying to update a missing row
1373 * - trying to delete a non existent row
1374 *
1375 * In such cases OVSDB_IDL_UPDATE_INCONSISTENT is returned.
1376 * Even though the IDL client could recover, it's best to report the
1377 * inconsistent state because the state the server is in is unknown so the
1378 * safest thing to do is to retry (potentially connecting to a new server).
1379 *
1380 * Returns OVSDB_IDL_UPDATE_NO_CHANGES otherwise.
1381 */
1382 static enum update_result
1383 ovsdb_idl_process_update(struct ovsdb_idl_table *table,
1384 const struct ovsdb_cs_row_update *ru)
1385 {
1386 const struct uuid *uuid = &ru->row_uuid;
1387 struct ovsdb_idl_row *row = ovsdb_idl_get_row(table, uuid);
1388
1389 switch (ru->type) {
1390 case OVSDB_CS_ROW_DELETE:
1391 if (row && !ovsdb_idl_row_is_orphan(row)) {
1392 /* XXX perhaps we should check the 'old' values? */
1393 ovsdb_idl_delete_row(row);
1394 } else {
1395 VLOG_ERR_RL(&semantic_rl, "cannot delete missing row "UUID_FMT" "
1396 "from table %s",
1397 UUID_ARGS(uuid), table->class_->name);
1398 return OVSDB_IDL_UPDATE_INCONSISTENT;
1399 }
1400 break;
1401
1402 case OVSDB_CS_ROW_INSERT:
1403 if (!row) {
1404 ovsdb_idl_insert_row(ovsdb_idl_row_create(table, uuid),
1405 ru->columns);
1406 } else if (ovsdb_idl_row_is_orphan(row)) {
1407 ovsdb_idl_insert_row(row, ru->columns);
1408 } else {
1409 VLOG_ERR_RL(&semantic_rl, "cannot add existing row "UUID_FMT" to "
1410 "table %s", UUID_ARGS(uuid), table->class_->name);
1411 return OVSDB_IDL_UPDATE_INCONSISTENT;
1412 }
1413 break;
1414
1415 case OVSDB_CS_ROW_UPDATE:
1416 case OVSDB_CS_ROW_XOR:
1417 if (row) {
1418 if (!ovsdb_idl_row_is_orphan(row)) {
1419 return ovsdb_idl_modify_row(row, ru->columns,
1420 ru->type == OVSDB_CS_ROW_XOR)
1421 ? OVSDB_IDL_UPDATE_DB_CHANGED
1422 : OVSDB_IDL_UPDATE_NO_CHANGES;
1423 } else {
1424 VLOG_ERR_RL(&semantic_rl, "cannot modify missing but "
1425 "referenced row "UUID_FMT" in table %s",
1426 UUID_ARGS(uuid), table->class_->name);
1427 return OVSDB_IDL_UPDATE_INCONSISTENT;
1428 }
1429 } else {
1430 VLOG_ERR_RL(&semantic_rl, "cannot modify missing row "UUID_FMT" "
1431 "in table %s", UUID_ARGS(uuid), table->class_->name);
1432 return OVSDB_IDL_UPDATE_INCONSISTENT;
1433 }
1434 break;
1435
1436 default:
1437 OVS_NOT_REACHED();
1438 }
1439
1440 return OVSDB_IDL_UPDATE_DB_CHANGED;
1441 }
1442
1443 /* Recursively add rows to tracked change lists for all rows that reference
1444 'row'. */
1445 static void
1446 add_tracked_change_for_references(struct ovsdb_idl_row *row)
1447 {
1448 const struct ovsdb_idl_arc *arc;
1449 LIST_FOR_EACH (arc, dst_node, &row->dst_arcs) {
1450 struct ovsdb_idl_row *ref = arc->src;
1451
1452 if (ovs_list_is_empty(&ref->track_node) &&
1453 ovsdb_idl_track_is_set(ref->table)) {
1454 ovs_list_push_back(&ref->table->track_list,
1455 &ref->track_node);
1456
1457 ref->change_seqno[OVSDB_IDL_CHANGE_MODIFY]
1458 = ref->table->change_seqno[OVSDB_IDL_CHANGE_MODIFY]
1459 = ref->table->idl->change_seqno + 1;
1460
1461 add_tracked_change_for_references(ref);
1462 }
1463 }
1464 }
1465
1466
1467 /* Returns true if a column with mode OVSDB_IDL_MODE_RW changed, false
1468 * otherwise.
1469 *
1470 * Change 'row' either with the content of 'row_json' or by apply 'diff'.
1471 * Caller needs to provide either valid 'row_json' or 'diff', but not
1472 * both. */
1473 static bool
1474 ovsdb_idl_row_change(struct ovsdb_idl_row *row, const struct shash *values,
1475 bool xor, enum ovsdb_idl_change change)
1476 {
1477 struct ovsdb_idl_table *table = row->table;
1478 const struct ovsdb_idl_table_class *class = table->class_;
1479 struct shash_node *node;
1480 bool changed = false;
1481
1482 SHASH_FOR_EACH (node, values) {
1483 const char *column_name = node->name;
1484 const struct ovsdb_idl_column *column;
1485 struct ovsdb_datum datum;
1486 struct ovsdb_error *error;
1487 unsigned int column_idx;
1488 struct ovsdb_datum *old;
1489
1490 column = shash_find_data(&table->columns, column_name);
1491 if (!column) {
1492 VLOG_WARN_RL(&syntax_rl, "unknown column %s updating row "UUID_FMT,
1493 column_name, UUID_ARGS(&row->uuid));
1494 continue;
1495 }
1496
1497 column_idx = column - table->class_->columns;
1498 old = &row->old_datum[column_idx];
1499
1500 error = NULL;
1501 if (xor) {
1502 struct ovsdb_datum diff;
1503
1504 error = ovsdb_transient_datum_from_json(&diff, &column->type,
1505 node->data);
1506 if (!error) {
1507 error = ovsdb_datum_apply_diff(&datum, old, &diff,
1508 &column->type);
1509 ovsdb_datum_destroy(&diff, &column->type);
1510 }
1511 } else {
1512 error = ovsdb_datum_from_json(&datum, &column->type, node->data,
1513 NULL);
1514 }
1515
1516 if (!error) {
1517 if (!ovsdb_datum_equals(old, &datum, &column->type)) {
1518 ovsdb_datum_swap(old, &datum);
1519 if (table->modes[column_idx] & OVSDB_IDL_ALERT) {
1520 changed = true;
1521 row->change_seqno[change]
1522 = row->table->change_seqno[change]
1523 = row->table->idl->change_seqno + 1;
1524
1525 if (table->modes[column_idx] & OVSDB_IDL_TRACK) {
1526 if (ovs_list_is_empty(&row->track_node) &&
1527 ovsdb_idl_track_is_set(row->table)) {
1528 ovs_list_push_back(&row->table->track_list,
1529 &row->track_node);
1530 }
1531
1532 add_tracked_change_for_references(row);
1533 if (!row->updated) {
1534 row->updated = bitmap_allocate(class->n_columns);
1535 }
1536 bitmap_set1(row->updated, column_idx);
1537 }
1538 }
1539 } else {
1540 /* Didn't really change but the OVSDB monitor protocol always
1541 * includes every value in a row. */
1542 }
1543
1544 ovsdb_datum_destroy(&datum, &column->type);
1545 } else {
1546 char *s = ovsdb_error_to_string_free(error);
1547 VLOG_WARN_RL(&syntax_rl, "error parsing column %s in row "UUID_FMT
1548 " in table %s: %s", column_name,
1549 UUID_ARGS(&row->uuid), table->class_->name, s);
1550 free(s);
1551 }
1552 }
1553 return changed;
1554 }
1555
1556 /* When a row A refers to row B through a column with a "refTable" constraint,
1557 * but row B does not exist, row B is called an "orphan row". Orphan rows
1558 * should not persist, because the database enforces referential integrity, but
1559 * they can appear transiently as changes from the database are received (the
1560 * database doesn't try to topologically sort them and circular references mean
1561 * it isn't always possible anyhow).
1562 *
1563 * This function returns true if 'row' is an orphan row, otherwise false.
1564 */
1565 static bool
1566 ovsdb_idl_row_is_orphan(const struct ovsdb_idl_row *row)
1567 {
1568 return !row->old_datum && !row->new_datum;
1569 }
1570
1571 /* Returns true if 'row' is conceptually part of the database as modified by
1572 * the current transaction (if any), false otherwise.
1573 *
1574 * This function will return true if 'row' is not an orphan (see the comment on
1575 * ovsdb_idl_row_is_orphan()) and:
1576 *
1577 * - 'row' exists in the database and has not been deleted within the
1578 * current transaction (if any).
1579 *
1580 * - 'row' was inserted within the current transaction and has not been
1581 * deleted. (In the latter case you should not have passed 'row' in at
1582 * all, because ovsdb_idl_txn_delete() freed it.)
1583 *
1584 * This function will return false if 'row' is an orphan or if 'row' was
1585 * deleted within the current transaction.
1586 */
1587 static bool
1588 ovsdb_idl_row_exists(const struct ovsdb_idl_row *row)
1589 {
1590 return row->new_datum != NULL;
1591 }
1592
1593 static void
1594 ovsdb_idl_row_parse(struct ovsdb_idl_row *row)
1595 {
1596 const struct ovsdb_idl_table_class *class = row->table->class_;
1597 size_t i;
1598
1599 if (row->parsed) {
1600 ovsdb_idl_row_unparse(row);
1601 }
1602 for (i = 0; i < class->n_columns; i++) {
1603 const struct ovsdb_idl_column *c = &class->columns[i];
1604 (c->parse)(row, &row->old_datum[i]);
1605 }
1606 row->parsed = true;
1607 }
1608
1609 static void
1610 ovsdb_idl_row_unparse(struct ovsdb_idl_row *row)
1611 {
1612 const struct ovsdb_idl_table_class *class = row->table->class_;
1613 size_t i;
1614
1615 if (!row->parsed) {
1616 return;
1617 }
1618 for (i = 0; i < class->n_columns; i++) {
1619 const struct ovsdb_idl_column *c = &class->columns[i];
1620 (c->unparse)(row);
1621 }
1622 row->parsed = false;
1623 }
1624 \f
1625 /* The OVSDB-IDL Compound Indexes feature allows for the creation of custom
1626 * table indexes over one or more columns in the IDL. These indexes provide
1627 * the ability to retrieve rows matching a particular search criteria and to
1628 * iterate over a subset of rows in a defined order.
1629 */
1630
1631 /* Generic comparator that can compare each index, using the custom
1632 * configuration (an struct ovsdb_idl_index) passed to it.
1633 * Not intended for direct usage.
1634 */
1635 static int
1636 ovsdb_idl_index_generic_comparer(const void *a,
1637 const void *b, const void *conf)
1638 {
1639 const struct ovsdb_idl_column *column;
1640 const struct ovsdb_idl_index *index;
1641 size_t i;
1642
1643 index = CONST_CAST(struct ovsdb_idl_index *, conf);
1644
1645 if (a == b) {
1646 return 0;
1647 }
1648
1649 for (i = 0; i < index->n_columns; i++) {
1650 int val;
1651 if (index->columns[i].comparer) {
1652 val = index->columns[i].comparer(a, b);
1653 } else {
1654 column = index->columns[i].column;
1655 const struct ovsdb_idl_row *row_a, *row_b;
1656 row_a = CONST_CAST(struct ovsdb_idl_row *, a);
1657 row_b = CONST_CAST(struct ovsdb_idl_row *, b);
1658 const struct ovsdb_datum *datum_a, *datum_b;
1659 datum_a = ovsdb_idl_read(row_a, column);
1660 datum_b = ovsdb_idl_read(row_b, column);
1661 val = ovsdb_datum_compare_3way(datum_a, datum_b, &column->type);
1662 }
1663
1664 if (val) {
1665 return index->columns[i].order == OVSDB_INDEX_ASC ? val : -val;
1666 }
1667 }
1668
1669 /* If ins_del is true then a row is being inserted into or deleted from
1670 * the index list. In this case, we augment the search key with
1671 * additional values (row UUID and memory address) to create a unique
1672 * search key in order to locate the correct entry efficiently and to
1673 * ensure that the correct entry is deleted in the case of a "delete"
1674 * operation.
1675 */
1676 if (index->ins_del) {
1677 const struct ovsdb_idl_row *row_a, *row_b;
1678
1679 row_a = (const struct ovsdb_idl_row *) a;
1680 row_b = (const struct ovsdb_idl_row *) b;
1681 int value = uuid_compare_3way(&row_a->uuid, &row_b->uuid);
1682
1683 return value ? value : (a < b) - (a > b);
1684 } else {
1685 return 0;
1686 }
1687 }
1688
1689 /* Creates a new index for the given 'idl' and with the 'n' specified
1690 * 'columns'.
1691 *
1692 * All indexes must be created before the first call to ovsdb_idl_run(). */
1693 struct ovsdb_idl_index *
1694 ovsdb_idl_index_create(struct ovsdb_idl *idl,
1695 const struct ovsdb_idl_index_column *columns,
1696 size_t n)
1697 {
1698 ovs_assert(n > 0);
1699
1700 struct ovsdb_idl_index *index = xzalloc(sizeof *index);
1701
1702 index->table = ovsdb_idl_table_from_column(idl, columns[0].column);
1703 for (size_t i = 0; i < n; i++) {
1704 const struct ovsdb_idl_index_column *c = &columns[i];
1705 ovs_assert(ovsdb_idl_table_from_column(idl,
1706 c->column) == index->table);
1707 ovs_assert(*ovsdb_idl_get_mode(idl, c->column) & OVSDB_IDL_MONITOR);
1708 }
1709
1710 index->columns = xmemdup(columns, n * sizeof *columns);
1711 index->n_columns = n;
1712 index->skiplist = skiplist_create(ovsdb_idl_index_generic_comparer, index);
1713
1714 ovs_list_push_back(&index->table->indexes, &index->node);
1715
1716 return index;
1717 }
1718
1719 struct ovsdb_idl_index *
1720 ovsdb_idl_index_create1(struct ovsdb_idl *idl,
1721 const struct ovsdb_idl_column *column1)
1722 {
1723 const struct ovsdb_idl_index_column columns[] = {
1724 { .column = column1 },
1725 };
1726 return ovsdb_idl_index_create(idl, columns, ARRAY_SIZE(columns));
1727 }
1728
1729 struct ovsdb_idl_index *
1730 ovsdb_idl_index_create2(struct ovsdb_idl *idl,
1731 const struct ovsdb_idl_column *column1,
1732 const struct ovsdb_idl_column *column2)
1733 {
1734 const struct ovsdb_idl_index_column columns[] = {
1735 { .column = column1 },
1736 { .column = column2 },
1737 };
1738 return ovsdb_idl_index_create(idl, columns, ARRAY_SIZE(columns));
1739 }
1740
1741 static void
1742 ovsdb_idl_destroy_indexes(struct ovsdb_idl_table *table)
1743 {
1744 struct ovsdb_idl_index *index, *next;
1745 LIST_FOR_EACH_SAFE (index, next, node, &table->indexes) {
1746 skiplist_destroy(index->skiplist, NULL);
1747 free(index->columns);
1748 free(index);
1749 }
1750 }
1751
1752 static void
1753 ovsdb_idl_add_to_indexes(const struct ovsdb_idl_row *row)
1754 {
1755 struct ovsdb_idl_table *table = row->table;
1756 struct ovsdb_idl_index *index;
1757 LIST_FOR_EACH (index, node, &table->indexes) {
1758 index->ins_del = true;
1759 skiplist_insert(index->skiplist, row);
1760 index->ins_del = false;
1761 }
1762 }
1763
1764 static void
1765 ovsdb_idl_remove_from_indexes(const struct ovsdb_idl_row *row)
1766 {
1767 struct ovsdb_idl_table *table = row->table;
1768 struct ovsdb_idl_index *index;
1769 LIST_FOR_EACH (index, node, &table->indexes) {
1770 index->ins_del = true;
1771 skiplist_delete(index->skiplist, row);
1772 index->ins_del = false;
1773 }
1774 }
1775
1776 /* Writes a datum in an ovsdb_idl_row, and updates the corresponding field in
1777 * the table record. Not intended for direct usage. */
1778 void
1779 ovsdb_idl_index_write(struct ovsdb_idl_row *const_row,
1780 const struct ovsdb_idl_column *column,
1781 struct ovsdb_datum *datum,
1782 const struct ovsdb_idl_table_class *class)
1783 {
1784 struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, const_row);
1785 size_t column_idx = column - class->columns;
1786
1787 if (bitmap_is_set(row->written, column_idx)) {
1788 free(row->new_datum[column_idx].values);
1789 free(row->new_datum[column_idx].keys);
1790 } else {
1791 bitmap_set1(row->written, column_idx);
1792 }
1793 row->new_datum[column_idx] = *datum;
1794 (column->unparse)(row);
1795 (column->parse)(row, &row->new_datum[column_idx]);
1796 }
1797
1798 /* Magic UUID for index rows */
1799 static const struct uuid index_row_uuid = {
1800 .parts = {0xdeadbeef,
1801 0xdeadbeef,
1802 0xdeadbeef,
1803 0xdeadbeef}};
1804
1805 /* Check if a row is an index row */
1806 static bool
1807 is_index_row(const struct ovsdb_idl_row *row)
1808 {
1809 return uuid_equals(&row->uuid, &index_row_uuid);
1810 }
1811
1812 /* Initializes a row for use in an indexed query.
1813 * Not intended for direct usage.
1814 */
1815 struct ovsdb_idl_row *
1816 ovsdb_idl_index_init_row(struct ovsdb_idl_index *index)
1817 {
1818 const struct ovsdb_idl_table_class *class = index->table->class_;
1819 struct ovsdb_idl_row *row = xzalloc(class->allocation_size);
1820 class->row_init(row);
1821 row->uuid = index_row_uuid;
1822 row->new_datum = xmalloc(class->n_columns * sizeof *row->new_datum);
1823 row->written = bitmap_allocate(class->n_columns);
1824 row->table = index->table;
1825 /* arcs are not used for index row, but it doesn't harm to initialize */
1826 ovs_list_init(&row->src_arcs);
1827 ovs_list_init(&row->dst_arcs);
1828 return row;
1829 }
1830
1831 /* Destroys 'row_' and frees all associated memory. This function is intended
1832 * to be used indirectly through one of the "index_destroy_row" functions
1833 * generated by ovsdb-idlc.
1834 */
1835 void
1836 ovsdb_idl_index_destroy_row(const struct ovsdb_idl_row *row_)
1837 {
1838 struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
1839 const struct ovsdb_idl_table_class *class = row->table->class_;
1840 const struct ovsdb_idl_column *c;
1841 size_t i;
1842
1843 ovs_assert(is_index_row(row_));
1844 ovs_assert(ovs_list_is_empty(&row_->src_arcs));
1845 ovs_assert(ovs_list_is_empty(&row_->dst_arcs));
1846 BITMAP_FOR_EACH_1 (i, class->n_columns, row->written) {
1847 c = &class->columns[i];
1848 (c->unparse) (row);
1849 free(row->new_datum[i].values);
1850 free(row->new_datum[i].keys);
1851 }
1852 free(row->new_datum);
1853 free(row->written);
1854 free(row);
1855 }
1856
1857 struct ovsdb_idl_row *
1858 ovsdb_idl_index_find(struct ovsdb_idl_index *index,
1859 const struct ovsdb_idl_row *target)
1860 {
1861 return skiplist_get_data(skiplist_find(index->skiplist, target));
1862 }
1863
1864 struct ovsdb_idl_cursor
1865 ovsdb_idl_cursor_first(struct ovsdb_idl_index *index)
1866 {
1867 struct skiplist_node *node = skiplist_first(index->skiplist);
1868 return (struct ovsdb_idl_cursor) { index, node };
1869 }
1870
1871 struct ovsdb_idl_cursor
1872 ovsdb_idl_cursor_first_eq(struct ovsdb_idl_index *index,
1873 const struct ovsdb_idl_row *target)
1874 {
1875 struct skiplist_node *node = skiplist_find(index->skiplist, target);
1876 return (struct ovsdb_idl_cursor) { index, node };
1877 }
1878
1879 struct ovsdb_idl_cursor
1880 ovsdb_idl_cursor_first_ge(struct ovsdb_idl_index *index,
1881 const struct ovsdb_idl_row *target)
1882 {
1883 struct skiplist_node *node = (target
1884 ? skiplist_forward_to(index->skiplist,
1885 target)
1886 : skiplist_first(index->skiplist));
1887 return (struct ovsdb_idl_cursor) { index, node };
1888 }
1889
1890 void
1891 ovsdb_idl_cursor_next(struct ovsdb_idl_cursor *cursor)
1892 {
1893 cursor->position = skiplist_next(cursor->position);
1894 }
1895
1896 void
1897 ovsdb_idl_cursor_next_eq(struct ovsdb_idl_cursor *cursor)
1898 {
1899 struct ovsdb_idl_row *data = skiplist_get_data(cursor->position);
1900 struct skiplist_node *next_position = skiplist_next(cursor->position);
1901 struct ovsdb_idl_row *next_data = skiplist_get_data(next_position);
1902 cursor->position = (!ovsdb_idl_index_compare(cursor->index,
1903 data, next_data)
1904 ? next_position : NULL);
1905 }
1906
1907 struct ovsdb_idl_row *
1908 ovsdb_idl_cursor_data(struct ovsdb_idl_cursor *cursor)
1909 {
1910 return skiplist_get_data(cursor->position);
1911 }
1912
1913 /* Returns the result of comparing two rows using the comparison function
1914 * for this index.
1915 * Returns:
1916 * < 0 if a < b
1917 * 0 if a == b
1918 * > 0 if a > b
1919 * When the pointer to either row is NULL, this function considers NULL to be
1920 * greater than any other value, and NULL == NULL.
1921 */
1922 int
1923 ovsdb_idl_index_compare(struct ovsdb_idl_index *index,
1924 const struct ovsdb_idl_row *a,
1925 const struct ovsdb_idl_row *b)
1926 {
1927 if (a && b) {
1928 return ovsdb_idl_index_generic_comparer(a, b, index);
1929 } else if (!a && !b) {
1930 return 0;
1931 } else if (a) {
1932 return -1;
1933 } else {
1934 return 1;
1935 }
1936 }
1937
1938 static void
1939 ovsdb_idl_row_clear_old(struct ovsdb_idl_row *row)
1940 {
1941 ovs_assert(row->old_datum == row->new_datum);
1942 if (!ovsdb_idl_row_is_orphan(row)) {
1943 if (ovsdb_idl_track_is_set(row->table) && !row->tracked_old_datum) {
1944 row->tracked_old_datum = row->old_datum;
1945 } else {
1946 const struct ovsdb_idl_table_class *class = row->table->class_;
1947 size_t i;
1948
1949 for (i = 0; i < class->n_columns; i++) {
1950 ovsdb_datum_destroy(&row->old_datum[i],
1951 &class->columns[i].type);
1952 }
1953 free(row->old_datum);
1954 }
1955 row->old_datum = row->new_datum = NULL;
1956 }
1957 }
1958
1959 static void
1960 ovsdb_idl_row_clear_new(struct ovsdb_idl_row *row)
1961 {
1962 if (row->old_datum != row->new_datum) {
1963 if (row->new_datum) {
1964 const struct ovsdb_idl_table_class *class = row->table->class_;
1965 size_t i;
1966
1967 if (row->written) {
1968 BITMAP_FOR_EACH_1 (i, class->n_columns, row->written) {
1969 ovsdb_datum_destroy(&row->new_datum[i],
1970 &class->columns[i].type);
1971 }
1972 }
1973 free(row->new_datum);
1974 free(row->written);
1975 row->written = NULL;
1976 }
1977 row->new_datum = row->old_datum;
1978 }
1979 }
1980
1981 static void
1982 ovsdb_idl_row_clear_arcs(struct ovsdb_idl_row *row, bool destroy_dsts)
1983 {
1984 struct ovsdb_idl_arc *arc, *next;
1985
1986 /* Delete all forward arcs. If 'destroy_dsts', destroy any orphaned rows
1987 * that this causes to be unreferenced.
1988 */
1989 LIST_FOR_EACH_SAFE (arc, next, src_node, &row->src_arcs) {
1990 ovs_list_remove(&arc->dst_node);
1991 if (destroy_dsts
1992 && ovsdb_idl_row_is_orphan(arc->dst)
1993 && ovs_list_is_empty(&arc->dst->dst_arcs)) {
1994 ovsdb_idl_row_destroy(arc->dst);
1995 }
1996 free(arc);
1997 }
1998 ovs_list_init(&row->src_arcs);
1999 }
2000
2001 /* Force nodes that reference 'row' to reparse. */
2002 static void
2003 ovsdb_idl_row_reparse_backrefs(struct ovsdb_idl_row *row)
2004 {
2005 struct ovsdb_idl_arc *arc, *next;
2006
2007 /* This is trickier than it looks. ovsdb_idl_row_clear_arcs() will destroy
2008 * 'arc', so we need to use the "safe" variant of list traversal. However,
2009 * calling an ovsdb_idl_column's 'parse' function will add an arc
2010 * equivalent to 'arc' to row->arcs. That could be a problem for
2011 * traversal, but it adds it at the beginning of the list to prevent us
2012 * from stumbling upon it again.
2013 *
2014 * (If duplicate arcs were possible then we would need to make sure that
2015 * 'next' didn't also point into 'arc''s destination, but we forbid
2016 * duplicate arcs.) */
2017 LIST_FOR_EACH_SAFE (arc, next, dst_node, &row->dst_arcs) {
2018 struct ovsdb_idl_row *ref = arc->src;
2019
2020 ovsdb_idl_row_unparse(ref);
2021 ovsdb_idl_row_clear_arcs(ref, false);
2022 ovsdb_idl_row_parse(ref);
2023 }
2024 }
2025
2026 static struct ovsdb_idl_row *
2027 ovsdb_idl_row_create__(const struct ovsdb_idl_table_class *class)
2028 {
2029 struct ovsdb_idl_row *row = xzalloc(class->allocation_size);
2030 class->row_init(row);
2031 ovs_list_init(&row->src_arcs);
2032 ovs_list_init(&row->dst_arcs);
2033 hmap_node_nullify(&row->txn_node);
2034 ovs_list_init(&row->track_node);
2035 return row;
2036 }
2037
2038 static struct ovsdb_idl_row *
2039 ovsdb_idl_row_create(struct ovsdb_idl_table *table, const struct uuid *uuid)
2040 {
2041 struct ovsdb_idl_row *row = ovsdb_idl_row_create__(table->class_);
2042 hmap_insert(&table->rows, &row->hmap_node, uuid_hash(uuid));
2043 row->uuid = *uuid;
2044 row->table = table;
2045 row->map_op_written = NULL;
2046 row->map_op_lists = NULL;
2047 row->set_op_written = NULL;
2048 row->set_op_lists = NULL;
2049 return row;
2050 }
2051
2052 static void
2053 ovsdb_idl_row_destroy(struct ovsdb_idl_row *row)
2054 {
2055 if (row) {
2056 ovsdb_idl_row_clear_old(row);
2057 hmap_remove(&row->table->rows, &row->hmap_node);
2058 ovsdb_idl_destroy_all_map_op_lists(row);
2059 ovsdb_idl_destroy_all_set_op_lists(row);
2060 if (ovsdb_idl_track_is_set(row->table)) {
2061 row->change_seqno[OVSDB_IDL_CHANGE_DELETE]
2062 = row->table->change_seqno[OVSDB_IDL_CHANGE_DELETE]
2063 = row->table->idl->change_seqno + 1;
2064 }
2065 if (ovs_list_is_empty(&row->track_node)) {
2066 ovs_list_push_back(&row->table->track_list, &row->track_node);
2067 }
2068 }
2069 }
2070
2071 static void
2072 ovsdb_idl_destroy_all_map_op_lists(struct ovsdb_idl_row *row)
2073 {
2074 if (row->map_op_written) {
2075 /* Clear Map Operation Lists */
2076 size_t idx, n_columns;
2077 const struct ovsdb_idl_column *columns;
2078 const struct ovsdb_type *type;
2079 n_columns = row->table->class_->n_columns;
2080 columns = row->table->class_->columns;
2081 BITMAP_FOR_EACH_1 (idx, n_columns, row->map_op_written) {
2082 type = &columns[idx].type;
2083 map_op_list_destroy(row->map_op_lists[idx], type);
2084 }
2085 free(row->map_op_lists);
2086 bitmap_free(row->map_op_written);
2087 row->map_op_lists = NULL;
2088 row->map_op_written = NULL;
2089 }
2090 }
2091
2092 static void
2093 ovsdb_idl_destroy_all_set_op_lists(struct ovsdb_idl_row *row)
2094 {
2095 if (row->set_op_written) {
2096 /* Clear Set Operation Lists */
2097 size_t idx, n_columns;
2098 const struct ovsdb_idl_column *columns;
2099 const struct ovsdb_type *type;
2100 n_columns = row->table->class_->n_columns;
2101 columns = row->table->class_->columns;
2102 BITMAP_FOR_EACH_1 (idx, n_columns, row->set_op_written) {
2103 type = &columns[idx].type;
2104 set_op_list_destroy(row->set_op_lists[idx], type);
2105 }
2106 free(row->set_op_lists);
2107 bitmap_free(row->set_op_written);
2108 row->set_op_lists = NULL;
2109 row->set_op_written = NULL;
2110 }
2111 }
2112
2113 static void
2114 ovsdb_idl_row_destroy_postprocess(struct ovsdb_idl *idl)
2115 {
2116 for (size_t i = 0; i < idl->class_->n_tables; i++) {
2117 struct ovsdb_idl_table *table = &idl->tables[i];
2118
2119 if (!ovs_list_is_empty(&table->track_list)) {
2120 struct ovsdb_idl_row *row, *next;
2121
2122 LIST_FOR_EACH_SAFE(row, next, track_node, &table->track_list) {
2123 if (!ovsdb_idl_track_is_set(row->table)) {
2124 ovs_list_remove(&row->track_node);
2125 ovsdb_idl_row_unparse(row);
2126 free(row);
2127 }
2128 }
2129 }
2130 }
2131 }
2132
2133 static void
2134 ovsdb_idl_insert_row(struct ovsdb_idl_row *row, const struct shash *data)
2135 {
2136 const struct ovsdb_idl_table_class *class = row->table->class_;
2137 size_t i, datum_size;
2138
2139 ovs_assert(!row->old_datum && !row->new_datum);
2140 datum_size = class->n_columns * sizeof *row->old_datum;
2141 row->old_datum = row->new_datum = xmalloc(datum_size);
2142 for (i = 0; i < class->n_columns; i++) {
2143 ovsdb_datum_init_default(&row->old_datum[i], &class->columns[i].type);
2144 }
2145 ovsdb_idl_row_change(row, data, false, OVSDB_IDL_CHANGE_INSERT);
2146 ovsdb_idl_row_parse(row);
2147
2148 ovsdb_idl_row_reparse_backrefs(row);
2149 ovsdb_idl_add_to_indexes(row);
2150 }
2151
2152 static void
2153 ovsdb_idl_delete_row(struct ovsdb_idl_row *row)
2154 {
2155 ovsdb_idl_remove_from_indexes(row);
2156 ovsdb_idl_row_clear_arcs(row, true);
2157 ovsdb_idl_row_clear_old(row);
2158 if (ovs_list_is_empty(&row->dst_arcs)) {
2159 ovsdb_idl_row_destroy(row);
2160 } else {
2161 ovsdb_idl_row_reparse_backrefs(row);
2162 }
2163 }
2164
2165 /* Returns true if a column with mode OVSDB_IDL_MODE_RW changed, false
2166 * otherwise. */
2167 static bool
2168 ovsdb_idl_modify_row(struct ovsdb_idl_row *row, const struct shash *values,
2169 bool xor)
2170 {
2171 ovsdb_idl_remove_from_indexes(row);
2172 ovsdb_idl_row_unparse(row);
2173 ovsdb_idl_row_clear_arcs(row, true);
2174 bool changed = ovsdb_idl_row_change(row, values, xor,
2175 OVSDB_IDL_CHANGE_MODIFY);
2176 ovsdb_idl_row_parse(row);
2177 ovsdb_idl_add_to_indexes(row);
2178
2179 return changed;
2180 }
2181
2182 static bool
2183 may_add_arc(const struct ovsdb_idl_row *src, const struct ovsdb_idl_row *dst)
2184 {
2185 const struct ovsdb_idl_arc *arc;
2186
2187 /* No self-arcs. */
2188 if (src == dst) {
2189 return false;
2190 }
2191
2192 /* No duplicate arcs.
2193 *
2194 * We only need to test whether the first arc in dst->dst_arcs originates
2195 * at 'src', since we add all of the arcs from a given source in a clump
2196 * (in a single call to ovsdb_idl_row_parse()) and new arcs are always
2197 * added at the front of the dst_arcs list. */
2198 if (ovs_list_is_empty(&dst->dst_arcs)) {
2199 return true;
2200 }
2201 arc = CONTAINER_OF(dst->dst_arcs.next, struct ovsdb_idl_arc, dst_node);
2202 return arc->src != src;
2203 }
2204
2205 static struct ovsdb_idl_table *
2206 ovsdb_idl_table_from_class(const struct ovsdb_idl *idl,
2207 const struct ovsdb_idl_table_class *table_class)
2208 {
2209 ptrdiff_t idx = table_class - idl->class_->tables;
2210 return idx >= 0 && idx < idl->class_->n_tables ? &idl->tables[idx] : NULL;
2211 }
2212
2213 /* Called by ovsdb-idlc generated code. */
2214 struct ovsdb_idl_row *
2215 ovsdb_idl_get_row_arc(struct ovsdb_idl_row *src,
2216 const struct ovsdb_idl_table_class *dst_table_class,
2217 const struct uuid *dst_uuid)
2218 {
2219 struct ovsdb_idl *idl = src->table->idl;
2220 struct ovsdb_idl_table *dst_table;
2221 struct ovsdb_idl_arc *arc;
2222 struct ovsdb_idl_row *dst;
2223
2224 dst_table = ovsdb_idl_table_from_class(idl, dst_table_class);
2225 dst = ovsdb_idl_get_row(dst_table, dst_uuid);
2226 if (idl->txn || is_index_row(src)) {
2227 /* There are two cases we should not update any arcs:
2228 *
2229 * 1. We're being called from ovsdb_idl_txn_write(). We must not update
2230 * any arcs, because the transaction will be backed out at commit or
2231 * abort time and we don't want our graph screwed up.
2232 *
2233 * 2. The row is used as an index for querying purpose only.
2234 *
2235 * In these cases, just return the destination row, if there is one and
2236 * it has not been deleted. */
2237 if (dst && (hmap_node_is_null(&dst->txn_node) || dst->new_datum)) {
2238 return dst;
2239 }
2240 return NULL;
2241 } else {
2242 /* We're being called from some other context. Update the graph. */
2243 if (!dst) {
2244 dst = ovsdb_idl_row_create(dst_table, dst_uuid);
2245 }
2246
2247 /* Add a new arc, if it wouldn't be a self-arc or a duplicate arc. */
2248 if (may_add_arc(src, dst)) {
2249 /* The arc *must* be added at the front of the dst_arcs list. See
2250 * ovsdb_idl_row_reparse_backrefs() for details. */
2251 arc = xmalloc(sizeof *arc);
2252 ovs_list_push_front(&src->src_arcs, &arc->src_node);
2253 ovs_list_push_front(&dst->dst_arcs, &arc->dst_node);
2254 arc->src = src;
2255 arc->dst = dst;
2256 }
2257
2258 return !ovsdb_idl_row_is_orphan(dst) ? dst : NULL;
2259 }
2260 }
2261
2262 /* Searches 'tc''s table in 'idl' for a row with UUID 'uuid'. Returns a
2263 * pointer to the row if there is one, otherwise a null pointer. */
2264 const struct ovsdb_idl_row *
2265 ovsdb_idl_get_row_for_uuid(const struct ovsdb_idl *idl,
2266 const struct ovsdb_idl_table_class *tc,
2267 const struct uuid *uuid)
2268 {
2269 return ovsdb_idl_get_row(ovsdb_idl_table_from_class(idl, tc), uuid);
2270 }
2271
2272 static struct ovsdb_idl_row *
2273 next_real_row(struct ovsdb_idl_table *table, struct hmap_node *node)
2274 {
2275 for (; node; node = hmap_next(&table->rows, node)) {
2276 struct ovsdb_idl_row *row;
2277
2278 row = CONTAINER_OF(node, struct ovsdb_idl_row, hmap_node);
2279 if (ovsdb_idl_row_exists(row)) {
2280 return row;
2281 }
2282 }
2283 return NULL;
2284 }
2285
2286 /* Returns a row in 'table_class''s table in 'idl', or a null pointer if that
2287 * table is empty.
2288 *
2289 * Database tables are internally maintained as hash tables, so adding or
2290 * removing rows while traversing the same table can cause some rows to be
2291 * visited twice or not at apply. */
2292 const struct ovsdb_idl_row *
2293 ovsdb_idl_first_row(const struct ovsdb_idl *idl,
2294 const struct ovsdb_idl_table_class *table_class)
2295 {
2296 struct ovsdb_idl_table *table = ovsdb_idl_table_from_class(idl,
2297 table_class);
2298 return next_real_row(table, hmap_first(&table->rows));
2299 }
2300
2301 /* Returns a row following 'row' within its table, or a null pointer if 'row'
2302 * is the last row in its table. */
2303 const struct ovsdb_idl_row *
2304 ovsdb_idl_next_row(const struct ovsdb_idl_row *row)
2305 {
2306 struct ovsdb_idl_table *table = row->table;
2307
2308 return next_real_row(table, hmap_next(&table->rows, &row->hmap_node));
2309 }
2310
2311 /* Reads and returns the value of 'column' within 'row'. If an ongoing
2312 * transaction has changed 'column''s value, the modified value is returned.
2313 *
2314 * The caller must not modify or free the returned value.
2315 *
2316 * Various kinds of changes can invalidate the returned value: writing to the
2317 * same 'column' in 'row' (e.g. with ovsdb_idl_txn_write()), deleting 'row'
2318 * (e.g. with ovsdb_idl_txn_delete()), or completing an ongoing transaction
2319 * (e.g. with ovsdb_idl_txn_commit() or ovsdb_idl_txn_abort()). If the
2320 * returned value is needed for a long time, it is best to make a copy of it
2321 * with ovsdb_datum_clone(). */
2322 const struct ovsdb_datum *
2323 ovsdb_idl_read(const struct ovsdb_idl_row *row,
2324 const struct ovsdb_idl_column *column)
2325 {
2326 const struct ovsdb_idl_table_class *class;
2327 size_t column_idx;
2328
2329 ovs_assert(!ovsdb_idl_row_is_synthetic(row));
2330
2331 class = row->table->class_;
2332 column_idx = column - class->columns;
2333
2334 ovs_assert(row->new_datum != NULL);
2335 ovs_assert(column_idx < class->n_columns);
2336
2337 if (row->written && bitmap_is_set(row->written, column_idx)) {
2338 return &row->new_datum[column_idx];
2339 } else if (row->old_datum) {
2340 return &row->old_datum[column_idx];
2341 } else {
2342 return ovsdb_datum_default(&column->type);
2343 }
2344 }
2345
2346 /* Same as ovsdb_idl_read(), except that it also asserts that 'column' has key
2347 * type 'key_type' and value type 'value_type'. (Scalar and set types will
2348 * have a value type of OVSDB_TYPE_VOID.)
2349 *
2350 * This is useful in code that "knows" that a particular column has a given
2351 * type, so that it will abort if someone changes the column's type without
2352 * updating the code that uses it. */
2353 const struct ovsdb_datum *
2354 ovsdb_idl_get(const struct ovsdb_idl_row *row,
2355 const struct ovsdb_idl_column *column,
2356 enum ovsdb_atomic_type key_type OVS_UNUSED,
2357 enum ovsdb_atomic_type value_type OVS_UNUSED)
2358 {
2359 ovs_assert(column->type.key.type == key_type);
2360 ovs_assert(column->type.value.type == value_type);
2361
2362 return ovsdb_idl_read(row, column);
2363 }
2364
2365 /* Returns true if the field represented by 'column' in 'row' may be modified,
2366 * false if it is immutable.
2367 *
2368 * Normally, whether a field is mutable is controlled by its column's schema.
2369 * However, an immutable column can be set to any initial value at the time of
2370 * insertion, so if 'row' is a new row (one that is being added as part of the
2371 * current transaction, supposing that a transaction is in progress) then even
2372 * its "immutable" fields are actually mutable. */
2373 bool
2374 ovsdb_idl_is_mutable(const struct ovsdb_idl_row *row,
2375 const struct ovsdb_idl_column *column)
2376 {
2377 return column->is_mutable || (row->new_datum && !row->old_datum);
2378 }
2379
2380 /* Returns false if 'row' was obtained from the IDL, true if it was initialized
2381 * to all-zero-bits by some other entity. If 'row' was set up some other way
2382 * then the return value is indeterminate. */
2383 bool
2384 ovsdb_idl_row_is_synthetic(const struct ovsdb_idl_row *row)
2385 {
2386 return row->table == NULL;
2387 }
2388 \f
2389 /* Transactions. */
2390
2391 static void ovsdb_idl_txn_complete(struct ovsdb_idl_txn *txn,
2392 enum ovsdb_idl_txn_status);
2393
2394 /* Returns a string representation of 'status'. The caller must not modify or
2395 * free the returned string.
2396 *
2397 * The return value is probably useful only for debug log messages and unit
2398 * tests. */
2399 const char *
2400 ovsdb_idl_txn_status_to_string(enum ovsdb_idl_txn_status status)
2401 {
2402 switch (status) {
2403 case TXN_UNCOMMITTED:
2404 return "uncommitted";
2405 case TXN_UNCHANGED:
2406 return "unchanged";
2407 case TXN_INCOMPLETE:
2408 return "incomplete";
2409 case TXN_ABORTED:
2410 return "aborted";
2411 case TXN_SUCCESS:
2412 return "success";
2413 case TXN_TRY_AGAIN:
2414 return "try again";
2415 case TXN_NOT_LOCKED:
2416 return "not locked";
2417 case TXN_ERROR:
2418 return "error";
2419 }
2420 return "<unknown>";
2421 }
2422
2423 /* Starts a new transaction on 'idl'. A given ovsdb_idl may only have a single
2424 * active transaction at a time. See the large comment in ovsdb-idl.h for
2425 * general information on transactions. */
2426 struct ovsdb_idl_txn *
2427 ovsdb_idl_txn_create(struct ovsdb_idl *idl)
2428 {
2429 struct ovsdb_idl_txn *txn;
2430
2431 ovs_assert(!idl->txn);
2432 idl->txn = txn = xmalloc(sizeof *txn);
2433 txn->request_id = NULL;
2434 txn->idl = idl;
2435 hmap_init(&txn->txn_rows);
2436 txn->status = TXN_UNCOMMITTED;
2437 txn->error = NULL;
2438 txn->dry_run = false;
2439 ds_init(&txn->comment);
2440
2441 txn->inc_table = NULL;
2442 txn->inc_column = NULL;
2443
2444 hmap_init(&txn->inserted_rows);
2445
2446 return txn;
2447 }
2448
2449 /* Appends 's', which is treated as a printf()-type format string, to the
2450 * comments that will be passed to the OVSDB server when 'txn' is committed.
2451 * (The comment will be committed to the OVSDB log, which "ovsdb-tool
2452 * show-log" can print in a relatively human-readable form.) */
2453 void
2454 ovsdb_idl_txn_add_comment(struct ovsdb_idl_txn *txn, const char *s, ...)
2455 {
2456 va_list args;
2457
2458 if (txn->comment.length) {
2459 ds_put_char(&txn->comment, '\n');
2460 }
2461
2462 va_start(args, s);
2463 ds_put_format_valist(&txn->comment, s, args);
2464 va_end(args);
2465 }
2466
2467 /* Marks 'txn' as a transaction that will not actually modify the database. In
2468 * almost every way, the transaction is treated like other transactions. It
2469 * must be committed or aborted like other transactions, it will be sent to the
2470 * database server like other transactions, and so on. The only difference is
2471 * that the operations sent to the database server will include, as the last
2472 * step, an "abort" operation, so that any changes made by the transaction will
2473 * not actually take effect. */
2474 void
2475 ovsdb_idl_txn_set_dry_run(struct ovsdb_idl_txn *txn)
2476 {
2477 txn->dry_run = true;
2478 }
2479
2480 /* Causes 'txn', when committed, to increment the value of 'column' within
2481 * 'row' by 1. 'column' must have an integer type. After 'txn' commits
2482 * successfully, the client may retrieve the final (incremented) value of
2483 * 'column' with ovsdb_idl_txn_get_increment_new_value().
2484 *
2485 * If at time of commit the transaction is otherwise empty, that is, it doesn't
2486 * change the database, then 'force' is important. If 'force' is false in this
2487 * case, the IDL suppresses the increment and skips a round trip to the
2488 * database server. If 'force' is true, the IDL will still increment the
2489 * column.
2490 *
2491 * The client could accomplish something similar with ovsdb_idl_read(),
2492 * ovsdb_idl_txn_verify() and ovsdb_idl_txn_write(), or with ovsdb-idlc
2493 * generated wrappers for these functions. However, ovsdb_idl_txn_increment()
2494 * will never (by itself) fail because of a verify error.
2495 *
2496 * The intended use is for incrementing the "next_cfg" column in the
2497 * Open_vSwitch table. */
2498 void
2499 ovsdb_idl_txn_increment(struct ovsdb_idl_txn *txn,
2500 const struct ovsdb_idl_row *row,
2501 const struct ovsdb_idl_column *column,
2502 bool force)
2503 {
2504 ovs_assert(!txn->inc_table);
2505 ovs_assert(column->type.key.type == OVSDB_TYPE_INTEGER);
2506 ovs_assert(column->type.value.type == OVSDB_TYPE_VOID);
2507
2508 txn->inc_table = row->table->class_->name;
2509 txn->inc_column = column->name;
2510 txn->inc_row = row->uuid;
2511 txn->inc_force = force;
2512 }
2513
2514 /* Destroys 'txn' and frees all associated memory. If ovsdb_idl_txn_commit()
2515 * has been called for 'txn' but the commit is still incomplete (that is, the
2516 * last call returned TXN_INCOMPLETE) then the transaction may or may not still
2517 * end up committing at the database server, but the client will not be able to
2518 * get any further status information back. */
2519 void
2520 ovsdb_idl_txn_destroy(struct ovsdb_idl_txn *txn)
2521 {
2522 struct ovsdb_idl_txn_insert *insert, *next;
2523
2524 if (txn->status == TXN_INCOMPLETE) {
2525 ovsdb_cs_forget_transaction(txn->idl->cs, txn->request_id);
2526 hmap_remove(&txn->idl->outstanding_txns, &txn->hmap_node);
2527 }
2528 json_destroy(txn->request_id);
2529 ovsdb_idl_txn_abort(txn);
2530 ds_destroy(&txn->comment);
2531 free(txn->error);
2532 HMAP_FOR_EACH_SAFE (insert, next, hmap_node, &txn->inserted_rows) {
2533 free(insert);
2534 }
2535 hmap_destroy(&txn->inserted_rows);
2536 free(txn);
2537 }
2538
2539 /* Causes poll_block() to wake up if 'txn' has completed committing. */
2540 void
2541 ovsdb_idl_txn_wait(const struct ovsdb_idl_txn *txn)
2542 {
2543 if (txn->status != TXN_UNCOMMITTED && txn->status != TXN_INCOMPLETE) {
2544 poll_immediate_wake();
2545 }
2546 }
2547
2548 static struct json *
2549 where_uuid_equals(const struct uuid *uuid)
2550 {
2551 return
2552 json_array_create_1(
2553 json_array_create_3(
2554 json_string_create("_uuid"),
2555 json_string_create("=="),
2556 json_array_create_2(
2557 json_string_create("uuid"),
2558 json_string_create_nocopy(
2559 xasprintf(UUID_FMT, UUID_ARGS(uuid))))));
2560 }
2561
2562 static const struct ovsdb_idl_row *
2563 ovsdb_idl_txn_get_row(const struct ovsdb_idl_txn *txn, const struct uuid *uuid)
2564 {
2565 const struct ovsdb_idl_row *row;
2566
2567 HMAP_FOR_EACH_WITH_HASH (row, txn_node, uuid_hash(uuid), &txn->txn_rows) {
2568 if (uuid_equals(&row->uuid, uuid)) {
2569 return row;
2570 }
2571 }
2572 return NULL;
2573 }
2574
2575 /* XXX there must be a cleaner way to do this */
2576 static struct json *
2577 substitute_uuids(struct json *json, const struct ovsdb_idl_txn *txn)
2578 {
2579 if (json->type == JSON_ARRAY) {
2580 struct uuid uuid;
2581 size_t i;
2582
2583 if (json->array.n == 2
2584 && json->array.elems[0]->type == JSON_STRING
2585 && json->array.elems[1]->type == JSON_STRING
2586 && !strcmp(json->array.elems[0]->string, "uuid")
2587 && uuid_from_string(&uuid, json->array.elems[1]->string)) {
2588 const struct ovsdb_idl_row *row;
2589
2590 row = ovsdb_idl_txn_get_row(txn, &uuid);
2591 if (row && !row->old_datum && row->new_datum) {
2592 json_destroy(json);
2593
2594 return json_array_create_2(
2595 json_string_create("named-uuid"),
2596 json_string_create_nocopy(ovsdb_data_row_name(&uuid)));
2597 }
2598 }
2599
2600 for (i = 0; i < json->array.n; i++) {
2601 json->array.elems[i] = substitute_uuids(json->array.elems[i],
2602 txn);
2603 }
2604 } else if (json->type == JSON_OBJECT) {
2605 struct shash_node *node;
2606
2607 SHASH_FOR_EACH (node, json_object(json)) {
2608 node->data = substitute_uuids(node->data, txn);
2609 }
2610 }
2611 return json;
2612 }
2613
2614 static void
2615 ovsdb_idl_txn_disassemble(struct ovsdb_idl_txn *txn)
2616 {
2617 struct ovsdb_idl_row *row, *next;
2618
2619 /* This must happen early. Otherwise, ovsdb_idl_row_parse() will call an
2620 * ovsdb_idl_column's 'parse' function, which will call
2621 * ovsdb_idl_get_row_arc(), which will seen that the IDL is in a
2622 * transaction and fail to update the graph. */
2623 txn->idl->txn = NULL;
2624
2625 HMAP_FOR_EACH_SAFE (row, next, txn_node, &txn->txn_rows) {
2626 enum { INSERTED, MODIFIED, DELETED } op
2627 = (!row->new_datum ? DELETED
2628 : !row->old_datum ? INSERTED
2629 : MODIFIED);
2630
2631 if (op != DELETED) {
2632 ovsdb_idl_remove_from_indexes(row);
2633 }
2634
2635 ovsdb_idl_destroy_all_map_op_lists(row);
2636 ovsdb_idl_destroy_all_set_op_lists(row);
2637 if (op != INSERTED) {
2638 if (row->written) {
2639 ovsdb_idl_row_unparse(row);
2640 ovsdb_idl_row_clear_arcs(row, false);
2641 ovsdb_idl_row_parse(row);
2642 }
2643 } else {
2644 ovsdb_idl_row_unparse(row);
2645 }
2646 ovsdb_idl_row_clear_new(row);
2647
2648 free(row->prereqs);
2649 row->prereqs = NULL;
2650
2651 free(row->written);
2652 row->written = NULL;
2653
2654 hmap_remove(&txn->txn_rows, &row->txn_node);
2655 hmap_node_nullify(&row->txn_node);
2656 if (op != INSERTED) {
2657 ovsdb_idl_add_to_indexes(row);
2658 } else {
2659 hmap_remove(&row->table->rows, &row->hmap_node);
2660 free(row);
2661 }
2662 }
2663 hmap_destroy(&txn->txn_rows);
2664 hmap_init(&txn->txn_rows);
2665 }
2666
2667 static bool
2668 ovsdb_idl_txn_extract_mutations(struct ovsdb_idl_row *row,
2669 struct json *mutations)
2670 {
2671 const struct ovsdb_idl_table_class *class = row->table->class_;
2672 size_t idx;
2673 bool any_mutations = false;
2674
2675 if (row->map_op_written) {
2676 BITMAP_FOR_EACH_1(idx, class->n_columns, row->map_op_written) {
2677 struct map_op_list *map_op_list;
2678 const struct ovsdb_idl_column *column;
2679 const struct ovsdb_datum *old_datum;
2680 enum ovsdb_atomic_type key_type, value_type;
2681 struct json *mutation, *map, *col_name, *mutator;
2682 struct json *del_set, *ins_map;
2683 bool any_del, any_ins;
2684
2685 map_op_list = row->map_op_lists[idx];
2686 column = &class->columns[idx];
2687 key_type = column->type.key.type;
2688 value_type = column->type.value.type;
2689
2690 /* Get the value to be changed */
2691 if (row->new_datum && row->written
2692 && bitmap_is_set(row->written,idx)) {
2693 old_datum = &row->new_datum[idx];
2694 } else if (row->old_datum != NULL) {
2695 old_datum = &row->old_datum[idx];
2696 } else {
2697 old_datum = ovsdb_datum_default(&column->type);
2698 }
2699
2700 del_set = json_array_create_empty();
2701 ins_map = json_array_create_empty();
2702 any_del = false;
2703 any_ins = false;
2704
2705 for (struct map_op *map_op = map_op_list_first(map_op_list); map_op;
2706 map_op = map_op_list_next(map_op_list, map_op)) {
2707
2708 if (map_op_type(map_op) == MAP_OP_UPDATE) {
2709 /* Find out if value really changed. */
2710 struct ovsdb_datum *new_datum;
2711 unsigned int pos;
2712 new_datum = map_op_datum(map_op);
2713 pos = ovsdb_datum_find_key(old_datum,
2714 &new_datum->keys[0],
2715 key_type);
2716 if (ovsdb_atom_equals(&new_datum->values[0],
2717 &old_datum->values[pos],
2718 value_type)) {
2719 /* No change in value. Move on to next update. */
2720 continue;
2721 }
2722 } else if (map_op_type(map_op) == MAP_OP_DELETE){
2723 /* Verify that there is a key to delete. */
2724 unsigned int pos;
2725 pos = ovsdb_datum_find_key(old_datum,
2726 &map_op_datum(map_op)->keys[0],
2727 key_type);
2728 if (pos == UINT_MAX) {
2729 /* No key to delete. Move on to next update. */
2730 VLOG_WARN("Trying to delete a key that doesn't "
2731 "exist in the map.");
2732 continue;
2733 }
2734 }
2735
2736 if (map_op_type(map_op) == MAP_OP_INSERT) {
2737 map = json_array_create_2(
2738 ovsdb_atom_to_json(&map_op_datum(map_op)->keys[0],
2739 key_type),
2740 ovsdb_atom_to_json(&map_op_datum(map_op)->values[0],
2741 value_type));
2742 json_array_add(ins_map, map);
2743 any_ins = true;
2744 } else { /* MAP_OP_UPDATE or MAP_OP_DELETE */
2745 map = ovsdb_atom_to_json(&map_op_datum(map_op)->keys[0],
2746 key_type);
2747 json_array_add(del_set, map);
2748 any_del = true;
2749 }
2750
2751 /* Generate an additional insert mutate for updates. */
2752 if (map_op_type(map_op) == MAP_OP_UPDATE) {
2753 map = json_array_create_2(
2754 ovsdb_atom_to_json(&map_op_datum(map_op)->keys[0],
2755 key_type),
2756 ovsdb_atom_to_json(&map_op_datum(map_op)->values[0],
2757 value_type));
2758 json_array_add(ins_map, map);
2759 any_ins = true;
2760 }
2761 }
2762
2763 if (any_del) {
2764 col_name = json_string_create(column->name);
2765 mutator = json_string_create("delete");
2766 map = json_array_create_2(json_string_create("set"), del_set);
2767 mutation = json_array_create_3(col_name, mutator, map);
2768 json_array_add(mutations, mutation);
2769 any_mutations = true;
2770 } else {
2771 json_destroy(del_set);
2772 }
2773 if (any_ins) {
2774 col_name = json_string_create(column->name);
2775 mutator = json_string_create("insert");
2776 map = json_array_create_2(json_string_create("map"), ins_map);
2777 mutation = json_array_create_3(col_name, mutator, map);
2778 json_array_add(mutations, mutation);
2779 any_mutations = true;
2780 } else {
2781 json_destroy(ins_map);
2782 }
2783 }
2784 }
2785 if (row->set_op_written) {
2786 BITMAP_FOR_EACH_1(idx, class->n_columns, row->set_op_written) {
2787 struct set_op_list *set_op_list;
2788 const struct ovsdb_idl_column *column;
2789 const struct ovsdb_datum *old_datum;
2790 enum ovsdb_atomic_type key_type;
2791 struct json *mutation, *set, *col_name, *mutator;
2792 struct json *del_set, *ins_set;
2793 bool any_del, any_ins;
2794
2795 set_op_list = row->set_op_lists[idx];
2796 column = &class->columns[idx];
2797 key_type = column->type.key.type;
2798
2799 /* Get the value to be changed */
2800 if (row->new_datum && row->written
2801 && bitmap_is_set(row->written,idx)) {
2802 old_datum = &row->new_datum[idx];
2803 } else if (row->old_datum != NULL) {
2804 old_datum = &row->old_datum[idx];
2805 } else {
2806 old_datum = ovsdb_datum_default(&column->type);
2807 }
2808
2809 del_set = json_array_create_empty();
2810 ins_set = json_array_create_empty();
2811 any_del = false;
2812 any_ins = false;
2813
2814 for (struct set_op *set_op = set_op_list_first(set_op_list); set_op;
2815 set_op = set_op_list_next(set_op_list, set_op)) {
2816 if (set_op_type(set_op) == SET_OP_INSERT) {
2817 set = ovsdb_atom_to_json(&set_op_datum(set_op)->keys[0],
2818 key_type);
2819 json_array_add(ins_set, set);
2820 any_ins = true;
2821 } else { /* SETP_OP_DELETE */
2822 /* Verify that there is a key to delete. */
2823 unsigned int pos;
2824 pos = ovsdb_datum_find_key(old_datum,
2825 &set_op_datum(set_op)->keys[0],
2826 key_type);
2827 if (pos == UINT_MAX) {
2828 /* No key to delete. Move on to next update. */
2829 VLOG_WARN("Trying to delete a key that doesn't "
2830 "exist in the set.");
2831 continue;
2832 }
2833 set = ovsdb_atom_to_json(&set_op_datum(set_op)->keys[0],
2834 key_type);
2835 json_array_add(del_set, set);
2836 any_del = true;
2837 }
2838 }
2839 if (any_del) {
2840 col_name = json_string_create(column->name);
2841 mutator = json_string_create("delete");
2842 set = json_array_create_2(json_string_create("set"), del_set);
2843 mutation = json_array_create_3(col_name, mutator, set);
2844 json_array_add(mutations, mutation);
2845 any_mutations = true;
2846 } else {
2847 json_destroy(del_set);
2848 }
2849 if (any_ins) {
2850 col_name = json_string_create(column->name);
2851 mutator = json_string_create("insert");
2852 set = json_array_create_2(json_string_create("set"), ins_set);
2853 mutation = json_array_create_3(col_name, mutator, set);
2854 json_array_add(mutations, mutation);
2855 any_mutations = true;
2856 } else {
2857 json_destroy(ins_set);
2858 }
2859 }
2860 }
2861 return any_mutations;
2862 }
2863
2864 /* Attempts to commit 'txn'. Returns the status of the commit operation, one
2865 * of the following TXN_* constants:
2866 *
2867 * TXN_INCOMPLETE:
2868 *
2869 * The transaction is in progress, but not yet complete. The caller
2870 * should call again later, after calling ovsdb_idl_run() to let the IDL
2871 * do OVSDB protocol processing.
2872 *
2873 * TXN_UNCHANGED:
2874 *
2875 * The transaction is complete. (It didn't actually change the database,
2876 * so the IDL didn't send any request to the database server.)
2877 *
2878 * TXN_ABORTED:
2879 *
2880 * The caller previously called ovsdb_idl_txn_abort().
2881 *
2882 * TXN_SUCCESS:
2883 *
2884 * The transaction was successful. The update made by the transaction
2885 * (and possibly other changes made by other database clients) should
2886 * already be visible in the IDL.
2887 *
2888 * TXN_TRY_AGAIN:
2889 *
2890 * The transaction failed for some transient reason, e.g. because a
2891 * "verify" operation reported an inconsistency or due to a network
2892 * problem. The caller should wait for a change to the database, then
2893 * compose a new transaction, and commit the new transaction.
2894 *
2895 * Use the return value of ovsdb_idl_get_seqno() to wait for a change in
2896 * the database. It is important to use its return value *before* the
2897 * initial call to ovsdb_idl_txn_commit() as the baseline for this
2898 * purpose, because the change that one should wait for can happen after
2899 * the initial call but before the call that returns TXN_TRY_AGAIN, and
2900 * using some other baseline value in that situation could cause an
2901 * indefinite wait if the database rarely changes.
2902 *
2903 * TXN_NOT_LOCKED:
2904 *
2905 * The transaction failed because the IDL has been configured to require
2906 * a database lock (with ovsdb_idl_set_lock()) but didn't get it yet or
2907 * has already lost it.
2908 *
2909 * Committing a transaction rolls back all of the changes that it made to the
2910 * IDL's copy of the database. If the transaction commits successfully, then
2911 * the database server will send an update and, thus, the IDL will be updated
2912 * with the committed changes. */
2913 enum ovsdb_idl_txn_status
2914 ovsdb_idl_txn_commit(struct ovsdb_idl_txn *txn)
2915 {
2916 struct ovsdb_idl *idl = txn->idl;
2917 if (txn != idl->txn) {
2918 goto coverage_out;
2919 } else if (!ovsdb_cs_may_send_transaction(idl->cs)) {
2920 txn->status = TXN_TRY_AGAIN;
2921 goto disassemble_out;
2922 } else if (ovsdb_cs_get_lock(idl->cs) && !ovsdb_cs_has_lock(idl->cs)) {
2923 txn->status = TXN_NOT_LOCKED;
2924 goto disassemble_out;
2925 }
2926
2927 struct json *operations = json_array_create_1(
2928 json_string_create(idl->class_->database));
2929
2930 /* Add prerequisites and declarations of new rows. */
2931 struct ovsdb_idl_row *row;
2932 HMAP_FOR_EACH (row, txn_node, &txn->txn_rows) {
2933 /* XXX check that deleted rows exist even if no prereqs? */
2934 if (row->prereqs) {
2935 const struct ovsdb_idl_table_class *class = row->table->class_;
2936 size_t n_columns = class->n_columns;
2937 struct json *op, *columns, *row_json;
2938 size_t idx;
2939
2940 op = json_object_create();
2941 json_array_add(operations, op);
2942 json_object_put_string(op, "op", "wait");
2943 json_object_put_string(op, "table", class->name);
2944 json_object_put(op, "timeout", json_integer_create(0));
2945 json_object_put(op, "where", where_uuid_equals(&row->uuid));
2946 json_object_put_string(op, "until", "==");
2947 columns = json_array_create_empty();
2948 json_object_put(op, "columns", columns);
2949 row_json = json_object_create();
2950 json_object_put(op, "rows", json_array_create_1(row_json));
2951
2952 BITMAP_FOR_EACH_1 (idx, n_columns, row->prereqs) {
2953 const struct ovsdb_idl_column *column = &class->columns[idx];
2954 json_array_add(columns, json_string_create(column->name));
2955 json_object_put(row_json, column->name,
2956 ovsdb_datum_to_json(&row->old_datum[idx],
2957 &column->type));
2958 }
2959 }
2960 }
2961
2962 /* Add updates. */
2963 bool any_updates = false;
2964
2965 /* For tables constrained to have only a single row (a fairly common OVSDB
2966 * pattern for storing global data), identify whether we're inserting a
2967 * row. If so, then verify that the table is empty before inserting the
2968 * row. This gives us a clear verification-related failure if there was an
2969 * insertion race with another client. */
2970 for (size_t i = 0; i < idl->class_->n_tables; i++) {
2971 struct ovsdb_idl_table *table = &idl->tables[i];
2972 if (table->class_->is_singleton) {
2973 /* Count the number of rows in the table before and after our
2974 * transaction commits. This is O(n) in the number of rows in the
2975 * table, but that's OK since we know that the table should only
2976 * have one row. */
2977 size_t initial_rows = 0;
2978 size_t final_rows = 0;
2979 HMAP_FOR_EACH (row, hmap_node, &table->rows) {
2980 initial_rows += row->old_datum != NULL;
2981 final_rows += row->new_datum != NULL;
2982 }
2983
2984 if (initial_rows == 0 && final_rows == 1) {
2985 struct json *op = json_object_create();
2986 json_array_add(operations, op);
2987 json_object_put_string(op, "op", "wait");
2988 json_object_put_string(op, "table", table->class_->name);
2989 json_object_put(op, "where", json_array_create_empty());
2990 json_object_put(op, "timeout", json_integer_create(0));
2991 json_object_put_string(op, "until", "==");
2992 json_object_put(op, "rows", json_array_create_empty());
2993 }
2994 }
2995 }
2996
2997 HMAP_FOR_EACH (row, txn_node, &txn->txn_rows) {
2998 const struct ovsdb_idl_table_class *class = row->table->class_;
2999
3000 if (!row->new_datum) {
3001 if (class->is_root) {
3002 struct json *op = json_object_create();
3003 json_object_put_string(op, "op", "delete");
3004 json_object_put_string(op, "table", class->name);
3005 json_object_put(op, "where", where_uuid_equals(&row->uuid));
3006 json_array_add(operations, op);
3007 any_updates = true;
3008 } else {
3009 /* Let ovsdb-server decide whether to really delete it. */
3010 }
3011 } else if (row->old_datum != row->new_datum) {
3012 struct json *row_json;
3013 size_t idx;
3014
3015 struct json *op = json_object_create();
3016 json_object_put_string(op, "op",
3017 row->old_datum ? "update" : "insert");
3018 json_object_put_string(op, "table", class->name);
3019 if (row->old_datum) {
3020 json_object_put(op, "where", where_uuid_equals(&row->uuid));
3021 } else {
3022 struct ovsdb_idl_txn_insert *insert;
3023
3024 any_updates = true;
3025
3026 json_object_put(op, "uuid-name",
3027 json_string_create_nocopy(
3028 ovsdb_data_row_name(&row->uuid)));
3029
3030 insert = xmalloc(sizeof *insert);
3031 insert->dummy = row->uuid;
3032 insert->op_index = operations->array.n - 1;
3033 uuid_zero(&insert->real);
3034 hmap_insert(&txn->inserted_rows, &insert->hmap_node,
3035 uuid_hash(&insert->dummy));
3036 }
3037 row_json = json_object_create();
3038 json_object_put(op, "row", row_json);
3039
3040 if (row->written) {
3041 BITMAP_FOR_EACH_1 (idx, class->n_columns, row->written) {
3042 const struct ovsdb_idl_column *column =
3043 &class->columns[idx];
3044
3045 if (row->old_datum
3046 || !ovsdb_datum_is_default(&row->new_datum[idx],
3047 &column->type)) {
3048 struct json *value;
3049
3050 value = ovsdb_datum_to_json(&row->new_datum[idx],
3051 &column->type);
3052 json_object_put(row_json, column->name,
3053 substitute_uuids(value, txn));
3054
3055 /* If anything really changed, consider it an update.
3056 * We can't suppress not-really-changed values earlier
3057 * or transactions would become nonatomic (see the big
3058 * comment inside ovsdb_idl_txn_write()). */
3059 if (!any_updates && row->old_datum &&
3060 !ovsdb_datum_equals(&row->old_datum[idx],
3061 &row->new_datum[idx],
3062 &column->type)) {
3063 any_updates = true;
3064 }
3065 }
3066 }
3067 }
3068
3069 if (!row->old_datum || !shash_is_empty(json_object(row_json))) {
3070 json_array_add(operations, op);
3071 } else {
3072 json_destroy(op);
3073 }
3074 }
3075
3076 /* Add mutate operation, for partial map or partial set updates. */
3077 if (row->map_op_written || row->set_op_written) {
3078 struct json *op, *mutations;
3079 bool any_mutations;
3080
3081 op = json_object_create();
3082 json_object_put_string(op, "op", "mutate");
3083 json_object_put_string(op, "table", class->name);
3084 json_object_put(op, "where", where_uuid_equals(&row->uuid));
3085 mutations = json_array_create_empty();
3086 any_mutations = ovsdb_idl_txn_extract_mutations(row, mutations);
3087 json_object_put(op, "mutations", mutations);
3088
3089 if (any_mutations) {
3090 op = substitute_uuids(op, txn);
3091 json_array_add(operations, op);
3092 any_updates = true;
3093 } else {
3094 json_destroy(op);
3095 }
3096 }
3097 }
3098
3099 /* Add increment. */
3100 if (txn->inc_table && (any_updates || txn->inc_force)) {
3101 any_updates = true;
3102 txn->inc_index = operations->array.n - 1;
3103
3104 struct json *op = json_object_create();
3105 json_object_put_string(op, "op", "mutate");
3106 json_object_put_string(op, "table", txn->inc_table);
3107 json_object_put(op, "where",
3108 substitute_uuids(where_uuid_equals(&txn->inc_row),
3109 txn));
3110 json_object_put(op, "mutations",
3111 json_array_create_1(
3112 json_array_create_3(
3113 json_string_create(txn->inc_column),
3114 json_string_create("+="),
3115 json_integer_create(1))));
3116 json_array_add(operations, op);
3117
3118 op = json_object_create();
3119 json_object_put_string(op, "op", "select");
3120 json_object_put_string(op, "table", txn->inc_table);
3121 json_object_put(op, "where",
3122 substitute_uuids(where_uuid_equals(&txn->inc_row),
3123 txn));
3124 json_object_put(op, "columns",
3125 json_array_create_1(json_string_create(
3126 txn->inc_column)));
3127 json_array_add(operations, op);
3128 }
3129
3130 if (txn->comment.length) {
3131 struct json *op = json_object_create();
3132 json_object_put_string(op, "op", "comment");
3133 json_object_put_string(op, "comment", ds_cstr(&txn->comment));
3134 json_array_add(operations, op);
3135 }
3136
3137 if (txn->dry_run) {
3138 struct json *op = json_object_create();
3139 json_object_put_string(op, "op", "abort");
3140 json_array_add(operations, op);
3141 }
3142
3143 if (!any_updates) {
3144 txn->status = TXN_UNCHANGED;
3145 json_destroy(operations);
3146 } else {
3147 txn->request_id = ovsdb_cs_send_transaction(idl->cs, operations);
3148 if (txn->request_id) {
3149 hmap_insert(&idl->outstanding_txns, &txn->hmap_node,
3150 json_hash(txn->request_id, 0));
3151 txn->status = TXN_INCOMPLETE;
3152 } else {
3153 txn->status = TXN_TRY_AGAIN;
3154 }
3155 }
3156
3157 disassemble_out:
3158 ovsdb_idl_txn_disassemble(txn);
3159 coverage_out:
3160 switch (txn->status) {
3161 case TXN_UNCOMMITTED: COVERAGE_INC(txn_uncommitted); break;
3162 case TXN_UNCHANGED: COVERAGE_INC(txn_unchanged); break;
3163 case TXN_INCOMPLETE: COVERAGE_INC(txn_incomplete); break;
3164 case TXN_ABORTED: COVERAGE_INC(txn_aborted); break;
3165 case TXN_SUCCESS: COVERAGE_INC(txn_success); break;
3166 case TXN_TRY_AGAIN: COVERAGE_INC(txn_try_again); break;
3167 case TXN_NOT_LOCKED: COVERAGE_INC(txn_not_locked); break;
3168 case TXN_ERROR: COVERAGE_INC(txn_error); break;
3169 }
3170
3171 return txn->status;
3172 }
3173
3174 /* Attempts to commit 'txn', blocking until the commit either succeeds or
3175 * fails. Returns the final commit status, which may be any TXN_* value other
3176 * than TXN_INCOMPLETE.
3177 *
3178 * This function calls ovsdb_idl_run() on 'txn''s IDL, so it may cause the
3179 * return value of ovsdb_idl_get_seqno() to change. */
3180 enum ovsdb_idl_txn_status
3181 ovsdb_idl_txn_commit_block(struct ovsdb_idl_txn *txn)
3182 {
3183 enum ovsdb_idl_txn_status status;
3184
3185 fatal_signal_run();
3186 while ((status = ovsdb_idl_txn_commit(txn)) == TXN_INCOMPLETE) {
3187 ovsdb_idl_run(txn->idl);
3188 ovsdb_idl_wait(txn->idl);
3189 ovsdb_idl_txn_wait(txn);
3190 poll_block();
3191 }
3192 return status;
3193 }
3194
3195 /* Returns the final (incremented) value of the column in 'txn' that was set to
3196 * be incremented by ovsdb_idl_txn_increment(). 'txn' must have committed
3197 * successfully. */
3198 int64_t
3199 ovsdb_idl_txn_get_increment_new_value(const struct ovsdb_idl_txn *txn)
3200 {
3201 ovs_assert(txn->status == TXN_SUCCESS);
3202 return txn->inc_new_value;
3203 }
3204
3205 /* Aborts 'txn' without sending it to the database server. This is effective
3206 * only if ovsdb_idl_txn_commit() has not yet been called for 'txn'.
3207 * Otherwise, it has no effect.
3208 *
3209 * Aborting a transaction doesn't free its memory. Use
3210 * ovsdb_idl_txn_destroy() to do that. */
3211 void
3212 ovsdb_idl_txn_abort(struct ovsdb_idl_txn *txn)
3213 {
3214 ovsdb_idl_txn_disassemble(txn);
3215 if (txn->status == TXN_UNCOMMITTED || txn->status == TXN_INCOMPLETE) {
3216 txn->status = TXN_ABORTED;
3217 }
3218 }
3219
3220 /* Returns a string that reports the error status for 'txn'. The caller must
3221 * not modify or free the returned string. A call to ovsdb_idl_txn_destroy()
3222 * for 'txn' may free the returned string.
3223 *
3224 * The return value is ordinarily one of the strings that
3225 * ovsdb_idl_txn_status_to_string() would return, but if the transaction failed
3226 * due to an error reported by the database server, the return value is that
3227 * error. */
3228 const char *
3229 ovsdb_idl_txn_get_error(const struct ovsdb_idl_txn *txn)
3230 {
3231 if (txn->status != TXN_ERROR) {
3232 return ovsdb_idl_txn_status_to_string(txn->status);
3233 } else if (txn->error) {
3234 return txn->error;
3235 } else {
3236 return "no error details available";
3237 }
3238 }
3239
3240 static void
3241 ovsdb_idl_txn_set_error_json(struct ovsdb_idl_txn *txn,
3242 const struct json *json)
3243 {
3244 if (json && txn->error == NULL) {
3245 txn->error = json_to_string(json, JSSF_SORT);
3246 }
3247 }
3248
3249 /* For transaction 'txn' that completed successfully, finds and returns the
3250 * permanent UUID that the database assigned to a newly inserted row, given the
3251 * 'uuid' that ovsdb_idl_txn_insert() assigned locally to that row.
3252 *
3253 * Returns NULL if 'uuid' is not a UUID assigned by ovsdb_idl_txn_insert() or
3254 * if it was assigned by that function and then deleted by
3255 * ovsdb_idl_txn_delete() within the same transaction. (Rows that are inserted
3256 * and then deleted within a single transaction are never sent to the database
3257 * server, so it never assigns them a permanent UUID.) */
3258 const struct uuid *
3259 ovsdb_idl_txn_get_insert_uuid(const struct ovsdb_idl_txn *txn,
3260 const struct uuid *uuid)
3261 {
3262 const struct ovsdb_idl_txn_insert *insert;
3263
3264 ovs_assert(txn->status == TXN_SUCCESS || txn->status == TXN_UNCHANGED);
3265 HMAP_FOR_EACH_IN_BUCKET (insert, hmap_node,
3266 uuid_hash(uuid), &txn->inserted_rows) {
3267 if (uuid_equals(uuid, &insert->dummy)) {
3268 return &insert->real;
3269 }
3270 }
3271 return NULL;
3272 }
3273
3274 static void
3275 ovsdb_idl_txn_complete(struct ovsdb_idl_txn *txn,
3276 enum ovsdb_idl_txn_status status)
3277 {
3278 txn->status = status;
3279 hmap_remove(&txn->idl->outstanding_txns, &txn->hmap_node);
3280 }
3281
3282 static void
3283 ovsdb_idl_txn_write__(const struct ovsdb_idl_row *row_,
3284 const struct ovsdb_idl_column *column,
3285 struct ovsdb_datum *datum, bool owns_datum)
3286 {
3287 struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
3288 const struct ovsdb_idl_table_class *class;
3289 size_t column_idx;
3290 bool write_only;
3291
3292 ovs_assert(!column->is_synthetic);
3293 if (ovsdb_idl_row_is_synthetic(row)) {
3294 goto discard_datum;
3295 }
3296
3297 class = row->table->class_;
3298 column_idx = column - class->columns;
3299 write_only = row->table->modes[column_idx] == OVSDB_IDL_MONITOR;
3300
3301 ovs_assert(row->new_datum != NULL);
3302 ovs_assert(column_idx < class->n_columns);
3303 ovs_assert(row->old_datum == NULL ||
3304 row->table->modes[column_idx] & OVSDB_IDL_MONITOR);
3305
3306 if (row->table->idl->verify_write_only && !write_only) {
3307 VLOG_ERR("Bug: Attempt to write to a read/write column (%s:%s) when"
3308 " explicitly configured not to.", class->name, column->name);
3309 goto discard_datum;
3310 }
3311
3312 /* If this is a write-only column and the datum being written is the same
3313 * as the one already there, just skip the update entirely. This is worth
3314 * optimizing because we have a lot of columns that get periodically
3315 * refreshed into the database but don't actually change that often.
3316 *
3317 * We don't do this for read/write columns because that would break
3318 * atomicity of transactions--some other client might have written a
3319 * different value in that column since we read it. (But if a whole
3320 * transaction only does writes of existing values, without making any real
3321 * changes, we will drop the whole transaction later in
3322 * ovsdb_idl_txn_commit().) */
3323 if (write_only && ovsdb_datum_equals(ovsdb_idl_read(row, column),
3324 datum, &column->type)) {
3325 goto discard_datum;
3326 }
3327
3328 bool index_row = is_index_row(row);
3329 if (!index_row) {
3330 ovsdb_idl_remove_from_indexes(row);
3331 }
3332 if (hmap_node_is_null(&row->txn_node)) {
3333 hmap_insert(&row->table->idl->txn->txn_rows, &row->txn_node,
3334 uuid_hash(&row->uuid));
3335 }
3336 if (row->old_datum == row->new_datum) {
3337 row->new_datum = xmalloc(class->n_columns * sizeof *row->new_datum);
3338 }
3339 if (!row->written) {
3340 row->written = bitmap_allocate(class->n_columns);
3341 }
3342 if (bitmap_is_set(row->written, column_idx)) {
3343 ovsdb_datum_destroy(&row->new_datum[column_idx], &column->type);
3344 } else {
3345 bitmap_set1(row->written, column_idx);
3346 }
3347 if (owns_datum) {
3348 row->new_datum[column_idx] = *datum;
3349 } else {
3350 ovsdb_datum_clone(&row->new_datum[column_idx], datum, &column->type);
3351 }
3352 (column->unparse)(row);
3353 (column->parse)(row, &row->new_datum[column_idx]);
3354 row->parsed = true;
3355 if (!index_row) {
3356 ovsdb_idl_add_to_indexes(row);
3357 }
3358 return;
3359
3360 discard_datum:
3361 if (owns_datum) {
3362 ovsdb_datum_destroy(datum, &column->type);
3363 }
3364 }
3365
3366 /* Writes 'datum' to the specified 'column' in 'row_'. Updates both 'row_'
3367 * itself and the structs derived from it (e.g. the "struct ovsrec_*", for
3368 * ovs-vswitchd).
3369 *
3370 * 'datum' must have the correct type for its column, but it needs not be
3371 * sorted or unique because this function will take care of that. The IDL does
3372 * not check that it meets schema constraints, but ovsdb-server will do so at
3373 * commit time so it had better be correct.
3374 *
3375 * A transaction must be in progress. Replication of 'column' must not have
3376 * been disabled (by calling ovsdb_idl_omit()).
3377 *
3378 * Usually this function is used indirectly through one of the "set" functions
3379 * generated by ovsdb-idlc.
3380 *
3381 * Takes ownership of what 'datum' points to (and in some cases destroys that
3382 * data before returning) but makes a copy of 'datum' itself. (Commonly
3383 * 'datum' is on the caller's stack.) */
3384 void
3385 ovsdb_idl_txn_write(const struct ovsdb_idl_row *row,
3386 const struct ovsdb_idl_column *column,
3387 struct ovsdb_datum *datum)
3388 {
3389 ovsdb_datum_sort_unique(datum,
3390 column->type.key.type, column->type.value.type);
3391 ovsdb_idl_txn_write__(row, column, datum, true);
3392 }
3393
3394 /* Similar to ovsdb_idl_txn_write(), except:
3395 *
3396 * - The caller retains ownership of 'datum' and what it points to.
3397 *
3398 * - The caller must ensure that 'datum' is sorted and unique (e.g. via
3399 * ovsdb_datum_sort_unique().) */
3400 void
3401 ovsdb_idl_txn_write_clone(const struct ovsdb_idl_row *row,
3402 const struct ovsdb_idl_column *column,
3403 const struct ovsdb_datum *datum)
3404 {
3405 ovsdb_idl_txn_write__(row, column,
3406 CONST_CAST(struct ovsdb_datum *, datum), false);
3407 }
3408
3409 /* Causes the original contents of 'column' in 'row_' to be verified as a
3410 * prerequisite to completing the transaction. That is, if 'column' in 'row_'
3411 * changed (or if 'row_' was deleted) between the time that the IDL originally
3412 * read its contents and the time that the transaction commits, then the
3413 * transaction aborts and ovsdb_idl_txn_commit() returns TXN_TRY_AGAIN.
3414 *
3415 * The intention is that, to ensure that no transaction commits based on dirty
3416 * reads, an application should call ovsdb_idl_txn_verify() on each data item
3417 * read as part of a read-modify-write operation.
3418 *
3419 * In some cases ovsdb_idl_txn_verify() reduces to a no-op, because the current
3420 * value of 'column' is already known:
3421 *
3422 * - If 'row_' is a row created by the current transaction (returned by
3423 * ovsdb_idl_txn_insert()).
3424 *
3425 * - If 'column' has already been modified (with ovsdb_idl_txn_write())
3426 * within the current transaction.
3427 *
3428 * Because of the latter property, always call ovsdb_idl_txn_verify() *before*
3429 * ovsdb_idl_txn_write() for a given read-modify-write.
3430 *
3431 * A transaction must be in progress.
3432 *
3433 * Usually this function is used indirectly through one of the "verify"
3434 * functions generated by ovsdb-idlc. */
3435 void
3436 ovsdb_idl_txn_verify(const struct ovsdb_idl_row *row_,
3437 const struct ovsdb_idl_column *column)
3438 {
3439 struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
3440 const struct ovsdb_idl_table_class *class;
3441 size_t column_idx;
3442
3443 if (ovsdb_idl_row_is_synthetic(row)) {
3444 return;
3445 }
3446
3447 class = row->table->class_;
3448 column_idx = column - class->columns;
3449
3450 ovs_assert(row->new_datum != NULL);
3451 ovs_assert(row->old_datum == NULL ||
3452 row->table->modes[column_idx] & OVSDB_IDL_MONITOR);
3453 if (!row->old_datum
3454 || (row->written && bitmap_is_set(row->written, column_idx))) {
3455 return;
3456 }
3457
3458 if (hmap_node_is_null(&row->txn_node)) {
3459 hmap_insert(&row->table->idl->txn->txn_rows, &row->txn_node,
3460 uuid_hash(&row->uuid));
3461 }
3462 if (!row->prereqs) {
3463 row->prereqs = bitmap_allocate(class->n_columns);
3464 }
3465 bitmap_set1(row->prereqs, column_idx);
3466 }
3467
3468 /* Deletes 'row_' from its table. May free 'row_', so it must not be
3469 * accessed afterward.
3470 *
3471 * A transaction must be in progress.
3472 *
3473 * Usually this function is used indirectly through one of the "delete"
3474 * functions generated by ovsdb-idlc. */
3475 void
3476 ovsdb_idl_txn_delete(const struct ovsdb_idl_row *row_)
3477 {
3478 struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
3479
3480 if (ovsdb_idl_row_is_synthetic(row)) {
3481 return;
3482 }
3483
3484 ovs_assert(row->new_datum != NULL);
3485 ovs_assert(!is_index_row(row_));
3486 ovsdb_idl_remove_from_indexes(row_);
3487 if (!row->old_datum) {
3488 ovsdb_idl_row_unparse(row);
3489 ovsdb_idl_row_clear_new(row);
3490 ovs_assert(!row->prereqs);
3491 hmap_remove(&row->table->rows, &row->hmap_node);
3492 hmap_remove(&row->table->idl->txn->txn_rows, &row->txn_node);
3493 free(row);
3494 return;
3495 }
3496 if (hmap_node_is_null(&row->txn_node)) {
3497 hmap_insert(&row->table->idl->txn->txn_rows, &row->txn_node,
3498 uuid_hash(&row->uuid));
3499 }
3500 ovsdb_idl_row_clear_new(row);
3501 row->new_datum = NULL;
3502 }
3503
3504 /* Inserts and returns a new row in the table with the specified 'class' in the
3505 * database with open transaction 'txn'.
3506 *
3507 * The new row is assigned a provisional UUID. If 'uuid' is null then one is
3508 * randomly generated; otherwise 'uuid' should specify a randomly generated
3509 * UUID not otherwise in use. ovsdb-server will assign a different UUID when
3510 * 'txn' is committed, but the IDL will replace any uses of the provisional
3511 * UUID in the data to be to be committed by the UUID assigned by
3512 * ovsdb-server.
3513 *
3514 * Usually this function is used indirectly through one of the "insert"
3515 * functions generated by ovsdb-idlc. */
3516 const struct ovsdb_idl_row *
3517 ovsdb_idl_txn_insert(struct ovsdb_idl_txn *txn,
3518 const struct ovsdb_idl_table_class *class,
3519 const struct uuid *uuid)
3520 {
3521 struct ovsdb_idl_row *row = ovsdb_idl_row_create__(class);
3522
3523 if (uuid) {
3524 ovs_assert(!ovsdb_idl_txn_get_row(txn, uuid));
3525 row->uuid = *uuid;
3526 } else {
3527 uuid_generate(&row->uuid);
3528 }
3529
3530 row->table = ovsdb_idl_table_from_class(txn->idl, class);
3531 row->new_datum = xmalloc(class->n_columns * sizeof *row->new_datum);
3532 hmap_insert(&row->table->rows, &row->hmap_node, uuid_hash(&row->uuid));
3533 hmap_insert(&txn->txn_rows, &row->txn_node, uuid_hash(&row->uuid));
3534 ovsdb_idl_add_to_indexes(row);
3535
3536 return row;
3537 }
3538
3539 static void
3540 ovsdb_idl_txn_abort_all(struct ovsdb_idl *idl)
3541 {
3542 struct ovsdb_idl_txn *txn;
3543
3544 HMAP_FOR_EACH (txn, hmap_node, &idl->outstanding_txns) {
3545 ovsdb_idl_txn_complete(txn, TXN_TRY_AGAIN);
3546 }
3547 }
3548
3549 static struct ovsdb_idl_txn *
3550 ovsdb_idl_txn_find(struct ovsdb_idl *idl, const struct json *id)
3551 {
3552 struct ovsdb_idl_txn *txn;
3553
3554 HMAP_FOR_EACH_WITH_HASH (txn, hmap_node,
3555 json_hash(id, 0), &idl->outstanding_txns) {
3556 if (json_equal(id, txn->request_id)) {
3557 return txn;
3558 }
3559 }
3560 return NULL;
3561 }
3562
3563 static bool
3564 check_json_type(const struct json *json, enum json_type type, const char *name)
3565 {
3566 if (!json) {
3567 VLOG_WARN_RL(&syntax_rl, "%s is missing", name);
3568 return false;
3569 } else if (json->type != type) {
3570 VLOG_WARN_RL(&syntax_rl, "%s is %s instead of %s",
3571 name, json_type_to_string(json->type),
3572 json_type_to_string(type));
3573 return false;
3574 } else {
3575 return true;
3576 }
3577 }
3578
3579 static bool
3580 ovsdb_idl_txn_process_inc_reply(struct ovsdb_idl_txn *txn,
3581 const struct json_array *results)
3582 {
3583 struct json *count, *rows, *row, *column;
3584 struct shash *mutate, *select;
3585
3586 if (txn->inc_index + 2 > results->n) {
3587 VLOG_WARN_RL(&syntax_rl, "reply does not contain enough operations "
3588 "for increment (has %"PRIuSIZE", needs %u)",
3589 results->n, txn->inc_index + 2);
3590 return false;
3591 }
3592
3593 /* We know that this is a JSON object because the loop in
3594 * ovsdb_idl_txn_process_reply() checked. */
3595 mutate = json_object(results->elems[txn->inc_index]);
3596 count = shash_find_data(mutate, "count");
3597 if (!check_json_type(count, JSON_INTEGER, "\"mutate\" reply \"count\"")) {
3598 return false;
3599 }
3600 if (count->integer != 1) {
3601 VLOG_WARN_RL(&syntax_rl,
3602 "\"mutate\" reply \"count\" is %lld instead of 1",
3603 count->integer);
3604 return false;
3605 }
3606
3607 select = json_object(results->elems[txn->inc_index + 1]);
3608 rows = shash_find_data(select, "rows");
3609 if (!check_json_type(rows, JSON_ARRAY, "\"select\" reply \"rows\"")) {
3610 return false;
3611 }
3612 if (rows->array.n != 1) {
3613 VLOG_WARN_RL(&syntax_rl, "\"select\" reply \"rows\" has %"PRIuSIZE" elements "
3614 "instead of 1",
3615 rows->array.n);
3616 return false;
3617 }
3618 row = rows->array.elems[0];
3619 if (!check_json_type(row, JSON_OBJECT, "\"select\" reply row")) {
3620 return false;
3621 }
3622 column = shash_find_data(json_object(row), txn->inc_column);
3623 if (!check_json_type(column, JSON_INTEGER,
3624 "\"select\" reply inc column")) {
3625 return false;
3626 }
3627 txn->inc_new_value = column->integer;
3628 return true;
3629 }
3630
3631 static bool
3632 ovsdb_idl_txn_process_insert_reply(struct ovsdb_idl_txn_insert *insert,
3633 const struct json_array *results)
3634 {
3635 static const struct ovsdb_base_type uuid_type = OVSDB_BASE_UUID_INIT;
3636 struct ovsdb_error *error;
3637 struct json *json_uuid;
3638 union ovsdb_atom uuid;
3639 struct shash *reply;
3640
3641 if (insert->op_index >= results->n) {
3642 VLOG_WARN_RL(&syntax_rl, "reply does not contain enough operations "
3643 "for insert (has %"PRIuSIZE", needs %u)",
3644 results->n, insert->op_index);
3645 return false;
3646 }
3647
3648 /* We know that this is a JSON object because the loop in
3649 * ovsdb_idl_txn_process_reply() checked. */
3650 reply = json_object(results->elems[insert->op_index]);
3651 json_uuid = shash_find_data(reply, "uuid");
3652 if (!check_json_type(json_uuid, JSON_ARRAY, "\"insert\" reply \"uuid\"")) {
3653 return false;
3654 }
3655
3656 error = ovsdb_atom_from_json(&uuid, &uuid_type, json_uuid, NULL);
3657 if (error) {
3658 char *s = ovsdb_error_to_string_free(error);
3659 VLOG_WARN_RL(&syntax_rl, "\"insert\" reply \"uuid\" is not a JSON "
3660 "UUID: %s", s);
3661 free(s);
3662 return false;
3663 }
3664
3665 insert->real = uuid.uuid;
3666
3667 return true;
3668 }
3669
3670 static void
3671 ovsdb_idl_txn_process_reply(struct ovsdb_idl *idl,
3672 const struct jsonrpc_msg *msg)
3673 {
3674 struct ovsdb_idl_txn *txn = ovsdb_idl_txn_find(idl, msg->id);
3675 if (!txn) {
3676 return;
3677 }
3678
3679 enum ovsdb_idl_txn_status status;
3680 if (msg->type == JSONRPC_ERROR) {
3681 if (msg->error
3682 && msg->error->type == JSON_STRING
3683 && !strcmp(json_string(msg->error), "canceled")) {
3684 /* ovsdb-server uses this error message to indicate that the
3685 * transaction was canceled because the database in question was
3686 * removed, converted, etc. */
3687 status = TXN_TRY_AGAIN;
3688 } else {
3689 status = TXN_ERROR;
3690 ovsdb_idl_txn_set_error_json(txn, msg->error);
3691 }
3692 } else if (msg->result->type != JSON_ARRAY) {
3693 VLOG_WARN_RL(&syntax_rl, "reply to \"transact\" is not JSON array");
3694 status = TXN_ERROR;
3695 ovsdb_idl_txn_set_error_json(txn, msg->result);
3696 } else {
3697 struct json_array *ops = &msg->result->array;
3698 int hard_errors = 0;
3699 int soft_errors = 0;
3700 int lock_errors = 0;
3701 size_t i;
3702
3703 for (i = 0; i < ops->n; i++) {
3704 struct json *op = ops->elems[i];
3705
3706 if (op->type == JSON_NULL) {
3707 /* This isn't an error in itself but indicates that some prior
3708 * operation failed, so make sure that we know about it. */
3709 soft_errors++;
3710 } else if (op->type == JSON_OBJECT) {
3711 struct json *error;
3712
3713 error = shash_find_data(json_object(op), "error");
3714 if (error) {
3715 if (error->type == JSON_STRING) {
3716 if (!strcmp(error->string, "timed out")) {
3717 soft_errors++;
3718 } else if (!strcmp(error->string,
3719 "unknown database")) {
3720 ovsdb_cs_flag_inconsistency(idl->cs);
3721 soft_errors++;
3722 } else if (!strcmp(error->string, "not owner")) {
3723 lock_errors++;
3724 } else if (!strcmp(error->string, "not allowed")) {
3725 hard_errors++;
3726 ovsdb_idl_txn_set_error_json(txn, op);
3727 } else if (strcmp(error->string, "aborted")) {
3728 hard_errors++;
3729 ovsdb_idl_txn_set_error_json(txn, op);
3730 VLOG_WARN_RL(&other_rl,
3731 "transaction error: %s", txn->error);
3732 }
3733 } else {
3734 hard_errors++;
3735 ovsdb_idl_txn_set_error_json(txn, op);
3736 VLOG_WARN_RL(&syntax_rl,
3737 "\"error\" in reply is not JSON string");
3738 }
3739 }
3740 } else {
3741 hard_errors++;
3742 ovsdb_idl_txn_set_error_json(txn, op);
3743 VLOG_WARN_RL(&syntax_rl,
3744 "operation reply is not JSON null or object");
3745 }
3746 }
3747
3748 if (!soft_errors && !hard_errors && !lock_errors) {
3749 struct ovsdb_idl_txn_insert *insert;
3750
3751 if (txn->inc_table && !ovsdb_idl_txn_process_inc_reply(txn, ops)) {
3752 hard_errors++;
3753 }
3754
3755 HMAP_FOR_EACH (insert, hmap_node, &txn->inserted_rows) {
3756 if (!ovsdb_idl_txn_process_insert_reply(insert, ops)) {
3757 hard_errors++;
3758 }
3759 }
3760 }
3761
3762 status = (hard_errors ? TXN_ERROR
3763 : lock_errors ? TXN_NOT_LOCKED
3764 : soft_errors ? TXN_TRY_AGAIN
3765 : TXN_SUCCESS);
3766 }
3767
3768 ovsdb_idl_txn_complete(txn, status);
3769 }
3770
3771 /* Returns the transaction currently active for 'row''s IDL. A transaction
3772 * must currently be active. */
3773 struct ovsdb_idl_txn *
3774 ovsdb_idl_txn_get(const struct ovsdb_idl_row *row)
3775 {
3776 struct ovsdb_idl_txn *txn = row->table->idl->txn;
3777 ovs_assert(txn != NULL);
3778 return txn;
3779 }
3780
3781 /* Returns the IDL on which 'txn' acts. */
3782 struct ovsdb_idl *
3783 ovsdb_idl_txn_get_idl (struct ovsdb_idl_txn *txn)
3784 {
3785 return txn->idl;
3786 }
3787
3788 /* Blocks until 'idl' successfully connects to the remote database and
3789 * retrieves its contents. */
3790 void
3791 ovsdb_idl_get_initial_snapshot(struct ovsdb_idl *idl)
3792 {
3793 while (1) {
3794 ovsdb_idl_run(idl);
3795 if (ovsdb_idl_has_ever_connected(idl)) {
3796 return;
3797 }
3798 ovsdb_idl_wait(idl);
3799 poll_block();
3800 }
3801 }
3802 \f
3803 /* If 'lock_name' is nonnull, configures 'idl' to obtain the named lock from
3804 * the database server and to avoid modifying the database when the lock cannot
3805 * be acquired (that is, when another client has the same lock).
3806 *
3807 * If 'lock_name' is NULL, drops the locking requirement and releases the
3808 * lock. */
3809 void
3810 ovsdb_idl_set_lock(struct ovsdb_idl *idl, const char *lock_name)
3811 {
3812 ovsdb_cs_set_lock(idl->cs, lock_name);
3813 }
3814
3815 /* Returns true if 'idl' is configured to obtain a lock and owns that lock.
3816 *
3817 * Locking and unlocking happens asynchronously from the database client's
3818 * point of view, so the information is only useful for optimization (e.g. if
3819 * the client doesn't have the lock then there's no point in trying to write to
3820 * the database). */
3821 bool
3822 ovsdb_idl_has_lock(const struct ovsdb_idl *idl)
3823 {
3824 return ovsdb_cs_has_lock(idl->cs);
3825 }
3826
3827 /* Returns true if 'idl' is configured to obtain a lock but the database server
3828 * has indicated that some other client already owns the requested lock. */
3829 bool
3830 ovsdb_idl_is_lock_contended(const struct ovsdb_idl *idl)
3831 {
3832 return ovsdb_cs_is_lock_contended(idl->cs);
3833 }
3834
3835 /* Inserts a new Map Operation into current transaction. */
3836 static void
3837 ovsdb_idl_txn_add_map_op(struct ovsdb_idl_row *row,
3838 const struct ovsdb_idl_column *column,
3839 struct ovsdb_datum *datum,
3840 enum map_op_type op_type)
3841 {
3842 const struct ovsdb_idl_table_class *class;
3843 size_t column_idx;
3844 struct map_op *map_op;
3845
3846 class = row->table->class_;
3847 column_idx = column - class->columns;
3848
3849 /* Check if a map operation list exists for this column. */
3850 if (!row->map_op_written) {
3851 row->map_op_written = bitmap_allocate(class->n_columns);
3852 row->map_op_lists = xzalloc(class->n_columns *
3853 sizeof *row->map_op_lists);
3854 }
3855 if (!row->map_op_lists[column_idx]) {
3856 row->map_op_lists[column_idx] = map_op_list_create();
3857 }
3858
3859 /* Add a map operation to the corresponding list. */
3860 map_op = map_op_create(datum, op_type);
3861 bitmap_set1(row->map_op_written, column_idx);
3862 map_op_list_add(row->map_op_lists[column_idx], map_op, &column->type);
3863
3864 /* Add this row to transaction's list of rows. */
3865 if (hmap_node_is_null(&row->txn_node)) {
3866 hmap_insert(&row->table->idl->txn->txn_rows, &row->txn_node,
3867 uuid_hash(&row->uuid));
3868 }
3869 }
3870
3871 /* Inserts a new Set Operation into current transaction. */
3872 static void
3873 ovsdb_idl_txn_add_set_op(struct ovsdb_idl_row *row,
3874 const struct ovsdb_idl_column *column,
3875 struct ovsdb_datum *datum,
3876 enum set_op_type op_type)
3877 {
3878 const struct ovsdb_idl_table_class *class;
3879 size_t column_idx;
3880 struct set_op *set_op;
3881
3882 class = row->table->class_;
3883 column_idx = column - class->columns;
3884
3885 /* Check if a set operation list exists for this column. */
3886 if (!row->set_op_written) {
3887 row->set_op_written = bitmap_allocate(class->n_columns);
3888 row->set_op_lists = xzalloc(class->n_columns *
3889 sizeof *row->set_op_lists);
3890 }
3891 if (!row->set_op_lists[column_idx]) {
3892 row->set_op_lists[column_idx] = set_op_list_create();
3893 }
3894
3895 /* Add a set operation to the corresponding list. */
3896 set_op = set_op_create(datum, op_type);
3897 bitmap_set1(row->set_op_written, column_idx);
3898 set_op_list_add(row->set_op_lists[column_idx], set_op, &column->type);
3899
3900 /* Add this row to the transactions's list of rows. */
3901 if (hmap_node_is_null(&row->txn_node)) {
3902 hmap_insert(&row->table->idl->txn->txn_rows, &row->txn_node,
3903 uuid_hash(&row->uuid));
3904 }
3905 }
3906
3907 static bool
3908 is_valid_partial_update(const struct ovsdb_idl_row *row,
3909 const struct ovsdb_idl_column *column,
3910 struct ovsdb_datum *datum)
3911 {
3912 /* Verify that this column is being monitored. */
3913 unsigned int column_idx = column - row->table->class_->columns;
3914 if (!(row->table->modes[column_idx] & OVSDB_IDL_MONITOR)) {
3915 VLOG_WARN("cannot partially update non-monitored column");
3916 return false;
3917 }
3918
3919 /* Verify that the update affects a single element. */
3920 if (datum->n != 1) {
3921 VLOG_WARN("invalid datum for partial update");
3922 return false;
3923 }
3924
3925 return true;
3926 }
3927
3928 /* Inserts the value described in 'datum' into the map in 'column' in
3929 * 'row_'. If the value doesn't already exist in 'column' then it's value
3930 * is added. The value in 'datum' must be of the same type as the values
3931 * in 'column'. This function takes ownership of 'datum'.
3932 *
3933 * Usually this function is used indirectly through one of the "update"
3934 * functions generated by vswitch-idl. */
3935 void
3936 ovsdb_idl_txn_write_partial_set(const struct ovsdb_idl_row *row_,
3937 const struct ovsdb_idl_column *column,
3938 struct ovsdb_datum *datum)
3939 {
3940 struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
3941 enum set_op_type op_type;
3942
3943 if (!is_valid_partial_update(row, column, datum)) {
3944 ovsdb_datum_destroy(datum, &column->type);
3945 free(datum);
3946 return;
3947 }
3948
3949 op_type = SET_OP_INSERT;
3950
3951 ovsdb_idl_txn_add_set_op(row, column, datum, op_type);
3952 }
3953
3954 /* Deletes the value specified in 'datum' from the set in 'column' in 'row_'.
3955 * The value in 'datum' must be of the same type as the keys in 'column'.
3956 * This function takes ownership of 'datum'.
3957 *
3958 * Usually this function is used indirectly through one of the "update"
3959 * functions generated by vswitch-idl. */
3960 void
3961 ovsdb_idl_txn_delete_partial_set(const struct ovsdb_idl_row *row_,
3962 const struct ovsdb_idl_column *column,
3963 struct ovsdb_datum *datum)
3964 {
3965 struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
3966
3967 if (!is_valid_partial_update(row, column, datum)) {
3968 struct ovsdb_type type_ = column->type;
3969 type_.value.type = OVSDB_TYPE_VOID;
3970 ovsdb_datum_destroy(datum, &type_);
3971 free(datum);
3972 return;
3973 }
3974 ovsdb_idl_txn_add_set_op(row, column, datum, SET_OP_DELETE);
3975 }
3976
3977 /* Inserts the key-value specified in 'datum' into the map in 'column' in
3978 * 'row_'. If the key already exist in 'column', then it's value is updated
3979 * with the value in 'datum'. The key-value in 'datum' must be of the same type
3980 * as the keys-values in 'column'. This function takes ownership of 'datum'.
3981 *
3982 * Usually this function is used indirectly through one of the "update"
3983 * functions generated by vswitch-idl. */
3984 void
3985 ovsdb_idl_txn_write_partial_map(const struct ovsdb_idl_row *row_,
3986 const struct ovsdb_idl_column *column,
3987 struct ovsdb_datum *datum)
3988 {
3989 struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
3990 enum ovsdb_atomic_type key_type;
3991 enum map_op_type op_type;
3992 unsigned int pos;
3993 const struct ovsdb_datum *old_datum;
3994
3995 if (!is_valid_partial_update(row, column, datum)) {
3996 ovsdb_datum_destroy(datum, &column->type);
3997 free(datum);
3998 return;
3999 }
4000
4001 /* Find out if this is an insert or an update. */
4002 key_type = column->type.key.type;
4003 old_datum = ovsdb_idl_read(row, column);
4004 pos = ovsdb_datum_find_key(old_datum, &datum->keys[0], key_type);
4005 op_type = pos == UINT_MAX ? MAP_OP_INSERT : MAP_OP_UPDATE;
4006
4007 ovsdb_idl_txn_add_map_op(row, column, datum, op_type);
4008 }
4009
4010 /* Deletes the key specified in 'datum' from the map in 'column' in 'row_'.
4011 * The key in 'datum' must be of the same type as the keys in 'column'.
4012 * The value in 'datum' must be NULL. This function takes ownership of
4013 * 'datum'.
4014 *
4015 * Usually this function is used indirectly through one of the "update"
4016 * functions generated by vswitch-idl. */
4017 void
4018 ovsdb_idl_txn_delete_partial_map(const struct ovsdb_idl_row *row_,
4019 const struct ovsdb_idl_column *column,
4020 struct ovsdb_datum *datum)
4021 {
4022 struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
4023
4024 if (!is_valid_partial_update(row, column, datum)) {
4025 struct ovsdb_type type_ = column->type;
4026 type_.value.type = OVSDB_TYPE_VOID;
4027 ovsdb_datum_destroy(datum, &type_);
4028 free(datum);
4029 return;
4030 }
4031 ovsdb_idl_txn_add_map_op(row, column, datum, MAP_OP_DELETE);
4032 }
4033
4034 void
4035 ovsdb_idl_loop_destroy(struct ovsdb_idl_loop *loop)
4036 {
4037 if (loop) {
4038 ovsdb_idl_destroy(loop->idl);
4039 }
4040 }
4041
4042 struct ovsdb_idl_txn *
4043 ovsdb_idl_loop_run(struct ovsdb_idl_loop *loop)
4044 {
4045 ovsdb_idl_run(loop->idl);
4046
4047 /* See if we can commit the loop->committing_txn. */
4048 if (loop->committing_txn) {
4049 ovsdb_idl_try_commit_loop_txn(loop, NULL);
4050 }
4051
4052 loop->open_txn = (loop->committing_txn
4053 || ovsdb_idl_get_seqno(loop->idl) == loop->skip_seqno
4054 ? NULL
4055 : ovsdb_idl_txn_create(loop->idl));
4056 if (loop->open_txn) {
4057 ovsdb_idl_txn_add_comment(loop->open_txn, "%s", program_name);
4058 }
4059 return loop->open_txn;
4060 }
4061
4062 /* Attempts to commit the current transaction, if one is open.
4063 *
4064 * If a transaction was open, in this or a previous iteration of the main loop,
4065 * and had not before finished committing (successfully or unsuccessfully), the
4066 * return value is one of:
4067 *
4068 * 1: The transaction committed successfully (or it did not change anything in
4069 * the database).
4070 * 0: The transaction failed.
4071 * -1: The commit is still in progress.
4072 *
4073 * Thus, the return value is -1 if the transaction is in progress and otherwise
4074 * true for success, false for failure.
4075 *
4076 * (In the corner case where the IDL sends a transaction to the database and
4077 * the database commits it, and the connection between the IDL and the database
4078 * drops before the IDL receives the message confirming the commit, this
4079 * function can return 0 even though the transaction succeeded.)
4080 */
4081 static int
4082 ovsdb_idl_try_commit_loop_txn(struct ovsdb_idl_loop *loop,
4083 bool *may_need_wakeup)
4084 {
4085 if (!loop->committing_txn) {
4086 /* Not a meaningful return value: no transaction was in progress. */
4087 return 1;
4088 }
4089
4090 int retval;
4091 struct ovsdb_idl_txn *txn = loop->committing_txn;
4092
4093 enum ovsdb_idl_txn_status status = ovsdb_idl_txn_commit(txn);
4094 if (status != TXN_INCOMPLETE) {
4095 switch (status) {
4096 case TXN_TRY_AGAIN:
4097 /* We want to re-evaluate the database when it's changed from
4098 * the contents that it had when we started the commit. (That
4099 * might have already happened.) */
4100 loop->skip_seqno = loop->precommit_seqno;
4101 if (ovsdb_idl_get_seqno(loop->idl) != loop->skip_seqno
4102 && may_need_wakeup) {
4103 *may_need_wakeup = true;
4104 }
4105 retval = 0;
4106 break;
4107
4108 case TXN_SUCCESS:
4109 /* Possibly some work on the database was deferred because no
4110 * further transaction could proceed. Wake up again. */
4111 retval = 1;
4112 loop->cur_cfg = loop->next_cfg;
4113 if (may_need_wakeup) {
4114 *may_need_wakeup = true;
4115 }
4116 break;
4117
4118 case TXN_UNCHANGED:
4119 retval = 1;
4120 loop->cur_cfg = loop->next_cfg;
4121 break;
4122
4123 case TXN_ABORTED:
4124 case TXN_NOT_LOCKED:
4125 case TXN_ERROR:
4126 retval = 0;
4127 break;
4128
4129 case TXN_UNCOMMITTED:
4130 case TXN_INCOMPLETE:
4131 default:
4132 OVS_NOT_REACHED();
4133 }
4134 ovsdb_idl_txn_destroy(txn);
4135 loop->committing_txn = NULL;
4136 } else {
4137 retval = -1;
4138 }
4139
4140 return retval;
4141 }
4142
4143 /* Attempts to commit the current transaction, if one is open, and sets up the
4144 * poll loop to wake up when some more work might be needed.
4145 *
4146 * If a transaction was open, in this or a previous iteration of the main loop,
4147 * and had not before finished committing (successfully or unsuccessfully), the
4148 * return value is one of:
4149 *
4150 * 1: The transaction committed successfully (or it did not change anything in
4151 * the database).
4152 * 0: The transaction failed.
4153 * -1: The commit is still in progress.
4154 *
4155 * Thus, the return value is -1 if the transaction is in progress and otherwise
4156 * true for success, false for failure.
4157 *
4158 * (In the corner case where the IDL sends a transaction to the database and
4159 * the database commits it, and the connection between the IDL and the database
4160 * drops before the IDL receives the message confirming the commit, this
4161 * function can return 0 even though the transaction succeeded.)
4162 */
4163 int
4164 ovsdb_idl_loop_commit_and_wait(struct ovsdb_idl_loop *loop)
4165 {
4166 if (loop->open_txn) {
4167 loop->committing_txn = loop->open_txn;
4168 loop->open_txn = NULL;
4169
4170 loop->precommit_seqno = ovsdb_idl_get_seqno(loop->idl);
4171 }
4172
4173 bool may_need_wakeup = false;
4174 int retval = ovsdb_idl_try_commit_loop_txn(loop, &may_need_wakeup);
4175 if (may_need_wakeup) {
4176 poll_immediate_wake();
4177 }
4178 ovsdb_idl_wait(loop->idl);
4179
4180 return retval;
4181 }