From 151be008378f90d6bca101cc9a54457cd4c54198 Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Wed, 9 May 2018 20:02:24 -0700 Subject: [PATCH 01/10] Add hmset and hgetallordered redis api function support --- common/redisclient.cpp | 45 +++++++++++++++++++++++++++++++++++++++++- common/redisclient.h | 3 +++ common/schema.h | 5 ++++- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/common/redisclient.cpp b/common/redisclient.cpp index 9568d91ee..473442aba 100644 --- a/common/redisclient.cpp +++ b/common/redisclient.cpp @@ -35,6 +35,34 @@ void RedisClient::hset(const string &key, const string &field, const string &val RedisReply r(m_db, shset, REDIS_REPLY_INTEGER); } +void RedisClient::hmset(const string &key, const vector &values) +{ + if (values.size() == 0) + return; + + RedisCommand shmset; + shmset.formatHMSET(key, values); + RedisReply r(m_db, shmset, REDIS_REPLY_STATUS); +} + +void RedisClient::hmset(const string &key, const std::map &vmap) +{ + if (vmap.size() == 0) + return; + + vector values; + auto it = vmap.begin(); + while (it != vmap.end()) + { + values.push_back(FieldValueTuple(it->first, it->second)); + it++; + } + + RedisCommand shmset; + shmset.formatHMSET(key, values); + RedisReply r(m_db, shmset, REDIS_REPLY_STATUS); +} + void RedisClient::set(const string &key, const string &value) { RedisCommand sset; @@ -57,6 +85,21 @@ unordered_map RedisClient::hgetall(const string &key) return map; } +std::map RedisClient::hgetallordered(const std::string &key) +{ + RedisCommand sincr; + sincr.format("HGETALL %s", key.c_str()); + RedisReply r(m_db, sincr, REDIS_REPLY_ARRAY); + + auto ctx = r.getContext(); + + map map; + for (unsigned int i = 0; i < ctx->elements; i += 2) + map[string(ctx->element[i]->str)] = string(ctx->element[i+1]->str); + + return map; +} + vector RedisClient::keys(const string &key) { RedisCommand skeys; @@ -94,7 +137,7 @@ shared_ptr RedisClient::get(const string &key) sget.format("GET %s", key.c_str()); RedisReply r(m_db, sget); auto reply = r.getContext(); - + if (reply->type == REDIS_REPLY_NIL) { return shared_ptr(NULL); diff --git a/common/redisclient.h b/common/redisclient.h index e19f1bd0c..fdf854b80 100644 --- a/common/redisclient.h +++ b/common/redisclient.h @@ -29,6 +29,7 @@ class RedisClient int64_t hdel(const std::string &key, const std::string &field); std::unordered_map hgetall(const std::string &key); + std::map hgetallordered(const std::string &key); std::vector keys(const std::string &key); @@ -41,6 +42,8 @@ class RedisClient void mset(const std::unordered_map &map); void hmset(const std::string &key, const std::unordered_map &map); + void hmset(const std::string &key, const std::vector &values); + void hmset(const std::string &key, const std::map &vmap); std::shared_ptr get(const std::string &key); diff --git a/common/schema.h b/common/schema.h index 4ebff5e8d..77f3bfeee 100644 --- a/common/schema.h +++ b/common/schema.h @@ -13,6 +13,7 @@ namespace swss { #define PFC_WD_DB 5 #define FLEX_COUNTER_DB 5 #define STATE_DB 6 +#define RESTORE_DB 7 /***** APPLICATION DATABASE *****/ @@ -32,6 +33,8 @@ namespace swss { #define APP_COPP_TABLE_NAME "COPP_TABLE" +#define APP_WARM_START_TABLE_NAME "WARM_START_TABLE" + /***** TO BE REMOVED *****/ #define APP_TC_TO_QUEUE_MAP_TABLE_NAME "TC_TO_QUEUE_MAP_TABLE" @@ -77,7 +80,7 @@ namespace swss { #define PFC_WD_STATE_TABLE "PFC_WD_STATE_TABLE" #define PFC_WD_PORT_COUNTER_ID_LIST "PORT_COUNTER_ID_LIST" #define PFC_WD_QUEUE_COUNTER_ID_LIST "QUEUE_COUNTER_ID_LIST" -#define PFC_WD_QUEUE_ATTR_ID_LIST "QUEUE_ATTR_ID_LIST" +#define PFC_WD_QUEUE_ATTR_ID_LIST "QUEUE_ATTR_ID_LIST" #define PLUGIN_TABLE "PLUGIN_TABLE" #define LUA_PLUGIN_TYPE "LUA_PLUGIN_TYPE" #define SAI_OBJECT_TYPE "SAI_OBJECT_TYPE" From 77352f6304953c35b712c49b1d37b1a964b969ae Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Mon, 28 May 2018 23:41:54 -0700 Subject: [PATCH 02/10] Add exists command support for redis client Signed-off-by: Jipan Yang --- common/redisclient.cpp | 8 ++++++++ common/redisclient.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/common/redisclient.cpp b/common/redisclient.cpp index 473442aba..51dd22936 100644 --- a/common/redisclient.cpp +++ b/common/redisclient.cpp @@ -20,6 +20,14 @@ int64_t RedisClient::del(const string &key) return r.getContext()->integer; } +int64_t RedisClient::exists(const string &key) +{ + RedisCommand sexists; + sexists.format("EXISTS %s", key.c_str()); + RedisReply r(m_db, sexists, REDIS_REPLY_INTEGER); + return r.getContext()->integer; +} + int64_t RedisClient::hdel(const string &key, const string &field) { RedisCommand shdel; diff --git a/common/redisclient.h b/common/redisclient.h index fdf854b80..904aef3d6 100644 --- a/common/redisclient.h +++ b/common/redisclient.h @@ -26,6 +26,8 @@ class RedisClient int64_t del(const std::string &key); + int64_t exists(const std::string &key); + int64_t hdel(const std::string &key, const std::string &field); std::unordered_map hgetall(const std::string &key); From 2939e6af1179cd3166a4a670f14b09f27c5c2134 Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Thu, 5 Jul 2018 23:23:51 -0700 Subject: [PATCH 03/10] Add warm restart table names for appDB and configDB Signed-off-by: Jipan Yang --- common/schema.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/schema.h b/common/schema.h index 77f3bfeee..17a28e62e 100644 --- a/common/schema.h +++ b/common/schema.h @@ -33,7 +33,7 @@ namespace swss { #define APP_COPP_TABLE_NAME "COPP_TABLE" -#define APP_WARM_START_TABLE_NAME "WARM_START_TABLE" +#define APP_WARM_RESTART_TABLE_NAME "WARM_RESTART_TABLE" /***** TO BE REMOVED *****/ @@ -144,6 +144,8 @@ namespace swss { #define CFG_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME "BUFFER_PORT_INGRESS_PROFILE_LIST" #define CFG_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME "BUFFER_PORT_EGRESS_PROFILE_LIST" + +#define CFG_WARM_RESTART_TABLE_NAME "WARM_RESTART" /***** STATE DATABASE *****/ #define STATE_PORT_TABLE_NAME "PORT_TABLE" From 5fe4e571bbbb5a7b027832e61d1406d5a492af2c Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Fri, 13 Jul 2018 17:02:36 -0700 Subject: [PATCH 04/10] Add getDbID() function for tableBase Signed-off-by: Jipan Yang --- common/table.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/table.h b/common/table.h index 4f153523c..d30552919 100644 --- a/common/table.h +++ b/common/table.h @@ -35,7 +35,7 @@ typedef std::map TableDump; class TableBase { public: TableBase(int dbId, const std::string &tableName) - : m_tableName(tableName) + : m_tableName(tableName), m_dbId(dbId) { /* Look up table separator for the provided DB */ auto it = tableNameSeparatorMap.find(dbId); @@ -52,6 +52,7 @@ class TableBase { } std::string getTableName() const { return m_tableName; } + int getDbId() const { return m_dbId; } /* Return the actual key name as a combination of tableNamekey */ std::string getKeyName(const std::string &key) @@ -74,6 +75,7 @@ class TableBase { std::string m_tableName; std::string m_tableSeparator; + int m_dbId; }; class TableEntryWritable { From c1414ed1cd234b35681beb7524ce24ab571e0e09 Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Tue, 17 Jul 2018 14:29:28 -0700 Subject: [PATCH 05/10] Address review comments Signed-off-by: Jipan Yang --- common/redisclient.cpp | 24 +++++++++++------------- common/redisclient.h | 2 +- common/schema.h | 7 +------ 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/common/redisclient.cpp b/common/redisclient.cpp index 51dd22936..e7795d924 100644 --- a/common/redisclient.cpp +++ b/common/redisclient.cpp @@ -20,12 +20,12 @@ int64_t RedisClient::del(const string &key) return r.getContext()->integer; } -int64_t RedisClient::exists(const string &key) +bool RedisClient::exists(const string &key) { - RedisCommand sexists; - sexists.format("EXISTS %s", key.c_str()); - RedisReply r(m_db, sexists, REDIS_REPLY_INTEGER); - return r.getContext()->integer; + RedisCommand rexists; + rexists.format("EXISTS %s", key.c_str()); + RedisReply r(m_db, rexists, REDIS_REPLY_INTEGER); + return (r.getContext()->integer > 0); } int64_t RedisClient::hdel(const string &key, const string &field) @@ -45,7 +45,7 @@ void RedisClient::hset(const string &key, const string &field, const string &val void RedisClient::hmset(const string &key, const vector &values) { - if (values.size() == 0) + if (values.empty()) return; RedisCommand shmset; @@ -55,15 +55,13 @@ void RedisClient::hmset(const string &key, const vector &values void RedisClient::hmset(const string &key, const std::map &vmap) { - if (vmap.size() == 0) + if (vmap.empty()) return; vector values; - auto it = vmap.begin(); - while (it != vmap.end()) + for(const auto it:vmap) { - values.push_back(FieldValueTuple(it->first, it->second)); - it++; + values.emplace_back(it.first, it.second); } RedisCommand shmset; @@ -88,7 +86,7 @@ unordered_map RedisClient::hgetall(const string &key) unordered_map map; for (unsigned int i = 0; i < ctx->elements; i += 2) - map[string(ctx->element[i]->str)] = string(ctx->element[i+1]->str); + map.emplace(ctx->element[i]->str, ctx->element[i+1]->str); return map; } @@ -103,7 +101,7 @@ std::map RedisClient::hgetallordered(const std::string map map; for (unsigned int i = 0; i < ctx->elements; i += 2) - map[string(ctx->element[i]->str)] = string(ctx->element[i+1]->str); + map.emplace(ctx->element[i]->str, ctx->element[i+1]->str); return map; } diff --git a/common/redisclient.h b/common/redisclient.h index 904aef3d6..844b75c11 100644 --- a/common/redisclient.h +++ b/common/redisclient.h @@ -26,7 +26,7 @@ class RedisClient int64_t del(const std::string &key); - int64_t exists(const std::string &key); + bool exists(const std::string &key); int64_t hdel(const std::string &key, const std::string &field); diff --git a/common/schema.h b/common/schema.h index 17a28e62e..4ebff5e8d 100644 --- a/common/schema.h +++ b/common/schema.h @@ -13,7 +13,6 @@ namespace swss { #define PFC_WD_DB 5 #define FLEX_COUNTER_DB 5 #define STATE_DB 6 -#define RESTORE_DB 7 /***** APPLICATION DATABASE *****/ @@ -33,8 +32,6 @@ namespace swss { #define APP_COPP_TABLE_NAME "COPP_TABLE" -#define APP_WARM_RESTART_TABLE_NAME "WARM_RESTART_TABLE" - /***** TO BE REMOVED *****/ #define APP_TC_TO_QUEUE_MAP_TABLE_NAME "TC_TO_QUEUE_MAP_TABLE" @@ -80,7 +77,7 @@ namespace swss { #define PFC_WD_STATE_TABLE "PFC_WD_STATE_TABLE" #define PFC_WD_PORT_COUNTER_ID_LIST "PORT_COUNTER_ID_LIST" #define PFC_WD_QUEUE_COUNTER_ID_LIST "QUEUE_COUNTER_ID_LIST" -#define PFC_WD_QUEUE_ATTR_ID_LIST "QUEUE_ATTR_ID_LIST" +#define PFC_WD_QUEUE_ATTR_ID_LIST "QUEUE_ATTR_ID_LIST" #define PLUGIN_TABLE "PLUGIN_TABLE" #define LUA_PLUGIN_TYPE "LUA_PLUGIN_TYPE" #define SAI_OBJECT_TYPE "SAI_OBJECT_TYPE" @@ -144,8 +141,6 @@ namespace swss { #define CFG_BUFFER_PORT_INGRESS_PROFILE_LIST_NAME "BUFFER_PORT_INGRESS_PROFILE_LIST" #define CFG_BUFFER_PORT_EGRESS_PROFILE_LIST_NAME "BUFFER_PORT_EGRESS_PROFILE_LIST" - -#define CFG_WARM_RESTART_TABLE_NAME "WARM_RESTART" /***** STATE DATABASE *****/ #define STATE_PORT_TABLE_NAME "PORT_TABLE" From bbff96a69fb2abe1944ccc6a752e63f8e22a9d8e Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Tue, 17 Jul 2018 15:36:36 -0700 Subject: [PATCH 06/10] Remove redundant empty check Signed-off-by: Jipan Yang --- common/redisclient.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/common/redisclient.cpp b/common/redisclient.cpp index e7795d924..ae69d34d9 100644 --- a/common/redisclient.cpp +++ b/common/redisclient.cpp @@ -45,9 +45,6 @@ void RedisClient::hset(const string &key, const string &field, const string &val void RedisClient::hmset(const string &key, const vector &values) { - if (values.empty()) - return; - RedisCommand shmset; shmset.formatHMSET(key, values); RedisReply r(m_db, shmset, REDIS_REPLY_STATUS); @@ -55,9 +52,6 @@ void RedisClient::hmset(const string &key, const vector &values void RedisClient::hmset(const string &key, const std::map &vmap) { - if (vmap.empty()) - return; - vector values; for(const auto it:vmap) { From b1f270e94702f3458697946f62d8c54fc6506214 Mon Sep 17 00:00:00 2001 From: Jipan Yang Date: Thu, 19 Jul 2018 16:57:04 -0700 Subject: [PATCH 07/10] For RedisClient exists, make sure no space or tab in key Signed-off-by: Jipan Yang --- common/redisclient.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common/redisclient.cpp b/common/redisclient.cpp index ae69d34d9..9b15ca8be 100644 --- a/common/redisclient.cpp +++ b/common/redisclient.cpp @@ -23,6 +23,11 @@ int64_t RedisClient::del(const string &key) bool RedisClient::exists(const string &key) { RedisCommand rexists; + if (key.find_first_of(" \t") != string::npos) + { + SWSS_LOG_ERROR("EXISTS failed, invalid space or tab in single key: %s", key.c_str()); + throw runtime_error("EXISTS failed, invalid space or tab in single key"); + } rexists.format("EXISTS %s", key.c_str()); RedisReply r(m_db, rexists, REDIS_REPLY_INTEGER); return (r.getContext()->integer > 0); From dc7f42d0bc4e18e879083728a02dd403f392c8ea Mon Sep 17 00:00:00 2001 From: Qi Luo Date: Fri, 20 Jul 2018 00:25:22 +0000 Subject: [PATCH 08/10] Implement template hgetall Signed-off-by: Qi Luo --- common/redisclient.cpp | 20 +++------ common/redisclient.h | 4 +- tests/redis_ut.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 14 deletions(-) diff --git a/common/redisclient.cpp b/common/redisclient.cpp index 9b15ca8be..4b0f289c2 100644 --- a/common/redisclient.cpp +++ b/common/redisclient.cpp @@ -77,20 +77,13 @@ void RedisClient::set(const string &key, const string &value) unordered_map RedisClient::hgetall(const string &key) { - RedisCommand sincr; - sincr.format("HGETALL %s", key.c_str()); - RedisReply r(m_db, sincr, REDIS_REPLY_ARRAY); - - auto ctx = r.getContext(); - unordered_map map; - for (unsigned int i = 0; i < ctx->elements; i += 2) - map.emplace(ctx->element[i]->str, ctx->element[i+1]->str); - + hgetall(key, std::inserter(map, map.end())); return map; } -std::map RedisClient::hgetallordered(const std::string &key) +template +void RedisClient::hgetall(const std::string &key, OutputIterator result) { RedisCommand sincr; sincr.format("HGETALL %s", key.c_str()); @@ -100,9 +93,10 @@ std::map RedisClient::hgetallordered(const std::string map map; for (unsigned int i = 0; i < ctx->elements; i += 2) - map.emplace(ctx->element[i]->str, ctx->element[i+1]->str); - - return map; + { + *result = std::make_pair(ctx->element[i]->str, ctx->element[i+1]->str); + ++result; + } } vector RedisClient::keys(const string &key) diff --git a/common/redisclient.h b/common/redisclient.h index 844b75c11..438449180 100644 --- a/common/redisclient.h +++ b/common/redisclient.h @@ -31,7 +31,9 @@ class RedisClient int64_t hdel(const std::string &key, const std::string &field); std::unordered_map hgetall(const std::string &key); - std::map hgetallordered(const std::string &key); + + template + void hgetall(const std::string &key, OutputIterator result); std::vector keys(const std::string &key); diff --git a/tests/redis_ut.cpp b/tests/redis_ut.cpp index 2ab8ad32a..6bf16929f 100644 --- a/tests/redis_ut.cpp +++ b/tests/redis_ut.cpp @@ -12,6 +12,7 @@ #include "common/selectableevent.h" #include "common/selectabletimer.h" #include "common/table.h" +#include "common/redisclient.h" using namespace std; using namespace swss; @@ -243,6 +244,103 @@ void TableBasicTest(string tableName) cout << "Done." << endl; } +TEST(DBConnector, RedisClient) +{ + DBConnector db(TEST_DB, "localhost", 6379, 0); + + RedisClient redic(&db); + + clearDB(); + cout << "Starting table manipulations" << endl; + + string key_1 = "a"; + string key_2 = "b"; + vector values; + + for (int i = 1; i < 4; i++) + { + string field = "field_" + to_string(i); + string value = to_string(i); + values.push_back(make_pair(field, value)); + } + + cout << "- Step 1. SET" << endl; + cout << "Set key [a] field_1:1 field_2:2 field_3:3" << endl; + cout << "Set key [b] field_1:1 field_2:2 field_3:3" << endl; + + redic.hmset(key_1, values); + redic.hmset(key_2, values); + + cout << "- Step 2. GET_TABLE_KEYS" << endl; + auto keys = redic.keys("*"); + EXPECT_EQ(keys.size(), (size_t)2); + + for (auto k : keys) + { + cout << "Get key [" << k << "]" << flush; + EXPECT_EQ(k.length(), (size_t)1); + } + + cout << "- Step 3. GET_TABLE_CONTENT" << endl; + + for (auto k : keys) + { + cout << "Get key [" << k << "]" << flush; + auto fvs = redic.hgetall(k); + unsigned int size_v = 3; + EXPECT_EQ(fvs.size(), size_v); + for (auto fv: fvs) + { + string value_1 = "1", value_2 = "2"; + cout << " " << fvField(fv) << ":" << fvValue(fv) << flush; + if (fvField(fv) == "field_1") + { + EXPECT_EQ(fvValue(fv), value_1); + } + if (fvField(fv) == "field_2") + { + EXPECT_EQ(fvValue(fv), value_2); + } + } + cout << endl; + } + + cout << "- Step 4. DEL" << endl; + cout << "Delete key [a]" << endl; + redic.del(key_1); + + cout << "- Step 5. GET" << endl; + cout << "Get key [a] and key [b]" << endl; + auto fvs = redic.hgetall(key_1); + EXPECT_TRUE(fvs.empty()); + fvs = redic.hgetall(key_2); + + cout << "Get key [b]" << flush; + for (auto fv: fvs) + { + string value_1 = "1", value_2 = "2"; + cout << " " << fvField(fv) << ":" << fvValue(fv) << flush; + if (fvField(fv) == "field_1") + { + EXPECT_EQ(fvValue(fv), value_1); + } + if (fvField(fv) == "field_2") + { + EXPECT_EQ(fvValue(fv), value_2); + } + } + cout << endl; + + cout << "- Step 6. DEL and GET_TABLE_CONTENT" << endl; + cout << "Delete key [b]" << endl; + redic.del(key_2); + fvs = redic.hgetall(key_2); + + EXPECT_TRUE(fvs.empty()); + + cout << "Done." << endl; +} + TEST(DBConnector, test) { thread *producerThreads[NUMBER_OF_THREADS]; From 58dacddcb05b17f27b23bde8d4853a9dc6f664d1 Mon Sep 17 00:00:00 2001 From: Qi Luo Date: Fri, 20 Jul 2018 01:52:29 +0000 Subject: [PATCH 09/10] Implement template shmset.formatHMSET() Signed-off-by: Qi Luo --- common/redisclient.cpp | 10 ++-------- common/rediscommand.cpp | 16 ++-------------- common/rediscommand.h | 20 ++++++++++++++++++++ common/table.cpp | 2 +- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/common/redisclient.cpp b/common/redisclient.cpp index 4b0f289c2..da218629c 100644 --- a/common/redisclient.cpp +++ b/common/redisclient.cpp @@ -51,20 +51,14 @@ void RedisClient::hset(const string &key, const string &field, const string &val void RedisClient::hmset(const string &key, const vector &values) { RedisCommand shmset; - shmset.formatHMSET(key, values); + shmset.formatHMSET(key, values.begin(), values.end()); RedisReply r(m_db, shmset, REDIS_REPLY_STATUS); } void RedisClient::hmset(const string &key, const std::map &vmap) { - vector values; - for(const auto it:vmap) - { - values.emplace_back(it.first, it.second); - } - RedisCommand shmset; - shmset.formatHMSET(key, values); + shmset.formatHMSET(key, vmap.begin(), vmap.end()); RedisReply r(m_db, shmset, REDIS_REPLY_STATUS); } diff --git a/common/rediscommand.cpp b/common/rediscommand.cpp index 10d96c7d1..8477f0ab6 100644 --- a/common/rediscommand.cpp +++ b/common/rediscommand.cpp @@ -37,23 +37,11 @@ void RedisCommand::formatArgv(int argc, const char **argv, const size_t *argvlen } } - /* Format HMSET key multiple field value command */ +/* Format HMSET key multiple field value command */ void RedisCommand::formatHMSET(const std::string &key, const std::vector &values) { - if (values.empty()) throw std::invalid_argument("empty values"); - - const char* cmd = "HMSET"; - - std::vector args = { cmd, key.c_str() }; - - for (const auto &fvt: values) - { - args.push_back(fvField(fvt).c_str()); - args.push_back(fvValue(fvt).c_str()); - } - - formatArgv((int)args.size(), args.data(), NULL); + formatHMSET(key, values.begin(), values.end()); } /* Format HSET key field value command */ diff --git a/common/rediscommand.h b/common/rediscommand.h index a76636ed6..9d7d0a5ee 100644 --- a/common/rediscommand.h +++ b/common/rediscommand.h @@ -24,9 +24,29 @@ class RedisCommand { void formatArgv(int argc, const char **argv, const size_t *argvlen); /* Format HMSET key multiple field value command */ + __attribute__((deprecated)) void formatHMSET(const std::string &key, const std::vector &values); + template + void formatHMSET(const std::string &key, + InputIterator start, InputIterator stop) + { + if (start == stop) throw std::invalid_argument("empty values"); + + const char* cmd = "HMSET"; + + std::vector args = { cmd, key.c_str() }; + + for (auto i = start; i != stop; i++) + { + args.push_back(fvField(*i).c_str()); + args.push_back(fvValue(*i).c_str()); + } + + formatArgv((int)args.size(), args.data(), NULL); + } + /* Format HSET key field value command */ void formatHSET(const std::string& key, const std::string& field, const std::string& value); diff --git a/common/table.cpp b/common/table.cpp index 9f251fca7..cf01e0cfe 100644 --- a/common/table.cpp +++ b/common/table.cpp @@ -92,7 +92,7 @@ void Table::set(const string &key, const vector &values, return; RedisCommand cmd; - cmd.formatHMSET(getKeyName(key), values); + cmd.formatHMSET(getKeyName(key), values.begin(), values.end()); m_pipe->push(cmd, REDIS_REPLY_STATUS); if (!m_buffered) From 0d24fd3874ac2e0e110f74e8c119bdd1697ad69e Mon Sep 17 00:00:00 2001 From: Qi Luo Date: Fri, 20 Jul 2018 11:38:47 -0700 Subject: [PATCH 10/10] Fix build (#3) * Fix swig compile Signed-off-by: Qi Luo * Fix: implement template function in header filese Signed-off-by: Qi Luo * Remove unused variable Signed-off-by: Qi Luo * Implement template hmset Signed-off-by: Qi Luo --- common/redisclient.cpp | 31 ------------------------------- common/redisclient.h | 29 ++++++++++++++++++++++++++--- common/rediscommand.h | 38 ++++++++++++++++++++++---------------- tests/redis_ut.cpp | 4 ++-- 4 files changed, 50 insertions(+), 52 deletions(-) diff --git a/common/redisclient.cpp b/common/redisclient.cpp index da218629c..30b745ab0 100644 --- a/common/redisclient.cpp +++ b/common/redisclient.cpp @@ -48,20 +48,6 @@ void RedisClient::hset(const string &key, const string &field, const string &val RedisReply r(m_db, shset, REDIS_REPLY_INTEGER); } -void RedisClient::hmset(const string &key, const vector &values) -{ - RedisCommand shmset; - shmset.formatHMSET(key, values.begin(), values.end()); - RedisReply r(m_db, shmset, REDIS_REPLY_STATUS); -} - -void RedisClient::hmset(const string &key, const std::map &vmap) -{ - RedisCommand shmset; - shmset.formatHMSET(key, vmap.begin(), vmap.end()); - RedisReply r(m_db, shmset, REDIS_REPLY_STATUS); -} - void RedisClient::set(const string &key, const string &value) { RedisCommand sset; @@ -76,23 +62,6 @@ unordered_map RedisClient::hgetall(const string &key) return map; } -template -void RedisClient::hgetall(const std::string &key, OutputIterator result) -{ - RedisCommand sincr; - sincr.format("HGETALL %s", key.c_str()); - RedisReply r(m_db, sincr, REDIS_REPLY_ARRAY); - - auto ctx = r.getContext(); - - map map; - for (unsigned int i = 0; i < ctx->elements; i += 2) - { - *result = std::make_pair(ctx->element[i]->str, ctx->element[i+1]->str); - ++result; - } -} - vector RedisClient::keys(const string &key) { RedisCommand skeys; diff --git a/common/redisclient.h b/common/redisclient.h index 438449180..e35699549 100644 --- a/common/redisclient.h +++ b/common/redisclient.h @@ -45,9 +45,8 @@ class RedisClient void mset(const std::unordered_map &map); - void hmset(const std::string &key, const std::unordered_map &map); - void hmset(const std::string &key, const std::vector &values); - void hmset(const std::string &key, const std::map &vmap); + template + void hmset(const std::string &key, InputIterator start, InputIterator stop); std::shared_ptr get(const std::string &key); @@ -69,6 +68,30 @@ class RedisClient swss::DBConnector *m_db; }; +template +void RedisClient::hgetall(const std::string &key, OutputIterator result) +{ + RedisCommand sincr; + sincr.format("HGETALL %s", key.c_str()); + RedisReply r(m_db, sincr, REDIS_REPLY_ARRAY); + + auto ctx = r.getContext(); + + for (unsigned int i = 0; i < ctx->elements; i += 2) + { + *result = std::make_pair(ctx->element[i]->str, ctx->element[i+1]->str); + ++result; + } +} + +template +void RedisClient::hmset(const std::string &key, InputIterator start, InputIterator stop) +{ + RedisCommand shmset; + shmset.formatHMSET(key, start, stop); + RedisReply r(m_db, shmset, REDIS_REPLY_STATUS); +} + } #endif // __REDISCLIENT_H__ diff --git a/common/rediscommand.h b/common/rediscommand.h index 9d7d0a5ee..1abfb2902 100644 --- a/common/rediscommand.h +++ b/common/rediscommand.h @@ -24,28 +24,15 @@ class RedisCommand { void formatArgv(int argc, const char **argv, const size_t *argvlen); /* Format HMSET key multiple field value command */ +#ifndef SWIG __attribute__((deprecated)) +#endif void formatHMSET(const std::string &key, const std::vector &values); template void formatHMSET(const std::string &key, - InputIterator start, InputIterator stop) - { - if (start == stop) throw std::invalid_argument("empty values"); - - const char* cmd = "HMSET"; - - std::vector args = { cmd, key.c_str() }; - - for (auto i = start; i != stop; i++) - { - args.push_back(fvField(*i).c_str()); - args.push_back(fvValue(*i).c_str()); - } - - formatArgv((int)args.size(), args.data(), NULL); - } + InputIterator start, InputIterator stop); /* Format HSET key field value command */ void formatHSET(const std::string& key, const std::string& field, @@ -65,4 +52,23 @@ class RedisCommand { char *temp; }; +template +void RedisCommand::formatHMSET(const std::string &key, + InputIterator start, InputIterator stop) +{ + if (start == stop) throw std::invalid_argument("empty values"); + + const char* cmd = "HMSET"; + + std::vector args = { cmd, key.c_str() }; + + for (auto i = start; i != stop; i++) + { + args.push_back(fvField(*i).c_str()); + args.push_back(fvValue(*i).c_str()); + } + + formatArgv((int)args.size(), args.data(), NULL); +} + } diff --git a/tests/redis_ut.cpp b/tests/redis_ut.cpp index 6bf16929f..1d8f8591f 100644 --- a/tests/redis_ut.cpp +++ b/tests/redis_ut.cpp @@ -268,8 +268,8 @@ TEST(DBConnector, RedisClient) cout << "Set key [a] field_1:1 field_2:2 field_3:3" << endl; cout << "Set key [b] field_1:1 field_2:2 field_3:3" << endl; - redic.hmset(key_1, values); - redic.hmset(key_2, values); + redic.hmset(key_1, values.begin(), values.end()); + redic.hmset(key_2, values.begin(), values.end()); cout << "- Step 2. GET_TABLE_KEYS" << endl; auto keys = redic.keys("*");