Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "ifmap/ifmap_agent_parser.h" 6 : 7 : #include <vector> 8 : #include <pugixml/pugixml.hpp> 9 : #include "base/logging.h" 10 : #include "db/db_entry.h" 11 : #include "ifmap/ifmap_agent_table.h" 12 : 13 : using namespace std; 14 : using namespace pugi; 15 : 16 149 : void IFMapAgentParser::NodeRegister(const string &node, NodeParseFn parser) { 17 : pair<NodeParseMap::iterator, bool> result = 18 149 : node_map_.insert(make_pair(node, parser)); 19 149 : assert(result.second); 20 149 : } 21 : 22 0 : void IFMapAgentParser::NodeClear() { 23 0 : node_map_.clear(); 24 0 : } 25 : 26 161 : void IFMapAgentParser::NodeParse(xml_node &node, DBRequest::DBOperation oper, uint64_t seq) { 27 : 28 161 : const char *name = node.attribute("type").value(); 29 : int msg_type; 30 161 : if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) 31 89 : msg_type = UPDATE; 32 : else 33 72 : msg_type = DEL; 34 : 35 : IFMapTable *table; 36 161 : table = IFMapTable::FindTable(db_, name); 37 161 : if(!table) { 38 0 : node_parse_errors_[msg_type]++; 39 0 : return; 40 : } 41 : 42 : // Locate the decode function using id_name 43 161 : NodeParseMap::const_iterator loc = node_map_.find(name); 44 161 : if (loc == node_map_.end()) { 45 0 : node_parse_errors_[msg_type]++; 46 0 : return; 47 : } 48 : 49 : IFMapObject *obj; 50 161 : IFMapTable::RequestKey *req_key = new IFMapTable::RequestKey; 51 : 52 : // Invoke the decode routine 53 161 : req_key->id_type = name; 54 161 : req_key->id_seq_num = seq; 55 161 : obj = loc->second(node, db_, &req_key->id_name); 56 161 : if (!obj) { 57 0 : node_parse_errors_[msg_type]++; 58 0 : delete req_key; 59 0 : return; 60 : } 61 : 62 161 : IFMapAgentTable::IFMapAgentData *req_data = new IFMapAgentTable::IFMapAgentData; 63 161 : req_data->content.reset(obj); 64 : 65 161 : unique_ptr<DBRequest> request(new DBRequest); 66 161 : request->oper = oper; 67 161 : request->data.reset(req_data); 68 161 : request->key.reset(req_key); 69 161 : table->Enqueue(request.get()); 70 161 : } 71 : 72 182 : void IFMapAgentParser::LinkParse(xml_node &link, DBRequest::DBOperation oper, uint64_t seq) { 73 : 74 182 : xml_node first_node; 75 182 : xml_node second_node; 76 182 : xml_node name_node1; 77 182 : xml_node name_node2; 78 : const char *name1; 79 : const char *name2; 80 : IFMapTable *table; 81 : IFMapAgentLinkTable *link_table; 82 : 83 : int msg_type; 84 182 : if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) 85 93 : msg_type = UPDATE; 86 : else 87 89 : msg_type = DEL; 88 : 89 : link_table = static_cast<IFMapAgentLinkTable *>( 90 182 : db_->FindTable(IFMAP_AGENT_LINK_DB_NAME)); 91 : 92 182 : assert(link_table); 93 : 94 : // Get both first and second node and its corresponding tables 95 182 : first_node = link.first_child(); 96 182 : if (!first_node) { 97 0 : link_parse_errors_[msg_type]++; 98 0 : return; 99 : } 100 : 101 182 : second_node = first_node.next_sibling(); 102 182 : if (!second_node) { 103 0 : link_parse_errors_[msg_type]++; 104 0 : return; 105 : } 106 : 107 182 : name1 = first_node.attribute("type").value(); 108 182 : table = IFMapTable::FindTable(db_, name1); 109 182 : if(!table) { 110 0 : link_parse_errors_[msg_type]++; 111 0 : return; 112 : } 113 : 114 182 : name2 = second_node.attribute("type").value(); 115 182 : table = IFMapTable::FindTable(db_, name2); 116 182 : if(!table) { 117 0 : link_parse_errors_[msg_type]++; 118 0 : return; 119 : } 120 : 121 : // Get id_name of both the nodes 122 182 : name_node1 = first_node.first_child(); 123 182 : if (!name_node1) { 124 0 : link_parse_errors_[msg_type]++; 125 0 : return; 126 : } 127 : 128 182 : if (strcmp(name_node1.name(), "name") != 0) { 129 0 : link_parse_errors_[msg_type]++; 130 0 : return; 131 : } 132 : 133 182 : name_node2 = second_node.first_child(); 134 182 : if (!name_node2) { 135 0 : link_parse_errors_[msg_type]++; 136 0 : return; 137 : } 138 : 139 182 : if (strcmp(name_node2.name(), "name") != 0) { 140 0 : link_parse_errors_[msg_type]++; 141 0 : return; 142 : } 143 : 144 : // Create both the request keys 145 182 : unique_ptr <IFMapAgentLinkTable::RequestKey> req_key (new IFMapAgentLinkTable::RequestKey); 146 182 : req_key->left_key.id_name = name_node1.child_value(); 147 182 : req_key->left_key.id_type = name1; 148 182 : req_key->left_key.id_seq_num = seq; 149 : 150 182 : req_key->right_key.id_name = name_node2.child_value(); 151 182 : req_key->right_key.id_type = name2; 152 182 : req_key->right_key.id_seq_num = seq; 153 : 154 182 : xml_node metadata = link.child("metadata"); 155 182 : if (metadata) { 156 182 : req_key->metadata = metadata.attribute("type").value(); 157 : } 158 : 159 182 : unique_ptr <DBRequest> req (new DBRequest); 160 182 : req->oper = oper; 161 182 : req->key = std::move(req_key); 162 : 163 182 : link_table->Enqueue(req.get()); 164 182 : } 165 : 166 156 : void IFMapAgentParser::ConfigParse(const xml_node config, const uint64_t seq) { 167 : 168 : DBRequest::DBOperation oper; 169 : 170 312 : for (xml_node node = config.first_child(); node; 171 156 : node = node.next_sibling()) { 172 : 173 : int msg_type; 174 156 : if (strcmp(node.name(), "update") == 0) { 175 85 : oper = DBRequest::DB_ENTRY_ADD_CHANGE; 176 85 : msg_type = UPDATE; 177 71 : } else if (strcmp(node.name(), "delete") == 0) { 178 71 : oper = DBRequest::DB_ENTRY_DELETE; 179 71 : msg_type = DEL; 180 : } else { 181 0 : continue; 182 : } 183 : 184 499 : for(xml_node chld = node.first_child(); chld; chld = chld.next_sibling()) { 185 : 186 : // Handle the links between the nodes 187 343 : if (strcmp(chld.name(), "link") == 0) { 188 182 : links_processed_[msg_type]++; 189 182 : LinkParse(chld, oper, seq); 190 182 : continue; 191 : } 192 : 193 161 : if (strcmp(chld.name(), "node") == 0) { 194 161 : nodes_processed_[msg_type]++; 195 161 : NodeParse(chld, oper, seq); 196 : } 197 : } 198 : } 199 156 : }