LCOV - code coverage report
Current view: top level - db - db_graph.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 141 162 87.0 %
Date: 2026-06-11 01:56:02 Functions: 29 31 93.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      30      189176 : void DBGraph::AddNode(DBGraphVertex *entry) {
      31      189176 :     entry->set_vertex(add_vertex(graph_));
      32      189176 :     DBGraphBase::VertexProperties &vertex = graph_[entry->vertex()];
      33      189176 :     vertex.entry = entry;
      34      189176 : }
      35             : 
      36      189166 : void DBGraph::RemoveNode(DBGraphVertex *entry) {
      37      189166 :     remove_vertex(entry->vertex(), graph_);
      38      189166 :     entry->VertexInvalidate();
      39      189166 : }
      40             : 
      41      159922 : DBGraph::Edge DBGraph::Link(DBGraphVertex *lhs, DBGraphVertex *rhs,
      42             :                             DBGraphEdge *edge) {
      43      159922 :     DBGraph::Edge edge_id;
      44             :     bool added;
      45      159922 :     boost::tie(edge_id, added) = add_edge(lhs->vertex(), rhs->vertex(),
      46      319844 :                                     EdgeProperties(edge->name(), edge), graph_);
      47      159922 :     assert(added);
      48      159922 :     edge->SetEdge(edge_id);
      49      319844 :     return edge_id;
      50             : }
      51             : 
      52      159914 : void DBGraph::Unlink(DBGraphEdge *edge) {
      53      159914 :     remove_edge(edge->edge_id(), graph_);
      54      159914 : }
      55             : 
      56             : template <typename GraphType>
      57             : class BFSVisitor : public default_bfs_visitor {
      58             : public:
      59             :     typedef DBGraphBase::VertexProperties Properties;
      60             : 
      61           5 :     BFSVisitor(DBGraph::VertexVisitor vertex_visit,
      62             :                DBGraph::EdgeVisitor edge_visit)
      63           5 :         : vertex_visit_(vertex_visit), edge_visit_(edge_visit) {
      64           5 :     }
      65             : 
      66           0 :     BFSVisitor(DBGraph::VertexVisitor vertex_visit,
      67             :                DBGraph::EdgeVisitor edge_visit,
      68             :                DBGraph::VertexFinish vertex_finish)
      69           0 :         : vertex_visit_(vertex_visit), edge_visit_(edge_visit),
      70           0 :           vertex_finish_(vertex_finish) {
      71           0 :     }
      72             : 
      73          21 :     void discover_vertex(DBGraph::Vertex u, const GraphType &graph) const {
      74          21 :         if (vertex_visit_) {
      75          21 :             vertex_visit_(graph[u].entry);
      76             :         }
      77          21 :     }
      78             : 
      79          21 :     void finish_vertex(DBGraph::Vertex u, const GraphType &graph) const {
      80          21 :         if (vertex_finish_) {
      81           0 :             vertex_finish_(graph[u].entry);
      82             :         }
      83          21 :     }
      84             : 
      85             :     // Edges are examined twice: once for the source and once for the target
      86             :     // node.
      87          34 :     void examine_edge(DBGraph::Edge e, const GraphType &graph) const {
      88          34 :         const DBGraphBase::EdgeProperties &properties = graph[e];
      89          34 :         if (edge_visit_) {
      90          18 :             edge_visit_(properties.edge);
      91             :         }
      92          34 :     }
      93             : 
      94             : private:
      95             :     DBGraph::VertexVisitor vertex_visit_;
      96             :     DBGraph::EdgeVisitor edge_visit_;
      97             :     DBGraph::VertexFinish vertex_finish_;
      98             : };
      99             : 
     100             : typedef std::map<DBGraph::Vertex, default_color_type> ColorMap;
     101             : 
     102           0 : 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           0 :                                   vertex_finish_fn);
     106           0 :     ColorMap color_map;
     107           0 :     breadth_first_search(graph_, start->vertex(),
     108           0 :         visitor(vis).color_map(make_assoc_property_map(color_map)));
     109           0 : }
     110             : 
     111           5 : void DBGraph::Visit(DBGraphVertex *start, VertexVisitor vertex_visit_fn,
     112             :                     EdgeVisitor edge_visit_fn) {
     113          10 :     const BFSVisitor<graph_t> vis(vertex_visit_fn, edge_visit_fn);
     114           5 :     ColorMap color_map;
     115           5 :     breadth_first_search(graph_, start->vertex(),
     116          10 :         visitor(vis).color_map(make_assoc_property_map(color_map)));
     117           5 : }
     118             : 
     119             : struct DBGraph::EdgePredicate {
     120             :     EdgePredicate() : graph_(NULL), filter_(NULL) { }
     121         130 :     EdgePredicate(const DBGraph *graph, const VisitorFilter &filter)
     122         130 :         : graph_(graph), filter_(&filter) {
     123         130 :     }
     124             : 
     125         541 :     bool operator()(const DBGraphVertex *src, const DBGraphVertex *tgt,
     126             :                     const DBGraphEdge *edge) const {
     127         541 :         if (edge->IsDeleted()) {
     128           0 :             return false;
     129             :         }
     130         541 :         return filter_->EdgeFilter(src, tgt, edge);
     131             :     }
     132             : 
     133             : private:
     134             :     const DBGraph *graph_;
     135             :     const VisitorFilter *filter_;
     136             : };
     137             : 
     138             : struct DBGraph::VertexPredicate {
     139             :     VertexPredicate() : graph_(NULL), filter_(NULL) { }
     140         130 :     VertexPredicate(const DBGraph *graph, const VisitorFilter &filter)
     141         130 :         : graph_(graph), filter_(&filter) {
     142         130 :     }
     143         535 :     bool operator()(const DBGraphVertex *entry) const {
     144         535 :         if (entry->IsDeleted()) {
     145           0 :             return false;
     146             :         }
     147         535 :         return filter_->VertexFilter(entry);
     148             :     }
     149             : private:
     150             :     const DBGraph *graph_;
     151             :     const VisitorFilter *filter_;
     152             : };
     153             : 
     154         541 : DBGraphVertex *DBGraph::vertex_target(DBGraphVertex *current_vertex,
     155             :                                       DBGraphEdge *edge) {
     156         541 :     DBGraphVertex *adjacent_vertex = edge->target(this);
     157         541 :     if (adjacent_vertex == current_vertex) {
     158         246 :         adjacent_vertex = edge->source(this);
     159             :     }
     160         541 :     return adjacent_vertex;
     161             : }
     162             : 
     163             : 
     164        3428 : void DBGraph::IterateEdges(DBGraphVertex *current_vertex,
     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        3969 :     for (; iter_begin != iter_end; ++iter_begin) {
     172        3085 :         const DBGraph::EdgeProperties &e_prop = get(edge_bundle, *iter_begin);
     173        3085 :         DBGraphEdge *edge = e_prop.edge;
     174        3085 :         if (match_name && e_prop.name() != allowed_edge) break;
     175         541 :         DBGraphVertex *adjacent_vertex = vertex_target(current_vertex, edge);
     176         541 :         if (edge_visit_fn) edge_visit_fn(edge);
     177         552 :         if (!edge_test(current_vertex, adjacent_vertex, edge)) continue;
     178         416 :         if (adjacent_vertex->visited(curr_walk)) continue;
     179         405 :         if (vertex_test(adjacent_vertex)) {
     180         399 :             vertex_visit_fn(adjacent_vertex);
     181         399 :             visit_q.push(adjacent_vertex);
     182             :         }
     183         405 :         adjacent_vertex->set_visited(curr_walk);
     184             :     }
     185        3428 : }
     186             : 
     187         130 : void DBGraph::Visit(DBGraphVertex *start, VertexVisitor vertex_visit_fn,
     188             :                     EdgeVisitor edge_visit_fn, const VisitorFilter &filter) {
     189             :     // uint64_t t = ClockMonotonicUsec();
     190         130 :     ::uint64_t curr_walk = get_graph_walk_num(); /* ::uint64_t because using namespace boost above */
     191         130 :     EdgePredicate edge_test(this, filter);
     192         130 :     VertexPredicate vertex_test(this, filter);
     193             : 
     194         130 :     VisitQ visit_q;
     195             : 
     196         130 :     visit_q.push(start);
     197         130 :     start->set_visited(curr_walk);
     198         130 :     if (vertex_test(start)) {
     199         130 :         vertex_visit_fn(start);
     200             :     }
     201         659 :     while (!visit_q.empty()) {
     202         529 :         DBGraphVertex *vertex = visit_q.front();
     203         529 :         visit_q.pop();
     204             :         // Get All out-edges from the node
     205         529 :         OutEdgeListType &out_edge_set = graph_.out_edge_list(vertex->vertex());
     206         529 :         if (out_edge_set.empty()) continue;
     207             : 
     208         525 :         OutEdgeListType::iterator it = out_edge_set.begin();
     209         525 :         OutEdgeListType::iterator it_end = out_edge_set.end();
     210             : 
     211             :         // Collect all allowed edges to visit
     212             :         DBGraph::VisitorFilter::AllowedEdgeRetVal allowed_edge_ret =
     213         525 :             filter.AllowedEdges(vertex);
     214             : 
     215         525 :         if (!allowed_edge_ret.first) {
     216        3913 :             for (auto allowed_edge : allowed_edge_ret.second) {
     217        3408 :                 EdgeContainer fake_container;
     218        3408 :                 fake_container.push_back(
     219        6816 :                          EdgeType(0, 0, EdgeProperties(allowed_edge, NULL)));
     220        3408 :                 StoredEdge es(vertex->vertex(), fake_container.begin());
     221             :                 // Call lower_bound on out edge list and walk on selected edges
     222        3408 :                 it = out_edge_set.lower_bound(es);
     223        3408 :                 IterateEdges(vertex, it, it_end, vertex_visit_fn, edge_visit_fn,
     224             :                 edge_test, vertex_test, curr_walk, visit_q, true, allowed_edge);
     225        3408 :             }
     226             :         } else {
     227          20 :             IterateEdges(vertex, it, it_end, vertex_visit_fn, edge_visit_fn,
     228             :                          edge_test, vertex_test, curr_walk, visit_q);
     229             :         }
     230         525 :     }
     231             :     // uint64_t end_t = ClockMonotonicUsec();
     232             :     // std::cout << "Graph Walk time(in usec) " <<  (end_t-t) << std::endl;
     233         130 : }
     234             : 
     235          22 : DBGraph::edge_iterator::edge_iterator(DBGraph *graph) : graph_(graph) {
     236          22 :     if (graph_) {
     237           8 :         boost::tie(iter_, end_) = edges(*graph_->graph());
     238             :     }
     239          22 : }
     240             : 
     241           8 : DBGraph::DBEdgeInfo DBGraph::edge_iterator::dereference() const {
     242           8 :     Vertex src = source(*iter_, *graph_->graph());
     243           8 :     Vertex tgt = target(*iter_, *graph_->graph());
     244           8 :     return boost::make_tuple(graph_->vertex_data(src), graph_->vertex_data(tgt),
     245          24 :                              graph_->edge_data(*iter_));
     246             : }
     247             : 
     248          14 : bool DBGraph::edge_iterator::equal(const edge_iterator &rhs) const {
     249          14 :     if (graph_ != NULL) {
     250          14 :         if (rhs.graph_ == NULL) {
     251          14 :             return (iter_ == end_);
     252             :         }
     253           0 :         return iter_ == rhs.iter_;
     254             :     } else {
     255           0 :         if (rhs.graph_ != NULL) {
     256           0 :             return (rhs.iter_ == rhs.end_);
     257             :         }
     258           0 :         return true;
     259             :     }
     260             : }
     261             : 
     262           6 : DBGraph::edge_iterator DBGraph::edge_list_begin() {
     263           6 :     return edge_iterator(this);
     264             : }
     265             : 
     266          14 : DBGraph::edge_iterator DBGraph::edge_list_end() {
     267          14 :     return edge_iterator(NULL);
     268             : }
     269             : 
     270          21 : DBGraph::vertex_iterator::vertex_iterator(DBGraph *graph)
     271          21 :     : graph_(graph) {
     272          21 :     if (graph_ != NULL) {
     273           5 :         boost::tie(iter_, end_) = vertices(*graph_->graph());
     274             :     }
     275          21 : }
     276             : 
     277          16 : bool DBGraph::vertex_iterator::equal(const vertex_iterator &rhs) const {
     278          16 :     if (graph_ != NULL) {
     279          16 :         if (rhs.graph_ != NULL) {
     280           0 :             return iter_ == rhs.iter_;
     281             :         } else {
     282          16 :             return (iter_ == end_);
     283             :         }
     284             :     } else {
     285           0 :         if (rhs.graph_ != NULL) {
     286           0 :             return rhs.iter_ == rhs.end_;
     287             :         } else {
     288           0 :             return true;
     289             :         }
     290             :     }
     291             : }
     292             : 
     293           3 : DBGraph::vertex_iterator DBGraph::vertex_list_begin() {
     294           3 :     return vertex_iterator(this);
     295             : }
     296             : 
     297          16 : DBGraph::vertex_iterator DBGraph::vertex_list_end() {
     298          16 :     return vertex_iterator(NULL);
     299             : }
     300             : 
     301           3 : void DBGraph::clear() {
     302           3 :     graph_.clear();
     303           3 : }
     304             : 
     305         585 : size_t DBGraph::vertex_count() const {
     306         585 :     return num_vertices(graph_);
     307             : }
     308             : 
     309         536 : size_t DBGraph::edge_count() const {
     310         536 :     return num_edges(graph_);
     311             : }
     312             : 
     313             : template <class StoredEdge>
     314      300761 : bool order_by_name<StoredEdge>::operator()(const StoredEdge& e1, const StoredEdge& e2) const {
     315      300761 :     const DBGraph::EdgeProperties &edge1 = get(edge_bundle, e1);
     316      300761 :     const DBGraph::EdgeProperties &edge2 = get(edge_bundle, e2);
     317      300761 :     return edge1.name() < edge2.name();
     318             : }

Generated by: LCOV version 1.14