LCOV - code coverage report
Current view: top level - ifmap - ifmap_server_parser.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 126 156 80.8 %
Date: 2026-06-11 01:56:02 Functions: 12 13 92.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <stdint.h>
       6             : #include "ifmap/ifmap_server_parser.h"
       7             : 
       8             : #include <pugixml/pugixml.hpp>
       9             : #include "db/db.h"
      10             : #include "ifmap/ifmap_server_table.h"
      11             : #include "ifmap/ifmap_log.h"
      12             : #include "ifmap/ifmap_log_types.h"
      13             : 
      14             : using namespace std;
      15             : using namespace pugi;
      16             : 
      17             : IFMapServerParser::ModuleMap IFMapServerParser::module_map_;
      18             : 
      19         105 : static const char *NodeName(const xml_node &node) {
      20         105 :     const char *name = node.name();
      21             :     // strip namespace
      22         105 :     const char *dot = strchr(name, ':');
      23         105 :     if (dot != NULL) {
      24          66 :         name = dot + 1;
      25             :     }
      26         105 :     return name;
      27             : }
      28             : 
      29           7 : IFMapServerParser *IFMapServerParser::GetInstance(const string &module) {
      30           7 :     ModuleMap::iterator loc = module_map_.find(module);
      31           7 :     if (loc != module_map_.end()) {
      32           0 :         return loc->second;
      33             :     }
      34           7 :     IFMapServerParser *parser = new IFMapServerParser();
      35           7 :     module_map_.insert(make_pair(module, parser));
      36           7 :     return parser;
      37             : }
      38             : 
      39           6 : void IFMapServerParser::DeleteInstance(const string &module) {
      40           6 :     ModuleMap::iterator loc = module_map_.find(module);
      41           6 :     if (loc == module_map_.end()) {
      42           0 :         return;
      43             :     }
      44             : 
      45           6 :     delete loc->second;
      46           6 :     module_map_.erase(loc);
      47             : }
      48             : 
      49          27 : void IFMapServerParser::MetadataRegister(const string &metadata,
      50             :                                    MetadataParseFn parser) {
      51             :     pair<MetadataParseMap::iterator, bool> result =
      52          27 :             metadata_map_.insert(make_pair(metadata, parser));
      53          27 :     assert(result.second);
      54          27 : }
      55             : 
      56           6 : void IFMapServerParser::MetadataClear(const string &module) {
      57           6 :     metadata_map_.clear();
      58           6 :     DeleteInstance(module);
      59           6 : }
      60             : 
      61          15 : static string ParseIdentifier(const xml_node &node) {
      62          15 :     string id(node.attribute("name").value());
      63          15 :     return id;
      64             : }
      65             : 
      66          17 : void IFMapServerParser::SetOrigin(struct DBRequest *result) const {
      67             :     IFMapServerTable::RequestData *data =
      68          17 :             static_cast<IFMapServerTable::RequestData *>(result->data.get());
      69          17 :     data->origin.set_origin(IFMapOrigin::MAP_SERVER);
      70          17 : }
      71             : 
      72          17 : bool IFMapServerParser::ParseMetadata(const pugi::xml_node &node,
      73             :                                       struct DBRequest *result) const {
      74             :     IFMapServerTable::RequestData *data =
      75          17 :             static_cast<IFMapServerTable::RequestData *>(result->data.get());
      76          17 :     const char *name = NodeName(node);
      77          17 :     MetadataParseMap::const_iterator loc = metadata_map_.find(name);
      78          17 :     if (loc == metadata_map_.end()) {
      79           0 :         return false;
      80             :     }
      81          17 :     std::unique_ptr<AutogenProperty> pvalue;
      82          17 :     bool success = (loc->second)(node, &pvalue);
      83          17 :     if (!success) {
      84           0 :         return false;
      85             :     }
      86          17 :     if (data == NULL) {
      87          11 :         data = new IFMapServerTable::RequestData();
      88          11 :         result->data.reset(data);
      89             :     }
      90          17 :     data->metadata = name;
      91          17 :     data->content.reset(pvalue.release());
      92          17 :     return true;
      93          17 : }
      94             : 
      95             : // Expect the identifier name to be [contrail:]type:name
      96          15 : static void IdentifierNsTypeName(const string &id, string *id_type,
      97             :                                  string *id_name) {
      98          15 :     size_t ns = id.find("contrail:");
      99          15 :     size_t start = (ns == 0) ? sizeof("contrail:") - 1: 0;
     100          15 :     size_t loc = id.find(':', start);
     101          15 :     if (loc != string::npos) {
     102          15 :         *id_type = string(id, start, loc - start);
     103          15 :         *id_name = string(id, loc + 1, id.size() - (loc + 1));
     104             :     } else {
     105           0 :         *id_name = id;
     106             :     }
     107          15 : }
     108             : 
     109           4 : static DBRequest *IFMapServerRequestClone(const DBRequest *src) {
     110           4 :     DBRequest *request = new DBRequest();
     111           4 :     request->oper = src->oper;
     112             :     IFMapTable::RequestKey *src_key =
     113           4 :             static_cast<IFMapTable::RequestKey *>(src->key.get());
     114           4 :     if (src_key != NULL) {
     115             :         IFMapTable::RequestKey *dst_key =
     116           4 :                 new IFMapTable::RequestKey();
     117           4 :         dst_key->id_type = src_key->id_type;
     118           4 :         dst_key->id_name = src_key->id_name;
     119           4 :         request->key.reset(dst_key);
     120             :     }
     121             : 
     122             :     IFMapServerTable::RequestData *src_data =
     123           4 :             static_cast<IFMapServerTable::RequestData *>(src->data.get());
     124           4 :     if (src_data) {
     125             :         IFMapServerTable::RequestData *dst_data =
     126           4 :                 new IFMapServerTable::RequestData();
     127           4 :         dst_data->id_type = src_data->id_type;
     128           4 :         dst_data->id_name = src_data->id_name;
     129           4 :         request->data.reset(dst_data);
     130             :     }
     131           4 :     return request;
     132             : }
     133             : 
     134          13 : bool IFMapServerParser::ParseResultItem(
     135             :     const xml_node &parent, bool add_change, RequestList *list) const {
     136          13 :     unique_ptr<DBRequest> request(new DBRequest);
     137          13 :     request->oper = (add_change ? DBRequest::DB_ENTRY_ADD_CHANGE :
     138             :                      DBRequest::DB_ENTRY_DELETE);
     139          13 :     IFMapTable::RequestKey *key = NULL;
     140          13 :     IFMapServerTable::RequestData *data = NULL;
     141          13 :     int idcount = 0;
     142          13 :     bool has_meta = false;
     143          41 :     for (xml_node node = parent.first_child(); node;
     144          28 :          node = node.next_sibling()) {
     145          28 :         const char *name = NodeName(node);
     146          28 :         if (strcmp(name, "identity") == 0) {
     147          15 :             string id = ParseIdentifier(node);
     148          15 :             switch (idcount) {
     149          13 :             case 0:
     150          13 :                 key = new IFMapTable::RequestKey();
     151          13 :                 request->key.reset(key);
     152          13 :                 IdentifierNsTypeName(id, &key->id_type, &key->id_name);
     153          13 :                 break;
     154           2 :             case 1:
     155           2 :                 data = new IFMapServerTable::RequestData();
     156           2 :                 request->data.reset(data);
     157           2 :                 IdentifierNsTypeName(id, &data->id_type, &data->id_name);
     158           2 :                 break;
     159           0 :             default:
     160           0 :                 return false;
     161             :             }
     162          15 :             idcount++;
     163          15 :             continue;
     164          15 :         }
     165          13 :         if (strcmp(name, "metadata") == 0) {
     166          13 :             if (has_meta) {
     167           0 :                 return false;
     168             :             }
     169          13 :             has_meta = true;
     170          30 :             for (xml_node meta = node.first_child(); meta;
     171          17 :                  meta = meta.next_sibling()) {
     172          17 :                 if (ParseMetadata(meta, request.get())) {
     173          17 :                     SetOrigin(request.get());
     174          17 :                     DBRequest *current = request.release();
     175          17 :                     if (meta.next_sibling()) {
     176           4 :                         request.reset(IFMapServerRequestClone(current));
     177             :                     }
     178          17 :                     list->push_back(current);
     179             :                 }
     180             :             }
     181             :         }
     182             :     }
     183             : 
     184          13 :     if (idcount == 0 || !has_meta) {
     185           0 :         return false;
     186             :     }
     187          13 :     return true;
     188          13 : }
     189             : 
     190           5 : void IFMapServerParser::ParseResults(
     191             :     const xml_document &xdoc, RequestList *list) const {
     192           5 :     xml_node current = xdoc.first_child();
     193          25 :     while (current) {
     194             :         bool add_change;
     195          20 :         if (strcmp(NodeName(current), "updateResult") == 0 ||
     196          35 :             strcmp(NodeName(current), "searchResult") == 0 ||
     197          15 :             strcmp(NodeName(current), "deleteResult") == 0) {
     198             : 
     199           5 :             if (strcmp(NodeName(current), "deleteResult") == 0) {
     200           0 :                 add_change = false;
     201             :             } else {
     202           5 :                 add_change = true;
     203             :             }
     204           5 :             xml_node result = current;
     205          18 :             for (xml_node node = result.first_child(); node;
     206          13 :                 node = node.next_sibling()) {
     207          13 :                 ParseResultItem(node, add_change, list);
     208             :             }
     209           5 :             current = current.next_sibling();
     210             :         } else {
     211          15 :             current = current.first_child();
     212             :         }
     213             :     }
     214           5 : }
     215             : 
     216             : // Called in the context of the ifmap client thread.
     217           0 : bool IFMapServerParser::Receive(DB *db, const char *data, size_t length,
     218             :                                 uint64_t sequence_number) {
     219           0 :     xml_document xdoc;
     220           0 :     pugi::xml_parse_result result = xdoc.load_buffer(data, length);
     221           0 :     if (!result) {
     222           0 :         IFMAP_WARN(IFMapXmlLoadError, "Unable to load XML document", length);
     223           0 :         return false;
     224             :     }
     225             : 
     226           0 :     IFMapServerParser::RequestList requests;
     227           0 :     ParseResults(xdoc, &requests);
     228             : 
     229           0 :     while (!requests.empty()) {
     230           0 :         unique_ptr<DBRequest> req(requests.front());
     231           0 :         requests.pop_front();
     232             : 
     233             :         IFMapTable::RequestKey *key =
     234           0 :                 static_cast<IFMapTable::RequestKey *>(req->key.get());
     235           0 :         key->id_seq_num = sequence_number;
     236             : 
     237           0 :         IFMapTable *table = IFMapTable::FindTable(db, key->id_type);
     238           0 :         if (table != NULL) {
     239           0 :             table->Enqueue(req.get());
     240             :         } else {
     241           0 :             IFMAP_TRACE(IFMapTblNotFoundTrace, "Cant find table", key->id_type);
     242             :         }
     243           0 :     }
     244           0 :     return true;
     245           0 : }

Generated by: LCOV version 1.14