diff --git a/common/consumertable.cpp b/common/consumertable.cpp index 4935371d44..c3ed28ab74 100644 --- a/common/consumertable.cpp +++ b/common/consumertable.cpp @@ -85,29 +85,6 @@ void ConsumerTable::pop(KeyOpFieldsValuesTuple &kco) kco = std::make_tuple(key, op, fieldsValues); } -bool ConsumerTable::peek(std::string key, vector &values) -{ - string hgetall_key("HGETALL "); - hgetall_key += getKeyName(key); - - RedisReply r(m_db, hgetall_key, REDIS_REPLY_ARRAY); - redisReply *reply = r.getContext(); - values.clear(); - - if (!reply->elements) - return false; - - if (reply->elements & 1) - throw system_error(make_error_code(errc::address_not_available), - "Unable to connect netlink socket"); - - for (unsigned int i = 0; i < reply->elements; i += 2) - values.push_back(make_tuple(reply->element[i]->str, - reply->element[i + 1]->str)); - - return true; -} - void ConsumerTable::addFd(fd_set *fd) { FD_SET(m_subscribe->getContext()->fd, fd); diff --git a/common/consumertable.h b/common/consumertable.h index 8c7701a6d2..59deed1d20 100644 --- a/common/consumertable.h +++ b/common/consumertable.h @@ -20,10 +20,6 @@ class ConsumerTable : public Table, public Selectable /* Get a singlesubsribe channel rpop */ void pop(KeyOpFieldsValuesTuple &kco); - /* Get a key content without poping it from the notificaiton list */ - /* return false if the key doesn't exists */ - bool peek(std::string key, std::vector &values); - virtual void addFd(fd_set *fd); virtual bool isMe(fd_set *fd); virtual int readCache(); diff --git a/common/producertable.cpp b/common/producertable.cpp index 5b6fa1cba6..603c298c5a 100644 --- a/common/producertable.cpp +++ b/common/producertable.cpp @@ -46,16 +46,9 @@ void ProducerTable::set(string key, vector &values, string op) { multi(); for (FieldValueTuple &i : values) - { - char *temp; - int len = redisFormatCommand(&temp, "HSET %s %s %s", - getKeyName(key).c_str(), - fvField(i).c_str(), - fvValue(i).c_str()); - string hset(temp, len); - free(temp); - enqueue(hset, REDIS_REPLY_INTEGER, true); - } + enqueue(formatHSET(getKeyName(key), fvField(i), fvValue(i)), + REDIS_REPLY_INTEGER, true); + enqueueDbChange(key, JSon::buildJson(values), op); exec(); } diff --git a/common/producertable.h b/common/producertable.h index 99951bfd9c..7f7a870ce5 100644 --- a/common/producertable.h +++ b/common/producertable.h @@ -16,9 +16,10 @@ class ProducerTable : public Table public: ProducerTable(DBConnector *db, std::string tableName); - void set(std::string key, std::vector &values, - std::string op = SET_COMMAND); - void del(std::string key, std::string op = DEL_COMMAND); + /* Implements set() and del() commands using notification messages */ + virtual void set(std::string key, std::vector &values, + std::string op = SET_COMMAND); + virtual void del(std::string key, std::string op = DEL_COMMAND); private: /* Disable copy-constructor and operator = */ diff --git a/common/table.cpp b/common/table.cpp index 08f48121a1..86cd97c171 100644 --- a/common/table.cpp +++ b/common/table.cpp @@ -40,6 +40,49 @@ string Table::getChannelTableName() return m_tableName + "_CHANNEL"; } +bool Table::get(std::string key, vector &values) +{ + string hgetall_key("HGETALL "); + hgetall_key += getKeyName(key); + + RedisReply r(m_db, hgetall_key, REDIS_REPLY_ARRAY); + redisReply *reply = r.getContext(); + values.clear(); + + if (!reply->elements) + return false; + + if (reply->elements & 1) + throw system_error(make_error_code(errc::address_not_available), + "Unable to connect netlink socket"); + + for (unsigned int i = 0; i < reply->elements; i += 2) + values.push_back(make_tuple(reply->element[i]->str, + reply->element[i + 1]->str)); + + return true; +} + +void Table::set(std::string key, std::vector &values, + std::string /*op*/) +{ + /* We are doing transaction for AON (All or nothing) */ + multi(); + for (FieldValueTuple &i : values) + enqueue(formatHSET(getKeyName(key), fvField(i), fvValue(i)), + REDIS_REPLY_INTEGER, true); + + exec(); +} + +void Table::del(std::string key, std::string /* op */) +{ + RedisReply r(m_db, string("DEL ") + getKeyName(key), REDIS_REPLY_INTEGER); + if (r.getContext()->type != REDIS_REPLY_INTEGER) + throw system_error(make_error_code(errc::io_error), + "DEL operation failed"); +} + void Table::multi() { while (!m_expectedResults.empty()) @@ -110,4 +153,17 @@ void Table::enqueue(std::string command, int exepectedResult, bool isFormatted) m_expectedResults.push(exepectedResult); } +string Table::formatHSET(const string& key, const string& field, + const string& value) +{ + char *temp; + int len = redisFormatCommand(&temp, "HSET %s %s %s", + key.c_str(), + field.c_str(), + value.c_str()); + string hset(temp, len); + free(temp); + return hset; +} + } diff --git a/common/table.h b/common/table.h index b67bff52b8..78d9893624 100644 --- a/common/table.h +++ b/common/table.h @@ -20,9 +20,20 @@ typedef std::tuple > KeyO #define kfvFieldsValues std::get<2> class Table { -protected: +public: Table(DBConnector *db, std::string tableName); + /* Read a value from the DB directly */ + /* Returns false if the key doesn't exists */ + bool get(std::string key, std::vector &values); + + /* Set an entry in the DB directly (op not in used) */ + virtual void set(std::string key, std::vector &values, + std::string op = ""); + /* Delete an entry in the DB directly (op not in used) */ + virtual void del(std::string key, std::string op = ""); + +protected: /* Return the actual key name as a comibation of tableName:key */ std::string getKeyName(std::string key); @@ -41,6 +52,11 @@ class Table { redisReply* queueResultsFront(); void queueResultsPop(); + /* Format HSET key field value command */ + static std::string formatHSET(const std::string &key, + const std::string &field, + const std::string &value); + DBConnector *m_db; std::string m_tableName; diff --git a/portsyncd/linksync.cpp b/portsyncd/linksync.cpp index 42f3fa6e0b..fd9aeb9c78 100644 --- a/portsyncd/linksync.cpp +++ b/portsyncd/linksync.cpp @@ -52,11 +52,11 @@ void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj) fvVector.push_back(o); fvVector.push_back(m); - if (m_lagTableConsumer.peek(key, temp)) + if (m_lagTableConsumer.get(key, temp)) m_lagTableProducer.set(key, fvVector); - else if (m_vlanTableConsumer.peek(key, temp)) + else if (m_vlanTableConsumer.get(key, temp)) m_vlanTableProducer.set(key, fvVector); - else if (m_portTableConsumer.peek(key, temp)) + else if (m_portTableConsumer.get(key, temp)) m_portTableProducer.set(key, fvVector); /* else discard managment or untracked netdev state */ } diff --git a/portsyncd/linksync.h b/portsyncd/linksync.h index 85b21699a3..e3578f95f9 100644 --- a/portsyncd/linksync.h +++ b/portsyncd/linksync.h @@ -3,7 +3,6 @@ #include "common/dbconnector.h" #include "common/producertable.h" -#include "common/consumertable.h" #include "common/netmsg.h" namespace swss { @@ -19,7 +18,7 @@ class LinkSync : public NetMsg private: ProducerTable m_portTableProducer, m_vlanTableProducer, m_lagTableProducer; - ConsumerTable m_portTableConsumer, m_vlanTableConsumer, m_lagTableConsumer; + Table m_portTableConsumer, m_vlanTableConsumer, m_lagTableConsumer; }; }