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