]>
Commit | Line | Data |
---|---|---|
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 | ||
23 | VLOG_DEFINE_THIS_MODULE(ovsdb_util); | |
24 | ||
1b1d2e6d | 25 | void |
6bb9b060 BP |
26 | ovsdb_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 |
57 | struct ovsdb_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, | |
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 */ | |
95 | const char * | |
96 | ovsdb_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 */ | |
125 | const struct ovsdb_row * | |
126 | ovsdb_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 |
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) | |
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 | ||
165 | bool | |
166 | ovsdb_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 | ||
177 | bool | |
178 | ovsdb_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 | ||
188 | bool | |
189 | ovsdb_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 |
199 | bool |
200 | ovsdb_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 | ||
210 | static void | |
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) | |
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 |
238 | void |
239 | ovsdb_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 |
247 | void |
248 | ovsdb_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 | ||
255 | void | |
256 | ovsdb_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 | ||
267 | void | |
268 | ovsdb_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 | ||
279 | void | |
280 | ovsdb_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 | } |