1 /* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2016 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.
20 #include "ovsdb-util.h"
21 #include "openvswitch/vlog.h"
23 VLOG_DEFINE_THIS_MODULE(ovsdb_util
);
26 ovsdb_util_clear_column(struct ovsdb_row
*row
, const char *column_name
)
28 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
29 const struct ovsdb_table_schema
*schema
= row
->table
->schema
;
30 const struct ovsdb_column
*column
;
32 column
= ovsdb_table_schema_get_column(schema
, column_name
);
34 VLOG_DBG_RL(&rl
, "Table `%s' has no `%s' column",
35 schema
->name
, column_name
);
39 if (column
->type
.n_min
) {
40 if (!VLOG_DROP_DBG(&rl
)) {
41 char *type_name
= ovsdb_type_to_english(&column
->type
);
42 VLOG_DBG("Table `%s' column `%s' has type %s, which requires "
43 "a value, but an attempt was made to clear it",
44 schema
->name
, column_name
, type_name
);
50 struct ovsdb_datum
*datum
= &row
->fields
[column
->index
];
52 ovsdb_datum_destroy(datum
, &column
->type
);
53 ovsdb_datum_init_empty(datum
);
58 ovsdb_util_get_datum(struct ovsdb_row
*row
, const char *column_name
,
59 const enum ovsdb_atomic_type key_type
,
60 const enum ovsdb_atomic_type value_type
,
63 static struct vlog_rate_limit rl
= VLOG_RATE_LIMIT_INIT(1, 1);
64 const struct ovsdb_table_schema
*schema
= row
->table
->schema
;
65 const struct ovsdb_column
*column
;
67 column
= ovsdb_table_schema_get_column(schema
, column_name
);
69 VLOG_DBG_RL(&rl
, "Table `%s' has no `%s' column",
70 schema
->name
, column_name
);
74 if (column
->type
.key
.type
!= key_type
75 || column
->type
.value
.type
!= value_type
76 || column
->type
.n_max
!= n_max
) {
77 if (!VLOG_DROP_DBG(&rl
)) {
78 char *type_name
= ovsdb_type_to_english(&column
->type
);
79 VLOG_DBG("Table `%s' column `%s' has type %s, not expected "
80 "key type %s, value type %s, max elements %"PRIuSIZE
".",
81 schema
->name
, column_name
, type_name
,
82 ovsdb_atomic_type_to_string(key_type
),
83 ovsdb_atomic_type_to_string(value_type
),
90 return &row
->fields
[column
->index
];
93 /* Read string-string key-values from a map. Returns the value associated with
94 * 'key', if found, or NULL */
96 ovsdb_util_read_map_string_column(const struct ovsdb_row
*row
,
97 const char *column_name
,
100 const struct ovsdb_datum
*datum
;
101 union ovsdb_atom
*atom_key
= NULL
, *atom_value
= NULL
;
104 datum
= ovsdb_util_get_datum(CONST_CAST(struct ovsdb_row
*, row
),
105 column_name
, OVSDB_TYPE_STRING
,
106 OVSDB_TYPE_STRING
, UINT_MAX
);
112 for (i
= 0; i
< datum
->n
; i
++) {
113 atom_key
= &datum
->keys
[i
];
114 if (!strcmp(atom_key
->string
, key
)) {
115 atom_value
= &datum
->values
[i
];
120 return atom_value
? atom_value
->string
: NULL
;
123 /* Read string-uuid key-values from a map. Returns the row associated with
124 * 'key', if found, or NULL */
125 const struct ovsdb_row
*
126 ovsdb_util_read_map_string_uuid_column(const struct ovsdb_row
*row
,
127 const char *column_name
,
130 const struct ovsdb_column
*column
131 = ovsdb_table_schema_get_column(row
->table
->schema
, column_name
);
133 column
->type
.key
.type
!= OVSDB_TYPE_STRING
||
134 column
->type
.value
.type
!= OVSDB_TYPE_UUID
) {
138 const struct ovsdb_table
*ref_table
= column
->type
.value
.uuid
.refTable
;
143 const struct ovsdb_datum
*datum
= &row
->fields
[column
->index
];
144 for (size_t i
= 0; i
< datum
->n
; i
++) {
145 union ovsdb_atom
*atom_key
= &datum
->keys
[i
];
146 if (!strcmp(atom_key
->string
, key
)) {
147 const union ovsdb_atom
*atom_value
= &datum
->values
[i
];
148 return ovsdb_table_get_row(ref_table
, &atom_value
->uuid
);
154 const union ovsdb_atom
*
155 ovsdb_util_read_column(const struct ovsdb_row
*row
, const char *column_name
,
156 enum ovsdb_atomic_type type
)
158 const struct ovsdb_datum
*datum
;
160 datum
= ovsdb_util_get_datum(CONST_CAST(struct ovsdb_row
*, row
),
161 column_name
, type
, OVSDB_TYPE_VOID
, 1);
162 return datum
&& datum
->n
? datum
->keys
: NULL
;
166 ovsdb_util_read_integer_column(const struct ovsdb_row
*row
,
167 const char *column_name
,
168 long long int *integerp
)
170 const union ovsdb_atom
*atom
;
172 atom
= ovsdb_util_read_column(row
, column_name
, OVSDB_TYPE_INTEGER
);
173 *integerp
= atom
? atom
->integer
: 0;
178 ovsdb_util_read_string_column(const struct ovsdb_row
*row
,
179 const char *column_name
, const char **stringp
)
181 const union ovsdb_atom
*atom
;
183 atom
= ovsdb_util_read_column(row
, column_name
, OVSDB_TYPE_STRING
);
184 *stringp
= atom
? atom
->string
: NULL
;
189 ovsdb_util_read_bool_column(const struct ovsdb_row
*row
,
190 const char *column_name
, bool *boolp
)
192 const union ovsdb_atom
*atom
;
194 atom
= ovsdb_util_read_column(row
, column_name
, OVSDB_TYPE_BOOLEAN
);
195 *boolp
= atom
? atom
->boolean
: false;
200 ovsdb_util_read_uuid_column(const struct ovsdb_row
*row
,
201 const char *column_name
, struct uuid
*uuid
)
203 const union ovsdb_atom
*atom
;
205 atom
= ovsdb_util_read_column(row
, column_name
, OVSDB_TYPE_UUID
);
206 *uuid
= atom
? atom
->uuid
: UUID_ZERO
;
211 ovsdb_util_write_singleton(struct ovsdb_row
*row
, const char *column_name
,
212 const union ovsdb_atom
*atom
,
213 enum ovsdb_atomic_type type
)
215 const struct ovsdb_column
*column
;
216 struct ovsdb_datum
*datum
;
218 column
= ovsdb_table_schema_get_column(row
->table
->schema
, column_name
);
219 datum
= ovsdb_util_get_datum(row
, column_name
, type
, OVSDB_TYPE_VOID
, 1);
225 if (ovsdb_atom_equals(&datum
->keys
[0], atom
, type
)) {
228 ovsdb_atom_destroy(&datum
->keys
[0], type
);
230 ovsdb_datum_destroy(datum
, &column
->type
);
232 datum
->keys
= xmalloc(sizeof *datum
->keys
);
233 datum
->values
= NULL
;
235 ovsdb_atom_clone(&datum
->keys
[0], atom
, type
);
239 ovsdb_util_write_integer_column(struct ovsdb_row
*row
,
240 const char *column_name
,
241 long long int integer
)
243 const union ovsdb_atom atom
= { .integer
= integer
};
244 ovsdb_util_write_singleton(row
, column_name
, &atom
, OVSDB_TYPE_INTEGER
);
248 ovsdb_util_write_bool_column(struct ovsdb_row
*row
, const char *column_name
,
251 const union ovsdb_atom atom
= { .boolean
= value
};
252 ovsdb_util_write_singleton(row
, column_name
, &atom
, OVSDB_TYPE_BOOLEAN
);
256 ovsdb_util_write_uuid_column(struct ovsdb_row
*row
, const char *column_name
,
257 const struct uuid
*uuid
)
260 const union ovsdb_atom atom
= { .uuid
= *uuid
};
261 ovsdb_util_write_singleton(row
, column_name
, &atom
, OVSDB_TYPE_UUID
);
263 ovsdb_util_clear_column(row
, column_name
);
268 ovsdb_util_write_string_column(struct ovsdb_row
*row
, const char *column_name
,
272 const union ovsdb_atom atom
= { .string
= CONST_CAST(char *, string
) };
273 ovsdb_util_write_singleton(row
, column_name
, &atom
, OVSDB_TYPE_STRING
);
275 ovsdb_util_clear_column(row
, column_name
);
280 ovsdb_util_write_string_string_column(struct ovsdb_row
*row
,
281 const char *column_name
,
282 char **keys
, char **values
, size_t n
)
284 const struct ovsdb_column
*column
;
285 struct ovsdb_datum
*datum
;
288 column
= ovsdb_table_schema_get_column(row
->table
->schema
, column_name
);
289 datum
= ovsdb_util_get_datum(row
, column_name
, OVSDB_TYPE_STRING
,
290 OVSDB_TYPE_STRING
, UINT_MAX
);
292 for (i
= 0; i
< n
; i
++) {
299 /* Free existing data. */
300 ovsdb_datum_destroy(datum
, &column
->type
);
302 /* Allocate space for new values. */
304 datum
->keys
= xmalloc(n
* sizeof *datum
->keys
);
305 datum
->values
= xmalloc(n
* sizeof *datum
->values
);
307 for (i
= 0; i
< n
; ++i
) {
308 datum
->keys
[i
].string
= keys
[i
];
309 datum
->values
[i
].string
= values
[i
];
312 /* Sort and check constraints. */
313 ovsdb_datum_sort_assert(datum
, column
->type
.key
.type
);