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 167 : void IFMapAgentParser::NodeParse(xml_node &node, DBRequest::DBOperation oper, uint64_t seq) { 27 : 28 167 : const char *name = node.attribute("type").value(); 29 : int msg_type; 30 167 : if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) 31 92 : msg_type = UPDATE; 32 : else 33 75 : msg_type = DEL; 34 : 35 : IFMapTable *table; 36 167 : table = IFMapTable::FindTable(db_, name); 37 167 : if(!table) { 38 0 : node_parse_errors_[msg_type]++; 39 0 : return; 40 : } 41 : 42 : // Locate the decode function using id_name 43 167 : NodeParseMap::const_iterator loc = node_map_.find(name); 44 167 : if (loc == node_map_.end()) { 45 0 : node_parse_errors_[msg_type]++; 46 0 : return; 47 : } 48 : 49 : IFMapObject *obj; 50 167 : IFMapTable::RequestKey *req_key = new IFMapTable::RequestKey; 51 : 52 : // Invoke the decode routine 53 167 : req_key->id_type = name; 54 167 : req_key->id_seq_num = seq; 55 167 : obj = loc->second(node, db_, &req_key->id_name); 56 167 : if (!obj) { 57 0 : node_parse_errors_[msg_type]++; 58 0 : delete req_key; 59 0 : return; 60 : } 61 : 62 167 : IFMapAgentTable::IFMapAgentData *req_data = new IFMapAgentTable::IFMapAgentData; 63 167 : req_data->content.reset(obj); 64 : 65 167 : unique_ptr<DBRequest> request(new DBRequest); 66 167 : request->oper = oper; 67 167 : request->data.reset(req_data); 68 167 : request->key.reset(req_key); 69 167 : table->Enqueue(request.get()); 70 167 : } 71 : 72 187 : void IFMapAgentParser::LinkParse(xml_node &link, DBRequest::DBOperation oper, uint64_t seq) { 73 : 74 187 : xml_node first_node; 75 187 : xml_node second_node; 76 187 : xml_node name_node1; 77 187 : 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 187 : if (oper == DBRequest::DB_ENTRY_ADD_CHANGE) 85 96 : msg_type = UPDATE; 86 : else 87 91 : msg_type = DEL; 88 : 89 : link_table = static_cast<IFMapAgentLinkTable *>( 90 187 : db_->FindTable(IFMAP_AGENT_LINK_DB_NAME)); 91 : 92 187 : assert(link_table); 93 : 94 : // Get both first and second node and its corresponding tables 95 187 : first_node = link.first_child(); 96 187 : if (!first_node) { 97 0 : link_parse_errors_[msg_type]++; 98 0 : return; 99 : } 100 : 101 187 : second_node = first_node.next_sibling(); 102 187 : if (!second_node) { 103 0 : link_parse_errors_[msg_type]++; 104 0 : return; 105 : } 106 : 107 187 : name1 = first_node.attribute("type").value(); 108 187 : table = IFMapTable::FindTable(db_, name1); 109 187 : if(!table) { 110 0 : link_parse_errors_[msg_type]++; 111 0 : return; 112 : } 113 : 114 187 : name2 = second_node.attribute("type").value(); 115 187 : table = IFMapTable::FindTable(db_, name2); 116 187 : if(!table) { 117 0 : link_parse_errors_[msg_type]++; 118 0 : return; 119 : } 120 : 121 : // Get id_name of both the nodes 122 187 : name_node1 = first_node.first_child(); 123 187 : if (!name_node1) { 124 0 : link_parse_errors_[msg_type]++; 125 0 : return; 126 : } 127 : 128 187 : if (strcmp(name_node1.name(), "name") != 0) { 129 0 : link_parse_errors_[msg_type]++; 130 0 : return; 131 : } 132 : 133 187 : name_node2 = second_node.first_child(); 134 187 : if (!name_node2) { 135 0 : link_parse_errors_[msg_type]++; 136 0 : return; 137 : } 138 : 139 187 : 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 187 : unique_ptr <IFMapAgentLinkTable::RequestKey> req_key (new IFMapAgentLinkTable::RequestKey); 146 187 : req_key->left_key.id_name = name_node1.child_value(); 147 187 : req_key->left_key.id_type = name1; 148 187 : req_key->left_key.id_seq_num = seq; 149 : 150 187 : req_key->right_key.id_name = name_node2.child_value(); 151 187 : req_key->right_key.id_type = name2; 152 187 : req_key->right_key.id_seq_num = seq; 153 : 154 187 : xml_node metadata = link.child("metadata"); 155 187 : if (metadata) { 156 187 : req_key->metadata = metadata.attribute("type").value(); 157 : } 158 : 159 187 : unique_ptr <DBRequest> req (new DBRequest); 160 187 : req->oper = oper; 161 187 : req->key = std::move(req_key); 162 : 163 187 : link_table->Enqueue(req.get()); 164 187 : } 165 : 166 165 : void IFMapAgentParser::ConfigParse(const xml_node config, const uint64_t seq) { 167 : 168 : DBRequest::DBOperation oper; 169 : 170 330 : for (xml_node node = config.first_child(); node; 171 165 : node = node.next_sibling()) { 172 : 173 : int msg_type; 174 165 : if (strcmp(node.name(), "update") == 0) { 175 90 : oper = DBRequest::DB_ENTRY_ADD_CHANGE; 176 90 : msg_type = UPDATE; 177 75 : } else if (strcmp(node.name(), "delete") == 0) { 178 75 : oper = DBRequest::DB_ENTRY_DELETE; 179 75 : msg_type = DEL; 180 : } else { 181 0 : continue; 182 : } 183 : 184 519 : for(xml_node chld = node.first_child(); chld; chld = chld.next_sibling()) { 185 : 186 : // Handle the links between the nodes 187 354 : if (strcmp(chld.name(), "link") == 0) { 188 187 : links_processed_[msg_type]++; 189 187 : LinkParse(chld, oper, seq); 190 187 : continue; 191 : } 192 : 193 167 : if (strcmp(chld.name(), "node") == 0) { 194 167 : nodes_processed_[msg_type]++; 195 167 : NodeParse(chld, oper, seq); 196 : } 197 : } 198 : } 199 165 : }