LCOV - code coverage report
Current view: top level - ovsdb - row.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 165 173 95.4 %
Date: 2016-09-14 01:02:56 Functions: 26 27 96.3 %
Branches: 64 84 76.2 %

           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 "row.h"
      19                 :            : 
      20                 :            : #include <stddef.h>
      21                 :            : 
      22                 :            : #include "openvswitch/dynamic-string.h"
      23                 :            : #include "openvswitch/json.h"
      24                 :            : #include "ovsdb-error.h"
      25                 :            : #include "openvswitch/shash.h"
      26                 :            : #include "sort.h"
      27                 :            : #include "table.h"
      28                 :            : #include "util.h"
      29                 :            : 
      30                 :            : static struct ovsdb_row *
      31                 :     110333 : allocate_row(const struct ovsdb_table *table)
      32                 :            : {
      33                 :     110333 :     size_t n_fields = shash_count(&table->schema->columns);
      34                 :     110333 :     size_t n_indexes = table->schema->n_indexes;
      35                 :     110333 :     size_t row_size = (offsetof(struct ovsdb_row, fields)
      36                 :     110333 :                        + sizeof(struct ovsdb_datum) * n_fields
      37                 :     110333 :                        + sizeof(struct hmap_node) * n_indexes);
      38                 :     110333 :     struct ovsdb_row *row = xmalloc(row_size);
      39                 :     110333 :     row->table = CONST_CAST(struct ovsdb_table *, table);
      40                 :     110333 :     row->txn_row = NULL;
      41                 :     110333 :     ovs_list_init(&row->src_refs);
      42                 :     110333 :     ovs_list_init(&row->dst_refs);
      43                 :     110333 :     row->n_refs = 0;
      44                 :     110333 :     return row;
      45                 :            : }
      46                 :            : 
      47                 :            : struct ovsdb_row *
      48                 :      64076 : ovsdb_row_create(const struct ovsdb_table *table)
      49                 :            : {
      50                 :            :     struct shash_node *node;
      51                 :            :     struct ovsdb_row *row;
      52                 :            : 
      53                 :      64076 :     row = allocate_row(table);
      54 [ +  + ][ -  + ]:    1469366 :     SHASH_FOR_EACH (node, &table->schema->columns) {
      55                 :    1405290 :         const struct ovsdb_column *column = node->data;
      56                 :    1405290 :         ovsdb_datum_init_default(&row->fields[column->index], &column->type);
      57                 :            :     }
      58                 :      64076 :     return row;
      59                 :            : }
      60                 :            : 
      61                 :            : struct ovsdb_row *
      62                 :      46257 : ovsdb_row_clone(const struct ovsdb_row *old)
      63                 :            : {
      64                 :      46257 :     const struct ovsdb_table *table = old->table;
      65                 :            :     const struct shash_node *node;
      66                 :            :     struct ovsdb_row *new;
      67                 :            : 
      68                 :      46257 :     new = allocate_row(table);
      69 [ +  + ][ -  + ]:    1102056 :     SHASH_FOR_EACH (node, &table->schema->columns) {
      70                 :    1055799 :         const struct ovsdb_column *column = node->data;
      71                 :    1055799 :         ovsdb_datum_clone(&new->fields[column->index],
      72                 :    1055799 :                           &old->fields[column->index],
      73                 :            :                           &column->type);
      74                 :            :     }
      75                 :      46257 :     return new;
      76                 :            : }
      77                 :            : 
      78                 :            : /* The caller is responsible for ensuring that 'row' has been removed from its
      79                 :            :  * table and that it is not participating in a transaction. */
      80                 :            : void
      81                 :     130561 : ovsdb_row_destroy(struct ovsdb_row *row)
      82                 :            : {
      83         [ +  + ]:     130561 :     if (row) {
      84                 :     110331 :         const struct ovsdb_table *table = row->table;
      85                 :            :         struct ovsdb_weak_ref *weak, *next;
      86                 :            :         const struct shash_node *node;
      87                 :            : 
      88 [ +  + ][ +  + ]:     110662 :         LIST_FOR_EACH_SAFE (weak, next, dst_node, &row->dst_refs) {
      89                 :        331 :             ovs_list_remove(&weak->src_node);
      90                 :        331 :             ovs_list_remove(&weak->dst_node);
      91                 :        331 :             free(weak);
      92                 :            :         }
      93                 :            : 
      94 [ +  + ][ +  + ]:     110434 :         LIST_FOR_EACH_SAFE (weak, next, src_node, &row->src_refs) {
      95                 :        103 :             ovs_list_remove(&weak->src_node);
      96                 :        103 :             ovs_list_remove(&weak->dst_node);
      97                 :        103 :             free(weak);
      98                 :            :         }
      99                 :            : 
     100 [ +  + ][ -  + ]:    2571388 :         SHASH_FOR_EACH (node, &table->schema->columns) {
     101                 :    2461057 :             const struct ovsdb_column *column = node->data;
     102                 :    2461057 :             ovsdb_datum_destroy(&row->fields[column->index], &column->type);
     103                 :            :         }
     104                 :     110331 :         free(row);
     105                 :            :     }
     106                 :     130561 : }
     107                 :            : 
     108                 :            : uint32_t
     109                 :     133472 : ovsdb_row_hash_columns(const struct ovsdb_row *row,
     110                 :            :                        const struct ovsdb_column_set *columns,
     111                 :            :                        uint32_t basis)
     112                 :            : {
     113                 :            :     size_t i;
     114                 :            : 
     115         [ +  + ]:     278527 :     for (i = 0; i < columns->n_columns; i++) {
     116                 :     145055 :         const struct ovsdb_column *column = columns->columns[i];
     117                 :     145055 :         basis = ovsdb_datum_hash(&row->fields[column->index], &column->type,
     118                 :            :                                  basis);
     119                 :            :     }
     120                 :            : 
     121                 :     133472 :     return basis;
     122                 :            : }
     123                 :            : 
     124                 :            : int
     125                 :        522 : ovsdb_row_compare_columns_3way(const struct ovsdb_row *a,
     126                 :            :                                const struct ovsdb_row *b,
     127                 :            :                                const struct ovsdb_column_set *columns)
     128                 :            : {
     129                 :            :     size_t i;
     130                 :            : 
     131         [ +  - ]:        564 :     for (i = 0; i < columns->n_columns; i++) {
     132                 :        564 :         const struct ovsdb_column *column = columns->columns[i];
     133                 :        564 :         int cmp = ovsdb_datum_compare_3way(&a->fields[column->index],
     134                 :        564 :                                            &b->fields[column->index],
     135                 :            :                                            &column->type);
     136         [ +  + ]:        564 :         if (cmp) {
     137                 :        522 :             return cmp;
     138                 :            :         }
     139                 :            :     }
     140                 :            : 
     141                 :          0 :     return 0;
     142                 :            : }
     143                 :            : 
     144                 :            : bool
     145                 :      84733 : ovsdb_row_equal_columns(const struct ovsdb_row *a,
     146                 :            :                         const struct ovsdb_row *b,
     147                 :            :                         const struct ovsdb_column_set *columns)
     148                 :            : {
     149                 :            :     size_t i;
     150                 :            : 
     151         [ +  + ]:     166842 :     for (i = 0; i < columns->n_columns; i++) {
     152                 :      99898 :         const struct ovsdb_column *column = columns->columns[i];
     153         [ +  + ]:      99898 :         if (!ovsdb_datum_equals(&a->fields[column->index],
     154                 :      99898 :                                 &b->fields[column->index],
     155                 :            :                                 &column->type)) {
     156                 :      17789 :             return false;
     157                 :            :         }
     158                 :            :     }
     159                 :            : 
     160                 :      66944 :     return true;
     161                 :            : }
     162                 :            : 
     163                 :            : void
     164                 :      16251 : ovsdb_row_update_columns(struct ovsdb_row *dst,
     165                 :            :                          const struct ovsdb_row *src,
     166                 :            :                          const struct ovsdb_column_set *columns)
     167                 :            : {
     168                 :            :     size_t i;
     169                 :            : 
     170         [ +  + ]:      57114 :     for (i = 0; i < columns->n_columns; i++) {
     171                 :      40863 :         const struct ovsdb_column *column = columns->columns[i];
     172                 :      40863 :         ovsdb_datum_destroy(&dst->fields[column->index], &column->type);
     173                 :      40863 :         ovsdb_datum_clone(&dst->fields[column->index],
     174                 :      40863 :                           &src->fields[column->index],
     175                 :            :                           &column->type);
     176                 :            :     }
     177                 :      16251 : }
     178                 :            : 
     179                 :            : /* Appends the string form of the value in 'row' of each of the columns in
     180                 :            :  * 'columns' to 'out', e.g. "1, \"xyz\", and [1, 2, 3]". */
     181                 :            : void
     182                 :         35 : ovsdb_row_columns_to_string(const struct ovsdb_row *row,
     183                 :            :                             const struct ovsdb_column_set *columns,
     184                 :            :                             struct ds *out)
     185                 :            : {
     186                 :            :     size_t i;
     187                 :            : 
     188         [ +  + ]:         70 :     for (i = 0; i < columns->n_columns; i++) {
     189                 :         35 :         const struct ovsdb_column *column = columns->columns[i];
     190                 :            : 
     191                 :         35 :         ds_put_cstr(out, english_list_delimiter(i, columns->n_columns));
     192                 :         35 :         ovsdb_datum_to_string(&row->fields[column->index], &column->type, out);
     193                 :            :     }
     194                 :         35 : }
     195                 :            : 
     196                 :            : struct ovsdb_error *
     197                 :      63314 : ovsdb_row_from_json(struct ovsdb_row *row, const struct json *json,
     198                 :            :                     struct ovsdb_symbol_table *symtab,
     199                 :            :                     struct ovsdb_column_set *included)
     200                 :            : {
     201                 :      63314 :     struct ovsdb_table_schema *schema = row->table->schema;
     202                 :            :     struct ovsdb_error *error;
     203                 :            :     struct shash_node *node;
     204                 :            : 
     205         [ -  + ]:      63314 :     if (json->type != JSON_OBJECT) {
     206                 :          0 :         return ovsdb_syntax_error(json, NULL, "row must be JSON object");
     207                 :            :     }
     208                 :            : 
     209 [ +  + ][ -  + ]:     200256 :     SHASH_FOR_EACH (node, json_object(json)) {
     210                 :     136957 :         const char *column_name = node->name;
     211                 :            :         const struct ovsdb_column *column;
     212                 :            :         struct ovsdb_datum datum;
     213                 :            : 
     214                 :     136957 :         column = ovsdb_table_schema_get_column(schema, column_name);
     215         [ -  + ]:     136957 :         if (!column) {
     216                 :         15 :             return ovsdb_syntax_error(json, "unknown column",
     217                 :            :                                       "No column %s in table %s.",
     218                 :            :                                       column_name, schema->name);
     219                 :            :         }
     220                 :            : 
     221                 :     136957 :         error = ovsdb_datum_from_json(&datum, &column->type, node->data,
     222                 :            :                                       symtab);
     223         [ +  + ]:     136957 :         if (error) {
     224                 :         15 :             return error;
     225                 :            :         }
     226                 :     136942 :         ovsdb_datum_swap(&row->fields[column->index], &datum);
     227                 :     136942 :         ovsdb_datum_destroy(&datum, &column->type);
     228         [ +  + ]:     136942 :         if (included) {
     229                 :      50982 :             ovsdb_column_set_add(included, column);
     230                 :            :         }
     231                 :            :     }
     232                 :            : 
     233                 :      63299 :     return NULL;
     234                 :            : }
     235                 :            : 
     236                 :            : static void
     237                 :       3714 : put_json_column(struct json *object, const struct ovsdb_row *row,
     238                 :            :                 const struct ovsdb_column *column)
     239                 :            : {
     240                 :       3714 :     json_object_put(object, column->name,
     241                 :       3714 :                     ovsdb_datum_to_json(&row->fields[column->index],
     242                 :            :                                         &column->type));
     243                 :       3714 : }
     244                 :            : 
     245                 :            : struct json *
     246                 :       2749 : ovsdb_row_to_json(const struct ovsdb_row *row,
     247                 :            :                   const struct ovsdb_column_set *columns)
     248                 :            : {
     249                 :            :     struct json *json;
     250                 :            :     size_t i;
     251                 :            : 
     252                 :       2749 :     json = json_object_create();
     253         [ +  + ]:       6463 :     for (i = 0; i < columns->n_columns; i++) {
     254                 :       3714 :         put_json_column(json, row, columns->columns[i]);
     255                 :            :     }
     256                 :       2749 :     return json;
     257                 :            : }
     258                 :            : 
     259                 :            : void
     260                 :         56 : ovsdb_row_set_init(struct ovsdb_row_set *set)
     261                 :            : {
     262                 :         56 :     set->rows = NULL;
     263                 :         56 :     set->n_rows = set->allocated_rows = 0;
     264                 :         56 : }
     265                 :            : 
     266                 :            : void
     267                 :       2543 : ovsdb_row_set_destroy(struct ovsdb_row_set *set)
     268                 :            : {
     269                 :       2543 :     free(set->rows);
     270                 :       2543 : }
     271                 :            : 
     272                 :            : void
     273                 :       2674 : ovsdb_row_set_add_row(struct ovsdb_row_set *set, const struct ovsdb_row *row)
     274                 :            : {
     275         [ +  + ]:       2674 :     if (set->n_rows >= set->allocated_rows) {
     276                 :       2632 :         set->rows = x2nrealloc(set->rows, &set->allocated_rows,
     277                 :            :                                sizeof *set->rows);
     278                 :            :     }
     279                 :       2674 :     set->rows[set->n_rows++] = row;
     280                 :       2674 : }
     281                 :            : 
     282                 :            : struct json *
     283                 :       2487 : ovsdb_row_set_to_json(const struct ovsdb_row_set *rows,
     284                 :            :                       const struct ovsdb_column_set *columns)
     285                 :            : {
     286                 :            :     struct json **json_rows;
     287                 :            :     size_t i;
     288                 :            : 
     289                 :       2487 :     json_rows = xmalloc(rows->n_rows * sizeof *json_rows);
     290         [ +  + ]:       5058 :     for (i = 0; i < rows->n_rows; i++) {
     291                 :       2571 :         json_rows[i] = ovsdb_row_to_json(rows->rows[i], columns);
     292                 :            :     }
     293                 :       2487 :     return json_array_create(json_rows, rows->n_rows);
     294                 :            : }
     295                 :            : 
     296                 :            : struct ovsdb_row_set_sort_cbdata {
     297                 :            :     struct ovsdb_row_set *set;
     298                 :            :     const struct ovsdb_column_set *columns;
     299                 :            : };
     300                 :            : 
     301                 :            : static int
     302                 :        501 : ovsdb_row_set_sort_compare_cb(size_t a, size_t b, void *cbdata_)
     303                 :            : {
     304                 :        501 :     struct ovsdb_row_set_sort_cbdata *cbdata = cbdata_;
     305                 :        501 :     return ovsdb_row_compare_columns_3way(cbdata->set->rows[a],
     306                 :        501 :                                           cbdata->set->rows[b],
     307                 :            :                                           cbdata->columns);
     308                 :            : }
     309                 :            : 
     310                 :            : static void
     311                 :        763 : ovsdb_row_set_sort_swap_cb(size_t a, size_t b, void *cbdata_)
     312                 :            : {
     313                 :        763 :     struct ovsdb_row_set_sort_cbdata *cbdata = cbdata_;
     314                 :        763 :     const struct ovsdb_row *tmp = cbdata->set->rows[a];
     315                 :        763 :     cbdata->set->rows[a] = cbdata->set->rows[b];
     316                 :        763 :     cbdata->set->rows[b] = tmp;
     317                 :        763 : }
     318                 :            : 
     319                 :            : void
     320                 :       2487 : ovsdb_row_set_sort(struct ovsdb_row_set *set,
     321                 :            :                    const struct ovsdb_column_set *columns)
     322                 :            : {
     323 [ +  - ][ +  - ]:       2487 :     if (columns && columns->n_columns && set->n_rows > 1) {
                 [ +  + ]
     324                 :            :         struct ovsdb_row_set_sort_cbdata cbdata;
     325                 :        121 :         cbdata.set = set;
     326                 :        121 :         cbdata.columns = columns;
     327                 :        121 :         sort(set->n_rows,
     328                 :            :              ovsdb_row_set_sort_compare_cb,
     329                 :            :              ovsdb_row_set_sort_swap_cb,
     330                 :            :              &cbdata);
     331                 :            :     }
     332                 :       2487 : }
     333                 :            : 
     334                 :            : void
     335                 :      56476 : ovsdb_row_hash_init(struct ovsdb_row_hash *rh,
     336                 :            :                     const struct ovsdb_column_set *columns)
     337                 :            : {
     338                 :      56476 :     hmap_init(&rh->rows);
     339                 :      56476 :     ovsdb_column_set_clone(&rh->columns, columns);
     340                 :      56476 : }
     341                 :            : 
     342                 :            : void
     343                 :      56476 : ovsdb_row_hash_destroy(struct ovsdb_row_hash *rh, bool destroy_rows)
     344                 :            : {
     345                 :            :     struct ovsdb_row_hash_node *node;
     346                 :            : 
     347 [ +  + ][ -  + ]:     113039 :     HMAP_FOR_EACH_POP (node, hmap_node, &rh->rows) {
                 [ +  + ]
     348         [ +  + ]:      56563 :         if (destroy_rows) {
     349                 :      27180 :             ovsdb_row_destroy(CONST_CAST(struct ovsdb_row *, node->row));
     350                 :            :         }
     351                 :      56563 :         free(node);
     352                 :            :     }
     353                 :      56476 :     hmap_destroy(&rh->rows);
     354                 :      56476 :     ovsdb_column_set_destroy(&rh->columns);
     355                 :      56476 : }
     356                 :            : 
     357                 :            : size_t
     358                 :      54192 : ovsdb_row_hash_count(const struct ovsdb_row_hash *rh)
     359                 :            : {
     360                 :      54192 :     return hmap_count(&rh->rows);
     361                 :            : }
     362                 :            : 
     363                 :            : bool
     364                 :      27164 : ovsdb_row_hash_contains(const struct ovsdb_row_hash *rh,
     365                 :            :                         const struct ovsdb_row *row)
     366                 :            : {
     367                 :      27164 :     size_t hash = ovsdb_row_hash_columns(row, &rh->columns, 0);
     368                 :      27164 :     return ovsdb_row_hash_contains__(rh, row, hash);
     369                 :            : }
     370                 :            : 
     371                 :            : /* Returns true if every row in 'b' has an equal row in 'a'. */
     372                 :            : bool
     373                 :          0 : ovsdb_row_hash_contains_all(const struct ovsdb_row_hash *a,
     374                 :            :                             const struct ovsdb_row_hash *b)
     375                 :            : {
     376                 :            :     struct ovsdb_row_hash_node *node;
     377                 :            : 
     378         [ #  # ]:          0 :     ovs_assert(ovsdb_column_set_equals(&a->columns, &b->columns));
     379 [ #  # ][ #  # ]:          0 :     HMAP_FOR_EACH (node, hmap_node, &b->rows) {
     380         [ #  # ]:          0 :         if (!ovsdb_row_hash_contains__(a, node->row, node->hmap_node.hash)) {
     381                 :          0 :             return false;
     382                 :            :         }
     383                 :            :     }
     384                 :          0 :     return true;
     385                 :            : }
     386                 :            : 
     387                 :            : bool
     388                 :      56590 : ovsdb_row_hash_insert(struct ovsdb_row_hash *rh, const struct ovsdb_row *row)
     389                 :            : {
     390                 :      56590 :     size_t hash = ovsdb_row_hash_columns(row, &rh->columns, 0);
     391                 :      56590 :     return ovsdb_row_hash_insert__(rh, row, hash);
     392                 :            : }
     393                 :            : 
     394                 :            : bool
     395                 :      83754 : ovsdb_row_hash_contains__(const struct ovsdb_row_hash *rh,
     396                 :            :                           const struct ovsdb_row *row, size_t hash)
     397                 :            : {
     398                 :            :     struct ovsdb_row_hash_node *node;
     399 [ +  + ][ -  + ]:      83754 :     HMAP_FOR_EACH_WITH_HASH (node, hmap_node, hash, &rh->rows) {
     400         [ +  - ]:      27166 :         if (ovsdb_row_equal_columns(row, node->row, &rh->columns)) {
     401                 :      27166 :             return true;
     402                 :            :         }
     403                 :            :     }
     404                 :      56588 :     return false;
     405                 :            : }
     406                 :            : 
     407                 :            : bool
     408                 :      56590 : ovsdb_row_hash_insert__(struct ovsdb_row_hash *rh, const struct ovsdb_row *row,
     409                 :            :                         size_t hash)
     410                 :            : {
     411         [ +  + ]:      56590 :     if (!ovsdb_row_hash_contains__(rh, row, hash)) {
     412                 :      56563 :         struct ovsdb_row_hash_node *node = xmalloc(sizeof *node);
     413                 :      56563 :         node->row = row;
     414                 :      56563 :         hmap_insert(&rh->rows, &node->hmap_node, hash);
     415                 :      56563 :         return true;
     416                 :            :     } else {
     417                 :         27 :         return false;
     418                 :            :     }
     419                 :            : }

Generated by: LCOV version 1.12