common/countertable.cpp (217 lines of code) (raw):

#include <hiredis/hiredis.h> #include <system_error> #include "common/logger.h" #include "common/redisreply.h" #include "common/rediscommand.h" #include "common/redisapi.h" #include <nlohmann/json.hpp> #include "common/schema.h" #include "common/countertable.h" using namespace std; using namespace swss; const std::string Counter::defaultLuaScript = "return nil"; /* * Port counter type */ unique_ptr<KeyCache<string>> PortCounter::keyCachePtr = nullptr; PortCounter::PortCounter(PortCounter::Mode mode) : m_mode(mode) { m_luaScript = loadLuaScript("portcounter.lua"); } const std::string& PortCounter::getLuaScript() const { return m_luaScript; } bool PortCounter::usingLuaTable(const CounterTable& t, const std::string &name) const { // Use LuaTable if and only if it is in UNION mode and has gearbox part. // That name map exists means the port has gearbox port part in PHY chip. return m_mode == Mode::UNION && t.getGbcountersDB()->hget(COUNTERS_PORT_NAME_MAP, name + "_line"); } std::vector<std::string> PortCounter::getLuaKeys(const CounterTable& t, const std::string &name) const { if (m_mode != Mode::UNION) return {}; KeyCache<string> &cache = keyCacheInstance(); if (cache.enabled()) { try { return {cache.at(name), cache.at(name + "_system"), cache.at(name + "_line")}; } catch (const std::out_of_range&) { return {}; } } auto oidLinesidePtr = t.getGbcountersDB()->hget(COUNTERS_PORT_NAME_MAP, name + "_line"); auto oidSystemsidePtr = t.getGbcountersDB()->hget(COUNTERS_PORT_NAME_MAP, name + "_system"); auto oidAsicPtr = t.getCountersDB()->hget(COUNTERS_PORT_NAME_MAP, name); if (oidAsicPtr && oidSystemsidePtr && oidLinesidePtr) { return {*oidAsicPtr, *oidSystemsidePtr, *oidLinesidePtr}; } return {}; } Counter::KeyPair PortCounter::getKey(const CounterTable& t, const std::string &name) const { int dbId = COUNTERS_DB; string portName = name; if (m_mode != Mode::ASIC && m_mode != Mode::UNION) { dbId = GB_COUNTERS_DB; if (m_mode == Mode::SYSTEMSIDE) { portName = name + "_system"; } else { portName = name + "_line"; } } KeyCache<string> &cache = keyCacheInstance(); if (cache.enabled()) { try { return {dbId, cache.at(portName)}; } catch (const std::out_of_range&) { return {-1, ""}; } } shared_ptr<std::string> oidPtr = nullptr; if (m_mode == Mode::ASIC || m_mode == Mode::UNION) { oidPtr = t.getCountersDB()->hget(COUNTERS_PORT_NAME_MAP, portName); } else { oidPtr = t.getGbcountersDB()->hget(COUNTERS_PORT_NAME_MAP, portName); } if (oidPtr == nullptr) return {-1, ""}; return {dbId, *oidPtr}; } KeyCache<string>& PortCounter::keyCacheInstance(void) { if (keyCachePtr == nullptr) { keyCachePtr.reset(new KeyCache<string>(PortCounter::cachingKey)); } return *keyCachePtr; } void PortCounter::cachingKey(const CounterTable& t) { auto fvs = t.getCountersDB()->hgetall(COUNTERS_PORT_NAME_MAP); keyCachePtr->insert(fvs.begin(), fvs.end()); fvs = t.getGbcountersDB()->hgetall(COUNTERS_PORT_NAME_MAP); keyCachePtr->insert(fvs.begin(), fvs.end()); } /* * MACSEC counter type */ unique_ptr<KeyCache<Counter::KeyPair>> MacsecCounter::keyCachePtr = nullptr; Counter::KeyPair MacsecCounter::getKey(const CounterTable& t, const std::string &name) const { KeyCache<Counter::KeyPair> &cache = keyCacheInstance(); if (cache.enabled()) { try { return cache.at(name); } catch (const std::out_of_range&) { return {-1, ""}; } } int dbId = COUNTERS_DB; auto oidPtr = t.getCountersDB()->hget(COUNTERS_MACSEC_NAME_MAP, name); if (oidPtr == nullptr) { dbId = GB_COUNTERS_DB; oidPtr = t.getGbcountersDB()->hget(COUNTERS_MACSEC_NAME_MAP, name); } if (oidPtr == nullptr) return {-1, ""}; return {dbId, *oidPtr}; } KeyCache<Counter::KeyPair>& MacsecCounter::keyCacheInstance(void) { if (keyCachePtr == nullptr) { keyCachePtr.reset(new KeyCache<Counter::KeyPair>(MacsecCounter::cachingKey)); } return *keyCachePtr; } void MacsecCounter::cachingKey(const CounterTable& t) { auto fvs = t.getCountersDB()->hgetall(COUNTERS_MACSEC_NAME_MAP); for (auto fv: fvs) { keyCachePtr->insert(fv.first, Counter::KeyPair(COUNTERS_DB, fv.second)); } fvs = t.getGbcountersDB()->hgetall(COUNTERS_MACSEC_NAME_MAP); for (auto fv: fvs) { keyCachePtr->insert(fv.first, Counter::KeyPair(GB_COUNTERS_DB, fv.second)); } } CounterTable::CounterTable(const DBConnector *db, const string &tableName) : TableBase(tableName, SonicDBConfig::getSeparator(db)) , m_countersDB(db->newConnector(0)) { unique_ptr<DBConnector> ptr(new DBConnector(GB_COUNTERS_DB, *m_countersDB)); m_gbcountersDB = std::move(ptr); } bool CounterTable::get(const Counter &counter, const std::string &name, std::vector<FieldValueTuple> &values) { if (counter.usingLuaTable(*this, name)) { LuaTable luaTable(m_countersDB.get(), getTableName(), counter.getLuaScript()); return luaTable.get(counter.getLuaKeys(*this, name), values); } else { auto keyPair = counter.getKey(*this, name); if (keyPair.second.empty()) { values.clear(); return false; } if (keyPair.first == GB_COUNTERS_DB) { Table table(m_gbcountersDB.get(), getTableName()); return table.get(keyPair.second, values); } else { Table table(m_countersDB.get(), getTableName()); return table.get(keyPair.second, values); } } } bool CounterTable::hget(const Counter &counter, const std::string &name, const std::string &field, std::string &value) { if (counter.usingLuaTable(*this, name)) { LuaTable luaTable(m_countersDB.get(), getTableName(), counter.getLuaScript()); return luaTable.hget(counter.getLuaKeys(*this, name), field, value); } else { auto keyPair = counter.getKey(*this, name); if (keyPair.second.empty()) { value.clear(); return false; } if (keyPair.first == GB_COUNTERS_DB) { Table table(getGbcountersDB().get(), getTableName()); return table.hget(keyPair.second, field, value); } else { Table table(m_countersDB.get(), getTableName()); return table.hget(keyPair.second, field, value); } } }