Skip to content

Commit adae97b

Browse files
author
Shuotian Cheng
committed
producertable: Adding dump file to record all producer activities to file
- Use json.hpp to construct the JSON data and store into the m_dumpFile, which could be used as input file for swssconfig. - Add unit test for verification
1 parent efd594d commit adae97b

5 files changed

Lines changed: 125 additions & 8 deletions

File tree

common/json.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88

99
namespace swss {
1010

11-
class JSon {
11+
class JSon
12+
{
1213
public:
1314
static std::string buildJson(const std::vector<FieldValueTuple> &fv);
14-
1515
static void readJson(const std::string &json, std::vector<FieldValueTuple> &fv);
1616
};
1717

common/producertable.cpp

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
#include "common/redisreply.h"
22
#include "common/producertable.h"
33
#include "common/json.h"
4+
#include "common/json.hpp"
45
#include <stdlib.h>
56
#include <tuple>
67

78
using namespace std;
9+
using json = nlohmann::json;
810

911
namespace swss {
1012

@@ -13,6 +15,21 @@ ProducerTable::ProducerTable(DBConnector *db, string tableName) :
1315
{
1416
}
1517

18+
ProducerTable::ProducerTable(DBConnector *db, string tableName, string dumpFile) :
19+
Table(db, tableName)
20+
{
21+
m_dumpFile.open(dumpFile, fstream::out | fstream::trunc);
22+
m_dumpFile << "[" << endl;
23+
}
24+
25+
ProducerTable::~ProducerTable() {
26+
if (m_dumpFile.is_open())
27+
{
28+
m_dumpFile << endl << "]" << endl;
29+
m_dumpFile.close();
30+
}
31+
}
32+
1633
void ProducerTable::enqueueDbChange(string key, string value, string op)
1734
{
1835
string lpush_value;
@@ -44,21 +61,43 @@ void ProducerTable::enqueueDbChange(string key, string value, string op)
4461

4562
void ProducerTable::set(string key, vector<FieldValueTuple> &values, string op)
4663
{
47-
multi();
64+
if (m_dumpFile.is_open())
65+
{
66+
if (!m_firstItem)
67+
m_dumpFile << "," << endl;
68+
else
69+
m_firstItem = false;
70+
71+
json j;
72+
j[key] = json::object();
73+
for (auto it : values)
74+
j[key][fvField(it)] = fvValue(it);
75+
j["OP"] = op;
76+
m_dumpFile << j.dump(4);
77+
}
4878

79+
multi();
4980
enqueueDbChange(key, JSon::buildJson(values), "S" + op);
5081
exec();
5182
}
5283

5384
void ProducerTable::del(string key, string op)
5485
{
55-
string del("DEL ");
56-
del += getKeyName(key);
86+
if (m_dumpFile.is_open())
87+
{
88+
if (!m_firstItem)
89+
m_dumpFile << "," << endl;
90+
else
91+
m_firstItem = false;
5792

58-
multi();
93+
json j;
94+
j[key] = json::object();
95+
j["OP"] = op;
96+
m_dumpFile << j.dump(4);
97+
}
5998

99+
multi();
60100
enqueueDbChange(key, "{}", "D" + op);
61-
62101
exec();
63102
}
64103

common/producertable.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef __PRODUCERTABLE__
22
#define __PRODUCERTABLE__
33

4+
#include <fstream>
5+
#include <iostream>
46
#include <string>
57
#include <vector>
68

@@ -14,6 +16,8 @@ class ProducerTable : public Table
1416
{
1517
public:
1618
ProducerTable(DBConnector *db, std::string tableName);
19+
ProducerTable(DBConnector *db, std::string tableName, std::string dumpFile);
20+
~ProducerTable();
1721

1822
/* Implements set() and del() commands using notification messages */
1923
virtual void set(std::string key, std::vector<FieldValueTuple> &values,
@@ -25,6 +29,9 @@ class ProducerTable : public Table
2529
ProducerTable(const ProducerTable &other);
2630
ProducerTable & operator = (const ProducerTable &other);
2731

32+
std::ofstream m_dumpFile;
33+
bool m_firstItem = true;
34+
2835
void enqueueDbChange(std::string key, std::string value, std::string op);
2936
};
3037

tests/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ LDADD_GTEST = $(top_srcdir)/googletest/build/googlemock/gtest/libgtest_main.a \
1313
$(top_srcdir)/googletest/build/googlemock/gtest/libgtest.a
1414

1515
tests_SOURCES = redis_ut.cpp \
16-
tokenize_ut.cpp
16+
tokenize_ut.cpp \
17+
json_ut.cpp
1718

1819
tests_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_GTEST)
1920
tests_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_GTEST)

tests/json_ut.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#include "common/json.hpp"
2+
#include "common/producertable.h"
3+
#include "gtest/gtest.h"
4+
5+
using namespace std;
6+
using namespace swss;
7+
using json = nlohmann::json;
8+
9+
#define TEST_VIEW (7)
10+
#define TEST_DUMP_FILE "ut_dump_file.txt"
11+
12+
TEST(JSON, test)
13+
{
14+
/* Construct the file */
15+
DBConnector db(TEST_VIEW, "localhost", 6379, 0);
16+
ProducerTable *p;
17+
p = new ProducerTable(&db, "UT_REDIS_CHANNEL", TEST_DUMP_FILE);
18+
19+
vector<FieldValueTuple> fvTuples;
20+
FieldValueTuple fv1("test_field_1", "test_value_1");
21+
fvTuples.push_back(fv1);
22+
23+
p->set("test_key_1", fvTuples);
24+
25+
FieldValueTuple fv2("test_field_2", "test_value_2");
26+
fvTuples.push_back(fv2);
27+
28+
p->set("test_key_2", fvTuples);
29+
30+
p->del("test_key_1");
31+
32+
delete(p);
33+
34+
/* Read the file and validate the content */
35+
fstream file(TEST_DUMP_FILE, fstream::in);
36+
json j;
37+
file >> j;
38+
39+
EXPECT_TRUE(j.is_array());
40+
EXPECT_TRUE(j.size() == 3);
41+
42+
for (size_t i = 0; i < j.size(); i++)
43+
{
44+
auto item = j[i];
45+
EXPECT_TRUE(item.is_object());
46+
EXPECT_TRUE(item.size() == 2);
47+
48+
for (auto it = item.begin(); it != item.end(); it++)
49+
{
50+
if (it.key() == "OP")
51+
EXPECT_TRUE(it.value() == "SET" || it.value() == "DEL");
52+
else
53+
{
54+
auto subitem = it.value();
55+
EXPECT_TRUE(subitem.is_object());
56+
if (subitem.size() > 0)
57+
{
58+
for (auto subit = subitem.begin(); subit != subitem.end(); subit++)
59+
{
60+
if (subit.key() == "test_field_1")
61+
EXPECT_EQ(subit.value(), "test_value_1");
62+
if (subit.key() == "test_field_2")
63+
EXPECT_EQ(subit.value(), "test_value_2");
64+
}
65+
}
66+
}
67+
}
68+
}
69+
file.close();
70+
}

0 commit comments

Comments
 (0)