LCOV - code coverage report
Current view: top level - ifmap - ifmap_dependency_tracker.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 6 6 100.0 %
Date: 2026-06-11 01:56:02 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : #ifndef IFMAP_IFMAP_DEPENDENCY_TRACKER_H__
       5             : #define IFMAP_IFMAP_DEPENDENCY_TRACKER_H__
       6             : 
       7             : #include <list>
       8             : #include <map>
       9             : #include <set>
      10             : #include <string>
      11             : #include <vector>
      12             : 
      13             : #include <boost/function.hpp>
      14             : 
      15             : class DB;
      16             : class DBGraph;
      17             : class IFMapNode;
      18             : 
      19             : //
      20             : // The DependencyTracker recursively evaluates dependencies as specified via a
      21             : // policy and pushes additional ConfigDeltas to the ChangeList.  This takes
      22             : // the burden of dependency tracking away from the consumers and automates it
      23             : // instead of being individually hand coded for each type of object.
      24             : //
      25             : // Elements are added onto the change list when they need to be reevaluated as
      26             : // a result of add/delete/change of other nodes and/or edges in the graph. The
      27             : // change list list is ultimately processed by the client
      28             : // (e.g. BgpConfigManager).
      29             : //
      30             : // The NodeEventPolicy is defined as a list of identifier types and associated
      31             : // ReactionMaps.
      32             : //
      33             : // A ReactionMap in turn is a mapping from a metadata type to a PropagateList,
      34             : // with the semantics that an add or delete of a edge of that type triggers a
      35             : // propagation across all edges with a type in the PropagateList. The keyword
      36             : // self is used instead of a metadata type to denote that the trigger is any
      37             : // change in the properties of the node itself. Note that the type of the node
      38             : // will always be the identifier type with which the ReactionMap is associated.
      39             : //
      40             : // A PropagateList is list of metadata types that need to be processed when
      41             : // propagating a change for a node or edge. They keyword self is used in this
      42             : // list to denote that the node associated with the edge should itself also be
      43             : // put on the ChangeList.
      44             : //
      45             : // The DependencyTracker is notified of Node and Link events by the listener.
      46             : // A Node event is considered interesting i.e. worthy of further propagation,
      47             : // if there's an entry for self in the ReactionMap for the identifier type.
      48             : //
      49             : // A Link is broken broken down into 2 unidirectional Edges.  An Edge consists
      50             : // of a Node and the associated metadata for the Link.  An Edge is considered
      51             : // interesting if there's an entry for the metadata in the ReactionMap for the
      52             : // Node's identifier type.
      53             : //
      54             : // A list of interesting Nodes and Edges is constructed based on Node and Link
      55             : // events as described above. Eventually, the DependencyTracker evaluates all
      56             : // the Nodes and Edges and recursively applies the NodeEventPolicy and builds
      57             : // up the change list of Nodes that needs to be processed by the client
      58             : // (e.g. BgpConfigManager).
      59             : // When applying the PropagateList, if the keyword self is present in the list
      60             : // the Node itself is added to the change list.  In any case, the rest of the
      61             : // metadata elements in the list are used to further propagate the changes.
      62             : //
      63             : // The NodeList and EdgeDescriptorList are both maintained using string names
      64             : // for the id type, id name and metadata.  Thus the DependencyTracker doesn't
      65             : // take any references on the IFMapNode objects. If an IFMapNode gets deleted
      66             : // before the changes in the NodeList and EdgeDescriptorList are propagated,
      67             : // we simply ignore the relevant nodes and edges when propagating the changes.
      68             : //
      69             : // Node and Link events are processed in the context of the db::DBTable task.
      70             : // The propagation of the NodeList and EdgeDescriptorList happens in context
      71             : // of the client task (e.g. bgp::Config) when the its requesst the ChangeList.
      72             : //
      73             : // CONCURRENCY: Not thread-safe. The class assumes that the caller ensures
      74             : // that only a single method can run at a time.
      75             : //
      76             : class IFMapDependencyTracker {
      77             : public:
      78             :     struct EdgeDescriptor {
      79      185078 :         EdgeDescriptor(const std::string &meta, const std::string &type,
      80             :             const std::string &name)
      81      185078 :             : metadata(meta), id_type(type), id_name(name) {
      82      185078 :         }
      83             :         std::string metadata;
      84             :         std::string id_type;
      85             :         std::string id_name;
      86             :     };
      87             :     typedef std::list<EdgeDescriptor> EdgeDescriptorList;
      88             :     typedef std::list<std::pair<std::string, std::string> > NodeList;
      89             : 
      90             :     // identifier type -> (incoming metadata, outgoing metadata list)
      91             :     typedef std::set<std::string> PropagateList;
      92             :     typedef std::map<std::string, PropagateList> ReactionMap;
      93             :     typedef std::map<std::string, ReactionMap> NodeEventPolicy;
      94             : 
      95             :     typedef boost::function<void(IFMapNode *node)> ChangeObserver;
      96             :     IFMapDependencyTracker(DB *db, DBGraph *graph, ChangeObserver observer);
      97             : 
      98       16184 :     NodeEventPolicy *policy_map() { return &policy_; }
      99             : 
     100             :     void NodeEvent(IFMapNode *node);
     101             :     void NodeEvent(IFMapNode *node, bool add_node_event);
     102             :     bool LinkEvent(const std::string metadata,
     103             :         IFMapNode *left, IFMapNode *right);
     104             :     void PropagateChanges();
     105             :     void Clear();
     106             : 
     107         108 :     const NodeList &node_list() const { return node_list_; }
     108         114 :     const EdgeDescriptorList& edge_list() const { return edge_list_; }
     109             : 
     110             : private:
     111             :     typedef std::set<std::pair<IFMapNode *, std::string> > InEdgeSet;
     112             : 
     113             :     const PropagateList *GetPropagateList(const std::string &type,
     114             :         const std::string &metadata) const;
     115             :     bool IsInterestingEvent(const IFMapNode *node,
     116             :         const std::string &metadata) const;
     117             : 
     118             :     void PropagateNode(IFMapNode *node, InEdgeSet *in_edges);
     119             :     void PropagateEdge(IFMapNode *node, const std::string &metadata,
     120             :         InEdgeSet *in_edges);
     121             :     void AddChangeEvent(IFMapNode *node);
     122             : 
     123             :     DB *database_;
     124             :     DBGraph *graph_;
     125             :     ChangeObserver observer_;
     126             :     NodeEventPolicy policy_;
     127             :     EdgeDescriptorList edge_list_;
     128             :     NodeList node_list_;
     129             : };
     130             : 
     131             : #endif

Generated by: LCOV version 1.14