Skip to content

Commit

Permalink
Merge "Log error during json configuration parsing failures"
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Feb 17, 2017
2 parents 2313954 + bb06cc6 commit dae0614
Show file tree
Hide file tree
Showing 12 changed files with 126 additions and 122 deletions.
5 changes: 2 additions & 3 deletions src/ifmap/client/config_cass2json_adapter.cc
Expand Up @@ -44,8 +44,7 @@ bool ConfigCass2JsonAdapter::assert_on_parse_error_;
do { \
if (condition) \
break; \
IFMAP_WARN(ConfigurationMalformed ## t, c.key, c.value, type_, uuid_, \
obj_type); \
IFMAP_WARN(ConfigurationMalformed ## t, c.key, c.value, type_, uuid_); \
if (assert_on_parse_error_) \
assert(false); \
return; \
Expand Down Expand Up @@ -219,7 +218,7 @@ void ConfigCass2JsonAdapter::CreateJsonString(const string &obj_type,
}
}

if (type_ == "") {
if (type_.empty()) {
IFMAP_WARN(ConfigurationMissingType, uuid_, obj_type);
return;
}
Expand Down
13 changes: 10 additions & 3 deletions src/ifmap/client/config_cass2json_adapter.h
Expand Up @@ -34,18 +34,25 @@ class ConfigCass2JsonAdapter {
ConfigCassandraClient *cassandra_client,
const std::string &obj_type,
const CassColumnKVVec &cdvec);
const contrail_rapidjson::Document &document() { return json_document_; }
const contrail_rapidjson::Document &document() const {
return json_document_;
}
static bool assert_on_parse_error() { return assert_on_parse_error_; }
static void set_assert_on_parse_error(bool flag) {
assert_on_parse_error_ = flag;
}
const std::string &uuid() const { return uuid_; }
const std::string &type() const { return type_; }

private:
void CreateJsonString(const std::string &obj_type,
const CassColumnKVVec &cdvec);
void AddOneEntry(contrail_rapidjson::Value *jsonObject, const std::string &obj_type,
void AddOneEntry(contrail_rapidjson::Value *jsonObject,
const std::string &obj_type,
const JsonAdapterDataType &c,
contrail_rapidjson::Document::AllocatorType &a);
static std::string GetJsonString(const contrail_rapidjson::Value &attr_value);
static std::string GetJsonString(
const contrail_rapidjson::Value &attr_value);

ConfigCassandraClient *cassandra_client_;
std::string uuid_;
Expand Down
9 changes: 5 additions & 4 deletions src/ifmap/client/config_cassandra_client.cc
Expand Up @@ -331,10 +331,10 @@ bool ConfigCassandraClient::ParseRowAndEnqueueToParser(const string &obj_type,
ConfigCass2JsonAdapter ccja(uuid_key, this, obj_type, cass_data_vec);

// Enqueue Json document to the parser here.
parser_->Receive(uuid_key, ccja.document(), IFMapOrigin::CASSANDRA);
parser_->Receive(ccja, IFMapOrigin::CASSANDRA);
} else {
IFMAP_WARN(IFMapGetRowError, "Parsing row response failed for table",
kUuidTableName);
kUuidTableName, uuid_key);
return false;
}

Expand Down Expand Up @@ -401,7 +401,8 @@ bool ConfigCassandraClient::ReadUuidTableRow(const string &obj_type,
}
} else {
HandleCassandraConnectionStatus(false);
IFMAP_WARN(IFMapGetRowError, "GetRow failed for table", kUuidTableName);
IFMAP_WARN(IFMapGetRowError, "GetRow failed for table", kUuidTableName,
uuid_key);
//
// Task is rescheduled to read the request queue
// Due to a bug CQL driver from datastax, connection status is
Expand Down Expand Up @@ -459,7 +460,7 @@ bool ConfigCassandraClient::ReadAllFqnTableRows() {
} else {
HandleCassandraConnectionStatus(false);
IFMAP_WARN(IFMapGetRowError, "GetAllRows failed for table. Retry !",
kFqnTableName);
kFqnTableName, "");
sleep(kInitRetryTimeSec);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/ifmap/client/config_client_manager.cc
Expand Up @@ -139,7 +139,7 @@ IFMapTable::RequestKey *ConfigClientManager::CloneKey(
}

string ConfigClientManager::GetLinkName(const string &left,
const string &right) const {
const string &right) const {
LinkNameMap::const_iterator it =
link_name_map_.find(make_pair(left, right));
if (it == link_name_map_.end())
Expand All @@ -148,7 +148,7 @@ string ConfigClientManager::GetLinkName(const string &left,
}

bool ConfigClientManager::IsLinkWithAttr(const string &left,
const string &right) const {
const string &right) const {
LinkNameMap::const_iterator it =
link_name_map_.find(make_pair(left, right));
if (it == link_name_map_.end())
Expand Down
134 changes: 78 additions & 56 deletions src/ifmap/client/config_json_parser.cc
Expand Up @@ -7,12 +7,27 @@

#include "config_cassandra_client.h"

#include "ifmap_log.h"
#include "base/autogen_util.h"
#include "client/config_log_types.h"
#include "ifmap/client/config_cass2json_adapter.h"
#include "ifmap/ifmap_log.h"
#include "ifmap/ifmap_log_types.h"

using namespace contrail_rapidjson;
using namespace std;

#define CONFIG_PARSE_ASSERT(t, condition, key, value) \
do { \
if (condition) \
break; \
IFMAP_WARN(ConfigurationMalformed ## t, key, value, adapter.type(), \
adapter.uuid()); \
if (ConfigCass2JsonAdapter::assert_on_parse_error()) \
assert(false); \
return false; \
} while (false)

ConfigJsonParser::ConfigJsonParser(ConfigClientManager *mgr)
: mgr_(mgr) {
}
Expand All @@ -28,19 +43,25 @@ void ConfigJsonParser::MetadataClear(const string &module) {
metadata_map_.clear();
}

bool ConfigJsonParser::ParseNameType(const Document &document,
bool ConfigJsonParser::ParseNameType(const ConfigCass2JsonAdapter &adapter,
IFMapTable::RequestKey *key) const {
// Type is the name of the document.
Value::ConstMemberIterator itr = document.MemberBegin();
assert(itr->name.IsString());
Value::ConstMemberIterator itr = adapter.document().MemberBegin();
CONFIG_PARSE_ASSERT(Type, autogen::ParseString(itr->name, &key->id_type),
"Name", "Bad name");

key->id_type = itr->name.GetString();

// Name is the fq_name field in the document.
const Value &value_node = itr->value;
assert(value_node.HasMember("fq_name"));
CONFIG_PARSE_ASSERT(FqName, value_node.HasMember("fq_name"), key->id_type,
"Missing FQ name");
const Value &fq_name_node = value_node["fq_name"];
assert(fq_name_node.IsArray());
assert(fq_name_node.Size() != 0);
CONFIG_PARSE_ASSERT(FqName, fq_name_node.IsArray(), key->id_type,
"FQ name is not an array");
CONFIG_PARSE_ASSERT(FqName, fq_name_node.Size(),
key->id_type, "FQ name array is empty");

size_t i = 0;

// Iterate over all items except the last one.
Expand All @@ -53,9 +74,9 @@ bool ConfigJsonParser::ParseNameType(const Document &document,
return true;
}

bool ConfigJsonParser::ParseOneProperty(const Value &key_node,
const Value &value_node, const IFMapTable::RequestKey &key,
IFMapOrigin::Origin origin,
bool ConfigJsonParser::ParseOneProperty(const ConfigCass2JsonAdapter &adapter,
const Value &key_node, const Value &value_node,
const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin,
ConfigClientManager::RequestList *req_list) const {
string metaname = key_node.GetString();
MetadataParseMap::const_iterator loc = metadata_map_.find(metaname);
Expand All @@ -64,78 +85,80 @@ bool ConfigJsonParser::ParseOneProperty(const Value &key_node,
}
auto_ptr<AutogenProperty> pvalue;
bool success = (loc->second)(value_node, &pvalue);
if (!success) {
cout << "Parsing value node for " << metaname << " failed" << endl;
return false;
}

CONFIG_PARSE_ASSERT(Property, success, metaname,
"No entry in metadata map");
std::replace(metaname.begin(), metaname.end(), '_', '-');
config_mgr()->InsertRequestIntoQ(origin, "", "", metaname, pvalue, key,
true, req_list);

return true;
}

bool ConfigJsonParser::ParseProperties(const Document &document,
bool ConfigJsonParser::ParseProperties(const ConfigCass2JsonAdapter &adapter,
const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin,
ConfigClientManager::RequestList *req_list) const {

Value::ConstMemberIterator doc_itr = document.MemberBegin();
Value::ConstMemberIterator doc_itr = adapter.document().MemberBegin();
const Value &value_node = doc_itr->value;
for (Value::ConstMemberIterator itr = value_node.MemberBegin();
itr != value_node.MemberEnd(); ++itr) {
ParseOneProperty(itr->name, itr->value, key, origin,
ParseOneProperty(adapter, itr->name, itr->value, key, origin,
req_list);
}

return true;
}

bool ConfigJsonParser::ParseRef(const Value &ref_entry,
IFMapOrigin::Origin origin, const string &to_underscore,
const IFMapTable::RequestKey &key,
bool ConfigJsonParser::ParseRef(const ConfigCass2JsonAdapter &adapter,
const Value &ref_entry, IFMapOrigin::Origin origin,
const string &refer, const IFMapTable::RequestKey &key,
ConfigClientManager::RequestList *req_list) const {
const Value& to_node = ref_entry["to"];

string from_underscore = key.id_type;
std::replace(from_underscore.begin(), from_underscore.end(), '-', '_');
string link_name =
config_mgr()->GetLinkName(from_underscore, to_underscore);
if (link_name.empty())
return false;
config_mgr()->GetLinkName(from_underscore, refer);
CONFIG_PARSE_ASSERT(Reference, !link_name.empty(), refer,
"Link name is empty");
string metaname = link_name;
std::replace(metaname.begin(), metaname.end(), '-', '_');

MetadataParseMap::const_iterator loc = metadata_map_.find(metaname);
if (loc == metadata_map_.end()) {
cout << metaname << " not found in metadata map" << endl;
return false;
}
CONFIG_PARSE_ASSERT(Reference, loc != metadata_map_.end(), metaname,
"No entry in metadata map");

auto_ptr<AutogenProperty> pvalue;
if (ref_entry.HasMember("attr")) {
const Value& attr_node = ref_entry["attr"];
bool success = (loc->second)(attr_node, &pvalue);
if (!success) {
cout << "Parsing link attribute for " << metaname << " failed"
<< endl;
return false;
}
CONFIG_PARSE_ASSERT(ReferenceLinkAttributes, success, metaname,
"Link attribute parse error");
}

string neigh_name;
neigh_name += to_node.GetString();

config_mgr()->InsertRequestIntoQ(origin, to_underscore, neigh_name,
config_mgr()->InsertRequestIntoQ(origin, refer, neigh_name,
link_name, pvalue, key, true, req_list);

return true;
}

bool ConfigJsonParser::ParseLinks(const Document &document,
bool ConfigJsonParser::ParseOneRef(const ConfigCass2JsonAdapter &adapter,
const Value &arr, const IFMapTable::RequestKey &key,
IFMapOrigin::Origin origin, ConfigClientManager::RequestList *req_list,
const string &key_str, size_t pos) const {
string refer = key_str.substr(0, pos);
CONFIG_PARSE_ASSERT(Reference, arr.IsArray(), refer, "Invalid referene");
for (size_t i = 0; i < arr.Size(); ++i)
ParseRef(adapter, arr[i], origin, refer, key, req_list);
return true;
}

bool ConfigJsonParser::ParseLinks(const ConfigCass2JsonAdapter &adapter,
const IFMapTable::RequestKey &key, IFMapOrigin::Origin origin,
ConfigClientManager::RequestList *req_list) const {
Value::ConstMemberIterator doc_itr = document.MemberBegin();
Value::ConstMemberIterator doc_itr = adapter.document().MemberBegin();
const Value &properties = doc_itr->value;
for (Value::ConstMemberIterator itr = properties.MemberBegin();
itr != properties.MemberEnd(); ++itr) {
Expand All @@ -146,24 +169,23 @@ bool ConfigJsonParser::ParseLinks(const Document &document,
}
size_t pos = key_str.find("_refs");
if (pos != string::npos) {
string to_underscore = key_str.substr(0, pos);
const Value& arr = itr->value;
assert(arr.IsArray());
for (size_t i = 0; i < arr.Size(); ++i) {
ParseRef(arr[i], origin, to_underscore,
key, req_list);
}
ParseOneRef(adapter, itr->value, key, origin, req_list, key_str,
pos);
continue;
}
if (key_str.compare("parent_type") == 0) {
const Value& ptype_node = itr->value;
assert(ptype_node.IsString());
CONFIG_PARSE_ASSERT(Parent, ptype_node.IsString(), key_str,
"Invalid parent type");
pos = key.id_name.find_last_of(":");
if (pos != string::npos) {
string parent_type = ptype_node.GetString();
// Get the parent name from our name.
string parent_name = key.id_name.substr(0, pos);
string metaname =
config_mgr()->GetLinkName(parent_type,key.id_type);
CONFIG_PARSE_ASSERT(Parent, !metaname.empty(), parent_type,
"Missing link name");
auto_ptr<AutogenProperty > pvalue;
config_mgr()->InsertRequestIntoQ(origin, parent_type,
parent_name, metaname, pvalue, key, true, req_list);
Expand All @@ -176,46 +198,46 @@ bool ConfigJsonParser::ParseLinks(const Document &document,
return true;
}

bool ConfigJsonParser::ParseDocument(const Document &document,
bool ConfigJsonParser::ParseDocument(const ConfigCass2JsonAdapter &adapter,
IFMapOrigin::Origin origin, ConfigClientManager::RequestList *req_list,
IFMapTable::RequestKey *key) const {
// Update the name and the type into 'key'.
if (!ParseNameType(document, key)) {
if (!ParseNameType(adapter, key)) {
return false;
}

// For each property, we will clone 'key' to create our DBRequest's i.e.
// 'key' will never become part of any DBRequest.
if (!ParseProperties(document, *key, origin, req_list)){
if (!ParseProperties(adapter, *key, origin, req_list)){
return false;
}

if (!ParseLinks(document, *key, origin, req_list)) {
if (!ParseLinks(adapter, *key, origin, req_list)) {
return false;
}

return true;
}

bool ConfigJsonParser::Receive(const string &uuid,
const contrail_rapidjson::Document &document,
bool ConfigJsonParser::Receive(const ConfigCass2JsonAdapter &adapter,
IFMapOrigin::Origin origin) {
ConfigClientManager::RequestList req_list;

if (document.HasParseError() || !document.IsObject()) {
size_t pos = document.GetErrorOffset();
if (adapter.document().HasParseError() || !adapter.document().IsObject()) {
size_t pos = adapter.document().GetErrorOffset();
// GetParseError returns const char *
IFMAP_WARN(IFMapJsonLoadError,
"Error in parsing JSON message at position",
pos, "with error description",
boost::lexical_cast<string>(document.GetParseError()));
boost::lexical_cast<string>(
adapter.document().GetParseError()), adapter.uuid());
return false;
} else {
auto_ptr<IFMapTable::RequestKey> key(new IFMapTable::RequestKey());
if (!ParseDocument(document, origin, &req_list, key.get()))
if (!ParseDocument(adapter, origin, &req_list, key.get()))
return false;
config_mgr()->config_db_client()->FormDeleteRequestList(uuid, &req_list,
key.get(), true);
config_mgr()->config_db_client()->FormDeleteRequestList(
adapter.uuid(), &req_list, key.get(), true);
config_mgr()->EnqueueListToTables(&req_list);
}
return true;
Expand Down

0 comments on commit dae0614

Please sign in to comment.