LCOV - code coverage report
Current view: top level - ovsdb - mutation.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 200 210 95.2 %
Date: 2016-09-14 01:02:56 Functions: 24 24 100.0 %
Branches: 121 143 84.6 %

           Branch data     Line data    Source code
       1                 :            : /* Copyright (c) 2009, 2010, 2011, 2012 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                 :            : 
      18                 :            : #include "mutation.h"
      19                 :            : 
      20                 :            : #include <float.h>
      21                 :            : #include <limits.h>
      22                 :            : 
      23                 :            : #include "column.h"
      24                 :            : #include "ovsdb-error.h"
      25                 :            : #include "openvswitch/json.h"
      26                 :            : #include "row.h"
      27                 :            : 
      28                 :            : #include <string.h>
      29                 :            : 
      30                 :            : #include "table.h"
      31                 :            : #include "util.h"
      32                 :            : 
      33                 :            : struct ovsdb_error *
      34                 :       2364 : ovsdb_mutator_from_string(const char *name, enum ovsdb_mutator *mutator)
      35                 :            : {
      36                 :            : #define OVSDB_MUTATOR(ENUM, NAME)               \
      37                 :            :     if (!strcmp(name, NAME)) {                  \
      38                 :            :         *mutator = ENUM;                        \
      39                 :            :         return NULL;                            \
      40                 :            :     }
      41 [ +  + ][ +  + ]:       2364 :     OVSDB_MUTATORS;
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
                 [ +  + ]
      42                 :            : #undef OVSDB_MUTATOR
      43                 :            : 
      44                 :          1 :     return ovsdb_syntax_error(NULL, "unknown mutator",
      45                 :            :                               "No mutator named %s.", name);
      46                 :            : }
      47                 :            : 
      48                 :            : const char *
      49                 :         81 : ovsdb_mutator_to_string(enum ovsdb_mutator mutator)
      50                 :            : {
      51   [ +  +  +  +  :         81 :     switch (mutator) {
             +  +  +  - ]
      52                 :            : #define OVSDB_MUTATOR(ENUM, NAME) case ENUM: return NAME;
      53                 :         81 :         OVSDB_MUTATORS;
      54                 :            : #undef OVSDB_MUTATOR
      55                 :            :     }
      56                 :            : 
      57                 :          0 :     return NULL;
      58                 :            : }
      59                 :            : 
      60                 :            : static OVS_WARN_UNUSED_RESULT struct ovsdb_error *
      61                 :         25 : type_mismatch(const struct ovsdb_mutation *m, const struct json *json)
      62                 :            : {
      63                 :            :     struct ovsdb_error *error;
      64                 :            :     char *s;
      65                 :            : 
      66                 :         25 :     s = ovsdb_type_to_english(&m->column->type);
      67                 :         25 :     error = ovsdb_syntax_error(
      68                 :            :         json, NULL, "Type mismatch: \"%s\" operator may not be "
      69                 :            :         "applied to column %s of type %s.",
      70                 :         25 :         ovsdb_mutator_to_string(m->mutator), m->column->name, s);
      71                 :         25 :     free(s);
      72                 :            : 
      73                 :         25 :     return error;
      74                 :            : }
      75                 :            : 
      76                 :            : static OVS_WARN_UNUSED_RESULT struct ovsdb_error *
      77                 :       2379 : 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)
      81                 :            : {
      82                 :            :     const struct json_array *array;
      83                 :            :     struct ovsdb_error *error;
      84                 :            :     const char *mutator_name;
      85                 :            :     const char *column_name;
      86                 :            : 
      87         [ +  - ]:       2379 :     if (json->type != JSON_ARRAY
      88         [ +  - ]:       2379 :         || json->u.array.n != 3
      89         [ +  - ]:       2379 :         || json->u.array.elems[0]->type != JSON_STRING
      90         [ -  + ]:       2379 :         || json->u.array.elems[1]->type != JSON_STRING) {
      91                 :          0 :         return ovsdb_syntax_error(json, NULL, "Parse error in mutation.");
      92                 :            :     }
      93                 :       2379 :     array = json_array(json);
      94                 :            : 
      95                 :       2379 :     column_name = json_string(array->elems[0]);
      96                 :       2379 :     m->column = ovsdb_table_schema_get_column(ts, column_name);
      97         [ -  + ]:       2379 :     if (!m->column) {
      98                 :          0 :         return ovsdb_syntax_error(json, "unknown column",
      99                 :            :                                   "No column %s in table %s.",
     100                 :            :                                   column_name, ts->name);
     101                 :            :     }
     102         [ +  + ]:       2379 :     if (!m->column->mutable) {
     103                 :         15 :         return ovsdb_syntax_error(json, "constraint violation",
     104                 :            :                                   "Cannot mutate immutable column %s in "
     105                 :            :                                   "table %s.", column_name, ts->name);
     106                 :            :     }
     107                 :            : 
     108                 :       2364 :     ovsdb_type_clone(&m->type, &m->column->type);
     109                 :            : 
     110                 :       2364 :     mutator_name = json_string(array->elems[1]);
     111                 :       2364 :     error = ovsdb_mutator_from_string(mutator_name, &m->mutator);
     112         [ +  + ]:       2364 :     if (error) {
     113                 :          1 :         goto exit;
     114                 :            :     }
     115                 :            : 
     116                 :            :     /* Type-check and relax restrictions on 'type' if appropriate.  */
     117      [ +  +  - ]:       2363 :     switch (m->mutator) {
     118                 :            :     case OVSDB_M_ADD:
     119                 :            :     case OVSDB_M_SUB:
     120                 :            :     case OVSDB_M_MUL:
     121                 :            :     case OVSDB_M_DIV:
     122                 :            :     case OVSDB_M_MOD:
     123 [ +  + ][ +  - ]:       2213 :         if ((!ovsdb_type_is_scalar(&m->type) && !ovsdb_type_is_set(&m->type))
     124         [ +  + ]:       2213 :             || (m->type.key.type != OVSDB_TYPE_INTEGER
     125         [ +  + ]:         42 :                 && m->type.key.type != OVSDB_TYPE_REAL)
     126         [ +  + ]:       2199 :             || (m->mutator == OVSDB_M_MOD
     127         [ +  + ]:          6 :                 && m->type.key.type == OVSDB_TYPE_REAL)) {
     128                 :         15 :             return type_mismatch(m, json);
     129                 :            :         }
     130                 :       2198 :         ovsdb_base_type_clear_constraints(&m->type.key);
     131                 :       2198 :         m->type.n_min = m->type.n_max = 1;
     132                 :       2198 :         error = ovsdb_datum_from_json(&m->arg, &m->type, array->elems[2],
     133                 :            :                                       symtab);
     134                 :       2198 :         break;
     135                 :            : 
     136                 :            :     case OVSDB_M_INSERT:
     137                 :            :     case OVSDB_M_DELETE:
     138 [ +  + ][ +  + ]:        150 :         if (!ovsdb_type_is_set(&m->type) && !ovsdb_type_is_map(&m->type)) {
     139                 :         10 :             return type_mismatch(m, json);
     140                 :            :         }
     141                 :        140 :         m->type.n_min = 0;
     142         [ +  + ]:        140 :         if (m->mutator == OVSDB_M_DELETE) {
     143                 :         63 :             m->type.n_max = UINT_MAX;
     144                 :            :         }
     145                 :        140 :         error = ovsdb_datum_from_json(&m->arg, &m->type, array->elems[2],
     146                 :            :                                       symtab);
     147 [ +  + ][ +  - ]:        140 :         if (error && ovsdb_type_is_map(&m->type)
     148         [ +  - ]:         12 :             && m->mutator == OVSDB_M_DELETE) {
     149                 :         12 :             ovsdb_error_destroy(error);
     150                 :         12 :             m->type.value.type = OVSDB_TYPE_VOID;
     151                 :         12 :             error = ovsdb_datum_from_json(&m->arg, &m->type, array->elems[2],
     152                 :            :                                           symtab);
     153                 :            :         }
     154                 :        140 :         break;
     155                 :            : 
     156                 :            :     default:
     157                 :          0 :         OVS_NOT_REACHED();
     158                 :            :     }
     159                 :            : 
     160                 :            : exit:
     161         [ +  + ]:       2339 :     if (error) {
     162                 :          1 :         ovsdb_type_destroy(&m->type);
     163                 :            :     }
     164                 :       2339 :     return error;
     165                 :            : }
     166                 :            : 
     167                 :            : static void
     168                 :       2338 : ovsdb_mutation_free(struct ovsdb_mutation *m)
     169                 :            : {
     170                 :       2338 :     ovsdb_datum_destroy(&m->arg, &m->type);
     171                 :       2338 :     ovsdb_type_destroy(&m->type);
     172                 :       2338 : }
     173                 :            : 
     174                 :            : struct ovsdb_error *
     175                 :       2368 : 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)
     179                 :            : {
     180                 :       2368 :     const struct json_array *array = json_array(json);
     181                 :            :     size_t i;
     182                 :            : 
     183                 :       2368 :     set->mutations = xmalloc(array->n * sizeof *set->mutations);
     184                 :       2368 :     set->n_mutations = 0;
     185         [ +  + ]:       4706 :     for (i = 0; i < array->n; i++) {
     186                 :            :         struct ovsdb_error *error;
     187                 :       2379 :         error = ovsdb_mutation_from_json(ts, array->elems[i], symtab,
     188                 :       2379 :                                          &set->mutations[i]);
     189         [ +  + ]:       2379 :         if (error) {
     190                 :         41 :             ovsdb_mutation_set_destroy(set);
     191                 :         41 :             set->mutations = NULL;
     192                 :         41 :             set->n_mutations = 0;
     193                 :         41 :             return error;
     194                 :            :         }
     195                 :       2338 :         set->n_mutations++;
     196                 :            :     }
     197                 :            : 
     198                 :       2327 :     return NULL;
     199                 :            : }
     200                 :            : 
     201                 :            : static struct json *
     202                 :         28 : ovsdb_mutation_to_json(const struct ovsdb_mutation *m)
     203                 :            : {
     204                 :         28 :     return json_array_create_3(
     205                 :         28 :         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));
     208                 :            : }
     209                 :            : 
     210                 :            : struct json *
     211                 :         29 : ovsdb_mutation_set_to_json(const struct ovsdb_mutation_set *set)
     212                 :            : {
     213                 :            :     struct json **mutations;
     214                 :            :     size_t i;
     215                 :            : 
     216                 :         29 :     mutations = xmalloc(set->n_mutations * sizeof *mutations);
     217         [ +  + ]:         57 :     for (i = 0; i < set->n_mutations; i++) {
     218                 :         28 :         mutations[i] = ovsdb_mutation_to_json(&set->mutations[i]);
     219                 :            :     }
     220                 :         29 :     return json_array_create(mutations, set->n_mutations);
     221                 :            : }
     222                 :            : 
     223                 :            : void
     224                 :       2409 : ovsdb_mutation_set_destroy(struct ovsdb_mutation_set *set)
     225                 :            : {
     226                 :            :     size_t i;
     227                 :            : 
     228         [ +  + ]:       4747 :     for (i = 0; i < set->n_mutations; i++) {
     229                 :       2338 :         ovsdb_mutation_free(&set->mutations[i]);
     230                 :            :     }
     231                 :       2409 :     free(set->mutations);
     232                 :       2409 : }
     233                 :            : 
     234                 :            : enum ovsdb_mutation_scalar_error {
     235                 :            :     ME_OK,
     236                 :            :     ME_DOM,
     237                 :            :     ME_RANGE
     238                 :            : };
     239                 :            : 
     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;
     244                 :            : };
     245                 :            : 
     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;
     251                 :            : 
     252                 :            : static struct ovsdb_error *
     253                 :         33 : ovsdb_mutation_scalar_error(enum ovsdb_mutation_scalar_error error,
     254                 :            :                             enum ovsdb_mutator mutator)
     255                 :            : {
     256   [ -  +  +  - ]:         33 :     switch (error) {
     257                 :            :     case ME_OK:
     258                 :          0 :         return OVSDB_BUG("unexpected success");
     259                 :            : 
     260                 :            :     case ME_DOM:
     261                 :         10 :         return ovsdb_error("domain error", "Division by zero.");
     262                 :            : 
     263                 :            :     case ME_RANGE:
     264                 :         23 :         return ovsdb_error("range error",
     265                 :            :                            "Result of \"%s\" operation is out of range.",
     266                 :            :                            ovsdb_mutator_to_string(mutator));
     267                 :            : 
     268                 :            :     default:
     269                 :          0 :         return OVSDB_BUG("unexpected error");
     270                 :            :     }
     271                 :            : }
     272                 :            : 
     273                 :            : static int
     274                 :         69 : check_real_range(double x)
     275                 :            : {
     276 [ +  + ][ +  + ]:         69 :     return x >= -DBL_MAX && x <= DBL_MAX ? 0 : ME_RANGE;
     277                 :            : }
     278                 :            : 
     279                 :            : static struct ovsdb_error *
     280                 :       2307 : 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)
     283                 :            : {
     284                 :       2307 :     const struct ovsdb_base_type *base = &dst_type->key;
     285                 :            :     struct ovsdb_error *error;
     286                 :            :     unsigned int i;
     287                 :            : 
     288         [ +  + ]:       2307 :     if (base->type == OVSDB_TYPE_INTEGER) {
     289                 :       2245 :         int64_t y = arg->integer;
     290         [ +  + ]:       4476 :         for (i = 0; i < dst->n; i++) {
     291                 :            :             enum ovsdb_mutation_scalar_error me;
     292                 :            : 
     293                 :       2255 :             me = (mutation->mutate_integer)(&dst->keys[i].integer, y);
     294         [ +  + ]:       2255 :             if (me != ME_OK) {
     295                 :         24 :                 return ovsdb_mutation_scalar_error(me, mutation->mutator);
     296                 :            :             }
     297                 :            :         }
     298         [ +  - ]:         62 :     } else if (base->type == OVSDB_TYPE_REAL) {
     299                 :         62 :         double y = arg->real;
     300         [ +  + ]:        125 :         for (i = 0; i < dst->n; i++) {
     301                 :         72 :             double *x = &dst->keys[i].real;
     302                 :            :             enum ovsdb_mutation_scalar_error me;
     303                 :            : 
     304                 :         72 :             me = (mutation->mutate_real)(x, y);
     305         [ +  + ]:         72 :             if (me == ME_OK) {
     306                 :         69 :                 me = check_real_range(*x);
     307                 :            :             }
     308         [ +  + ]:         72 :             if (me != ME_OK) {
     309                 :          9 :                 return ovsdb_mutation_scalar_error(me, mutation->mutator);
     310                 :            :             }
     311                 :            :         }
     312                 :            :     } else {
     313                 :          0 :         OVS_NOT_REACHED();
     314                 :            :     }
     315                 :            : 
     316         [ +  + ]:       4558 :     for (i = 0; i < dst->n; i++) {
     317                 :       2294 :         error = ovsdb_atom_check_constraints(&dst->keys[i], base);
     318         [ +  + ]:       2294 :         if (error) {
     319                 :         10 :             return error;
     320                 :            :         }
     321                 :            :     }
     322                 :            : 
     323                 :       2264 :     error = ovsdb_datum_sort(dst, dst_type->key.type);
     324         [ +  + ]:       2264 :     if (error) {
     325                 :          5 :         ovsdb_error_destroy(error);
     326                 :          5 :         return ovsdb_error("constraint violation",
     327                 :            :                            "Result of \"%s\" operation contains duplicates.",
     328                 :            :                            ovsdb_mutator_to_string(mutation->mutator));
     329                 :            :     }
     330                 :       2259 :     return NULL;
     331                 :            : }
     332                 :            : 
     333                 :            : static struct ovsdb_error *
     334                 :        236 : ovsdb_mutation_check_count(struct ovsdb_datum *dst,
     335                 :            :                            const struct ovsdb_type *dst_type)
     336                 :            : {
     337         [ +  + ]:        236 :     if (!ovsdb_datum_conforms_to_type(dst, dst_type)) {
     338                 :         11 :         char *s = ovsdb_type_to_english(dst_type);
     339                 :         11 :         struct ovsdb_error *e = ovsdb_error(
     340                 :            :             "constraint violation",
     341                 :            :             "Attempted to store %u elements in %s.", dst->n, s);
     342                 :         11 :         free(s);
     343                 :         11 :         return e;
     344                 :            :     }
     345                 :        225 :     return NULL;
     346                 :            : }
     347                 :            : 
     348                 :            : struct ovsdb_error *
     349                 :       2533 : ovsdb_mutation_set_execute(struct ovsdb_row *row,
     350                 :            :                            const struct ovsdb_mutation_set *set)
     351                 :            : {
     352                 :            :     size_t i;
     353                 :            : 
     354         [ +  + ]:       5017 :     for (i = 0; i < set->n_mutations; i++) {
     355                 :       2543 :         const struct ovsdb_mutation *m = &set->mutations[i];
     356                 :       2543 :         struct ovsdb_datum *dst = &row->fields[m->column->index];
     357                 :       2543 :         const struct ovsdb_type *dst_type = &m->column->type;
     358                 :       2543 :         const struct ovsdb_datum *arg = &set->mutations[i].arg;
     359                 :       2543 :         const struct ovsdb_type *arg_type = &m->type;
     360                 :            :         struct ovsdb_error *error;
     361                 :            : 
     362   [ +  +  +  +  :       2543 :         switch (m->mutator) {
             +  +  +  - ]
     363                 :            :         case OVSDB_M_ADD:
     364                 :       2169 :             error = mutate_scalar(dst_type, dst, &arg->keys[0], &add_mutation);
     365                 :       2169 :             break;
     366                 :            : 
     367                 :            :         case OVSDB_M_SUB:
     368                 :         37 :             error = mutate_scalar(dst_type, dst, &arg->keys[0], &sub_mutation);
     369                 :         37 :             break;
     370                 :            : 
     371                 :            :         case OVSDB_M_MUL:
     372                 :         48 :             error = mutate_scalar(dst_type, dst, &arg->keys[0], &mul_mutation);
     373                 :         48 :             break;
     374                 :            : 
     375                 :            :         case OVSDB_M_DIV:
     376                 :         43 :             error = mutate_scalar(dst_type, dst, &arg->keys[0], &div_mutation);
     377                 :         43 :             break;
     378                 :            : 
     379                 :            :         case OVSDB_M_MOD:
     380                 :         10 :             error = mutate_scalar(dst_type, dst, &arg->keys[0], &mod_mutation);
     381                 :         10 :             break;
     382                 :            : 
     383                 :            :         case OVSDB_M_INSERT:
     384                 :        121 :             ovsdb_datum_union(dst, arg, dst_type, false);
     385                 :        121 :             error = ovsdb_mutation_check_count(dst, dst_type);
     386                 :        121 :             break;
     387                 :            : 
     388                 :            :         case OVSDB_M_DELETE:
     389                 :        115 :             ovsdb_datum_subtract(dst, dst_type, arg, arg_type);
     390                 :        115 :             error = ovsdb_mutation_check_count(dst, dst_type);
     391                 :        115 :             break;
     392                 :            : 
     393                 :            :         default:
     394                 :          0 :             OVS_NOT_REACHED();
     395                 :            :         }
     396         [ +  + ]:       2543 :         if (error) {
     397                 :         59 :             return error;
     398                 :            :         }
     399                 :            :     }
     400                 :            : 
     401                 :       2474 :     return NULL;
     402                 :            : }
     403                 :            : 
     404                 :            : static int
     405                 :       2158 : add_int(int64_t *x, int64_t y)
     406                 :            : {
     407                 :            :     /* Check for overflow.  See _Hacker's Delight_ pp. 27. */
     408                 :       2158 :     int64_t z = ~(*x ^ y) & INT64_MIN;
     409         [ +  + ]:       2158 :     if ((~(*x ^ y) & ~(((*x ^ z) + y) ^ y)) >> 63) {
     410                 :          6 :         return ME_RANGE;
     411                 :            :     } else {
     412                 :       2152 :         *x += y;
     413                 :       2152 :         return 0;
     414                 :            :     }
     415                 :            : }
     416                 :            : 
     417                 :            : static int
     418                 :         26 : sub_int(int64_t *x, int64_t y)
     419                 :            : {
     420                 :            :     /* Check for overflow.  See _Hacker's Delight_ pp. 27. */
     421                 :         26 :     int64_t z = (*x ^ y) & INT64_MIN;
     422         [ +  + ]:         26 :     if (((*x ^ y) & (((*x ^ z) - y) ^ y)) >> 63) {
     423                 :          6 :         return ME_RANGE;
     424                 :            :     } else {
     425                 :         20 :         *x -= y;
     426                 :         20 :         return 0;
     427                 :            :     }
     428                 :            : }
     429                 :            : 
     430                 :            : static int
     431                 :         33 : mul_int(int64_t *x, int64_t y)
     432                 :            : {
     433                 :            :     /* Check for overflow.  See _Hacker's Delight_ pp. 30. */
     434 [ +  + ][ +  - ]:         33 :     if (*x > 0
         [ +  - ][ +  + ]
     435                 :            :         ? (y > 0
     436                 :         24 :            ? *x >= INT64_MAX / y
     437                 :          0 :            : y  < INT64_MIN / *x)
     438                 :            :         : (y > 0
     439                 :          9 :            ? *x < INT64_MIN / y
     440 [ #  # ][ #  # ]:          0 :            : *x != 0 && y < INT64_MAX / y)) {
     441                 :          4 :         return ME_RANGE;
     442                 :            :     } else {
     443                 :         29 :         *x *= y;
     444                 :         29 :         return 0;
     445                 :            :     }
     446                 :            : }
     447                 :            : 
     448                 :            : static int
     449                 :         38 : check_int_div(int64_t x, int64_t y)
     450                 :            : {
     451                 :            :     /* Check for overflow.  See _Hacker's Delight_ pp. 32. */
     452         [ +  + ]:         38 :     if (!y) {
     453                 :          7 :         return ME_DOM;
     454 [ +  + ][ +  - ]:         31 :     } else if (x == INT64_MIN && y == -1) {
     455                 :          1 :         return ME_RANGE;
     456                 :            :     } else {
     457                 :         30 :         return 0;
     458                 :            :     }
     459                 :            : }
     460                 :            : 
     461                 :            : static int
     462                 :         26 : div_int(int64_t *x, int64_t y)
     463                 :            : {
     464                 :         26 :     int error = check_int_div(*x, y);
     465         [ +  + ]:         26 :     if (!error) {
     466                 :         18 :         *x /= y;
     467                 :            :     }
     468                 :         26 :     return error;
     469                 :            : }
     470                 :            : 
     471                 :            : static int
     472                 :         12 : mod_int(int64_t *x, int64_t y)
     473                 :            : {
     474                 :         12 :     int error = check_int_div(*x, y);
     475         [ +  - ]:         12 :     if (!error) {
     476                 :         12 :         *x %= y;
     477                 :            :     }
     478                 :         12 :     return error;
     479                 :            : }
     480                 :            : 
     481                 :            : static int
     482                 :         15 : add_double(double *x, double y)
     483                 :            : {
     484                 :         15 :     *x += y;
     485                 :         15 :     return 0;
     486                 :            : }
     487                 :            : 
     488                 :            : static int
     489                 :         15 : sub_double(double *x, double y)
     490                 :            : {
     491                 :         15 :     *x -= y;
     492                 :         15 :     return 0;
     493                 :            : }
     494                 :            : 
     495                 :            : static int
     496                 :         21 : mul_double(double *x, double y)
     497                 :            : {
     498                 :         21 :     *x *= y;
     499                 :         21 :     return 0;
     500                 :            : }
     501                 :            : 
     502                 :            : static int
     503                 :         21 : div_double(double *x, double y)
     504                 :            : {
     505         [ +  + ]:         21 :     if (y == 0) {
     506                 :          3 :         return ME_DOM;
     507                 :            :     } else {
     508                 :         18 :         *x /= y;
     509                 :         18 :         return 0;
     510                 :            :     }
     511                 :            : }
     512                 :            : 
     513                 :            : static const struct ovsdb_scalar_mutation add_mutation = {
     514                 :            :     add_int, add_double, OVSDB_M_ADD
     515                 :            : };
     516                 :            : 
     517                 :            : static const struct ovsdb_scalar_mutation sub_mutation = {
     518                 :            :     sub_int, sub_double, OVSDB_M_SUB
     519                 :            : };
     520                 :            : 
     521                 :            : static const struct ovsdb_scalar_mutation mul_mutation = {
     522                 :            :     mul_int, mul_double, OVSDB_M_MUL
     523                 :            : };
     524                 :            : 
     525                 :            : static const struct ovsdb_scalar_mutation div_mutation = {
     526                 :            :     div_int, div_double, OVSDB_M_DIV
     527                 :            : };
     528                 :            : 
     529                 :            : static const struct ovsdb_scalar_mutation mod_mutation = {
     530                 :            :     mod_int, NULL, OVSDB_M_MOD
     531                 :            : };

Generated by: LCOV version 1.12