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 3349 : AgentOperDBKey() : AgentKey() { } 28 31301 : AgentOperDBKey(DBSubOperation sub_op) : AgentKey(sub_op) { } 29 34650 : virtual ~AgentOperDBKey() { } 30 : }; 31 : 32 : struct AgentOperDBData : public AgentData { 33 : 34 331 : AgentOperDBData(const Agent *agent, IFMapNode *node) : 35 331 : AgentData(), agent_(agent) { 36 331 : SetIFMapNode(node); 37 331 : } 38 331 : virtual ~AgentOperDBData() { 39 331 : SetIFMapNode(NULL); 40 331 : } 41 : 42 : 43 732 : void SetIFMapNode(IFMapNode *node) { 44 : 45 732 : if (node == NULL) { 46 466 : ifmap_node_state_ = NULL; 47 466 : return; 48 : } 49 : 50 266 : assert(agent_); 51 : 52 : // We dont allow changing the node 53 266 : assert(!ifmap_node_state_); 54 : 55 266 : IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager(); 56 266 : ifmap_node_state_ = dep->SetState(node); 57 : } 58 : 59 649 : IFMapNode *ifmap_node() const { 60 649 : if (!ifmap_node_state_) 61 27 : return NULL; 62 622 : IFMapNodeState *state = ifmap_node_state_.get(); 63 622 : return state->node(); 64 : } 65 132 : const Agent *agent() const { 66 132 : 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 3306 : AgentOperDBEntry() : AgentDBEntry() { } 77 3306 : virtual ~AgentOperDBEntry() { } 78 : 79 385 : IFMapNode *ifmap_node() const { 80 385 : if (!ifmap_node_state_) 81 96 : return NULL; 82 289 : IFMapNodeState *state = ifmap_node_state_.get(); 83 289 : return state->node(); 84 : } 85 : 86 94 : void SetIFMapNodeState(IFMapDependencyManager::IFMapNodePtr sref) { 87 94 : ifmap_node_state_ = sref; 88 94 : } 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 478 : virtual void ConfigEventHandler(IFMapNode *node, DBEntry *entry) { 121 478 : DBRequest req; 122 478 : IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager(); 123 478 : boost::uuids::uuid new_uuid = boost::uuids::nil_uuid(); 124 478 : bool uuid_set = IFNodeToUuid(node, new_uuid); 125 478 : IFMapNodeState *state = dep->IFMapNodeGet(node); 126 478 : boost::uuids::uuid old_uuid = state->uuid(); 127 : 128 478 : if (!node->IsDeleted()) { 129 409 : if (entry) { 130 216 : 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 409 : if (uuid_set && dep->IsNodeIdentifiedByUuid(node)) { 141 346 : assert(new_uuid != boost::uuids::nil_uuid()); 142 : } 143 409 : state->set_uuid(new_uuid); 144 409 : state->set_oper_db_request_enqueued(true); 145 409 : req.oper = DBRequest::DB_ENTRY_ADD_CHANGE; 146 : } else { 147 69 : req.oper = DBRequest::DB_ENTRY_DELETE; 148 69 : 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 69 : new_uuid = old_uuid; 154 69 : if (state) { 155 69 : state->set_oper_db_request_enqueued(false); 156 : } 157 : } 158 : 159 478 : if (IFNodeToReq(node, req, new_uuid) == true) { 160 19 : Enqueue(&req); 161 : } 162 : 163 478 : return; 164 478 : } 165 : 166 : protected: 167 : // Handle change in IFMapNode for a DBEntry 168 306 : void UpdateIfMapNode(AgentOperDBEntry *entry, IFMapNode *node) { 169 306 : if (entry == NULL) 170 0 : return; 171 : 172 306 : IFMapNode *old_node = entry->ifmap_node(); 173 : 174 306 : if (old_node == node) 175 212 : return; 176 : 177 94 : IFMapDependencyManager *dep = agent()->oper_db()->dependency_manager(); 178 94 : if (old_node) { 179 47 : dep->SetObject(old_node, NULL); 180 47 : entry->SetIFMapNodeState(NULL); 181 : } 182 : 183 94 : if (node) { 184 47 : entry->SetIFMapNodeState(dep->SetState(node)); 185 47 : dep->SetObject(node, entry); 186 : } 187 : } 188 : 189 : // Implement Add, Delete, OnChange to provide common agent functionality 190 : // including, 191 58 : virtual DBEntry *Add(const DBRequest *req) { 192 : AgentOperDBEntry *entry = static_cast<AgentOperDBEntry *> 193 58 : (OperDBAdd(req)); 194 58 : AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get()); 195 58 : if (data && data->ifmap_node()) 196 35 : UpdateIfMapNode(entry, data->ifmap_node()); 197 58 : return entry; 198 : } 199 : 200 158 : virtual bool OnChange(DBEntry *entry, const DBRequest *req) { 201 158 : AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry); 202 158 : bool ret = OperDBOnChange(entry, req); 203 : 204 158 : AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get()); 205 158 : if (data && data->ifmap_node()) 206 155 : UpdateIfMapNode(oper_entry, data->ifmap_node()); 207 158 : return ret; 208 : } 209 : 210 39 : virtual bool Resync(DBEntry *entry, const DBRequest *req) { 211 39 : AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry); 212 39 : bool ret = OperDBResync(entry, req); 213 : 214 39 : AgentOperDBData *data = static_cast<AgentOperDBData *>(req->data.get()); 215 39 : if (data && data->ifmap_node()) 216 38 : UpdateIfMapNode(oper_entry, data->ifmap_node()); 217 39 : return ret; 218 : } 219 : 220 78 : virtual bool Delete(DBEntry *entry, const DBRequest *req) { 221 78 : AgentOperDBEntry *oper_entry = static_cast<AgentOperDBEntry *>(entry); 222 78 : bool ret = OperDBDelete(entry, req); 223 : 224 78 : UpdateIfMapNode(oper_entry, NULL); 225 78 : 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 100 : 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 39 : void ConfigEventHandler(IFMapNode *node, DBEntry *entry) { 251 39 : if (node->IsDeleted()) { 252 18 : ConfigDelete(node); 253 18 : tree_.erase(node); 254 18 : return; 255 : } 256 : 257 21 : ConfigManagerEnqueue(node); 258 21 : return; 259 : } 260 : 261 : // Callback from config-manager 262 13 : void ProcessConfig(IFMapNode *node) { 263 13 : if (node->IsDeleted()) { 264 0 : return; 265 : } 266 : 267 13 : IFMapDependencyManager *dep = agent_->oper_db()->dependency_manager(); 268 13 : tree_.insert(std::make_pair(node, dep->SetState(node))); 269 13 : 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_