LCOV - code coverage report
Current view: top level - root/contrail/src/contrail-common/config-client-mgr - config_cass2json_adapter.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 127 147 86.4 %
Date: 2026-08-03 02:19:58 Functions: 3 5 60.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include "config_cass2json_adapter.h"
       6             : 
       7             : #include <assert.h>
       8             : #include <boost/algorithm/string/predicate.hpp>
       9             : #include <boost/assign/list_of.hpp>
      10             : #include <string>
      11             : #include <iostream>
      12             : 
      13             : #include "base/string_util.h"
      14             : #include "config_cassandra_client.h"
      15             : #include "config_client_log.h"
      16             : #include "config_client_log_types.h"
      17             : #include "rapidjson/stringbuffer.h"
      18             : #include "rapidjson/writer.h"
      19             : 
      20             : using boost::assign::list_of;
      21             : using contrail_rapidjson::Document;
      22             : using contrail_rapidjson::StringBuffer;
      23             : using contrail_rapidjson::Value;
      24             : using contrail_rapidjson::Writer;
      25             : using std::cout;
      26             : using std::endl;
      27             : using std::set;
      28             : using std::string;
      29             : 
      30             : const string ConfigCass2JsonAdapter::fq_name_prefix = "fq_name";
      31             : const string ConfigCass2JsonAdapter::prop_prefix = "prop:";
      32             : const string ConfigCass2JsonAdapter::list_prop_prefix = "propl:";
      33             : const string ConfigCass2JsonAdapter::map_prop_prefix = "propm:";
      34             : const string ConfigCass2JsonAdapter::ref_prefix = "ref:";
      35             : const string ConfigCass2JsonAdapter::parent_prefix = "parent:";
      36             : const string ConfigCass2JsonAdapter::parent_type_prefix = "parent_type";
      37             : 
      38             : const set<string> ConfigCass2JsonAdapter::allowed_properties =
      39             :              list_of(prop_prefix)(map_prop_prefix)
      40             :                     (list_prop_prefix)(ref_prefix)(parent_prefix);
      41             : 
      42             : bool ConfigCass2JsonAdapter::assert_on_parse_error_ =
      43             :     getenv("CONTRAIL_CONFIG_ASSERT_ON_PARSE_ERROR") != NULL;
      44             : 
      45             : #define CONFIG_PARSE_ASSERT(t, condition)                                      \
      46             :     do {                                                                       \
      47             :         if (condition)                                                         \
      48             :             break;                                                             \
      49             :         CONFIG_CLIENT_WARN_LOG(ConfigurationMalformed ## t ## Warning ## Log,  \
      50             :             Category::CONFIG_CLIENT, c.key, c.value, type_, uuid_);            \
      51             :         CONFIG_CLIENT_TRACE(ConfigurationMalformed ## t ## Warning ## Trace,   \
      52             :             c.key, c.value, type_, uuid_);                                     \
      53             :         cout << "CONFIG_PARSE_ERROR " << __FILE__ << ":" << __LINE__ << " ";   \
      54             :         cout << type_ << " " << c.key << " " << c.value << " ";                \
      55             :         cout << uuid_ << endl;                                                 \
      56             :         if (assert_on_parse_error_)                                            \
      57             :             assert(false);                                                     \
      58             :         return;                                                                \
      59             :     } while (false)
      60             : 
      61        2717 : ConfigCass2JsonAdapter::ConfigCass2JsonAdapter(const string &uuid,
      62             :        ConfigCassandraClient *cassandra_client, const string &obj_type,
      63        2717 :        const CassColumnKVVec &cdvec) : cassandra_client_(cassandra_client),
      64        2717 :        uuid_(uuid) {
      65        2717 :     CreateJsonString(obj_type, cdvec);
      66        2717 : }
      67             : 
      68           0 : ConfigCass2JsonAdapter::ConfigCass2JsonAdapter(const string &uuid,
      69           0 :        const string &type, const Document &doc) : uuid_(uuid) {
      70             :     /**
      71             :       * Construct the final Json Document.
      72             :       */
      73           0 :     Document::AllocatorType &a = json_document_.GetAllocator();
      74           0 :     Value v;
      75           0 :     v.CopyFrom(doc, a);
      76             : 
      77           0 :     Value vk;
      78           0 :     json_document_.SetObject().AddMember(vk.SetString(type.c_str(), a),
      79             :                                          v, a);
      80           0 : }
      81             : 
      82           0 : string ConfigCass2JsonAdapter::GetJsonString(const Value &attr_value) {
      83           0 :     StringBuffer buffer;
      84           0 :     Writer<StringBuffer> writer(buffer);
      85           0 :     attr_value.Accept(writer);
      86           0 :     return buffer.GetString();
      87           0 : }
      88             : 
      89       15871 : void ConfigCass2JsonAdapter::AddOneEntry(Value *jsonObject,
      90             :     const string &obj_type, const JsonAdapterDataType &c,
      91             :     Document::AllocatorType &a) {
      92             : 
      93             :     // Process scalar property values.
      94       15871 :     if (boost::starts_with(c.key, prop_prefix)) {
      95        4952 :         string c_value = c.value;
      96        4951 :         if (c.key == "prop:bgpaas_session_attributes")
      97           0 :             c_value = "\"\"";
      98        4951 :         Document prop_document(&a);
      99        4951 :         prop_document.Parse<0>(c_value.c_str());
     100        4952 :         CONFIG_PARSE_ASSERT(Property, !prop_document.HasParseError());
     101        4952 :         Value vk;
     102        4952 :         jsonObject->AddMember(
     103        9904 :             vk.SetString(c.key.substr(prop_prefix.size()).c_str(), a),
     104             :                          prop_document, a);
     105        4952 :         return;
     106        4952 :     }
     107             : 
     108             :     // Process property list and  property map values.
     109       10921 :     bool is_map = false;
     110       21573 :     if ((is_map = boost::starts_with(c.key, map_prop_prefix)) ||
     111       10649 :             boost::starts_with(c.key, list_prop_prefix)) {
     112         528 :         size_t from_front_pos = c.key.find(':');
     113         528 :         size_t from_back_pos = c.key.rfind(':');
     114             :         string prop_map = c.key.substr(from_front_pos + 1,
     115         528 :                                        from_back_pos - from_front_pos - 1);
     116         528 :         string wrapper = cassandra_client_->mgr()-> \
     117         528 :                  config_json_parser()->GetWrapperFieldName(type_,
     118         528 :                                                        prop_map);
     119         528 :         if (wrapper.empty()) {
     120           0 :             return;
     121             :         }
     122         528 :         if (!jsonObject->HasMember(prop_map.c_str())) {
     123         280 :             Value v;
     124         280 :             Value vk;
     125         280 :             jsonObject->AddMember(
     126             :                 vk.SetString(prop_map.c_str(), a), v.SetObject(), a);
     127         280 :             Value va;
     128         280 :             Value vak;
     129         280 :             (*jsonObject)[prop_map.c_str()].AddMember(
     130             :                 vak.SetString(wrapper.c_str(), a), va.SetArray(), a);
     131         280 :         }
     132             : 
     133         528 :         Document map_document(&a);
     134         528 :         map_document.Parse<0>(c.value.c_str());
     135         528 :         if (is_map)
     136         268 :             CONFIG_PARSE_ASSERT(PropertyMap, !map_document.HasParseError());
     137             :         else
     138         260 :             CONFIG_PARSE_ASSERT(PropertyList, !map_document.HasParseError());
     139             : 
     140         528 :         (*jsonObject)[prop_map.c_str()][wrapper.c_str()].PushBack(
     141             :             map_document, a);
     142         528 :         return;
     143         528 :     }
     144             : 
     145       10392 :     if (boost::starts_with(c.key, ref_prefix)) {
     146        1205 :         size_t from_front_pos = c.key.find(':');
     147        1205 :         size_t from_back_pos = c.key.rfind(':');
     148        1205 :         CONFIG_PARSE_ASSERT(Reference, from_front_pos != string::npos);
     149        1205 :         CONFIG_PARSE_ASSERT(Reference, from_back_pos != string::npos);
     150             :         string ref_type = c.key.substr(from_front_pos + 1,
     151        1205 :                                        from_back_pos-from_front_pos - 1);
     152        1205 :         string ref_uuid = c.key.substr(from_back_pos + 1);
     153        1205 :         string fq_name_ref = c.ref_fq_name;
     154        1205 :         string r = ref_type + "_refs";
     155        1205 :         if (!jsonObject->HasMember(r.c_str())) {
     156        1171 :             Value v;
     157        1171 :             Value vk;
     158        1171 :             jsonObject->AddMember(vk.SetString(r.c_str(), a), v.SetArray(), a);
     159        1171 :         }
     160             : 
     161        1205 :         Value v;
     162        1205 :         v.SetObject();
     163             : 
     164        1205 :         Value vs1;
     165        1205 :         Value vs2;
     166        1205 :         v.AddMember("to", vs1.SetString(fq_name_ref.c_str(), a), a);
     167        1205 :         v.AddMember("uuid", vs2.SetString(ref_uuid.c_str(), a), a);
     168             : 
     169             :         bool link_with_attr =
     170        1205 :             cassandra_client_->mgr()->config_json_parser()->\
     171        1205 :             IsLinkWithAttr(obj_type, ref_type);
     172        1205 :         if (link_with_attr) {
     173         478 :             Document ref_document(&a);
     174         478 :             ref_document.Parse<0>(c.value.c_str());
     175         478 :             CONFIG_PARSE_ASSERT(ReferenceLinkAttributes,
     176             :                                 !ref_document.HasParseError());
     177         478 :             CONFIG_PARSE_ASSERT(ReferenceLinkAttributes,
     178             :                                 ref_document.HasMember("attr"));
     179         478 :             Value &attr_value = ref_document["attr"];
     180         478 :             if (!attr_value.IsNull()) {
     181         472 :                 v.AddMember("attr", attr_value, a);
     182             :             } else {
     183           6 :                 Value vm;
     184           6 :                 v.AddMember("attr", vm.SetObject(), a);
     185           6 :             }
     186         478 :         } else {
     187         727 :             Value vm;
     188         727 :             v.AddMember("attr", vm.SetObject(), a);
     189         727 :         }
     190        1205 :         (*jsonObject)[r.c_str()].PushBack(v, a);
     191        1205 :         return;
     192        1205 :     }
     193             : 
     194        9187 :     if (boost::starts_with(c.key, parent_prefix)) {
     195        1614 :         size_t pos = c.key.rfind(':');
     196        1614 :         CONFIG_PARSE_ASSERT(Parent, pos != string::npos);
     197        1614 :         size_t type_pos = c.key.find(':');
     198        1614 :         CONFIG_PARSE_ASSERT(Parent, type_pos != string::npos);
     199        1614 :         Value v;
     200        1614 :         Value vk;
     201        1614 :         jsonObject->AddMember(vk.SetString(parent_type_prefix.c_str(), a),
     202        1614 :                     v.SetString(c.key.substr(type_pos + 1,
     203        1614 :                                              pos-type_pos - 1).c_str(), a), a);
     204        1614 :         return;
     205        1614 :     }
     206             : 
     207        7573 :     if (!c.key.compare(fq_name_prefix)) {
     208        2717 :         Document fq_name_document(&a);
     209        2717 :         fq_name_document.Parse<0>(c.value.c_str());
     210        2717 :         CONFIG_PARSE_ASSERT(FqName, !fq_name_document.HasParseError());
     211        2717 :         Value vk;
     212        2717 :         jsonObject->AddMember(vk.SetString(c.key.c_str(), a),
     213             :                               fq_name_document, a);
     214        2717 :         return;
     215        2717 :     }
     216             : 
     217        4856 :     if (!c.key.compare("type")) {
     218             :         // Prepend the 'type'. This is "our key", with value being the json
     219             :         // sub-document containing all other columns.
     220        2717 :         CONFIG_PARSE_ASSERT(Type, type_ != obj_type);
     221        2717 :         type_ = c.value;
     222        2717 :         type_.erase(remove(type_.begin(), type_.end(), '\"'), type_.end());
     223        2717 :         return;
     224             :     }
     225             : }
     226             : 
     227        2716 : void ConfigCass2JsonAdapter::CreateJsonString(const string &obj_type,
     228             :                                               const CassColumnKVVec &cdvec) {
     229        2716 :     if (cdvec.empty())
     230           0 :         return;
     231        2717 :     Document::AllocatorType &a = json_document_.GetAllocator();
     232        2717 :     Value jsonObject;
     233        2717 :     jsonObject.SetObject();
     234             : 
     235             :     // First look for and part "type" field. We usually expect it to be at the
     236             :     // end as column keys are suppose to be allways sorted lexicographically.
     237        2717 :     size_t type_index = -1;
     238        2717 :     size_t i = cdvec.size();
     239        7024 :     while (i--) {
     240        7024 :         if (!cdvec[i].key.compare("type")) {
     241        2717 :             AddOneEntry(&jsonObject, obj_type, cdvec[i], a);
     242        2717 :             type_index = i;
     243        2717 :             break;
     244             :         }
     245             :     }
     246             : 
     247        2717 :     if (type_.empty()) {
     248             : 
     249           0 :         CONFIG_CLIENT_WARN_LOG(ConfigurationMissingTypeWarningLog,
     250             :                                Category::CONFIG_CLIENT, uuid_, obj_type);
     251           0 :         CONFIG_CLIENT_TRACE(ConfigurationMissingTypeWarningTrace, uuid_,
     252             :                             obj_type);
     253           0 :         return;
     254             :     }
     255             : 
     256       18589 :     for (size_t i = 0; i < cdvec.size(); ++i) {
     257       15872 :         if (i != type_index)
     258       13155 :             AddOneEntry(&jsonObject, obj_type, cdvec[i], a);
     259             :     }
     260             : 
     261        2717 :     Value vk;
     262        2717 :     json_document_.SetObject().AddMember(vk.SetString(type_.c_str(), a),
     263             :                                          jsonObject, a);
     264        2717 : }

Generated by: LCOV version 1.14