1 /* Copyright (c) 2009, 2010, 2011, 2012 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.
24 #include "ovsdb-error.h"
25 #include "openvswitch/json.h"
34 ovsdb_mutator_from_string(const char *name, enum ovsdb_mutator *mutator)
36 #define OVSDB_MUTATOR(ENUM, NAME) \
37 if (!strcmp(name, NAME)) { \
44 return ovsdb_syntax_error(NULL, "unknown mutator",
45 "No mutator named %s.", name);
49 ovsdb_mutator_to_string(enum ovsdb_mutator mutator)
52 #define OVSDB_MUTATOR(ENUM, NAME) case ENUM: return NAME;
60 static OVS_WARN_UNUSED_RESULT struct ovsdb_error *
61 type_mismatch(const struct ovsdb_mutation *m, const struct json *json)
63 struct ovsdb_error *error;
66 s = ovsdb_type_to_english(&m->column->type);
67 error = ovsdb_syntax_error(
68 json, NULL, "Type mismatch: \"%s\" operator may not be "
69 "applied to column %s of type %s.",
70 ovsdb_mutator_to_string(m->mutator), m->column->name, s);
76 static OVS_WARN_UNUSED_RESULT struct ovsdb_error *
77 ovsdb_mutation_from_json(const struct ovsdb_table_schema *ts,
78 const struct json *json,
79 struct ovsdb_symbol_table *symtab,
80 struct ovsdb_mutation *m)
82 const struct json_array *array;
83 struct ovsdb_error *error;
84 const char *mutator_name;
85 const char *column_name;
87 if (json->type != JSON_ARRAY
88 || json->u.array.n != 3
89 || json->u.array.elems[0]->type != JSON_STRING
90 || json->u.array.elems[1]->type != JSON_STRING) {
91 return ovsdb_syntax_error(json, NULL, "Parse error in mutation.");
93 array = json_array(json);
95 column_name = json_string(array->elems[0]);
96 m->column = ovsdb_table_schema_get_column(ts, column_name);
98 return ovsdb_syntax_error(json, "unknown column",
99 "No column %s in table %s.",
100 column_name, ts->name);
102 if (!m->column->mutable) {
103 return ovsdb_syntax_error(json, "constraint violation",
104 "Cannot mutate immutable column %s in "
105 "table %s.", column_name, ts->name);
108 ovsdb_type_clone(&m->type, &m->column->type);
110 mutator_name = json_string(array->elems[1]);
111 error = ovsdb_mutator_from_string(mutator_name, &m->mutator);
116 /* Type-check and relax restrictions on 'type' if appropriate. */
117 switch (m->mutator) {
123 if ((!ovsdb_type_is_scalar(&m->type) && !ovsdb_type_is_set(&m->type))
124 || (m->type.key.type != OVSDB_TYPE_INTEGER
125 && m->type.key.type != OVSDB_TYPE_REAL)
126 || (m->mutator == OVSDB_M_MOD
127 && m->type.key.type == OVSDB_TYPE_REAL)) {
128 return type_mismatch(m, json);
130 ovsdb_base_type_clear_constraints(&m->type.key);
131 m->type.n_min = m->type.n_max = 1;
132 error = ovsdb_datum_from_json(&m->arg, &m->type, array->elems[2],
138 if (!ovsdb_type_is_set(&m->type) && !ovsdb_type_is_map(&m->type)) {
139 return type_mismatch(m, json);
142 if (m->mutator == OVSDB_M_DELETE) {
143 m->type.n_max = UINT_MAX;
145 error = ovsdb_datum_from_json(&m->arg, &m->type, array->elems[2],
147 if (error && ovsdb_type_is_map(&m->type)
148 && m->mutator == OVSDB_M_DELETE) {
149 ovsdb_error_destroy(error);
150 m->type.value.type = OVSDB_TYPE_VOID;
151 error = ovsdb_datum_from_json(&m->arg, &m->type, array->elems[2],
162 ovsdb_type_destroy(&m->type);
168 ovsdb_mutation_free(struct ovsdb_mutation *m)
170 ovsdb_datum_destroy(&m->arg, &m->type);
171 ovsdb_type_destroy(&m->type);
175 ovsdb_mutation_set_from_json(const struct ovsdb_table_schema *ts,
176 const struct json *json,
177 struct ovsdb_symbol_table *symtab,
178 struct ovsdb_mutation_set *set)
180 const struct json_array *array = json_array(json);
183 set->mutations = xmalloc(array->n * sizeof *set->mutations);
184 set->n_mutations = 0;
185 for (i = 0; i < array->n; i++) {
186 struct ovsdb_error *error;
187 error = ovsdb_mutation_from_json(ts, array->elems[i], symtab,
190 ovsdb_mutation_set_destroy(set);
191 set->mutations = NULL;
192 set->n_mutations = 0;
202 ovsdb_mutation_to_json(const struct ovsdb_mutation *m)
204 return json_array_create_3(
205 json_string_create(m->column->name),
206 json_string_create(ovsdb_mutator_to_string(m->mutator)),
207 ovsdb_datum_to_json(&m->arg, &m->type));
211 ovsdb_mutation_set_to_json(const struct ovsdb_mutation_set *set)
213 struct json **mutations;
216 mutations = xmalloc(set->n_mutations * sizeof *mutations);
217 for (i = 0; i < set->n_mutations; i++) {
218 mutations[i] = ovsdb_mutation_to_json(&set->mutations[i]);
220 return json_array_create(mutations, set->n_mutations);
224 ovsdb_mutation_set_destroy(struct ovsdb_mutation_set *set)
228 for (i = 0; i < set->n_mutations; i++) {
229 ovsdb_mutation_free(&set->mutations[i]);
231 free(set->mutations);
234 enum ovsdb_mutation_scalar_error {
240 struct ovsdb_scalar_mutation {
241 int (*mutate_integer)(int64_t *x, int64_t y);
242 int (*mutate_real)(double *x, double y);
243 enum ovsdb_mutator mutator;
246 static const struct ovsdb_scalar_mutation add_mutation;
247 static const struct ovsdb_scalar_mutation sub_mutation;
248 static const struct ovsdb_scalar_mutation mul_mutation;
249 static const struct ovsdb_scalar_mutation div_mutation;
250 static const struct ovsdb_scalar_mutation mod_mutation;
252 static struct ovsdb_error *
253 ovsdb_mutation_scalar_error(enum ovsdb_mutation_scalar_error error,
254 enum ovsdb_mutator mutator)
258 return OVSDB_BUG("unexpected success");
261 return ovsdb_error("domain error", "Division by zero.");
264 return ovsdb_error("range error",
265 "Result of \"%s\" operation is out of range.",
266 ovsdb_mutator_to_string(mutator));
269 return OVSDB_BUG("unexpected error");
274 check_real_range(double x)
276 return x >= -DBL_MAX && x <= DBL_MAX ? 0 : ME_RANGE;
279 static struct ovsdb_error *
280 mutate_scalar(const struct ovsdb_type *dst_type, struct ovsdb_datum *dst,
281 const union ovsdb_atom *arg,
282 const struct ovsdb_scalar_mutation *mutation)
284 const struct ovsdb_base_type *base = &dst_type->key;
285 struct ovsdb_error *error;
288 if (base->type == OVSDB_TYPE_INTEGER) {
289 int64_t y = arg->integer;
290 for (i = 0; i < dst->n; i++) {
291 enum ovsdb_mutation_scalar_error me;
293 me = (mutation->mutate_integer)(&dst->keys[i].integer, y);
295 return ovsdb_mutation_scalar_error(me, mutation->mutator);
298 } else if (base->type == OVSDB_TYPE_REAL) {
299 double y = arg->real;
300 for (i = 0; i < dst->n; i++) {
301 double *x = &dst->keys[i].real;
302 enum ovsdb_mutation_scalar_error me;
304 me = (mutation->mutate_real)(x, y);
306 me = check_real_range(*x);
309 return ovsdb_mutation_scalar_error(me, mutation->mutator);
316 for (i = 0; i < dst->n; i++) {
317 error = ovsdb_atom_check_constraints(&dst->keys[i], base);
323 error = ovsdb_datum_sort(dst, dst_type->key.type);
325 ovsdb_error_destroy(error);
326 return ovsdb_error("constraint violation",
327 "Result of \"%s\" operation contains duplicates.",
328 ovsdb_mutator_to_string(mutation->mutator));
333 static struct ovsdb_error *
334 ovsdb_mutation_check_count(struct ovsdb_datum *dst,
335 const struct ovsdb_type *dst_type)
337 if (!ovsdb_datum_conforms_to_type(dst, dst_type)) {
338 char *s = ovsdb_type_to_english(dst_type);
339 struct ovsdb_error *e = ovsdb_error(
340 "constraint violation",
341 "Attempted to store %u elements in %s.", dst->n, s);
349 ovsdb_mutation_set_execute(struct ovsdb_row *row,
350 const struct ovsdb_mutation_set *set)
354 for (i = 0; i < set->n_mutations; i++) {
355 const struct ovsdb_mutation *m = &set->mutations[i];
356 struct ovsdb_datum *dst = &row->fields[m->column->index];
357 const struct ovsdb_type *dst_type = &m->column->type;
358 const struct ovsdb_datum *arg = &set->mutations[i].arg;
359 const struct ovsdb_type *arg_type = &m->type;
360 struct ovsdb_error *error;
362 switch (m->mutator) {
364 error = mutate_scalar(dst_type, dst, &arg->keys[0], &add_mutation);
368 error = mutate_scalar(dst_type, dst, &arg->keys[0], &sub_mutation);
372 error = mutate_scalar(dst_type, dst, &arg->keys[0], &mul_mutation);
376 error = mutate_scalar(dst_type, dst, &arg->keys[0], &div_mutation);
380 error = mutate_scalar(dst_type, dst, &arg->keys[0], &mod_mutation);
384 ovsdb_datum_union(dst, arg, dst_type, false);
385 error = ovsdb_mutation_check_count(dst, dst_type);
389 ovsdb_datum_subtract(dst, dst_type, arg, arg_type);
390 error = ovsdb_mutation_check_count(dst, dst_type);
405 add_int(int64_t *x, int64_t y)
407 /* Check for overflow. See _Hacker's Delight_ pp. 27. */
408 int64_t z = ~(*x ^ y) & INT64_MIN;
409 if ((~(*x ^ y) & ~(((*x ^ z) + y) ^ y)) >> 63) {
418 sub_int(int64_t *x, int64_t y)
420 /* Check for overflow. See _Hacker's Delight_ pp. 27. */
421 int64_t z = (*x ^ y) & INT64_MIN;
422 if (((*x ^ y) & (((*x ^ z) - y) ^ y)) >> 63) {
431 mul_int(int64_t *x, int64_t y)
433 /* Check for overflow. See _Hacker's Delight_ pp. 30. */
436 ? *x >= INT64_MAX / y
437 : y < INT64_MIN / *x)
440 : *x != 0 && y < INT64_MAX / y)) {
449 check_int_div(int64_t x, int64_t y)
451 /* Check for overflow. See _Hacker's Delight_ pp. 32. */
454 } else if (x == INT64_MIN && y == -1) {
462 div_int(int64_t *x, int64_t y)
464 int error = check_int_div(*x, y);
472 mod_int(int64_t *x, int64_t y)
474 int error = check_int_div(*x, y);
482 add_double(double *x, double y)
489 sub_double(double *x, double y)
496 mul_double(double *x, double y)
503 div_double(double *x, double y)
513 static const struct ovsdb_scalar_mutation add_mutation = {
514 add_int, add_double, OVSDB_M_ADD
517 static const struct ovsdb_scalar_mutation sub_mutation = {
518 sub_int, sub_double, OVSDB_M_SUB
521 static const struct ovsdb_scalar_mutation mul_mutation = {
522 mul_int, mul_double, OVSDB_M_MUL
525 static const struct ovsdb_scalar_mutation div_mutation = {
526 div_int, div_double, OVSDB_M_DIV
529 static const struct ovsdb_scalar_mutation mod_mutation = {
530 mod_int, NULL, OVSDB_M_MOD