LCOV - code coverage report
Current view: top level - ifmap - ifmap_dependency_tracker.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 96 98 98.0 %
Date: 2026-08-17 02:09:53 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "ifmap/ifmap_dependency_tracker.h"
       6             : 
       7             : #include <sstream>
       8             : #include <boost/assign/list_of.hpp>
       9             : 
      10             : #include "ifmap/ifmap_link.h"
      11             : #include "ifmap/ifmap_node.h"
      12             : #include "ifmap/ifmap_table.h"
      13             : 
      14             : using namespace boost::assign;
      15             : using namespace std;
      16             : 
      17        8198 : IFMapDependencyTracker::IFMapDependencyTracker(
      18        8198 :     DB *db, DBGraph *graph, ChangeObserver observer)
      19        8198 :         : database_(db), graph_(graph), observer_(observer) {
      20        8198 : }
      21             : 
      22             : //
      23             : // Add an IFMapNode to the NodeList for further propagation if it's an
      24             : // interesting node. It's interesting if there's an entry for self in the
      25             : // ReactionMap.
      26             : //
      27             : // Node event is added based on "add_node_event" flag
      28             : //
      29      197667 : void IFMapDependencyTracker::NodeEvent(IFMapNode *node, bool add_node_event) {
      30      197667 :     if (add_node_event)
      31      192036 :         AddChangeEvent(node);
      32      197667 :     if (IsInterestingEvent(node, "self")) {
      33      146195 :         node_list_.push_back(
      34      292390 :             make_pair(node->table()->Typename(), node->name()));
      35             :     }
      36      197667 : }
      37             : 
      38             : //
      39             : // Add an IFMapNode to the NodeList for further propagation if it's an
      40             : // interesting node. It's interesting if there's an entry for self in the
      41             : // ReactionMap.
      42             : //
      43             : // The node is always added to the ChangeList even if it's not interesting.
      44             : //
      45      192036 : void IFMapDependencyTracker::NodeEvent(IFMapNode *node) {
      46      192036 :     NodeEvent(node, true);
      47      192036 : }
      48             : 
      49             : //
      50             : // Check both the edges corresponding to the IFMapLink and add them to the
      51             : // EdgeDescriptorList if interesting. An edge is considered interesting if
      52             : // there's an entry for the metadata in the ReactionMap for the IFMapNode's
      53             : // identifier type.
      54             : //
      55      253769 : bool IFMapDependencyTracker::LinkEvent(const string metadata,
      56             :     IFMapNode *left, IFMapNode *right) {
      57      253769 :     bool interest = false;
      58             : 
      59      253769 :     if ((left != NULL) && IsInterestingEvent(left, metadata)) {
      60      110032 :         const char *type_left = left->table()->Typename();
      61      110032 :         edge_list_.push_back(
      62      220064 :             EdgeDescriptor(metadata, type_left, left->name()));
      63      110032 :         interest = true;
      64             :     }
      65      253769 :     if ((right != NULL) && IsInterestingEvent(right, metadata)) {
      66       78338 :         const char *type_right = right->table()->Typename();
      67       78338 :         edge_list_.push_back(
      68      156676 :             EdgeDescriptor(metadata, type_right, right->name()));
      69       78338 :         interest = true;
      70             :     }
      71             : 
      72      253769 :     return interest;
      73             : }
      74             : 
      75             : //
      76             : // Walk the NodeList and EdgeDescriptorList and evaluate the NodeEventPolicy
      77             : // to build up the change list. The InEdgeSet is used to avoid evaluating the
      78             : // same EdgeDescriptor more than once, hence avoiding any loops in the graph.
      79             : //
      80       70095 : void IFMapDependencyTracker::PropagateChanges() {
      81       70095 :     InEdgeSet in_edges;
      82             : 
      83       70095 :     for (NodeList::iterator iter = node_list_.begin();
      84      216290 :          iter != node_list_.end(); ++iter) {
      85             :         IFMapTable *table =
      86      146195 :             IFMapTable::FindTable(database_, iter->first);
      87      146195 :         if (table == NULL) {
      88           0 :             continue;
      89             :         }
      90      146195 :         IFMapNode *node = table->FindNode(iter->second);
      91      146195 :         if ((node == NULL) || node->IsDeleted()) {
      92           4 :             continue;
      93             :         }
      94      146191 :         PropagateNode(node, &in_edges);
      95             :     }
      96             : 
      97       70095 :     for (EdgeDescriptorList::iterator iter = edge_list_.begin();
      98      258465 :          iter != edge_list_.end(); ++iter) {
      99      188370 :         const EdgeDescriptor &edge = *iter;
     100             :         IFMapTable *table =
     101      188370 :             IFMapTable::FindTable(database_, edge.id_type);
     102      188370 :         if (table == NULL) {
     103           0 :             continue;
     104             :         }
     105      188370 :         IFMapNode *node = table->FindNode(edge.id_name);
     106      188370 :         if ((node == NULL) || node->IsDeleted()) {
     107           3 :             continue;
     108             :         }
     109      188367 :         PropagateEdge(node, edge.metadata, &in_edges);
     110             :     }
     111       70095 : }
     112             : 
     113             : //
     114             : // Clear all intermediate state used during propagation. This is called after
     115             : // we're done propagating all accumulated node and edge triggers to the change
     116             : // list.
     117             : //
     118       70095 : void IFMapDependencyTracker::Clear() {
     119       70095 :     node_list_.clear();
     120       70095 :     edge_list_.clear();
     121       70095 : }
     122             : 
     123             : //
     124             : // Get the PropagateList for the given identifier type and metadata.
     125             : //
     126             : const IFMapDependencyTracker::PropagateList *
     127     1069755 : IFMapDependencyTracker::GetPropagateList(
     128             :     const string &type, const string &metadata) const {
     129             : 
     130     1069755 :     NodeEventPolicy::const_iterator ploc = policy_.find(type);
     131     1069755 :     if (ploc == policy_.end()) {
     132      159317 :         return NULL;
     133             :     }
     134      910438 :     ReactionMap::const_iterator rloc = ploc->second.find(metadata);
     135      910438 :     if (rloc == ploc->second.end()) {
     136       67257 :         return NULL;
     137             :     }
     138      843181 :     return &rloc->second;
     139             : }
     140             : 
     141             : //
     142             : // Determine if the event specified by the node and metadata is interesting.
     143             : // It's interesting if the NodeEventPolicy has non-empty propagate list for
     144             : // the event.
     145             : //
     146      664739 : bool IFMapDependencyTracker::IsInterestingEvent(
     147             :     const IFMapNode *node, const string &metadata) const {
     148      664739 :     if (node->IsDeleted()) {
     149      103600 :         return false;
     150             :     }
     151      561139 :     return GetPropagateList(node->table()->Typename(), metadata) != NULL;
     152             : }
     153             : 
     154             : //
     155             : // Propagate changes for a IFMapNode on the NodeList.  The fact that it's on
     156             : // the NodeList means that the node must have been deemed interesting and so
     157             : // it's PropagateList must be non-empty.
     158             : //
     159      146191 : void IFMapDependencyTracker::PropagateNode(
     160             :     IFMapNode *node, InEdgeSet *in_edges) {
     161             : 
     162             :     const PropagateList *plist =
     163      146191 :         GetPropagateList(node->table()->Typename(), "self");
     164      146191 :     assert(plist);
     165             : 
     166             :     // Iterate through the edges of node. If the metadata for an edge is in
     167             :     // the PropagateList, we need to propagate changes for the edge itself.
     168      146191 :     for (DBGraphVertex::edge_iterator iter =
     169      146191 :          node->edge_list_begin(graph_);
     170      358850 :          iter != node->edge_list_end(graph_); ++iter) {
     171      212659 :         IFMapLink *link = static_cast<IFMapLink *>(iter.operator->());
     172      212659 :         IFMapNode *target = static_cast<IFMapNode *>(iter.target());
     173      212659 :         if (plist->find(link->metadata()) == plist->end()) {
     174      118129 :             continue;
     175             :         }
     176       94530 :         PropagateEdge(target, link->metadata(), in_edges);
     177             :     }
     178      146191 : }
     179             : 
     180             : //
     181             : // Propagate changes for an edge on the EdgeDescriptorList.
     182             : //
     183      362425 : void IFMapDependencyTracker::PropagateEdge(
     184             :     IFMapNode *node, const string &metadata, InEdgeSet *in_edges) {
     185      362425 :     assert(!node->IsDeleted());
     186             : 
     187             :     // Make a bidirectional check i.e. policy terms that apply to the two
     188             :     // edges for a link must be symmetrical.
     189             :     const PropagateList *plist =
     190      362425 :         GetPropagateList(node->table()->Typename(), metadata);
     191      362425 :     assert(plist);
     192             : 
     193             :     // Skip if this edge in already in the InEdgeSet i.e. it's a duplicate.
     194      362425 :     if (in_edges->count(make_pair(node, metadata)) > 0) {
     195      144043 :         return;
     196             :     }
     197             : 
     198             :     // Add entry to InEdgeSet for loop prevention.
     199      218382 :     in_edges->insert(make_pair(node, metadata));
     200             : 
     201             :     // Add the node corresponding to this edge to the change list if there's
     202             :     // an entry for self in the PropagateList.
     203      218382 :     PropagateList::const_iterator self = plist->find("self");
     204      218382 :     if (self != plist->end()) {
     205      144760 :         AddChangeEvent(node);
     206             :     }
     207             : 
     208             :     // Iterate through the edges of node. If the metadata for an edge is in
     209             :     // the PropagateList, we need to propagate changes for the edge itself.
     210      218382 :     for (DBGraphVertex::edge_iterator iter =
     211      218382 :          node->edge_list_begin(graph_);
     212     1112941 :          iter != node->edge_list_end(graph_); ++iter) {
     213      894559 :         IFMapLink *link = static_cast<IFMapLink *>(iter.operator->());
     214      894559 :         if (plist->find(link->metadata()) == plist->end()) {
     215      815031 :             continue;
     216             :         }
     217       79528 :         IFMapNode *target = static_cast<IFMapNode *>(iter.target());
     218       79528 :         PropagateEdge(target, link->metadata(), in_edges);
     219             :     }
     220             : }
     221             : 
     222             : //
     223             : // Add the IFMapNode to the change list.
     224             : //
     225      336796 : void IFMapDependencyTracker::AddChangeEvent(IFMapNode *node) {
     226      336796 :     observer_(node);
     227      336796 : }
     228             : 

Generated by: LCOV version 1.14