Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions .azure-pipelines/build-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,17 @@ jobs:
sudo mkdir /usr/local/yang-models

sudo dpkg -i libswsscommon_*.deb
sudo dpkg -i libswsscommon-dev_*.deb
sudo dpkg -i python-swsscommon_*.deb

./tests/tests
redis-cli FLUSHALL
pytest --cov=. --cov-report=xml
mv coverage.xml tests/coverage.xml
gcovr -r ./ -e ".*/swsscommon_wrap.cpp" --exclude-unreachable-branches --exclude-throw-branches -x --xml-pretty -o coverage.xml
make -C goext
redis-cli FLUSHALL
make -C goext check

rm -rf $(Build.ArtifactStagingDirectory)/download
displayName: "Run swss common unit tests"
Expand Down
2 changes: 2 additions & 0 deletions common/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ libswsscommon_la_SOURCES = \
defaultvalueprovider.cpp \
sonicv2connector.cpp \
table.cpp \
decoratortable.cpp \
json.cpp \
producertable.cpp \
producerstatetable.cpp \
Expand Down Expand Up @@ -67,6 +68,7 @@ libswsscommon_la_SOURCES = \
exec.cpp \
saiaclschema.cpp \
subscriberstatetable.cpp \
decoratorsubscriberstatetable.cpp \
timestamp.cpp \
warm_restart.cpp \
luatable.cpp \
Expand Down
49 changes: 47 additions & 2 deletions common/configdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class ConfigDBConnector_Native : public SonicV2Connector_Native
std::string m_db_name;
};

#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
%pythoncode %{
## Note: diamond inheritance, reusing functions in both classes
class ConfigDBConnector(SonicV2Connector, ConfigDBConnector_Native):
Expand Down Expand Up @@ -240,6 +240,51 @@ class ConfigDBConnector_Native : public SonicV2Connector_Native
entry = self.raw_to_typed(entry)
ret.setdefault(table_name, {})[self.deserialize_key(row)] = entry
return ret

class YangDefaultDecorator(object):
def __init__(self, config_db_connector):
self.connector = config_db_connector
self.default_value_provider = DefaultValueProvider()
# helper methods for append default values to result.
def _append_default_value(self, table, key, data):
if data is None or len(data) == 0:
# empty entry means the entry been deleted
return data
serialized_key = self.connector.serialize_key(key)
defaultValues = self.default_value_provider.getDefaultValues(table, serialized_key)
for field in defaultValues:
if field not in data:
data[field] = defaultValues[field]
# override read APIs
def new_get_entry(self, table, key):
result = self.connector.get_entry(table, key)
self._append_default_value(table, key, result)
return result
def new_get_table(self, table):
result = self.connector.get_table(table)
for key in result:
self._append_default_value(table, key, result[key])
return result
def new_get_config(self):
result = self.connector.get_config()
for table in result:
for key in result[table]:
# Can not pass result[table][key] as parameter here, because python will create a copy. re-assign entry to result to bypass this issue.
entry = result[table][key]
self._append_default_value(table, key, entry)
result[table][key] = entry
return result
def __getattr__(self, name):
if name == "get_entry":
return self.new_get_entry
elif name == "get_table":
return self.new_get_table
elif name == "get_config":
return self.new_get_config

originalMethod = self.connector.__getattribute__(name)
return originalMethod

%}
#endif

Expand All @@ -262,7 +307,7 @@ class ConfigDBPipeConnector_Native: public ConfigDBConnector_Native
int _get_config(DBConnector& client, RedisTransactioner& pipe, std::map<std::string, std::map<std::string, std::map<std::string, std::string>>>& data, int cursor);
};

#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
%pythoncode %{
class ConfigDBPipeConnector(ConfigDBConnector, ConfigDBPipeConnector_Native):

Expand Down
2 changes: 1 addition & 1 deletion common/countertable.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class KeyCache {
return m_keyMap.at(name);
}

#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
%pythoncode %{
def __getitem__(self, name):
return self.at(name)
Expand Down
10 changes: 5 additions & 5 deletions common/dbconnector.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class SonicDBConfig
static constexpr const char *DEFAULT_SONIC_DB_CONFIG_FILE = "/var/run/redis/sonic-db/database_config.json";
static constexpr const char *DEFAULT_SONIC_DB_GLOBAL_CONFIG_FILE = "/var/run/redis/sonic-db/database_global.json";
static void initialize(const std::string &file = DEFAULT_SONIC_DB_CONFIG_FILE);
#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
%pythoncode %{
## TODO: the python function and C++ one is not on-par
@staticmethod
Expand All @@ -51,7 +51,7 @@ class SonicDBConfig
#endif

static void initializeGlobalConfig(const std::string &file = DEFAULT_SONIC_DB_GLOBAL_CONFIG_FILE);
#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
%pythoncode %{
## TODO: the python function and C++ one is not on-par
@staticmethod
Expand All @@ -70,7 +70,7 @@ class SonicDBConfig
static std::string getDbHostname(const std::string &dbName, const std::string &netns = EMPTY_NAMESPACE);
static int getDbPort(const std::string &dbName, const std::string &netns = EMPTY_NAMESPACE);
static std::vector<std::string> getNamespaces();
#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
%pythoncode %{
## TODO: the python function and C++ one is not on-par
@staticmethod
Expand Down Expand Up @@ -163,7 +163,7 @@ class DBConnector : public RedisContext
std::string getDbName() const;
std::string getNamespace() const;

#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
%pythoncode %{
namespace = property(getNamespace)
%}
Expand All @@ -181,7 +181,7 @@ class DBConnector : public RedisContext

int64_t del(const std::string &key);

#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
// SWIG interface file (.i) globally rename map C++ `del` to python `delete`,
// but applications already followed the old behavior of auto renamed `_del`.
// So we implemented old behavior for backward compatibility
Expand Down
34 changes: 34 additions & 0 deletions common/decoratorsubscriberstatetable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <boost/algorithm/string.hpp>
#include "common/decoratorsubscriberstatetable.h"
#include "common/defaultvalueprovider.h"

using namespace std;
using namespace swss;

DecoratorSubscriberStateTable::DecoratorSubscriberStateTable(DBConnector *db, const string &tableName, int popBatchSize, int pri)
:SubscriberStateTable(db, tableName, popBatchSize, pri)
{
m_defaultValueProvider = std::make_shared<DefaultValueProvider>();
}

/* Get multiple pop elements */
void DecoratorSubscriberStateTable::pops(deque<KeyOpFieldsValuesTuple> &vkco, const string &prefix)
{
SubscriberStateTable::pops(vkco, prefix);
for (auto& kco : vkco)
{
appendDefaultValue(kfvKey(kco), kfvOp(kco), kfvFieldsValues(kco));
}
}

void DecoratorSubscriberStateTable::appendDefaultValue(std::string &key, std::string &op, std::vector<FieldValueTuple> &fvs)
{
if (op != SET_COMMAND)
{
// When pops, 'set' operation means read data, only read need decorate.
return;
}

auto table = getTableName();
m_defaultValueProvider->appendDefaultValues(table, key, fvs);
}
31 changes: 31 additions & 0 deletions common/decoratorsubscriberstatetable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <assert.h>
#include <string>
#include <queue>
#include <tuple>
#include <utility>
#include <map>
#include <memory>
#include <deque>
#include "table.h"
#include "subscriberstatetable.h"
#include "defaultvalueprovider.h"

namespace swss {

class DecoratorSubscriberStateTable : public SubscriberStateTable
{
public:
DecoratorSubscriberStateTable(DBConnector *db, const std::string &tableName, int popBatchSize = swss::TableConsumable::DEFAULT_POP_BATCH_SIZE, int pri = 0);

/* Get all elements available */
void pops(std::deque<KeyOpFieldsValuesTuple> &vkco, const std::string &prefix = EMPTY_PREFIX) override;

private:
std::shared_ptr<DefaultValueProvider> m_defaultValueProvider;

void appendDefaultValue(std::string &key, std::string &op, std::vector<FieldValueTuple> &fvs);
};

}
53 changes: 53 additions & 0 deletions common/decoratortable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <boost/algorithm/string.hpp>

#include "common/decoratortable.h"

using namespace std;
using namespace swss;

DecoratorTable::DecoratorTable(const DBConnector *db, const string &tableName)
: Table(db, tableName)
{
m_defaultValueProvider = std::make_shared<DefaultValueProvider>();
}

DecoratorTable::DecoratorTable(RedisPipeline *pipeline, const string &tableName, bool buffered)
:Table(pipeline, tableName, buffered)
{
m_defaultValueProvider = std::make_shared<DefaultValueProvider>();
}

/* Get all the field-value tuple of the table entry with the key */
bool DecoratorTable::get(const string &key, vector<pair<string, string>> &ovalues)
{
bool result = Table::get(key, ovalues);
auto table = getTableName();

// Append default values
m_defaultValueProvider->appendDefaultValues(table, key, ovalues);

return result;
}

bool DecoratorTable::hget(const string &key, const string &field, string &value)
{
auto result = Table::hget(key,
field,
value);
if (result)
{
return true;
}

auto table = getTableName();

// Try append default values
auto default_value = m_defaultValueProvider->getDefaultValue(table, key, field);
if (default_value != nullptr)
{
value = *default_value;
return true;
}

return false;
}
33 changes: 33 additions & 0 deletions common/decoratortable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <assert.h>
#include <string>
#include <queue>
#include <tuple>
#include <utility>
#include <map>
#include <memory>
#include <deque>
#include "table.h"
#include "subscriberstatetable.h"
#include "defaultvalueprovider.h"

namespace swss {

class DecoratorTable : public Table
{
public:
DecoratorTable(const DBConnector *db, const std::string &tableName);
DecoratorTable(RedisPipeline *pipeline, const std::string &tableName, bool buffered);

/* Get all the field-value tuple of the table entry with the key */
bool get(const std::string &key, std::vector<std::pair<std::string, std::string>> &ovalues) override;

/* Get an entry field-value from the table */
bool hget(const std::string &key, const std::string &field, std::string &value) override;

private:
std::shared_ptr<DefaultValueProvider> m_defaultValueProvider;
};

}
2 changes: 1 addition & 1 deletion common/defaultvalueprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <map>
#include <string>
#include <vector>
#include "common/table.h"
#include "table.h"

#include <libyang/libyang.h>

Expand Down
2 changes: 1 addition & 1 deletion common/producerstatetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class ProducerStateTable : public TableBase, public TableName_KeySet
const std::string &op = DEL_COMMAND,
const std::string &prefix = EMPTY_PREFIX);

#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
// SWIG interface file (.i) globally rename map C++ `del` to python `delete`,
// but applications already followed the old behavior of auto renamed `_del`.
// So we implemented old behavior for backward compatibility
Expand Down
2 changes: 1 addition & 1 deletion common/producertable.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ProducerTable : public TableBase, public TableName_KeyValueOpQueues
const std::string &op = DEL_COMMAND,
const std::string &prefix = EMPTY_PREFIX);

#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
// SWIG interface file (.i) globally rename map C++ `del` to python `delete`,
// but applications already followed the old behavior of auto renamed `_del`.
// So we implemented old behavior for backward compatibility
Expand Down
2 changes: 1 addition & 1 deletion common/sonicv2connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class SonicV2Connector_Native
std::string m_netns;
};

#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
%pythoncode %{
class SonicV2Connector(SonicV2Connector_Native):

Expand Down
6 changes: 4 additions & 2 deletions common/table.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ class TableEntryPoppable {
}
};

#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
%pythoncode %{
def transpose_pops(m):
return [tuple(m[j][i] for j in range(len(m))) for i in range(len(m[0]))]
Expand All @@ -168,6 +168,8 @@ class TableEntryEnumerable {
/* Get all the field-value tuple of the table entry with the key */
virtual bool get(const std::string &key, std::vector<FieldValueTuple> &values) = 0;

virtual bool hget(const std::string &key, const std::string &field, std::string &value) = 0;

/* get all the keys in the table */
virtual void getKeys(std::vector<std::string> &keys) = 0;

Expand Down Expand Up @@ -205,7 +207,7 @@ class Table : public TableBase, public TableEntryEnumerable {
/* Get the configured ttl value for key */
bool ttl(const std::string &key, int64_t &reply_value);

#ifdef SWIG
#if defined(SWIG) && defined(SWIGPYTHON)
// SWIG interface file (.i) globally rename map C++ `del` to python `delete`,
// but applications already followed the old behavior of auto renamed `_del`.
// So we implemented old behavior for backward compatibility
Expand Down
1 change: 1 addition & 0 deletions debian/libswsscommon-dev.install
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
common/*.h usr/include/swss
common/*.hpp usr/include/swss
pyext/swsscommon.i usr/share/swss
Loading