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 =
515 g_error_description.find(error);
516 if (iter == g_error_description.end())
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();
VrouterErrorDescriptionMap g_error_description
#define KSYNC_TRACE(obj, parent,...)
KSyncEntry::KSyncState KSyncSM_AddDefer(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
int intrusive_ptr_add_ref(const AsPath *cpath)
std::string AckOperationString(KSyncEvent ack_event) const
void Change(KSyncEntry *entry)
DupEntryList dup_entry_list_
void InitStaleEntryCleanup(boost::asio::io_context &ios, uint32_t cleanup_time, uint32_t cleanup_intvl, uint16_t entries_per_intvl)
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
void RegisterDb(DBTableBase *table)
uint32_t GetRefCount() const
virtual void StaleTimerExpired()
KSyncEntry::KSyncState KSyncSM_SyncWait(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
virtual bool IsDataResolved()
DBState * GetState(DBTableBase *tbl_base, ListenerId listener) const
uint16_t stale_entries_per_intvl_
KSyncEntry::KSyncState KSyncSM_Init(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
DISALLOW_COPY_AND_ASSIGN(KSyncDummyEntry)
KSyncObject(const std::string &name)
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_
std::string StateString() const
void SetState(DBTableBase *tbl_base, ListenerId listener, DBState *state)
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)
void Delete(KSyncEntry *entry)
#define KSYNC_ERROR_TRACE(obj,...)
KSyncEntry::KSyncState KSyncSM_DelPending_Sync(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
WorkQueue< KSyncObjectEvent * > * event_queue_
#define KSYNC_ERROR(obj,...)
KSyncEntry::KSyncState KSyncSM_RenewWait(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
bool del_add_pending() const
KSyncObject * GetObject() const
void TestTriggerStaleEntryCleanupCb(KSyncObject *obj)
KSyncEntry * back_reference_
boost::shared_ptr< TraceBuffer< SandeshTrace > > SandeshTraceBufferPtr
bool StaleEntryCleanupCb()
KSyncEntry::KSyncState KSyncSM_DelPending_DelAck(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
static void Unregister(KSyncObject *)
virtual void Free(KSyncEntry *entry)
virtual void NetlinkAck(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
void ChangeKey(KSyncEntry *entry, uint32_t arg)
void Enqueue(KSyncObjectEvent *event)
void Unregister(ListenerId listener)
int GetTaskId(const std::string &name)
void set_del_add_pending(bool pending)
virtual void CleanupOnDel(KSyncEntry *kentry)
ListenerId Register(ChangeCallback callback, const std::string &name="unspecified")
void NetlinkAckInternal(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
boost::intrusive::set< KSyncBackReference, KSyncBackRefNode > BackRefTree
std::set< KSyncEntry::KSyncEntryPtr > stale_entry_tree_
KSyncEntry * CreateImpl(const KSyncEntry *key)
virtual bool DoEventTrace(void)
void SetState(KSyncState state)
Timer * stale_entry_cleanup_timer_
virtual void UpdateKey(KSyncEntry *entry, uint32_t arg)
KSyncDBObject(const std::string &name)
void SafeNotifyEvent(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
static TaskScheduler * GetInstance()
KSyncEntry::KSyncState KSyncSM_Add(KSyncObject *obj, KSyncEntry *entry)
DBTableBase::ListenerId id() const
tbb::atomic< int > refcount_
boost::intrusive_ptr< KSyncEntry > KSyncEntryPtr
SandeshTraceBufferPtr KSyncTraceBuf
virtual KSyncObject * GetObject() const =0
virtual bool AllowDeleteStateComp()
void BackRefAdd(KSyncEntry *key, KSyncEntry *reference)
KSyncState GetState() const
void ClearStale(KSyncEntry *entry)
virtual bool ShouldReEvalBackReference() const
KSyncEntry::KSyncState KSyncSM_Delete(KSyncEntry *entry)
std::string ToString() const
virtual uint32_t GetKey(KSyncEntry *entry)
static const size_t kInvalidIndex
void Notify(DBTablePartBase *partition, DBEntryBase *entry)
void NotifyEvent(KSyncEntry *entry, KSyncEntry::KSyncEvent event)
uint32_t stale_entry_cleanup_intvl_
static BackRefTree back_ref_tree_
virtual void PreFree(KSyncEntry *entry)
virtual std::string VrouterError(uint32_t error) const
KSyncEntry * Find(const KSyncEntry *key)
DBTableBase::ListenerId id_
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)
void ClearState(DBTableBase *tbl_base, ListenerId listener)
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
boost::intrusive::set< KSyncFwdReference, KSyncFwdRefNode > FwdRefTree
DBTableBase::ListenerId GetListenerId(DBTableBase *table)
KSyncEntry::KSyncState KSyncSM_Temp(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
static std::unique_ptr< KSyncEntry > default_defer_entry_
virtual bool Sync(DBEntry *entry)=0
KSyncEntry * CreateStale(const KSyncEntry *key)
void Delete(KSyncObject *)
void RecordTransition(KSyncState from, KSyncState to, KSyncEvent event)
static const int kMaxEntriesProcess
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)
KSyncEntry * UnresolvedReference()
tbb::recursive_mutex lock_
#define LOG(_Level, _Msg)
void UnregisterDb(DBTableBase *table)
KSyncEntry::KSyncState KSyncSM_DeleteAdd(KSyncObject *obj, KSyncEntry *entry)
static FwdRefTree fwd_ref_tree_
void intrusive_ptr_release(const AsPath *cpath)
static KSyncEntry * default_defer_entry()
static KSyncObjectManager * Init()
void set_test_id(DBTableBase::ListenerId id)
virtual KSyncEntry * UnresolvedReference()=0
virtual void CleanupOnDel(KSyncEntry *kentry)
KSyncEntry::KSyncState KSyncSM_DelPending_Ref(KSyncObject *obj, KSyncEntry *entry, KSyncEntry::KSyncEvent event)
bool Reschedule(int time)
virtual void EmptyTable(void)
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)
static KSyncObjectManager * singleton_
KSyncIndexTable index_table_
KSyncEntry::KSyncEntryPtr ref_
void SetDBEntry(DBEntry *db_entry)
SandeshTraceBufferPtr SandeshTraceBufferCreate(const std::string &buf_name, size_t buf_size, bool trace_enable=true)
static bool DeleteTimer(Timer *Timer)