LCOV - code coverage report
Current view: top level - ovsdb - table.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 147 148 99.3 %
Date: 2016-09-14 01:02:56 Functions: 10 10 100.0 %
Branches: 82 94 87.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 "table.h"
      19                 :            : 
      20                 :            : #include <limits.h>
      21                 :            : 
      22                 :            : #include "openvswitch/json.h"
      23                 :            : #include "column.h"
      24                 :            : #include "ovsdb-error.h"
      25                 :            : #include "ovsdb-parser.h"
      26                 :            : #include "ovsdb-types.h"
      27                 :            : #include "row.h"
      28                 :            : 
      29                 :            : static void
      30                 :     336093 : add_column(struct ovsdb_table_schema *ts, struct ovsdb_column *column)
      31                 :            : {
      32         [ -  + ]:     336093 :     ovs_assert(!shash_find(&ts->columns, column->name));
      33                 :     336093 :     column->index = shash_count(&ts->columns);
      34                 :     336093 :     shash_add(&ts->columns, column->name, column);
      35                 :     336093 : }
      36                 :            : 
      37                 :            : struct ovsdb_table_schema *
      38                 :      30957 : ovsdb_table_schema_create(const char *name, bool mutable,
      39                 :            :                           unsigned int max_rows, bool is_root)
      40                 :            : {
      41                 :            :     struct ovsdb_column *uuid, *version;
      42                 :            :     struct ovsdb_table_schema *ts;
      43                 :            : 
      44                 :      30957 :     ts = xzalloc(sizeof *ts);
      45                 :      30957 :     ts->name = xstrdup(name);
      46                 :      30957 :     ts->mutable = mutable;
      47                 :      30957 :     shash_init(&ts->columns);
      48                 :      30957 :     ts->max_rows = max_rows;
      49                 :      30957 :     ts->is_root = is_root;
      50                 :            : 
      51                 :      30957 :     uuid = ovsdb_column_create("_uuid", false, true, &ovsdb_type_uuid);
      52                 :      30957 :     add_column(ts, uuid);
      53         [ -  + ]:      30957 :     ovs_assert(uuid->index == OVSDB_COL_UUID);
      54                 :            : 
      55                 :      30957 :     version = ovsdb_column_create("_version", false, false, &ovsdb_type_uuid);
      56                 :      30957 :     add_column(ts, version);
      57         [ -  + ]:      30957 :     ovs_assert(version->index == OVSDB_COL_VERSION);
      58                 :            : 
      59                 :      30957 :     ts->n_indexes = 0;
      60                 :      30957 :     ts->indexes = NULL;
      61                 :            : 
      62                 :      30957 :     return ts;
      63                 :            : }
      64                 :            : 
      65                 :            : struct ovsdb_table_schema *
      66                 :          2 : ovsdb_table_schema_clone(const struct ovsdb_table_schema *old)
      67                 :            : {
      68                 :            :     struct ovsdb_table_schema *new;
      69                 :            :     struct shash_node *node;
      70                 :            :     size_t i;
      71                 :            : 
      72                 :          2 :     new = ovsdb_table_schema_create(old->name, old->mutable,
      73                 :          2 :                                     old->max_rows, old->is_root);
      74 [ +  + ][ -  + ]:          9 :     SHASH_FOR_EACH (node, &old->columns) {
      75                 :          7 :         const struct ovsdb_column *column = node->data;
      76                 :            : 
      77         [ +  + ]:          7 :         if (column->name[0] == '_') {
      78                 :            :             /* Added automatically by ovsdb_table_schema_create(). */
      79                 :          4 :             continue;
      80                 :            :         }
      81                 :            : 
      82                 :          3 :         add_column(new, ovsdb_column_clone(column));
      83                 :            :     }
      84                 :            : 
      85                 :          2 :     new->n_indexes = old->n_indexes;
      86                 :          2 :     new->indexes = xmalloc(new->n_indexes * sizeof *new->indexes);
      87         [ +  + ]:          3 :     for (i = 0; i < new->n_indexes; i++) {
      88                 :          1 :         const struct ovsdb_column_set *old_index = &old->indexes[i];
      89                 :          1 :         struct ovsdb_column_set *new_index = &new->indexes[i];
      90                 :            :         size_t j;
      91                 :            : 
      92                 :          1 :         ovsdb_column_set_init(new_index);
      93         [ +  + ]:          2 :         for (j = 0; j < old_index->n_columns; j++) {
      94                 :          1 :             const struct ovsdb_column *old_column = old_index->columns[j];
      95                 :            :             const struct ovsdb_column *new_column;
      96                 :            : 
      97                 :          1 :             new_column = ovsdb_table_schema_get_column(new, old_column->name);
      98                 :          1 :             ovsdb_column_set_add(new_index, new_column);
      99                 :            :         }
     100                 :            :     }
     101                 :            : 
     102                 :          2 :     return new;
     103                 :            : }
     104                 :            : 
     105                 :            : void
     106                 :      30895 : ovsdb_table_schema_destroy(struct ovsdb_table_schema *ts)
     107                 :            : {
     108                 :            :     struct shash_node *node;
     109                 :            :     size_t i;
     110                 :            : 
     111         [ +  + ]:      40546 :     for (i = 0; i < ts->n_indexes; i++) {
     112                 :       9651 :         ovsdb_column_set_destroy(&ts->indexes[i]);
     113                 :            :     }
     114                 :      30895 :     free(ts->indexes);
     115                 :            : 
     116 [ +  + ][ -  + ]:     366469 :     SHASH_FOR_EACH (node, &ts->columns) {
     117                 :     335574 :         ovsdb_column_destroy(node->data);
     118                 :            :     }
     119                 :      30895 :     shash_destroy(&ts->columns);
     120                 :      30895 :     free(ts->name);
     121                 :      30895 :     free(ts);
     122                 :      30895 : }
     123                 :            : 
     124                 :            : struct ovsdb_error *
     125                 :      30958 : ovsdb_table_schema_from_json(const struct json *json, const char *name,
     126                 :            :                              struct ovsdb_table_schema **tsp)
     127                 :            : {
     128                 :            :     struct ovsdb_table_schema *ts;
     129                 :            :     const struct json *columns, *mutable, *max_rows, *is_root, *indexes;
     130                 :            :     struct shash_node *node;
     131                 :            :     struct ovsdb_parser parser;
     132                 :            :     struct ovsdb_error *error;
     133                 :            :     long long int n_max_rows;
     134                 :            : 
     135                 :      30958 :     *tsp = NULL;
     136                 :            : 
     137                 :      30958 :     ovsdb_parser_init(&parser, json, "table schema for table %s", name);
     138                 :      30958 :     columns = ovsdb_parser_member(&parser, "columns", OP_OBJECT);
     139                 :      30958 :     mutable = ovsdb_parser_member(&parser, "mutable",
     140                 :            :                                   OP_TRUE | OP_FALSE | OP_OPTIONAL);
     141                 :      30958 :     max_rows = ovsdb_parser_member(&parser, "maxRows",
     142                 :            :                                    OP_INTEGER | OP_OPTIONAL);
     143                 :      30958 :     is_root = ovsdb_parser_member(&parser, "isRoot", OP_BOOLEAN | OP_OPTIONAL);
     144                 :      30958 :     indexes = ovsdb_parser_member(&parser, "indexes", OP_ARRAY | OP_OPTIONAL);
     145                 :      30958 :     error = ovsdb_parser_finish(&parser);
     146         [ +  + ]:      30958 :     if (error) {
     147                 :          1 :         return error;
     148                 :            :     }
     149                 :            : 
     150         [ +  + ]:      30957 :     if (max_rows) {
     151         [ +  + ]:       3299 :         if (json_integer(max_rows) <= 0) {
     152                 :          1 :             return ovsdb_syntax_error(json, NULL,
     153                 :            :                                       "maxRows must be at least 1");
     154                 :            :         }
     155                 :       3298 :         n_max_rows = max_rows->u.integer;
     156                 :            :     } else {
     157                 :      27658 :         n_max_rows = UINT_MAX;
     158                 :            :     }
     159                 :            : 
     160         [ +  + ]:      30956 :     if (shash_is_empty(json_object(columns))) {
     161                 :          1 :         return ovsdb_syntax_error(json, NULL,
     162                 :            :                                   "table must have at least one column");
     163                 :            :     }
     164                 :            : 
     165                 :      30955 :     ts = ovsdb_table_schema_create(name,
     166 [ +  + ][ -  + ]:      30955 :                                    mutable ? json_boolean(mutable) : true,
     167                 :      30955 :                                    MIN(n_max_rows, UINT_MAX),
     168 [ +  + ][ +  + ]:      30955 :                                    is_root ? json_boolean(is_root) : false);
     169 [ +  + ][ -  + ]:     305131 :     SHASH_FOR_EACH (node, json_object(columns)) {
     170                 :            :         struct ovsdb_column *column;
     171                 :            : 
     172         [ +  + ]:     274177 :         if (node->name[0] == '_') {
     173                 :          1 :             error = ovsdb_syntax_error(json, NULL, "names beginning with "
     174                 :            :                                        "\"_\" are reserved");
     175         [ -  + ]:     274176 :         } else if (!ovsdb_parser_is_id(node->name)) {
     176                 :          0 :             error = ovsdb_syntax_error(json, NULL, "name must be a valid id");
     177                 :            :         } else {
     178                 :     274176 :             error = ovsdb_column_from_json(node->data, node->name, &column);
     179                 :            :         }
     180         [ +  + ]:     274177 :         if (error) {
     181                 :          1 :             goto error;
     182                 :            :         }
     183                 :            : 
     184                 :     274176 :         add_column(ts, column);
     185                 :            :     }
     186                 :            : 
     187         [ +  + ]:      30954 :     if (indexes) {
     188                 :            :         size_t i;
     189                 :            : 
     190                 :       9522 :         ts->indexes = xmalloc(indexes->u.array.n * sizeof *ts->indexes);
     191         [ +  + ]:      19208 :         for (i = 0; i < indexes->u.array.n; i++) {
     192                 :       9689 :             struct ovsdb_column_set *index = &ts->indexes[i];
     193                 :            :             size_t j;
     194                 :            : 
     195                 :       9689 :             error = ovsdb_column_set_from_json(indexes->u.array.elems[i],
     196                 :            :                                                ts, index);
     197         [ +  + ]:       9689 :             if (error) {
     198                 :          1 :                 goto error;
     199                 :            :             }
     200         [ +  + ]:       9688 :             if (index->n_columns == 0) {
     201                 :          1 :                 error = ovsdb_syntax_error(json, NULL, "index must have "
     202                 :            :                                            "at least one column");
     203                 :          1 :                 goto error;
     204                 :            :             }
     205                 :       9687 :             ts->n_indexes++;
     206                 :            : 
     207         [ +  + ]:      21406 :             for (j = 0; j < index->n_columns; j++) {
     208                 :      11720 :                 const struct ovsdb_column *column = index->columns[j];
     209                 :            : 
     210         [ +  + ]:      11720 :                 if (!column->persistent) {
     211                 :          1 :                     error = ovsdb_syntax_error(json, NULL, "ephemeral columns "
     212                 :            :                                                "(such as %s) may not be "
     213                 :            :                                                "indexed", column->name);
     214                 :          1 :                     goto error;
     215                 :            :                 }
     216                 :            :             }
     217                 :            :         }
     218                 :            :     }
     219                 :            : 
     220                 :      30951 :     *tsp = ts;
     221                 :      30951 :     return NULL;
     222                 :            : 
     223                 :            : error:
     224                 :          4 :     ovsdb_table_schema_destroy(ts);
     225                 :      30958 :     return error;
     226                 :            : }
     227                 :            : 
     228                 :            : /* Returns table schema 'ts' serialized into JSON.
     229                 :            :  *
     230                 :            :  * The "isRoot" member is included in the JSON only if its value would differ
     231                 :            :  * from 'default_is_root'.  Ordinarily 'default_is_root' should be false,
     232                 :            :  * because ordinarily a table would be not be part of the root set if its
     233                 :            :  * "isRoot" member is omitted.  However, garbage collection was not originally
     234                 :            :  * included in OVSDB, so in older schemas that do not include any "isRoot"
     235                 :            :  * members, every table is implicitly part of the root set.  To serialize such
     236                 :            :  * a schema in a way that can be read by older OVSDB tools, specify
     237                 :            :  * 'default_is_root' as true. */
     238                 :            : struct json *
     239                 :     122089 : ovsdb_table_schema_to_json(const struct ovsdb_table_schema *ts,
     240                 :            :                            bool default_is_root)
     241                 :            : {
     242                 :            :     struct json *json, *columns;
     243                 :            :     struct shash_node *node;
     244                 :            : 
     245                 :     122089 :     json = json_object_create();
     246         [ +  + ]:     122089 :     if (!ts->mutable) {
     247                 :          1 :         json_object_put(json, "mutable", json_boolean_create(false));
     248                 :            :     }
     249         [ +  + ]:     122089 :     if (default_is_root != ts->is_root) {
     250                 :      39682 :         json_object_put(json, "isRoot", json_boolean_create(ts->is_root));
     251                 :            :     }
     252                 :            : 
     253                 :     122089 :     columns = json_object_create();
     254                 :            : 
     255 [ +  + ][ -  + ]:    1487609 :     SHASH_FOR_EACH (node, &ts->columns) {
     256                 :    1365520 :         const struct ovsdb_column *column = node->data;
     257         [ +  + ]:    1365520 :         if (node->name[0] != '_') {
     258                 :    1121342 :             json_object_put(columns, column->name,
     259                 :            :                             ovsdb_column_to_json(column));
     260                 :            :         }
     261                 :            :     }
     262                 :     122089 :     json_object_put(json, "columns", columns);
     263         [ +  + ]:     122089 :     if (ts->max_rows != UINT_MAX) {
     264                 :      13670 :         json_object_put(json, "maxRows", json_integer_create(ts->max_rows));
     265                 :            :     }
     266                 :            : 
     267         [ +  + ]:     122089 :     if (ts->n_indexes) {
     268                 :            :         struct json **indexes;
     269                 :            :         size_t i;
     270                 :            : 
     271                 :      38566 :         indexes = xmalloc(ts->n_indexes * sizeof *indexes);
     272         [ +  + ]:      77614 :         for (i = 0; i < ts->n_indexes; i++) {
     273                 :      39048 :             indexes[i] = ovsdb_column_set_to_json(&ts->indexes[i]);
     274                 :            :         }
     275                 :      38566 :         json_object_put(json, "indexes",
     276                 :            :                         json_array_create(indexes, ts->n_indexes));
     277                 :            :     }
     278                 :            : 
     279                 :     122089 :     return json;
     280                 :            : }
     281                 :            : 
     282                 :            : const struct ovsdb_column *
     283                 :     192436 : ovsdb_table_schema_get_column(const struct ovsdb_table_schema *ts,
     284                 :            :                               const char *name)
     285                 :            : {
     286                 :     192436 :     return shash_find_data(&ts->columns, name);
     287                 :            : }
     288                 :            : 
     289                 :            : struct ovsdb_table *
     290                 :      15735 : ovsdb_table_create(struct ovsdb_table_schema *ts)
     291                 :            : {
     292                 :            :     struct ovsdb_table *table;
     293                 :            :     size_t i;
     294                 :            : 
     295                 :      15735 :     table = xmalloc(sizeof *table);
     296                 :      15735 :     table->schema = ts;
     297                 :      15735 :     table->txn_table = NULL;
     298                 :      15735 :     table->indexes = xmalloc(ts->n_indexes * sizeof *table->indexes);
     299         [ +  + ]:      20578 :     for (i = 0; i < ts->n_indexes; i++) {
     300                 :       4843 :         hmap_init(&table->indexes[i]);
     301                 :            :     }
     302                 :      15735 :     hmap_init(&table->rows);
     303                 :            : 
     304                 :      15735 :     return table;
     305                 :            : }
     306                 :            : 
     307                 :            : void
     308                 :      15702 : ovsdb_table_destroy(struct ovsdb_table *table)
     309                 :            : {
     310         [ +  - ]:      15702 :     if (table) {
     311                 :            :         struct ovsdb_row *row, *next;
     312                 :            :         size_t i;
     313                 :            : 
     314 [ +  + ][ -  + ]:      29411 :         HMAP_FOR_EACH_SAFE (row, next, hmap_node, &table->rows) {
                 [ +  + ]
     315                 :      13709 :             ovsdb_row_destroy(row);
     316                 :            :         }
     317                 :      15702 :         hmap_destroy(&table->rows);
     318                 :            : 
     319         [ +  + ]:      20535 :         for (i = 0; i < table->schema->n_indexes; i++) {
     320                 :       4833 :             hmap_destroy(&table->indexes[i]);
     321                 :            :         }
     322                 :      15702 :         free(table->indexes);
     323                 :            : 
     324                 :      15702 :         ovsdb_table_schema_destroy(table->schema);
     325                 :      15702 :         free(table);
     326                 :            :     }
     327                 :      15702 : }
     328                 :            : 
     329                 :            : const struct ovsdb_row *
     330                 :      82755 : ovsdb_table_get_row(const struct ovsdb_table *table, const struct uuid *uuid)
     331                 :            : {
     332                 :            :     struct ovsdb_row *row;
     333                 :            : 
     334 [ +  + ][ -  + ]:      82786 :     HMAP_FOR_EACH_WITH_HASH (row, hmap_node, uuid_hash(uuid), &table->rows) {
     335         [ +  + ]:      81832 :         if (uuid_equals(ovsdb_row_get_uuid(row), uuid)) {
     336                 :      81801 :             return row;
     337                 :            :         }
     338                 :            :     }
     339                 :            : 
     340                 :        954 :     return NULL;
     341                 :            : }

Generated by: LCOV version 1.12