common/redistran.cpp (84 lines of code) (raw):
#include "redistran.h"
#include "dbconnector.h"
namespace swss {
RedisTransactioner::RedisTransactioner(DBConnector *db) : m_db(db)
{
}
RedisTransactioner::~RedisTransactioner()
{
clearResults();
}
/* Start a transaction */
void RedisTransactioner::multi()
{
m_expectedResults.clear();
RedisReply r(m_db, "MULTI", REDIS_REPLY_STATUS);
r.checkStatusOK();
}
/* Execute a transaction and get results */
bool RedisTransactioner::exec()
{
using namespace std;
RedisReply r(m_db, "EXEC");
redisReply *reply = r.getContext();
size_t size = reply->elements;
// if meet error in transaction
if (reply->type != REDIS_REPLY_ARRAY)
{
return false;
}
if (size != m_expectedResults.size())
throw system_error(make_error_code(errc::io_error),
"Got to different number of answers!");
clearResults();
for (unsigned int i = 0; i < size; i++)
{
int expectedType = m_expectedResults.front();
m_expectedResults.pop_front();
if (expectedType != reply->element[i]->type)
{
SWSS_LOG_ERROR("Expected to get redis type %d got type %d",
expectedType, reply->element[i]->type);
throw system_error(make_error_code(errc::io_error),
"Got unexpected result");
}
}
for (size_t i = 0; i < size; i++)
m_results.push_back(reply->element[i]);
/* Free only the array memory */
r.release();
free(reply->element);
free(reply);
return true;
}
/* Send a command within a transaction */
void RedisTransactioner::enqueue(const std::string& command, int expectedType)
{
RedisReply r(m_db, command, REDIS_REPLY_STATUS);
r.checkStatusQueued();
m_expectedResults.push_back(expectedType);
}
void RedisTransactioner::enqueue(const RedisCommand& command, int expectedType)
{
RedisReply r(m_db, command, REDIS_REPLY_STATUS);
r.checkStatusQueued();
m_expectedResults.push_back(expectedType);
}
redisReply *RedisTransactioner::dequeueReply()
{
if (m_results.empty())
{
return NULL;
}
redisReply *ret = m_results.front();
m_results.pop_front();
return ret;
}
void RedisTransactioner::clearResults()
{
if (m_results.empty())
{
return;
}
for (const auto& r: m_results)
{
freeReplyObject(r);
}
m_results.clear();
}
}