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