5 #include <sys/socket.h>
8 #include <linux/netlink.h>
9 #include <linux/rtnetlink.h>
10 #include <linux/sockios.h>
13 #include <boost/bind/bind.hpp>
14 #include <boost/assign/list_of.hpp>
22 #include <sandesh/sandesh_trace.h>
27 #include "ksync_types.h"
29 using namespace boost::placeholders;
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");
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) {
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) {
75 assert(
tree_.size() == 0);
82 uint32_t cleanup_time,
83 uint32_t cleanup_intvl,
84 uint16_t entries_per_intvl) {
88 "KSync Stale Entry Cleanup Timer",
102 Tree::iterator it =
tree_.find(*key);
103 if (it !=
tree_.end()) {
104 return it.operator->();
111 std::lock_guard<std::recursive_mutex> lock(
lock_);
112 Tree::const_iterator it;
116 it =
tree_.iterator_to(*entry);
119 if (it !=
tree_.end()) {
120 return const_cast<KSyncEntry *
>(it.operator->());
134 std::pair<Tree::iterator, bool> ret =
tree_.insert(*entry);
135 if (ret.second ==
false) {
140 entry = ret.first.operator->();
159 std::lock_guard<std::recursive_mutex> lock(
lock_);
162 if (no_lookup ==
false)
182 return Create(key,
false);
189 std::lock_guard<std::recursive_mutex> lock(
lock_);
239 std::lock_guard<std::recursive_mutex> lock(
lock_);
240 assert(
tree_.erase(*entry) > 0);
241 uint32_t old_key =
GetKey(entry);
243 std::pair<Tree::iterator, bool> ret =
tree_.insert(*entry);
244 if (ret.second ==
false) {
248 assert(
tree_.erase(*current) > 0);
251 assert(
tree_.insert(*current).second ==
true);
252 assert(
tree_.insert(*entry).second ==
true);
262 assert(
tree_.erase(*entry) > 0);
276 std::lock_guard<std::recursive_mutex> lock(
lock_);
288 int max_index) :
KSyncObject(name, max_index), test_id_(-1) {
366 std::lock_guard<std::recursive_mutex> lock(
lock_);
405 KSyncDBEntry::DupEntryList::iterator it_dup;
408 if (entry == *it_dup)
449 bool need_sync =
false;
460 if (ksync->
stale()) {
471 if (old_db_entry != NULL) {
498 if (ksync->
Sync(entry) || need_sync) {
516 std::map<uint32_t, std::string>::iterator iter =
519 return strerror(error);
533 KSYNC_ERROR(VRouterError,
"VRouter operation failed. Error <", err,
534 ":", error_msg,
">. Object <",
ToString(),
536 ">. Message number :", seq_no);
538 std::stringstream sstr;
539 sstr <<
"VRouter operation failed. Error <" << err <<
":" << error_msg <<
540 ">. Object <" <<
ToString() <<
">. Operation <" <<
543 LOG(ERROR, sstr.str().c_str());
565 std::stringstream str;
581 str <<
"Change defer";
597 str <<
"Delete defer sync";
601 str <<
"Delete pending due to reference";
605 str <<
"Delete pending due to Delete ack wait";
609 str <<
"Delete ack wait";
622 str <<
" (Stale entry) ";
625 str <<
'(' <<
state_ <<
')';
631 std::stringstream str;
634 str <<
"Add/Change request";
646 str <<
"Delete request";
650 str <<
"Delete followed by Add request";
658 str <<
"Re-evaluate";
662 str <<
"Reference release";
668 str <<
'(' <<
event <<
')';
768 assert(entry->
Seen());
813 assert(!entry->
stale());
1173 if (!entry->
Seen()) {
1337 bool dep_reval =
false;
1341 std::string obj_string(entry->
ToString());
1343 std::string event_string(entry->
EventString(event));
1410 if (dep_reval ==
true && entry->
IsResolved() &&
1424 if (
tree_.empty() ==
true) {
1430 std::lock_guard<std::recursive_mutex> lock(
lock_);
1469 FwdRefTree::iterator fwd_it =
fwd_ref_tree_.find(*fwd_node);
1483 FwdRefTree::iterator fwd_it =
fwd_ref_tree_.find(fwd_search_node);
1493 BackRefTree::iterator back_it =
back_ref_tree_.find(back_search_node);
1504 std::vector<KSyncEntry *> buf;
1507 for (BackRefTree::iterator it =
back_ref_tree_.upper_bound(node);
1509 BackRefTree::iterator it_work = it;
1512 if (entry->
key_ != key) {
1516 buf.push_back(back_ref);
1521 std::vector<KSyncEntry *>::iterator it = buf.begin();
1522 while (it != buf.end()) {
1523 std::lock_guard<std::recursive_mutex> lock((*it)->GetObject()->lock_);
1541 if (event->
ref_.get() == NULL) {
1542 event->obj_->set_delete_scheduled();
1546 event->obj_->EmptyTable();
1550 entry =
event->obj_->Next(NULL);
1552 entry =
event->ref_.get();
1559 while (entry.get() != NULL) {
1560 next_entry =
event->obj_->Next(entry.get());
1562 if (entry->IsDeleted() ==
false) {
1564 event->obj_->Delete(entry.get());
1570 event->ref_ = next_entry.get();
1578 entry = next_entry.get();
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
void ClearState(DBTableBase *tbl_base, ListenerId listener)
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
void Unregister(ListenerId listener)
DupEntryList dup_entry_list_
void SetDBEntry(DBEntry *db_entry)
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
DBTableBase::ListenerId id_
virtual void CleanupOnDel(KSyncEntry *kentry)
DBTableBase::ListenerId test_id_
virtual DBFilterResp DBEntryFilter(const DBEntry *entry, const KSyncDBEntry *ksync)
void RegisterDb(DBTableBase *table)
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()
virtual std::string VrouterError(uint32_t error) const
virtual bool IsDataResolved()
std::string AckOperationString(KSyncEvent ack_event) const
virtual KSyncObject * GetObject() const =0
void SetState(KSyncState state)
void set_del_add_pending(bool pending)
virtual std::string ToString() const =0
bool del_add_pending() const
std::string EventString(KSyncEvent event) const
std::string StateString() const
virtual bool ShouldReEvalBackReference() const
virtual void StaleTimerExpired()
boost::intrusive_ptr< KSyncEntry > KSyncEntryPtr
void RecordTransition(KSyncState from, KSyncState to, KSyncEvent event)
virtual void ErrorHandler(int err, uint32_t seqno, KSyncEvent event) const
static std::string VrouterErrorToString(uint32_t error)
std::atomic< int > refcount_
uint32_t GetRefCount() const
static const size_t kInvalidIndex
KSyncState GetState() const
virtual KSyncEntry * UnresolvedReference()=0
static std::unique_ptr< KSyncEntry > default_defer_entry_
WorkQueue< KSyncObjectEvent * > * event_queue_
static KSyncEntry * default_defer_entry()
bool Process(KSyncObjectEvent *event)
static KSyncObjectManager * GetInstance()
static KSyncObjectManager * singleton_
void Enqueue(KSyncObjectEvent *event)
static const int kMaxEntriesProcess
static void Unregister(KSyncObject *)
static KSyncObjectManager * Init()
void Delete(KSyncObject *)
boost::intrusive::set< KSyncBackReference, KSyncBackRefNode > BackRefTree
virtual void NetlinkAck(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
bool IsIndexValid() const
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_
virtual bool DoEventTrace(void)
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_
KSyncEntry * Next(const KSyncEntry *entry) const
virtual void CleanupOnDel(KSyncEntry *kentry)
void SafeNotifyEvent(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
void BackRefAdd(KSyncEntry *key, KSyncEntry *reference)
void NetlinkAckInternal(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
void BackRefDel(KSyncEntry *key)
virtual void EmptyTable(void)
virtual void PreFree(KSyncEntry *entry)
uint16_t stale_entries_per_intvl_
virtual uint32_t GetKey(KSyncEntry *entry)
KSyncEntry * CreateStale(const KSyncEntry *key)
void NotifyEvent(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
KSyncObject(const std::string &name)
KSyncIndexTable index_table_
boost::intrusive::set< KSyncFwdReference, KSyncFwdRefNode > FwdRefTree
virtual void Free(KSyncEntry *entry)
std::recursive_mutex lock_
KSyncEntry * GetReference(const KSyncEntry *key)
SandeshTraceBufferPtr KSyncTraceBuf
static BackRefTree back_ref_tree_
Timer * stale_entry_cleanup_timer_
virtual void UpdateKey(KSyncEntry *entry, uint32_t arg)
void InitStaleEntryCleanup(boost::asio::io_context &ios, uint32_t cleanup_time, uint32_t cleanup_intvl, uint16_t entries_per_intvl)
KSyncEntry * Create(const KSyncEntry *key)
std::set< KSyncEntry::KSyncEntryPtr > stale_entry_tree_
void Delete(KSyncEntry *entry)
static TaskScheduler * GetInstance()
static bool DeleteTimer(Timer *Timer)
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)
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
bool Reschedule(int time)
bool Enqueue(QueueEntryT entry)
#define KSYNC_ERROR(obj,...)
#define KSYNC_ERROR_TRACE(obj,...)
void TestTriggerStaleEntryCleanupCb(KSyncObject *obj)
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
VrouterErrorDescriptionMap g_error_description
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,...)
#define LOG(_Level, _Msg)
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
KSyncEntry * back_reference_
KSyncEntry::KSyncEntryPtr ref_