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