5 #include <sys/socket.h>
8 #include <linux/netlink.h>
9 #include <linux/rtnetlink.h>
10 #include <linux/sockios.h>
13 #include <boost/bind.hpp>
14 #include <boost/assign/list_of.hpp>
22 #include <sandesh/sandesh_trace.h>
27 #include "ksync_types.h"
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");
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) {
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) {
73 assert(
tree_.size() == 0);
80 uint32_t cleanup_time,
81 uint32_t cleanup_intvl,
82 uint16_t entries_per_intvl) {
86 "KSync Stale Entry Cleanup Timer",
100 Tree::iterator it =
tree_.find(*key);
101 if (it !=
tree_.end()) {
102 return it.operator->();
109 tbb::recursive_mutex::scoped_lock lock(
lock_);
110 Tree::const_iterator it;
114 it =
tree_.iterator_to(*entry);
117 if (it !=
tree_.end()) {
118 return const_cast<KSyncEntry *
>(it.operator->());
132 std::pair<Tree::iterator, bool> ret =
tree_.insert(*entry);
133 if (ret.second ==
false) {
138 entry = ret.first.operator->();
157 tbb::recursive_mutex::scoped_lock lock(
lock_);
160 if (no_lookup ==
false)
180 return Create(key,
false);
187 tbb::recursive_mutex::scoped_lock lock(
lock_);
237 tbb::recursive_mutex::scoped_lock lock(
lock_);
238 assert(
tree_.erase(*entry) > 0);
239 uint32_t old_key =
GetKey(entry);
241 std::pair<Tree::iterator, bool> ret =
tree_.insert(*entry);
242 if (ret.second ==
false) {
246 assert(
tree_.erase(*current) > 0);
249 assert(
tree_.insert(*current).second ==
true);
250 assert(
tree_.insert(*entry).second ==
true);
260 assert(
tree_.erase(*entry) > 0);
274 tbb::recursive_mutex::scoped_lock lock(
lock_);
286 int max_index) :
KSyncObject(name, max_index), test_id_(-1) {
364 tbb::recursive_mutex::scoped_lock lock(
lock_);
403 KSyncDBEntry::DupEntryList::iterator it_dup;
406 if (entry == *it_dup)
447 bool need_sync =
false;
458 if (ksync->
stale()) {
469 if (old_db_entry != NULL) {
496 if (ksync->
Sync(entry) || need_sync) {
514 std::map<uint32_t, std::string>::iterator iter =
517 return strerror(error);
531 KSYNC_ERROR(VRouterError,
"VRouter operation failed. Error <", err,
532 ":", error_msg,
">. Object <",
ToString(),
534 ">. Message number :", seq_no);
536 std::stringstream sstr;
537 sstr <<
"VRouter operation failed. Error <" << err <<
":" << error_msg <<
538 ">. Object <" <<
ToString() <<
">. Operation <" <<
541 LOG(ERROR, sstr.str().c_str());
563 std::stringstream str;
579 str <<
"Change defer";
595 str <<
"Delete defer sync";
599 str <<
"Delete pending due to reference";
603 str <<
"Delete pending due to Delete ack wait";
607 str <<
"Delete ack wait";
620 str <<
" (Stale entry) ";
623 str <<
'(' <<
state_ <<
')';
629 std::stringstream str;
632 str <<
"Add/Change request";
644 str <<
"Delete request";
648 str <<
"Delete followed by Add request";
656 str <<
"Re-evaluate";
660 str <<
"Reference release";
666 str <<
'(' <<
event <<
')';
766 assert(entry->
Seen());
811 assert(!entry->
stale());
1171 if (!entry->
Seen()) {
1335 bool dep_reval =
false;
1339 std::string obj_string(entry->
ToString());
1341 std::string event_string(entry->
EventString(event));
1408 if (dep_reval ==
true && entry->
IsResolved() &&
1422 if (
tree_.empty() ==
true) {
1428 tbb::recursive_mutex::scoped_lock lock(
lock_);
1467 FwdRefTree::iterator fwd_it =
fwd_ref_tree_.find(*fwd_node);
1481 FwdRefTree::iterator fwd_it =
fwd_ref_tree_.find(fwd_search_node);
1491 BackRefTree::iterator back_it =
back_ref_tree_.find(back_search_node);
1502 std::vector<KSyncEntry *> buf;
1505 for (BackRefTree::iterator it =
back_ref_tree_.upper_bound(node);
1507 BackRefTree::iterator it_work = it;
1510 if (entry->
key_ != key) {
1514 buf.push_back(back_ref);
1519 std::vector<KSyncEntry *>::iterator it = buf.begin();
1520 while (it != buf.end()) {
1521 tbb::recursive_mutex::scoped_lock lock((*it)->GetObject()->lock_);
1539 if (event->
ref_.get() == NULL) {
1540 event->obj_->set_delete_scheduled();
1544 event->obj_->EmptyTable();
1548 entry =
event->obj_->Next(NULL);
1550 entry =
event->ref_.get();
1557 while (entry.get() != NULL) {
1558 next_entry =
event->obj_->Next(entry.get());
1560 if (entry->IsDeleted() ==
false) {
1562 event->obj_->Delete(entry.get());
1568 event->ref_ = next_entry.get();
1576 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
tbb::atomic< int > refcount_
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)
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)
tbb::recursive_mutex lock_
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)
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_