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

Generated by: LCOV version 1.14