LCOV - code coverage report
Current view: top level - ovsdb - condition.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 222 242 91.7 %
Date: 2016-09-14 01:02:56 Functions: 23 24 95.8 %
Branches: 154 197 78.2 %

           Branch data     Line data    Source code
       1                 :            : /* Copyright (c) 2009, 2010, 2011 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 "condition.h"
      19                 :            : 
      20                 :            : #include <limits.h>
      21                 :            : 
      22                 :            : #include "column.h"
      23                 :            : #include "openvswitch/json.h"
      24                 :            : #include "ovsdb-error.h"
      25                 :            : #include "row.h"
      26                 :            : 
      27                 :            : #include <string.h>
      28                 :            : 
      29                 :            : #include "table.h"
      30                 :            : #include "util.h"
      31                 :            : 
      32                 :            : struct ovsdb_error *
      33                 :      51199 : ovsdb_function_from_string(const char *name, enum ovsdb_function *function)
      34                 :            : {
      35                 :            : #define OVSDB_FUNCTION(ENUM, NAME)              \
      36                 :            :     if (!strcmp(name, NAME)) {                  \
      37                 :            :         *function = ENUM;                       \
      38                 :            :         return NULL;                            \
      39                 :            :     }
      40 [ -  + ][ -  + ]:      51199 :     OVSDB_FUNCTIONS;
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  - ]
      41                 :            : #undef OVSDB_FUNCTION
      42                 :            : 
      43                 :          0 :     return ovsdb_syntax_error(NULL, "unknown function",
      44                 :            :                               "No function named %s.", name);
      45                 :            : }
      46                 :            : 
      47                 :            : const char *
      48                 :         78 : ovsdb_function_to_string(enum ovsdb_function function)
      49                 :            : {
      50   [ -  -  +  +  :         78 :     switch (function) {
          +  +  +  +  +  
                   +  - ]
      51                 :            : #define OVSDB_FUNCTION(ENUM, NAME) case ENUM: return NAME;
      52                 :         78 :         OVSDB_FUNCTIONS;
      53                 :            : #undef OVSDB_FUNCTION
      54                 :            :     }
      55                 :            : 
      56                 :          0 :     return NULL;
      57                 :            : }
      58                 :            : 
      59                 :            : static struct ovsdb_error *
      60                 :      51415 : ovsdb_clause_from_json(const struct ovsdb_table_schema *ts,
      61                 :            :                        const struct json *json,
      62                 :            :                        struct ovsdb_symbol_table *symtab,
      63                 :            :                        struct ovsdb_clause *clause)
      64                 :            : {
      65                 :            :     const struct json_array *array;
      66                 :            :     struct ovsdb_error *error;
      67                 :            :     const char *function_name;
      68                 :            :     const char *column_name;
      69                 :            :     struct ovsdb_type type;
      70                 :            : 
      71 [ +  + ][ +  + ]:      51415 :     if (json->type == JSON_TRUE || json->type == JSON_FALSE) {
      72                 :        225 :         clause->function =
      73                 :        225 :             json->type == JSON_TRUE ? OVSDB_F_TRUE : OVSDB_F_FALSE;
      74                 :            : 
      75                 :            :         /* Column and arg fields are not being used with boolean functions.
      76                 :            :          * Use dummy values */
      77                 :        225 :         clause->column = ovsdb_table_schema_get_column(ts, "_uuid");
      78                 :        225 :         clause->index = clause->column->index;
      79                 :        225 :         ovsdb_datum_init_default(&clause->arg, &clause->column->type);
      80                 :        225 :         return NULL;
      81                 :            :     }
      82                 :            : 
      83         [ +  - ]:      51190 :     if (json->type != JSON_ARRAY
      84         [ +  - ]:      51190 :         || json->u.array.n != 3
      85         [ +  - ]:      51190 :         || json->u.array.elems[0]->type != JSON_STRING
      86         [ -  + ]:      51190 :         || json->u.array.elems[1]->type != JSON_STRING) {
      87                 :          0 :         return ovsdb_syntax_error(json, NULL, "Parse error in condition.");
      88                 :            :     }
      89                 :      51190 :     array = json_array(json);
      90                 :            : 
      91                 :      51190 :     column_name = json_string(array->elems[0]);
      92                 :      51190 :     clause->column = ovsdb_table_schema_get_column(ts, column_name);
      93         [ -  + ]:      51190 :     if (!clause->column) {
      94                 :          0 :         return ovsdb_syntax_error(json, "unknown column",
      95                 :            :                                   "No column %s in table %s.",
      96                 :            :                                   column_name, ts->name);
      97                 :            :     }
      98                 :      51190 :     clause->index = clause->column->index;
      99                 :      51190 :     type = clause->column->type;
     100                 :            : 
     101                 :      51190 :     function_name = json_string(array->elems[1]);
     102                 :      51190 :     error = ovsdb_function_from_string(function_name, &clause->function);
     103         [ -  + ]:      51190 :     if (error) {
     104                 :          0 :         return error;
     105                 :            :     }
     106                 :            : 
     107                 :            :     /* Type-check and relax restrictions on 'type' if appropriate.  */
     108   [ +  +  +  +  :      51190 :     switch (clause->function) {
                   -  - ]
     109                 :            :     case OVSDB_F_LT:
     110                 :            :     case OVSDB_F_LE:
     111                 :            :     case OVSDB_F_GT:
     112                 :            :     case OVSDB_F_GE:
     113                 :            :         /* Allow these operators for types with n_min == 0, n_max == 1.
     114                 :            :          * (They will always be "false" if the value is missing.) */
     115   [ +  +  +  - ]:         94 :         if (!(ovsdb_type_is_scalar(&type)
     116                 :         10 :             || ovsdb_type_is_optional_scalar(&type))
     117         [ +  + ]:         84 :             || (type.key.type != OVSDB_TYPE_INTEGER
     118         [ +  + ]:         36 :                 && type.key.type != OVSDB_TYPE_REAL)) {
     119                 :         12 :             char *s = ovsdb_type_to_english(&type);
     120                 :         12 :             error = ovsdb_syntax_error(
     121                 :            :                 json, NULL, "Type mismatch: \"%s\" operator may not be "
     122                 :            :                 "applied to column %s of type %s.",
     123                 :            :                 ovsdb_function_to_string(clause->function),
     124                 :         12 :                 clause->column->name, s);
     125                 :         12 :             free(s);
     126                 :         12 :             return error;
     127                 :            :         }
     128                 :         72 :         break;
     129                 :            :     case OVSDB_F_EQ:
     130                 :            :     case OVSDB_F_NE:
     131                 :      50931 :         break;
     132                 :            : 
     133                 :            :     case OVSDB_F_EXCLUDES:
     134         [ +  + ]:         83 :         if (!ovsdb_type_is_scalar(&type)) {
     135                 :         57 :             type.n_min = 0;
     136                 :         57 :             type.n_max = UINT_MAX;
     137                 :            :         }
     138                 :         83 :         break;
     139                 :            : 
     140                 :            :     case OVSDB_F_INCLUDES:
     141         [ +  + ]:         92 :         if (!ovsdb_type_is_scalar(&type)) {
     142                 :         63 :             type.n_min = 0;
     143                 :            :         }
     144                 :         92 :         break;
     145                 :            :     case OVSDB_F_TRUE:
     146                 :            :     case OVSDB_F_FALSE:
     147                 :          0 :         OVS_NOT_REACHED();
     148                 :            :     }
     149                 :      51415 :     return ovsdb_datum_from_json(&clause->arg, &type, array->elems[2], symtab);
     150                 :            : }
     151                 :            : 
     152                 :            : static void
     153                 :      51881 : ovsdb_clause_free(struct ovsdb_clause *clause)
     154                 :            : {
     155                 :      51881 :     ovsdb_datum_destroy(&clause->arg, &clause->column->type);
     156                 :      51881 : }
     157                 :            : 
     158                 :            : static int
     159                 :        339 : compare_clauses_3way(const void *a_, const void *b_)
     160                 :            : {
     161                 :        339 :     const struct ovsdb_clause *a = a_;
     162                 :        339 :     const struct ovsdb_clause *b = b_;
     163                 :            : 
     164         [ +  + ]:        339 :     if (a->function != b->function) {
     165                 :            :         /* Bring functions to the front based on the fraction of table rows
     166                 :            :          * that they are (heuristically) expected to leave in the query
     167                 :            :          * results.  Note that "enum ovsdb_function" is intentionally ordered
     168                 :            :          * to make this trivial. */
     169         [ +  + ]:        102 :         return a->function < b->function ? -1 : 1;
     170         [ +  + ]:        237 :     } else if (a->column->index != b->column->index) {
     171         [ +  - ]:          1 :         if (a->column->index < OVSDB_N_STD_COLUMNS
     172         [ +  - ]:          1 :             || b->column->index < OVSDB_N_STD_COLUMNS) {
     173                 :            :             /* Bring the standard columns and in particular the UUID column
     174                 :            :              * (since OVSDB_COL_UUID has value 0) to the front.  We have an
     175                 :            :              * index on the UUID column, so that makes our queries cheaper. */
     176         [ -  + ]:          1 :             return a->column->index < b->column->index ? -1 : 1;
     177                 :            :         } else {
     178                 :            :             /* Order clauses predictably to make testing easier. */
     179                 :          0 :             return strcmp(a->column->name, b->column->name);
     180                 :            :         }
     181                 :            :     } else {
     182                 :        236 :         return 0;
     183                 :            :     }
     184                 :            : }
     185                 :            : 
     186                 :            : static int
     187                 :        339 : compare_clauses_3way_with_data(const void *a_, const void *b_)
     188                 :            : {
     189                 :        339 :     const struct ovsdb_clause *a = a_;
     190                 :        339 :     const struct ovsdb_clause *b = b_;
     191                 :            :     int res;
     192                 :            : 
     193                 :        339 :     res = compare_clauses_3way(a, b);
     194         [ +  + ]:        339 :     return res ? res : ovsdb_datum_compare_3way(&a->arg,
     195                 :            :                                                 &b->arg,
     196                 :        236 :                                                 &a->column->type);
     197                 :            :  }
     198                 :            : 
     199                 :            : struct ovsdb_o_column {
     200                 :            :     const struct ovsdb_column *column;
     201                 :            :     struct hmap o_clauses;
     202                 :            : };
     203                 :            : 
     204                 :            : struct ovsdb_o_clause {
     205                 :            :     struct ovsdb_datum *arg;
     206                 :            :     struct hmap_node hmap_node;
     207                 :            : };
     208                 :            : 
     209                 :            : static void
     210                 :      96102 : ovsdb_condition_optimize(struct ovsdb_condition *cnd)
     211                 :            : {
     212                 :            :     size_t i;
     213                 :            :     uint32_t hash;
     214                 :            : 
     215         [ +  + ]:      96102 :     if (!cnd->optimized) {
     216                 :        326 :         return;
     217                 :            :     }
     218                 :            : 
     219         [ +  + ]:     147313 :     for(i = 0; i < cnd->n_clauses; i++) {
     220                 :      51537 :         struct ovsdb_clause *clause = &cnd->clauses[i];
     221                 :            : 
     222         [ +  + ]:      51537 :         if (clause->function != OVSDB_F_EQ) {
     223                 :        527 :             continue;
     224                 :            :         }
     225                 :            : 
     226                 :      51010 :         struct ovsdb_o_clause *o_clause = xzalloc(sizeof *o_clause);
     227                 :      51010 :         struct ovsdb_o_column *o_column =
     228                 :      51010 :             shash_find_data(&cnd->o_columns, clause->column->name);
     229                 :            : 
     230         [ +  + ]:      51010 :         if (!o_column) {
     231                 :      50939 :             o_column = xzalloc(sizeof *o_column);
     232                 :      50939 :             o_column->column = clause->column;
     233                 :      50939 :             hmap_init(&o_column->o_clauses);
     234                 :      50939 :             shash_add(&cnd->o_columns, clause->column->name, o_column);
     235                 :            :         }
     236                 :      51010 :         o_clause->arg = &clause->arg;
     237                 :      51010 :         hash = ovsdb_datum_hash(&clause->arg, &clause->column->type, 0);
     238                 :      51010 :         hmap_insert(&o_column->o_clauses, &o_clause->hmap_node, hash);
     239                 :            :     }
     240                 :            : }
     241                 :            : 
     242                 :            : static void
     243                 :     140114 : ovsdb_condition_optimize_destroy(struct ovsdb_condition *cnd)
     244                 :            : {
     245                 :            :      struct shash_node *node, *next;
     246                 :            : 
     247 [ +  + ][ -  + ]:     191053 :      SHASH_FOR_EACH_SAFE (node, next, &cnd->o_columns) {
                 [ +  + ]
     248                 :      50939 :          struct ovsdb_o_column *o_column = node->data;
     249                 :            :          struct ovsdb_o_clause *c, *c_next;
     250                 :            : 
     251 [ +  + ][ -  + ]:     101949 :          HMAP_FOR_EACH_SAFE(c, c_next, hmap_node, &o_column->o_clauses) {
                 [ +  + ]
     252                 :      51010 :              hmap_remove(&o_column->o_clauses, &c->hmap_node);
     253                 :      51010 :              free(c);
     254                 :            :          }
     255                 :      50939 :          hmap_destroy(&o_column->o_clauses);
     256                 :      50939 :          shash_delete(&cnd->o_columns, node);
     257                 :      50939 :          free(o_column);
     258                 :            :      }
     259                 :     140114 :      shash_destroy(&cnd->o_columns);
     260                 :     140114 : }
     261                 :            : 
     262                 :            : struct ovsdb_error *
     263                 :      51848 : ovsdb_condition_from_json(const struct ovsdb_table_schema *ts,
     264                 :            :                           const struct json *json,
     265                 :            :                           struct ovsdb_symbol_table *symtab,
     266                 :            :                           struct ovsdb_condition *cnd)
     267                 :            : {
     268                 :      51848 :     const struct json_array *array = json_array(json);
     269                 :            :     size_t i;
     270                 :            : 
     271                 :      51848 :     ovsdb_condition_init(cnd);
     272                 :      51848 :     cnd->clauses = xmalloc(array->n * sizeof *cnd->clauses);
     273                 :            : 
     274         [ +  + ]:     103251 :     for (i = 0; i < array->n; i++) {
     275                 :            :         struct ovsdb_error *error;
     276                 :      51415 :         error = ovsdb_clause_from_json(ts, array->elems[i], symtab,
     277                 :      51415 :                                        &cnd->clauses[i]);
     278         [ +  + ]:      51415 :         if (error) {
     279                 :         12 :             ovsdb_condition_destroy(cnd);
     280                 :         12 :             cnd->clauses = NULL;
     281                 :         12 :             cnd->n_clauses = 0;
     282                 :         12 :             return error;
     283                 :            :         }
     284                 :      51403 :         cnd->n_clauses++;
     285         [ +  + ]:      51403 :         if (cnd->clauses[i].function > OVSDB_F_EQ) {
     286                 :        342 :             cnd->optimized = false;
     287                 :            :         }
     288                 :            :     }
     289                 :            : 
     290                 :            :     /* A real database would have a query optimizer here. */
     291                 :      51836 :     qsort(cnd->clauses, cnd->n_clauses, sizeof *cnd->clauses,
     292                 :            :           compare_clauses_3way_with_data);
     293                 :            : 
     294                 :      51836 :     ovsdb_condition_optimize(cnd);
     295                 :            : 
     296                 :      51836 :     return NULL;
     297                 :            : }
     298                 :            : 
     299                 :            : static struct json *
     300                 :         59 : ovsdb_clause_to_json(const struct ovsdb_clause *clause)
     301                 :            : {
     302 [ +  + ][ +  + ]:         59 :     if (clause->function != OVSDB_F_TRUE &&
     303                 :         58 :         clause->function != OVSDB_F_FALSE) {
     304                 :         57 :         return json_array_create_3(
     305                 :         57 :                 json_string_create(clause->column->name),
     306                 :            :                 json_string_create(ovsdb_function_to_string(clause->function)),
     307                 :         57 :                 ovsdb_datum_to_json(&clause->arg, &clause->column->type));
     308                 :            :     }
     309                 :            : 
     310                 :          2 :     return json_boolean_create(clause->function == OVSDB_F_TRUE);
     311                 :            : }
     312                 :            : 
     313                 :            : struct json *
     314                 :         52 : ovsdb_condition_to_json(const struct ovsdb_condition *cnd)
     315                 :            : {
     316                 :            :     struct json **clauses;
     317                 :            :     size_t i;
     318                 :            : 
     319                 :         52 :     clauses = xmalloc(cnd->n_clauses * sizeof *clauses);
     320         [ +  + ]:        111 :     for (i = 0; i < cnd->n_clauses; i++) {
     321                 :         59 :         clauses[i] = ovsdb_clause_to_json(&cnd->clauses[i]);
     322                 :            :     }
     323                 :         52 :     return json_array_create(clauses, cnd->n_clauses);
     324                 :            : }
     325                 :            : 
     326                 :            : static bool
     327                 :      53634 : ovsdb_clause_evaluate(const struct ovsdb_datum *fields,
     328                 :            :                       const struct ovsdb_clause *c,
     329                 :            :                       unsigned int index_map[])
     330                 :            : {
     331         [ -  + ]:      53634 :     const struct ovsdb_datum *field = &fields[index_map ?
     332                 :          0 :                                               index_map[c->column->index] :
     333                 :      53634 :                                               c->column->index];
     334                 :      53634 :     const struct ovsdb_datum *arg = &c->arg;
     335                 :      53634 :     const struct ovsdb_type *type = &c->column->type;
     336                 :            : 
     337 [ +  - ][ -  + ]:      53634 :     if (c->function == OVSDB_F_TRUE ||
     338                 :      53634 :         c->function == OVSDB_F_FALSE) {
     339                 :          0 :         return c->function == OVSDB_F_TRUE;
     340                 :            :     }
     341 [ +  + ][ +  + ]:      53634 :     if (ovsdb_type_is_optional_scalar(type) && field->n == 0) {
     342   [ +  +  -  - ]:         29 :         switch (c->function) {
     343                 :            :             case OVSDB_F_LT:
     344                 :            :             case OVSDB_F_LE:
     345                 :            :             case OVSDB_F_EQ:
     346                 :            :             case OVSDB_F_GE:
     347                 :            :             case OVSDB_F_GT:
     348                 :            :             case OVSDB_F_INCLUDES:
     349                 :         17 :                 return false;
     350                 :            :             case OVSDB_F_NE:
     351                 :            :             case OVSDB_F_EXCLUDES:
     352                 :         12 :                 return true;
     353                 :            :             case OVSDB_F_TRUE:
     354                 :            :             case OVSDB_F_FALSE:
     355                 :          0 :                 OVS_NOT_REACHED();
     356                 :            :         }
     357         [ +  + ]:      53605 :     } else if (ovsdb_type_is_scalar(type)
     358         [ +  + ]:       2116 :                || ovsdb_type_is_optional_scalar(type)) {
     359                 :      51576 :         int cmp = ovsdb_atom_compare_3way(&field->keys[0], &arg->keys[0],
     360                 :            :                                           type->key.type);
     361   [ +  +  +  +  :      51576 :         switch (c->function) {
             +  +  -  - ]
     362                 :            :         case OVSDB_F_LT:
     363                 :         96 :             return cmp < 0;
     364                 :            :         case OVSDB_F_LE:
     365                 :         42 :             return cmp <= 0;
     366                 :            :         case OVSDB_F_EQ:
     367                 :            :         case OVSDB_F_INCLUDES:
     368                 :      51122 :             return cmp == 0;
     369                 :            :         case OVSDB_F_NE:
     370                 :            :         case OVSDB_F_EXCLUDES:
     371                 :        228 :             return cmp != 0;
     372                 :            :         case OVSDB_F_GE:
     373                 :         42 :             return cmp >= 0;
     374                 :            :         case OVSDB_F_GT:
     375                 :         46 :             return cmp > 0;
     376                 :            :         case OVSDB_F_TRUE:
     377                 :            :         case OVSDB_F_FALSE:
     378                 :          0 :             OVS_NOT_REACHED();
     379                 :            :         }
     380                 :            :     } else {
     381   [ +  +  +  +  :       2029 :         switch (c->function) {
                   -  - ]
     382                 :            :         case OVSDB_F_EQ:
     383                 :        496 :             return ovsdb_datum_equals(field, arg, type);
     384                 :            :         case OVSDB_F_NE:
     385                 :        496 :             return !ovsdb_datum_equals(field, arg, type);
     386                 :            :         case OVSDB_F_INCLUDES:
     387                 :        541 :             return ovsdb_datum_includes_all(arg, field, type);
     388                 :            :         case OVSDB_F_EXCLUDES:
     389                 :        496 :             return ovsdb_datum_excludes_all(arg, field, type);
     390                 :            :         case OVSDB_F_LT:
     391                 :            :         case OVSDB_F_LE:
     392                 :            :         case OVSDB_F_GE:
     393                 :            :         case OVSDB_F_GT:
     394                 :            :         case OVSDB_F_TRUE:
     395                 :            :         case OVSDB_F_FALSE:
     396                 :          0 :             OVS_NOT_REACHED();
     397                 :            :         }
     398                 :            :     }
     399                 :            : 
     400                 :          0 :     OVS_NOT_REACHED();
     401                 :            : }
     402                 :            : 
     403                 :            : static void
     404                 :        478 : ovsdb_clause_clone(struct ovsdb_clause *new, struct ovsdb_clause *old)
     405                 :            : {
     406                 :        478 :     new->function = old->function;
     407                 :        478 :     new->column = old->column;
     408                 :        478 :     ovsdb_datum_clone(&new->arg,
     409                 :        478 :                       &old->arg,
     410                 :        478 :                       &old->column->type);
     411                 :        478 : }
     412                 :            : 
     413                 :            : bool
     414                 :      54460 : ovsdb_condition_match_every_clause(const struct ovsdb_row *row,
     415                 :            :                                    const struct ovsdb_condition *cnd)
     416                 :            : {
     417                 :            :     size_t i;
     418                 :            : 
     419         [ +  + ]:     106360 :     for (i = 0; i < cnd->n_clauses; i++) {
     420         [ +  + ]:      53634 :         if (!ovsdb_clause_evaluate(row->fields, &cnd->clauses[i], NULL)) {
     421                 :       1734 :             return false;
     422                 :            :         }
     423                 :            :     }
     424                 :            : 
     425                 :      52726 :     return true;
     426                 :            : }
     427                 :            : 
     428                 :            : static bool
     429                 :        335 : ovsdb_condition_match_any_clause_optimized(const struct ovsdb_datum *row_datum,
     430                 :            :                                            const struct ovsdb_condition *cnd,
     431                 :            :                                            unsigned int index_map[])
     432                 :            : {
     433         [ +  + ]:        335 :     if (ovsdb_condition_is_true(cnd)) {
     434                 :         15 :         return true;
     435                 :            :     }
     436                 :            : 
     437                 :            :     struct shash_node *node;
     438 [ +  + ][ -  + ]:        358 :     SHASH_FOR_EACH (node, &cnd->o_columns) {
     439                 :        134 :         struct ovsdb_o_column *o_column = node->data;
     440                 :        134 :         const struct ovsdb_column *column = o_column->column;
     441         [ +  + ]:        134 :         const struct ovsdb_datum *arg = &row_datum[index_map ?
     442                 :         29 :                                                    index_map[column->index] :
     443                 :        105 :                                                    column->index];
     444                 :        134 :         uint32_t hash = ovsdb_datum_hash(arg, &column->type, 0);
     445                 :            :         struct ovsdb_o_clause *o_clause;
     446                 :            : 
     447 [ +  + ][ -  + ]:        134 :         HMAP_FOR_EACH_WITH_HASH(o_clause, hmap_node, hash, &o_column->o_clauses) {
     448         [ +  - ]:         96 :             if (ovsdb_datum_equals(arg, o_clause->arg, &column->type)) {
     449                 :         96 :                 return true;
     450                 :            :             }
     451                 :            :         }
     452                 :            :     }
     453                 :        224 :     return false;
     454                 :            : }
     455                 :            : 
     456                 :            : /* Returns true if condition evaluation of one of the clauses is
     457                 :            :  * true. index_map[] is an optional array that if exists indicates a mapping
     458                 :            :  * between indexing row_datum to the indexes in ovsdb_column */
     459                 :            : bool
     460                 :        335 : ovsdb_condition_match_any_clause(const struct ovsdb_datum *row_datum,
     461                 :            :                                  const struct ovsdb_condition *cnd,
     462                 :            :                                  unsigned int index_map[])
     463                 :            : {
     464                 :            :     size_t i;
     465                 :            : 
     466         [ +  - ]:        335 :     if (cnd->optimized) {
     467                 :        335 :         return ovsdb_condition_match_any_clause_optimized(row_datum, cnd,
     468                 :            :                                                           index_map);
     469                 :            :     }
     470                 :            : 
     471         [ #  # ]:          0 :     for (i = 0; i < cnd->n_clauses; i++) {
     472         [ #  # ]:          0 :         if (ovsdb_clause_evaluate(row_datum, &cnd->clauses[i], index_map)) {
     473                 :          0 :             return true;
     474                 :            :         }
     475                 :            :     }
     476                 :            : 
     477                 :          0 :     return false;
     478                 :            : }
     479                 :            : 
     480                 :            : void
     481                 :     140114 : ovsdb_condition_destroy(struct ovsdb_condition *cnd)
     482                 :            : {
     483                 :            :     size_t i;
     484                 :            : 
     485         [ +  + ]:     191995 :     for (i = 0; i < cnd->n_clauses; i++) {
     486                 :      51881 :         ovsdb_clause_free(&cnd->clauses[i]);
     487                 :            :     }
     488                 :     140114 :     free(cnd->clauses);
     489                 :     140114 :     cnd->n_clauses = 0;
     490                 :            : 
     491                 :     140114 :     ovsdb_condition_optimize_destroy(cnd);
     492                 :     140114 : }
     493                 :            : 
     494                 :            : void
     495                 :     184178 : ovsdb_condition_init(struct ovsdb_condition *cnd)
     496                 :            : {
     497                 :     184178 :     cnd->clauses = NULL;
     498                 :     184178 :     cnd->n_clauses = 0;
     499                 :     184178 :     cnd->optimized = true;
     500                 :     184178 :     shash_init(&cnd->o_columns);
     501                 :     184178 : }
     502                 :            : 
     503                 :            : bool
     504                 :     164523 : ovsdb_condition_empty(const struct ovsdb_condition *cnd)
     505                 :            : {
     506                 :     164523 :     return cnd->n_clauses == 0;
     507                 :            : }
     508                 :            : 
     509                 :            : int
     510                 :        860 : ovsdb_condition_cmp_3way(const struct ovsdb_condition *a,
     511                 :            :                          const struct ovsdb_condition *b)
     512                 :            : {
     513                 :            :     size_t i;
     514                 :            :     int res;
     515                 :            : 
     516         [ +  + ]:        860 :     if (a->n_clauses != b->n_clauses) {
     517         [ +  + ]:        167 :         return a->n_clauses < b->n_clauses ? -1 : 1;
     518                 :            :     }
     519                 :            : 
     520                 :            :     /* We assume clauses are sorted */
     521         [ +  + ]:        890 :     for (i = 0; i < a->n_clauses; i++) {
     522                 :        202 :         res = (compare_clauses_3way_with_data(&a->clauses[i], &b->clauses[i]));
     523         [ +  + ]:        202 :         if (res != 0) {
     524                 :          5 :             return res;
     525                 :            :         }
     526                 :            :     }
     527                 :            : 
     528                 :        688 :     return 0;
     529                 :            : }
     530                 :            : 
     531                 :            : void
     532                 :      44266 : ovsdb_condition_clone(struct ovsdb_condition *to,
     533                 :            :                       const struct ovsdb_condition *from)
     534                 :            : {
     535                 :            :     size_t i;
     536                 :            : 
     537                 :      44266 :     ovsdb_condition_init(to);
     538                 :            : 
     539                 :      44266 :     to->clauses = xzalloc(from->n_clauses * sizeof *to->clauses);
     540                 :            : 
     541         [ +  + ]:      44744 :     for (i = 0; i < from->n_clauses; i++) {
     542                 :        478 :         ovsdb_clause_clone(&to->clauses[i], &from->clauses[i]);
     543                 :            :     }
     544                 :      44266 :     to->n_clauses = from->n_clauses;
     545                 :      44266 :     to->optimized = from->optimized;
     546         [ +  - ]:      44266 :     if (to->optimized) {
     547                 :      44266 :         ovsdb_condition_optimize(to);
     548                 :            :     }
     549                 :      44266 : }
     550                 :            : 
     551                 :            : /* Return true if ovsdb_condition_match_any_clause() will return true on
     552                 :            :  * any row */
     553                 :            : bool
     554                 :      44537 : ovsdb_condition_is_true(const struct ovsdb_condition *cond)
     555                 :            : {
     556         [ +  - ]:      45109 :     return (!cond->n_clauses ||
     557 [ +  + ][ +  + ]:      45328 :        (cond->n_clauses >= 1 && (cond->clauses[0].function == OVSDB_F_TRUE)) ||
                 [ +  + ]
     558         [ +  + ]:        219 :        (cond->n_clauses >= 2 && (cond->clauses[1].function == OVSDB_F_TRUE)));
     559                 :            : }
     560                 :            : 
     561                 :            : bool
     562                 :          0 : ovsdb_condition_is_false(const struct ovsdb_condition *cond)
     563                 :            : {
     564 [ #  # ][ #  # ]:          0 :     return ((cond->n_clauses == 1) &&
     565                 :          0 :             (cond->clauses[0].function == OVSDB_F_FALSE));
     566                 :            :  }
     567                 :            : 
     568                 :            : const struct ovsdb_column **
     569                 :      44181 : ovsdb_condition_get_columns(const struct ovsdb_condition *cond,
     570                 :            :                             size_t *n_columns)
     571                 :            : {
     572                 :            :     const struct ovsdb_column **columns;
     573                 :            :     size_t i;
     574                 :            : 
     575                 :      44181 :     columns = xmalloc(cond->n_clauses * sizeof *columns);
     576         [ +  + ]:      44492 :     for (i = 0; i < cond->n_clauses; i++) {
     577                 :        311 :         columns[i] = cond->clauses[i].column;
     578                 :            :     }
     579                 :      44181 :     *n_columns = i;
     580                 :            : 
     581                 :      44181 :     return columns;
     582                 :            : }

Generated by: LCOV version 1.12