OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ksync_object.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #ifndef ctrlplane_ksync_object_h
6 #define ctrlplane_ksync_object_h
7 
8 #include <tbb/mutex.h>
9 #include <tbb/recursive_mutex.h>
10 #include <base/queue_task.h>
11 #include <base/timer.h>
12 #include <sandesh/sandesh_trace.h>
13 
14 #include "ksync_entry.h"
15 #include "ksync_index.h"
17 // Back-Ref management needs two trees,
18 // Back-Ref tree:
19 // --------------
20 // An entry of type <key-entry, back-ref-entry> means that key-entry is
21 // waiting for back-ref-entry to be added to kernel.
22 // Note, there can be more than one key-entry waiting on a single
23 // back-ref-entry. However, a key-entry can be waiting on only one
24 // back-ref-entry at a time.
25 //
26 // This is a dynamic tree. Entries are added only when constraints are not
27 // met. Entries will not be in tree when constraints are met.
28 //
29 // Fwd-Ref tree:
30 // -------------
31 // Holds forward reference information. If Object-A is waiting on Object-B
32 // Fwd-Ref tree will have an entry with Object-A as key and Object-B as data.
34 
37  reference_(ref) { };
38 
39  bool operator<(const KSyncFwdReference &rhs) const {
40  return (key_ < rhs.key_);
41  };
42 
43  boost::intrusive::set_member_hook<> node_;
46 };
47 
50  key_(key), back_reference_(ref) { };
51 
52  bool operator<(const KSyncBackReference &rhs) const {
53  if (key_ < rhs.key_)
54  return true;
55 
56  if (key_ > rhs.key_)
57  return false;
58 
60  return true;
61 
62  return false;
63  };
64 
65  boost::intrusive::set_member_hook<> node_;
68 };
69 
70 class KSyncObject {
71 public:
72  typedef boost::intrusive::member_hook<KSyncEntry,
73  boost::intrusive::set_member_hook<>,
75  typedef boost::intrusive::set<KSyncEntry, KSyncObjectNode> Tree;
76 
77  typedef boost::intrusive::member_hook<KSyncFwdReference,
78  boost::intrusive::set_member_hook<>,
80  typedef boost::intrusive::set<KSyncFwdReference, KSyncFwdRefNode> FwdRefTree;
81 
82  typedef boost::intrusive::member_hook<KSyncBackReference,
83  boost::intrusive::set_member_hook<>,
85  typedef boost::intrusive::set<KSyncBackReference, KSyncBackRefNode> BackRefTree;
86 
87  // Default constructor. No index needed
88  KSyncObject(const std::string &name);
89  // Constructor for objects needing index
90  KSyncObject(const std::string &name, int max_index);
91  // Destructor
92  virtual ~KSyncObject();
93 
94  // Initialise stale entry cleanup state machine.
95  void InitStaleEntryCleanup(boost::asio::io_context &ios,
96  uint32_t cleanup_time, uint32_t cleanup_intvl,
97  uint16_t entries_per_intvl);
98 
99  // Notify an event to KSyncEvent state-machine
100  void NotifyEvent(KSyncEntry *entry, KSyncEntry::KSyncEvent event);
101  // Call Notify event with mutex lock held
103  // Handle Netlink ACK message
104  virtual void NetlinkAck(KSyncEntry *entry, KSyncEntry::KSyncEvent event);
105  // Add a back-reference entry
106  void BackRefAdd(KSyncEntry *key, KSyncEntry *reference);
107  // Delete a back-reference entry
108  void BackRefDel(KSyncEntry *key);
109  // Re-valuate the back-reference entries
110  void BackRefReEval(KSyncEntry *key);
111 
112  // Create an entry
113  KSyncEntry *Create(const KSyncEntry *key);
114  KSyncEntry *Create(const KSyncEntry *key, bool skip_lookup);
115  // Create a Stale entry, which needs to be cleanedup as part for
116  // stale entry cleanup (timer).
117  // Derived class can choose to create this entry to manage stale
118  // states in Kernel
119  KSyncEntry *CreateStale(const KSyncEntry *key);
120  // Called on change to ksync_entry. Will resulting in sync of the entry
121  void Change(KSyncEntry *entry);
122  // Delete a KSyncEntry
123  void Delete(KSyncEntry *entry);
124  // Query function. Key is in entry
125  KSyncEntry *Find(const KSyncEntry *key);
126  // Get Next Function.
127  KSyncEntry *Next(const KSyncEntry *entry) const;
128  // Query KSyncEntry for key in entry. Create temporary entry if not present
129  KSyncEntry *GetReference(const KSyncEntry *key);
130 
131  // Called from Create or GetReference to Allocate a KSyncEntry.
132  // The KSyncEntry must be populated with fields in key and index
133  virtual KSyncEntry *Alloc(const KSyncEntry *key, uint32_t index) = 0;
134  virtual void Free(KSyncEntry *entry);
135 
136  //Callback when all the entries in table are deleted
137  virtual void EmptyTable(void) { };
138  bool IsEmpty(void) { return tree_.empty(); };
139 
140  virtual bool DoEventTrace(void) { return true; }
141  virtual void PreFree(KSyncEntry *entry) { }
142  static void Shutdown();
143 
144  std::size_t Size() { return tree_.size(); }
148 
149 protected:
150  // Create an entry with default state. Used internally
151  KSyncEntry *CreateImpl(const KSyncEntry *key);
152  // Clear Stale Entry flag
153  void ClearStale(KSyncEntry *entry);
154  // Big lock on the tree
155  // TODO: Make this more fine granular
156  mutable tbb::recursive_mutex lock_;
157  void ChangeKey(KSyncEntry *entry, uint32_t arg);
158  virtual void UpdateKey(KSyncEntry *entry, uint32_t arg) { }
159 
160  // derived class needs to implement GetKey,
161  // default impl will assert
162  virtual uint32_t GetKey(KSyncEntry *entry);
163 
164 private:
165  friend class KSyncEntry;
167 
168  // Free indication of an KSyncElement.
169  // Removes from tree and free index if allocated earlier
170  void FreeInd(KSyncEntry *entry, uint32_t index);
172 
173  bool IsIndexValid() const { return need_index_; }
174 
175  // timer Callback to trigger delete of stale entries.
176  bool StaleEntryCleanupCb();
177 
178  //Callback to do cleanup when DEL ACK is received.
179  virtual void CleanupOnDel(KSyncEntry *kentry) {}
180 
181  // Tree of all KSyncEntries
183  // Forward reference tree
185  // Back reference tree
187  // Does the KSyncEntry need index?
189  // Index table for KSyncObject
191  // scheduled for deletion
193 
194  // stale entry tree
195  std::set<KSyncEntry::KSyncEntryPtr> stale_entry_tree_;
196 
197  // Stale Entry Cleanup Timer
199 
203 
205 };
206 
207 // Special KSyncObject for DB client
208 class KSyncDBObject : public KSyncObject {
209 public:
210  // Response to DB Filter API using which derived class can choose to
211  // ignore or trigger delete for some of the DB entries.
212  // This can be used where we don't want to handle certain type of OPER
213  // DB entries in KSync, using this simplifies the behaviour defination
214  // for KSync Object.
216  DBFilterAccept, // Accept DB Entry Add/Change for processing
217  DBFilterIgnore, // Ignore DB Entry Add/Change
218  DBFilterDelete, // Ignore DB Entry Add/Change and clear previous state
219  DBFilterDelAdd, // Delete current ksync and add new one (key change)
221  };
222  // Create KSyncObject. DB Table will be registered later
223  KSyncDBObject(const std::string &name);
224  KSyncDBObject(const std::string &name, int max_index);
225 
226  KSyncDBObject(const std::string &name, DBTableBase *table);
227  // KSync DB Object with index allocation
228  KSyncDBObject(const std::string &name,
229  DBTableBase *table,
230  int max_index);
231 
232  // Destructor
233  virtual ~KSyncDBObject();
234 
235  // Register to a DB Table
236  void RegisterDb(DBTableBase *table);
237 
238  //Unregister from a DB table
239  void UnregisterDb(DBTableBase *table);
240 
241  // Callback registered to DB Table
242  void Notify(DBTablePartBase *partition, DBEntryBase *entry);
243 
246 
247  // Function to filter DB Entries to be used, default behaviour will accept
248  // All DB Entries, needs to be overriden by derived class to get desired
249  // behavior.
250  virtual DBFilterResp DBEntryFilter(const DBEntry *entry,
251  const KSyncDBEntry *ksync);
252  // Populate Key in KSyncEntry from DB Entry.
253  // Used for lookup of KSyncEntry from DBEntry
254  virtual KSyncEntry *DBToKSyncEntry(const DBEntry *entry) = 0;
256  DBTableBase::ListenerId id() const {return id_;}
257 
258 private:
259  //Callback to do cleanup when DEL ACK is received.
260  virtual void CleanupOnDel(KSyncEntry *kentry);
261 
265 
268 };
269 
271  enum Event {
275  };
277  obj_(obj), event_(event) {
278  }
282 };
283 
285 public:
286  static const int kMaxEntriesProcess = 100;
287 
290  bool Process(KSyncObjectEvent *event);
291  void Enqueue(KSyncObjectEvent *event);
293  static KSyncObjectManager *Init();
294  static void Shutdown();
295  static void Unregister(KSyncObject *);
296  void Delete(KSyncObject *);
298 private:
300  static std::unique_ptr<KSyncEntry> default_defer_entry_;
302 };
303 
304 #define KSYNC_TRACE(obj, parent, ...)\
305 do {\
306  KSync##obj::TraceMsg(parent->GetKSyncTraceBuf(), __FILE__, __LINE__, ##__VA_ARGS__);\
307 } while (false)
308 
309 #endif // ctrlplane_ksync_object_h
boost::intrusive::set< KSyncEntry, KSyncObjectNode > Tree
Definition: ksync_object.h:75
boost::intrusive::member_hook< KSyncFwdReference, boost::intrusive::set_member_hook<>,&KSyncFwdReference::node_ > KSyncFwdRefNode
Definition: ksync_object.h:79
virtual SandeshTraceBufferPtr GetKSyncTraceBuf()
Definition: ksync_object.h:147
void Change(KSyncEntry *entry)
DISALLOW_COPY_AND_ASSIGN(KSyncObject)
void InitStaleEntryCleanup(boost::asio::io_context &ios, uint32_t cleanup_time, uint32_t cleanup_intvl, uint16_t entries_per_intvl)
Definition: ksync_object.cc:79
virtual DBFilterResp DBEntryFilter(const DBEntry *entry, const KSyncDBEntry *ksync)
KSyncEntry * Next(const KSyncEntry *entry) const
virtual KSyncEntry * DBToKSyncEntry(const DBEntry *entry)=0
void RegisterDb(DBTableBase *table)
bool operator<(const KSyncBackReference &rhs) const
Definition: ksync_object.h:52
uint16_t stale_entries_per_intvl_
Definition: ksync_object.h:201
KSyncObject(const std::string &name)
Definition: ksync_object.cc:55
KSyncIndexTable index_table_
Definition: ksync_object.h:266
DBTableBase::ListenerId test_id_
Definition: ksync_object.h:264
DISALLOW_COPY_AND_ASSIGN(KSyncDBObject)
void BackRefDel(KSyncEntry *key)
int ListenerId
Definition: db_table.h:62
boost::intrusive::member_hook< KSyncBackReference, boost::intrusive::set_member_hook<>,&KSyncBackReference::node_ > KSyncBackRefNode
Definition: ksync_object.h:84
void Delete(KSyncEntry *entry)
WorkQueue< KSyncObjectEvent * > * event_queue_
Definition: ksync_object.h:299
KSyncEntry * back_reference_
Definition: ksync_object.h:67
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
Definition: sandesh_trace.h:18
bool StaleEntryCleanupCb()
static void Unregister(KSyncObject *)
virtual void Free(KSyncEntry *entry)
bool delete_scheduled()
Definition: ksync_object.h:146
virtual void NetlinkAck(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
void ChangeKey(KSyncEntry *entry, uint32_t arg)
void Enqueue(KSyncObjectEvent *event)
void set_delete_scheduled()
Definition: ksync_object.h:145
virtual void CleanupOnDel(KSyncEntry *kentry)
KSyncEntry * key_
Definition: ksync_object.h:44
KSyncObjectEvent(KSyncObject *obj, Event event)
Definition: ksync_object.h:276
void NetlinkAckInternal(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
boost::intrusive::set< KSyncBackReference, KSyncBackRefNode > BackRefTree
Definition: ksync_object.h:85
std::set< KSyncEntry::KSyncEntryPtr > stale_entry_tree_
Definition: ksync_object.h:195
KSyncEntry * CreateImpl(const KSyncEntry *key)
virtual bool DoEventTrace(void)
Definition: ksync_object.h:140
Timer * stale_entry_cleanup_timer_
Definition: ksync_object.h:198
friend void TestTriggerStaleEntryCleanupCb(KSyncObject *obj)
Definition: ksync_object.cc:51
virtual void UpdateKey(KSyncEntry *entry, uint32_t arg)
Definition: ksync_object.h:158
KSyncDBObject(const std::string &name)
void SafeNotifyEvent(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
boost::intrusive::set_member_hook node_
Definition: ksync_entry.h:188
DBTableBase::ListenerId id() const
Definition: ksync_object.h:256
DBTableBase * GetDBTable()
Definition: ksync_object.h:244
boost::intrusive_ptr< KSyncEntry > KSyncEntryPtr
Definition: ksync_entry.h:68
SandeshTraceBufferPtr KSyncTraceBuf
Definition: ksync_object.h:202
KSyncEntry * reference_
Definition: ksync_object.h:45
void BackRefAdd(KSyncEntry *key, KSyncEntry *reference)
void ClearStale(KSyncEntry *entry)
bool operator<(const KSyncFwdReference &rhs) const
Definition: ksync_object.h:39
virtual ~KSyncDBObject()
static void Shutdown()
Definition: ksync_object.cc:94
virtual uint32_t GetKey(KSyncEntry *entry)
void Notify(DBTablePartBase *partition, DBEntryBase *entry)
void NotifyEvent(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
uint32_t stale_entry_cleanup_intvl_
Definition: ksync_object.h:200
virtual ~KSyncObject()
Definition: ksync_object.cc:72
static BackRefTree back_ref_tree_
Definition: ksync_object.h:186
std::size_t Size()
Definition: ksync_object.h:144
virtual void PreFree(KSyncEntry *entry)
Definition: ksync_object.h:141
KSyncEntry * Find(const KSyncEntry *key)
Definition: ksync_object.cc:99
DBTableBase::ListenerId id_
Definition: ksync_object.h:263
KSyncFwdReference(KSyncEntry *key, KSyncEntry *ref)
Definition: ksync_object.h:36
bool IsEmpty(void)
Definition: ksync_object.h:138
KSyncEntry * GetReference(const KSyncEntry *key)
bool Process(KSyncObjectEvent *event)
void FreeInd(KSyncEntry *entry, uint32_t index)
KSyncEntry * Create(const KSyncEntry *key)
void BackRefReEval(KSyncEntry *key)
boost::intrusive::set_member_hook node_
Definition: ksync_object.h:41
bool IsIndexValid() const
Definition: ksync_object.h:173
boost::intrusive::set< KSyncFwdReference, KSyncFwdRefNode > FwdRefTree
Definition: ksync_object.h:80
DBTableBase::ListenerId GetListenerId(DBTableBase *table)
static std::unique_ptr< KSyncEntry > default_defer_entry_
Definition: ksync_object.h:300
KSyncEntry * CreateStale(const KSyncEntry *key)
void Delete(KSyncObject *)
static const int kMaxEntriesProcess
Definition: ksync_object.h:286
boost::intrusive::member_hook< KSyncEntry, boost::intrusive::set_member_hook<>,&KSyncEntry::node_ > KSyncObjectNode
Definition: ksync_object.h:74
bool delete_scheduled_
Definition: ksync_object.h:192
bool need_index_
Definition: ksync_object.h:188
tbb::recursive_mutex lock_
Definition: ksync_object.h:156
void UnregisterDb(DBTableBase *table)
static FwdRefTree fwd_ref_tree_
Definition: ksync_object.h:184
static KSyncEntry * default_defer_entry()
static KSyncObjectManager * Init()
void set_test_id(DBTableBase::ListenerId id)
virtual void CleanupOnDel(KSyncEntry *kentry)
Definition: ksync_object.h:179
static void Shutdown()
virtual void EmptyTable(void)
Definition: ksync_object.h:137
Definition: timer.h:54
virtual KSyncEntry * Alloc(const KSyncEntry *key, uint32_t index)=0
static KSyncObjectManager * GetInstance()
KSyncObject * obj_
Definition: ksync_object.h:280
static KSyncObjectManager * singleton_
Definition: ksync_object.h:301
friend class KSyncEntry
Definition: ksync_object.h:165
KSyncIndexTable index_table_
Definition: ksync_object.h:190
DBTableBase * table_
Definition: ksync_object.h:262
KSyncEntry * key_
Definition: ksync_object.h:66
KSyncEntry::KSyncEntryPtr ref_
Definition: ksync_object.h:279
KSyncBackReference(KSyncEntry *key, KSyncEntry *ref)
Definition: ksync_object.h:49
boost::intrusive::set_member_hook node_
Definition: ksync_object.h:63