OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ksync_object.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <sys/socket.h>
6 #include <sys/types.h>
7 #if defined(__linux__)
8 #include <linux/netlink.h>
9 #include <linux/rtnetlink.h>
10 #include <linux/sockios.h>
11 #endif
12 
13 #include <boost/bind.hpp>
14 #include <boost/assign/list_of.hpp>
15 
16 #include <base/logging.h>
17 #include <db/db.h>
18 #include <db/db_entry.h>
19 #include <db/db_table.h>
20 #include <db/db_table_partition.h>
21 
22 #include <sandesh/sandesh_trace.h>
23 
24 #include "ksync_index.h"
25 #include "ksync_entry.h"
26 #include "ksync_object.h"
27 #include "ksync_types.h"
28 
30  SandeshTraceBufferCreate("KSync Error", 5000));
31 
35 std::unique_ptr<KSyncEntry> KSyncObjectManager::default_defer_entry_;
36 
37 typedef std::map<uint32_t, std::string> VrouterErrorDescriptionMap;
38 VrouterErrorDescriptionMap g_error_description =
39  boost::assign::map_list_of<uint32_t, std::string>
40  (ENOENT, "Entry not present")
41  (EBADF, "Key mismatch")
42  (ENOMEM, "Memory insufficient")
43  (EBUSY, "Object cannot be modified")
44  (EEXIST, "Object already present")
45  (ENODEV, "Object not present")
46  (EINVAL, "Invalid object parameters")
47  (ENOSPC, "Object table full");
48 
49 // to be used only by test code, for triggering
50 // stale entry timer callback explicitly
52  obj->StaleEntryCleanupCb();
53 }
54 
55 KSyncObject::KSyncObject(const std::string &name) : need_index_(false), index_table_(),
56  delete_scheduled_(false), stale_entry_tree_(),
57  stale_entry_cleanup_timer_(NULL),
58  stale_entry_cleanup_intvl_(0),
59  stale_entries_per_intvl_(0) {
61 }
62 
63 KSyncObject::KSyncObject(const std::string &name, int max_index) :
64  need_index_(true), index_table_(max_index),
65  delete_scheduled_(false), stale_entry_tree_(),
66  stale_entry_cleanup_timer_(NULL),
67  stale_entry_cleanup_intvl_(0),
68  stale_entries_per_intvl_(0) {
70 }
71 
73  assert(tree_.size() == 0);
74  if (stale_entry_cleanup_timer_ != NULL) {
76  }
77 }
78 
79 void KSyncObject::InitStaleEntryCleanup(boost::asio::io_context &ios,
80  uint32_t cleanup_time,
81  uint32_t cleanup_intvl,
82  uint16_t entries_per_intvl) {
83  // init should be called only once
84  assert(stale_entry_cleanup_timer_ == NULL);
86  "KSync Stale Entry Cleanup Timer",
87  TaskScheduler::GetInstance()->GetTaskId("Agent::KSync"), 0);
88  stale_entry_cleanup_timer_->Start(cleanup_time,
89  boost::bind(&KSyncObject::StaleEntryCleanupCb, this));
90  stale_entry_cleanup_intvl_ = cleanup_intvl;
91  stale_entries_per_intvl_ = entries_per_intvl;
92 }
93 
95  assert(fwd_ref_tree_.size() == 0);
96  assert(back_ref_tree_.size() == 0);
97 }
98 
100  Tree::iterator it = tree_.find(*key);
101  if (it != tree_.end()) {
102  return it.operator->();
103  }
104 
105  return NULL;
106 }
107 
109  tbb::recursive_mutex::scoped_lock lock(lock_);
110  Tree::const_iterator it;
111  if (entry == NULL) {
112  it = tree_.begin();
113  } else {
114  it = tree_.iterator_to(*entry);
115  it++;
116  }
117  if (it != tree_.end()) {
118  return const_cast<KSyncEntry *>(it.operator->());
119  }
120  return NULL;
121 }
123  // should not create an entry while scheduled for deletion
124  assert(delete_scheduled_ == false);
125 
126  KSyncEntry *entry;
127  if (need_index_) {
128  entry = Alloc(key, index_table_.Alloc());
129  } else {
130  entry = Alloc(key, KSyncEntry::kInvalidIndex);
131  }
132  std::pair<Tree::iterator, bool> ret = tree_.insert(*entry);
133  if (ret.second == false) {
134  // entry with same key already exists in the Ksync tree
135  // delete the allocated entry and use the entry available
136  // in ksync tree
137  delete entry;
138  entry = ret.first.operator->();
139  } else {
140  // add reference only if tree insert for newly allocated
141  // entry succeeds, otherwise reference for tree insertion
142  // is already accounted for
143  intrusive_ptr_add_ref(entry);
144  }
145  return entry;
146 }
147 
149  // Clear stale marked entry and remove from stale entry tree
150  entry->stale_ = false;
151  stale_entry_tree_.erase(entry);
152 }
153 
154 // Creates a KSync entry. Calling routine sets no_lookup to TRUE when its
155 // guaranteed that KSync entry is not present (ex: flow)
156 KSyncEntry *KSyncObject::Create(const KSyncEntry *key, bool no_lookup) {
157  tbb::recursive_mutex::scoped_lock lock(lock_);
158 
159  KSyncEntry *entry = NULL;
160  if (no_lookup == false)
161  entry = Find(key);
162  if (entry == NULL) {
163  entry = CreateImpl(key);
164  } else {
165  if (entry->stale_) {
166  // Clear stale marked entry
167  ClearStale(entry);
168  } else if (entry->GetState() != KSyncEntry::TEMP && !entry->IsDeleted()) {
169  // If entry is already present, it should be in TEMP state
170  // or deleted state.
171  assert(0);
172  }
173  }
174 
176  return entry;
177 }
178 
180  return Create(key, false);
181 }
182 
184  // Should not be called without initialising stale entry
185  // cleanup InitStaleEntryCleanup
186  assert(stale_entry_cleanup_timer_ != NULL);
187  tbb::recursive_mutex::scoped_lock lock(lock_);
188  KSyncEntry *entry = Find(key);
189  if (entry == NULL) {
190  entry = CreateImpl(key);
191  } else {
192  if (entry->GetState() != KSyncEntry::TEMP && !entry->IsDeleted()) {
193  // If entry is already present, it should be in TEMP state
194  // or deleted state to form a stale entry
195  return NULL;
196  }
197  // cleanup associated DB entry for KSyncDBObject
198  // so that DB operation on this KSyncEntry does not happen
199  // without re-claiming this entry
200  CleanupOnDel(entry);
201  }
202 
203  // mark the entry stale and add to stale entry tree.
204  entry->stale_ = true;
205  stale_entry_tree_.insert(entry);
206 
208  // try starting the timer if not running already
210  boost::bind(&KSyncObject::StaleEntryCleanupCb, this));
211  return entry;
212 }
213 
215  KSyncEntry *entry = Find(key);
216 
217  if (entry != NULL)
218  return entry;
219 
220  entry = CreateImpl(key);
221  entry->SetState(KSyncEntry::TEMP);
222  return entry;
223 }
224 
227 }
228 
230  if (entry->stale_) {
231  ClearStale(entry);
232  }
234 }
235 
236 void KSyncObject::ChangeKey(KSyncEntry *entry, uint32_t arg) {
237  tbb::recursive_mutex::scoped_lock lock(lock_);
238  assert(tree_.erase(*entry) > 0);
239  uint32_t old_key = GetKey(entry);
240  UpdateKey(entry, arg);
241  std::pair<Tree::iterator, bool> ret = tree_.insert(*entry);
242  if (ret.second == false) {
243  // entry with the same key already exist, to proceed further
244  // switch place with the existing entry
245  KSyncEntry *current = ret.first.operator->();
246  assert(tree_.erase(*current) > 0);
247  UpdateKey(current, old_key);
248  // following tree insertions should always pass
249  assert(tree_.insert(*current).second == true);
250  assert(tree_.insert(*entry).second == true);
251  }
252 }
253 
254 uint32_t KSyncObject::GetKey(KSyncEntry *entry) {
255  assert(false);
256  return 0;
257 }
258 
259 void KSyncObject::FreeInd(KSyncEntry *entry, uint32_t index) {
260  assert(tree_.erase(*entry) > 0);
261  if (need_index_ == true && index != KSyncEntry::kInvalidIndex) {
262  index_table_.Free(index);
263  }
264  PreFree(entry);
265  Free(entry);
266 }
267 
269  delete entry;
270 }
271 
273  KSyncEntry::KSyncEvent event) {
274  tbb::recursive_mutex::scoped_lock lock(lock_);
275  NotifyEvent(entry, event);
276 }
277 
279 // KSyncDBObject routines
281 KSyncDBObject::KSyncDBObject(const std::string &name) : KSyncObject(name), test_id_(-1) {
282  table_ = NULL;
283 }
284 
285 KSyncDBObject::KSyncDBObject(const std::string &name,
286  int max_index) : KSyncObject(name, max_index), test_id_(-1) {
287  table_ = NULL;
288 }
289 
290 KSyncDBObject::KSyncDBObject(const std::string &name,
291  DBTableBase *table) : KSyncObject(name), test_id_(-1) {
292  table_ = table;
293  id_ = table->Register(boost::bind(&KSyncDBObject::Notify, this, _1, _2));
294 }
295 
296 KSyncDBObject::KSyncDBObject(const std::string &name,
297  DBTableBase *table, int max_index)
298  : KSyncObject(name, max_index), test_id_(-1) {
299  table_ = table;
300  id_ = table->Register(boost::bind(&KSyncDBObject::Notify, this, _1, _2));
301 }
302 
304  if (table_) {
306  }
307 }
308 
310  assert(table_ == NULL);
311  table_ = table;
312  id_ = table->Register(boost::bind(&KSyncDBObject::Notify, this, _1, _2));
313 }
314 
316  assert(table_ == table);
318  id_ = -1;
319  table_ = NULL;
320 }
321 
323  const DBEntry *entry, const KSyncDBEntry *ksync) {
324  // Default accept all
325  return DBFilterAccept;
326 }
327 
329  test_id_ = id;
330 }
331 
333  assert(table_ == table);
334  if (test_id_ != -1) {
335  return test_id_;
336  }
337  return id_;
338 }
339 
341  KSyncDBEntry *kentry = static_cast<KSyncDBEntry *>(entry);
342  if (kentry->GetDBEntry() != NULL) {
343  // when object is created only because of reference it will be in
344  // temp state without DB entry, deletion of which doesn't need
345  // this cleanup
346  kentry->GetDBEntry()->ClearState(table_, id_);
347  kentry->SetDBEntry(NULL);
348  }
349 
350  if (delete_scheduled()) {
351  // we are in cleanup process remove all duplicate entries
352  while (kentry->dup_entry_list_.empty() == false) {
353  // and clear db entry state
354  kentry->dup_entry_list_.front()->ClearState(table_, id_);
355  kentry->dup_entry_list_.pop_front();
356  }
357  }
358 }
359 
360 // DBTable notification handler.
361 // Generates events for the KSyncEntry state-machine based DBEntry
362 // Stores the KSyncEntry allocated as DBEntry-state
364  tbb::recursive_mutex::scoped_lock lock(lock_);
365  DBEntry *entry = static_cast<DBEntry *>(e);
366  DBTableBase *table = partition->parent();
367  assert(table_ == table);
368  KSyncDBEntry *ksync =
369  static_cast<KSyncDBEntry *>(entry->GetState(table, id_));
371 
372  // cleanup is in-process, ignore All db notifications.
373  if (delete_scheduled()) {
374  return;
375  }
376 
377  // Trigger DB Filter callback only for ADD/CHANGE, since we need to handle
378  // cleanup for delete anyways.
379  if (!entry->IsDeleted()) {
380  resp = DBEntryFilter(entry, ksync);
381  }
382 
383  if (entry->IsDeleted() || resp == DBFilterDelete ||
384  resp == DBFilterDelAdd) {
385  if (ksync != NULL) {
386  // Check if there is any entry present in dup_entry_list
387  if (!ksync->dup_entry_list_.empty()) {
388  // Check if entry getting deleted is actively associated with
389  // Ksync Entry.
390  if (entry == ksync->GetDBEntry()) {
391  // clean up db entry state.
392  CleanupOnDel(ksync);
393  ksync->SetDBEntry(ksync->dup_entry_list_.front());
394  ksync->dup_entry_list_.pop_front();
395 
396  // DB entry association changed, trigger re-sync.
397  if (ksync->Sync(ksync->GetDBEntry())) {
399  }
400  } else {
401  // iterate through entries and delete the
402  // corresponding DB ref.
403  KSyncDBEntry::DupEntryList::iterator it_dup;
404  for (it_dup = ksync->dup_entry_list_.begin();
405  it_dup != ksync->dup_entry_list_.end(); ++it_dup) {
406  if (entry == *it_dup)
407  break;
408  }
409  // something bad has happened if we fail to find the entry.
410  assert(it_dup != ksync->dup_entry_list_.end());
411  ksync->dup_entry_list_.erase(it_dup);
412  entry->ClearState(table_, id_);
413  }
414  } else {
415  if (resp == DBFilterDelAdd) {
416  // clean up db entry state, so that other ksync entry can
417  // replace the states appropriately.
418  // cleanup needs to be triggered before notifying delete
419  // after that ksync entry might be already free'd
420  CleanupOnDel(ksync);
421  }
422  // We may get duplicate delete notification in
423  // case of db entry reuse
424  // add -> change ->delete(Notify) -> change -> delete(Notify)
425  // delete and change gets suppresed as delete and we get
426  // a duplicate delete notification
427  if (ksync->IsDeleted() == false) {
429  }
430  }
431  }
432  if (resp != DBFilterDelAdd) {
433  // return from here except for DBFilterDelAdd case, where
434  // ADD needs to be triggered after Delete
435  return;
436  }
437  // reset ksync entry pointer, as ksync and DB entry is already
438  // dissassociated
439  ksync = NULL;
440  }
441 
442  if (resp == DBFilterIgnore) {
443  // DB filter tells us to ignore this Add/Change.
444  return;
445  }
446 
447  bool need_sync = false;
448  if (ksync == NULL) {
449  KSyncEntry *key, *found;
450 
451  // TODO : Memory is allocated and freed only for lookup. Fix this.
452  key = DBToKSyncEntry(entry);
453  found = Find(key);
454  if (found == NULL) {
455  ksync = static_cast<KSyncDBEntry *>(CreateImpl(key));
456  } else {
457  ksync = static_cast<KSyncDBEntry *>(found);
458  if (ksync->stale()) {
459  // Clear stale marked entry and remove from stale entry tree
460  ClearStale(ksync);
461  }
462  }
463  delete key;
464  entry->SetState(table, id_, ksync);
465  // Allow reuse of KSync Entry if the previous associated DB Entry
466  // is marked deleted. This can happen when Key for OPER DB entry
467  // deferes from that used in KSync Object.
468  DBEntry *old_db_entry = ksync->GetDBEntry();
469  if (old_db_entry != NULL) {
470  // cleanup previous state id the old db entry is delete marked.
471  if (old_db_entry->IsDeleted()) {
472  CleanupOnDel(ksync);
473  } else {
474  // In case Oper DB and Ksync use different Keys, its
475  // possible to have multiple Oper DB entries pointing to
476  // same Ksync Entry.
477  // add the entry to dup_entry_list and return
478  ksync->dup_entry_list_.push_back(entry);
479  return;
480  }
481  }
482  ksync->SetDBEntry(entry);
483  need_sync = true;
484  } else {
485  // ignore change on non-associated entry.
486  if (entry != ksync->GetDBEntry()) {
487  return;
488  }
489  }
490 
491  if (ksync->IsDeleted()) {
492  // ksync entry was marked as delete, sync required.
493  need_sync = true;
494  }
495 
496  if (ksync->Sync(entry) || need_sync) {
498  }
499 }
500 
502 // KSyncEntry routines
505  KSyncObject *obj = GetObject();
506  if (obj->IsIndexValid() && index_ == kInvalidIndex)
507  return false;
508  if (IsDataResolved() == false)
509  return false;
510  return ((state_ >= IN_SYNC) && (state_ < DEL_DEFER_SYNC));
511 }
512 
513 std::string KSyncEntry::VrouterErrorToString(uint32_t error) {
514  std::map<uint32_t, std::string>::iterator iter =
515  g_error_description.find(error);
516  if (iter == g_error_description.end())
517  return strerror(error);
518  return iter->second;
519 }
520 
521 std::string KSyncEntry::VrouterError(uint32_t error) const {
522  return VrouterErrorToString(error);
523 }
524 
525 void KSyncEntry::ErrorHandler(int err, uint32_t seq_no,
526  KSyncEvent event) const {
527  if (err == 0) {
528  return;
529  }
530  std::string error_msg = VrouterError(err);
531  KSYNC_ERROR(VRouterError, "VRouter operation failed. Error <", err,
532  ":", error_msg, ">. Object <", ToString(),
533  ">. Operation <", AckOperationString(event),
534  ">. Message number :", seq_no);
535 
536  std::stringstream sstr;
537  sstr << "VRouter operation failed. Error <" << err << ":" << error_msg <<
538  ">. Object <" << ToString() << ">. Operation <" <<
539  AckOperationString(event) << ">. Message number :" << seq_no;
540  KSYNC_ERROR_TRACE(Trace, sstr.str().c_str());
541  LOG(ERROR, sstr.str().c_str());
542 }
543 
544 std::string KSyncEntry::AckOperationString(KSyncEvent event) const {
545  switch(event) {
546  case ADD_ACK:
547  return "Addition";
548 
549  case CHANGE_ACK:
550  return "Change";
551 
552  case DEL_ACK:
553  return "Deletion";
554 
555  default:
556  // AckOperationString should track only acks, if something else is
557  // passed convert it to EventString
558  return EventString(event);
559  }
560 }
561 
562 std::string KSyncEntry::StateString() const {
563  std::stringstream str;
564 
565  switch (state_) {
566  case INIT:
567  str << "Init";
568  break;
569 
570  case TEMP:
571  str << "Temp";
572  break;
573 
574  case ADD_DEFER:
575  str << "Add defer";
576  break;
577 
578  case CHANGE_DEFER:
579  str << "Change defer";
580  break;
581 
582  case IN_SYNC:
583  str << "In sync";
584  break;
585 
586  case SYNC_WAIT:
587  str << "Sync wait";
588  break;
589 
590  case NEED_SYNC:
591  str << "Need sync";
592  break;
593 
594  case DEL_DEFER_SYNC:
595  str << "Delete defer sync";
596  break;
597 
598  case DEL_DEFER_REF:
599  str << "Delete pending due to reference";
600  break;
601 
602  case DEL_DEFER_DEL_ACK:
603  str << "Delete pending due to Delete ack wait";
604  break;
605 
606  case DEL_ACK_WAIT:
607  str << "Delete ack wait";
608  break;
609 
610  case RENEW_WAIT:
611  str << "Renew wait";
612  break;
613 
614  case FREE_WAIT:
615  str << "Free wait";
616  break;
617  }
618 
619  if (stale_) {
620  str << " (Stale entry) ";
621  }
622 
623  str << '(' << state_ << ')';
624  str << '(' << refcount_ << ')';
625  return str.str();
626 }
627 
628 std::string KSyncEntry::EventString(KSyncEvent event) const {
629  std::stringstream str;
630  switch (event) {
631  case ADD_CHANGE_REQ:
632  str << "Add/Change request";
633  break;
634 
635  case ADD_ACK:
636  str << "Add Ack";
637  break;
638 
639  case CHANGE_ACK:
640  str << "Change ack";
641  break;
642 
643  case DEL_REQ:
644  str << "Delete request";
645  break;
646 
647  case DEL_ADD_REQ:
648  str << "Delete followed by Add request";
649  break;
650 
651  case DEL_ACK:
652  str << "Delete ack";
653  break;
654 
655  case RE_EVAL:
656  str << "Re-evaluate";
657  break;
658 
659  case INT_PTR_REL:
660  str << "Reference release";
661  break;
662  case INVALID:
663  str << "Invalid";
664  break;
665  }
666  str << '(' << event << ')';
667  return str.str();
668 }
669 
671  p->refcount_++;
672 };
673 
674 // KSync adds a reference to object when its created.
675 // Delete the object if reference falls to 1 and either
676 // (i) delete was deferred due to refcount or
677 // (ii) the ksync entry is in TEMP state.
679  if (--p->refcount_ == 1) {
680  KSyncObject *obj = p->GetObject();
681  switch(p->state_) {
682  case KSyncEntry::TEMP:
683  // FALLTHRU
686  break;
687  default:
688  break;
689  }
690  }
691 }
692 
694 // KSyncEntry state machine.
695 //
696 // Brief description of States:
697 //
698 // INIT : KSyncEntry created. No events notified to the object yet
699 // TEMP : Temporary object created either due to reference or on
700 // process restart.
701 // Ex: Obj-A refers to Obj-B. If Obj-B is not present when Obj-A
702 // is to be sent, then Obj-B is created in TEMP state
703 //
704 // ADD_DEFER : Object deferred since it has some unmet constraints.
705 // Ex: Obj-A refers to Obj-B. Obj-B is not yet added to kernel.
706 // Obj-A will get to ADD_DEFER state
707 // Obj-A goes into BackRefTree for Obj-B.
708 // Creation of Obj-B will take Obj-A out of this state
709 // CHANGE_DEFER : Object already added to kernel, subsequent change deferred
710 // since it has some unmet constraints.
711 // Ex: Obj-A refers to Obj-B. Obj-B is not yet added to kernel.
712 // Obj-A will get to ADD_DEFER state
713 // Obj-A goes into BackRefTree for Obj-B.
714 // Add of Obj-B will take Obj-A out of this state
715 // IN_SYNC : Object in-sync with kernel
716 // SYNC_WAIT : Add or Change sent to kernel. Waiting for ACK from Kernel
717 // NEED_SYNC : Object out-of-sync with kernel. Need to send a change message
718 // to sync kernel state
719 // DEL_DEFER_SYNC:Object deleted when waiting for ACK from kernel. Delete must
720 // be sent to kernel on getting ACK
721 // DEL_DEFER_REF: Object deleted with pending references . Delete must be sent
722 // to kernel when all pending references goes away.
723 // DEL_DEFER_DEL_ACK: Object delete with pending delete ack wait, Delete
724 // needs to be sent after receiving a del ACK.
725 // DEL_ACK_WAIT : Delete sent to Kernel. Waiting for ACK from kernel.
726 // Can get renewed if there is request to ADD in this case
727 // RENEW_WAIT : Object being renewed. Waiting for ACK of delete to renew the
728 // object
729 // FREE_WAIT : Object marked to be freed at the end of this function call.
730 // Can only be a temporary state
731 //
732 // Brief description of Events:
733 // ADD_CHANGE_REQ : Request to Add or Change an entry
734 // ADD_ACK, : Ack from kernel for ADD request
735 // CHANGE_ACK : Ack from kernel for CHANGE request
736 // DEL_REQ : Request to DEL an entry
737 // DEL_ADD_REQ : Request to DEL an entry followed by ADD for the same
738 // DEL_ACK : Ack from kernel for DEL request
739 // RE_EVAL : Event to re-evaluate dependencies.
740 // Ex: If Obj-A is added into Obj-B back-ref tree
741 // When Obj-B is created, RE_EVAL is sent to Obj-A
743 
744 // Utility function to handle Add of KSyncEntry.
745 // If operation is complete, move state to IN_SYNC. Else move to SYNC_WAIT
747  KSyncEntry *dep;
748  if ((dep = entry->UnresolvedReference()) != NULL) {
749  obj->BackRefAdd(entry, dep);
750  return KSyncEntry::ADD_DEFER;
751  }
752 
753  entry->SetSeen();
754  if (entry->Add()) {
755  return KSyncEntry::IN_SYNC;
756  } else {
757  return KSyncEntry::SYNC_WAIT;
758  }
759 }
760 
761 // Utility function to handle Change of KSyncEntry.
762 // If operation is complete, move state to IN_SYNC. Else move to SYNC_WAIT
764  KSyncEntry *dep;
765 
766  assert(entry->Seen());
767  if ((dep = entry->UnresolvedReference()) != NULL) {
768  obj->BackRefAdd(entry, dep);
770  }
771 
772  if (entry->Change()) {
773  return KSyncEntry::IN_SYNC;
774  } else {
775  return KSyncEntry::SYNC_WAIT;
776  }
777 }
778 
779 // Utility function to handle Delete of KSyncEntry.
780 // If there are more references to the object, then move it to DEL_DEFER
781 // state. Object will be deleted when all references drop. If object is
782 // still not seen by Kernel yet we don't have to delete it.
783 //
784 // If operation is complete, move state to IN_SYNC. Else move to SYNC_WAIT
786  if (entry->GetRefCount() > 1) {
788  }
789 
790  assert(entry->GetRefCount() == 1);
791  if (!entry->Seen() && entry->AllowDeleteStateComp()) {
792  return KSyncEntry::FREE_WAIT;
793  }
794  if (entry->Delete()) {
795  return KSyncEntry::FREE_WAIT;
796  } else {
798  }
799 }
800 
801 // Utility function to handle Delete followed by ADD of KSyncEntry.
802 // delete is triggered irrespective of the references to the object
803 // followed by ADD of the object
804 //
805 // If operation is complete, move state to IN_SYNC. Else move to SYNC_WAIT
807  // DeleteAdd operation is not supported/defined for stale entries
808  // when such an operation is required for stale entry, it must be
809  // sufficient to trigger only a delete and let Add happen when
810  // entry is ready to become non-stale
811  assert(!entry->stale());
812 
813  // NOTE this API doesnot support managing references for delete trigger
814  if (entry->Seen() || !entry->AllowDeleteStateComp()) {
815  if (!entry->Delete()) {
816  // move to renew wait to trigger Add on DEL_ACK
817  return KSyncEntry::RENEW_WAIT;
818  }
819  }
820 
821  return KSyncSM_Add(obj, entry);
822 }
823 
824 //
825 //
826 // ADD_CHANGE_REQ :
827 // If entry has unresolved references, move it to ADD_DEFER
828 // Else, send ADD message and move to SYNC_WAIT state
829 //
830 // No other events are expected in this state
832  KSyncEntry::KSyncEvent event) {
834 
835  assert(entry->GetRefCount());
836  switch (event) {
838  state = KSyncSM_Add(obj, entry);
839  break;
840 
841  default:
842  assert(0);
843  break;
844  }
845 
846  return state;
847 }
848 
849 // ADD_CHANGE_REQ :
850 // ADD_CHANGE_REQ event for an entry in TEMP state.
851 // If entry has unresolved references, move it to ADD_DEFER
852 // Else, send ADD message and move to SYNC_WAIT state
853 //
854 // DEL_REQ :
855 // DEL_REQ event for an entry in TEMP state. Can happen only when reference
856 // for the TEMP entry is dropped
857 //
858 // Explicit DEL_REQ event is not expected. This is enforced by checking
859 // ref-count
860 //
861 // Event notified when refcount for object goes to 1 In TEMP state.
862 // Entry not sent to kernel, so dont send delete message
863 // Delete object in this state
864 //
866  KSyncEntry::KSyncEvent event) {
868 
869  assert(entry->GetRefCount());
870  switch (event) {
873  state = KSyncSM_Add(obj, entry);
874  break;
875 
877  case KSyncEntry::DEL_REQ:
878  if (entry->GetRefCount() == 1) {
879  state = KSyncEntry::FREE_WAIT;
880  }
881  break;
882 
883  default:
884  assert(0);
885  break;
886  }
887 
888  return state;
889 }
890 
891 // ADD_CHANGE_REQ :
892 // ADD_CHANGE_REQ event for an entry in ADD_DEFER state.
893 // Remove the old dependency constraint.
894 // Re-evaluate to see if there are any further unmet dependencies
895 //
896 // RE_EVAL:
897 // Triggred from back-ref tree when KSyncEntry waited on is added to Kernel
898 // Entry would already be removed from backref tree
899 // Re-evaluate to see if there are any further unmet dependencies
900 //
901 // DEL_REQ :
902 // Delete when entry is not yet added to kernel. Dont delete entry. Move state
903 // based on ref-count
905  KSyncEntry::KSyncEvent event) {
907 
908  assert(entry->GetRefCount());
909  switch (event) {
911  obj->BackRefDel(entry);
912  // FALLTHRU
913  case KSyncEntry::RE_EVAL:
914  state = KSyncSM_Add(obj, entry);
915  break;
916 
917  // Remove any back-ref entry
918  // Free entry if there are no more references. Else wait in TEMP
919  // state for either release of reference or for movement to different
920  // state.
921  case KSyncEntry::DEL_REQ:
922  obj->BackRefDel(entry);
923  if (entry->AllowDeleteStateComp() == false) {
924  state = KSyncSM_Delete(entry);
925  } else if (entry->GetRefCount() > 1) {
926  state = KSyncEntry::TEMP;
927  } else {
928  state = KSyncEntry::FREE_WAIT;
929  }
930  break;
931 
933  obj->BackRefDel(entry);
934  state = KSyncSM_DeleteAdd(obj, entry);
935  break;
936 
938  break;
939 
940  default:
941  assert(0);
942  break;
943  }
944 
945  return state;
946 }
947 
948 // ADD_CHANGE_REQ :
949 // ADD_CHANGE_REQ event for an entry in CHANGE_DEFER state.
950 // Remove the old dependency constraint.
951 // Re-evaluate to see if there are any further unmet dependencies
952 //
953 // RE_EVAL:
954 // Triggred from back-ref tree when KSyncEntry waited on is added to Kernel
955 // Entry would already be removed from backref tree
956 // Re-evaluate to see if there are any further unmet dependencies
957 //
958 // DEL_REQ :
959 // Move state based on ref-count.
961  KSyncEntry::KSyncEvent event) {
963 
964  assert(entry->GetRefCount());
965  switch (event) {
967  obj->BackRefDel(entry);
968  // FALLTHRU
969  case KSyncEntry::RE_EVAL:
970  state = KSyncSM_Change(obj, entry);
971  break;
972 
973  // Remove any back-ref entry and process delete
974  case KSyncEntry::DEL_REQ:
975  obj->BackRefDel(entry);
976  state = KSyncSM_Delete(entry);
977  break;
978 
980  obj->BackRefDel(entry);
981  state = KSyncSM_DeleteAdd(obj, entry);
982  break;
983 
985  break;
986 
987  default:
988  assert(0);
989  break;
990  }
991 
992  return state;
993 }
994 
995 // Object state IN-SYNC with kernel
996 //
997 // ADD_CHANGE_REQ :
998 // Invoke Change on the object
999 //
1000 // DEL_REQ :
1001 // Delete of entry that is already added to kernel.
1003  KSyncEntry::KSyncEvent event) {
1005 
1006  assert(entry->GetRefCount());
1007  switch (event) {
1009  state = KSyncSM_Change(obj, entry);
1010  break;
1011 
1012  case KSyncEntry::DEL_REQ:
1013  state = KSyncSM_Delete(entry);
1014  break;
1015 
1017  state = KSyncSM_DeleteAdd(obj, entry);
1018  break;
1019 
1021  break;
1022 
1023  default:
1024  assert(0);
1025  break;
1026  }
1027 
1028  return state;
1029 }
1030 
1031 // Entry waiting on ACK or Add or Change
1032 // If event is change request, move to NEED_SYNC
1033 // If event is delete request, move to DEL_DEFER for references to drop
1035  KSyncEntry::KSyncEvent event) {
1037 
1038  assert(entry->GetRefCount());
1039  switch (event) {
1041  state = KSyncEntry::NEED_SYNC;
1042  break;
1043 
1044  case KSyncEntry::ADD_ACK:
1046  if (entry->del_add_pending()) {
1047  // del_add_pending trigger DeleteAdd
1048  entry->set_del_add_pending(false);
1049  state = KSyncSM_DeleteAdd(obj, entry);
1050  } else {
1051  state = KSyncEntry::IN_SYNC;
1052  }
1053  break;
1054 
1055  case KSyncEntry::DEL_REQ:
1057  entry->set_del_add_pending(false);
1058  break;
1059 
1061  // entry is waiting for Ack, mark del_add_pending flag
1062  // to trigger DeleteAdd on receiving Ack
1063  entry->set_del_add_pending(true);
1064  break;
1065 
1067  break;
1068 
1069  default:
1070  assert(0);
1071  break;
1072  }
1073 
1074  return state;
1075 }
1076 
1077 // NEED_SYNC state means object was modified while waiting for ACK
1079  KSyncEntry::KSyncEvent event) {
1081 
1082  assert(entry->GetRefCount());
1083  switch (event) {
1084  // Continue in NEED_SYNC state on change
1086  break;
1087 
1088  // Wait for ACK to arrive in DEL_DEFER_SYNC state
1089  case KSyncEntry::DEL_REQ:
1091  entry->set_del_add_pending(false);
1092  break;
1093 
1095  // entry is waiting for Ack, mark del_add_pending flag
1096  // to trigger DeleteAdd on receiving Ack
1097  entry->set_del_add_pending(true);
1098  break;
1099 
1100  // Try to resend on getting ACK of pending operation
1101  case KSyncEntry::ADD_ACK:
1103  if (entry->del_add_pending()) {
1104  // del_add_pending trigger DeleteAdd
1105  entry->set_del_add_pending(false);
1106  state = KSyncSM_DeleteAdd(obj, entry);
1107  } else {
1108  state = KSyncSM_Change(obj, entry);
1109  }
1110  break;
1111 
1113  break;
1114 
1115  default:
1116  assert(0);
1117  break;
1118  }
1119 
1120  return state;
1121 }
1122 
1123 // Object waiting for DELETE to be sent.
1124 // ADD_CHANGE_REQ will result in renew of object. Send only a Change
1125 // On ADD/CHANGE ACK, try sending delete
1127  KSyncEntry *entry,
1128  KSyncEntry::KSyncEvent event) {
1130 
1131  assert(entry->GetRefCount());
1132  switch (event) {
1134  state = KSyncEntry::NEED_SYNC;
1135  break;
1136 
1138  // entry is waiting for Ack, mark del_add_pending flag
1139  // to trigger DeleteAdd on receiving Ack
1140  entry->set_del_add_pending(true);
1141  state = KSyncEntry::NEED_SYNC;
1142  break;
1143 
1144  case KSyncEntry::ADD_ACK:
1146  state = KSyncSM_Delete(entry);
1147  break;
1148 
1150  break;
1151 
1152  default:
1153  assert(0);
1154  break;
1155  }
1156 
1157  return state;
1158 }
1159 
1160 // Object waiting for DELETE to be sent.
1161 // ADD_CHANGE_REQ will result in renew of object. Send only a Change
1162 // On ADD/CHANGE ACK, try sending delete
1164  KSyncEntry *entry,
1165  KSyncEntry::KSyncEvent event) {
1167 
1168  assert(entry->GetRefCount());
1169  switch (event) {
1171  if (!entry->Seen()) {
1172  // Trigger Add if entry was not seen earlier
1173  state = KSyncSM_Add(obj, entry);
1174  } else {
1175  state = KSyncSM_Change(obj, entry);
1176  }
1177  break;
1178 
1180  case KSyncEntry::DEL_REQ:
1181  assert(entry->GetRefCount()== 1);
1182  state = KSyncSM_Delete(entry);
1183  break;
1184 
1186  state = KSyncSM_DeleteAdd(obj, entry);
1187  break;
1188 
1189  default:
1190  assert(0);
1191  break;
1192  }
1193 
1194  return state;
1195 }
1196 
1197 // Object waiting for DELETE to be sent.
1198 // ADD_CHANGE_REQ will result in renew of object. Send only a Change
1199 // On DEL ACK, try sending delete
1201  KSyncEntry *entry,
1202  KSyncEntry::KSyncEvent event) {
1204 
1205  assert(entry->GetRefCount());
1206  assert(entry->AllowDeleteStateComp() == false);
1207 
1208  switch (event) {
1210  state = KSyncEntry::RENEW_WAIT;
1211  entry->set_del_add_pending(false);
1212  break;
1213 
1214  case KSyncEntry::DEL_ACK:
1215  if (entry->del_add_pending()) {
1216  // del_add_pending trigger DeleteAdd
1217  entry->set_del_add_pending(false);
1218  state = KSyncSM_DeleteAdd(obj, entry);
1219  } else {
1220  state = KSyncSM_Delete(entry);
1221  }
1222  break;
1223 
1225  // entry is waiting for Ack, mark del_add_pending flag
1226  // to trigger DeleteAdd on receiving Ack
1227  entry->set_del_add_pending(true);
1228  break;
1229 
1231  break;
1232 
1233  default:
1234  assert(0);
1235  break;
1236  }
1237 
1238  return state;
1239 }
1240 
1241 // Object waiting for ACK of DELETE sent earlier
1242 // ADD_CHANGE_REQ will result in renew of object. TODO: This is TBD
1244  KSyncEntry::KSyncEvent event) {
1246 
1247  assert(entry->GetRefCount());
1248  switch (event) {
1250  state = KSyncEntry::RENEW_WAIT;
1251  entry->set_del_add_pending(false);
1252  break;
1253 
1254  case KSyncEntry::DEL_ACK:
1255  if (entry->del_add_pending()) {
1256  // del_add_pending trigger DeleteAdd
1257  entry->set_del_add_pending(false);
1258  state = KSyncSM_DeleteAdd(obj, entry);
1259  } else {
1260  if (entry->GetRefCount() > 1) {
1261  state = KSyncEntry::TEMP;
1262  } else {
1263  state = KSyncEntry::FREE_WAIT;
1264  }
1265  }
1266  break;
1267 
1269  // entry is waiting for Ack, mark del_add_pending flag
1270  // to trigger DeleteAdd on receiving Ack
1271  entry->set_del_add_pending(true);
1272  break;
1273 
1275  break;
1276 
1277  default:
1278  assert(0);
1279  break;
1280  }
1281 
1282  return state;
1283 }
1284 
1285 // TODO: Object renewal. This is not yet handled
1287  KSyncEntry::KSyncEvent event) {
1289 
1290  assert(entry->GetRefCount());
1291  switch (event) {
1293  entry->set_del_add_pending(false);
1294  break;
1295 
1296  case KSyncEntry::DEL_REQ:
1297  entry->set_del_add_pending(false);
1298  if (entry->AllowDeleteStateComp()) {
1299  state = KSyncEntry::DEL_ACK_WAIT;
1300  } else {
1302  }
1303  break;
1304 
1306  // entry is waiting for Ack, mark del_add_pending flag
1307  // to trigger DeleteAdd on receiving Ack
1308  entry->set_del_add_pending(true);
1309  break;
1310 
1311  case KSyncEntry::DEL_ACK:
1312  if (entry->del_add_pending()) {
1313  // del_add_pending trigger DeleteAdd
1314  entry->set_del_add_pending(false);
1315  state = KSyncSM_DeleteAdd(obj, entry);
1316  } else {
1317  state = KSyncSM_Add(obj, entry);
1318  }
1319  break;
1320 
1322  break;
1323 
1324  default:
1325  assert(0);
1326  break;
1327  }
1328 
1329  return state;
1330 }
1331 
1333 
1334  KSyncEntry::KSyncState state;
1335  bool dep_reval = false;
1336  KSyncEntry::KSyncState from_state = entry->GetState();
1337 
1338  if (DoEventTrace()) {
1339  std::string obj_string(entry->ToString());
1340  std::string state_string(entry->StateString());
1341  std::string event_string(entry->EventString(event));
1342  KSYNC_TRACE(Event, this, obj_string, state_string,
1343  event_string);
1344  }
1345  switch (entry->GetState()) {
1346  case KSyncEntry::INIT:
1347  state = KSyncSM_Init(this, entry, event);
1348  break;
1349 
1350  case KSyncEntry::TEMP:
1351  dep_reval = true;
1352  state = KSyncSM_Temp(this, entry, event);
1353  break;
1354 
1355  case KSyncEntry::ADD_DEFER:
1356  dep_reval = true;
1357  state = KSyncSM_AddDefer(this, entry, event);
1358  break;
1359 
1361  dep_reval = true;
1362  state = KSyncSM_ChangeDefer(this, entry, event);
1363  break;
1364 
1365  case KSyncEntry::IN_SYNC:
1366  state = KSyncSM_InSync(this, entry, event);
1367  break;
1368 
1369  case KSyncEntry::SYNC_WAIT:
1370  dep_reval = true;
1371  state = KSyncSM_SyncWait(this, entry, event);
1372  break;
1373 
1374  case KSyncEntry::NEED_SYNC:
1375  state = KSyncSM_NeedSync(this, entry, event);
1376  break;
1377 
1379  state = KSyncSM_DelPending_Sync(this, entry, event);
1380  break;
1381 
1383  dep_reval = true;
1384  state = KSyncSM_DelPending_Ref(this, entry, event);
1385  break;
1386 
1388  state = KSyncSM_DelPending_DelAck(this, entry, event);
1389  break;
1390 
1392  state = KSyncSM_DelAckWait(this, entry, event);
1393  break;
1394 
1396  dep_reval = true;
1397  state = KSyncSM_RenewWait(this, entry, event);
1398  break;
1399 
1400  default:
1401  assert(0);
1402  break;
1403  }
1404 
1405  entry->SetState(state);
1406  entry->RecordTransition(from_state, state, event);
1407 
1408  if (dep_reval == true && entry->IsResolved() &&
1409  entry->ShouldReEvalBackReference()) {
1410  BackRefReEval(entry);
1411  }
1412 
1413  if (state == KSyncEntry::FREE_WAIT || state == KSyncEntry::TEMP) {
1414  CleanupOnDel(entry);
1415  }
1416 
1417  if (state == KSyncEntry::FREE_WAIT) {
1418  intrusive_ptr_release(entry);
1419  FreeInd(entry, entry->GetIndex());
1420  }
1421 
1422  if (tree_.empty() == true) {
1423  EmptyTable();
1424  }
1425 }
1426 
1428  tbb::recursive_mutex::scoped_lock lock(lock_);
1429  entry->Response();
1430  NotifyEvent(entry, event);
1431 }
1432 
1434  // donot reschedule timer if no stale entries
1435  if (stale_entry_tree_.empty()) {
1436  return false;
1437  }
1438 
1439  uint32_t count = 0;
1440  std::set<KSyncEntry::KSyncEntryPtr>::iterator it = stale_entry_tree_.begin();
1441  while (it != stale_entry_tree_.end()) {
1442  if (count == stale_entries_per_intvl_) {
1443  break;
1444  }
1445  KSyncEntry *entry = (*it).get();
1446  // Notify entry of stale timer expiration
1447  entry->StaleTimerExpired();
1448  // Delete removes entry from stale entry tree
1449  Delete(entry);
1450  it = stale_entry_tree_.begin();
1451  count++;
1452  }
1453 
1454  // iterate entries and trigger delete
1456 }
1457 
1459  NetlinkAckInternal(entry, event);
1460 }
1461 
1463 // KSyncEntry dependency management
1466  KSyncFwdReference *fwd_node = new KSyncFwdReference(key, reference);
1467  FwdRefTree::iterator fwd_it = fwd_ref_tree_.find(*fwd_node);
1468  assert(fwd_it == fwd_ref_tree_.end());
1469  fwd_ref_tree_.insert(*fwd_node);
1470  intrusive_ptr_add_ref(key);
1471  intrusive_ptr_add_ref(reference);
1472 
1473  KSyncBackReference *back_node = new KSyncBackReference(reference, key);
1474  BackRefTree::iterator back_it = back_ref_tree_.find(*back_node);
1475  assert(back_it == back_ref_tree_.end());
1476  back_ref_tree_.insert(*back_node);
1477 }
1478 
1480  KSyncFwdReference fwd_search_node(key, NULL);
1481  FwdRefTree::iterator fwd_it = fwd_ref_tree_.find(fwd_search_node);
1482  if (fwd_it == fwd_ref_tree_.end()) {
1483  return;
1484  }
1485  KSyncFwdReference *entry = fwd_it.operator->();
1486  KSyncEntry *reference = entry->reference_;
1487  fwd_ref_tree_.erase(fwd_it);
1488  delete entry;
1489 
1490  KSyncBackReference back_search_node(reference, key);
1491  BackRefTree::iterator back_it = back_ref_tree_.find(back_search_node);
1492  assert(back_it != back_ref_tree_.end());
1493  KSyncBackReference *back_node = back_it.operator->();
1494  back_ref_tree_.erase(back_it);
1495  delete back_node;
1496 
1497  intrusive_ptr_release(key);
1498  intrusive_ptr_release(reference);
1499 }
1500 
1502  std::vector<KSyncEntry *> buf;
1503  KSyncBackReference node(key, NULL);
1504 
1505  for (BackRefTree::iterator it = back_ref_tree_.upper_bound(node);
1506  it != back_ref_tree_.end(); ) {
1507  BackRefTree::iterator it_work = it;
1508 
1509  KSyncBackReference *entry = it_work.operator->();
1510  if (entry->key_ != key) {
1511  break;
1512  }
1513  KSyncEntry *back_ref = entry->back_reference_;
1514  buf.push_back(back_ref);
1515  BackRefDel(entry->back_reference_);
1516  it = back_ref_tree_.upper_bound(node);
1517  }
1518 
1519  std::vector<KSyncEntry *>::iterator it = buf.begin();
1520  while (it != buf.end()) {
1521  tbb::recursive_mutex::scoped_lock lock((*it)->GetObject()->lock_);
1523  it++;
1524  }
1525 }
1526 
1528  switch(event->event_) {
1530  if (event->obj_->Size() == 0) {
1531  delete event->obj_;
1532  }
1533  break;
1534  case KSyncObjectEvent::DEL:
1535  {
1536  int count = 0;
1537  // hold reference to entry to ensure the pointer sanity
1538  KSyncEntry::KSyncEntryPtr entry(NULL);
1539  if (event->ref_.get() == NULL) {
1540  event->obj_->set_delete_scheduled();
1541  if (event->obj_->IsEmpty()) {
1542  // trigger explicit empty table callback for client to
1543  // complete deletion of object in KSync Context.
1544  event->obj_->EmptyTable();
1545  break;
1546  }
1547  // get the first entry to start with
1548  entry = event->obj_->Next(NULL);
1549  } else {
1550  entry = event->ref_.get();
1551  }
1552 
1553  // hold reference to entry to ensure the pointer sanity
1554  // next entry can get free'd in certain cases while processing
1555  // current entry
1556  KSyncEntry::KSyncEntryPtr next_entry(NULL);
1557  while (entry.get() != NULL) {
1558  next_entry = event->obj_->Next(entry.get());
1559  count++;
1560  if (entry->IsDeleted() == false) {
1561  // trigger delete if entry is not marked delete already.
1562  event->obj_->Delete(entry.get());
1563  }
1564 
1565  if (count == kMaxEntriesProcess && next_entry.get() != NULL) {
1566  // update reference with which entry to start with
1567  // in next iteration.
1568  event->ref_ = next_entry.get();
1569  // yeild and re-enqueue event for processing later.
1570  event_queue_->Enqueue(event);
1571 
1572  // release reference to deleted entry.
1573  entry = NULL;
1574  return false;
1575  }
1576  entry = next_entry.get();
1577  }
1578  break;
1579  }
1580  default:
1581  assert(0);
1582  }
1583  delete event;
1584  return true;
1585 }
1586 
1588  event_queue_->Enqueue(event);
1589 }
1590 
1592  KSyncObjectEvent *event = new KSyncObjectEvent(table,
1594  singleton_->Enqueue(event);
1595 }
1596 
1599  (TaskScheduler::GetInstance()->GetTaskId("Agent::KSync"), 0,
1600  boost::bind(&KSyncObjectManager::Process, this, _1));
1601 }
1602 
1604  delete event_queue_;
1605 }
1606 
1608  if (singleton_ == NULL) {
1610  }
1611  return singleton_;
1612 }
1613 
1615  if (singleton_) {
1616  delete singleton_;
1617  }
1618  singleton_ = NULL;
1619 }
1620 
1621 // Create a KSync Object event to trigger Delete of all the KSync Entries
1622 // present in the given object.
1623 // Once the delete is scheduled new entry creation is not allowed for this
1624 // object and EmptyTable callback is trigger when all the entries of given
1625 // object are cleaned up. As part of which client can delete the object.
1626 //
1627 // This API can be used to clean up KSync objects irrespective of config
1628 // or oper tables
1629 
1631  KSyncObjectEvent *event = new KSyncObjectEvent(object,
1633  Enqueue(event);
1634 }
1635 
1637  return singleton_;
1638 }
1639 
1640 // Create a dummy KSync Entry. This entry will all ways be in deferred state
1641 // Any back-ref added to it will never get resolved.
1642 // Can be used to defer an incomplete entry
1643 
1644 class KSyncDummyEntry : public KSyncEntry {
1645 public:
1647  virtual ~KSyncDummyEntry() { }
1648  virtual bool IsLess(const KSyncEntry &rhs) const {
1649  return false;
1650  }
1651  std::string ToString() const { return "Dummy"; }
1652  bool Add() { return false;}
1653  bool Change() { return false; }
1654  bool Delete() { return false; }
1655  KSyncObject *GetObject() const { return NULL; }
1656  KSyncEntry *UnresolvedReference() { return NULL; }
1657  bool IsDataResolved() {return false;}
1658 private:
1660 };
1661 
1663  if (default_defer_entry_.get() == NULL) {
1665  }
1666  return default_defer_entry_.get();
1667 }
VrouterErrorDescriptionMap g_error_description
Definition: ksync_object.cc:38
#define KSYNC_TRACE(obj, parent,...)
Definition: ksync_object.h:304
KSyncEntry::KSyncState KSyncSM_AddDefer(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
int intrusive_ptr_add_ref(const AsPath *cpath)
Definition: bgp_aspath.h:147
std::string AckOperationString(KSyncEvent ack_event) const
DBEntry * GetDBEntry()
Definition: ksync_entry.h:253
void Change(KSyncEntry *entry)
DupEntryList dup_entry_list_
Definition: ksync_entry.h:259
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
std::map< uint32_t, std::string > VrouterErrorDescriptionMap
Definition: ksync_object.cc:37
void RegisterDb(DBTableBase *table)
uint32_t GetRefCount() const
Definition: ksync_entry.h:159
virtual void StaleTimerExpired()
Definition: ksync_entry.h:154
KSyncEntry::KSyncState KSyncSM_SyncWait(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
virtual bool IsDataResolved()
Definition: ksync_entry.h:131
bool IsResolved()
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
Definition: db_entry.cc:37
uint16_t stale_entries_per_intvl_
Definition: ksync_object.h:201
KSyncEntry::KSyncState KSyncSM_Init(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
DISALLOW_COPY_AND_ASSIGN(KSyncDummyEntry)
KSyncObject(const std::string &name)
Definition: ksync_object.cc:55
virtual ~KSyncDummyEntry()
KSyncEntry::KSyncState KSyncSM_Change(KSyncObject *obj, KSyncEntry *entry)
KSyncEntry::KSyncState KSyncSM_DelAckWait(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
DBTableBase::ListenerId test_id_
Definition: ksync_object.h:264
virtual void Response()
Definition: ksync_entry.h:134
std::string StateString() const
bool IsDeleted() const
Definition: db_entry.h:49
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
Definition: db_entry.cc:22
virtual bool Add()=0
KSyncEntry::KSyncState KSyncSM_InSync(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
KSyncEntry::KSyncState KSyncSM_ChangeDefer(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
void BackRefDel(KSyncEntry *key)
int ListenerId
Definition: db_table.h:62
void Delete(KSyncEntry *entry)
#define KSYNC_ERROR_TRACE(obj,...)
Definition: ksync_entry.h:24
DBTableBase * parent()
KSyncEntry::KSyncState KSyncSM_DelPending_Sync(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
WorkQueue< KSyncObjectEvent * > * event_queue_
Definition: ksync_object.h:299
#define KSYNC_ERROR(obj,...)
Definition: ksync_entry.h:16
KSyncEntry::KSyncState KSyncSM_RenewWait(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
bool del_add_pending() const
Definition: ksync_entry.h:158
KSyncObject * GetObject() const
void TestTriggerStaleEntryCleanupCb(KSyncObject *obj)
Definition: ksync_object.cc:51
KSyncEntry * back_reference_
Definition: ksync_object.h:67
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
Definition: sandesh_trace.h:18
virtual bool Change()=0
bool StaleEntryCleanupCb()
KSyncEntry::KSyncState KSyncSM_DelPending_DelAck(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
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 Unregister(ListenerId listener)
Definition: db_table.cc:186
int GetTaskId(const std::string &name)
Definition: task.cc:856
void set_del_add_pending(bool pending)
Definition: ksync_entry.h:174
virtual void CleanupOnDel(KSyncEntry *kentry)
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
Definition: db_table.cc:181
size_t Alloc()
Definition: ksync_index.h:23
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
void SetState(KSyncState state)
Definition: ksync_entry.h:181
Timer * stale_entry_cleanup_timer_
Definition: ksync_object.h:198
void Free(size_t index)
Definition: ksync_index.h:30
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)
static TaskScheduler * GetInstance()
Definition: task.cc:547
KSyncEntry::KSyncState KSyncSM_Add(KSyncObject *obj, KSyncEntry *entry)
Event
Definition: http_client.h:27
DBTableBase::ListenerId id() const
Definition: ksync_object.h:256
tbb::atomic< int > refcount_
Definition: ksync_entry.h:192
boost::intrusive_ptr< KSyncEntry > KSyncEntryPtr
Definition: ksync_entry.h:68
SandeshTraceBufferPtr KSyncTraceBuf
Definition: ksync_object.h:202
virtual KSyncObject * GetObject() const =0
KSyncEntry * reference_
Definition: ksync_object.h:45
virtual bool AllowDeleteStateComp()
Definition: ksync_entry.h:137
void BackRefAdd(KSyncEntry *key, KSyncEntry *reference)
KSyncState GetState() const
Definition: ksync_entry.h:157
void ClearStale(KSyncEntry *entry)
virtual bool ShouldReEvalBackReference() const
Definition: ksync_entry.h:125
Definition: trace.h:220
KSyncEntry::KSyncState KSyncSM_Delete(KSyncEntry *entry)
std::string ToString() const
virtual ~KSyncDBObject()
static void Shutdown()
Definition: ksync_object.cc:94
void SetSeen()
Definition: ksync_entry.h:162
bool stale() const
Definition: ksync_entry.h:161
virtual uint32_t GetKey(KSyncEntry *entry)
static const size_t kInvalidIndex
Definition: ksync_entry.h:69
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
virtual std::string VrouterError(uint32_t error) const
KSyncEntry * Find(const KSyncEntry *key)
Definition: ksync_object.cc:99
DBTableBase::ListenerId id_
Definition: ksync_object.h:263
SandeshTraceBufferPtr KSyncErrorTraceBuf
std::string EventString(KSyncEvent event) const
static Timer * CreateTimer(boost::asio::io_context &service, const std::string &name, int task_id=Timer::GetTimerTaskId(), int task_instance=Timer::GetTimerInstanceId(), bool delete_on_completion=false)
Definition: timer.cc:201
void ClearState(DBTableBase *tbl_base, ListenerId listener)
Definition: db_entry.cc:73
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)
static std::string VrouterErrorToString(uint32_t error)
void BackRefReEval(KSyncEntry *key)
bool IsIndexValid() const
Definition: ksync_object.h:173
bool IsDeleted()
Definition: ksync_entry.h:163
boost::intrusive::set< KSyncFwdReference, KSyncFwdRefNode > FwdRefTree
Definition: ksync_object.h:80
DBTableBase::ListenerId GetListenerId(DBTableBase *table)
KSyncEntry::KSyncState KSyncSM_Temp(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
static std::unique_ptr< KSyncEntry > default_defer_entry_
Definition: ksync_object.h:300
virtual bool Sync(DBEntry *entry)=0
KSyncEntry * CreateStale(const KSyncEntry *key)
void Delete(KSyncObject *)
void RecordTransition(KSyncState from, KSyncState to, KSyncEvent event)
Definition: ksync_entry.h:175
size_t index_
Definition: ksync_entry.h:190
static const int kMaxEntriesProcess
Definition: ksync_object.h:286
virtual void ErrorHandler(int err, uint32_t seqno, KSyncEvent event) const
virtual std::string ToString() const =0
virtual bool IsLess(const KSyncEntry &rhs) const
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
Definition: timer.cc:108
bool delete_scheduled_
Definition: ksync_object.h:192
bool need_index_
Definition: ksync_object.h:188
KSyncEntry * UnresolvedReference()
tbb::recursive_mutex lock_
Definition: ksync_object.h:156
KSyncState state_
Definition: ksync_entry.h:191
#define LOG(_Level, _Msg)
Definition: logging.h:33
void UnregisterDb(DBTableBase *table)
KSyncEntry::KSyncState KSyncSM_DeleteAdd(KSyncObject *obj, KSyncEntry *entry)
static FwdRefTree fwd_ref_tree_
Definition: ksync_object.h:184
void intrusive_ptr_release(const AsPath *cpath)
Definition: bgp_aspath.h:155
static KSyncEntry * default_defer_entry()
static KSyncObjectManager * Init()
void set_test_id(DBTableBase::ListenerId id)
virtual KSyncEntry * UnresolvedReference()=0
virtual void CleanupOnDel(KSyncEntry *kentry)
Definition: ksync_object.h:179
KSyncEntry::KSyncState KSyncSM_DelPending_Ref(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
bool Reschedule(int time)
Definition: timer.cc:137
static void Shutdown()
virtual void EmptyTable(void)
Definition: ksync_object.h:137
size_t GetIndex() const
Definition: ksync_entry.h:156
bool Seen() const
Definition: ksync_entry.h:160
virtual KSyncEntry * Alloc(const KSyncEntry *key, uint32_t index)=0
static KSyncObjectManager * GetInstance()
KSyncEntry::KSyncState KSyncSM_NeedSync(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
bool Enqueue(QueueEntryT entry)
Definition: queue_task.h:248
KSyncObject * obj_
Definition: ksync_object.h:280
static KSyncObjectManager * singleton_
Definition: ksync_object.h:301
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
void SetDBEntry(DBEntry *db_entry)
Definition: ksync_entry.h:252
virtual bool Delete()=0
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
Definition: sandesh_trace.h:46
static bool DeleteTimer(Timer *Timer)
Definition: timer.cc:222