[ovs-dev] [ovsdb join 4/5] ovsdb: expand ovsdb-tool to support multiple schemas

Ansis Atteka ansisatteka at gmail.com
Sun Jun 21 21:10:30 UTC 2015


On 15 June 2015 at 19:35, Andy Zhou <azhou at nicira.com> wrote:

> ovsdb-tool now accepts multiple schema files for all applicable options.

If these schema can be joined together without compatibility error,
>
s/schema/[schemas|schemata]

> the joined schema will be used as the runtime DB schema.
>
> When storing joined schemata into a database file, A JSON array will
> be store as its first record, with every individual schema as the
>
s/store/stored

> element of the array. The joined schema is not stored into the file.
> Since one can be rebuilt by rejoining the schmeata represented by
> the JSON array.
>

This file also requires updates to man pages.

>
> Signed-off-by: Andy Zhou <azhou at nicira.com>
> ---
>  ovsdb/file.c         |  85 ++++++++++++++----------
>  ovsdb/file.h         |  14 ++--
>  ovsdb/ovsdb-server.c |   2 +-
>  ovsdb/ovsdb-tool.c   | 178
> +++++++++++++++++++++++++++++++++++++++------------
>  4 files changed, 199 insertions(+), 80 deletions(-)
>
> diff --git a/ovsdb/file.c b/ovsdb/file.c
> index 8c3c31b..041b538 100644
> --- a/ovsdb/file.c
> +++ b/ovsdb/file.c
> @@ -64,7 +64,7 @@ static struct ovsdb_error *ovsdb_file_txn_commit(struct
> json *,
>                                                   struct ovsdb_log *);
>
>  static struct ovsdb_error *ovsdb_file_open__(const char *file_name,
> -                                             const struct ovsdb_schema *,
> +                                             struct shash *schemata,
>                                               bool read_only, struct ovsdb
> **,
>                                               struct ovsdb_file **);
>  static struct ovsdb_error *ovsdb_file_txn_from_json(
> @@ -85,20 +85,28 @@ static struct ovsdb_error *ovsdb_file_create(struct
> ovsdb *,
>   * '*filep' to an ovsdb_file that represents the open file.  This
> ovsdb_file
>   * persists until '*dbp' is destroyed.
>   *
> + * If 'schemata' is nonnull, it needs to be an empty shash. On success,
> + * it contains the schemata read from the log file. Caller is repsonsible
> + * for freeing memory.

+ *
>   * On success, returns NULL.  On failure, returns an ovsdb_error (which
> the
>   * caller must destroy) and sets '*dbp' and '*filep' to NULL. */
>  struct ovsdb_error *
>  ovsdb_file_open(const char *file_name, bool read_only,
> -                struct ovsdb **dbp, struct ovsdb_file **filep)
> +                struct ovsdb **dbp, struct ovsdb_file **filep,
> +                struct shash *schemata)
>  {
> -    return ovsdb_file_open__(file_name, NULL, read_only, dbp, filep);
> +    if (schemata) {
> +        ovs_assert(shash_count(schemata) == 0);
> +    }
> +    return ovsdb_file_open__(file_name, schemata, read_only, dbp, filep);
>  }
>
> -/* Opens database 'file_name' with an alternate schema.  The specified
> 'schema'
> - * is used to interpret the data in 'file_name', ignoring the schema
> actually
> - * stored in the file.  Data in the file for tables or columns that do not
> - * exist in 'schema' are ignored, but the ovsdb file format must
> otherwise be
> - * observed, including column constraints.
> +/* Opens database 'file_name' with an alternate schemata.  The specified
> + * 'schemata' * is used to interpret the data in 'file_name', ignoring the
> + * schemata actually stored in the file.  Data in the file for tables or
> + * columns that do not exist in 'schemata' are ignored, but the ovsdb file
> + * format must otherwise be observed, including column constraints.
>   *
>   * This function can be useful for upgrading or downgrading databases to
>   * "almost-compatible" formats.
> @@ -110,23 +118,22 @@ ovsdb_file_open(const char *file_name, bool
> read_only,
>   * null pointer.  On failure, returns an ovsdb_error (which the caller
> must
>   * destroy) and sets '*dbp' to NULL. */
>  struct ovsdb_error *
> -ovsdb_file_open_as_schema(const char *file_name,
> -                          const struct ovsdb_schema *schema,
> -                          struct ovsdb **dbp)
> +ovsdb_file_open_as_schemata(const char *file_name,
> +                            struct shash *schemata,
> +                            struct ovsdb **dbp)
>  {
> -    return ovsdb_file_open__(file_name, schema, true, dbp, NULL);
> +    return ovsdb_file_open__(file_name, schemata, true, dbp, NULL);
>  }
>
>  static struct ovsdb_error *
>  ovsdb_file_open_log(const char *file_name, enum ovsdb_log_open_mode
> open_mode,
> -                    struct ovsdb_log **logp, struct ovsdb_schema
> **schemap)
> +                    struct ovsdb_log **logp, struct shash *schemata)
>  {
> -    struct ovsdb_schema *schema = NULL;
>      struct ovsdb_log *log = NULL;
>      struct ovsdb_error *error;
>      struct json *json = NULL;
>
> -    ovs_assert(logp || schemap);
> +    ovs_assert(logp || schemata);
>
>      error = ovsdb_log_open(file_name, open_mode, -1, &log);
>      if (error) {
> @@ -142,8 +149,8 @@ ovsdb_file_open_log(const char *file_name, enum
> ovsdb_log_open_mode open_mode,
>          goto error;
>      }
>
> -    if (schemap) {
> -        error = ovsdb_schema_from_json(json, &schema);
> +    if (ovsdb_schemata_is_empty(schemata)) {
> +        error = ovsdb_schemata_from_json(json, schemata);
>          if (error) {
>              error = ovsdb_wrap_error(error,
>                                       "failed to parse \"%s\" as ovsdb
> schema",
> @@ -158,9 +165,6 @@ ovsdb_file_open_log(const char *file_name, enum
> ovsdb_log_open_mode open_mode,
>      } else {
>          ovsdb_log_close(log);
>      }
> -    if (schemap) {
> -        *schemap = schema;
> -    }
>      return NULL;
>
>  error:
> @@ -169,44 +173,57 @@ error:
>      if (logp) {
>          *logp = NULL;
>      }
> -    if (schemap) {
> -        *schemap = NULL;
> -    }
>      return error;
>  }
>
>  static struct ovsdb_error *
>  ovsdb_file_open__(const char *file_name,
> -                  const struct ovsdb_schema *alternate_schema,
> +                  struct shash *schemata,
>                    bool read_only, struct ovsdb **dbp,
>                    struct ovsdb_file **filep)
>  {
>      enum ovsdb_log_open_mode open_mode;
>      unsigned int n_transactions;
> -    struct ovsdb_schema *schema = NULL;
> +    struct ovsdb_schema *joined_schema;
>      struct ovsdb_error *error;
>      struct ovsdb_log *log;
>      struct json *json;
>      struct ovsdb *db = NULL;
> +    bool convert = ovsdb_schemata_is_non_empty(schemata);
> +    struct shash local_schemata = SHASH_INITIALIZER(&local_schemata);
> +
> +    /* If caller passed in non empty 'schemata',  we will use it
> +     * instead of the schemata stored int the log file.  Otherwise,
> +     * it will be the container for storing the schemata read from
> +     * the log file.  */
> +    if (!schemata) {
> +        /* Caller don't need the schmeta information, we use
> 'local_schemata'
>
typo "schmeta"

> +         * to read it from the db file. */
> +        schemata = &local_schemata;
> +    }
>
>      /* In read-only mode there is no ovsdb_file so 'filep' must be null.
> */
>      ovs_assert(!(read_only && filep));
>
>      open_mode = read_only ? OVSDB_LOG_READ_ONLY : OVSDB_LOG_READ_WRITE;
> -    error = ovsdb_file_open_log(file_name, open_mode, &log,
> -                                alternate_schema ? NULL : &schema);
> +    error = ovsdb_file_open_log(file_name, open_mode, &log, schemata);
> +    if (error) {
> +        goto error;
> +    }
> +
> +    error = ovsdb_schemata_join(schemata, &joined_schema);
>      if (error) {
>          goto error;
>      }
>
> -    db = ovsdb_create(schema ? schema :
> ovsdb_schema_clone(alternate_schema));
> +    /* 'db' will take the ownership of joined_schema */
> +    db = ovsdb_create(joined_schema);
>
>      n_transactions = 0;
>      while ((error = ovsdb_log_read(log, &json)) == NULL && json) {
>          struct ovsdb_txn *txn;
>
> -        error = ovsdb_file_txn_from_json(db, json, alternate_schema !=
> NULL,
> -                                         &txn);
> +        error = ovsdb_file_txn_from_json(db, json, convert, &txn);
>          json_destroy(json);
>          if (error) {
>              ovsdb_log_unread(log);
> @@ -246,6 +263,7 @@ ovsdb_file_open__(const char *file_name,
>      }
>
>      *dbp = db;
>
 For example, ovsdb_file_open_log()->ovsdb_schemata_from_json() might have
already called ovsdb_schemata_destroy() for you in case of error. So this
would potentially lead to double free. Is it right?

> +    ovsdb_schemata_destroy(&local_schemata);
>      return NULL;
>
>  error:
> @@ -253,6 +271,7 @@ error:
>      if (filep) {
>          *filep = NULL;
>      }
> +    ovsdb_schemata_destroy(&local_schemata);
>      ovsdb_destroy(db);
>      ovsdb_log_close(log);
>      return error;
> @@ -484,10 +503,10 @@ ovsdb_file_save_copy(const char *file_name, int
> locking,
>   * schema.  On failure, returns an ovsdb_error (which the caller must
> destroy)
>   * and sets '*dbp' to NULL. */
>  struct ovsdb_error *
> -ovsdb_file_read_schema(const char *file_name, struct ovsdb_schema
> **schemap)
> +ovsdb_file_read_schemata(const char *file_name, struct shash *schemata)
>  {
> -    ovs_assert(schemap != NULL);
> -    return ovsdb_file_open_log(file_name, OVSDB_LOG_READ_ONLY, NULL,
> schemap);
> +    ovs_assert(schemata && ovsdb_schemata_is_empty(schemata));
> +    return ovsdb_file_open_log(file_name, OVSDB_LOG_READ_ONLY, NULL,
> schemata);
>  }
>
>  /* Replica implementation. */
> diff --git a/ovsdb/file.h b/ovsdb/file.h
> index ee67b12..aaa9c8c 100644
> --- a/ovsdb/file.h
> +++ b/ovsdb/file.h
> @@ -18,6 +18,7 @@
>
>  #include <stdbool.h>
>  #include "compiler.h"
> +#include "shash.h"
>  #include "log.h"
>
>  struct ovsdb;
> @@ -25,12 +26,13 @@ struct ovsdb_file;
>  struct ovsdb_schema;
>
>  struct ovsdb_error *ovsdb_file_open(const char *file_name, bool read_only,
> -                                    struct ovsdb **, struct ovsdb_file **)
> +                                    struct ovsdb **, struct ovsdb_file **,
> +                                    struct shash *schemata)
>      OVS_WARN_UNUSED_RESULT;
>
> -struct ovsdb_error *ovsdb_file_open_as_schema(const char *file_name,
> -                                              const struct ovsdb_schema *,
> -                                              struct ovsdb **)
> +struct ovsdb_error *ovsdb_file_open_as_schemata(const char *file_name,
> +                                                struct shash *schemata,
> +                                                struct ovsdb **)
>      OVS_WARN_UNUSED_RESULT;
>
>  struct ovsdb_error *ovsdb_file_save_copy(const char *file_name, int
> locking,
> @@ -40,8 +42,8 @@ struct ovsdb_error *ovsdb_file_save_copy(const char
> *file_name, int locking,
>
>  struct ovsdb_error *ovsdb_file_compact(struct ovsdb_file *);
>
> -struct ovsdb_error *ovsdb_file_read_schema(const char *file_name,
> -                                           struct ovsdb_schema **)
> +struct ovsdb_error *ovsdb_file_read_schemata(const char *file_name,
> +                                           struct shash *schemata)
>      OVS_WARN_UNUSED_RESULT;
>
>  #endif /* ovsdb/file.h */
> diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
> index cd13b0d..c52af17 100644
> --- a/ovsdb/ovsdb-server.c
> +++ b/ovsdb/ovsdb-server.c
> @@ -407,7 +407,7 @@ open_db(struct server_config *config, const char
> *filename)
>      db = xzalloc(sizeof *db);
>      db->filename = xstrdup(filename);
>
> -    db_error = ovsdb_file_open(db->filename, false, &db->db, &db->file);
> +    db_error = ovsdb_file_open(db->filename, false, &db->db, &db->file,
> NULL);
>      if (db_error) {
>          error = ovsdb_error_to_string(db_error);
>      } else if (!ovsdb_jsonrpc_server_add_db(config->jsonrpc, db->db)) {
> diff --git a/ovsdb/ovsdb-tool.c b/ovsdb/ovsdb-tool.c
> index 32883e2..a91d8b2 100644
> --- a/ovsdb/ovsdb-tool.c
> +++ b/ovsdb/ovsdb-tool.c
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
> + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2015 Nicira, Inc.
>   *
>   * Licensed under the Apache License, Version 2.0 (the "License");
>   * you may not use this file except in compliance with the License.
> @@ -38,7 +38,9 @@
>  #include "socket-util.h"
>  #include "table.h"
>  #include "timeval.h"
> +#include "sset.h"
>
Alphabetical order?

>  #include "util.h"
> +#include "shash.h"
>  #include "openvswitch/vlog.h"
>
>  /* -m, --more: Verbosity level for "show-log" command output. */
> @@ -56,12 +58,14 @@ int
>  main(int argc, char *argv[])
>  {
>      struct ovs_cmdl_context ctx = { .argc = 0, };
> +
>      set_program_name(argv[0]);
>      parse_options(argc, argv);
>      fatal_ignore_sigpipe();
>      ctx.argc = argc - optind;
>      ctx.argv = argv + optind;
>      ovs_cmdl_run_command(&ctx, get_all_commands());
> +
>      return 0;
>  }
>
> @@ -188,20 +192,33 @@ check_ovsdb_error(struct ovsdb_error *error)
>          ovs_fatal(0, "%s", ovsdb_error_to_string(error));
>      }
>  }
> +
> +static void
> +parse_schema_file_names(const char *file_names, struct sset *names)
> +{
> +   ovsdb_parse_schema_file_names(file_names, names, default_schema());
> +   ovs_assert(!sset_is_empty(names));
> +}
> +
>
>  static void
>  do_create(struct ovs_cmdl_context *ctx)
>  {
>      const char *db_file_name = ctx->argc >= 2 ? ctx->argv[1] :
> default_db();
> -    const char *schema_file_name = ctx->argc >= 3 ? ctx->argv[2] :
> default_schema();
> -    struct ovsdb_schema *schema;
> +    const char *schema_file_name = ctx->argc >= 3 ? ctx->argv[2] : NULL;
>      struct ovsdb_log *log;
>      struct json *json;
> +    struct shash schemata = SHASH_INITIALIZER(&schemata);
> +    struct sset schema_names = SSET_INITIALIZER(&schema_names);
>
> -    /* Read schema from file and convert to JSON. */
> -    check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema));
> -    json = ovsdb_schema_to_json(schema);
> -    ovsdb_schema_destroy(schema);
> +    /* Read schema from file(s) and convert to JSON. */
> +    parse_schema_file_names(schema_file_name, &schema_names);
> +
> +    check_ovsdb_error(ovsdb_schemata_from_files(&schema_names,
> &schemata));
> +    sset_destroy(&schema_names);
> +
> +    json = ovsdb_schemata_to_json(&schemata);
> +    ovsdb_schemata_destroy(&schemata);
>
>      /* Create database file. */
>      check_ovsdb_error(ovsdb_log_open(db_file_name, OVSDB_LOG_CREATE,
> @@ -215,7 +232,7 @@ do_create(struct ovs_cmdl_context *ctx)
>
>  static void
>  compact_or_convert(const char *src_name_, const char *dst_name_,
> -                   const struct ovsdb_schema *new_schema,
> +                   struct shash *new_schemata,
>                     const char *comment)
>  {
>      char *src_name, *dst_name;
> @@ -249,9 +266,9 @@ compact_or_convert(const char *src_name_, const char
> *dst_name_,
>      }
>
>      /* Save a copy. */
> -    check_ovsdb_error(new_schema
> -                      ? ovsdb_file_open_as_schema(src_name, new_schema,
> &db)
> -                      : ovsdb_file_open(src_name, true, &db, NULL));
> +    check_ovsdb_error(ovsdb_schemata_is_null_or_empty(new_schemata)
> +                      ? ovsdb_file_open(src_name, true, &db, NULL,
> new_schemata)
> +                      : ovsdb_file_open_as_schemata(src_name,
> new_schemata, &db));
>      check_ovsdb_error(ovsdb_file_save_copy(dst_name, false, comment, db));
>      ovsdb_destroy(db);
>
> @@ -287,72 +304,153 @@ static void
>  do_convert(struct ovs_cmdl_context *ctx)
>  {
>      const char *db = ctx->argc >= 2 ? ctx->argv[1] : default_db();
> -    const char *schema = ctx->argc >= 3 ? ctx->argv[2] : default_schema();
> +    const char *schema_file_name = ctx->argc >= 3 ? ctx->argv[2] : NULL;
>      const char *target = ctx->argc >= 4 ? ctx->argv[3] : NULL;
> -    struct ovsdb_schema *new_schema;
> +    struct shash schemata = SHASH_INITIALIZER(&schemata);
> +    struct sset schema_names = SSET_INITIALIZER(&schema_names);
>
> -    check_ovsdb_error(ovsdb_schema_from_file(schema, &new_schema));
> -    compact_or_convert(db, target, new_schema,
> +    parse_schema_file_names(schema_file_name, &schema_names);
> +    check_ovsdb_error(ovsdb_schemata_from_files(&schema_names,
> &schemata));
> +    sset_destroy(&schema_names);
> +
> +    compact_or_convert(db, target, &schemata,
>                         "converted by ovsdb-tool "VERSION);
> -    ovsdb_schema_destroy(new_schema);
> +    ovsdb_schemata_destroy(&schemata);
>  }
>
>  static void
>  do_needs_conversion(struct ovs_cmdl_context *ctx)
>  {
>      const char *db_file_name = ctx->argc >= 2 ? ctx->argv[1] :
> default_db();
> -    const char *schema_file_name = ctx->argc >= 3 ? ctx->argv[2] :
> default_schema();
> -    struct ovsdb_schema *schema1, *schema2;
> -
> -    check_ovsdb_error(ovsdb_file_read_schema(db_file_name, &schema1));
> -    check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema2));
> -    puts(ovsdb_schema_equal(schema1, schema2) ? "no" : "yes");
> -    ovsdb_schema_destroy(schema1);
> -    ovsdb_schema_destroy(schema2);
> +    const char *schema_file_name = ctx->argc >= 3 ? ctx->argv[2] : NULL;
> +    struct shash schemata1 = SHASH_INITIALIZER(&schemata1);
> +    struct shash schemata2 = SHASH_INITIALIZER(&schemata2);
> +    struct shash_node *node1, *node2;
> +    bool need_conversion = false;
> +    struct sset schema_names = SSET_INITIALIZER(&schema_names);
> +
> +
> +    /* Read schema from file(s) and convert to JSON. */
> +    parse_schema_file_names(schema_file_name, &schema_names);
> +    check_ovsdb_error(ovsdb_schemata_from_files(&schema_names,
> &schemata1));
> +    sset_destroy(&schema_names);
> +
> +    check_ovsdb_error(ovsdb_file_read_schemata(db_file_name, &schemata2));
> +
> +    SHASH_FOR_EACH (node1, &schemata1) {
> +        struct ovsdb_schema *schema1 = node1->data;
> +
> +        node2 = shash_find(&schemata2, schema1->name);
> +        if (node2) {
> +            const struct ovsdb_schema *schema2 = node2->data;
> +
> +            need_conversion = ovsdb_schema_equal(schema1, schema2);
> +        }
> +
> +        if (!need_conversion) {
> +            break;
> +        }
> +    }
> +
> +    puts(need_conversion ? "no" : "yes");
>
Do you have this reverse way? ovsdb-tool man page says this:

        needs-conversion db schema
              Reads  the  schema  embedded  in db and the standalone schema
in
              schema and compares them.  If the schemas are the  same,
 prints
              no on stdout; if they differ, print yes.

in your case I think "need_conversion" actually should be renamed to
"schemas_are_equal" because "need_conversion" is negation of that?

> +
> +    ovsdb_schemata_destroy(&schemata1);
> +    ovsdb_schemata_destroy(&schemata2);
>  }
>
>  static void
>  do_db_version(struct ovs_cmdl_context *ctx)
>  {
>      const char *db_file_name = ctx->argc >= 2 ? ctx->argv[1] :
> default_db();
> +    struct shash schemata = SHASH_INITIALIZER(&schemata);
>      struct ovsdb_schema *schema;
>
> -    check_ovsdb_error(ovsdb_file_read_schema(db_file_name, &schema));
> -    puts(schema->version);
> -    ovsdb_schema_destroy(schema);
> +    check_ovsdb_error(ovsdb_file_read_schemata(db_file_name, &schemata));
> +
> +    if (shash_count(&schemata) == 1) {
> +        schema = shash_first(&schemata)->data;
> +        puts(schema->version);
> +    } else {
> +        struct shash_node *node;
> +        SHASH_FOR_EACH (node, &schemata) {
> +            schema = node->data;
> +            printf("%s:%s\n", schema->name, schema->version);
> +        }
> +    }
> +
> +    ovsdb_schemata_destroy(&schemata);
>  }
>
>  static void
>  do_db_cksum(struct ovs_cmdl_context *ctx)
>  {
>      const char *db_file_name = ctx->argc >= 2 ? ctx->argv[1] :
> default_db();
> +    struct shash schemata = SHASH_INITIALIZER(&schemata);
>      struct ovsdb_schema *schema;
>
> -    check_ovsdb_error(ovsdb_file_read_schema(db_file_name, &schema));
> -    puts(schema->cksum);
> -    ovsdb_schema_destroy(schema);
> +    check_ovsdb_error(ovsdb_file_read_schemata(db_file_name, &schemata));
> +
> +    if (shash_count(&schemata) == 1) {
> +        schema = shash_first(&schemata)->data;
> +        puts(schema->cksum);
> +    } else {
> +        struct shash_node *node;
> +        SHASH_FOR_EACH (node, &schemata) {
> +            schema = node->data;
> +            printf("%s:%s\n", schema->name, schema->cksum);
> +        }
> +    }
> +    ovsdb_schemata_destroy(&schemata);
>  }
>
>  static void
>  do_schema_version(struct ovs_cmdl_context *ctx)
>  {
>      const char *schema_file_name = ctx->argc >= 2 ? ctx->argv[1] :
> default_schema();
> +    struct shash schemata = SHASH_INITIALIZER(&schemata);
>      struct ovsdb_schema *schema;
> -
> -    check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema));
> -    puts(schema->version);
> -    ovsdb_schema_destroy(schema);
> +    struct sset schema_names = SSET_INITIALIZER(&schema_names);
> +
> +    parse_schema_file_names(schema_file_name, &schema_names);
> +    check_ovsdb_error(ovsdb_schemata_from_files(&schema_names,
> &schemata));
> +    sset_destroy(&schema_names);
> +
> +    if (shash_count(&schemata) == 1) {
> +        schema = shash_first(&schemata)->data;
> +        puts(schema->version);
> +    } else {
> +        struct shash_node *node;
> +        SHASH_FOR_EACH (node, &schemata) {
> +            schema = node->data;
> +            printf("%s:%s\n", schema->name, schema->version);
> +        }
> +    }
> +    ovsdb_schemata_destroy(&schemata);
>  }
>
>  static void
>  do_schema_cksum(struct ovs_cmdl_context *ctx)
>  {
> -    const char *schema_file_name = ctx->argc >= 2 ? ctx->argv[1] :
> default_schema();
> +    const char *schema_file_name = ctx->argc >= 2 ? ctx->argv[1] : NULL;
> +    struct shash schemata = SHASH_INITIALIZER(&schemata);
>      struct ovsdb_schema *schema;
> -
> -    check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema));
> -    puts(schema->cksum);
> -    ovsdb_schema_destroy(schema);
> +    struct sset schema_names = SSET_INITIALIZER(&schema_names);
> +
> +    parse_schema_file_names(schema_file_name, &schema_names);
> +    check_ovsdb_error(ovsdb_schemata_from_files(&schema_names,
> &schemata));

+    sset_destroy(&schema_names);
> +
> +    if (shash_count(&schemata) == 1) {
> +        schema = shash_first(&schemata)->data;
> +        puts(schema->cksum);
> +    } else {
> +        struct shash_node *node;
> +        SHASH_FOR_EACH (node, &schemata) {
> +            schema = node->data;
> +            printf("%s:%s\n", schema->name, schema->cksum);
> +        }
> +    }
>
+    ovsdb_schemata_destroy(&schemata);
>  }
>
>  static void
> @@ -363,7 +461,7 @@ transact(bool read_only, int argc, char *argv[])
>      struct json *request, *result;
>      struct ovsdb *db;
>
> -    check_ovsdb_error(ovsdb_file_open(db_file_name, read_only, &db,
> NULL));
> +    check_ovsdb_error(ovsdb_file_open(db_file_name, read_only, &db, NULL,
> NULL));
>
>      request = parse_json(transaction);
>      result = ovsdb_execute(db, NULL, request, 0, NULL);
> --
> 1.9.1
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
>



More information about the dev mailing list