Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VOQ][saidump] Enhance saidump with new option -r to parser the JSON file and displays/format the right output #1288

Merged
merged 17 commits into from
Sep 25, 2023
187 changes: 184 additions & 3 deletions saidump/saidump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
#include <string>
#include <set>
#include <sstream>
#include <iostream>
#include <fstream>
#include <regex>

extern "C" {
#include <sai.h>
Expand All @@ -10,18 +13,26 @@ extern "C" {
#include "swss/table.h"
#include "meta/sai_serialize.h"
#include "sairediscommon.h"
#include "swss/json.h"
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
#include "swss/json.hpp"
kcudnik marked this conversation as resolved.
Show resolved Hide resolved

#include <getopt.h>

// TODO split to multiple cpp

using namespace swss;
using namespace std;
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
using json = nlohmann::json;

// 100 MB
const int64_t RDB_FILE_MAX_SIZE = 1024 * 1024 * 100;
kcudnik marked this conversation as resolved.
Show resolved Hide resolved

struct CmdOptions
{
bool skipAttributes;
bool dumpTempView;
bool dumpGraph;
string rdb_file;
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
};

CmdOptions g_cmdOptions;
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -31,11 +42,13 @@ void printUsage()
{
SWSS_LOG_ENTER();

std::cout << "Usage: saidump [-t] [-g] [-h]" << std::endl;
std::cout << "Usage: saidump [-t] [-g] [-r] [-h]" << std::endl;
std::cout << " -t --tempView:" << std::endl;
std::cout << " Dump temp view" << std::endl;
std::cout << " -g --dumpGraph:" << std::endl;
std::cout << " Dump current graph" << std::endl;
std::cout << " -r --rdb:" << std::endl;
std::cout << " Dump by parsing the Redis persistence file dump.rdb that is generated by SAVE command." << std::endl;
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
std::cout << " -h --help:" << std::endl;
std::cout << " Print out this message" << std::endl;
}
Expand All @@ -49,14 +62,15 @@ CmdOptions handleCmdLine(int argc, char **argv)
options.dumpTempView = false;
options.dumpGraph = false;

const char* const optstring = "gth";
const char* const optstring = "gtr:h";

while (true)
{
static struct option long_options[] =
{
{ "dumpGraph", no_argument, 0, 'g' },
{ "tempView", no_argument, 0, 't' },
{ "rdb", required_argument, 0, 'r' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
};
Expand All @@ -82,6 +96,11 @@ CmdOptions handleCmdLine(int argc, char **argv)
options.dumpTempView = true;
break;

case 'r':
SWSS_LOG_WARN("Dumping from dump.rdb");
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
options.rdb_file = string(optarg);
break;

case 'h':
printUsage();
exit(EXIT_SUCCESS);
Expand Down Expand Up @@ -399,7 +418,159 @@ void dumpGraph(const TableDump& td)
std::cout << "}" << std::endl;
}

int main(int argc, char ** argv)
/*
preprocess the input json file to make sure it's a valid json file.
*/
int pre_process_file(string file_name)
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
{
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
ifstream input_file(file_name);

if (!input_file.is_open())
{
cerr << "Failed to open the input file." << endl;
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
return SAI_STATUS_FAILURE;
}

input_file.seekg(0, ios::end); // Move to the end of the file
int64_t file_size = input_file.tellg(); // Get the current position

if (file_size >= RDB_FILE_MAX_SIZE)
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
{
SWSS_LOG_ERROR("Get %s's size failure or its size %ld >= %ld MB.\n", file_name.c_str(), file_size, RDB_FILE_MAX_SIZE / 1024 / 1024);
kcudnik marked this conversation as resolved.
Show resolved Hide resolved

// Close the input file
input_file.close();
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
return SAI_STATUS_FAILURE;
}
input_file.seekg(0, ios::beg); // Move to the begin of the file
kcudnik marked this conversation as resolved.
Show resolved Hide resolved

// Read the content of the input file into a string
string content((istreambuf_iterator<char>(input_file)),
istreambuf_iterator<char>());

kcudnik marked this conversation as resolved.
Show resolved Hide resolved

input_file.close();

content = regex_replace(content, regex("\\},\\{\\r"), ",");
kcudnik marked this conversation as resolved.
Show resolved Hide resolved

//erase the 1st and last char.
if (content.length() >= 2 && content[0] == '[' && content[content.length()-1] == ']') {
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
content.erase(0, 1);
content.erase(content.length() - 1);
}

ofstream outputFile(file_name);

if (!outputFile.is_open())
{
cerr << "Failed to open the output file." << endl;
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
return SAI_STATUS_FAILURE;
}

outputFile << content;
outputFile.close();

return SAI_STATUS_SUCCESS;
}

int dump_from_redis_rdb_file(string file_name)
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
{
ifstream input_file(file_name);
if (!input_file.is_open())
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
{
SWSS_LOG_NOTICE("The file %s does not exist for dumping from redis dump.rdb file.", file_name);
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
return SAI_STATUS_FAILURE;
}

input_file.seekg(0, ios::end); // Move to the end of the file
int64_t file_size = input_file.tellg(); // Get the current position
if (file_size >= RDB_FILE_MAX_SIZE)
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
{
SWSS_LOG_ERROR("Get %s's size failure or its size %ld >= %ld MB.\n", file_name.c_str(), file_size, RDB_FILE_MAX_SIZE / 1024 / 1024);

// Close the input file
input_file.close();
return SAI_STATUS_FAILURE;
}
input_file.seekg(0, ios::beg); // Move to the begin of the file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty line after }


try
{
// Parse the JSON data from the file (validation)
nlohmann::json jsonData;
input_file >> jsonData;
input_file.close();

SWSS_LOG_DEBUG("%s\n","JSON file is valid.\n");
kcudnik marked this conversation as resolved.
Show resolved Hide resolved

for (json::iterator it = jsonData.begin(); it != jsonData.end(); ++it)
{
json jj_key = it.key();

string keystr = jj_key;
string item_name = keystr;
size_t pos = keystr.find_first_of(":");
if (pos != string::npos)
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
{
if("ASIC_STATE" != keystr.substr(0, pos)) // filter out non ASIC_STATE
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
{
continue;
}
item_name = keystr.substr(pos + 1);
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
if (item_name.find(":") != string::npos)
{
item_name.replace(item_name.find_first_of(":"), 1, " ");
}
}
else
{
continue;
}

cout << item_name << " " << endl;
kcudnik marked this conversation as resolved.
Show resolved Hide resolved

json jj = it.value();

if (!(*it).is_object())
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
{
continue;
}

TableMap map;
for (json::iterator itt = jj.begin(); itt != jj.end(); ++itt)
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
{
if (itt.key() == "NULL")
{
continue;
}
map[itt.key()] = itt.value();
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
}

size_t indent = 4;
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
size_t max_len = get_max_attr_len(map);
string str_indent = pad_string("", indent);

for (const auto&field: map)
{
stringstream ss;
ss << str_indent << pad_string(field.first, max_len) << " : ";
ss << field.second;
cout << ss.str() << std::endl;
}
cout << endl;
}
return SAI_STATUS_SUCCESS;
}
catch (exception &ex)
{
input_file.close();
cerr << "JSON file:" << file_name << " is invalid." << endl;
kcudnik marked this conversation as resolved.
Show resolved Hide resolved
cerr << "JSON parsing error: " << ex.what() << endl;
}
return SAI_STATUS_FAILURE;
}

int main(int argc, char **argv)
{
swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG);

Expand All @@ -411,6 +582,16 @@ int main(int argc, char ** argv)

g_cmdOptions = handleCmdLine(argc, argv);

if (g_cmdOptions.rdb_file.size() > 0)
{
if (SAI_STATUS_FAILURE == pre_process_file(g_cmdOptions.rdb_file))
{
return EXIT_FAILURE;
}
dump_from_redis_rdb_file(g_cmdOptions.rdb_file);
return EXIT_SUCCESS;
}

swss::DBConnector db("ASIC_DB", 0);

std::string table = ASIC_STATE_TABLE;
Expand Down