1 /* Copyright (c) 2009, 2010, 2011, 2012, 2014, 2016, 2017 Nicira, Inc.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
18 #include "ovsdb-data.h"
25 #include "openvswitch/dynamic-string.h"
27 #include "ovs-thread.h"
28 #include "ovsdb-error.h"
29 #include "ovsdb-parser.h"
30 #include "openvswitch/json.h"
31 #include "openvswitch/shash.h"
38 wrap_json(const char *name
, struct json
*wrapped
)
40 return json_array_create_2(json_string_create(name
), wrapped
);
43 /* Initializes 'atom' with the default value of the given 'type'.
45 * The default value for an atom is as defined in RFC 7047:
47 * - "integer" or "real": 0
51 * - "string": "" (the empty string)
53 * - "uuid": 00000000-0000-0000-0000-000000000000
55 * The caller must eventually arrange for 'atom' to be destroyed (with
56 * ovsdb_atom_destroy()). */
58 ovsdb_atom_init_default(union ovsdb_atom
*atom
, enum ovsdb_atomic_type type
)
64 case OVSDB_TYPE_INTEGER
:
72 case OVSDB_TYPE_BOOLEAN
:
73 atom
->boolean
= false;
76 case OVSDB_TYPE_STRING
:
77 atom
->string
= xmemdup("", 1);
81 uuid_zero(&atom
->uuid
);
90 /* Returns a read-only atom of the given 'type' that has the default value for
91 * 'type'. The caller must not modify or free the returned atom.
93 * See ovsdb_atom_init_default() for an explanation of the default value of an
95 const union ovsdb_atom
*
96 ovsdb_atom_default(enum ovsdb_atomic_type type
)
98 static union ovsdb_atom default_atoms
[OVSDB_N_TYPES
];
99 static struct ovsthread_once once
= OVSTHREAD_ONCE_INITIALIZER
;
101 if (ovsthread_once_start(&once
)) {
104 for (i
= 0; i
< OVSDB_N_TYPES
; i
++) {
105 if (i
!= OVSDB_TYPE_VOID
) {
106 ovsdb_atom_init_default(&default_atoms
[i
], i
);
109 ovsthread_once_done(&once
);
112 ovs_assert(ovsdb_atomic_type_is_valid(type
));
113 return &default_atoms
[type
];
116 /* Returns true if 'atom', which must have the given 'type', has the default
117 * value for that type.
119 * See ovsdb_atom_init_default() for an explanation of the default value of an
122 ovsdb_atom_is_default(const union ovsdb_atom
*atom
,
123 enum ovsdb_atomic_type type
)
126 case OVSDB_TYPE_VOID
:
129 case OVSDB_TYPE_INTEGER
:
130 return atom
->integer
== 0;
132 case OVSDB_TYPE_REAL
:
133 return atom
->real
== 0.0;
135 case OVSDB_TYPE_BOOLEAN
:
136 return atom
->boolean
== false;
138 case OVSDB_TYPE_STRING
:
139 return atom
->string
[0] == '\0';
141 case OVSDB_TYPE_UUID
:
142 return uuid_is_zero(&atom
->uuid
);
150 /* Initializes 'new' as a copy of 'old', with the given 'type'.
152 * The caller must eventually arrange for 'new' to be destroyed (with
153 * ovsdb_atom_destroy()). */
155 ovsdb_atom_clone(union ovsdb_atom
*new, const union ovsdb_atom
*old
,
156 enum ovsdb_atomic_type type
)
159 case OVSDB_TYPE_VOID
:
162 case OVSDB_TYPE_INTEGER
:
163 new->integer
= old
->integer
;
166 case OVSDB_TYPE_REAL
:
167 new->real
= old
->real
;
170 case OVSDB_TYPE_BOOLEAN
:
171 new->boolean
= old
->boolean
;
174 case OVSDB_TYPE_STRING
:
175 new->string
= xstrdup(old
->string
);
178 case OVSDB_TYPE_UUID
:
179 new->uuid
= old
->uuid
;
188 /* Swaps the contents of 'a' and 'b', which need not have the same type. */
190 ovsdb_atom_swap(union ovsdb_atom
*a
, union ovsdb_atom
*b
)
192 union ovsdb_atom tmp
= *a
;
197 /* Returns a hash value for 'atom', which has the specified 'type', folding
198 * 'basis' into the calculation. */
200 ovsdb_atom_hash(const union ovsdb_atom
*atom
, enum ovsdb_atomic_type type
,
204 case OVSDB_TYPE_VOID
:
207 case OVSDB_TYPE_INTEGER
:
208 return hash_int(atom
->integer
, basis
);
210 case OVSDB_TYPE_REAL
:
211 return hash_double(atom
->real
, basis
);
213 case OVSDB_TYPE_BOOLEAN
:
214 return hash_boolean(atom
->boolean
, basis
);
216 case OVSDB_TYPE_STRING
:
217 return hash_string(atom
->string
, basis
);
219 case OVSDB_TYPE_UUID
:
220 return hash_int(uuid_hash(&atom
->uuid
), basis
);
228 /* Compares 'a' and 'b', which both have type 'type', and returns a
229 * strcmp()-like result. */
231 ovsdb_atom_compare_3way(const union ovsdb_atom
*a
,
232 const union ovsdb_atom
*b
,
233 enum ovsdb_atomic_type type
)
236 case OVSDB_TYPE_VOID
:
239 case OVSDB_TYPE_INTEGER
:
240 return a
->integer
< b
->integer
? -1 : a
->integer
> b
->integer
;
242 case OVSDB_TYPE_REAL
:
243 return a
->real
< b
->real
? -1 : a
->real
> b
->real
;
245 case OVSDB_TYPE_BOOLEAN
:
246 return a
->boolean
- b
->boolean
;
248 case OVSDB_TYPE_STRING
:
249 return strcmp(a
->string
, b
->string
);
251 case OVSDB_TYPE_UUID
:
252 return uuid_compare_3way(&a
->uuid
, &b
->uuid
);
260 static struct ovsdb_error
*
261 unwrap_json(const struct json
*json
, const char *name
,
262 enum json_type value_type
, const struct json
**value
)
264 if (json
->type
!= JSON_ARRAY
265 || json
->array
.n
!= 2
266 || json
->array
.elems
[0]->type
!= JSON_STRING
267 || (name
&& strcmp(json
->array
.elems
[0]->string
, name
))
268 || json
->array
.elems
[1]->type
!= value_type
)
271 return ovsdb_syntax_error(json
, NULL
, "expected [\"%s\", <%s>]", name
,
272 json_type_to_string(value_type
));
274 *value
= json
->array
.elems
[1];
278 static struct ovsdb_error
*
279 parse_json_pair(const struct json
*json
,
280 const struct json
**elem0
, const struct json
**elem1
)
282 if (json
->type
!= JSON_ARRAY
|| json
->array
.n
!= 2) {
283 return ovsdb_syntax_error(json
, NULL
, "expected 2-element array");
285 *elem0
= json
->array
.elems
[0];
286 *elem1
= json
->array
.elems
[1];
291 ovsdb_symbol_referenced(struct ovsdb_symbol
*symbol
,
292 const struct ovsdb_base_type
*base
)
294 ovs_assert(base
->type
== OVSDB_TYPE_UUID
);
296 if (base
->uuid
.refTableName
) {
297 switch (base
->uuid
.refType
) {
298 case OVSDB_REF_STRONG
:
299 symbol
->strong_ref
= true;
302 symbol
->weak_ref
= true;
308 static union ovsdb_atom
*
309 alloc_default_atoms(enum ovsdb_atomic_type type
, size_t n
)
311 if (type
!= OVSDB_TYPE_VOID
&& n
) {
312 union ovsdb_atom
*atoms
;
315 atoms
= xmalloc(n
* sizeof *atoms
);
316 for (i
= 0; i
< n
; i
++) {
317 ovsdb_atom_init_default(&atoms
[i
], type
);
321 /* Avoid wasting memory in the n == 0 case, because xmalloc(0) is
322 * treated as xmalloc(1). */
327 static struct ovsdb_error
* OVS_WARN_UNUSED_RESULT
328 ovsdb_atom_parse_uuid(struct uuid
*uuid
, const struct json
*json
,
329 struct ovsdb_symbol_table
*symtab
,
330 const struct ovsdb_base_type
*base
)
332 struct ovsdb_error
*error0
;
333 const struct json
*value
;
335 error0
= unwrap_json(json
, "uuid", JSON_STRING
, &value
);
337 const char *uuid_string
= json_string(value
);
338 if (!uuid_from_string(uuid
, uuid_string
)) {
339 return ovsdb_syntax_error(json
, NULL
, "\"%s\" is not a valid UUID",
343 struct ovsdb_error
*error1
;
345 error1
= unwrap_json(json
, "named-uuid", JSON_STRING
, &value
);
347 struct ovsdb_symbol
*symbol
;
349 ovsdb_error_destroy(error0
);
350 if (!ovsdb_parser_is_id(json_string(value
))) {
351 return ovsdb_syntax_error(json
, NULL
, "named-uuid string is "
355 symbol
= ovsdb_symbol_table_insert(symtab
, json_string(value
));
356 *uuid
= symbol
->uuid
;
357 ovsdb_symbol_referenced(symbol
, base
);
360 ovsdb_error_destroy(error1
);
366 static struct ovsdb_error
* OVS_WARN_UNUSED_RESULT
367 ovsdb_atom_from_json__(union ovsdb_atom
*atom
,
368 const struct ovsdb_base_type
*base
,
369 const struct json
*json
,
370 struct ovsdb_symbol_table
*symtab
)
372 enum ovsdb_atomic_type type
= base
->type
;
375 case OVSDB_TYPE_VOID
:
378 case OVSDB_TYPE_INTEGER
:
379 if (json
->type
== JSON_INTEGER
) {
380 atom
->integer
= json
->integer
;
385 case OVSDB_TYPE_REAL
:
386 if (json
->type
== JSON_INTEGER
) {
387 atom
->real
= json
->integer
;
389 } else if (json
->type
== JSON_REAL
) {
390 atom
->real
= json
->real
;
395 case OVSDB_TYPE_BOOLEAN
:
396 if (json
->type
== JSON_TRUE
) {
397 atom
->boolean
= true;
399 } else if (json
->type
== JSON_FALSE
) {
400 atom
->boolean
= false;
405 case OVSDB_TYPE_STRING
:
406 if (json
->type
== JSON_STRING
) {
407 atom
->string
= xstrdup(json
->string
);
412 case OVSDB_TYPE_UUID
:
413 return ovsdb_atom_parse_uuid(&atom
->uuid
, json
, symtab
, base
);
420 return ovsdb_syntax_error(json
, NULL
, "expected %s",
421 ovsdb_atomic_type_to_string(type
));
424 /* Parses 'json' as an atom of the type described by 'base'. If successful,
425 * returns NULL and initializes 'atom' with the parsed atom. On failure,
426 * returns an error and the contents of 'atom' are indeterminate. The caller
427 * is responsible for freeing the error or the atom that is returned.
429 * Violations of constraints expressed by 'base' are treated as errors.
431 * If 'symtab' is nonnull, then named UUIDs in 'symtab' are accepted. Refer to
432 * RFC 7047 for information about this, and for the syntax that this function
433 * accepts. If 'base' is a reference and a symbol is parsed, then the symbol's
434 * 'strong_ref' or 'weak_ref' member is set to true, as appropriate. */
436 ovsdb_atom_from_json(union ovsdb_atom
*atom
,
437 const struct ovsdb_base_type
*base
,
438 const struct json
*json
,
439 struct ovsdb_symbol_table
*symtab
)
441 struct ovsdb_error
*error
;
443 error
= ovsdb_atom_from_json__(atom
, base
, json
, symtab
);
448 error
= ovsdb_atom_check_constraints(atom
, base
);
450 ovsdb_atom_destroy(atom
, base
->type
);
455 /* Converts 'atom', of the specified 'type', to JSON format, and returns the
456 * JSON. The caller is responsible for freeing the returned JSON.
458 * Refer to RFC 7047 for the format of the JSON that this function produces. */
460 ovsdb_atom_to_json(const union ovsdb_atom
*atom
, enum ovsdb_atomic_type type
)
463 case OVSDB_TYPE_VOID
:
466 case OVSDB_TYPE_INTEGER
:
467 return json_integer_create(atom
->integer
);
469 case OVSDB_TYPE_REAL
:
470 return json_real_create(atom
->real
);
472 case OVSDB_TYPE_BOOLEAN
:
473 return json_boolean_create(atom
->boolean
);
475 case OVSDB_TYPE_STRING
:
476 return json_string_create(atom
->string
);
478 case OVSDB_TYPE_UUID
:
479 return wrap_json("uuid", json_string_create_nocopy(
480 xasprintf(UUID_FMT
, UUID_ARGS(&atom
->uuid
))));
489 ovsdb_atom_from_string__(union ovsdb_atom
*atom
,
490 union ovsdb_atom
**range_end_atom
,
491 const struct ovsdb_base_type
*base
, const char *s
,
492 struct ovsdb_symbol_table
*symtab
)
494 enum ovsdb_atomic_type type
= base
->type
;
497 case OVSDB_TYPE_VOID
:
500 case OVSDB_TYPE_INTEGER
: {
501 long long int integer
, end
;
503 && str_to_llong_range(s
, 10, &integer
, &end
)) {
505 return xasprintf("\"%s\" is not a valid range. "
506 "Range end cannot be before start.", s
);
508 *range_end_atom
= alloc_default_atoms(type
, 1);
509 if (!(*range_end_atom
)) {
510 return xasprintf("\"%s\" is not a valid range", s
);
512 (*range_end_atom
)->integer
= end
;
513 } else if (!str_to_llong(s
, 10, &integer
)) {
514 return xasprintf("\"%s\" is not a valid integer or range", s
);
516 atom
->integer
= integer
;
520 case OVSDB_TYPE_REAL
:
521 if (!str_to_double(s
, &atom
->real
)) {
522 return xasprintf("\"%s\" is not a valid real number", s
);
524 /* Our JSON input routines map negative zero to zero, so do that here
525 * too for consistency. */
526 if (atom
->real
== 0.0) {
531 case OVSDB_TYPE_BOOLEAN
:
532 if (!strcmp(s
, "true") || !strcmp(s
, "yes") || !strcmp(s
, "on")
533 || !strcmp(s
, "1")) {
534 atom
->boolean
= true;
535 } else if (!strcmp(s
, "false") || !strcmp(s
, "no") || !strcmp(s
, "off")
536 || !strcmp(s
, "0")) {
537 atom
->boolean
= false;
539 return xasprintf("\"%s\" is not a valid boolean "
540 "(use \"true\" or \"false\")", s
);
544 case OVSDB_TYPE_STRING
:
546 return xstrdup("An empty string is not valid as input; "
547 "use \"\" to represent the empty string");
548 } else if (*s
== '"') {
549 size_t s_len
= strlen(s
);
551 if (s_len
< 2 || s
[s_len
- 1] != '"') {
552 return xasprintf("%s: missing quote at end of "
554 } else if (!json_string_unescape(s
+ 1, s_len
- 2,
556 char *error
= xasprintf("%s: %s", s
, atom
->string
);
561 atom
->string
= xstrdup(s
);
565 case OVSDB_TYPE_UUID
:
567 struct ovsdb_symbol
*symbol
= ovsdb_symbol_table_insert(symtab
, s
);
568 atom
->uuid
= symbol
->uuid
;
569 ovsdb_symbol_referenced(symbol
, base
);
570 } else if (!uuid_from_string(&atom
->uuid
, s
)) {
571 return xasprintf("\"%s\" is not a valid UUID", s
);
583 /* Initializes 'atom' and optionally 'range_end_atom' to a value of type 'base'
584 * parsed from 's', which takes one of the following forms:
586 * - OVSDB_TYPE_INTEGER: A decimal integer optionally preceded by a sign
587 * or two decimal integers optionally preceded by a sign and separated
588 * by a hyphen, representing inclusive range of integers
589 * ['atom', 'range_end_atom'].
591 * - OVSDB_TYPE_REAL: A floating-point number in the format accepted by
594 * - OVSDB_TYPE_BOOLEAN: "true", "yes", "on", "1" for true, or "false",
595 * "no", "off", or "0" for false.
597 * - OVSDB_TYPE_STRING: A JSON string if it begins with a quote, otherwise
598 * an arbitrary string.
600 * - OVSDB_TYPE_UUID: A UUID in RFC 4122 format. If 'symtab' is nonnull,
601 * then an identifier beginning with '@' is also acceptable. If the
602 * named identifier is already in 'symtab', then the associated UUID is
603 * used; otherwise, a new, random UUID is used and added to the symbol
604 * table. If 'base' is a reference and a symbol is parsed, then the
605 * symbol's 'strong_ref' or 'weak_ref' member is set to true, as
608 * Returns a null pointer if successful, otherwise an error message describing
609 * the problem. On failure, the contents of 'atom' are indeterminate. The
610 * caller is responsible for freeing the atom or the error.
612 * Does not attempt to parse range if 'range_end_atom' is a null pointer.
613 * Dynamically allocates ovdsb_atom and stores its address in '*range_end_atom'
614 * if successfully parses range. Caller is responsible for deallocating
615 * the memory by calling 'ovsdb_atom_destroy' and then 'free' on the address.
616 * Does not allocate memory and sets '*range_end_atom' to a null pointer
617 * if does not parse a range or fails for any reason.
620 ovsdb_atom_from_string(union ovsdb_atom
*atom
,
621 union ovsdb_atom
**range_end_atom
,
622 const struct ovsdb_base_type
*base
, const char *s
,
623 struct ovsdb_symbol_table
*symtab
)
625 struct ovsdb_error
*error
;
628 if (range_end_atom
) {
629 *range_end_atom
= NULL
;
632 msg
= ovsdb_atom_from_string__(atom
, range_end_atom
, base
, s
, symtab
);
637 error
= ovsdb_atom_check_constraints(atom
, base
);
639 if (!error
&& range_end_atom
&& *range_end_atom
) {
640 /* Check range constraints */
641 int64_t start
= atom
->integer
;
642 int64_t end
= (*range_end_atom
)->integer
;
644 for (int64_t i
= start
+ 1; i
<= end
; i
++) {
645 union ovsdb_atom ai
= { .integer
= i
};
646 error
= ovsdb_atom_check_constraints(&ai
, base
);
652 error
= ovsdb_atom_check_constraints(*range_end_atom
, base
);
656 error
= ovsdb_atom_range_check_size(start
, end
);
661 ovsdb_atom_destroy(atom
, base
->type
);
662 if (range_end_atom
&& *range_end_atom
) {
663 ovsdb_atom_destroy(*range_end_atom
, base
->type
);
664 free(*range_end_atom
);
665 *range_end_atom
= NULL
;
667 msg
= ovsdb_error_to_string_free(error
);
673 string_needs_quotes(const char *s
)
679 if (!isalpha(c
) && c
!= '_') {
683 while ((c
= *p
++) != '\0') {
684 if (!isalpha(c
) && c
!= '_' && c
!= '-' && c
!= '.') {
689 if (!strcmp(s
, "true") || !strcmp(s
, "false")) {
696 /* Appends 'atom' (which has the given 'type') to 'out', in a format acceptable
697 * to ovsdb_atom_from_string(). */
699 ovsdb_atom_to_string(const union ovsdb_atom
*atom
, enum ovsdb_atomic_type type
,
703 case OVSDB_TYPE_VOID
:
706 case OVSDB_TYPE_INTEGER
:
707 ds_put_format(out
, "%"PRId64
, atom
->integer
);
710 case OVSDB_TYPE_REAL
:
711 ds_put_format(out
, "%.*g", DBL_DIG
, atom
->real
);
714 case OVSDB_TYPE_BOOLEAN
:
715 ds_put_cstr(out
, atom
->boolean
? "true" : "false");
718 case OVSDB_TYPE_STRING
:
719 if (string_needs_quotes(atom
->string
)) {
722 json
.type
= JSON_STRING
;
723 json
.string
= atom
->string
;
724 json_to_ds(&json
, 0, out
);
726 ds_put_cstr(out
, atom
->string
);
730 case OVSDB_TYPE_UUID
:
731 ds_put_format(out
, UUID_FMT
, UUID_ARGS(&atom
->uuid
));
740 /* Appends 'atom' (which has the given 'type') to 'out', in a bare string
741 * format that cannot be parsed uniformly back into a datum but is easier for
742 * shell scripts, etc., to deal with. */
744 ovsdb_atom_to_bare(const union ovsdb_atom
*atom
, enum ovsdb_atomic_type type
,
747 if (type
== OVSDB_TYPE_STRING
) {
748 ds_put_cstr(out
, atom
->string
);
750 ovsdb_atom_to_string(atom
, type
, out
);
754 static struct ovsdb_error
*
755 check_string_constraints(const char *s
,
756 const struct ovsdb_string_constraints
*c
)
761 msg
= utf8_validate(s
, &n_chars
);
763 struct ovsdb_error
*error
;
765 error
= ovsdb_error("constraint violation",
766 "not a valid UTF-8 string: %s", msg
);
771 if (n_chars
< c
->minLen
) {
773 "constraint violation",
774 "\"%s\" length %"PRIuSIZE
" is less than minimum allowed "
775 "length %u", s
, n_chars
, c
->minLen
);
776 } else if (n_chars
> c
->maxLen
) {
778 "constraint violation",
779 "\"%s\" length %"PRIuSIZE
" is greater than maximum allowed "
780 "length %u", s
, n_chars
, c
->maxLen
);
786 /* Checks whether 'atom' meets the constraints (if any) defined in 'base'.
787 * (base->type must specify 'atom''s type.) Returns a null pointer if the
788 * constraints are met, otherwise an error that explains the violation.
790 * Checking UUID constraints is deferred to transaction commit time, so this
791 * function does nothing for UUID constraints. */
793 ovsdb_atom_check_constraints(const union ovsdb_atom
*atom
,
794 const struct ovsdb_base_type
*base
)
797 && ovsdb_datum_find_key(base
->enum_
, atom
, base
->type
) == UINT_MAX
) {
798 struct ovsdb_error
*error
;
799 struct ds actual
= DS_EMPTY_INITIALIZER
;
800 struct ds valid
= DS_EMPTY_INITIALIZER
;
802 ovsdb_atom_to_string(atom
, base
->type
, &actual
);
803 ovsdb_datum_to_string(base
->enum_
,
804 ovsdb_base_type_get_enum_type(base
->type
),
806 error
= ovsdb_error("constraint violation",
807 "%s is not one of the allowed values (%s)",
808 ds_cstr(&actual
), ds_cstr(&valid
));
815 switch (base
->type
) {
816 case OVSDB_TYPE_VOID
:
819 case OVSDB_TYPE_INTEGER
:
820 if (atom
->integer
>= base
->integer
.min
821 && atom
->integer
<= base
->integer
.max
) {
823 } else if (base
->integer
.min
!= INT64_MIN
) {
824 if (base
->integer
.max
!= INT64_MAX
) {
825 return ovsdb_error("constraint violation",
826 "%"PRId64
" is not in the valid range "
827 "%"PRId64
" to %"PRId64
" (inclusive)",
829 base
->integer
.min
, base
->integer
.max
);
831 return ovsdb_error("constraint violation",
832 "%"PRId64
" is less than minimum allowed "
834 atom
->integer
, base
->integer
.min
);
837 return ovsdb_error("constraint violation",
838 "%"PRId64
" is greater than maximum allowed "
840 atom
->integer
, base
->integer
.max
);
844 case OVSDB_TYPE_REAL
:
845 if (atom
->real
>= base
->real
.min
&& atom
->real
<= base
->real
.max
) {
847 } else if (base
->real
.min
!= -DBL_MAX
) {
848 if (base
->real
.max
!= DBL_MAX
) {
849 return ovsdb_error("constraint violation",
850 "%.*g is not in the valid range "
851 "%.*g to %.*g (inclusive)",
853 DBL_DIG
, base
->real
.min
,
854 DBL_DIG
, base
->real
.max
);
856 return ovsdb_error("constraint violation",
857 "%.*g is less than minimum allowed "
860 DBL_DIG
, base
->real
.min
);
863 return ovsdb_error("constraint violation",
864 "%.*g is greater than maximum allowed "
867 DBL_DIG
, base
->real
.max
);
871 case OVSDB_TYPE_BOOLEAN
:
874 case OVSDB_TYPE_STRING
:
875 return check_string_constraints(atom
->string
, &base
->string
);
877 case OVSDB_TYPE_UUID
:
886 /* Initializes 'datum' as an empty datum. (An empty datum can be treated as
889 ovsdb_datum_init_empty(struct ovsdb_datum
*datum
)
893 datum
->values
= NULL
;
896 /* Initializes 'datum' as a datum that has the default value for 'type'.
898 * The default value for a particular type is as defined in RFC 7047:
900 * - If n_min is 0, then the default value is the empty set (or map).
902 * - If n_min is 1, the default value is a single value or a single
903 * key-value pair, whose key and value are the defaults for their
904 * atomic types. (See ovsdb_atom_init_default() for details.)
906 * - n_min > 1 is invalid. See ovsdb_type_is_valid().
909 ovsdb_datum_init_default(struct ovsdb_datum
*datum
,
910 const struct ovsdb_type
*type
)
912 datum
->n
= type
->n_min
;
913 datum
->keys
= alloc_default_atoms(type
->key
.type
, datum
->n
);
914 datum
->values
= alloc_default_atoms(type
->value
.type
, datum
->n
);
917 /* Returns a read-only datum of the given 'type' that has the default value for
918 * 'type'. The caller must not modify or free the returned datum.
920 * See ovsdb_datum_init_default() for an explanation of the default value of a
922 const struct ovsdb_datum
*
923 ovsdb_datum_default(const struct ovsdb_type
*type
)
925 if (type
->n_min
== 0) {
926 static const struct ovsdb_datum empty
;
928 } else if (type
->n_min
== 1) {
929 static struct ovsdb_datum default_data
[OVSDB_N_TYPES
][OVSDB_N_TYPES
];
930 struct ovsdb_datum
*d
;
931 int kt
= type
->key
.type
;
932 int vt
= type
->value
.type
;
934 ovs_assert(ovsdb_type_is_valid(type
));
936 d
= &default_data
[kt
][vt
];
939 d
->keys
= CONST_CAST(union ovsdb_atom
*, ovsdb_atom_default(kt
));
940 if (vt
!= OVSDB_TYPE_VOID
) {
941 d
->values
= CONST_CAST(union ovsdb_atom
*,
942 ovsdb_atom_default(vt
));
951 /* Returns true if 'datum', which must have the given 'type', has the default
952 * value for that type.
954 * See ovsdb_datum_init_default() for an explanation of the default value of a
957 ovsdb_datum_is_default(const struct ovsdb_datum
*datum
,
958 const struct ovsdb_type
*type
)
962 if (datum
->n
!= type
->n_min
) {
965 for (i
= 0; i
< datum
->n
; i
++) {
966 if (!ovsdb_atom_is_default(&datum
->keys
[i
], type
->key
.type
)) {
969 if (type
->value
.type
!= OVSDB_TYPE_VOID
970 && !ovsdb_atom_is_default(&datum
->values
[i
], type
->value
.type
)) {
978 static union ovsdb_atom
*
979 clone_atoms(const union ovsdb_atom
*old
, enum ovsdb_atomic_type type
, size_t n
)
981 if (type
!= OVSDB_TYPE_VOID
&& n
) {
982 union ovsdb_atom
*new;
985 new = xmalloc(n
* sizeof *new);
986 for (i
= 0; i
< n
; i
++) {
987 ovsdb_atom_clone(&new[i
], &old
[i
], type
);
991 /* Avoid wasting memory in the n == 0 case, because xmalloc(0) is
992 * treated as xmalloc(1). */
997 /* Initializes 'new' as a copy of 'old', with the given 'type'.
999 * The caller must eventually arrange for 'new' to be destroyed (with
1000 * ovsdb_datum_destroy()). */
1002 ovsdb_datum_clone(struct ovsdb_datum
*new, const struct ovsdb_datum
*old
,
1003 const struct ovsdb_type
*type
)
1005 unsigned int n
= old
->n
;
1007 new->keys
= clone_atoms(old
->keys
, type
->key
.type
, n
);
1008 new->values
= clone_atoms(old
->values
, type
->value
.type
, n
);
1012 free_data(enum ovsdb_atomic_type type
,
1013 union ovsdb_atom
*atoms
, size_t n_atoms
)
1015 if (ovsdb_atom_needs_destruction(type
)) {
1017 for (i
= 0; i
< n_atoms
; i
++) {
1018 ovsdb_atom_destroy(&atoms
[i
], type
);
1024 /* Frees the data owned by 'datum', which must have the given 'type'.
1026 * This does not actually call free(datum). If necessary, the caller must be
1027 * responsible for that. */
1029 ovsdb_datum_destroy(struct ovsdb_datum
*datum
, const struct ovsdb_type
*type
)
1031 free_data(type
->key
.type
, datum
->keys
, datum
->n
);
1032 free_data(type
->value
.type
, datum
->values
, datum
->n
);
1035 /* Swaps the contents of 'a' and 'b', which need not have the same type. */
1037 ovsdb_datum_swap(struct ovsdb_datum
*a
, struct ovsdb_datum
*b
)
1039 struct ovsdb_datum tmp
= *a
;
1044 struct ovsdb_datum_sort_cbdata
{
1045 enum ovsdb_atomic_type key_type
;
1046 enum ovsdb_atomic_type value_type
;
1047 struct ovsdb_datum
*datum
;
1051 ovsdb_datum_sort_compare_cb(size_t a
, size_t b
, void *cbdata_
)
1053 struct ovsdb_datum_sort_cbdata
*cbdata
= cbdata_
;
1056 retval
= ovsdb_atom_compare_3way(&cbdata
->datum
->keys
[a
],
1057 &cbdata
->datum
->keys
[b
],
1059 if (retval
|| cbdata
->value_type
== OVSDB_TYPE_VOID
) {
1063 return ovsdb_atom_compare_3way(&cbdata
->datum
->values
[a
],
1064 &cbdata
->datum
->values
[b
],
1065 cbdata
->value_type
);
1069 ovsdb_datum_sort_swap_cb(size_t a
, size_t b
, void *cbdata_
)
1071 struct ovsdb_datum_sort_cbdata
*cbdata
= cbdata_
;
1073 ovsdb_atom_swap(&cbdata
->datum
->keys
[a
], &cbdata
->datum
->keys
[b
]);
1074 if (cbdata
->datum
->values
) {
1075 ovsdb_atom_swap(&cbdata
->datum
->values
[a
], &cbdata
->datum
->values
[b
]);
1080 ovsdb_datum_sort__(struct ovsdb_datum
*datum
, enum ovsdb_atomic_type key_type
,
1081 enum ovsdb_atomic_type value_type
)
1083 struct ovsdb_datum_sort_cbdata cbdata
;
1085 cbdata
.key_type
= key_type
;
1086 cbdata
.value_type
= value_type
;
1087 cbdata
.datum
= datum
;
1088 sort(datum
->n
, ovsdb_datum_sort_compare_cb
, ovsdb_datum_sort_swap_cb
,
1092 /* The keys in an ovsdb_datum must be unique and in sorted order. Most
1093 * functions that modify an ovsdb_datum maintain these invariants. For those
1094 * that don't, this function checks and restores these invariants for 'datum',
1095 * whose keys are of type 'key_type'.
1097 * This function returns NULL if successful, otherwise an error message. The
1098 * caller must free the returned error when it is no longer needed. On error,
1099 * 'datum' is sorted but not unique. */
1100 struct ovsdb_error
*
1101 ovsdb_datum_sort(struct ovsdb_datum
*datum
, enum ovsdb_atomic_type key_type
)
1109 ovsdb_datum_sort__(datum
, key_type
, OVSDB_TYPE_VOID
);
1111 for (i
= 0; i
< datum
->n
- 1; i
++) {
1112 if (ovsdb_atom_equals(&datum
->keys
[i
], &datum
->keys
[i
+ 1],
1114 if (datum
->values
) {
1115 return ovsdb_error(NULL
, "map contains duplicate key");
1117 return ovsdb_error(NULL
, "set contains duplicate");
1124 /* This function is the same as ovsdb_datum_sort(), except that the caller
1125 * knows that 'datum' is unique. The operation therefore "cannot fail", so
1126 * this function assert-fails if it actually does. */
1128 ovsdb_datum_sort_assert(struct ovsdb_datum
*datum
,
1129 enum ovsdb_atomic_type key_type
)
1131 struct ovsdb_error
*error
= ovsdb_datum_sort(datum
, key_type
);
1137 /* This is similar to ovsdb_datum_sort(), except that it drops duplicate keys
1138 * instead of reporting an error. In a map type, the smallest value among a
1139 * group of duplicate pairs is retained and the others are dropped.
1141 * Returns the number of keys (or pairs) that were dropped. */
1143 ovsdb_datum_sort_unique(struct ovsdb_datum
*datum
,
1144 enum ovsdb_atomic_type key_type
,
1145 enum ovsdb_atomic_type value_type
)
1153 ovsdb_datum_sort__(datum
, key_type
, value_type
);
1156 for (src
= 1; src
< datum
->n
; src
++) {
1157 if (ovsdb_atom_equals(&datum
->keys
[src
], &datum
->keys
[dst
- 1],
1159 ovsdb_atom_destroy(&datum
->keys
[src
], key_type
);
1160 if (value_type
!= OVSDB_TYPE_VOID
) {
1161 ovsdb_atom_destroy(&datum
->values
[src
], value_type
);
1165 datum
->keys
[dst
] = datum
->keys
[src
];
1166 if (value_type
!= OVSDB_TYPE_VOID
) {
1167 datum
->values
[dst
] = datum
->values
[src
];
1174 return datum
->n
- src
;
1177 /* Checks that each of the atoms in 'datum' conforms to the constraints
1178 * specified by its 'type'. Returns an error if a constraint is violated,
1179 * otherwise a null pointer.
1181 * This function is not commonly useful because the most ordinary way to obtain
1182 * a datum is ultimately via ovsdb_atom_from_string() or
1183 * ovsdb_atom_from_json(), which check constraints themselves. */
1184 struct ovsdb_error
*
1185 ovsdb_datum_check_constraints(const struct ovsdb_datum
*datum
,
1186 const struct ovsdb_type
*type
)
1188 struct ovsdb_error
*error
;
1191 for (i
= 0; i
< datum
->n
; i
++) {
1192 error
= ovsdb_atom_check_constraints(&datum
->keys
[i
], &type
->key
);
1198 if (type
->value
.type
!= OVSDB_TYPE_VOID
) {
1199 for (i
= 0; i
< datum
->n
; i
++) {
1200 error
= ovsdb_atom_check_constraints(&datum
->values
[i
],
1211 static struct ovsdb_error
*
1212 ovsdb_datum_from_json__(struct ovsdb_datum
*datum
,
1213 const struct ovsdb_type
*type
,
1214 const struct json
*json
,
1215 struct ovsdb_symbol_table
*symtab
)
1217 struct ovsdb_error
*error
;
1219 if (ovsdb_type_is_map(type
)
1220 || (json
->type
== JSON_ARRAY
1221 && json
->array
.n
> 0
1222 && json
->array
.elems
[0]->type
== JSON_STRING
1223 && !strcmp(json
->array
.elems
[0]->string
, "set"))) {
1224 bool is_map
= ovsdb_type_is_map(type
);
1225 const char *class = is_map
? "map" : "set";
1226 const struct json
*inner
;
1230 error
= unwrap_json(json
, class, JSON_ARRAY
, &inner
);
1236 if (n
< type
->n_min
|| n
> type
->n_max
) {
1237 if (type
->n_min
== 1 && type
->n_max
== 1) {
1238 return ovsdb_syntax_error(json
, NULL
, "%s must have exactly "
1239 "one member but %"PRIuSIZE
" "
1240 "are present", class, n
);
1242 return ovsdb_syntax_error(json
, NULL
, "%s must have %u to "
1243 "%u members but %"PRIuSIZE
" are "
1245 class, type
->n_min
, type
->n_max
, n
);
1250 datum
->keys
= xmalloc(n
* sizeof *datum
->keys
);
1251 datum
->values
= is_map
? xmalloc(n
* sizeof *datum
->values
) : NULL
;
1252 for (i
= 0; i
< n
; i
++) {
1253 const struct json
*element
= inner
->array
.elems
[i
];
1254 const struct json
*key
= NULL
;
1255 const struct json
*value
= NULL
;
1260 error
= parse_json_pair(element
, &key
, &value
);
1266 error
= ovsdb_atom_from_json(&datum
->keys
[i
], &type
->key
,
1273 error
= ovsdb_atom_from_json(&datum
->values
[i
],
1274 &type
->value
, value
, symtab
);
1276 ovsdb_atom_destroy(&datum
->keys
[i
], type
->key
.type
);
1286 ovsdb_datum_destroy(datum
, type
);
1290 datum
->keys
= xmalloc(sizeof *datum
->keys
);
1291 datum
->values
= NULL
;
1293 error
= ovsdb_atom_from_json(&datum
->keys
[0], &type
->key
,
1302 /* Parses 'json' as a datum of the type described by 'type'. If successful,
1303 * returns NULL and initializes 'datum' with the parsed datum. On failure,
1304 * returns an error and the contents of 'datum' are indeterminate. The caller
1305 * is responsible for freeing the error or the datum that is returned.
1307 * Violations of constraints expressed by 'type' are treated as errors.
1309 * If 'symtab' is nonnull, then named UUIDs in 'symtab' are accepted. Refer to
1310 * RFC 7047 for information about this, and for the syntax that this function
1312 struct ovsdb_error
* OVS_WARN_UNUSED_RESULT
1313 ovsdb_datum_from_json(struct ovsdb_datum
*datum
,
1314 const struct ovsdb_type
*type
,
1315 const struct json
*json
,
1316 struct ovsdb_symbol_table
*symtab
)
1318 struct ovsdb_error
*error
;
1320 error
= ovsdb_datum_from_json__(datum
, type
, json
, symtab
);
1325 error
= ovsdb_datum_sort(datum
, type
->key
.type
);
1327 ovsdb_datum_destroy(datum
, type
);
1332 /* Parses 'json' as a datum of the type described by 'type' for internal
1333 * use. This function is similar to 'ovsdb_datum_from_json', except the
1334 * member size of set or map is not checked.
1336 * The datum generated should be used then discard. It is not suitable
1337 * for storing into IDL because of the possible member size violation. */
1338 struct ovsdb_error
* OVS_WARN_UNUSED_RESULT
1339 ovsdb_transient_datum_from_json(struct ovsdb_datum
*datum
,
1340 const struct ovsdb_type
*type
,
1341 const struct json
*json
)
1343 struct ovsdb_type relaxed_type
= *type
;
1345 relaxed_type
.n_min
= 0;
1346 relaxed_type
.n_max
= UINT_MAX
;
1348 return ovsdb_datum_from_json(datum
, &relaxed_type
, json
, NULL
);
1351 /* Parses 'json' as a datum of the type described by 'type', but ignoring all
1353 struct ovsdb_error
* OVS_WARN_UNUSED_RESULT
1354 ovsdb_unconstrained_datum_from_json(struct ovsdb_datum
*datum
,
1355 const struct ovsdb_type
*type
,
1356 const struct json
*json
)
1358 struct ovsdb_type relaxed_type
;
1360 ovsdb_base_type_init(&relaxed_type
.key
, type
->key
.type
);
1361 ovsdb_base_type_init(&relaxed_type
.value
, type
->value
.type
);
1362 relaxed_type
.n_min
= 0;
1363 relaxed_type
.n_max
= UINT_MAX
;
1365 return ovsdb_datum_from_json(datum
, &relaxed_type
, json
, NULL
);
1368 static struct json
*
1369 ovsdb_base_to_json(const union ovsdb_atom
*atom
,
1370 const struct ovsdb_base_type
*base
,
1374 || base
->type
!= OVSDB_TYPE_UUID
1375 || !base
->uuid
.refTableName
) {
1376 return ovsdb_atom_to_json(atom
, base
->type
);
1378 return json_array_create_2(
1379 json_string_create("named-uuid"),
1380 json_string_create_nocopy(ovsdb_data_row_name(&atom
->uuid
)));
1384 static struct json
*
1385 ovsdb_datum_to_json__(const struct ovsdb_datum
*datum
,
1386 const struct ovsdb_type
*type
,
1389 if (ovsdb_type_is_map(type
)) {
1390 struct json
**elems
;
1393 elems
= xmalloc(datum
->n
* sizeof *elems
);
1394 for (i
= 0; i
< datum
->n
; i
++) {
1395 elems
[i
] = json_array_create_2(
1396 ovsdb_base_to_json(&datum
->keys
[i
], &type
->key
,
1398 ovsdb_base_to_json(&datum
->values
[i
], &type
->value
,
1402 return wrap_json("map", json_array_create(elems
, datum
->n
));
1403 } else if (datum
->n
== 1) {
1404 return ovsdb_base_to_json(&datum
->keys
[0], &type
->key
, use_row_names
);
1406 struct json
**elems
;
1409 elems
= xmalloc(datum
->n
* sizeof *elems
);
1410 for (i
= 0; i
< datum
->n
; i
++) {
1411 elems
[i
] = ovsdb_base_to_json(&datum
->keys
[i
], &type
->key
,
1415 return wrap_json("set", json_array_create(elems
, datum
->n
));
1419 /* Converts 'datum', of the specified 'type', to JSON format, and returns the
1420 * JSON. The caller is responsible for freeing the returned JSON.
1422 * 'type' constraints on datum->n are ignored.
1424 * Refer to RFC 7047 for the format of the JSON that this function produces. */
1426 ovsdb_datum_to_json(const struct ovsdb_datum
*datum
,
1427 const struct ovsdb_type
*type
)
1429 return ovsdb_datum_to_json__(datum
, type
, false);
1433 ovsdb_datum_to_json_with_row_names(const struct ovsdb_datum
*datum
,
1434 const struct ovsdb_type
*type
)
1436 return ovsdb_datum_to_json__(datum
, type
, true);
1440 skip_spaces(const char *p
)
1442 while (isspace((unsigned char) *p
)) {
1449 parse_atom_token(const char **s
, const struct ovsdb_base_type
*base
,
1450 union ovsdb_atom
*atom
, union ovsdb_atom
**range_end_atom
,
1451 struct ovsdb_symbol_table
*symtab
)
1453 char *token
, *error
;
1455 error
= ovsdb_token_parse(s
, &token
);
1457 error
= ovsdb_atom_from_string(atom
, range_end_atom
,
1458 base
, token
, symtab
);
1465 parse_key_value(const char **s
, const struct ovsdb_type
*type
,
1466 union ovsdb_atom
*key
, union ovsdb_atom
*value
,
1467 struct ovsdb_symbol_table
*symtab
,
1468 union ovsdb_atom
**range_end_key
)
1470 const char *start
= *s
;
1473 error
= parse_atom_token(s
, &type
->key
, key
, range_end_key
, symtab
);
1475 if (!error
&& type
->value
.type
!= OVSDB_TYPE_VOID
) {
1476 *s
= skip_spaces(*s
);
1479 *s
= skip_spaces(*s
);
1480 error
= parse_atom_token(s
, &type
->value
, value
, NULL
, symtab
);
1482 error
= xasprintf("%s: syntax error at \"%c\" expecting \"=\"",
1486 ovsdb_atom_destroy(key
, type
->key
.type
);
1487 if (range_end_key
&& *range_end_key
) {
1488 ovsdb_atom_destroy(*range_end_key
, type
->key
.type
);
1489 free(*range_end_key
);
1490 *range_end_key
= NULL
;
1498 free_key_value_range(const struct ovsdb_type
*type
,
1499 union ovsdb_atom
*key
, union ovsdb_atom
*value
,
1500 union ovsdb_atom
**range_end_atom
)
1502 ovsdb_atom_destroy(key
, type
->key
.type
);
1503 if (type
->value
.type
!= OVSDB_TYPE_VOID
) {
1504 ovsdb_atom_destroy(value
, type
->value
.type
);
1506 if (range_end_atom
&& *range_end_atom
) {
1507 ovsdb_atom_destroy(*range_end_atom
, type
->key
.type
);
1508 free(*range_end_atom
);
1509 *range_end_atom
= NULL
;
1513 /* Initializes 'datum' as a datum of the given 'type', parsing its contents
1514 * from 's'. The format of 's' is a series of space or comma separated atoms
1515 * or, for a map, '='-delimited pairs of atoms. Each atom must in a format
1516 * acceptable to ovsdb_atom_from_string(). Optionally, a set may be enclosed
1517 * in "[]" or a map in "{}"; for an empty set or map these punctuators are
1520 * Optionally, a symbol table may be supplied as 'symtab'. It is passed to
1521 * ovsdb_atom_to_string(). */
1523 ovsdb_datum_from_string(struct ovsdb_datum
*datum
,
1524 const struct ovsdb_type
*type
, const char *s
,
1525 struct ovsdb_symbol_table
*symtab
)
1527 bool is_map
= ovsdb_type_is_map(type
);
1528 struct ovsdb_error
*dberror
;
1533 ovsdb_datum_init_empty(datum
);
1535 /* Swallow a leading delimiter if there is one. */
1537 if (*p
== (is_map
? '{' : '[')) {
1538 end_delim
= is_map
? '}' : ']';
1539 p
= skip_spaces(p
+ 1);
1542 return xstrdup("use \"{}\" to specify the empty map");
1544 return xstrdup("use \"[]\" to specify the empty set");
1550 while (*p
&& *p
!= end_delim
) {
1551 union ovsdb_atom key
, value
;
1552 union ovsdb_atom
*range_end_key
= NULL
;
1554 if (ovsdb_token_is_delim(*p
)) {
1555 char *type_str
= ovsdb_type_to_english(type
);
1556 error
= xasprintf("%s: unexpected \"%c\" parsing %s",
1563 error
= parse_key_value(&p
, type
, &key
, &value
,
1564 symtab
, &range_end_key
);
1568 ovsdb_datum_add_unsafe(datum
, &key
, &value
, type
, range_end_key
);
1569 free_key_value_range(type
, &key
, &value
, &range_end_key
);
1571 /* Skip optional white space and comma. */
1574 p
= skip_spaces(p
+ 1);
1578 if (*p
!= end_delim
) {
1579 error
= xasprintf("%s: missing \"%c\" at end of data", s
, end_delim
);
1583 p
= skip_spaces(p
+ 1);
1585 error
= xasprintf("%s: trailing garbage after \"%c\"",
1591 if (datum
->n
< type
->n_min
) {
1592 error
= xasprintf("%s: %u %s specified but the minimum number is %u",
1593 s
, datum
->n
, is_map
? "pair(s)" : "value(s)",
1596 } else if (datum
->n
> type
->n_max
) {
1597 error
= xasprintf("%s: %u %s specified but the maximum number is %u",
1598 s
, datum
->n
, is_map
? "pair(s)" : "value(s)",
1603 dberror
= ovsdb_datum_sort(datum
, type
->key
.type
);
1605 ovsdb_error_destroy(dberror
);
1606 if (ovsdb_type_is_map(type
)) {
1607 error
= xasprintf("%s: map contains duplicate key", s
);
1609 error
= xasprintf("%s: set contains duplicate value", s
);
1617 ovsdb_datum_destroy(datum
, type
);
1618 ovsdb_datum_init_empty(datum
);
1622 /* Appends to 'out' the 'datum' (with the given 'type') in a format acceptable
1623 * to ovsdb_datum_from_string(). */
1625 ovsdb_datum_to_string(const struct ovsdb_datum
*datum
,
1626 const struct ovsdb_type
*type
, struct ds
*out
)
1628 bool is_map
= ovsdb_type_is_map(type
);
1631 if (type
->n_max
> 1 || !datum
->n
) {
1632 ds_put_char(out
, is_map
? '{' : '[');
1634 for (i
= 0; i
< datum
->n
; i
++) {
1636 ds_put_cstr(out
, ", ");
1639 ovsdb_atom_to_string(&datum
->keys
[i
], type
->key
.type
, out
);
1641 ds_put_char(out
, '=');
1642 ovsdb_atom_to_string(&datum
->values
[i
], type
->value
.type
, out
);
1645 if (type
->n_max
> 1 || !datum
->n
) {
1646 ds_put_char(out
, is_map
? '}' : ']');
1650 /* Appends to 'out' the 'datum' (with the given 'type') in a bare string format
1651 * that cannot be parsed uniformly back into a datum but is easier for shell
1652 * scripts, etc., to deal with. */
1654 ovsdb_datum_to_bare(const struct ovsdb_datum
*datum
,
1655 const struct ovsdb_type
*type
, struct ds
*out
)
1657 bool is_map
= ovsdb_type_is_map(type
);
1660 for (i
= 0; i
< datum
->n
; i
++) {
1662 ds_put_cstr(out
, " ");
1665 ovsdb_atom_to_bare(&datum
->keys
[i
], type
->key
.type
, out
);
1667 ds_put_char(out
, '=');
1668 ovsdb_atom_to_bare(&datum
->values
[i
], type
->value
.type
, out
);
1673 /* Initializes 'datum' as a string-to-string map whose contents are copied from
1674 * 'smap', which is not modified. */
1676 ovsdb_datum_from_smap(struct ovsdb_datum
*datum
, const struct smap
*smap
)
1678 datum
->n
= smap_count(smap
);
1679 datum
->keys
= xmalloc(datum
->n
* sizeof *datum
->keys
);
1680 datum
->values
= xmalloc(datum
->n
* sizeof *datum
->values
);
1682 struct smap_node
*node
;
1684 SMAP_FOR_EACH (node
, smap
) {
1685 datum
->keys
[i
].string
= xstrdup(node
->key
);
1686 datum
->values
[i
].string
= xstrdup(node
->value
);
1689 ovs_assert(i
== datum
->n
);
1691 ovsdb_datum_sort_unique(datum
, OVSDB_TYPE_STRING
, OVSDB_TYPE_STRING
);
1694 struct ovsdb_error
* OVS_WARN_UNUSED_RESULT
1695 ovsdb_datum_convert(struct ovsdb_datum
*dst
,
1696 const struct ovsdb_type
*dst_type
,
1697 const struct ovsdb_datum
*src
,
1698 const struct ovsdb_type
*src_type
)
1700 struct json
*json
= ovsdb_datum_to_json(src
, src_type
);
1701 struct ovsdb_error
*error
= ovsdb_datum_from_json(dst
, dst_type
, json
,
1708 hash_atoms(enum ovsdb_atomic_type type
, const union ovsdb_atom
*atoms
,
1709 unsigned int n
, uint32_t basis
)
1711 if (type
!= OVSDB_TYPE_VOID
) {
1714 for (i
= 0; i
< n
; i
++) {
1715 basis
= ovsdb_atom_hash(&atoms
[i
], type
, basis
);
1722 ovsdb_datum_hash(const struct ovsdb_datum
*datum
,
1723 const struct ovsdb_type
*type
, uint32_t basis
)
1725 basis
= hash_atoms(type
->key
.type
, datum
->keys
, datum
->n
, basis
);
1726 basis
^= (type
->key
.type
<< 24) | (type
->value
.type
<< 16) | datum
->n
;
1727 basis
= hash_atoms(type
->value
.type
, datum
->values
, datum
->n
, basis
);
1732 atom_arrays_compare_3way(const union ovsdb_atom
*a
,
1733 const union ovsdb_atom
*b
,
1734 enum ovsdb_atomic_type type
,
1739 for (i
= 0; i
< n
; i
++) {
1740 int cmp
= ovsdb_atom_compare_3way(&a
[i
], &b
[i
], type
);
1750 ovsdb_datum_equals(const struct ovsdb_datum
*a
,
1751 const struct ovsdb_datum
*b
,
1752 const struct ovsdb_type
*type
)
1754 return !ovsdb_datum_compare_3way(a
, b
, type
);
1758 ovsdb_datum_compare_3way(const struct ovsdb_datum
*a
,
1759 const struct ovsdb_datum
*b
,
1760 const struct ovsdb_type
*type
)
1765 return a
->n
< b
->n
? -1 : 1;
1768 cmp
= atom_arrays_compare_3way(a
->keys
, b
->keys
, type
->key
.type
, a
->n
);
1773 return (type
->value
.type
== OVSDB_TYPE_VOID
? 0
1774 : atom_arrays_compare_3way(a
->values
, b
->values
, type
->value
.type
,
1778 /* If 'key' is one of the keys in 'datum', returns its index within 'datum',
1779 * otherwise UINT_MAX. 'key.type' must be the type of the atoms stored in the
1780 * 'keys' array in 'datum'.
1783 ovsdb_datum_find_key(const struct ovsdb_datum
*datum
,
1784 const union ovsdb_atom
*key
,
1785 enum ovsdb_atomic_type key_type
)
1787 unsigned int low
= 0;
1788 unsigned int high
= datum
->n
;
1789 while (low
< high
) {
1790 unsigned int idx
= (low
+ high
) / 2;
1791 int cmp
= ovsdb_atom_compare_3way(key
, &datum
->keys
[idx
], key_type
);
1794 } else if (cmp
> 0) {
1803 /* If 'key' and 'value' is one of the key-value pairs in 'datum', returns its
1804 * index within 'datum', otherwise UINT_MAX. 'key.type' must be the type of
1805 * the atoms stored in the 'keys' array in 'datum'. 'value_type' may be the
1806 * type of the 'values' atoms or OVSDB_TYPE_VOID to compare only keys.
1809 ovsdb_datum_find_key_value(const struct ovsdb_datum
*datum
,
1810 const union ovsdb_atom
*key
,
1811 enum ovsdb_atomic_type key_type
,
1812 const union ovsdb_atom
*value
,
1813 enum ovsdb_atomic_type value_type
)
1815 unsigned int idx
= ovsdb_datum_find_key(datum
, key
, key_type
);
1817 && value_type
!= OVSDB_TYPE_VOID
1818 && !ovsdb_atom_equals(&datum
->values
[idx
], value
, value_type
)) {
1824 /* If atom 'i' in 'a' is also in 'b', returns its index in 'b', otherwise
1825 * UINT_MAX. 'type' must be the type of 'a' and 'b', except that
1826 * type->value.type may be set to OVSDB_TYPE_VOID to compare keys but not
1829 ovsdb_datum_find(const struct ovsdb_datum
*a
, int i
,
1830 const struct ovsdb_datum
*b
,
1831 const struct ovsdb_type
*type
)
1833 return ovsdb_datum_find_key_value(b
,
1834 &a
->keys
[i
], type
->key
.type
,
1835 a
->values
? &a
->values
[i
] : NULL
,
1839 /* Returns true if every element in 'a' is also in 'b', false otherwise. */
1841 ovsdb_datum_includes_all(const struct ovsdb_datum
*a
,
1842 const struct ovsdb_datum
*b
,
1843 const struct ovsdb_type
*type
)
1850 for (i
= 0; i
< a
->n
; i
++) {
1851 if (ovsdb_datum_find(a
, i
, b
, type
) == UINT_MAX
) {
1858 /* Returns true if no element in 'a' is also in 'b', false otherwise. */
1860 ovsdb_datum_excludes_all(const struct ovsdb_datum
*a
,
1861 const struct ovsdb_datum
*b
,
1862 const struct ovsdb_type
*type
)
1866 for (i
= 0; i
< a
->n
; i
++) {
1867 if (ovsdb_datum_find(a
, i
, b
, type
) != UINT_MAX
) {
1875 ovsdb_datum_reallocate(struct ovsdb_datum
*a
, const struct ovsdb_type
*type
,
1876 unsigned int capacity
)
1878 a
->keys
= xrealloc(a
->keys
, capacity
* sizeof *a
->keys
);
1879 if (type
->value
.type
!= OVSDB_TYPE_VOID
) {
1880 a
->values
= xrealloc(a
->values
, capacity
* sizeof *a
->values
);
1884 /* Removes the element with index 'idx' from 'datum', which has type 'type'.
1885 * If 'idx' is not the last element in 'datum', then the removed element is
1886 * replaced by the (former) last element.
1888 * This function does not maintain ovsdb_datum invariants. Use
1889 * ovsdb_datum_sort() to check and restore these invariants. */
1891 ovsdb_datum_remove_unsafe(struct ovsdb_datum
*datum
, size_t idx
,
1892 const struct ovsdb_type
*type
)
1894 ovsdb_atom_destroy(&datum
->keys
[idx
], type
->key
.type
);
1895 datum
->keys
[idx
] = datum
->keys
[datum
->n
- 1];
1896 if (type
->value
.type
!= OVSDB_TYPE_VOID
) {
1897 ovsdb_atom_destroy(&datum
->values
[idx
], type
->value
.type
);
1898 datum
->values
[idx
] = datum
->values
[datum
->n
- 1];
1903 /* Adds the element with the given 'key' and 'value' to 'datum', which must
1904 * have the specified 'type'. Optionally if 'range_end_atom' is not
1905 * a null pointer, adds a set of integers to 'datum' from inclusive
1906 * range ['key', 'range_end_atom'].
1908 * This function always allocates memory, so it is not an efficient way to add
1909 * a number of elements to a datum.
1911 * When adding a range of integers, this function allocates the memory once
1912 * for the whole range.
1914 * This function does not maintain ovsdb_datum invariants. Use
1915 * ovsdb_datum_sort() to check and restore these invariants. (But a datum with
1916 * 0 or 1 elements cannot violate the invariants anyhow.) */
1918 ovsdb_datum_add_unsafe(struct ovsdb_datum
*datum
,
1919 const union ovsdb_atom
*key
,
1920 const union ovsdb_atom
*value
,
1921 const struct ovsdb_type
*type
,
1922 const union ovsdb_atom
*range_end_atom
)
1924 size_t idx
= datum
->n
;
1925 datum
->n
+= range_end_atom
?
1926 (range_end_atom
->integer
- key
->integer
+ 1) : 1;
1927 datum
->keys
= xrealloc(datum
->keys
, datum
->n
* sizeof *datum
->keys
);
1928 if (range_end_atom
&& key
->integer
<= range_end_atom
->integer
) {
1929 for (int64_t i
= key
->integer
; i
<= range_end_atom
->integer
; i
++) {
1930 datum
->keys
[idx
++].integer
= i
;
1933 ovsdb_atom_clone(&datum
->keys
[idx
], key
, type
->key
.type
);
1934 if (type
->value
.type
!= OVSDB_TYPE_VOID
) {
1935 datum
->values
= xrealloc(datum
->values
,
1936 datum
->n
* sizeof *datum
->values
);
1937 ovsdb_atom_clone(&datum
->values
[idx
], value
, type
->value
.type
);
1943 ovsdb_datum_union(struct ovsdb_datum
*a
, const struct ovsdb_datum
*b
,
1944 const struct ovsdb_type
*type
, bool replace
)
1950 for (bi
= 0; bi
< b
->n
; bi
++) {
1953 ai
= ovsdb_datum_find_key(a
, &b
->keys
[bi
], type
->key
.type
);
1954 if (ai
== UINT_MAX
) {
1956 ovsdb_datum_reallocate(a
, type
, a
->n
+ (b
->n
- bi
));
1958 ovsdb_atom_clone(&a
->keys
[n
], &b
->keys
[bi
], type
->key
.type
);
1959 if (type
->value
.type
!= OVSDB_TYPE_VOID
) {
1960 ovsdb_atom_clone(&a
->values
[n
], &b
->values
[bi
],
1964 } else if (replace
&& type
->value
.type
!= OVSDB_TYPE_VOID
) {
1965 ovsdb_atom_destroy(&a
->values
[ai
], type
->value
.type
);
1966 ovsdb_atom_clone(&a
->values
[ai
], &b
->values
[bi
],
1972 ovs_assert(!ovsdb_datum_sort(a
, type
->key
.type
));
1977 ovsdb_datum_subtract(struct ovsdb_datum
*a
, const struct ovsdb_type
*a_type
,
1978 const struct ovsdb_datum
*b
,
1979 const struct ovsdb_type
*b_type
)
1981 bool changed
= false;
1984 ovs_assert(a_type
->key
.type
== b_type
->key
.type
);
1985 ovs_assert(a_type
->value
.type
== b_type
->value
.type
1986 || b_type
->value
.type
== OVSDB_TYPE_VOID
);
1988 /* XXX The big-O of this could easily be improved. */
1989 for (i
= 0; i
< a
->n
; ) {
1990 unsigned int idx
= ovsdb_datum_find(a
, i
, b
, b_type
);
1991 if (idx
!= UINT_MAX
) {
1993 ovsdb_datum_remove_unsafe(a
, i
, a_type
);
1999 ovsdb_datum_sort_assert(a
, a_type
->key
.type
);
2003 struct ovsdb_symbol_table
*
2004 ovsdb_symbol_table_create(void)
2006 struct ovsdb_symbol_table
*symtab
= xmalloc(sizeof *symtab
);
2007 shash_init(&symtab
->sh
);
2012 ovsdb_symbol_table_destroy(struct ovsdb_symbol_table
*symtab
)
2015 shash_destroy_free_data(&symtab
->sh
);
2020 struct ovsdb_symbol
*
2021 ovsdb_symbol_table_get(const struct ovsdb_symbol_table
*symtab
,
2024 return shash_find_data(&symtab
->sh
, name
);
2027 struct ovsdb_symbol
*
2028 ovsdb_symbol_table_put(struct ovsdb_symbol_table
*symtab
, const char *name
,
2029 const struct uuid
*uuid
, bool created
)
2031 struct ovsdb_symbol
*symbol
;
2033 ovs_assert(!ovsdb_symbol_table_get(symtab
, name
));
2034 symbol
= xmalloc(sizeof *symbol
);
2035 symbol
->uuid
= *uuid
;
2036 symbol
->created
= created
;
2037 symbol
->strong_ref
= false;
2038 symbol
->weak_ref
= false;
2039 shash_add(&symtab
->sh
, name
, symbol
);
2043 struct ovsdb_symbol
*
2044 ovsdb_symbol_table_insert(struct ovsdb_symbol_table
*symtab
,
2047 struct ovsdb_symbol
*symbol
;
2049 symbol
= ovsdb_symbol_table_get(symtab
, name
);
2053 uuid_generate(&uuid
);
2054 symbol
= ovsdb_symbol_table_put(symtab
, name
, &uuid
, false);
2059 /* APIs for Generating and apply diffs. */
2061 /* Generate a difference ovsdb_dataum between 'old' and 'new'.
2062 * 'new' can be regenerated by applying the difference to the 'old'.
2064 * The diff operation is reversible. Given 'old',
2065 * 'new' can be recreated by applying diff to 'old'.
2068 * Let d = 'old' diff 'new'
2069 * then 'new' = 'old' diff d
2071 * The 'diff' datum is always safe; the orders of keys are maintained
2072 * since they are added in order. */
2074 ovsdb_datum_diff(struct ovsdb_datum
*diff
,
2075 const struct ovsdb_datum
*old
,
2076 const struct ovsdb_datum
*new,
2077 const struct ovsdb_type
*type
)
2081 ovsdb_datum_init_empty(diff
);
2082 if (!ovsdb_type_is_composite(type
)) {
2083 ovsdb_datum_clone(diff
, new, type
);
2087 /* Generate the diff in O(n) time. */
2088 for (oi
= ni
= 0; oi
< old
->n
&& ni
< new->n
; ) {
2089 int c
= ovsdb_atom_compare_3way(&old
->keys
[oi
], &new->keys
[ni
],
2092 ovsdb_datum_add_unsafe(diff
, &old
->keys
[oi
], &old
->values
[oi
],
2096 ovsdb_datum_add_unsafe(diff
, &new->keys
[ni
], &new->values
[ni
],
2100 if (type
->value
.type
!= OVSDB_TYPE_VOID
&&
2101 ovsdb_atom_compare_3way(&old
->values
[oi
], &new->values
[ni
],
2102 type
->value
.type
)) {
2103 ovsdb_datum_add_unsafe(diff
, &new->keys
[ni
], &new->values
[ni
],
2110 for (; oi
< old
->n
; oi
++) {
2111 ovsdb_datum_add_unsafe(diff
, &old
->keys
[oi
], &old
->values
[oi
],
2115 for (; ni
< new->n
; ni
++) {
2116 ovsdb_datum_add_unsafe(diff
, &new->keys
[ni
], &new->values
[ni
],
2121 /* Apply 'diff' to 'old' to regenerate 'new'.
2123 * Return NULL if the 'new' is successfully generated, otherwise, return
2124 * ovsdb_error and the stat of 'new' is indeterministic. */
2125 struct ovsdb_error
*
2126 ovsdb_datum_apply_diff(struct ovsdb_datum
*new,
2127 const struct ovsdb_datum
*old
,
2128 const struct ovsdb_datum
*diff
,
2129 const struct ovsdb_type
*type
)
2131 ovsdb_datum_diff(new, old
, diff
, type
);
2133 /* Make sure member size of 'new' conforms to type. */
2134 if (new->n
< type
->n_min
|| new->n
> type
->n_max
) {
2135 ovsdb_datum_destroy(new, type
);
2136 return ovsdb_error(NULL
, "Datum crated by diff has size error");
2143 /* Extracts a token from the beginning of 's' and returns a pointer just after
2144 * the token. Stores the token itself into '*outp', which the caller is
2145 * responsible for freeing (with free()).
2147 * If 's[0]' is a delimiter, the returned token is the empty string.
2149 * A token extends from 's' to the first delimiter, as defined by
2150 * ovsdb_token_is_delim(), or until the end of the string. A delimiter can be
2151 * escaped with a backslash, in which case the backslash does not appear in the
2152 * output. Double quotes also cause delimiters to be ignored, but the double
2153 * quotes are retained in the output. (Backslashes inside double quotes are
2154 * not removed, either.)
2157 ovsdb_token_parse(const char **s
, char **outp
)
2166 for (p
= *s
; *p
!= '\0'; ) {
2170 ds_put_char(&out
, '\\');
2173 error
= xasprintf("%s: backslash at end of argument", *s
);
2176 ds_put_char(&out
, *p
++);
2177 } else if (!in_quotes
&& ovsdb_token_is_delim(c
)) {
2181 ds_put_char(&out
, c
);
2183 in_quotes
= !in_quotes
;
2188 error
= xasprintf("%s: quoted string extends past end of argument",
2192 *outp
= ds_cstr(&out
);
2202 /* Returns true if 'c' delimits tokens, or if 'c' is 0, and false otherwise. */
2204 ovsdb_token_is_delim(unsigned char c
)
2206 return strchr(":=, []{}!<>", c
) != NULL
;
2209 struct ovsdb_error
*
2210 ovsdb_atom_range_check_size(int64_t range_start
, int64_t range_end
)
2212 if ((uint64_t) range_end
- (uint64_t) range_start
2213 >= MAX_OVSDB_ATOM_RANGE_SIZE
) {
2214 return ovsdb_error("constraint violation",
2215 "Range \"%"PRId64
"-%"PRId64
"\" is too big. "
2216 "Maximum allowed size is %d.",
2217 range_start
, range_end
, MAX_OVSDB_ATOM_RANGE_SIZE
);
2223 ovsdb_data_row_name(const struct uuid
*uuid
)
2228 name
= xasprintf("row"UUID_FMT
, UUID_ARGS(uuid
));
2229 for (p
= name
; *p
!= '\0'; p
++) {