common/luatable.cpp (102 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/luatable.h" using namespace std; using namespace swss; LuaTable::LuaTable(const DBConnector *db, const string &tableName, const string &lua, const vector<string> &luaArgv) : TableBase(tableName, SonicDBConfig::getSeparator(db)) , m_db(db->newConnector(0)) , m_lua(lua) , m_luaArgv(luaArgv) { } LuaTable::~LuaTable() { } bool LuaTable::get(const vector<string> &luaKeys, vector<FieldValueTuple> &values) { if (m_lua.empty() || luaKeys.empty()) { values.clear(); return false; } // Assembly redis command args into a string vector vector<string> args; args.emplace_back("EVALSHA"); args.emplace_back(loadRedisScript(m_db.get(), m_lua)); args.emplace_back(to_string(luaKeys.size())); for (const auto& k: luaKeys) { args.emplace_back(k); } // ARGV[1..4]: counter db, gearbox counter db, table name, separator args.emplace_back(to_string(COUNTERS_DB)); args.emplace_back(to_string(GB_COUNTERS_DB)); args.emplace_back(getTableName()); args.emplace_back(getTableNameSeparator()); args.emplace_back("HGETALL"); // ARGV[5] get all fields for (const auto& v: m_luaArgv) // ARGV[6...] extra user-defined { args.emplace_back(v); } // Invoke redis command RedisCommand command; command.format(args); RedisReply r(m_db.get(), command, REDIS_REPLY_ARRAY); redisReply *reply = r.getContext(); if (!reply->elements) return false; if (reply->elements & 1) throw system_error(make_error_code(errc::address_not_available), "Unable to connect netlink socket"); values.clear(); for (unsigned int i = 0; i < reply->elements; i += 2) { values.emplace_back(reply->element[i]->str, reply->element[i + 1]->str); } return true; } bool LuaTable::hget(const vector<string> &luaKeys, const string &field, string &value) { if (m_lua.empty() || luaKeys.empty() || field.empty()) { value.clear(); return false; } // Assembly redis command args into a string vector vector<string> args; args.emplace_back("EVALSHA"); args.emplace_back(loadRedisScript(m_db.get(), m_lua)); args.emplace_back(to_string(luaKeys.size())); for (const auto& k: luaKeys) { args.emplace_back(k); } // ARGV[1..4]: counter db, gearbox counter db, table name, separator args.emplace_back(to_string(COUNTERS_DB)); args.emplace_back(to_string(GB_COUNTERS_DB)); args.emplace_back(getTableName()); args.emplace_back(getTableNameSeparator()); args.emplace_back("HGET"); // ARGV[5] get one field args.emplace_back(field); // ARGV[6] field name for (const auto& v: m_luaArgv) // ARGV[7...] extra user-defined { args.emplace_back(v); } // Invoke redis command RedisCommand command; command.format(args); RedisReply r(m_db.get(), command); redisReply *reply = r.getContext(); if (reply->type == REDIS_REPLY_NIL) { value.clear(); return false; } if (reply->type != REDIS_REPLY_STRING) throw system_error(make_error_code(errc::io_error), "Got unexpected reply type"); value = reply->str; return true; }