OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
db_graph.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "db/db_graph.h"
6 
7 #ifdef __clang__
8 #pragma clang diagnostic push
9 #pragma clang diagnostic ignored "-Wunused-variable"
10 #pragma clang diagnostic ignored "-Wunneeded-internal-declaration"
11 #endif
12 
13 #include <boost/foreach.hpp>
14 #include <boost/scoped_ptr.hpp>
15 #include <boost/graph/breadth_first_search.hpp>
16 #include <boost/graph/filtered_graph.hpp>
17 
18 #ifdef __clang__
19 #pragma clang diagnostic pop
20 #endif
21 
22 #include "base/logging.h"
23 #include "base/time_util.h"
24 #include "db/db_graph_vertex.h"
25 #include "db/db_graph_edge.h"
26 
27 using namespace std;
28 using namespace boost;
29 
31  entry->set_vertex(add_vertex(graph_));
32  DBGraphBase::VertexProperties &vertex = graph_[entry->vertex()];
33  vertex.entry = entry;
34 }
35 
37  remove_vertex(entry->vertex(), graph_);
38  entry->VertexInvalidate();
39 }
40 
42  DBGraphEdge *edge) {
43  DBGraph::Edge edge_id;
44  bool added;
45  boost::tie(edge_id, added) = add_edge(lhs->vertex(), rhs->vertex(),
46  EdgeProperties(edge->name(), edge), graph_);
47  assert(added);
48  edge->SetEdge(edge_id);
49  return edge_id;
50 }
51 
53  remove_edge(edge->edge_id(), graph_);
54 }
55 
56 template <typename GraphType>
57 class BFSVisitor : public default_bfs_visitor {
58 public:
60 
62  DBGraph::EdgeVisitor edge_visit)
63  : vertex_visit_(vertex_visit), edge_visit_(edge_visit) {
64  }
65 
67  DBGraph::EdgeVisitor edge_visit,
68  DBGraph::VertexFinish vertex_finish)
69  : vertex_visit_(vertex_visit), edge_visit_(edge_visit),
70  vertex_finish_(vertex_finish) {
71  }
72 
73  void discover_vertex(DBGraph::Vertex u, const GraphType &graph) const {
74  if (vertex_visit_) {
75  vertex_visit_(graph[u].entry);
76  }
77  }
78 
79  void finish_vertex(DBGraph::Vertex u, const GraphType &graph) const {
80  if (vertex_finish_) {
81  vertex_finish_(graph[u].entry);
82  }
83  }
84 
85  // Edges are examined twice: once for the source and once for the target
86  // node.
87  void examine_edge(DBGraph::Edge e, const GraphType &graph) const {
88  const DBGraphBase::EdgeProperties &properties = graph[e];
89  if (edge_visit_) {
90  edge_visit_(properties.edge);
91  }
92  }
93 
94 private:
98 };
99 
100 typedef std::map<DBGraph::Vertex, default_color_type> ColorMap;
101 
102 void DBGraph::Visit(DBGraphVertex *start, VertexVisitor vertex_visit_fn,
103  EdgeVisitor edge_visit_fn, VertexFinish vertex_finish_fn) {
104  const BFSVisitor<graph_t> vis(vertex_visit_fn, edge_visit_fn,
105  vertex_finish_fn);
106  ColorMap color_map;
107  breadth_first_search(graph_, start->vertex(),
108  visitor(vis).color_map(make_assoc_property_map(color_map)));
109 }
110 
111 void DBGraph::Visit(DBGraphVertex *start, VertexVisitor vertex_visit_fn,
112  EdgeVisitor edge_visit_fn) {
113  const BFSVisitor<graph_t> vis(vertex_visit_fn, edge_visit_fn);
114  ColorMap color_map;
115  breadth_first_search(graph_, start->vertex(),
116  visitor(vis).color_map(make_assoc_property_map(color_map)));
117 }
118 
120  EdgePredicate() : graph_(NULL), filter_(NULL) { }
121  EdgePredicate(const DBGraph *graph, const VisitorFilter &filter)
122  : graph_(graph), filter_(&filter) {
123  }
124 
125  bool operator()(const DBGraphVertex *src, const DBGraphVertex *tgt,
126  const DBGraphEdge *edge) const {
127  if (edge->IsDeleted()) {
128  return false;
129  }
130  return filter_->EdgeFilter(src, tgt, edge);
131  }
132 
133 private:
134  const DBGraph *graph_;
136 };
137 
139  VertexPredicate() : graph_(NULL), filter_(NULL) { }
140  VertexPredicate(const DBGraph *graph, const VisitorFilter &filter)
141  : graph_(graph), filter_(&filter) {
142  }
143  bool operator()(const DBGraphVertex *entry) const {
144  if (entry->IsDeleted()) {
145  return false;
146  }
147  return filter_->VertexFilter(entry);
148  }
149 private:
150  const DBGraph *graph_;
152 };
153 
155  DBGraphEdge *edge) {
156  DBGraphVertex *adjacent_vertex = edge->target(this);
157  if (adjacent_vertex == current_vertex) {
158  adjacent_vertex = edge->source(this);
159  }
160  return adjacent_vertex;
161 }
162 
163 
165  OutEdgeIterator &iter_begin, OutEdgeIterator &iter_end,
166  VertexVisitor vertex_visit_fn, EdgeVisitor edge_visit_fn,
167  EdgePredicate &edge_test, VertexPredicate &vertex_test,
168  ::uint64_t curr_walk, /* ::uint64_t because using namespace boost above */
169  VisitQ &visit_q,
170  bool match_name, const std::string &allowed_edge) {
171  for (; iter_begin != iter_end; ++iter_begin) {
172  const DBGraph::EdgeProperties &e_prop = get(edge_bundle, *iter_begin);
173  DBGraphEdge *edge = e_prop.edge;
174  if (match_name && e_prop.name() != allowed_edge) break;
175  DBGraphVertex *adjacent_vertex = vertex_target(current_vertex, edge);
176  if (edge_visit_fn) edge_visit_fn(edge);
177  if (!edge_test(current_vertex, adjacent_vertex, edge)) continue;
178  if (adjacent_vertex->visited(curr_walk)) continue;
179  if (vertex_test(adjacent_vertex)) {
180  vertex_visit_fn(adjacent_vertex);
181  visit_q.push(adjacent_vertex);
182  }
183  adjacent_vertex->set_visited(curr_walk);
184  }
185 }
186 
187 void DBGraph::Visit(DBGraphVertex *start, VertexVisitor vertex_visit_fn,
188  EdgeVisitor edge_visit_fn, const VisitorFilter &filter) {
189  // uint64_t t = ClockMonotonicUsec();
190  ::uint64_t curr_walk = get_graph_walk_num(); /* ::uint64_t because using namespace boost above */
191  EdgePredicate edge_test(this, filter);
192  VertexPredicate vertex_test(this, filter);
193 
194  VisitQ visit_q;
195 
196  visit_q.push(start);
197  start->set_visited(curr_walk);
198  if (vertex_test(start)) {
199  vertex_visit_fn(start);
200  }
201  while (!visit_q.empty()) {
202  DBGraphVertex *vertex = visit_q.front();
203  visit_q.pop();
204  // Get All out-edges from the node
205  OutEdgeListType &out_edge_set = graph_.out_edge_list(vertex->vertex());
206  if (out_edge_set.empty()) continue;
207 
208  OutEdgeListType::iterator it = out_edge_set.begin();
209  OutEdgeListType::iterator it_end = out_edge_set.end();
210 
211  // Collect all allowed edges to visit
213  filter.AllowedEdges(vertex);
214 
215  if (!allowed_edge_ret.first) {
216  for (auto allowed_edge : allowed_edge_ret.second) {
217  EdgeContainer fake_container;
218  fake_container.push_back(
219  EdgeType(0, 0, EdgeProperties(allowed_edge, NULL)));
220  StoredEdge es(vertex->vertex(), fake_container.begin());
221  // Call lower_bound on out edge list and walk on selected edges
222  it = out_edge_set.lower_bound(es);
223  IterateEdges(vertex, it, it_end, vertex_visit_fn, edge_visit_fn,
224  edge_test, vertex_test, curr_walk, visit_q, true, allowed_edge);
225  }
226  } else {
227  IterateEdges(vertex, it, it_end, vertex_visit_fn, edge_visit_fn,
228  edge_test, vertex_test, curr_walk, visit_q);
229  }
230  }
231  // uint64_t end_t = ClockMonotonicUsec();
232  // std::cout << "Graph Walk time(in usec) " << (end_t-t) << std::endl;
233 }
234 
236  if (graph_) {
237  boost::tie(iter_, end_) = edges(*graph_->graph());
238  }
239 }
240 
242  Vertex src = source(*iter_, *graph_->graph());
243  Vertex tgt = target(*iter_, *graph_->graph());
244  return boost::make_tuple(graph_->vertex_data(src), graph_->vertex_data(tgt),
245  graph_->edge_data(*iter_));
246 }
247 
249  if (graph_ != NULL) {
250  if (rhs.graph_ == NULL) {
251  return (iter_ == end_);
252  }
253  return iter_ == rhs.iter_;
254  } else {
255  if (rhs.graph_ != NULL) {
256  return (rhs.iter_ == rhs.end_);
257  }
258  return true;
259  }
260 }
261 
263  return edge_iterator(this);
264 }
265 
267  return edge_iterator(NULL);
268 }
269 
271  : graph_(graph) {
272  if (graph_ != NULL) {
273  boost::tie(iter_, end_) = vertices(*graph_->graph());
274  }
275 }
276 
278  if (graph_ != NULL) {
279  if (rhs.graph_ != NULL) {
280  return iter_ == rhs.iter_;
281  } else {
282  return (iter_ == end_);
283  }
284  } else {
285  if (rhs.graph_ != NULL) {
286  return rhs.iter_ == rhs.end_;
287  } else {
288  return true;
289  }
290  }
291 }
292 
294  return vertex_iterator(this);
295 }
296 
298  return vertex_iterator(NULL);
299 }
300 
302  graph_.clear();
303 }
304 
305 size_t DBGraph::vertex_count() const {
306  return num_vertices(graph_);
307 }
308 
309 size_t DBGraph::edge_count() const {
310  return num_edges(graph_);
311 }
312 
313 template <class StoredEdge>
315  const DBGraph::EdgeProperties &edge1 = get(edge_bundle, e1);
316  const DBGraph::EdgeProperties &edge2 = get(edge_bundle, e2);
317  return edge1.name() < edge2.name();
318 }
bool equal(const edge_iterator &rhs) const
Definition: db_graph.cc:248
edge_iterator edge_list_begin()
Definition: db_graph.cc:262
boost::graph_traits< graph_t >::edge_iterator edge_iterator
Definition: db_graph_base.h:61
graph_t::StoredEdge StoredEdge
Definition: db_graph_base.h:64
const graph_t * graph() const
Definition: db_graph.h:91
void IterateEdges(DBGraphVertex *start, OutEdgeIterator &iter_begin, OutEdgeIterator &iter_end, VertexVisitor vertex_visit_fn, EdgeVisitor edge_visit_fn, EdgePredicate &edge_test, VertexPredicate &vertex_test, uint64_t curr_walk, VisitQ &visit_queue, bool match_name=false, const std::string &allowed_edge="")
Definition: db_graph.cc:164
edge_iterator(DBGraph *graph)
Definition: db_graph.cc:235
bool IsDeleted() const
Definition: db_entry.h:49
void finish_vertex(DBGraph::Vertex u, const GraphType &graph) const
Definition: db_graph.cc:79
void Unlink(DBGraphEdge *link)
Definition: db_graph.cc:52
DBGraphBase::VertexProperties Properties
Definition: db_graph.cc:59
bool operator()(const DBGraphVertex *entry) const
Definition: db_graph.cc:143
std::queue< DBGraphVertex * > VisitQ
Definition: db_graph.h:124
virtual AllowedEdgeRetVal AllowedEdges(const DBGraphVertex *vertex) const
Definition: db_graph.h:40
const std::string & name() const
Definition: db_graph_base.h:48
DBGraph::VertexVisitor vertex_visit_
Definition: db_graph.cc:95
boost::container_gen< graph_t::out_edge_list_selector, StoredEdge >::type OutEdgeListType
Definition: db_graph_base.h:66
boost::function< void(DBGraphEdge *)> EdgeVisitor
Definition: db_graph.h:23
DBGraphBase::edge_iterator iter_
Definition: db_graph.h:59
size_t vertex_count() const
Definition: db_graph.cc:305
void discover_vertex(DBGraph::Vertex u, const GraphType &graph) const
Definition: db_graph.cc:73
vertex_iterator vertex_list_begin()
Definition: db_graph.cc:293
void clear()
Definition: db_graph.cc:301
bool visited(uint64_t current_graph_walk_num)
void SetEdge(Edge edge)
DBGraphBase::vertex_descriptor Vertex
Definition: db_graph.h:21
vertex_iterator vertex_list_end()
Definition: db_graph.cc:297
edge_iterator edge_list_end()
Definition: db_graph.cc:266
DBEdgeInfo dereference() const
Definition: db_graph.cc:241
const VisitorFilter * filter_
Definition: db_graph.cc:135
void examine_edge(DBGraph::Edge e, const GraphType &graph) const
Definition: db_graph.cc:87
void AddNode(DBGraphVertex *entry)
Definition: db_graph.cc:30
graph_t graph_
Definition: db_graph.h:138
graph_t::EdgeContainer EdgeContainer
Definition: db_graph_base.h:69
Edge edge_id() const
Definition: db_graph_edge.h:25
EdgePredicate(const DBGraph *graph, const VisitorFilter &filter)
Definition: db_graph.cc:121
DBGraphVertex * target(DBGraph *graph)
const DBGraph * graph_
Definition: db_graph.cc:134
void Visit(DBGraphVertex *start, VertexVisitor vertex_visit_fn, EdgeVisitor edge_visit_fn)
Definition: db_graph.cc:111
graph_t::vertex_iterator iter_
Definition: db_graph.h:79
Vertex vertex() const
bool operator()(const StoredEdge &e1, const StoredEdge &e2) const
Definition: db_graph.cc:314
void RemoveNode(DBGraphVertex *entry)
Definition: db_graph.cc:36
BFSVisitor(DBGraph::VertexVisitor vertex_visit, DBGraph::EdgeVisitor edge_visit, DBGraph::VertexFinish vertex_finish)
Definition: db_graph.cc:66
std::map< DBGraph::Vertex, default_color_type > ColorMap
Definition: db_graph.cc:100
DBGraph::VertexFinish vertex_finish_
Definition: db_graph.cc:97
graph_t::vertex_iterator end_
Definition: db_graph.h:80
std::pair< bool, AllowedEdgeSet > AllowedEdgeRetVal
Definition: db_graph.h:30
boost::function< void(DBGraphVertex *)> VertexFinish
Definition: db_graph.h:24
void set_visited(uint64_t current_graph_walk_num)
const VisitorFilter * filter_
Definition: db_graph.cc:151
DBGraphBase::edge_descriptor Edge
Definition: db_graph.h:20
Edge Link(DBGraphVertex *lhs, DBGraphVertex *rhs, DBGraphEdge *link)
Definition: db_graph.cc:41
virtual const std::string & name() const =0
vertex_iterator(DBGraph *graph)
Definition: db_graph.cc:270
VertexPredicate(const DBGraph *graph, const VisitorFilter &filter)
Definition: db_graph.cc:140
DBGraphVertex * vertex_target(DBGraphVertex *current_vertex, DBGraphEdge *edge)
Definition: db_graph.cc:154
bool equal(const vertex_iterator &rhs) const
Definition: db_graph.cc:277
size_t edge_count() const
Definition: db_graph.cc:309
void set_vertex(const Vertex &vertex_id)
DBGraphBase::edge_iterator end_
Definition: db_graph.h:60
void VertexInvalidate()
const DBGraph * graph_
Definition: db_graph.cc:150
OutEdgeListType::iterator OutEdgeIterator
Definition: db_graph_base.h:67
DBGraphVertex * source(DBGraph *graph)
boost::function< void(DBGraphVertex *)> VertexVisitor
Definition: db_graph.h:22
boost::tuple< DBGraphVertex *, DBGraphVertex *, DBGraphEdge * > DBEdgeInfo
Definition: db_graph.h:45
adjacency_iterator begin(DBGraph *graph)
BFSVisitor(DBGraph::VertexVisitor vertex_visit, DBGraph::EdgeVisitor edge_visit)
Definition: db_graph.cc:61
EdgeContainer::value_type EdgeType
Definition: db_graph_base.h:70
bool operator()(const DBGraphVertex *src, const DBGraphVertex *tgt, const DBGraphEdge *edge) const
Definition: db_graph.cc:125
DBGraph::EdgeVisitor edge_visit_
Definition: db_graph.cc:96