On Thu, Jun 13, 2013 at 8:29 AM, Gurucharan Shetty <span dir="ltr">&lt;<a href="mailto:shettyg@nicira.com" target="_blank">shettyg@nicira.com</a>&gt;</span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="im">On Wed, Jun 12, 2013 at 5:10 PM, Ben Pfaff <span dir="ltr">&lt;<a href="mailto:blp@nicira.com" target="_blank">blp@nicira.com</a>&gt;</span> wrote:<br></div><div class="gmail_quote"><div class="im"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

---<br>
This is unpolished but it shows the approach I have in mind.<br>
Sending out for comments on the approach.<br></blockquote></div><div>I am fine with the approach. The two negatives I see with this:</div><div>* If /tmp is cleaned up routinely, we will loose the information. If we decide to put this in /etc/openvswitch, it may look a little dirty when program is abnormally terminated.</div>
</div></blockquote><div>This concern is probably invalid. I don&#39;t think there is a possibility that a second file with the same name will be created if the first one is deleted.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote">
<div>* If we have multiple run time data, (ex: add/remove databases) we may need multiple files.</div><div><br></div><div>If you are fine with this, I am fine with it.</div><div><div class="h5"><div><br></div><div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c<br>
index 20e1964..d87360a 100644<br>
--- a/ovsdb/ovsdb-server.c<br>
+++ b/ovsdb/ovsdb-server.c<br>
@@ -81,8 +81,14 @@ struct add_remote_aux {<br>
     struct sset *remotes;<br>
     struct db *dbs;<br>
     size_t n_dbs;<br>
+    FILE *config_tmpfile;<br>
 };<br>
 static unixctl_cb_func ovsdb_server_add_remote;<br>
+<br>
+struct remove_remote_aux {<br>
+    struct sset *remotes;<br>
+    FILE *config_tmpfile;<br>
+};<br>
 static unixctl_cb_func ovsdb_server_remove_remote;<br>
 static unixctl_cb_func ovsdb_server_list_remotes;<br>
<br>
@@ -99,6 +105,9 @@ static void update_remote_status(const struct ovsdb_jsonrpc_server *jsonrpc,<br>
                                  const struct sset *remotes,<br>
                                  struct db dbs[], size_t n_dbs);<br>
<br>
+static void save_config(FILE *config_file, const struct sset *);<br>
+static void load_config(FILE *config_file, struct sset *);<br>
+<br>
 int<br>
 main(int argc, char *argv[])<br>
 {<br>
@@ -112,6 +121,8 @@ main(int argc, char *argv[])<br>
     int retval;<br>
     long long int status_timer = LLONG_MIN;<br>
     struct add_remote_aux add_remote_aux;<br>
+    struct remove_remote_aux remove_remote_aux;<br>
+    FILE *config_tmpfile;<br>
<br>
     struct db *dbs;<br>
     int n_dbs;<br>
@@ -125,7 +136,14 @@ main(int argc, char *argv[])<br>
<br>
     parse_options(&amp;argc, &amp;argv, &amp;remotes, &amp;unixctl_path, &amp;run_command);<br>
<br>
+    config_tmpfile = tmpfile();<br>
+    if (!config_tmpfile) {<br>
+        ovs_fatal(errno, &quot;failed to create temporary file&quot;);<br>
+    }<br>
+<br>
+    save_config(config_tmpfile, &amp;remotes);<br>
     daemonize_start();<br>
+    load_config(config_tmpfile, &amp;remotes);<br>
<br>
     n_dbs = MAX(1, argc);<br>
     dbs = xcalloc(n_dbs + 1, sizeof *dbs);<br>
@@ -195,10 +213,13 @@ main(int argc, char *argv[])<br>
     add_remote_aux.remotes = &amp;remotes;<br>
     add_remote_aux.dbs = dbs;<br>
     add_remote_aux.n_dbs = n_dbs;<br>
+    add_remote_aux.config_tmpfile = config_tmpfile;<br>
     unixctl_command_register(&quot;ovsdb-server/add-remote&quot;, &quot;REMOTE&quot;, 1, 1,<br>
                              ovsdb_server_add_remote, &amp;add_remote_aux);<br>
+    remove_remote_aux.remotes = &amp;remotes;<br>
+    remove_remote_aux.config_tmpfile = config_tmpfile;<br>
     unixctl_command_register(&quot;ovsdb-server/remove-remote&quot;, &quot;REMOTE&quot;, 1, 1,<br>
-                             ovsdb_server_remove_remote, &amp;remotes);<br>
+                             ovsdb_server_remove_remote, &amp;remove_remote_aux);<br>
     unixctl_command_register(&quot;ovsdb-server/list-remotes&quot;, &quot;&quot;, 0, 0,<br>
                              ovsdb_server_list_remotes, &amp;remotes);<br>
<br>
@@ -922,7 +943,9 @@ ovsdb_server_add_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,<br>
               : parse_db_column(aux-&gt;dbs, aux-&gt;n_dbs, remote,<br>
                                 &amp;db, &amp;table, &amp;column));<br>
     if (!retval) {<br>
-        sset_add(aux-&gt;remotes, remote);<br>
+        if (sset_add(aux-&gt;remotes, remote)) {<br>
+            save_config(aux-&gt;config_tmpfile, aux-&gt;remotes);<br>
+        }<br>
         unixctl_command_reply(conn, NULL);<br>
     } else {<br>
         unixctl_command_reply_error(conn, retval);<br>
@@ -934,14 +957,15 @@ ovsdb_server_add_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,<br>
  * that ovsdb-server services. */<br>
 static void<br>
 ovsdb_server_remove_remote(struct unixctl_conn *conn, int argc OVS_UNUSED,<br>
-                           const char *argv[], void *remotes_)<br>
+                           const char *argv[], void *aux_)<br>
 {<br>
-    struct sset *remotes = remotes_;<br>
+    struct remove_remote_aux *aux = aux_;<br>
     struct sset_node *node;<br>
<br>
-    node = sset_find(remotes, argv[1]);<br>
+    node = sset_find(aux-&gt;remotes, argv[1]);<br>
     if (node) {<br>
-        sset_delete(remotes, node);<br>
+        sset_delete(aux-&gt;remotes, node);<br>
+        save_config(aux-&gt;config_tmpfile, aux-&gt;remotes);<br>
         unixctl_command_reply(conn, NULL);<br>
     } else {<br>
         unixctl_command_reply_error(conn, &quot;no such remote&quot;);<br>
@@ -1092,3 +1116,48 @@ usage(void)<br>
     leak_checker_usage();<br>
     exit(EXIT_SUCCESS);<br>
 }<br>
+ <br>
+static void<br>
+save_config(FILE *config_file, const struct sset *remotes)<br>
+{<br>
+    const char *remote;<br>
+    struct json *json;<br>
+    char *s;<br>
+<br>
+    if (ftruncate(fileno(config_file), 0) == -1) {<br>
+        ovs_fatal(errno, &quot;truncate failed&quot;);<br>
+    }<br>
+<br>
+    json = json_array_create_empty();<br>
+    SSET_FOR_EACH (remote, remotes) {<br>
+        json_array_add(json, json_string_create(remote));<br>
+    }<br>
+    s = json_to_string(json, 0);<br>
+    json_destroy(json);<br>
+<br>
+    if (fputs(s, config_file) == EOF || fflush(config_file) == EOF) {<br>
+        ovs_fatal(errno, &quot;write failed&quot;);<br>
+    }<br>
+    free(s);<br>
+}<br>
+<br>
+static void<br>
+load_config(FILE *config_file, struct sset *remotes)<br>
+{<br>
+    struct json *json;<br>
+    size_t i;<br>
+<br>
+    sset_clear(remotes);<br>
+<br>
+    rewind(config_file);<br>
+    json = json_from_stream(config_file);<br>
+    if (json-&gt;type == JSON_STRING) {<br>
+        ovs_fatal(0, &quot;reading json failed (%s)&quot;, json_string(json));<br>
+    }<br>
+    ovs_assert(json-&gt;type == JSON_ARRAY);<br>
+    for (i = 0; i &lt; json-&gt;u.array.n; i++) {<br>
+        const struct json *remote = json-&gt;u.array.elems[i];<br>
+        sset_add(remotes, json_string(remote));<br>
+    }<br>
+    json_destroy(json);<br>
+}<br>
<span><font color="#888888">--<br>
1.7.2.5<br>
<br>
_______________________________________________<br>
dev mailing list<br>
<a href="mailto:dev@openvswitch.org" target="_blank">dev@openvswitch.org</a><br>
<a href="http://openvswitch.org/mailman/listinfo/dev" target="_blank">http://openvswitch.org/mailman/listinfo/dev</a><br>
</font></span></blockquote></div></div></div><br>
</blockquote></div><br>