common/profileprovider.cpp (176 lines of code) (raw):
#include <boost/algorithm/string.hpp>
#include <cassert>
#include <iostream>
#include <map>
#include <string>
#include <tuple>
#include <vector>
#include <dirent.h>
#include <stdio.h>
#include "profileprovider.h"
#include "logger.h"
#include "table.h"
#include "schema.h"
using namespace std;
using namespace swss;
ProfileProvider& ProfileProvider::instance()
{
static ProfileProvider instance;
return instance;
}
shared_ptr<string> ProfileProvider::getConfig(const string &table, const string &key, const string &field, DBConnector* cfgDbConnector)
{
assert(!table.empty());
assert(!key.empty());
assert(!field.empty());
auto staticConfig = getConfigs(table, key, cfgDbConnector);
auto result = staticConfig.find(field);
if (result != staticConfig.end())
{
return make_shared<string>(result->second);
}
// Config not found is different with 'empty' config
return nullptr;
}
bool ProfileProvider::appendConfigs(const string &table, const string &key, vector<pair<string, string> > &values, DBConnector* cfgDbConnector)
{
assert(!table.empty());
assert(!key.empty());
SWSS_LOG_DEBUG("DefaultValueProvider::AppendDefaultValues %s %s\n", table.c_str(), key.c_str());
auto staticConfig = getConfigs(table, key, cfgDbConnector);
map<string, string> existedValues;
for (auto& fieldValuePair : values)
{
existedValues.emplace(fieldValuePair.first, fieldValuePair.second);
}
bool appendValues = false;
for (auto& fieldValuePair : staticConfig)
{
auto findresult = existedValues.find(fieldValuePair.first);
if (findresult == existedValues.end())
{
appendValues = true;
values.emplace_back(fieldValuePair.first, fieldValuePair.second);
}
}
return appendValues;
}
map<string, string> ProfileProvider::getConfigs(const string &table, const string &key, DBConnector* cfgDbConnector)
{
if (itemDeleted(table, key, cfgDbConnector))
{
SWSS_LOG_DEBUG("DefaultValueProvider::GetConfigs item %s %s deleted.\n", table.c_str(), key.c_str());
map<string, string> map;
return map;
}
auto& staticCfgDbConnector = getStaticCfgDBConnector(cfgDbConnector);
auto itemkey = getKeyName(table, key, &staticCfgDbConnector);
return staticCfgDbConnector.hgetall<map<string, string>>(itemkey);
}
map<string, map<string, map<string, string>>> ProfileProvider::getConfigs(DBConnector* cfgDbConnector)
{
auto& staticCfgDbConnector = getStaticCfgDBConnector(cfgDbConnector);
auto configs = staticCfgDbConnector.getall();
// If a profile item mark as 'deleted', it's shoud not exist in result.
list<pair<string, string>> deletedItems;
for(auto const& tableItem: configs)
{
auto table = tableItem.first;
for(auto const& item: tableItem.second)
{
auto key = item.first;
if (itemDeleted(table, key, cfgDbConnector))
{
SWSS_LOG_DEBUG("DefaultValueProvider::GetConfigs item %s %s deleted.\n", table.c_str(), key.c_str());
deletedItems.push_back(make_pair(table, key));
}
}
}
for(auto const& deletedItem: deletedItems)
{
auto table = deletedItem.first;
auto key = deletedItem.second;
SWSS_LOG_DEBUG("DefaultValueProvider::GetConfigs remove deleted item %s %s from result.\n", table.c_str(), key.c_str());
configs[table].erase(key);
}
return configs;
}
vector<string> ProfileProvider::getKeys(const string &table, DBConnector* cfgDbConnector)
{
auto& staticCfgDbConnector = getStaticCfgDBConnector(cfgDbConnector);
auto pattern = getKeyName(table, "*", &staticCfgDbConnector);
auto keys = staticCfgDbConnector.keys(pattern);
const auto separator = SonicDBConfig::getSeparator(&staticCfgDbConnector);
vector<string> result;
for(auto const& itemKey: keys)
{
size_t pos = itemKey.find(separator);
if (pos == string::npos)
{
SWSS_LOG_DEBUG("DefaultValueProvider::GetConfigs can't find separator %s in %s.\n", separator.c_str(), itemKey.c_str());
continue;
}
auto row = itemKey.substr(pos + 1);
if (!itemDeleted(table, row, cfgDbConnector))
{
result.push_back(row);
}
else
{
SWSS_LOG_DEBUG("DefaultValueProvider::GetConfigs item %s %s deleted.\n", table.c_str(), row.c_str());
}
}
return result;
}
ProfileProvider::ProfileProvider()
{
}
ProfileProvider::~ProfileProvider()
{
}
bool ProfileProvider::tryRevertItem(const string &table, const string &key, DBConnector* cfgDbConnector)
{
if (itemDeleted(table, key, cfgDbConnector))
{
revertItem(table, key, cfgDbConnector);
return true;
}
return false;
}
bool ProfileProvider::tryDeleteItem(const string &table, const string &key, DBConnector* cfgDbConnector)
{
if (!itemDeleted(table, key, cfgDbConnector))
{
deleteItem(table, key, cfgDbConnector);
return true;
}
return false;
}
bool ProfileProvider::itemDeleted(const string &table, const string &key, DBConnector* cfgDbConnector)
{
auto deletedkey = getDeletedKeyName(table, key, cfgDbConnector);
return cfgDbConnector->exists(deletedkey) == true;
}
void ProfileProvider::deleteItem(const string &table, const string &key, DBConnector* cfgDbConnector)
{
auto deletedkey = getDeletedKeyName(table, key, cfgDbConnector);
// Only need deletedkey to mark the item is deleted.
cfgDbConnector->hset(deletedkey, "", "");
}
void ProfileProvider::revertItem(const string &table, const string &key, DBConnector* cfgDbConnector)
{
auto deletedkey = getDeletedKeyName(table, key,cfgDbConnector);
cfgDbConnector->del(deletedkey);
}
DBConnector& ProfileProvider::getStaticCfgDBConnector(DBConnector* cfgDbConnector)
{
auto ns = cfgDbConnector->getNamespace();
auto result = m_staticCfgDBMap.find(ns);
if (result != m_staticCfgDBMap.end())
{
return result->second;
}
// Create new DBConnector instance to PROFILE_DB
const string staticDbName = "PROFILE_DB";
m_staticCfgDBMap.emplace(piecewise_construct,
forward_as_tuple(ns),
forward_as_tuple(staticDbName, SonicDBConfig::getDbId(staticDbName, ns), true, ns));
result = m_staticCfgDBMap.find(ns);
return result->second;
}