]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: Generalize graph to work for any data type
authorQuentin Young <qlyoung@cumulusnetworks.com>
Thu, 1 Sep 2016 21:27:33 +0000 (21:27 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Thu, 1 Sep 2016 21:30:17 +0000 (21:30 +0000)
Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
lib/Makefile.am
lib/command_graph.c [deleted file]
lib/command_graph.h [deleted file]
lib/graph.c [new file with mode: 0644]
lib/graph.h [new file with mode: 0644]

index 2df5ed61f434679ec5615f941b91b434cc4782a7..d12f9ed6d9651086a8203f7e938abe5901fb449d 100644 (file)
@@ -11,7 +11,7 @@ libzebra_la_LDFLAGS = -version-info 0:0:0
 libzebra_la_SOURCES = \
        network.c pid_output.c getopt.c getopt1.c daemon.c \
        checksum.c vector.c linklist.c vty.c \
-       command_graph.c command_parse.y command_lex.l command_match.c grammar_sandbox.c \
+       graph.c command_parse.y command_lex.l command_match.c grammar_sandbox.c \
        command.c \
        sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c hash.c \
        filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
@@ -28,7 +28,7 @@ libzebra_la_LIBADD = @LIB_REGEX@ @LIBCAP@
 pkginclude_HEADERS = \
        buffer.h checksum.h filter.h getopt.h hash.h \
        if.h linklist.h log.h \
-       command_graph.h command_match.h grammar_sandbox.h \
+       graph.h command_match.h grammar_sandbox.h \
        command.h \
        memory.h network.h prefix.h routemap.h distribute.h sockunion.h \
        str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
diff --git a/lib/command_graph.c b/lib/command_graph.c
deleted file mode 100644 (file)
index 323bd3e..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Graph data structure and companion routines for CLI backend.
- *
- * --
- * Copyright (C) 2016 Cumulus Networks, Inc.
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-#include <zebra.h>
-#include "command_graph.h"
-#include "memory.h"
-
-struct graph_node *
-graphnode_add_child (struct graph_node *parent, struct graph_node *child)
-{
-  vector_set (parent->children, child);
-  child->refs++;
-  return child;
-}
-
-struct graph_node *
-graphnode_new (enum graph_node_type type)
-{
-  struct graph_node *node =
-     XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct graph_node));
-
-  node->type = type;
-  node->children = vector_init(VECTOR_MIN_SIZE);
-
-  return node;
-}
-
-void
-graphnode_delete (struct graph_node *node)
-{
-  if (!node) return;
-  if (node->children) vector_free (node->children);
-  if (node->element) free_cmd_element (node->element);
-  free (node->text);
-  free (node->arg);
-  free (node);
-}
-
-void
-graphnode_delete_graph (struct graph_node *start)
-{
-  if (start && start->children && vector_active (start->children) > 0)
-    {
-      for (unsigned int i = 0; i < vector_active (start->children); i++)
-        {
-          graphnode_delete (vector_slot(start->children, i));
-          vector_unset (start->children, i);
-        }
-    }
-
-  if (--(start->refs) == 0)
-    graphnode_delete (start);
-}
diff --git a/lib/command_graph.h b/lib/command_graph.h
deleted file mode 100644 (file)
index a2f84e3..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Graph data structure and companion routines for CLI backend.
- *
- * --
- * Copyright (C) 2016 Cumulus Networks, Inc.
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
-
-#ifndef _ZEBRA_COMMAND_GRAPH_H
-#define _ZEBRA_COMMAND_GRAPH_H
-
-#include "command.h"
-
-/**
- * Types for graph nodes.
- *
- * The node type determines what kind of data the node can match (in the
- * matching use case) or hold (in the argv use case).
- */
-enum graph_node_type
-{
-  IPV4_GN,          // IPV4 addresses
-  IPV4_PREFIX_GN,   // IPV4 network prefixes
-  IPV6_GN,          // IPV6 prefixes
-  IPV6_PREFIX_GN,   // IPV6 network prefixes
-  WORD_GN,          // words
-  RANGE_GN,         // integer ranges
-  NUMBER_GN,        // numbers
-  VARIABLE_GN,      // almost anything
-  /* plumbing types */
-  SELECTOR_GN,      // marks beginning of selector subgraph
-  OPTION_GN,        // marks beginning of option subgraph
-  NUL_GN,           // transparent node with various uses
-  START_GN,         // first node in the graph (has no parents)
-  END_GN            // leaf node in the graph, has pointer to cmd_element
-};
-
-/**
- * Command graph node.
- * Used for matching and passing arguments to vtysh commands.
- */
-struct graph_node
-{
-  enum graph_node_type type;    // data type this node matches or holds
-  vector children;              // this node's children
-
-  char *text;                   // original format text
-  char *doc;                    // docstring for this node
-  long long value;              // for NUMBER_GN
-  long long min, max;           // for RANGE_GN
-
-  /* cmd_element struct pointer, only valid for END_GN */
-  struct cmd_element *element;
-
-  /* used for passing arguments to command functions */
-  char *arg;
-
-  /* refcount for node parents */
-  unsigned int refs;
-};
-
-/**
- * Adds a node as a child of another node.
- *
- * @param[in] parent node
- * @param[in] child node
- * @return child node
- */
-struct graph_node *
-graphnode_add_child (struct graph_node *parent, struct graph_node *child);
-
-/**
- * Creates a new node, initializes all fields to default values and sets the
- * node type.
- *
- * @param[in] type node type
- * @return pointer to the created node
- */
-struct graph_node *
-graphnode_new (enum graph_node_type type);
-
-/**
- * Deletes a graph node without deleting its children.
- *
- * @param[out] node pointer to node to delete
- */
-void
-graphnode_delete (struct graph_node *node);
-
-/**
- * Deletes a graph node and recursively deletes all its direct and indirect
- * children.
- *
- * @param[out] node start node of graph to free
- */
-void
-graphnode_delete_graph (struct graph_node *node);
-
-#endif /* _ZEBRA_COMMAND_GRAPH_H */
diff --git a/lib/graph.c b/lib/graph.c
new file mode 100644 (file)
index 0000000..a46f714
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Graph data structure.
+ *
+ * --
+ * Copyright (C) 2016 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#include <zebra.h>
+#include "command_graph.h"
+#include "memory.h"
+
+
+struct graph_node *
+graph_new_node (struct graph *graph, void *data, void (*del) (void*))
+{
+  struct graph_node *node =
+     XCALLOC(MTYPE_CMD_TOKENS, sizeof(struct graph_node));
+
+  node->from = vector_init(VECTOR_MIN_SIZE);
+  node->to   = vector_init(VECTOR_MIN_SIZE);
+  node->data = data;
+  node->del  = del;
+
+  vector_set (graph->nodes, node);
+
+  return node;
+}
+
+void
+graph_delete_node (struct graph *graph, struct graph_node *node)
+{
+  if (!node) return;
+
+  // an adjacent node
+  struct graph_node *adj;
+
+  // for all nodes that have an edge to us, remove us from their ->to
+  for (int i = 0; i < vector_active (node->from); i++)
+    {
+      adj = vector_slot (node->from, i);
+      for (int j = 0; j < vector_active (adj->to); j++)
+        if (vector_slot (adj->to, j) == node)
+          vector_unset (adj->to, j);
+
+      // if the node is orphaned, delete it
+      if (vector_active (adj->to) == 0 && vector_active (adj->from) == 0)
+        graph_delete_node (adj);
+    }
+
+  // for all nodes that we have an edge to, remove us from their ->from
+  for (int i = 0; i < vector_active (node->to); i++)
+    {
+      adj = vector_slot (node->to, i);
+      for (int j = 0; j < vector_active (adj->from); j++)
+        if (vector_slot (adj->from, j) == node)
+          vector_unset (adj->from, j);
+
+      // if the node is orphaned, delete it
+      if (vector_active (adj->to) == 0 && vector_active (adj->from) == 0)
+        graph_delete_node (adj);
+    }
+
+  // if there is a deletion callback, call it!
+  if (node->del && node->data)
+    (*node->del) (node->data);
+
+  // free adjacency lists
+  vector_free (node->to);
+  vector_free (node->from);
+
+  // remove node from graph->nodes
+  for (int i = 0; i < vector_active (graph->nodes); i++)
+    if (vector_slot (graph->nodes, i) == node)
+      vector_unset (graph->nodes, i);
+
+  // free the node itself
+  free (node);
+}
+
+struct graph_node *
+graph_add_edge (struct graph_node *from, struct graph_node *to)
+{
+  vector_set (from->to, to);
+  vector_set (to->from, from);
+  return to;
+}
+
+void
+graph_delete_graph (struct graph *graph)
+{
+  // delete each node in the graph
+  for (int i = 0; i < vector_active (graph->nodes); i++)
+    graph_delete_node (vector_slot (graph->nodes, i));
+
+  vector_free (graph->nodes);
+  free (graph);
+}
diff --git a/lib/graph.h b/lib/graph.h
new file mode 100644 (file)
index 0000000..7c0f848
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Graph data structure.
+ *
+ * --
+ * Copyright (C) 2016 Cumulus Networks, Inc.
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_COMMAND_GRAPH_H
+#define _ZEBRA_COMMAND_GRAPH_H
+
+#include "vector.h"
+
+/**
+ * Graph structure.
+ */
+struct graph
+{
+  vector nodes; // all nodes in the graph
+}
+
+/**
+ * Graph node / vertex.
+ */
+struct graph_node
+{
+  vector from;                  // nodes which have edges to this node
+  vector to;                    // nodes which this node has edges to
+
+  void *data;                   // node data
+  void (*del) (void *data)      // deletion callback
+};
+
+/**
+ * Creates a new node.
+ *
+ * @struct graph the graph this node exists in
+ * @param[in] data this node's data
+ * @param[in] del data deletion callback
+ * @return the new node
+ */
+struct graph_node *
+graph_new_node (struct graph *graph, void *data, void (*del) (void*));
+
+/**
+ * Deletes a node.
+ *
+ * Before deletion, this function removes all edges to and from this node from
+ * any neighbor nodes.
+ *
+ * If, as a result of this operation, any neighbor node has no edges either to
+ * or from itself, that node will be deleted as well. If the graph topology is
+ * e.g. a star this will result in the deletion of all nodes.
+ *
+ * If *data and *del are non-null, the following call is made:
+ *   (*node->del) (node->data);
+ *
+ * @param[out] node pointer to node to delete
+ */
+void
+graph_delete_node (struct graph *graph, struct graph_node *node);
+
+/**
+ * Makes a directed edge between two nodes.
+ *
+ * @param[in] from
+ * @param[in] to
+ * @return to
+ */
+struct graph_node *
+graph_add_edge (struct graph_node *from, struct graph_node *to);
+
+/**
+ * Deletes a graph.
+ *
+ * Calls graph_delete_node on each node before freeing the graph struct itself.
+ *
+ * @param graph the graph to delete
+ */
+void
+graph_delete_graph (struct graph *graph);
+
+#endif /* _ZEBRA_COMMAND_GRAPH_H */