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