+\f
+static struct json *
+sset_to_json(const struct sset *sset)
+{
+ struct json *array;
+ const char *s;
+
+ array = json_array_create_empty();
+ SSET_FOR_EACH (s, sset) {
+ json_array_add(array, json_string_create(s));
+ }
+ return array;
+}
+
+/* Truncates and replaces the contents of 'config_file' by a representation of
+ * 'remotes' and 'db_filenames'. */
+static void
+save_config__(FILE *config_file, const struct sset *remotes,
+ const struct sset *db_filenames)
+{
+ struct json *obj;
+ char *s;
+
+ if (ftruncate(fileno(config_file), 0) == -1) {
+ VLOG_FATAL("failed to truncate temporary file (%s)",
+ ovs_strerror(errno));
+ }
+
+ obj = json_object_create();
+ json_object_put(obj, "remotes", sset_to_json(remotes));
+ json_object_put(obj, "db_filenames", sset_to_json(db_filenames));
+ s = json_to_string(obj, 0);
+ json_destroy(obj);
+
+ if (fseek(config_file, 0, SEEK_SET) != 0
+ || fputs(s, config_file) == EOF
+ || fflush(config_file) == EOF) {
+ VLOG_FATAL("failed to write temporary file (%s)", ovs_strerror(errno));
+ }
+ free(s);
+}
+
+/* Truncates and replaces the contents of 'config_file' by a representation of
+ * 'config'. */
+static void
+save_config(struct server_config *config)
+{
+ struct sset db_filenames;
+ struct shash_node *node;
+
+ sset_init(&db_filenames);
+ SHASH_FOR_EACH (node, config->all_dbs) {
+ struct db *db = node->data;
+ sset_add(&db_filenames, db->filename);
+ }
+
+ save_config__(config->config_tmpfile, config->remotes, &db_filenames);
+
+ sset_destroy(&db_filenames);
+}
+
+static void
+sset_from_json(struct sset *sset, const struct json *array)
+{
+ size_t i;
+
+ sset_clear(sset);
+
+ ovs_assert(array->type == JSON_ARRAY);
+ for (i = 0; i < array->u.array.n; i++) {
+ const struct json *elem = array->u.array.elems[i];
+ sset_add(sset, json_string(elem));
+ }
+}
+
+/* Clears and replaces 'remotes' and 'dbnames' by a configuration read from
+ * 'config_file', which must have been previously written by save_config(). */
+static void
+load_config(FILE *config_file, struct sset *remotes, struct sset *db_filenames)
+{
+ struct json *json;
+
+ if (fseek(config_file, 0, SEEK_SET) != 0) {
+ VLOG_FATAL("seek failed in temporary file (%s)", ovs_strerror(errno));
+ }
+ json = json_from_stream(config_file);
+ if (json->type == JSON_STRING) {
+ VLOG_FATAL("reading json failed (%s)", json_string(json));
+ }
+ ovs_assert(json->type == JSON_OBJECT);
+
+ sset_from_json(remotes, shash_find_data(json_object(json), "remotes"));
+ sset_from_json(db_filenames,
+ shash_find_data(json_object(json), "db_filenames"));
+ json_destroy(json);
+}