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