ovsdb: Implement garbage collection.
[sliver-openvswitch.git] / utilities / ovs-vsctl.c
index e5e03f7..80c9048 100644 (file)
@@ -1035,12 +1035,6 @@ cmd_emer_reset(struct vsctl_context *ctx)
     const struct ovsrec_bridge *br;
     const struct ovsrec_port *port;
     const struct ovsrec_interface *iface;
-    const struct ovsrec_mirror *mirror, *next_mirror;
-    const struct ovsrec_controller *ctrl, *next_ctrl;
-    const struct ovsrec_manager *mgr, *next_mgr;
-    const struct ovsrec_netflow *nf, *next_nf;
-    const struct ovsrec_ssl *ssl, *next_ssl;
-    const struct ovsrec_sflow *sflow, *next_sflow;
 
     /* Reset the Open_vSwitch table. */
     ovsrec_open_vswitch_set_manager_options(ctx->ovs, NULL, 0);
@@ -1084,30 +1078,6 @@ cmd_emer_reset(struct vsctl_context *ctx)
         ovsrec_interface_set_ingress_policing_rate(iface, 0);
         ovsrec_interface_set_ingress_policing_burst(iface, 0);
     }
-
-    OVSREC_MIRROR_FOR_EACH_SAFE (mirror, next_mirror, idl) {
-        ovsrec_mirror_delete(mirror);
-    }
-
-    OVSREC_CONTROLLER_FOR_EACH_SAFE (ctrl, next_ctrl, idl) {
-        ovsrec_controller_delete(ctrl);
-    }
-
-    OVSREC_MANAGER_FOR_EACH_SAFE (mgr, next_mgr, idl) {
-        ovsrec_manager_delete(mgr);
-    }
-
-    OVSREC_NETFLOW_FOR_EACH_SAFE (nf, next_nf, idl) {
-        ovsrec_netflow_delete(nf);
-    }
-
-    OVSREC_SSL_FOR_EACH_SAFE (ssl, next_ssl, idl) {
-        ovsrec_ssl_delete(ssl);
-    }
-
-    OVSREC_SFLOW_FOR_EACH_SAFE (sflow, next_sflow, idl) {
-        ovsrec_sflow_delete(sflow);
-    }
 }
 
 static void
@@ -1218,18 +1188,8 @@ cmd_add_br(struct vsctl_context *ctx)
 }
 
 static void
-del_port(struct vsctl_info *info, struct vsctl_port *port)
+del_port(struct vsctl_port *port)
 {
-    struct shash_node *node;
-
-    SHASH_FOR_EACH (node, &info->ifaces) {
-        struct vsctl_iface *iface = node->data;
-        if (iface->port == port) {
-            ovsrec_interface_delete(iface->iface_cfg);
-        }
-    }
-    ovsrec_port_delete(port->port_cfg);
-
     bridge_delete_port((port->bridge->parent
                         ? port->bridge->parent->br_cfg
                         : port->bridge->br_cfg), port->port_cfg);
@@ -1245,18 +1205,18 @@ cmd_del_br(struct vsctl_context *ctx)
     get_info(ctx, &info);
     bridge = find_bridge(&info, ctx->argv[1], must_exist);
     if (bridge) {
-        struct shash_node *node;
-
-        SHASH_FOR_EACH (node, &info.ports) {
-            struct vsctl_port *port = node->data;
-            if (port->bridge == bridge || port->bridge->parent == bridge
-                || !strcmp(port->port_cfg->name, bridge->name)) {
-                del_port(&info, port);
-            }
-        }
         if (bridge->br_cfg) {
-            ovsrec_bridge_delete(bridge->br_cfg);
             ovs_delete_bridge(ctx->ovs, bridge->br_cfg);
+        } else {
+            struct shash_node *node;
+
+            SHASH_FOR_EACH (node, &info.ports) {
+                struct vsctl_port *port = node->data;
+                if (port->bridge == bridge || port->bridge->parent == bridge
+                    || !strcmp(port->port_cfg->name, bridge->name)) {
+                    del_port(port);
+                }
+            }
         }
     }
     free_info(&info);
@@ -1641,7 +1601,7 @@ cmd_del_port(struct vsctl_context *ctx)
             }
         }
 
-        del_port(&info, port);
+        del_port(port);
     }
 
     free_info(&info);
@@ -1773,17 +1733,6 @@ cmd_get_controller(struct vsctl_context *ctx)
     free_info(&info);
 }
 
-static void
-delete_controllers(struct ovsrec_controller **controllers,
-                   size_t n_controllers)
-{
-    size_t i;
-
-    for (i = 0; i < n_controllers; i++) {
-        ovsrec_controller_delete(controllers[i]);
-    }
-}
-
 static void
 cmd_del_controller(struct vsctl_context *ctx)
 {
@@ -1791,13 +1740,9 @@ cmd_del_controller(struct vsctl_context *ctx)
     struct vsctl_bridge *br;
 
     get_info(ctx, &info);
-    br = find_real_bridge(&info, ctx->argv[1], true);
-    verify_controllers(br->br_cfg);
 
-    if (br->ctrl) {
-        delete_controllers(br->ctrl, br->n_ctrl);
-        ovsrec_bridge_set_controller(br->br_cfg, NULL, 0);
-    }
+    br = find_real_bridge(&info, ctx->argv[1], true);
+    ovsrec_bridge_set_controller(br->br_cfg, NULL, 0);
 
     free_info(&info);
 }
@@ -1827,9 +1772,6 @@ cmd_set_controller(struct vsctl_context *ctx)
 
     get_info(ctx, &info);
     br = find_real_bridge(&info, ctx->argv[1], true);
-    verify_controllers(br->br_cfg);
-
-    delete_controllers(br->ctrl, br->n_ctrl);
 
     n = ctx->argc - 2;
     controllers = insert_controllers(ctx->txn, &ctx->argv[2], n);
@@ -1935,28 +1877,12 @@ cmd_get_manager(struct vsctl_context *ctx)
     svec_destroy(&targets);
 }
 
-static void
-delete_managers(const struct vsctl_context *ctx)
-{
-    const struct ovsrec_open_vswitch *ovs = ctx->ovs;
-    size_t i;
-
-    /* Delete Manager rows pointed to by 'manager_options' column. */
-    for (i = 0; i < ovs->n_manager_options; i++) {
-        ovsrec_manager_delete(ovs->manager_options[i]);
-    }
-
-    /* Delete 'Manager' row refs in 'manager_options' column. */
-    ovsrec_open_vswitch_set_manager_options(ovs, NULL, 0);
-}
-
 static void
 cmd_del_manager(struct vsctl_context *ctx)
 {
     const struct ovsrec_open_vswitch *ovs = ctx->ovs;
 
-    verify_managers(ovs);
-    delete_managers(ctx);
+    ovsrec_open_vswitch_set_manager_options(ovs, NULL, 0);
 }
 
 static void
@@ -1982,8 +1908,6 @@ cmd_set_manager(struct vsctl_context *ctx)
 {
     const size_t n = ctx->argc - 1;
 
-    verify_managers(ctx->ovs);
-    delete_managers(ctx);
     insert_managers(ctx, &ctx->argv[1], n);
 }
 
@@ -2027,13 +1951,7 @@ pre_cmd_del_ssl(struct vsctl_context *ctx)
 static void
 cmd_del_ssl(struct vsctl_context *ctx)
 {
-    struct ovsrec_ssl *ssl = ctx->ovs->ssl;
-
-    if (ssl) {
-        ovsrec_open_vswitch_verify_ssl(ctx->ovs);
-        ovsrec_ssl_delete(ssl);
-        ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
-    }
+    ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
 }
 
 static void
@@ -2046,12 +1964,8 @@ static void
 cmd_set_ssl(struct vsctl_context *ctx)
 {
     bool bootstrap = shash_find(&ctx->options, "--bootstrap");
-    struct ovsrec_ssl *ssl = ctx->ovs->ssl;
+    struct ovsrec_ssl *ssl;
 
-    ovsrec_open_vswitch_verify_ssl(ctx->ovs);
-    if (ssl) {
-        ovsrec_ssl_delete(ssl);
-    }
     ssl = ovsrec_ssl_insert(ctx->txn);
 
     ovsrec_ssl_set_private_key(ssl, ctx->argv[1]);
@@ -2351,7 +2265,7 @@ get_column(const struct vsctl_table_class *table, const char *column_name,
     }
 }
 
-static struct uuid *
+static struct ovsdb_symbol *
 create_symbol(struct ovsdb_symbol_table *symtab, const char *id, bool *newp)
 {
     struct ovsdb_symbol *symbol;
@@ -2370,7 +2284,7 @@ create_symbol(struct ovsdb_symbol_table *symtab, const char *id, bool *newp)
                     id);
     }
     symbol->created = true;
-    return &symbol->uuid;
+    return symbol;
 }
 
 static void
@@ -2578,13 +2492,19 @@ cmd_get(struct vsctl_context *ctx)
     table = get_table(table_name);
     row = must_get_row(ctx, table, record_id);
     if (id) {
+        struct ovsdb_symbol *symbol;
         bool new;
 
-        *create_symbol(ctx->symtab, id, &new) = row->uuid;
+        symbol = create_symbol(ctx->symtab, id, &new);
         if (!new) {
             vsctl_fatal("row id \"%s\" specified on \"get\" command was used "
                         "before it was defined", id);
         }
+        symbol->uuid = row->uuid;
+
+        /* This symbol refers to a row that already exists, so disable warnings
+         * about it being unreferenced. */
+        symbol->strong_ref = true;
     }
     for (i = 3; i < ctx->argc; i++) {
         const struct ovsdb_idl_column *column;
@@ -3093,18 +3013,42 @@ cmd_clear(struct vsctl_context *ctx)
 }
 
 static void
-cmd_create(struct vsctl_context *ctx)
+pre_create(struct vsctl_context *ctx)
 {
     const char *id = shash_find_data(&ctx->options, "--id");
     const char *table_name = ctx->argv[1];
     const struct vsctl_table_class *table;
+
+    table = get_table(table_name);
+    if (!id && !table->class->is_root) {
+        VLOG_WARN("applying \"create\" command to table %s without --id "
+                  "option will have no effect", table->class->name);
+    }
+}
+
+static void
+cmd_create(struct vsctl_context *ctx)
+{
+    const char *id = shash_find_data(&ctx->options, "--id");
+    const char *table_name = ctx->argv[1];
+    const struct vsctl_table_class *table = get_table(table_name);
     const struct ovsdb_idl_row *row;
     const struct uuid *uuid;
     int i;
 
-    uuid = id ? create_symbol(ctx->symtab, id, NULL) : NULL;
+    if (id) {
+        struct ovsdb_symbol *symbol = create_symbol(ctx->symtab, id, NULL);
+        if (table->class->is_root) {
+            /* This table is in the root set, meaning that rows created in it
+             * won't disappear even if they are unreferenced, so disable
+             * warnings about that by pretending that there is a reference. */
+            symbol->strong_ref = true;
+        }
+        uuid = &symbol->uuid;
+    } else {
+        uuid = NULL;
+    }
 
-    table = get_table(table_name);
     row = ovsdb_idl_txn_insert(ctx->txn, table->class, uuid);
     for (i = 2; i < ctx->argc; i++) {
         set_column(table, row, ctx->argv[i], ctx->symtab);
@@ -3402,6 +3346,17 @@ do_vsctl(const char *args, struct vsctl_command *commands, size_t n_commands,
                         "with \"-- --id=%s create ...\")",
                         node->name, node->name);
         }
+        if (!symbol->strong_ref) {
+            if (!symbol->weak_ref) {
+                VLOG_WARN("row id \"%s\" was created but no reference to it "
+                          "was inserted, so it will not actually appear in "
+                          "the database", node->name);
+            } else {
+                VLOG_WARN("row id \"%s\" was created but only a weak "
+                          "reference to it was inserted, so it will not "
+                          "actually appear in the database", node->name);
+            }
+        }
     }
 
     status = ovsdb_idl_txn_commit_block(txn);
@@ -3577,7 +3532,7 @@ static const struct vsctl_command_syntax all_commands[] = {
     {"add", 4, INT_MAX, pre_cmd_add, cmd_add, NULL, "", RW},
     {"remove", 4, INT_MAX, pre_cmd_remove, cmd_remove, NULL, "", RW},
     {"clear", 3, INT_MAX, pre_cmd_clear, cmd_clear, NULL, "", RW},
-    {"create", 2, INT_MAX, NULL, cmd_create, post_create, "--id=", RW},
+    {"create", 2, INT_MAX, pre_create, cmd_create, post_create, "--id=", RW},
     {"destroy", 1, INT_MAX, pre_cmd_destroy, cmd_destroy, NULL, "--if-exists",
      RW},
     {"wait-until", 2, INT_MAX, pre_cmd_wait_until, cmd_wait_until, NULL, "",