]> git.proxmox.com Git - mirror_ovs.git/blame - ovsdb/ovsdb-util.c
ovn-nbctl: Fix the ovn-nbctl test "LBs - daemon" which fails during rpm build
[mirror_ovs.git] / ovsdb / ovsdb-util.c
CommitLineData
40e66ba7
LR
1/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2016 Nicira, Inc.
2 *
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:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
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.
14 */
15
16#include <config.h>
17#include "row.h"
18#include "sset.h"
19#include "table.h"
20#include "ovsdb-util.h"
21#include "openvswitch/vlog.h"
22
23VLOG_DEFINE_THIS_MODULE(ovsdb_util);
24
1b1d2e6d 25void
6bb9b060
BP
26ovsdb_util_clear_column(struct ovsdb_row *row, const char *column_name)
27{
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;
31
32 column = ovsdb_table_schema_get_column(schema, column_name);
33 if (!column) {
34 VLOG_DBG_RL(&rl, "Table `%s' has no `%s' column",
35 schema->name, column_name);
36 return;
37 }
38
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);
45 free(type_name);
46 }
47 return;
48 }
49
50 struct ovsdb_datum *datum = &row->fields[column->index];
51 if (datum->n) {
52 ovsdb_datum_destroy(datum, &column->type);
53 ovsdb_datum_init_empty(datum);
54 }
55}
56
40e66ba7
LR
57struct ovsdb_datum *
58ovsdb_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,
61 const size_t n_max)
62{
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;
66
67 column = ovsdb_table_schema_get_column(schema, column_name);
68 if (!column) {
69 VLOG_DBG_RL(&rl, "Table `%s' has no `%s' column",
70 schema->name, column_name);
71 return NULL;
72 }
73
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),
84 n_max);
85 free(type_name);
86 }
87 return NULL;
88 }
89
90 return &row->fields[column->index];
91}
92
93/* Read string-string key-values from a map. Returns the value associated with
94 * 'key', if found, or NULL */
95const char *
96ovsdb_util_read_map_string_column(const struct ovsdb_row *row,
97 const char *column_name,
98 const char *key)
99{
100 const struct ovsdb_datum *datum;
101 union ovsdb_atom *atom_key = NULL, *atom_value = NULL;
102 size_t i;
103
104 datum = ovsdb_util_get_datum(CONST_CAST(struct ovsdb_row *, row),
105 column_name, OVSDB_TYPE_STRING,
106 OVSDB_TYPE_STRING, UINT_MAX);
107
108 if (!datum) {
109 return NULL;
110 }
111
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];
116 break;
117 }
118 }
119
120 return atom_value ? atom_value->string : NULL;
121}
122
d6db7b3c
LR
123/* Read string-uuid key-values from a map. Returns the row associated with
124 * 'key', if found, or NULL */
125const struct ovsdb_row *
126ovsdb_util_read_map_string_uuid_column(const struct ovsdb_row *row,
127 const char *column_name,
128 const char *key)
129{
130 const struct ovsdb_column *column
131 = ovsdb_table_schema_get_column(row->table->schema, column_name);
132 if (!column ||
133 column->type.key.type != OVSDB_TYPE_STRING ||
134 column->type.value.type != OVSDB_TYPE_UUID) {
135 return NULL;
136 }
137
fa37affa 138 const struct ovsdb_table *ref_table = column->type.value.uuid.refTable;
d6db7b3c
LR
139 if (!ref_table) {
140 return NULL;
141 }
142
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);
149 }
150 }
151 return NULL;
152}
153
40e66ba7
LR
154const union ovsdb_atom *
155ovsdb_util_read_column(const struct ovsdb_row *row, const char *column_name,
156 enum ovsdb_atomic_type type)
157{
158 const struct ovsdb_datum *datum;
159
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;
163}
164
165bool
166ovsdb_util_read_integer_column(const struct ovsdb_row *row,
167 const char *column_name,
168 long long int *integerp)
169{
170 const union ovsdb_atom *atom;
171
172 atom = ovsdb_util_read_column(row, column_name, OVSDB_TYPE_INTEGER);
173 *integerp = atom ? atom->integer : 0;
174 return atom != NULL;
175}
176
177bool
178ovsdb_util_read_string_column(const struct ovsdb_row *row,
179 const char *column_name, const char **stringp)
180{
181 const union ovsdb_atom *atom;
182
183 atom = ovsdb_util_read_column(row, column_name, OVSDB_TYPE_STRING);
184 *stringp = atom ? atom->string : NULL;
185 return atom != NULL;
186}
187
188bool
189ovsdb_util_read_bool_column(const struct ovsdb_row *row,
190 const char *column_name, bool *boolp)
191{
192 const union ovsdb_atom *atom;
193
194 atom = ovsdb_util_read_column(row, column_name, OVSDB_TYPE_BOOLEAN);
195 *boolp = atom ? atom->boolean : false;
196 return atom != NULL;
197}
198
6bb9b060
BP
199bool
200ovsdb_util_read_uuid_column(const struct ovsdb_row *row,
201 const char *column_name, struct uuid *uuid)
202{
203 const union ovsdb_atom *atom;
204
205 atom = ovsdb_util_read_column(row, column_name, OVSDB_TYPE_UUID);
206 *uuid = atom ? atom->uuid : UUID_ZERO;
207 return atom != NULL;
208}
209
210static void
211ovsdb_util_write_singleton(struct ovsdb_row *row, const char *column_name,
212 const union ovsdb_atom *atom,
213 enum ovsdb_atomic_type type)
40e66ba7
LR
214{
215 const struct ovsdb_column *column;
216 struct ovsdb_datum *datum;
217
218 column = ovsdb_table_schema_get_column(row->table->schema, column_name);
6bb9b060 219 datum = ovsdb_util_get_datum(row, column_name, type, OVSDB_TYPE_VOID, 1);
40e66ba7
LR
220 if (!datum) {
221 return;
222 }
223
6bb9b060
BP
224 if (datum->n == 1) {
225 if (ovsdb_atom_equals(&datum->keys[0], atom, type)) {
226 return;
227 }
228 ovsdb_atom_destroy(&datum->keys[0], type);
229 } else {
40e66ba7 230 ovsdb_datum_destroy(datum, &column->type);
40e66ba7
LR
231 datum->n = 1;
232 datum->keys = xmalloc(sizeof *datum->keys);
233 datum->values = NULL;
234 }
6bb9b060
BP
235 ovsdb_atom_clone(&datum->keys[0], atom, type);
236}
40e66ba7 237
1b1d2e6d
BP
238void
239ovsdb_util_write_integer_column(struct ovsdb_row *row,
240 const char *column_name,
241 long long int integer)
242{
243 const union ovsdb_atom atom = { .integer = integer };
244 ovsdb_util_write_singleton(row, column_name, &atom, OVSDB_TYPE_INTEGER);
245}
246
6bb9b060
BP
247void
248ovsdb_util_write_bool_column(struct ovsdb_row *row, const char *column_name,
249 bool value)
250{
251 const union ovsdb_atom atom = { .boolean = value };
252 ovsdb_util_write_singleton(row, column_name, &atom, OVSDB_TYPE_BOOLEAN);
253}
254
255void
256ovsdb_util_write_uuid_column(struct ovsdb_row *row, const char *column_name,
257 const struct uuid *uuid)
258{
259 if (uuid) {
260 const union ovsdb_atom atom = { .uuid = *uuid };
261 ovsdb_util_write_singleton(row, column_name, &atom, OVSDB_TYPE_UUID);
262 } else {
263 ovsdb_util_clear_column(row, column_name);
264 }
265}
266
267void
268ovsdb_util_write_string_column(struct ovsdb_row *row, const char *column_name,
269 const char *string)
270{
271 if (string) {
272 const union ovsdb_atom atom = { .string = CONST_CAST(char *, string) };
273 ovsdb_util_write_singleton(row, column_name, &atom, OVSDB_TYPE_STRING);
274 } else {
275 ovsdb_util_clear_column(row, column_name);
276 }
40e66ba7
LR
277}
278
279void
280ovsdb_util_write_string_string_column(struct ovsdb_row *row,
281 const char *column_name,
282 char **keys, char **values, size_t n)
283{
284 const struct ovsdb_column *column;
285 struct ovsdb_datum *datum;
286 size_t i;
287
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);
291 if (!datum) {
292 for (i = 0; i < n; i++) {
293 free(keys[i]);
294 free(values[i]);
295 }
296 return;
297 }
298
299 /* Free existing data. */
300 ovsdb_datum_destroy(datum, &column->type);
301
302 /* Allocate space for new values. */
303 datum->n = n;
304 datum->keys = xmalloc(n * sizeof *datum->keys);
305 datum->values = xmalloc(n * sizeof *datum->values);
306
307 for (i = 0; i < n; ++i) {
308 datum->keys[i].string = keys[i];
309 datum->values[i].string = values[i];
310 }
311
312 /* Sort and check constraints. */
313 ovsdb_datum_sort_assert(datum, column->type.key.type);
314}