Skip to content

Commit

Permalink
Add lua script for redis multi keys api hmset and del (sonic-net#406)
Browse files Browse the repository at this point in the history
  • Loading branch information
kcudnik authored and kktheballer committed Dec 21, 2020
1 parent 5a4f355 commit 1757b53
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 0 deletions.
1 change: 1 addition & 0 deletions common/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ EXTRA_DIST = \
consumer_table_pops.lua \
producer_state_table_apply_view.lua \
table_dump.lua \
redis_multi.lua \
fdb_flush.lua

EXTRA_CONF_DIST = database_config.json
Expand Down
58 changes: 58 additions & 0 deletions common/dbconnector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "common/dbconnector.h"
#include "common/redisreply.h"
#include "common/redisapi.h"

using json = nlohmann::json;
using namespace std;
Expand Down Expand Up @@ -421,6 +422,9 @@ void DBConnector::select(DBConnector *db)

RedisReply r(db, select, REDIS_REPLY_STATUS);
r.checkStatusOK();

std::string luaScript = loadLuaScript("redis_multi.lua");
db->m_shaRedisMulti = loadRedisScript(db, luaScript);
}

DBConnector::DBConnector(const DBConnector &other)
Expand Down Expand Up @@ -710,3 +714,57 @@ int64_t DBConnector::publish(const string &channel, const string &message)
RedisReply r(this, publish, REDIS_REPLY_INTEGER);
return r.getReply<long long int>();
}

void DBConnector::hmset(const std::unordered_map<std::string, std::vector<std::pair<std::string, std::string>>>& multiHash)
{
SWSS_LOG_ENTER();

json j;

// pack multi hash to json (takes bout 70 ms for 10k to construct)
for (const auto& kvp: multiHash)
{
json o;

for (const auto &item: kvp.second)
{
o[std::get<0>(item)] = std::get<1>(item);
}

j[kvp.first] = o;
}

std::string strJson = j.dump();

RedisCommand command;
command.format(
"EVALSHA %s 1 %s %s",
m_shaRedisMulti.c_str(),
strJson.c_str(),
"mhset");

RedisReply r(this, command, REDIS_REPLY_NIL);
}

void DBConnector::hdel(const std::vector<std::string>& keys)
{
SWSS_LOG_ENTER();

json j = json::array();

for (const auto& key: keys)
{
j.push_back(key);
}

std::string strJson = j.dump();

RedisCommand command;
command.format(
"EVALSHA %s 1 %s %s",
m_shaRedisMulti.c_str(),
strJson.c_str(),
"mdel");

RedisReply r(this, command, REDIS_REPLY_NIL);
}
6 changes: 6 additions & 0 deletions common/dbconnector.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ class DBConnector : public RedisContext

int64_t hdel(const std::string &key, const std::vector<std::string> &fields);

void hdel(const std::vector<std::string>& keys);

std::unordered_map<std::string, std::string> hgetall(const std::string &key);

template <typename OutputIterator>
Expand All @@ -166,6 +168,8 @@ class DBConnector : public RedisContext
template<typename InputIterator>
void hmset(const std::string &key, InputIterator start, InputIterator stop);

void hmset(const std::unordered_map<std::string, std::vector<std::pair<std::string, std::string>>>& multiHash);

std::shared_ptr<std::string> get(const std::string &key);

std::shared_ptr<std::string> hget(const std::string &key, const std::string &field);
Expand All @@ -192,6 +196,8 @@ class DBConnector : public RedisContext
int m_dbId;
std::string m_dbName;
std::string m_namespace;

std::string m_shaRedisMulti;
};

template<typename OutputIterator>
Expand Down
20 changes: 20 additions & 0 deletions common/redis_multi.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
local op = ARGV[1]
local jj = cjson.decode(KEYS[1])

if op == "mhset" then

for keyname,o in pairs(jj) do
for k,v in pairs(o) do
redis.call('HSET', keyname, k, v)
end
end

elseif op == "mdel" then

for idx,keyname in ipairs(jj) do
redis.call('DEL', keyname)
end

else
error("unsupported operation command: " .. op .. ", FIXME")
end

0 comments on commit 1757b53

Please sign in to comment.