1 /* Copyright (c) 2009 Nicira Networks
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.
24 #include "ovsdb-error.h"
38 ovsdb_mutator_from_string(const char *name, enum ovsdb_mutator *mutator)
40 #define OVSDB_MUTATOR(ENUM, NAME) \
41 if (!strcmp(name, NAME)) { \
48 return ovsdb_syntax_error(NULL, "unknown mutator",
49 "No mutator named %s.", name);
53 ovsdb_mutator_to_string(enum ovsdb_mutator mutator)
56 #define OVSDB_MUTATOR(ENUM, NAME) case ENUM: return NAME;
64 static WARN_UNUSED_RESULT struct ovsdb_error *
65 type_mismatch(const struct ovsdb_mutation *m, const struct json *json)
67 struct ovsdb_error *error;
70 s = ovsdb_type_to_english(&m->column->type);
71 error = ovsdb_syntax_error(
72 json, NULL, "Type mismatch: \"%s\" operator may not be "
73 "applied to column %s of type %s.",
74 ovsdb_mutator_to_string(m->mutator), m->column->name, s);
80 static WARN_UNUSED_RESULT struct ovsdb_error *
81 ovsdb_mutation_from_json(const struct ovsdb_table_schema *ts,
82 const struct json *json,
83 const struct ovsdb_symbol_table *symtab,
84 struct ovsdb_mutation *m)
86 const struct json_array *array;
87 struct ovsdb_error *error;
88 const char *mutator_name;
89 const char *column_name;
91 if (json->type != JSON_ARRAY
92 || json->u.array.n != 3
93 || json->u.array.elems[0]->type != JSON_STRING
94 || json->u.array.elems[1]->type != JSON_STRING) {
95 return ovsdb_syntax_error(json, NULL, "Parse error in mutation.");
97 array = json_array(json);
99 column_name = json_string(array->elems[0]);
100 m->column = ovsdb_table_schema_get_column(ts, column_name);
102 return ovsdb_syntax_error(json, "unknown column",
103 "No column %s in table %s.",
104 column_name, ts->name);
106 m->type = m->column->type;
108 mutator_name = json_string(array->elems[1]);
109 error = ovsdb_mutator_from_string(mutator_name, &m->mutator);
114 /* Type-check and relax restrictions on 'type' if appropriate. */
115 switch (m->mutator) {
121 if ((!ovsdb_type_is_scalar(&m->type) && !ovsdb_type_is_set(&m->type))
122 || (m->type.key_type != OVSDB_TYPE_INTEGER
123 && m->type.key_type != OVSDB_TYPE_REAL)
124 || (m->mutator == OVSDB_M_MOD
125 && m->type.key_type == OVSDB_TYPE_REAL)) {
126 return type_mismatch(m, json);
128 m->type.n_min = m->type.n_max = 1;
129 return ovsdb_datum_from_json(&m->arg, &m->type, array->elems[2],
134 if (!ovsdb_type_is_set(&m->type) && !ovsdb_type_is_map(&m->type)) {
135 return type_mismatch(m, json);
138 if (m->mutator == OVSDB_M_DELETE) {
139 m->type.n_max = UINT_MAX;
141 error = ovsdb_datum_from_json(&m->arg, &m->type, array->elems[2],
143 if (error && ovsdb_type_is_map(&m->type)
144 && m->mutator == OVSDB_M_DELETE) {
145 ovsdb_error_destroy(error);
146 m->type.value_type = OVSDB_TYPE_VOID;
147 error = ovsdb_datum_from_json(&m->arg, &m->type, array->elems[2],
157 ovsdb_mutation_free(struct ovsdb_mutation *m)
159 ovsdb_datum_destroy(&m->arg, &m->type);
163 ovsdb_mutation_set_from_json(const struct ovsdb_table_schema *ts,
164 const struct json *json,
165 const struct ovsdb_symbol_table *symtab,
166 struct ovsdb_mutation_set *set)
168 const struct json_array *array = json_array(json);
171 set->mutations = xmalloc(array->n * sizeof *set->mutations);
172 set->n_mutations = 0;
173 for (i = 0; i < array->n; i++) {
174 struct ovsdb_error *error;
175 error = ovsdb_mutation_from_json(ts, array->elems[i], symtab,
178 ovsdb_mutation_set_destroy(set);
179 set->mutations = NULL;
180 set->n_mutations = 0;
190 ovsdb_mutation_to_json(const struct ovsdb_mutation *m)
192 return json_array_create_3(
193 json_string_create(m->column->name),
194 json_string_create(ovsdb_mutator_to_string(m->mutator)),
195 ovsdb_datum_to_json(&m->arg, &m->type));
199 ovsdb_mutation_set_to_json(const struct ovsdb_mutation_set *set)
201 struct json **mutations;
204 mutations = xmalloc(set->n_mutations * sizeof *mutations);
205 for (i = 0; i < set->n_mutations; i++) {
206 mutations[i] = ovsdb_mutation_to_json(&set->mutations[i]);
208 return json_array_create(mutations, set->n_mutations);
212 ovsdb_mutation_set_destroy(struct ovsdb_mutation_set *set)
216 for (i = 0; i < set->n_mutations; i++) {
217 ovsdb_mutation_free(&set->mutations[i]);
219 free(set->mutations);
223 add_int(int64_t *x, int64_t y)
225 /* Check for overflow. See _Hacker's Delight_ pp. 27. */
226 int64_t z = ~(*x ^ y) & INT64_MIN;
227 if ((~(*x ^ y) & ~(((*x ^ z) + y) ^ y)) >> 63) {
236 sub_int(int64_t *x, int64_t y)
238 /* Check for overflow. See _Hacker's Delight_ pp. 27. */
239 int64_t z = (*x ^ y) & INT64_MIN;
240 if (((*x ^ y) & (((*x ^ z) - y) ^ y)) >> 63) {
249 mul_int(int64_t *x, int64_t y)
251 /* Check for overflow. See _Hacker's Delight_ pp. 30. */
254 ? *x >= INT64_MAX / y
255 : y < INT64_MIN / *x)
258 : *x != 0 && y < INT64_MAX / y)) {
267 check_int_div(int64_t x, int64_t y)
269 /* Check for overflow. See _Hacker's Delight_ pp. 32. */
272 } else if (x == INT64_MIN && y == -1) {
280 div_int(int64_t *x, int64_t y)
282 int error = check_int_div(*x, y);
290 mod_int(int64_t *x, int64_t y)
292 int error = check_int_div(*x, y);
300 check_real_range(double x)
302 return x >= -DBL_MAX && x <= DBL_MAX ? 0 : ME_RANGE;
306 add_double(double *x, double y)
313 sub_double(double *x, double y)
320 mul_double(double *x, double y)
327 div_double(double *x, double y)
338 mutate_scalar(const struct ovsdb_type *dst_type, struct ovsdb_datum *dst,
339 const union ovsdb_atom *arg,
340 int (*mutate_integer)(int64_t *x, int64_t y),
341 int (*mutate_real)(double *x, double y))
343 struct ovsdb_error *error;
346 if (dst_type->key_type == OVSDB_TYPE_INTEGER) {
347 int64_t y = arg->integer;
348 for (i = 0; i < dst->n; i++) {
349 int error = mutate_integer(&dst->keys[i].integer, y);
354 } else if (dst_type->key_type == OVSDB_TYPE_REAL) {
355 double y = arg->real;
356 for (i = 0; i < dst->n; i++) {
357 double *x = &dst->keys[i].real;
358 int error = mutate_real(x, y);
360 error = check_real_range(*x);
370 error = ovsdb_datum_sort(dst, dst_type);
372 ovsdb_error_destroy(error);
379 ovsdb_mutation_set_execute(struct ovsdb_row *row,
380 const struct ovsdb_mutation_set *set)
384 for (i = 0; i < set->n_mutations; i++) {
385 const struct ovsdb_mutation *m = &set->mutations[i];
386 struct ovsdb_datum *dst = &row->fields[m->column->index];
387 const struct ovsdb_type *dst_type = &m->column->type;
388 const struct ovsdb_datum *arg = &set->mutations[i].arg;
389 const struct ovsdb_type *arg_type = &m->type;
392 switch (m->mutator) {
394 error = mutate_scalar(dst_type, dst, &arg->keys[0],
395 add_int, add_double);
399 error = mutate_scalar(dst_type, dst, &arg->keys[0],
400 sub_int, sub_double);
404 error = mutate_scalar(dst_type, dst, &arg->keys[0],
405 mul_int, mul_double);
409 error = mutate_scalar(dst_type, dst, &arg->keys[0],
410 div_int, div_double);
414 error = mutate_scalar(dst_type, dst, &arg->keys[0],
419 ovsdb_datum_union(dst, arg, dst_type);
420 error = ovsdb_datum_conforms_to_type(dst, dst_type) ? 0 : ME_COUNT;
424 ovsdb_datum_subtract(dst, dst_type, arg, arg_type);
425 error = ovsdb_datum_conforms_to_type(dst, dst_type) ? 0 : ME_COUNT;
434 return ovsdb_error("domain error", "Division by zero.");
437 return ovsdb_error("range error",
438 "Result of \"%s\" operation is out of range.",
439 ovsdb_mutator_to_string(m->mutator));
442 return ovsdb_error("constraint violation",
443 "Result of \"%s\" operation contains "
445 ovsdb_mutator_to_string(m->mutator));
448 char *s = ovsdb_type_to_english(dst_type);
449 struct ovsdb_error *e = ovsdb_error(
450 "constaint violation",
451 "Attempted to store %u elements in %s.", dst->n, s);
457 return OVSDB_BUG("unexpected errno");