LCOV - code coverage report
Current view: top level - db - db_table_walk_mgr.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 13 13 100.0 %
Date: 2026-06-22 02:21:21 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #ifndef ctrlplane_db_table_walk_mgr_h
       6             : #define ctrlplane_db_table_walk_mgr_h
       7             : 
       8             : #include <list>
       9             : #include <set>
      10             : #include <mutex>
      11             : 
      12             : #include <boost/assign.hpp>
      13             : #include <boost/function.hpp>
      14             : #include <boost/scoped_ptr.hpp>
      15             : #include <boost/shared_ptr.hpp>
      16             : 
      17             : 
      18             : #include "base/logging.h"
      19             : #include "base/task_trigger.h"
      20             : #include "base/util.h"
      21             : 
      22             : #include "db/db_table.h"
      23             : 
      24             : //
      25             : // DBTableWalkMgr:
      26             : // ==============
      27             : // DBTableWalkMgr provides infrastructure to walk DBTable.
      28             : //
      29             : // DBTable class provides API for walking DBTable. Following APIs are provided
      30             : //
      31             : //    1. AllocWalker: This API allocates a walk handle and returns to the caller
      32             : //      Application is suppose to release the walker using ReleaseWalker.
      33             : //
      34             : //      AllocWalker API can be called from any task context.
      35             : //
      36             : //      Application provides two callback function as input to for this API.
      37             : //
      38             : //      DBTable::WalkFn : Callback invoked by walk infra while traversing each
      39             : //           DBEntry in DBTable. This API is invoked in db::DBTable task context
      40             : //           by default. Application can configure the task id in which
      41             : //           DBTable walk is performed using DBTable::SetWalkTaskId
      42             : //
      43             : //      DBTable::WalkCompleteFn: Callback invoked by walk infra on completion of
      44             : //           ongoing walk request. This API is invoked in db::Walker task
      45             : //           context irrespective of the task id set with DBTable::SetWalkTaskId
      46             : //           This callback is not invoked in cases where application
      47             : //           calls ReleaseWalker on ongoing walker. Also, WalkCompleteFn is
      48             : //           called only after handling all WalkAgain requests on the walker.
      49             : //
      50             : //    2. ReleaseWalker: This API releases the walker. After invoking this API,
      51             : //    application will stop getting Walk callback for the ongoing Walk request.
      52             : //    Application should not refer to the DBTableWalkRef after invoking this API
      53             : //
      54             : //    ReleaseWalker API can be called from any task context.
      55             : //
      56             : //    3. WalkTable: This API starts the table walk. This API should be called
      57             : //    from a task which is mutually exclusive from db::Walker task.
      58             : //
      59             : //    4. WalkAgain: To re-trigger/restart current walk request from application.
      60             : //    Callback for WalkFn is no longer invoked for ongoing walk and walk is
      61             : //    restarted from beginning of DBTable. This API should be called from a task
      62             : //    which is mutually exclusive from db::Walker task.
      63             : //
      64             : // DBTableWalkMgr ensures that not more than one DBTable is walked at any point
      65             : // in time. All other DBTable walk requests are queued and taken up only after
      66             : // current walk completes.
      67             : // Actual DBTable walk (i.e. iterating the DBTablePartition) is performed in
      68             : // db::DBTable task or task id configured with DBTable::SetWalkTaskId with
      69             : // instance id set as partition index.
      70             : // The advantage of running DBTable walk in serial manner is in clubbing
      71             : // multiple walk requests on a given table and serving such requests in one
      72             : // iteration of DBTable walk
      73             : //
      74             : // WalkReqList holds list of DBTableWalkRef(i.e. walkers created by multiple
      75             : // application modules) that requested for DBTable walk on a specific table.
      76             : // InvokeWalkCb notifies all such walkers stored in current_table_walk_, while
      77             : // iterating through DBTable entries
      78             : //
      79             : // WalkRequestInfo:
      80             : // ===============
      81             : // WalkRequestInfo is a per table Walk request structure. It also holds
      82             : // DBTableWalkRef which requested for DBTable walk.
      83             : //
      84             : // WalkRequestInfoList
      85             : // ===================
      86             : // walk_request_list_ holds list of WalkRequestInfo. This list is keyed by
      87             : // DBTable. Additional walk_request_set_ is maintained for easy search of
      88             : // WalkRequestInfo for a given DBTable.
      89             : // Current table on which walk is going on will not be present in the
      90             : // walk_request_list_. If caller requests for WalkAgain(), it is added back to
      91             : // the walk_request_list_ (in the end of the list).
      92             : //
      93             : // Task Triggers:
      94             : // walk_request_trigger_ : Task trigger which evaluate walk_request_list_.
      95             : // It removes the WalkRequestInfo on top of this list and starts walk on the
      96             : // table. This task trigger runs in "db::Walker" task context.
      97             : //
      98             : // walk_done_trigger_ : Task trigger ensures that WalkCompleteFn is triggered
      99             : // in db::Walker task context for all DBTableWalkRef which requested for
     100             : // current DBTable walk. At the end of ProcessWalkDone, walk_request_trigger_ is
     101             : // triggered to evaluate walk request from top of walk_request_list_.
     102             : //
     103             : class DBTableWalkMgr {
     104             : public:
     105             :     DBTableWalkMgr();
     106             : 
     107          22 :     void DisableWalkProcessing() {
     108          22 :         walk_request_trigger_->set_disable();
     109          22 :     }
     110             : 
     111          22 :     void EnableWalkProcessing() {
     112          22 :         walk_request_trigger_->set_enable();
     113          22 :     }
     114             : 
     115             :     void DisableWalkDoneTrigger() {
     116             :         walk_done_trigger_->set_disable();
     117             :     }
     118             : 
     119             :     void EnableWalkDoneTrigger() {
     120             :         walk_done_trigger_->set_enable();
     121             :     }
     122             : 
     123             : private:
     124             :     friend class DBTable;
     125             :     typedef std::set<DBTable::DBTableWalkRef> WalkReqList;
     126             : 
     127             :     struct WalkRequestInfo {
     128      481826 :         WalkRequestInfo(DBTable *table) : table(table) {
     129      481826 :         }
     130             : 
     131      255670 :         void AppendWalkReq(DBTable::DBTableWalkRef ref) {
     132      255670 :             pending_requests.insert(ref);
     133      255670 :         }
     134             : 
     135             :         void DeleteWalkReq(DBTable::DBTableWalkRef ref) {
     136             :             pending_requests.erase(ref);
     137             :         }
     138             : 
     139             :         bool WalkPending() {
     140             :             return !pending_requests.empty();
     141             :         }
     142             :         DBTable *table;
     143             :         WalkReqList pending_requests;
     144             :     };
     145             : 
     146             :     struct WalkRequestCompare {
     147     1233837 :         bool operator()(const WalkRequestInfo *lhs,
     148             :                         const WalkRequestInfo *rhs) const {
     149     1233837 :             return lhs->table < rhs->table;
     150             :         }
     151             :     };
     152             :     typedef boost::shared_ptr<WalkRequestInfo> WalkRequestInfoPtr;
     153             :     typedef std::list<WalkRequestInfoPtr> WalkRequestInfoList;
     154             :     typedef std::set<WalkRequestInfo *, WalkRequestCompare> WalkRequestInfoSet;
     155             : 
     156             :     // Create a DBTable Walker
     157             :     DBTable::DBTableWalkRef AllocWalker(DBTable *table, DBTable::WalkFn walk_fn,
     158             :                        DBTable::WalkCompleteFn walk_complete);
     159             : 
     160             :     // Release the Walker
     161             :     void ReleaseWalker(DBTable::DBTableWalkRef &walk);
     162             : 
     163             :     // Start a walk on the table.
     164             :     void WalkTable(DBTable::DBTableWalkRef walk);
     165             : 
     166             :     // DBTable finished walking
     167             :     void WalkDone();
     168             : 
     169             :     // Walk the table again
     170             :     void WalkAgain(DBTable::DBTableWalkRef walk);
     171             : 
     172             :     bool ProcessWalkRequestList();
     173             : 
     174             :     bool ProcessWalkDone();
     175             : 
     176             :     bool InvokeWalkCb(DBTablePartBase *part, DBEntryBase *entry);
     177             : 
     178             :     boost::scoped_ptr<TaskTrigger> walk_request_trigger_;
     179             :     boost::scoped_ptr<TaskTrigger> walk_done_trigger_;
     180             : 
     181             :     // Mutex to protect walk_request_list_ and walk_request_set_ as
     182             :     // Walk can be requested from task which may run concurrently
     183             :     std::mutex mutex_;
     184             :     WalkRequestInfoList walk_request_list_;
     185             :     WalkRequestInfoSet walk_request_set_;
     186             : 
     187             :     WalkReqList current_table_walk_;
     188             : 
     189             :     DISALLOW_COPY_AND_ASSIGN(DBTableWalkMgr);
     190             : };
     191             : 
     192             : #endif

Generated by: LCOV version 1.14