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
89 || json
->array
.elems
[0]->type
!= JSON_STRING
90 || json
->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