Thanks. I pushed these to master.
On Mon, Sep 24, 2012 at 01:35:13PM -0700, Ethan Jackson wrote: > Acked-by: Ethan Jackson <et...@nicira.com> > > > On Fri, Sep 21, 2012 at 11:26 AM, Ben Pfaff <b...@nicira.com> wrote: > > The OVSDB protocol has supported multiple databases for a long time, but > > the ovsdb-server implementation only supported one database at a time. > > This commit adds support for multiple databases. > > > > Feature #12353. > > Signed-off-by: Ben Pfaff <b...@nicira.com> > > --- > > ovsdb/jsonrpc-server.c | 115 ++++++++++++-------- > > ovsdb/jsonrpc-server.h | 4 +- > > ovsdb/ovsdb-server.1.in | 32 +++--- > > ovsdb/ovsdb-server.c | 273 > > ++++++++++++++++++++++++++++++++--------------- > > ovsdb/server.c | 28 ++++-- > > ovsdb/server.h | 13 ++- > > ovsdb/trigger.c | 9 +- > > ovsdb/trigger.h | 8 +- > > tests/ovsdb-server.at | 61 ++++++++--- > > tests/test-ovsdb.c | 8 +- > > utilities/ovs-ctl.8 | 6 + > > utilities/ovs-ctl.in | 17 +++- > > 12 files changed, 392 insertions(+), 182 deletions(-) > > > > diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c > > index bb887d0..279ea97 100644 > > --- a/ovsdb/jsonrpc-server.c > > +++ b/ovsdb/jsonrpc-server.c > > @@ -66,6 +66,7 @@ static void ovsdb_jsonrpc_session_unlock__(struct > > ovsdb_lock_waiter *); > > > > /* Triggers. */ > > static void ovsdb_jsonrpc_trigger_create(struct ovsdb_jsonrpc_session *, > > + struct ovsdb *, > > struct json *id, struct json > > *params); > > static struct ovsdb_jsonrpc_trigger *ovsdb_jsonrpc_trigger_find( > > struct ovsdb_jsonrpc_session *, const struct json *id, size_t hash); > > @@ -76,7 +77,7 @@ static void ovsdb_jsonrpc_trigger_complete_done( > > > > /* Monitors. */ > > static struct json *ovsdb_jsonrpc_monitor_create( > > - struct ovsdb_jsonrpc_session *, struct json *params); > > + struct ovsdb_jsonrpc_session *, struct ovsdb *, struct json *params); > > static struct jsonrpc_msg *ovsdb_jsonrpc_monitor_cancel( > > struct ovsdb_jsonrpc_session *, > > struct json_array *params, > > @@ -106,16 +107,29 @@ static struct ovsdb_jsonrpc_remote > > *ovsdb_jsonrpc_server_add_remote( > > ); > > static void ovsdb_jsonrpc_server_del_remote(struct shash_node *); > > > > +/* Creates and returns a new server to provide JSON-RPC access to an OVSDB. > > + * > > + * The caller must call ovsdb_jsonrpc_server_add_db() for each database to > > + * which 'server' should provide access. */ > > struct ovsdb_jsonrpc_server * > > -ovsdb_jsonrpc_server_create(struct ovsdb *db) > > +ovsdb_jsonrpc_server_create(void) > > { > > struct ovsdb_jsonrpc_server *server = xzalloc(sizeof *server); > > - ovsdb_server_init(&server->up, db); > > + ovsdb_server_init(&server->up); > > server->max_sessions = 64; > > shash_init(&server->remotes); > > return server; > > } > > > > +/* Adds 'db' to the set of databases served out by 'svr'. Returns true if > > + * successful, false if 'db''s name is the same as some database already in > > + * 'server'. */ > > +bool > > +ovsdb_jsonrpc_server_add_db(struct ovsdb_jsonrpc_server *svr, struct ovsdb > > *db) > > +{ > > + return ovsdb_server_add_db(&svr->up, db); > > +} > > + > > void > > ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *svr) > > { > > @@ -350,7 +364,7 @@ ovsdb_jsonrpc_session_create(struct > > ovsdb_jsonrpc_remote *remote, > > struct ovsdb_jsonrpc_session *s; > > > > s = xzalloc(sizeof *s); > > - ovsdb_session_init(&s->up, remote->server->up.db); > > + ovsdb_session_init(&s->up, &remote->server->up); > > s->remote = remote; > > list_push_back(&remote->sessions, &s->node); > > hmap_init(&s->triggers); > > @@ -558,21 +572,22 @@ ovsdb_jsonrpc_session_get_status(const struct > > ovsdb_jsonrpc_remote *remote, > > return true; > > } > > > > -static const char * > > -get_db_name(const struct ovsdb_jsonrpc_session *s) > > -{ > > - return s->remote->server->up.db->schema->name; > > -} > > - > > -static struct jsonrpc_msg * > > -ovsdb_jsonrpc_check_db_name(const struct ovsdb_jsonrpc_session *s, > > - const struct jsonrpc_msg *request) > > +/* Examines 'request' to determine the database to which it relates, and > > then > > + * searches 's' to find that database: > > + * > > + * - If successful, returns the database and sets '*replyp' to NULL. > > + * > > + * - If no such database exists, returns NULL and sets '*replyp' to an > > + * appropriate JSON-RPC error reply, owned by the caller. */ > > +static struct ovsdb * > > +ovsdb_jsonrpc_lookup_db(const struct ovsdb_jsonrpc_session *s, > > + const struct jsonrpc_msg *request, > > + struct jsonrpc_msg **replyp) > > { > > struct json_array *params; > > - const char *want_db_name; > > - const char *have_db_name; > > struct ovsdb_error *error; > > - struct jsonrpc_msg *reply; > > + const char *db_name; > > + struct ovsdb *db; > > > > params = json_array(request->params); > > if (!params->n || params->elems[0]->type != JSON_STRING) { > > @@ -582,22 +597,23 @@ ovsdb_jsonrpc_check_db_name(const struct > > ovsdb_jsonrpc_session *s, > > goto error; > > } > > > > - want_db_name = params->elems[0]->u.string; > > - have_db_name = get_db_name(s); > > - if (strcmp(want_db_name, have_db_name)) { > > + db_name = params->elems[0]->u.string; > > + db = shash_find_data(&s->up.server->dbs, db_name); > > + if (!db) { > > error = ovsdb_syntax_error( > > request->params, "unknown database", > > "%s request specifies unknown database %s", > > - request->method, want_db_name); > > + request->method, db_name); > > goto error; > > } > > > > - return NULL; > > + *replyp = NULL; > > + return db; > > > > error: > > - reply = jsonrpc_create_reply(ovsdb_error_to_json(error), request->id); > > + *replyp = jsonrpc_create_reply(ovsdb_error_to_json(error), > > request->id); > > ovsdb_error_destroy(error); > > - return reply; > > + return NULL; > > } > > > > static struct ovsdb_error * > > @@ -739,10 +755,10 @@ error: > > } > > > > static struct jsonrpc_msg * > > -execute_transaction(struct ovsdb_jsonrpc_session *s, > > +execute_transaction(struct ovsdb_jsonrpc_session *s, struct ovsdb *db, > > struct jsonrpc_msg *request) > > { > > - ovsdb_jsonrpc_trigger_create(s, request->id, request->params); > > + ovsdb_jsonrpc_trigger_create(s, db, request->id, request->params); > > request->id = NULL; > > request->params = NULL; > > jsonrpc_msg_destroy(request); > > @@ -756,30 +772,39 @@ ovsdb_jsonrpc_session_got_request(struct > > ovsdb_jsonrpc_session *s, > > struct jsonrpc_msg *reply; > > > > if (!strcmp(request->method, "transact")) { > > - reply = ovsdb_jsonrpc_check_db_name(s, request); > > + struct ovsdb *db = ovsdb_jsonrpc_lookup_db(s, request, &reply); > > if (!reply) { > > - reply = execute_transaction(s, request); > > + reply = execute_transaction(s, db, request); > > } > > } else if (!strcmp(request->method, "monitor")) { > > - reply = ovsdb_jsonrpc_check_db_name(s, request); > > + struct ovsdb *db = ovsdb_jsonrpc_lookup_db(s, request, &reply); > > if (!reply) { > > reply = jsonrpc_create_reply( > > - ovsdb_jsonrpc_monitor_create(s, request->params), > > request->id); > > + ovsdb_jsonrpc_monitor_create(s, db, request->params), > > + request->id); > > } > > } else if (!strcmp(request->method, "monitor_cancel")) { > > reply = ovsdb_jsonrpc_monitor_cancel(s, > > json_array(request->params), > > request->id); > > } else if (!strcmp(request->method, "get_schema")) { > > - reply = ovsdb_jsonrpc_check_db_name(s, request); > > + struct ovsdb *db = ovsdb_jsonrpc_lookup_db(s, request, &reply); > > if (!reply) { > > - reply = jsonrpc_create_reply( > > - ovsdb_schema_to_json(s->remote->server->up.db->schema), > > - request->id); > > + reply = jsonrpc_create_reply(ovsdb_schema_to_json(db->schema), > > + request->id); > > } > > } else if (!strcmp(request->method, "list_dbs")) { > > - reply = jsonrpc_create_reply( > > - json_array_create_1(json_string_create(get_db_name(s))), > > - request->id); > > + size_t n_dbs = shash_count(&s->up.server->dbs); > > + struct shash_node *node; > > + struct json **dbs; > > + size_t i; > > + > > + dbs = xmalloc(n_dbs * sizeof *dbs); > > + i = 0; > > + SHASH_FOR_EACH (node, &s->up.server->dbs) { > > + dbs[i++] = json_string_create(node->name); > > + } > > + reply = jsonrpc_create_reply(json_array_create(dbs, n_dbs), > > + request->id); > > } else if (!strcmp(request->method, "lock")) { > > reply = ovsdb_jsonrpc_session_lock(s, request, OVSDB_LOCK_WAIT); > > } else if (!strcmp(request->method, "steal")) { > > @@ -836,7 +861,7 @@ struct ovsdb_jsonrpc_trigger { > > }; > > > > static void > > -ovsdb_jsonrpc_trigger_create(struct ovsdb_jsonrpc_session *s, > > +ovsdb_jsonrpc_trigger_create(struct ovsdb_jsonrpc_session *s, struct ovsdb > > *db, > > struct json *id, struct json *params) > > { > > struct ovsdb_jsonrpc_trigger *t; > > @@ -858,7 +883,7 @@ ovsdb_jsonrpc_trigger_create(struct > > ovsdb_jsonrpc_session *s, > > > > /* Insert into trigger table. */ > > t = xmalloc(sizeof *t); > > - ovsdb_trigger_init(&s->up, &t->trigger, params, time_msec()); > > + ovsdb_trigger_init(&s->up, db, &t->trigger, params, time_msec()); > > t->id = id; > > hmap_insert(&s->triggers, &t->hmap_node, hash); > > > > @@ -962,6 +987,7 @@ struct ovsdb_jsonrpc_monitor_table { > > struct ovsdb_jsonrpc_monitor { > > struct ovsdb_replica replica; > > struct ovsdb_jsonrpc_session *session; > > + struct ovsdb *db; > > struct hmap_node node; /* In ovsdb_jsonrpc_session's "monitors". > > */ > > > > struct json *monitor_id; > > @@ -1113,7 +1139,7 @@ ovsdb_jsonrpc_parse_monitor_request(struct > > ovsdb_jsonrpc_monitor_table *mt, > > } > > > > static struct json * > > -ovsdb_jsonrpc_monitor_create(struct ovsdb_jsonrpc_session *s, > > +ovsdb_jsonrpc_monitor_create(struct ovsdb_jsonrpc_session *s, struct ovsdb > > *db, > > struct json *params) > > { > > struct ovsdb_jsonrpc_monitor *m = NULL; > > @@ -1141,8 +1167,9 @@ ovsdb_jsonrpc_monitor_create(struct > > ovsdb_jsonrpc_session *s, > > > > m = xzalloc(sizeof *m); > > ovsdb_replica_init(&m->replica, &ovsdb_jsonrpc_replica_class); > > - ovsdb_add_replica(s->remote->server->up.db, &m->replica); > > + ovsdb_add_replica(db, &m->replica); > > m->session = s; > > + m->db = db; > > hmap_insert(&s->monitors, &m->node, json_hash(monitor_id, 0)); > > m->monitor_id = json_clone(monitor_id); > > shash_init(&m->tables); > > @@ -1154,7 +1181,7 @@ ovsdb_jsonrpc_monitor_create(struct > > ovsdb_jsonrpc_session *s, > > const struct json *mr_value; > > size_t i; > > > > - table = ovsdb_get_table(s->remote->server->up.db, node->name); > > + table = ovsdb_get_table(m->db, node->name); > > if (!table) { > > error = ovsdb_syntax_error(NULL, NULL, > > "no table named %s", node->name); > > @@ -1203,7 +1230,7 @@ ovsdb_jsonrpc_monitor_create(struct > > ovsdb_jsonrpc_session *s, > > > > error: > > if (m) { > > - ovsdb_remove_replica(s->remote->server->up.db, &m->replica); > > + ovsdb_remove_replica(m->db, &m->replica); > > } > > > > json = ovsdb_error_to_json(error); > > @@ -1227,7 +1254,7 @@ ovsdb_jsonrpc_monitor_cancel(struct > > ovsdb_jsonrpc_session *s, > > return jsonrpc_create_error(json_string_create("unknown > > monitor"), > > request_id); > > } else { > > - ovsdb_remove_replica(s->remote->server->up.db, &m->replica); > > + ovsdb_remove_replica(m->db, &m->replica); > > return jsonrpc_create_reply(json_object_create(), request_id); > > } > > } > > @@ -1239,7 +1266,7 @@ ovsdb_jsonrpc_monitor_remove_all(struct > > ovsdb_jsonrpc_session *s) > > struct ovsdb_jsonrpc_monitor *m, *next; > > > > HMAP_FOR_EACH_SAFE (m, next, node, &s->monitors) { > > - ovsdb_remove_replica(s->remote->server->up.db, &m->replica); > > + ovsdb_remove_replica(m->db, &m->replica); > > } > > } > > > > diff --git a/ovsdb/jsonrpc-server.h b/ovsdb/jsonrpc-server.h > > index 2dc0c78..bf2a2fc 100644 > > --- a/ovsdb/jsonrpc-server.h > > +++ b/ovsdb/jsonrpc-server.h > > @@ -22,7 +22,9 @@ struct ovsdb; > > struct shash; > > struct simap; > > > > -struct ovsdb_jsonrpc_server *ovsdb_jsonrpc_server_create(struct ovsdb *); > > +struct ovsdb_jsonrpc_server *ovsdb_jsonrpc_server_create(void); > > +bool ovsdb_jsonrpc_server_add_db(struct ovsdb_jsonrpc_server *, > > + struct ovsdb *); > > void ovsdb_jsonrpc_server_destroy(struct ovsdb_jsonrpc_server *); > > > > /* Options for a remote. */ > > diff --git a/ovsdb/ovsdb-server.1.in b/ovsdb/ovsdb-server.1.in > > index 1f5be03..b4b6eb6 100644 > > --- a/ovsdb/ovsdb-server.1.in > > +++ b/ovsdb/ovsdb-server.1.in > > @@ -10,7 +10,7 @@ ovsdb\-server \- Open vSwitch database server > > . > > .SH SYNOPSIS > > \fBovsdb\-server\fR > > -[\fIdatabase\fR] > > +[\fIdatabase\fR]\&... > > [\fB\-\-remote=\fIremote\fR]\&... > > [\fB\-\-run=\fIcommand\fR] > > .so lib/daemon-syn.man > > @@ -21,13 +21,13 @@ ovsdb\-server \- Open vSwitch database server > > .so lib/common-syn.man > > . > > .SH DESCRIPTION > > -The \fBovsdb\-server\fR program provides RPC interfaces to an Open > > -vSwitch database (OVSDB). It supports JSON-RPC client connections > > -over active or passive TCP/IP or Unix domain sockets. > > +The \fBovsdb\-server\fR program provides RPC interfaces to one or more > > +Open vSwitch databases (OVSDBs). It supports JSON-RPC client > > +connections over active or passive TCP/IP or Unix domain sockets. > > .PP > > -The OVSDB file may be specified on the command line as \fIdatabase\fR. > > -The default is \fB@DBDIR@/conf.db\fR. The database > > -file must already have been created and initialized using, for > > +Each OVSDB file may be specified on the command line as \fIdatabase\fR. > > +If none is specified, the default is \fB@DBDIR@/conf.db\fR. The database > > +files must already have been created and initialized using, for > > example, \fBovsdb\-tool create\fR. > > . > > .SH OPTIONS > > @@ -40,11 +40,12 @@ Adds \fIremote\fR as a connection method used by > > \fBovsdb\-server\fR. > > .so ovsdb/remote-passive.man > > .so ovsdb/remote-active.man > > . > > -.IP "\fBdb:\fItable\fB,\fIcolumn\fR" > > +.IP "\fBdb:\fR[\fIdb\fB,\fR]\fItable\fB,\fIcolumn\fR" > > Reads additional connection methods from \fIcolumn\fR in all of the > > -rows in \fItable\fR. As the contents of \fIcolumn\fR changes, > > -\fBovsdb\-server\fR also adds and drops connection methods > > -accordingly. > > +rows in \fItable\fR within \fIdb\fR. (If \fBovsdb\-server\fR is > > +providing access to only one database, then \fIdb\fR is optional.) As > > +the contents of \fIcolumn\fR changes, \fBovsdb\-server\fR also adds > > +and drops connection methods accordingly. > > .IP > > If \fIcolumn\fR's type is string or set of strings, then the > > connection methods are taken directly from the column. The connection > > @@ -61,7 +62,7 @@ is mandatory: if it is missing or empty then no > > connection method can > > be configured. > > .IP "\fBmax_backoff\fR (integer)" > > Maximum number of milliseconds to wait between connection attempts. > > -.IP "\fBinactivity_probe\fR (integer) > > +.IP "\fBinactivity_probe\fR (integer)" > > Maximum number of milliseconds of idle time on connection to > > client before sending an inactivity probe message. > > .RE > > @@ -111,9 +112,10 @@ described below. > > These commands are specific to \fBovsdb\-server\fR. > > .IP "\fBexit\fR" > > Causes \fBovsdb\-server\fR to gracefully terminate. > > -.IP "\fBovsdb\-server/compact\fR" > > -Compacts the database in-place. The database is also automatically > > -compacted occasionally. > > +.IP "\fBovsdb\-server/compact\fR [\fIdb\fR]\&..." > > +Compacts each database \fIdb\fR in-place. If no \fIdb\fR is > > +specified, compacts every database in-place. Databases are also > > +automatically compacted occasionally. > > . > > .IP "\fBovsdb\-server/reconnect\fR" > > Makes \fBovsdb\-server\fR drop all of the JSON\-RPC > > diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c > > index 0baf9fc..69548c2 100644 > > --- a/ovsdb/ovsdb-server.c > > +++ b/ovsdb/ovsdb-server.c > > @@ -26,6 +26,7 @@ > > #include "daemon.h" > > #include "dirs.h" > > #include "dummy.h" > > +#include "dynamic-string.h" > > #include "file.h" > > #include "hash.h" > > #include "json.h" > > @@ -56,6 +57,16 @@ > > > > VLOG_DEFINE_THIS_MODULE(ovsdb_server); > > > > +struct db { > > + /* Initialized in main(). */ > > + char *filename; > > + struct ovsdb_file *file; > > + struct ovsdb *db; > > + > > + /* Only used by update_remote_status(). */ > > + struct ovsdb_txn *txn; > > +}; > > + > > /* SSL configuration. */ > > static char *private_key_file; > > static char *certificate_file; > > @@ -66,17 +77,18 @@ static unixctl_cb_func ovsdb_server_exit; > > static unixctl_cb_func ovsdb_server_compact; > > static unixctl_cb_func ovsdb_server_reconnect; > > > > -static void parse_options(int argc, char *argv[], char **file_namep, > > +static void parse_options(int *argc, char **argvp[], > > struct sset *remotes, char **unixctl_pathp, > > char **run_command); > > static void usage(void) NO_RETURN; > > > > static void reconfigure_from_db(struct ovsdb_jsonrpc_server *jsonrpc, > > - const struct ovsdb *db, struct sset > > *remotes); > > + const struct db dbs[], size_t n_dbs, > > + struct sset *remotes); > > > > static void update_remote_status(const struct ovsdb_jsonrpc_server > > *jsonrpc, > > const struct sset *remotes, > > - struct ovsdb *db); > > + struct db dbs[], size_t n_dbs); > > > > int > > main(int argc, char *argv[]) > > @@ -86,34 +98,53 @@ main(int argc, char *argv[]) > > struct unixctl_server *unixctl; > > struct ovsdb_jsonrpc_server *jsonrpc; > > struct sset remotes; > > - struct ovsdb_error *error; > > - struct ovsdb_file *file; > > - struct ovsdb *db; > > struct process *run_process; > > - char *file_name; > > bool exiting; > > int retval; > > long long int status_timer = LLONG_MIN; > > > > + struct db *dbs; > > + int n_dbs; > > + int i; > > + > > proctitle_init(argc, argv); > > set_program_name(argv[0]); > > stress_init_command(); > > signal(SIGPIPE, SIG_IGN); > > process_init(); > > > > - parse_options(argc, argv, &file_name, &remotes, &unixctl_path, > > - &run_command); > > + parse_options(&argc, &argv, &remotes, &unixctl_path, &run_command); > > > > daemonize_start(); > > > > - error = ovsdb_file_open(file_name, false, &db, &file); > > - if (error) { > > - ovs_fatal(0, "%s", ovsdb_error_to_string(error)); > > + n_dbs = MAX(1, argc); > > + dbs = xcalloc(n_dbs + 1, sizeof *dbs); > > + if (argc > 0) { > > + for (i = 0; i < argc; i++) { > > + dbs[i].filename = argv[i]; > > + } > > + } else { > > + dbs[0].filename = xasprintf("%s/conf.db", ovs_dbdir()); > > } > > - free(file_name); > > > > - jsonrpc = ovsdb_jsonrpc_server_create(db); > > - reconfigure_from_db(jsonrpc, db, &remotes); > > + for (i = 0; i < n_dbs; i++) { > > + struct ovsdb_error *error; > > + > > + error = ovsdb_file_open(dbs[i].filename, false, > > + &dbs[i].db, &dbs[i].file); > > + if (error) { > > + ovs_fatal(0, "%s", ovsdb_error_to_string(error)); > > + } > > + } > > + > > + jsonrpc = ovsdb_jsonrpc_server_create(); > > + for (i = 0; i < n_dbs; i++) { > > + if (!ovsdb_jsonrpc_server_add_db(jsonrpc, dbs[i].db)) { > > + ovs_fatal(0, "%s: duplicate database name", > > + dbs[i].db->schema->name); > > + } > > + } > > + reconfigure_from_db(jsonrpc, dbs, n_dbs, &remotes); > > > > retval = unixctl_server_create(unixctl_path, &unixctl); > > if (retval) { > > @@ -146,28 +177,35 @@ main(int argc, char *argv[]) > > } > > > > unixctl_command_register("exit", "", 0, 0, ovsdb_server_exit, > > &exiting); > > - unixctl_command_register("ovsdb-server/compact", "", 0, 0, > > - ovsdb_server_compact, file); > > + unixctl_command_register("ovsdb-server/compact", "", 0, 1, > > + ovsdb_server_compact, dbs); > > unixctl_command_register("ovsdb-server/reconnect", "", 0, 0, > > ovsdb_server_reconnect, jsonrpc); > > > > exiting = false; > > while (!exiting) { > > + int i; > > + > > memory_run(); > > if (memory_should_report()) { > > struct simap usage; > > > > simap_init(&usage); > > ovsdb_jsonrpc_server_get_memory_usage(jsonrpc, &usage); > > - ovsdb_get_memory_usage(db, &usage); > > + for (i = 0; i < n_dbs; i++) { > > + ovsdb_get_memory_usage(dbs[i].db, &usage); > > + } > > memory_report(&usage); > > simap_destroy(&usage); > > } > > > > - reconfigure_from_db(jsonrpc, db, &remotes); > > + reconfigure_from_db(jsonrpc, dbs, n_dbs, &remotes); > > ovsdb_jsonrpc_server_run(jsonrpc); > > unixctl_server_run(unixctl); > > - ovsdb_trigger_run(db, time_msec()); > > + > > + for (i = 0; i < n_dbs; i++) { > > + ovsdb_trigger_run(dbs[i].db, time_msec()); > > + } > > if (run_process && process_exited(run_process)) { > > exiting = true; > > } > > @@ -175,13 +213,15 @@ main(int argc, char *argv[]) > > /* update Manager status(es) every 5 seconds */ > > if (time_msec() >= status_timer) { > > status_timer = time_msec() + 5000; > > - update_remote_status(jsonrpc, &remotes, db); > > + update_remote_status(jsonrpc, &remotes, dbs, n_dbs); > > } > > > > memory_wait(); > > ovsdb_jsonrpc_server_wait(jsonrpc); > > unixctl_server_wait(unixctl); > > - ovsdb_trigger_wait(db, time_msec()); > > + for (i = 0; i < n_dbs; i++) { > > + ovsdb_trigger_wait(dbs[i].db, time_msec()); > > + } > > if (run_process) { > > process_wait(run_process); > > } > > @@ -192,7 +232,9 @@ main(int argc, char *argv[]) > > poll_block(); > > } > > ovsdb_jsonrpc_server_destroy(jsonrpc); > > - ovsdb_destroy(db); > > + for (i = 0; i < n_dbs; i++) { > > + ovsdb_destroy(dbs[i].db); > > + } > > sset_destroy(&remotes); > > unixctl_server_destroy(unixctl); > > > > @@ -207,26 +249,64 @@ main(int argc, char *argv[]) > > return 0; > > } > > > > +static const struct db * > > +find_db(const struct db dbs[], size_t n_dbs, const char *db_name) > > +{ > > + size_t i; > > + > > + for (i = 0; i < n_dbs; i++) { > > + if (!strcmp(dbs[i].db->schema->name, db_name)) { > > + return &dbs[i]; > > + } > > + } > > + > > + return NULL; > > +} > > + > > static void > > -parse_db_column(const struct ovsdb *db, > > +parse_db_column(const struct db dbs[], size_t n_dbs, > > const char *name_, > > + const struct db **dbp, > > const struct ovsdb_table **tablep, > > const struct ovsdb_column **columnp) > > { > > - char *name, *table_name, *column_name; > > + const char *table_name, *column_name; > > const struct ovsdb_column *column; > > const struct ovsdb_table *table; > > + const char *tokens[3]; > > char *save_ptr = NULL; > > + const struct db *db; > > + char *name; > > > > name = xstrdup(name_); > > strtok_r(name, ":", &save_ptr); /* "db:" */ > > - table_name = strtok_r(NULL, ",", &save_ptr); > > - column_name = strtok_r(NULL, ",", &save_ptr); > > - if (!table_name || !column_name) { > > + tokens[0] = strtok_r(NULL, ",", &save_ptr); > > + tokens[1] = strtok_r(NULL, ",", &save_ptr); > > + tokens[2] = strtok_r(NULL, ",", &save_ptr); > > + if (!tokens[0] || !tokens[1]) { > > ovs_fatal(0, "\"%s\": invalid syntax", name_); > > } > > + if (tokens[2]) { > > + const char *db_name = tokens[0]; > > + table_name = tokens[1]; > > + column_name = tokens[2]; > > + > > + db = find_db(dbs, n_dbs, tokens[0]); > > + if (!db) { > > + ovs_fatal(0, "\"%s\": no database named %s", name_, db_name); > > + } > > + } else { > > + if (n_dbs > 1) { > > + ovs_fatal(0, "\"%s\": database name must be specified (because > > " > > + "multiple databases are configured)", name_); > > + } > > + > > + table_name = tokens[0]; > > + column_name = tokens[1]; > > + db = &dbs[0]; > > + } > > > > - table = ovsdb_get_table(db, table_name); > > + table = ovsdb_get_table(db->db, table_name); > > if (!table) { > > ovs_fatal(0, "\"%s\": no table named %s", name_, table_name); > > } > > @@ -238,20 +318,23 @@ parse_db_column(const struct ovsdb *db, > > } > > free(name); > > > > + *dbp = db; > > *columnp = column; > > *tablep = table; > > } > > > > static void > > -parse_db_string_column(const struct ovsdb *db, > > +parse_db_string_column(const struct db dbs[], size_t n_dbs, > > const char *name, > > + const struct db **dbp, > > const struct ovsdb_table **tablep, > > const struct ovsdb_column **columnp) > > { > > const struct ovsdb_column *column; > > const struct ovsdb_table *table; > > + const struct db *db; > > > > - parse_db_column(db, name, &table, &column); > > + parse_db_column(dbs, n_dbs, name, &db, &table, &column); > > > > if (column->type.key.type != OVSDB_TYPE_STRING > > || column->type.value.type != OVSDB_TYPE_VOID) { > > @@ -260,12 +343,13 @@ parse_db_string_column(const struct ovsdb *db, > > name, table->schema->name, column->name); > > } > > > > + *dbp = db; > > *columnp = column; > > *tablep = table; > > } > > > > static OVS_UNUSED const char * > > -query_db_string(const struct ovsdb *db, const char *name) > > +query_db_string(const struct db dbs[], size_t n_dbs, const char *name) > > { > > if (!name || strncmp(name, "db:", 3)) { > > return name; > > @@ -273,8 +357,9 @@ query_db_string(const struct ovsdb *db, const char > > *name) > > const struct ovsdb_column *column; > > const struct ovsdb_table *table; > > const struct ovsdb_row *row; > > + const struct db *db; > > > > - parse_db_string_column(db, name, &table, &column); > > + parse_db_string_column(dbs, n_dbs, name, &db, &table, &column); > > > > HMAP_FOR_EACH (row, hmap_node, &table->rows) { > > const struct ovsdb_datum *datum; > > @@ -493,14 +578,15 @@ add_manager_options(struct shash *remotes, const > > struct ovsdb_row *row) > > } > > > > static void > > -query_db_remotes(const char *name, const struct ovsdb *db, > > +query_db_remotes(const char *name, const struct db dbs[], size_t n_dbs, > > struct shash *remotes) > > { > > const struct ovsdb_column *column; > > const struct ovsdb_table *table; > > const struct ovsdb_row *row; > > + const struct db *db; > > > > - parse_db_column(db, name, &table, &column); > > + parse_db_column(dbs, n_dbs, name, &db, &table, &column); > > > > if (column->type.key.type == OVSDB_TYPE_STRING > > && column->type.value.type == OVSDB_TYPE_VOID) { > > @@ -594,19 +680,20 @@ update_remote_row(const struct ovsdb_row *row, struct > > ovsdb_txn *txn, > > } > > > > static void > > -update_remote_rows(const struct ovsdb *db, struct ovsdb_txn *txn, > > +update_remote_rows(const struct db dbs[], size_t n_dbs, > > const char *remote_name, > > const struct ovsdb_jsonrpc_server *jsonrpc) > > { > > const struct ovsdb_table *table, *ref_table; > > const struct ovsdb_column *column; > > const struct ovsdb_row *row; > > + const struct db *db; > > > > if (strncmp("db:", remote_name, 3)) { > > return; > > } > > > > - parse_db_column(db, remote_name, &table, &column); > > + parse_db_column(dbs, n_dbs, remote_name, &db, &table, &column); > > > > if (column->type.key.type != OVSDB_TYPE_UUID > > || !column->type.key.u.uuid.refTable > > @@ -626,7 +713,7 @@ update_remote_rows(const struct ovsdb *db, struct > > ovsdb_txn *txn, > > > > ref_row = ovsdb_table_get_row(ref_table, &datum->keys[i].uuid); > > if (ref_row) { > > - update_remote_row(ref_row, txn, jsonrpc); > > + update_remote_row(ref_row, db->txn, jsonrpc); > > } > > } > > } > > @@ -634,32 +721,36 @@ update_remote_rows(const struct ovsdb *db, struct > > ovsdb_txn *txn, > > > > static void > > update_remote_status(const struct ovsdb_jsonrpc_server *jsonrpc, > > - const struct sset *remotes, struct ovsdb *db) > > + const struct sset *remotes, > > + struct db dbs[], size_t n_dbs) > > { > > static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); > > - struct ovsdb_txn *txn; > > - const bool durable_txn = false; > > - struct ovsdb_error *error; > > const char *remote; > > + size_t i; > > > > - txn = ovsdb_txn_create(db); > > + for (i = 0; i < n_dbs; i++) { > > + dbs[i].txn = ovsdb_txn_create(dbs[i].db); > > + } > > > > /* Iterate over --remote arguments given on command line. */ > > SSET_FOR_EACH (remote, remotes) { > > - update_remote_rows(db, txn, remote, jsonrpc); > > + update_remote_rows(dbs, n_dbs, remote, jsonrpc); > > } > > > > - error = ovsdb_txn_commit(txn, durable_txn); > > - if (error) { > > - VLOG_ERR_RL(&rl, "Failed to update remote status: %s", > > - ovsdb_error_to_string(error)); > > + for (i = 0; i < n_dbs; i++) { > > + struct ovsdb_error *error = ovsdb_txn_commit(dbs[i].txn, false); > > + if (error) { > > + VLOG_ERR_RL(&rl, "Failed to update remote status: %s", > > + ovsdb_error_to_string(error)); > > + ovsdb_error_destroy(error); > > + } > > } > > } > > > > /* Reconfigures ovsdb-server based on information in the database. */ > > static void > > reconfigure_from_db(struct ovsdb_jsonrpc_server *jsonrpc, > > - const struct ovsdb *db, struct sset *remotes) > > + const struct db dbs[], size_t n_dbs, struct sset > > *remotes) > > { > > struct shash resolved_remotes; > > const char *name; > > @@ -668,7 +759,7 @@ reconfigure_from_db(struct ovsdb_jsonrpc_server > > *jsonrpc, > > shash_init(&resolved_remotes); > > SSET_FOR_EACH (name, remotes) { > > if (!strncmp(name, "db:", 3)) { > > - query_db_remotes(name, db, &resolved_remotes); > > + query_db_remotes(name, dbs, n_dbs, &resolved_remotes); > > } else { > > add_remote(&resolved_remotes, name); > > } > > @@ -677,9 +768,9 @@ reconfigure_from_db(struct ovsdb_jsonrpc_server > > *jsonrpc, > > shash_destroy_free_data(&resolved_remotes); > > > > /* Configure SSL. */ > > - stream_ssl_set_key_and_cert(query_db_string(db, private_key_file), > > - query_db_string(db, certificate_file)); > > - stream_ssl_set_ca_cert_file(query_db_string(db, ca_cert_file), > > + stream_ssl_set_key_and_cert(query_db_string(dbs, n_dbs, > > private_key_file), > > + query_db_string(dbs, n_dbs, > > certificate_file)); > > + stream_ssl_set_ca_cert_file(query_db_string(dbs, n_dbs, ca_cert_file), > > bootstrap_ca_cert); > > } > > > > @@ -694,22 +785,42 @@ ovsdb_server_exit(struct unixctl_conn *conn, int argc > > OVS_UNUSED, > > } > > > > static void > > -ovsdb_server_compact(struct unixctl_conn *conn, int argc OVS_UNUSED, > > - const char *argv[] OVS_UNUSED, void *file_) > > +ovsdb_server_compact(struct unixctl_conn *conn, int argc, > > + const char *argv[], void *dbs_) > > { > > - struct ovsdb_file *file = file_; > > - struct ovsdb_error *error; > > + struct db *dbs = dbs_; > > + struct ds reply; > > + struct db *db; > > + int n = 0; > > > > - VLOG_INFO("compacting database by user request"); > > - error = ovsdb_file_compact(file); > > - if (!error) { > > - unixctl_command_reply(conn, NULL); > > + ds_init(&reply); > > + for (db = dbs; db->filename != NULL; db++) { > > + const char *name = db->db->schema->name; > > + > > + if (argc < 2 || !strcmp(argv[1], name)) { > > + struct ovsdb_error *error; > > + > > + VLOG_INFO("compacting %s database by user request", name); > > + > > + error = ovsdb_file_compact(db->file); > > + if (error) { > > + char *s = ovsdb_error_to_string(error); > > + ds_put_format(&reply, "%s\n", s); > > + free(s); > > + } > > + > > + n++; > > + } > > + } > > + > > + if (!n) { > > + unixctl_command_reply_error(conn, "no database by that name"); > > + } else if (reply.length) { > > + unixctl_command_reply_error(conn, ds_cstr(&reply)); > > } else { > > - char *s = ovsdb_error_to_string(error); > > - ovsdb_error_destroy(error); > > - unixctl_command_reply_error(conn, s); > > - free(s); > > + unixctl_command_reply(conn, NULL); > > } > > + ds_destroy(&reply); > > } > > > > /* "ovsdb-server/reconnect": makes ovsdb-server drop all of its JSON-RPC > > @@ -725,9 +836,8 @@ ovsdb_server_reconnect(struct unixctl_conn *conn, int > > argc OVS_UNUSED, > > } > > > > static void > > -parse_options(int argc, char *argv[], char **file_namep, > > - struct sset *remotes, char **unixctl_pathp, > > - char **run_command) > > +parse_options(int *argcp, char **argvp[], > > + struct sset *remotes, char **unixctl_pathp, char > > **run_command) > > { > > enum { > > OPT_REMOTE = UCHAR_MAX + 1, > > @@ -756,6 +866,8 @@ parse_options(int argc, char *argv[], char **file_namep, > > {NULL, 0, NULL, 0}, > > }; > > char *short_options = long_options_to_short_options(long_options); > > + int argc = *argcp; > > + char **argv = *argvp; > > > > sset_init(remotes); > > for (;;) { > > @@ -821,31 +933,18 @@ parse_options(int argc, char *argv[], char > > **file_namep, > > } > > free(short_options); > > > > - argc -= optind; > > - argv += optind; > > - > > - switch (argc) { > > - case 0: > > - *file_namep = xasprintf("%s/conf.db", ovs_dbdir()); > > - break; > > - > > - case 1: > > - *file_namep = xstrdup(argv[0]); > > - break; > > - > > - default: > > - ovs_fatal(0, "database file is only non-option argument; " > > - "use --help for usage"); > > - } > > + *argcp -= optind; > > + *argvp += optind; > > } > > > > static void > > usage(void) > > { > > printf("%s: Open vSwitch database server\n" > > - "usage: %s [OPTIONS] DATABASE\n" > > - "where DATABASE is a database file in ovsdb format.\n", > > - program_name, program_name); > > + "usage: %s [OPTIONS] [DATABASE...]\n" > > + "where each DATABASE is a database file in ovsdb format.\n" > > + "The default DATABASE, if none is given, is\n%s/conf.db.\n", > > + program_name, program_name, ovs_dbdir()); > > printf("\nJSON-RPC options (may be specified any number of times):\n" > > " --remote=REMOTE connect or listen to REMOTE\n"); > > stream_usage("JSON-RPC", true, true, true); > > diff --git a/ovsdb/server.c b/ovsdb/server.c > > index 7cd4263..ac2aa29 100644 > > --- a/ovsdb/server.c > > +++ b/ovsdb/server.c > > @@ -1,4 +1,4 @@ > > -/* Copyright (c) 2011 Nicira, Inc. > > +/* Copyright (c) 2011, 2012 Nicira, Inc. > > * > > * Licensed under the Apache License, Version 2.0 (the "License"); > > * you may not use this file except in compliance with the License. > > @@ -20,12 +20,13 @@ > > #include <assert.h> > > > > #include "hash.h" > > +#include "ovsdb.h" > > > > -/* Initializes 'session' as a session that operates on 'db'. */ > > +/* Initializes 'session' as a session within 'server'. */ > > void > > -ovsdb_session_init(struct ovsdb_session *session, struct ovsdb *db) > > +ovsdb_session_init(struct ovsdb_session *session, struct ovsdb_server > > *server) > > { > > - session->db = db; > > + session->server = server; > > list_init(&session->completions); > > hmap_init(&session->waiters); > > } > > @@ -113,18 +114,31 @@ ovsdb_lock_waiter_is_owner(const struct > > ovsdb_lock_waiter *waiter) > > return waiter->lock && waiter == ovsdb_lock_get_owner(waiter->lock); > > } > > > > -/* Initializes 'server' as a server that operates on 'db'. */ > > +/* Initializes 'server'. > > + * > > + * The caller must call ovsdb_server_add_db() for each database to which > > + * 'server' should provide access. */ > > void > > -ovsdb_server_init(struct ovsdb_server *server, struct ovsdb *db) > > +ovsdb_server_init(struct ovsdb_server *server) > > { > > - server->db = db; > > + shash_init(&server->dbs); > > hmap_init(&server->locks); > > } > > > > +/* Adds 'db' to the set of databases served out by 'server'. Returns true > > if > > + * successful, false if 'db''s name is the same as some database already in > > + * 'server'. */ > > +bool > > +ovsdb_server_add_db(struct ovsdb_server *server, struct ovsdb *db) > > +{ > > + return shash_add_once(&server->dbs, db->schema->name, db); > > +} > > + > > /* Destroys 'server'. */ > > void > > ovsdb_server_destroy(struct ovsdb_server *server) > > { > > + shash_destroy(&server->dbs); > > hmap_destroy(&server->locks); > > } > > > > diff --git a/ovsdb/server.h b/ovsdb/server.h > > index e073850..561f01e 100644 > > --- a/ovsdb/server.h > > +++ b/ovsdb/server.h > > @@ -18,17 +18,21 @@ > > > > #include "hmap.h" > > #include "list.h" > > +#include "shash.h" > > + > > +struct ovsdb; > > +struct ovsdb_server; > > > > /* Abstract representation of an OVSDB client connection, not tied to any > > * particular network protocol. Protocol implementations > > * (e.g. jsonrpc-server.c) embed this in a larger data structure. */ > > struct ovsdb_session { > > - struct ovsdb *db; > > + struct ovsdb_server *server; > > struct list completions; /* Completed triggers. */ > > struct hmap waiters; /* "ovsdb_lock_waiter *"s by lock name. */ > > }; > > > > -void ovsdb_session_init(struct ovsdb_session *, struct ovsdb *); > > +void ovsdb_session_init(struct ovsdb_session *, struct ovsdb_server *); > > void ovsdb_session_destroy(struct ovsdb_session *); > > > > struct ovsdb_lock_waiter *ovsdb_session_get_lock_waiter( > > @@ -73,11 +77,12 @@ bool ovsdb_lock_waiter_is_owner(const struct > > ovsdb_lock_waiter *); > > * network protocol. Protocol implementations (e.g. jsonrpc-server.c) > > embed > > * this in a larger data structure. */ > > struct ovsdb_server { > > - struct ovsdb *db; > > + struct shash dbs; /* Maps from a db name to a "struct ovsdb *". */ > > struct hmap locks; /* Contains "struct ovsdb_lock"s indexed by > > name. */ > > }; > > > > -void ovsdb_server_init(struct ovsdb_server *, struct ovsdb *); > > +void ovsdb_server_init(struct ovsdb_server *); > > +bool ovsdb_server_add_db(struct ovsdb_server *, struct ovsdb *); > > void ovsdb_server_destroy(struct ovsdb_server *); > > > > struct ovsdb_lock_waiter *ovsdb_server_lock(struct ovsdb_server *, > > diff --git a/ovsdb/trigger.c b/ovsdb/trigger.c > > index 6ae1f51..a93b844 100644 > > --- a/ovsdb/trigger.c > > +++ b/ovsdb/trigger.c > > @@ -1,4 +1,4 @@ > > -/* Copyright (c) 2009, 2010, 2011 Nicira, Inc. > > +/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc. > > * > > * Licensed under the Apache License, Version 2.0 (the "License"); > > * you may not use this file except in compliance with the License. > > @@ -30,12 +30,13 @@ static bool ovsdb_trigger_try(struct ovsdb_trigger *, > > long long int now); > > static void ovsdb_trigger_complete(struct ovsdb_trigger *); > > > > void > > -ovsdb_trigger_init(struct ovsdb_session *session, > > +ovsdb_trigger_init(struct ovsdb_session *session, struct ovsdb *db, > > struct ovsdb_trigger *trigger, > > struct json *request, long long int now) > > { > > trigger->session = session; > > - list_push_back(&trigger->session->db->triggers, &trigger->node); > > + trigger->db = db; > > + list_push_back(&trigger->db->triggers, &trigger->node); > > trigger->request = request; > > trigger->result = NULL; > > trigger->created = now; > > @@ -110,7 +111,7 @@ ovsdb_trigger_wait(struct ovsdb *db, long long int now) > > static bool > > ovsdb_trigger_try(struct ovsdb_trigger *t, long long int now) > > { > > - t->result = ovsdb_execute(t->session->db, t->session, > > + t->result = ovsdb_execute(t->db, t->session, > > t->request, now - t->created, > > &t->timeout_msec); > > if (t->result) { > > ovsdb_trigger_complete(t); > > diff --git a/ovsdb/trigger.h b/ovsdb/trigger.h > > index 1d47f3f..f686b15 100644 > > --- a/ovsdb/trigger.h > > +++ b/ovsdb/trigger.h > > @@ -1,4 +1,4 @@ > > -/* Copyright (c) 2009, 2011 Nicira, Inc. > > +/* Copyright (c) 2009, 2011, 2012 Nicira, Inc. > > * > > * Licensed under the Apache License, Version 2.0 (the "License"); > > * you may not use this file except in compliance with the License. > > @@ -22,7 +22,8 @@ struct ovsdb; > > > > struct ovsdb_trigger { > > struct ovsdb_session *session; /* Session that owns this trigger. */ > > - struct list node; /* !result: in session->db->triggers; > > + struct ovsdb *db; /* Database on which trigger acts. */ > > + struct list node; /* !result: in db->triggers; > > * result: in session->completions. */ > > struct json *request; /* Database request. */ > > struct json *result; /* Result (null if none yet). */ > > @@ -30,7 +31,8 @@ struct ovsdb_trigger { > > long long int timeout_msec; /* Max wait duration. */ > > }; > > > > -void ovsdb_trigger_init(struct ovsdb_session *, struct ovsdb_trigger *, > > +void ovsdb_trigger_init(struct ovsdb_session *, struct ovsdb *, > > + struct ovsdb_trigger *, > > struct json *request, long long int now); > > void ovsdb_trigger_destroy(struct ovsdb_trigger *); > > > > diff --git a/tests/ovsdb-server.at b/tests/ovsdb-server.at > > index b0a3377..f787f5a 100644 > > --- a/tests/ovsdb-server.at > > +++ b/tests/ovsdb-server.at > > @@ -142,12 +142,15 @@ AT_CLEANUP > > > > AT_SETUP([database multiplexing implementation]) > > AT_KEYWORDS([ovsdb server positive]) > > -ordinal_schema > schema > > -AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore]) > > -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid > > --unixctl="`pwd`"/unixctl --remote=punix:socket db], [0], [ignore], > > [ignore]) > > +ordinal_schema > schema1 > > +constraint_schema > schema2 > > +AT_CHECK([ovsdb-tool create db1 schema1], [0], [ignore], [ignore]) > > +AT_CHECK([ovsdb-tool create db2 schema2], [0], [ignore], [ignore]) > > +AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid > > --unixctl="`pwd`"/unixctl --remote=punix:socket db1 db2], [0], [ignore], > > [ignore]) > > AT_CHECK( > > [[ovsdb-client list-dbs unix:socket]], > > - [0], [ordinals > > + [0], [constraints > > +ordinals > > ], [ignore], [test ! -e pid || kill `cat pid`]) > > AT_CHECK( > > [[test-jsonrpc request unix:socket get_schema [\"nonexistent\"]]], [0], > > @@ -158,37 +161,67 @@ AT_CLEANUP > > > > AT_SETUP([--remote=db: implementation]) > > AT_KEYWORDS([ovsdb server positive]) > > +OVS_RUNDIR=`pwd`; export OVS_RUNDIR > > +OVS_LOGDIR=`pwd`; export OVS_LOGDIR > > AT_DATA([schema], > > [[{"name": "mydb", > > "tables": { > > + "Root": { > > + "columns": { > > + "managers": { > > + "type": { > > + "key": "string", > > + "min": 0, > > + "max": "unlimited"}}, > > + "manager_options": { > > + "type": { > > + "key": {"type": "uuid", "refTable": "Manager"}, > > + "min": 0, > > + "max": "unlimited"}}}}, > > "Manager": { > > "columns": { > > - "manager": {"type": "string"}}}}} > > + "target": { > > + "type": "string"}, > > + "is_connected": { > > + "type": { > > + "key": "boolean", > > + "min": 0, > > + "max": 1}}}}}} > > ]]) > > AT_CHECK([ovsdb-tool create db schema], [0], [ignore], [ignore]) > > AT_CHECK( > > [[ovsdb-tool transact db \ > > '["mydb", > > {"op": "insert", > > + "table": "Root", > > + "row": { > > + "managers": "punix:socket1", > > + "manager_options": ["set", [["named-uuid", "x"]]]}}, > > + {"op": "insert", > > "table": "Manager", > > - "row": {"manager": "punix:socket"}}]']], [0], [ignore], [ignore]) > > -AT_CHECK([ovsdb-server --detach --no-chdir --pidfile="`pwd`"/pid > > --remote=db:Manager,manager --unixctl="`pwd`"/unixctl db], [0], [ignore], > > [ignore]) > > + "uuid-name": "x", > > + "row": {"target": "punix:socket2"}}]']], [0], [ignore], [ignore]) > > +ON_EXIT([kill `cat ovsdb-server.pid`]) > > +AT_CHECK([ovsdb-server --enable-dummy --detach --no-chdir --pidfile > > --remote=db:Root,managers --remote=db:Root,manager_options --log-file db], > > [0], [ignore], [ignore]) > > +for i in 1 2 3 4 5 6; do ovs-appctl -t ovsdb-server time/warp 1000; done > > AT_CHECK( > > - [[ovsdb-client transact unix:socket \ > > + [[ovsdb-client transact unix:socket1 \ > > '["mydb", > > {"op": "select", > > + "table": "Root", > > + "where": [], > > + "columns": ["managers"]}, > > + {"op": "select", > > "table": "Manager", > > "where": [], > > - "columns": ["manager"]}]']], > > - [0], [stdout], [ignore], [test ! -e pid || kill `cat pid`]) > > + "columns": ["target", "is_connected"]}]']], > > + [0], [stdout], [ignore]) > > AT_CHECK( > > [perl $srcdir/uuidfilt.pl stdout], > > [0], > > - [[[{"rows":[{"manager":"punix:socket"}]}] > > + > > [[[{"rows":[{"managers":"punix:socket1"}]},{"rows":[{"is_connected":false,"target":"punix:socket2"}]}] > > ]], > > - [ignore], > > - [test ! -e pid || kill `cat pid`]) > > -OVSDB_SERVER_SHUTDOWN > > + [ignore]) > > AT_CLEANUP > > > > AT_SETUP([SSL db: implementation]) > > diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c > > index a1ad2cb..d448109 100644 > > --- a/tests/test-ovsdb.c > > +++ b/tests/test-ovsdb.c > > @@ -1294,6 +1294,7 @@ do_trigger(int argc OVS_UNUSED, char *argv[]) > > { > > struct ovsdb_schema *schema; > > struct ovsdb_session session; > > + struct ovsdb_server server; > > struct json *json; > > struct ovsdb *db; > > long long int now; > > @@ -1306,7 +1307,9 @@ do_trigger(int argc OVS_UNUSED, char *argv[]) > > json_destroy(json); > > db = ovsdb_create(schema); > > > > - ovsdb_session_init(&session, db); > > + ovsdb_server_init(&server); > > + ovsdb_server_add_db(&server, db); > > + ovsdb_session_init(&session, &server); > > > > now = 0; > > number = 0; > > @@ -1321,7 +1324,7 @@ do_trigger(int argc OVS_UNUSED, char *argv[]) > > json_destroy(params); > > } else { > > struct test_trigger *t = xmalloc(sizeof *t); > > - ovsdb_trigger_init(&session, &t->trigger, params, now); > > + ovsdb_trigger_init(&session, db, &t->trigger, params, now); > > t->number = number++; > > if (ovsdb_trigger_is_complete(&t->trigger)) { > > do_trigger_dump(t, now, "immediate"); > > @@ -1342,6 +1345,7 @@ do_trigger(int argc OVS_UNUSED, char *argv[]) > > poll_block(); > > } > > > > + ovsdb_server_destroy(&server); > > ovsdb_destroy(db); > > } > > > > diff --git a/utilities/ovs-ctl.8 b/utilities/ovs-ctl.8 > > index c730778..22db06b 100644 > > --- a/utilities/ovs-ctl.8 > > +++ b/utilities/ovs-ctl.8 > > @@ -223,6 +223,12 @@ Overrides the file name for the Unix domain socket > > used to connect to > > .IP "\fB\-\-db\-schema=\fIschema\fR" > > Overrides the file name for the OVS database schema. > > . > > +.IP "\fB\-\-extra-dbs=\fIfile\fR" > > +Adds \fIfile\fR as an extra database for \fBovsdb\-server\fR to serve > > +out. Multiple space-separated file names may also be specified. > > +\fIfile\fR should begin with \fB/\fR; if it does not, then it will be > > +taken as relative to \fIdbdir\fR. > > +. > > .SH "The ``stop'' command" > > . > > .PP > > diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in > > index 674c3c3..2aa6398 100755 > > --- a/utilities/ovs-ctl.in > > +++ b/utilities/ovs-ctl.in > > @@ -189,9 +189,23 @@ start_ovsdb () { > > > > # Start ovsdb-server. > > set ovsdb-server "$DB_FILE" > > + for db in $EXTRA_DBS; do > > + case $db in > > + /*) ;; > > + *) db=$dbdir/$db ;; > > + esac > > + > > + if test ! -f "$db"; then > > + log_warning_msg "$db (from \$EXTRA_DBS) does not exist." > > + elif ovsdb-tool db-version "$db" >/dev/null; then > > + set "$@" "$db" > > + else > > + log_warning_msg "$db (from \$EXTRA_DBS) cannot be read as > > a database (see error message above)" > > + fi > > + done > > set "$@" -vconsole:emer -vsyslog:err -vfile:info > > set "$@" --remote=punix:"$DB_SOCK" > > - set "$@" --remote=db:Open_vSwitch,manager_options > > + set "$@" --remote=db:Open_vSwitch,Open_vSwitch,manager_options > > set "$@" --private-key=db:SSL,private_key > > set "$@" --certificate=db:SSL,certificate > > set "$@" --bootstrap-ca-cert=db:SSL,ca_cert > > @@ -406,6 +420,7 @@ set_defaults () { > > DB_FILE=$dbdir/conf.db > > DB_SOCK=$rundir/db.sock > > DB_SCHEMA=$datadir/vswitch.ovsschema > > + EXTRA_DBS= > > > > PROTOCOL=gre > > DPORT= > > -- > > 1.7.2.5 > > > > _______________________________________________ > > dev mailing list > > dev@openvswitch.org > > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev