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