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

Reintroducing PR #364 - DBconnector to support namespaces. #371

Merged
merged 3 commits into from
Aug 11, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
292 changes: 233 additions & 59 deletions common/dbconnector.cpp

Large diffs are not rendered by default.

50 changes: 36 additions & 14 deletions common/dbconnector.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,20 @@
#include <utility>

#include <hiredis/hiredis.h>
#define EMPTY_NAMESPACE std::string()

namespace swss {

class DBConnector;

class RedisInstInfo
{
public:
std::string unixSocketPath;
std::string hostname;
int port;
};

class SonicDBInfo
{
public:
Expand All @@ -23,26 +32,36 @@ class SonicDBInfo
class SonicDBConfig
{
public:
static void initialize(const std::string &file = DEFAULT_SONIC_DB_CONFIG_FILE);
static std::string getDbInst(const std::string &dbName);
static int getDbId(const std::string &dbName);
static std::string getSeparator(const std::string &dbName);
static std::string getSeparator(int dbId);
static void initialize(const std::string &file = DEFAULT_SONIC_DB_CONFIG_FILE, const std::string &nameSpace = EMPTY_NAMESPACE);
static void initializeGlobalConfig(const std::string &file = DEFAULT_SONIC_DB_GLOBAL_CONFIG_FILE);
static void validateNamespace(const std::string &nameSpace);
static std::string getDbInst(const std::string &dbName, const std::string &nameSpace = EMPTY_NAMESPACE);
static int getDbId(const std::string &dbName, const std::string &nameSpace = EMPTY_NAMESPACE);
static std::string getSeparator(const std::string &dbName, const std::string &nameSpace = EMPTY_NAMESPACE);
static std::string getSeparator(int dbId, const std::string &nameSpace = EMPTY_NAMESPACE);
static std::string getSeparator(const DBConnector* db);
static std::string getDbSock(const std::string &dbName);
static std::string getDbHostname(const std::string &dbName);
static int getDbPort(const std::string &dbName);
static std::string getDbSock(const std::string &dbName, const std::string &nameSpace = EMPTY_NAMESPACE);
static std::string getDbHostname(const std::string &dbName, const std::string &nameSpace = EMPTY_NAMESPACE);
static int getDbPort(const std::string &dbName, const std::string &nameSpace = EMPTY_NAMESPACE);
static std::vector<std::string> getNamespaces();
static bool isInit() { return m_init; };
static bool isGlobalInit() { return m_global_init; };

private:
static constexpr const char *DEFAULT_SONIC_DB_CONFIG_FILE = "/var/run/redis/sonic-db/database_config.json";
// { instName, { unix_socket_path, {hostname, port} } }
static std::unordered_map<std::string, std::pair<std::string, std::pair<std::string, int>>> m_inst_info;
// { dbName, {instName, dbId} }
static std::unordered_map<std::string, SonicDBInfo> m_db_info;
// { dbIp, separator }
static std::unordered_map<int, std::string> m_db_separator;
static constexpr const char *DEFAULT_SONIC_DB_GLOBAL_CONFIG_FILE = "/var/run/redis/sonic-db/database_global.json";
// { namespace { instName, { unix_socket_path, hostname, port } } }
static std::unordered_map<std::string, std::unordered_map<std::string, RedisInstInfo>> m_inst_info;
// { namespace, { dbName, {instName, dbId, separator} } }
static std::unordered_map<std::string, std::unordered_map<std::string, SonicDBInfo>> m_db_info;
// { namespace, { dbId, separator } }
static std::unordered_map<std::string, std::unordered_map<int, std::string>> m_db_separator;
static bool m_init;
static bool m_global_init;
static void parseDatabaseConfig(const std::string &file,
std::unordered_map<std::string, RedisInstInfo> &inst_entry,
std::unordered_map<std::string, SonicDBInfo> &db_entry,
std::unordered_map<int, std::string> &separator_entry);
};

class DBConnector
Expand All @@ -60,12 +79,14 @@ class DBConnector
DBConnector(int dbId, const std::string &hostname, int port, unsigned int timeout);
DBConnector(int dbId, const std::string &unixPath, unsigned int timeout);
DBConnector(const std::string &dbName, unsigned int timeout, bool isTcpConn = false);
DBConnector(const std::string &dbName, unsigned int timeout, bool isTcpConn, const std::string &nameSpace);
Copy link
Contributor

Choose a reason for hiding this comment

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

nameSpace [](start = 100, length = 9)

nameSpace -> namespace

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@Qi cannot use namespace as this is a C++ keyword. may be namespaceName or name_space ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks! how about netns ?


~DBConnector();

redisContext *getContext() const;
int getDbId() const;
std::string getDbName() const;
std::string getNamespace() const;

static void select(DBConnector *db);

Expand All @@ -84,6 +105,7 @@ class DBConnector
redisContext *m_conn;
int m_dbId;
std::string m_dbName;
std::string m_namespace;
};

}
Expand Down
9 changes: 9 additions & 0 deletions common/redisselect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ int RedisSelect::getFd()
{
return m_subscribe->getContext()->fd;
}
int RedisSelect::getDbConnectorId()
{
return m_subscribe->getDbId();
}

std::string RedisSelect::getDbNamespace()
{
return m_subscribe->getNamespace();
}

uint64_t RedisSelect::readData()
{
Expand Down
2 changes: 2 additions & 0 deletions common/redisselect.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class RedisSelect : public Selectable
bool hasCachedData() override;
bool initializedWithData() override;
void updateAfterRead() override;
int getDbConnectorId() override;
std::string getDbNamespace() override;

/* Create a new redisContext, SELECT DB and SUBSCRIBE */
void subscribe(DBConnector* db, const std::string &channelName);
Expand Down
10 changes: 10 additions & 0 deletions common/selectable.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ class Selectable
return m_priority;
}

virtual int getDbConnectorId()
{
return 0;
}

virtual std::string getDbNamespace()
{
return std::string();
}

private:

friend class Select;
Expand Down
1 change: 1 addition & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ tests_SOURCES = redis_ut.cpp \
warm_restart_ut.cpp \
redis_multi_db_ut.cpp \
logger_ut.cpp \
redis_multi_ns_ut.cpp \
fdb_flush.cpp \
main.cpp

Expand Down
43 changes: 43 additions & 0 deletions tests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ using namespace swss;

string existing_file = "./tests/redis_multi_db_ut_config/database_config.json";
string nonexisting_file = "./tests/redis_multi_db_ut_config/database_config_nonexisting.json";
string global_existing_file = "./tests/redis_multi_db_ut_config/database_global.json";
string global_nonexisting_file = "./tests/redis_multi_db_ut_config/database_global_nonexisting.json";

#define TEST_DB "APPL_DB"
#define TEST_NAMESPACE "asic0"
#define INVALID_NAMESPACE "invalid"

class SwsscommonEnvironment : public ::testing::Environment {
public:
Expand All @@ -32,6 +38,43 @@ class SwsscommonEnvironment : public ::testing::Environment {
SonicDBConfig::initialize(existing_file);
cout<<"INIT: load local db config file, isInit = "<<SonicDBConfig::isInit()<<endl;
EXPECT_TRUE(SonicDBConfig::isInit());

// Test the database_global.json file
// by default , global_init should be false
cout<<"Default : isGlobalInit = "<<SonicDBConfig::isGlobalInit()<<endl;
EXPECT_FALSE(SonicDBConfig::isGlobalInit());

// Call an API which actually needs the data populated by SonicDBConfig::initializeGlobalConfig
try
{
cout<<"INIT: Invoking SonicDBConfig::getDbId(APPL_DB, asic0)"<<endl;
SonicDBConfig::getDbId(TEST_DB, TEST_NAMESPACE);
}
catch (exception &e)
{
EXPECT_TRUE(strstr(e.what(), "Initialize global DB config using API SonicDBConfig::initializeGlobalConfig"));
}

// load nonexisting database_global.json file, no exception thrown, and global_init flag is still False.
cout<<"INIT: loading nonexisting global db config file"<<endl;
SonicDBConfig::initializeGlobalConfig(global_nonexisting_file);
EXPECT_FALSE(SonicDBConfig::isGlobalInit());

// load local global file, init should be true
SonicDBConfig::initializeGlobalConfig(global_existing_file);
cout<<"INIT: load global db config file, isInit = "<<SonicDBConfig::isGlobalInit()<<endl;
EXPECT_TRUE(SonicDBConfig::isGlobalInit());

// Call an API with wrong namespace passed
try
{
cout<<"INIT: Invoking SonicDBConfig::getDbId(APPL_DB, invalid)"<<endl;
SonicDBConfig::getDbId(TEST_DB, INVALID_NAMESPACE);
}
catch (exception &e)
{
EXPECT_TRUE(strstr(e.what(), "Namespace invalid is not a valid namespace name in config file"));
}
}
};

Expand Down
82 changes: 82 additions & 0 deletions tests/redis_multi_db_ut_config/database_config0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"INSTANCES": {
"redis":{
"hostname" : "127.0.0.1",
"port": 6379,
"unix_socket_path": "/var/run/redis0/redis.sock"
}
},
"DATABASES" : {
"APPL_DB" : {
"id" : 0,
"separator": ":",
"instance" : "redis"
},
"ASIC_DB" : {
"id" : 1,
"separator": ":",
"instance" : "redis"
},
"COUNTERS_DB" : {
"id" : 2,
"separator": ":",
"instance" : "redis"
},
"LOGLEVEL_DB" : {
"id" : 3,
"separator": ":",
"instance" : "redis"
},
"CONFIG_DB" : {
"id" : 4,
"separator": "|",
"instance" : "redis"
},
"PFC_WD_DB" : {
"id" : 5,
"separator": ":",
"instance" : "redis"
},
"FLEX_COUNTER_DB" : {
"id" : 5,
"separator": ":",
"instance" : "redis"
},
"STATE_DB" : {
"id" : 6,
"separator": "|",
"instance" : "redis"
},
"SNMP_OVERLAY_DB" : {
"id" : 7,
"separator": "|",
"instance" : "redis"
},
"ASIC_DB2" : {
"id" : 10,
"separator": ":",
"instance" : "redis"
},
"COUNTERS_DB2" : {
"id" : 11,
"separator": ":",
"instance" : "redis"
},
"FLEX_COUNTER_DB2" : {
"id" : 12,
"separator": ":",
"instance" : "redis"
},
"STATE_DB2" : {
"id" : 13,
"separator": "|",
"instance" : "redis"
},
"TEST_DB" : {
"id" : 15,
"separator": ":",
"instance" : "redis"
}
},
"VERSION" : "1.0"
}
82 changes: 82 additions & 0 deletions tests/redis_multi_db_ut_config/database_config1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"INSTANCES": {
"redis":{
"hostname" : "127.0.0.1",
"port": 6379,
"unix_socket_path": "/var/run/redis1/redis.sock"
}
},
"DATABASES" : {
"APPL_DB" : {
"id" : 0,
"separator": ":",
"instance" : "redis"
},
"ASIC_DB" : {
"id" : 1,
"separator": ":",
"instance" : "redis"
},
"COUNTERS_DB" : {
"id" : 2,
"separator": ":",
"instance" : "redis"
},
"LOGLEVEL_DB" : {
"id" : 3,
"separator": ":",
"instance" : "redis"
},
"CONFIG_DB" : {
"id" : 4,
"separator": "|",
"instance" : "redis"
},
"PFC_WD_DB" : {
"id" : 5,
"separator": ":",
"instance" : "redis"
},
"FLEX_COUNTER_DB" : {
"id" : 5,
"separator": ":",
"instance" : "redis"
},
"STATE_DB" : {
"id" : 6,
"separator": "|",
"instance" : "redis"
},
"SNMP_OVERLAY_DB" : {
"id" : 7,
"separator": "|",
"instance" : "redis"
},
"ASIC_DB2" : {
"id" : 10,
"separator": ":",
"instance" : "redis"
},
"COUNTERS_DB2" : {
"id" : 11,
"separator": ":",
"instance" : "redis"
},
"FLEX_COUNTER_DB2" : {
"id" : 12,
"separator": ":",
"instance" : "redis"
},
"STATE_DB2" : {
"id" : 13,
"separator": "|",
"instance" : "redis"
},
"TEST_DB" : {
"id" : 15,
"separator": ":",
"instance" : "redis"
}
},
"VERSION" : "1.0"
}
16 changes: 16 additions & 0 deletions tests/redis_multi_db_ut_config/database_global.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"INCLUDES" : [
{
"include" : "database_config.json"
},
{
"namespace" : "asic0",
"include" : "../redis_multi_db_ut_config/database_config0.json"
},
{
"namespace" : "asic1",
"include" : "../redis_multi_db_ut_config/database_config1.json"
}
],
"VERSION" : "1.0"
}
Loading