Line data Source code
1 : /* 2 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #ifndef SRC_VNSW_AGENT_OPER_OPER_DB_H_ 6 : #define SRC_VNSW_AGENT_OPER_OPER_DB_H_ 7 : 8 : ///////////////////////////////////////////////////////////////////////////// 9 : // This file defines set of common agent oper-db class with following 10 : // - Support IFMap dependency tracking. 11 : // - The IFMapNode for a request is passed in the AgentOperDBData object 12 : // - AgentOperDBTable::Add allocates a AgentOperDBEntry and sets the 13 : // AgentOperDBEntry allocated as "state" for IFMapNode passed 14 : // - AgentOperDBTable::OnChange and AgentOperDBTable::Resync will check 15 : // if there is change in IFMapNode for the AgentOperDBEntry. If so, 16 : // it will release state from the previous IFMapNode and set state to 17 : // the new IFMapNode 18 : // - AgentOperDBTable::Delete will release the state added for IFMapNode 19 : ///////////////////////////////////////////////////////////////////////////// 20 : #include <cmn/agent_cmn.h> 21 : #include <cmn/agent_db.h> 22 : #include <operdb_init.h> 23 : #include <ifmap_dependency_manager.h> 24 : #include <ifmap/ifmap_node.h> 25 : 26 : struct AgentOperDBKey : public AgentKey { 27 7665 : AgentOperDBKey() : AgentKey() { } 28 31925 : AgentOperDBKey(DBSubOperation sub_op) : AgentKey(sub_op) { } 29 39590 : virtual ~AgentOperDBKey() { } 30 : }; 31 : 32 : struct AgentOperDBData : public AgentData { 33 : 34 677 : AgentOperDBData(const Agent *agent, IFMapNode *node) : 35 677 : AgentData(), agent_(agent) { 36 677 : SetIFMapNode(node); 37 677 : } 38 677 : virtual ~AgentOperDBData() { 39 677 : SetIFMapNode(NULL); 40 677 : } 41 : 42 : 43 1466 : void SetIFMapNode(IFMapNode *node) { 44 : 45 1466 : if (node == NULL) { 46 922 : ifmap_node_state_ = NULL; 47 922 : return; 48 : } 49 : 50 544 : assert(agent_); 51 : 52 : // We dont allow changing the node 53 544 : assert(!ifmap_node_state_); 54 : 55 544 : IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager(); 56 544 : ifmap_node_state_ = dep->SetState(node); 57 : } 58 : 59 1403 : IFMapNode *ifmap_node() const { 60 1403 : if (!ifmap_node_state_) 61 51 : return NULL; 62 1352 : IFMapNodeState *state = ifmap_node_state_.get(); 63 1352 : return state->node(); 64 : } 65 160 : const Agent *agent() const { 66 160 : return agent_; 67 : } 68 : private: 69 : const Agent *agent_; 70 : // IFMap Node pointer for the object 71 : IFMapDependencyManager::IFMapNodePtr ifmap_node_state_; 72 : }; 73 : 74 : class AgentOperDBEntry : public AgentDBEntry { 75 : public: 76 6471 : AgentOperDBEntry() : AgentDBEntry() { } 77 6471 : virtual ~AgentOperDBEntry() { } 78 : 79 853 : IFMapNode *ifmap_node() const { 80 853 : if (!ifmap_node_state_) 81 205 : return NULL; 82 648 : IFMapNodeState *state = ifmap_node_state_.get(); 83 648 : return state->node(); 84 : } 85 : 86 206 : void SetIFMapNodeState(IFMapDependencyManager::IFMapNodePtr sref) { 87 206 : ifmap_node_state_ = sref; 88 206 : } 89 : private: 90 : friend class AgentOperDBTable; 91 : IFMapDependencyManager::IFMapNodePtr ifmap_node_state_; 92 : DISALLOW_COPY_AND_ASSIGN(AgentOperDBEntry); 93 : }; 94 : 95 : class AgentOperDBTable : public AgentDBTable { 96 : public: 97 32 : AgentOperDBTable(DB *db, const std::string &name) : 98 32 : AgentDBTable(db, name) { 99 32 : } 100 : 101 : AgentOperDBTable(DB *db, const std::string &name, 102 : bool del_on_zero_refcount) : 103 : AgentDBTable(db, name, del_on_zero_refcount) { 104 : } 105 32 : virtual ~AgentOperDBTable() { } 106 : 107 : // AgentOperDBTable implements Add/OnChange/Delete/Resync APIs for 108 : // AgentDBTable. They will in-turn invoke 109 : // OperDBAdd/OperDBOnChange/OperDBDelete/OperDBResync correspondingly 110 : virtual DBEntry *OperDBAdd(const DBRequest *req) = 0; 111 : virtual bool OperDBOnChange(DBEntry *entry, const DBRequest *req) = 0; 112 : virtual bool OperDBDelete(DBEntry *entry, const DBRequest *req) = 0; 113 0 : virtual bool OperDBResync(DBEntry *entry, const DBRequest *req) { 114 0 : return false; 115 : } 116 : 117 : // Default callback handler from IFMap Dependency tracker. We invoke 118 : // IFNodeToReq to keep all IFMap handling at one place 119 : 120 979 : virtual void ConfigEventHandler(IFMapNode *node, DBEntry *entry) { 121 979 : DBRequest req; 122 979 : IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager(); 123 979 : boost::uuids::uuid new_uuid = boost::uuids::nil_uuid(); 124 979 : bool uuid_set = IFNodeToUuid(node, new_uuid); 125 979 : IFMapNodeState *state = dep->IFMapNodeGet(node); 126 979 : boost::uuids::uuid old_uuid = state->uuid(); 127 : 128 979 : if (!node->IsDeleted()) { 129 827 : if (entry) { 130 548 : if ((old_uuid != new_uuid)) { 131 0 : if (old_uuid != boost::uuids::nil_uuid()) { 132 0 : req.oper = DBRequest::DB_ENTRY_DELETE; 133 0 : if (IFNodeToReq(node, req, old_uuid) == true) { 134 0 : assert(req.oper == DBRequest::DB_ENTRY_DELETE); 135 0 : Enqueue(&req); 136 : } 137 : } 138 : } 139 : } 140 827 : if (uuid_set && dep->IsNodeIdentifiedByUuid(node)) { 141 666 : assert(new_uuid != boost::uuids::nil_uuid()); 142 : } 143 827 : state->set_uuid(new_uuid); 144 827 : state->set_oper_db_request_enqueued(true); 145 827 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; 146 : } else { 147 152 : req.oper = DBRequest::DB_ENTRY_DELETE; 148 152 : if (uuid_set && (old_uuid == boost::uuids::nil_uuid()) && 149 0 : (dep->IsNodeIdentifiedByUuid(node))) { 150 : //Node was never added so no point sending delete 151 0 : return; 152 : } 153 152 : new_uuid = old_uuid; 154 152 : if (state) { 155 152 : state->set_oper_db_request_enqueued(false); 156 : } 157 : } 158 : 159 979 : if (IFNodeToReq(node, req, new_uuid) == true) { 160 33 : Enqueue(&req); 161 : } 162 : 163 979 : return; 164 979 : } 165 : 166 : protected: 167 : // Handle change in IFMapNode for a DBEntry 168 638 : void UpdateIfMapNode(AgentOperDBEntry *entry, IFMapNode *node) { 169 638 : if (entry == NULL) 170 0 : return; 171 : 172 638 : IFMapNode *old_node = entry->ifmap_node(); 173 : 174 638 : if (old_node == node) 175 432 : return; 176 : 177 206 : IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager(); 178 206 : if (old_node) { 179 103 : dep->SetObject(old_node, NULL); 180 103 : entry->SetIFMapNodeState(NULL); 181 : } 182 : 183 206 : if (node) { 184 103 : entry->SetIFMapNodeState(dep->SetState(node)); 185 103 : dep->SetObject(node, entry); 186 : } 187 : } 188 : 189 : // Implement Add, Delete, OnChange to provide common agent functionality 190 : // including, 191 113 : virtual DBEntry *Add(const DBRequest *req) { 192 : AgentOperDBEntry *entry = static_cast<AgentOperDBEntry *> 193 113 : (OperDBAdd(req)); 194 113 : AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get()); 195 113 : if (data && data->ifmap_node()) 196 64 : UpdateIfMapNode(entry, data->ifmap_node()); 197 113 : return entry; 198 : } 199 : 200 336 : virtual bool OnChange(DBEntry *entry, const DBRequest *req) { 201 336 : AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry); 202 336 : bool ret = OperDBOnChange(entry, req); 203 : 204 336 : AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get()); 205 336 : if (data && data->ifmap_node()) 206 334 : UpdateIfMapNode(oper_entry, data->ifmap_node()); 207 336 : return ret; 208 : } 209 : 210 80 : virtual bool Resync(DBEntry *entry, const DBRequest *req) { 211 80 : AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry); 212 80 : bool ret = OperDBResync(entry, req); 213 : 214 80 : AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get()); 215 80 : if (data && data->ifmap_node()) 216 80 : UpdateIfMapNode(oper_entry, data->ifmap_node()); 217 80 : return ret; 218 : } 219 : 220 160 : virtual bool Delete(DBEntry *entry, const DBRequest *req) { 221 160 : AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry); 222 160 : bool ret = OperDBDelete(entry, req); 223 : 224 160 : UpdateIfMapNode(oper_entry, NULL); 225 160 : return ret; 226 : } 227 : 228 : private: 229 : DISALLOW_COPY_AND_ASSIGN(AgentOperDBTable); 230 : }; 231 : 232 : // Oper-DB works on few IFMap tables which do not have corresponding 233 : // oper DBTable. 234 : // Example : virtual-router, network-ipam etc... 235 : // The IFMap nodes are registered with ifmap-dependency-manager. The class 236 : // OperIFMapTable is responsible to manage notifications of such IFMap tables 237 : class OperIFMapTable { 238 : public: 239 : typedef std::map<IFMapNode *, IFMapDependencyManager::IFMapNodePtr> Tree; 240 14 : OperIFMapTable(Agent *agent) : agent_(agent), oper_(agent->oper_db()) { } 241 14 : virtual ~OperIFMapTable() { 242 14 : assert(tree_.size() == 0); 243 14 : } 244 : 245 389 : Agent *agent() const { return agent_; } 246 : OperDB *oper() const { return oper_; } 247 : uint32_t Size() const { return tree_.size(); } 248 : 249 : // Callback from ifmap-dependnecy-manager 250 165 : void ConfigEventHandler(IFMapNode *node, DBEntry *entry) { 251 165 : if (node->IsDeleted()) { 252 67 : ConfigDelete(node); 253 67 : tree_.erase(node); 254 67 : return; 255 : } 256 : 257 98 : ConfigManagerEnqueue(node); 258 98 : return; 259 : } 260 : 261 : // Callback from config-manager 262 62 : void ProcessConfig(IFMapNode *node) { 263 62 : if (node->IsDeleted()) { 264 0 : return; 265 : } 266 : 267 62 : IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager(); 268 62 : tree_.insert(std::make_pair(node, dep->SetState(node))); 269 62 : ConfigAddChange(node); 270 : } 271 : 272 : virtual void ConfigDelete(IFMapNode *node) = 0; 273 : virtual void ConfigAddChange(IFMapNode *node) = 0; 274 : virtual void ConfigManagerEnqueue(IFMapNode *node) = 0; 275 : private: 276 : Agent *agent_; 277 : OperDB *oper_; 278 : Tree tree_; 279 : DISALLOW_COPY_AND_ASSIGN(OperIFMapTable); 280 : }; 281 : #endif // SRC_VNSW_AGENT_OPER_OPER_DB_H_