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