Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef vnsw_agent_db_hpp 6 : #define vnsw_agent_db_hpp 7 : 8 : #include <atomic> 9 : #include <mutex> 10 : #include <cmn/agent_cmn.h> 11 : 12 : class Agent; 13 : class AgentDBEntry; 14 : class AgentDBTable; 15 : struct AgentDBState; 16 : class AgentSandesh; 17 : class AgentSandeshArguments; 18 : class AgentSandesh; 19 : class ResourceManager; 20 : typedef class boost::shared_ptr<AgentSandesh> AgentSandeshPtr; 21 : 22 : ///////////////////////////////////////////////////////////////////////////// 23 : // Refcount class for AgentDBEntry 24 : ///////////////////////////////////////////////////////////////////////////// 25 : template <class Derived> 26 : class AgentRefCount { 27 : public: 28 4401 : friend void intrusive_ptr_add_ref(const Derived* p) { 29 4401 : const AgentRefCount *entry = (const AgentRefCount *) (p); 30 8802 : if (entry->refcount_.fetch_add(1) == 0) { 31 295 : p->SetRefState(); 32 : } 33 4401 : } 34 : 35 4400 : friend void intrusive_ptr_release(const Derived* p) { 36 4400 : const AgentRefCount *entry = (const AgentRefCount *) (p); 37 8800 : if (entry->refcount_.fetch_sub(1) == 1) { 38 294 : p->ClearRefState(); 39 : } 40 4400 : } 41 : 42 1010 : friend void intrusive_ptr_add_back_ref(const IntrusiveReferrer ref, 43 : const Derived* p) { 44 1010 : const AgentRefCount *entry = (const AgentRefCount *) (p); 45 1010 : std::scoped_lock lock(entry->back_ref_mutex_); 46 1010 : entry->back_ref_set_.insert(ref); 47 1010 : } 48 : 49 2039 : friend void intrusive_ptr_del_back_ref(const IntrusiveReferrer ref, 50 : const Derived* p) { 51 2039 : const AgentRefCount *entry = (const AgentRefCount *) (p); 52 2039 : std::scoped_lock lock(entry->back_ref_mutex_); 53 2039 : entry->back_ref_set_.erase(ref); 54 2039 : } 55 : 56 424 : uint32_t GetRefCount() const {return refcount_;}; 57 : protected: 58 319704 : AgentRefCount() {refcount_ = 0;} 59 : AgentRefCount(const AgentRefCount&) { refcount_ = 0; } 60 : AgentRefCount& operator=(const AgentRefCount&) { return *this; } 61 320825 : virtual ~AgentRefCount() {assert(refcount_ == 0);}; 62 : void swap(AgentRefCount&) {}; 63 : 64 : mutable std::mutex back_ref_mutex_; 65 : mutable std::set<IntrusiveReferrer> back_ref_set_; 66 : 67 : private: 68 : mutable std::atomic<uint32_t> refcount_; 69 : }; 70 : 71 : ///////////////////////////////////////////////////////////////////////////// 72 : // DBState for AgentDBEntry 73 : ///////////////////////////////////////////////////////////////////////////// 74 : struct AgentDBState : DBState { 75 290 : AgentDBState(const AgentDBEntry *entry) : DBState(), entry_(entry) { }; 76 : const AgentDBEntry *entry_; 77 : }; 78 : 79 : ///////////////////////////////////////////////////////////////////////////// 80 : // VNSwitch DB Table Partition class 81 : ///////////////////////////////////////////////////////////////////////////// 82 : class AgentDBTablePartition: public DBTablePartition { 83 : public: 84 48 : AgentDBTablePartition(DBTable *parent, int index) : 85 48 : DBTablePartition(parent, index) { }; 86 96 : virtual ~AgentDBTablePartition() {}; 87 : virtual void Add(DBEntry *entry); 88 : virtual void Remove(DBEntryBase *entry); 89 : 90 : private: 91 : DISALLOW_COPY_AND_ASSIGN(AgentDBTablePartition); 92 : }; 93 : 94 : ///////////////////////////////////////////////////////////////////////////// 95 : // VNSwitch DB Entry Key base class. Defines additional operations on DBEntry 96 : ///////////////////////////////////////////////////////////////////////////// 97 : struct AgentKey : public DBRequestKey { 98 : typedef enum { 99 : // Add/Delete/Change a entry 100 : ADD_DEL_CHANGE, 101 : // Change an entry if its already present and not in deleted state 102 : // Its a no-op if entry is not present or is in deleted state 103 : RESYNC, 104 : } DBSubOperation; 105 : 106 6139 : AgentKey() : DBRequestKey(), sub_op_(ADD_DEL_CHANGE) { }; 107 31301 : AgentKey(DBSubOperation sub_op) : DBRequestKey(), sub_op_(sub_op) { }; 108 37440 : virtual ~AgentKey() { }; 109 : 110 : uint8_t sub_op_; 111 : }; 112 : 113 : ///////////////////////////////////////////////////////////////////////////// 114 : // VNSwitch DB Entry Data base class 115 : ///////////////////////////////////////////////////////////////////////////// 116 : struct AgentData : public DBRequestData { 117 1259 : AgentData() : DBRequestData() { }; 118 1259 : virtual ~AgentData() { }; 119 : }; 120 : 121 : ///////////////////////////////////////////////////////////////////////////// 122 : // VNSwitch DB Entry base class. Supports 123 : // 1. Reference counting with boost Intrusive pointer 124 : ///////////////////////////////////////////////////////////////////////////// 125 : class AgentDBEntry : public DBEntry { 126 : public: 127 5366 : AgentDBEntry() : DBEntry() {}; 128 5365 : virtual ~AgentDBEntry() {}; 129 : virtual uint32_t GetRefCount() const = 0; 130 : 131 : typedef boost::intrusive_ptr<AgentDBEntry> AgentDBEntyRef; 132 : void SetRefState() const; 133 : void ClearRefState() const; 134 : bool IsActive() const; 135 : DBState *GetAgentDBEntryState(int listener_id); 136 : const DBState *GetAgentDBEntryState(int listener_id) const; 137 : 138 : virtual void AllocateResources(ResourceManager *resource_manager); 139 : virtual void FreeResources(ResourceManager *resource_manager); 140 : virtual void PostAdd(); 141 : virtual bool DBEntrySandesh(Sandesh *resp, std::string &name) const = 0; 142 : private: 143 : friend class AgentDBTable; 144 : DISALLOW_COPY_AND_ASSIGN(AgentDBEntry); 145 : }; 146 : 147 : ///////////////////////////////////////////////////////////////////////////// 148 : // VNSwitch DB Table base class 149 : ///////////////////////////////////////////////////////////////////////////// 150 : class AgentDBTable : public DBTable { 151 : public: 152 : static const int kPartitionCount = 1; 153 : AgentDBTable(DB *db, const std::string &name); 154 : AgentDBTable(DB *db, const std::string &name, bool del_on_zero_refcount); 155 : virtual ~AgentDBTable(); 156 : 157 214 : virtual int PartitionCount() const { return kPartitionCount; } 158 : virtual void Input(DBTablePartition *root, DBClient *client, 159 : DBRequest *req); 160 0 : virtual DBEntry *CfgAdd(DBRequest *req) {return NULL;}; 161 0 : virtual bool Resync(DBEntry *entry, const DBRequest *req) {return false;}; 162 : 163 : /* 164 : * Clear all entries on a table. Requires the table to have no listeners. 165 : * Used in process shutdown. 166 : */ 167 : virtual void Clear(); 168 : 169 0 : virtual bool IFNodeToReq(IFMapNode *node, DBRequest &req, 170 : const boost::uuids::uuid &uuid) { 171 0 : assert(0); 172 : return false; 173 : } 174 0 : virtual bool IFLinkToReq(IFMapLink *link, IFMapNode *node, 175 : const std::string &peer_name, IFMapNode *peer, 176 : DBRequest &req) { 177 0 : assert(0); 178 : return false; 179 : } 180 : virtual bool IFNodeToUuid(IFMapNode *node, boost::uuids::uuid &id); 181 : 182 48 : virtual DBTablePartition *AllocPartition(int index) { 183 48 : return new AgentDBTablePartition(this, index); 184 : }; 185 54 : virtual void OnZeroRefcount(AgentDBEntry *e) {}; 186 : virtual void NotifyEntry(DBEntryBase *entry); 187 : 188 0 : virtual AgentSandeshPtr GetAgentSandesh(const AgentSandeshArguments *args, 189 : const std::string &context) { 190 0 : return AgentSandeshPtr(); 191 : } 192 : 193 : // Dummy notification 194 727 : void Notify(DBTablePartBase *partition, DBEntryBase *entry) { 195 727 : }; 196 : 197 868 : DBTableBase::ListenerId GetRefListenerId() const {return ref_listener_id_;}; 198 : AgentDBEntry *FindActiveEntry(const DBEntry *key); 199 : AgentDBEntry *FindActiveEntryNoLock(const DBEntry *key); 200 : AgentDBEntry *FindActiveEntry(const DBRequestKey *key); 201 : AgentDBEntry *FindActiveEntryNoLock(const DBRequestKey *key); 202 : AgentDBEntry *Find(const DBEntry *key, bool ret_del); 203 : AgentDBEntry *Find(const DBRequestKey *key, bool ret_del); 204 0 : virtual bool CanNotify(IFMapNode *dbe) { 205 0 : return true; 206 : } 207 : virtual void Process(DBRequest &req); 208 0 : virtual bool ProcessConfig(IFMapNode *node, DBRequest &req, 209 : const boost::uuids::uuid &u) { 210 0 : assert(0); 211 : return false; 212 : } 213 : 214 48 : void set_agent(Agent *agent) { agent_ = agent; } 215 8889 : Agent *agent() const { return agent_; } 216 : 217 : void Flush(); 218 : void reset_flush_walk_ref(); 219 861 : SandeshTraceBufferPtr GetOperDBTraceBuf() const {return OperDBTraceBuf;} 220 : private: 221 : AgentDBEntry *Find(const DBEntry *key); 222 : AgentDBEntry *Find(const DBRequestKey *key); 223 : 224 : DBTableBase::ListenerId ref_listener_id_; 225 : Agent *agent_; 226 : SandeshTraceBufferPtr OperDBTraceBuf; 227 : DBTable::DBTableWalkRef flush_walk_ref_; 228 : DISALLOW_COPY_AND_ASSIGN(AgentDBTable); 229 : }; 230 : 231 : #define OPER_TRACE(obj, ...)\ 232 : do {\ 233 : Oper##obj::TraceMsg(GetOperDBTraceBuf(), __FILE__, __LINE__, __VA_ARGS__);\ 234 : } while (false) 235 : 236 : #define OPER_TRACE_ENTRY(obj, table, ...)\ 237 : do {\ 238 : Oper##obj::TraceMsg(table->GetOperDBTraceBuf(),\ 239 : __FILE__, __LINE__, __VA_ARGS__);\ 240 : } while (false) 241 : 242 : #endif // vnsw_agent_db_hpp