调用函数:
int32_t seasonId = 0;
{
pRedisSession->commandF("HGET {} season_id", strArenaConfig);
RedisReply r(pRedisSession->getReply());
if (r.isString())
{
auto buffer = r.getString();
seasonId = std::atoi(buffer.c_str());
}
}
头文件:
#pragma once
#include "prerequisites.h"
#include
class RedisReply
{
public:
explicit RedisReply(redisReply* r);
~RedisReply() = default;
void copy(redisReply* r);
int getType() const { return m_type; }
bool isNil() { return m_type == REDIS_REPLY_NIL; }
bool isError() { return m_type == REDIS_REPLY_ERROR; }
bool isStatus() { return m_type == REDIS_REPLY_STATUS; }
bool isString() { return m_type == REDIS_REPLY_STRING; }
bool isInteger() { return m_type == REDIS_REPLY_INTEGER; }
bool isArray() { return m_type == REDIS_REPLY_ARRAY; }
int64_t getInteger() { return m_integer; }
std::string getString() { return m_string; }
int sizeElement() { return (int)m_element.size(); }
RedisReply* getElement(int index);
private:
int m_type;
int64_t m_integer;
std::string m_string;
std::vector m_element;
};
class RedisSession : private boost::noncopyable
{
public:
RedisSession();
virtual ~RedisSession();
virtual void initialize(const std::string& hostName, uint16_t port, int dbnum, const std::string& password, float connectimeout);
virtual bool connect();
bool isValid();
void close();
void freeReply();
void command(const char* cmd);
void commandArgv(int argc, const char** argv, const size_t* argvlen);
template
void commandF(std::string_view fmt, Args&&... args)
{
try
{
std::string strCmd = fmt::format(fmt, std::forward(args)...);
command(strCmd.c_str());
}
catch (const std::exception& e)
{
assert(false);
printf("commandF err:%s ~~ %s\n", e.what(), fmt.data());
}
}
redisReply* getReply()
{
return m_pReply;
}
protected:
std::string m_hostName;
uint16_t m_port;
int m_dbnum;
std::string m_password;
float m_connectimeout;
redisContext* m_pContext;
redisReply* m_pReply;
};
源文件:
#include "RedisSession.h"
#include "LoggerManager.h"
RedisReply::RedisReply(redisReply* r)
: m_type(REDIS_REPLY_NIL)
, m_integer(0)
{
copy(r);
}
void RedisReply::copy(redisReply* r)
{
if (nullptr == r)
{
m_type = REDIS_REPLY_NIL;
return;
}
m_type = r->type;
switch (m_type)
{
case REDIS_REPLY_NIL:
/* Nothing... */
break;
case REDIS_REPLY_ERROR:
case REDIS_REPLY_STATUS:
case REDIS_REPLY_STRING:
m_string.assign(r->str, r->len);
break;
case REDIS_REPLY_INTEGER:
m_integer = r->integer;
break;
case REDIS_REPLY_ARRAY:
m_element.clear();
for (size_t i = 0; i < r->elements; i++)
{
m_element.push_back(RedisReply(r->element[i]));
}
break;
default:
{
m_type = REDIS_REPLY_ERROR;
m_string = fmt::format("Unknown reply type: {}", r->type);
}
break;
}
}
RedisReply* RedisReply::getElement(int index)
{
int num = m_element.size();
if ((size_t)index >= m_element.size())
return nullptr;
return &m_element[index];
}
//
RedisSession::RedisSession()
: m_port(0)
, m_dbnum(0)
, m_connectimeout(1.5f)
, m_pContext(nullptr)
, m_pReply(nullptr)
{
}
RedisSession::~RedisSession()
{
close();
}
void RedisSession::initialize(const std::string& hostName, uint16_t port, int dbnum, const std::string& password, float connectimeout)
{
m_hostName = hostName;
m_port = (port == 0 ? 6379 : port); // 默认端口
m_dbnum = dbnum;
m_password = password;
m_connectimeout = connectimeout;
}
void RedisSession::close()
{
LOG_INFO(redis, "redis(host={}, port={}, dbnum={}) close", m_hostName, m_port, m_dbnum);
freeReply();
if (m_pContext)
{
redisFree(m_pContext);
m_pContext = nullptr;
}
}
void RedisSession::freeReply()
{
if (m_pReply)
{
freeReplyObject(m_pReply);
m_pReply = nullptr;
}
}
bool RedisSession::isValid()
{
return m_pContext;
}
bool RedisSession::connect()
{
struct timeval tv;
tv.tv_sec = static_cast(m_connectimeout);
tv.tv_usec = static_cast(m_connectimeout * 1000000) % 1000000;
m_pContext = redisConnectWithTimeout(m_hostName.c_str(), m_port, tv);
if (!m_pContext)
{
LOG_ERROR(redis, "redis(host={}, port={}, dbnum={}) connect failed", m_hostName, m_port, m_dbnum);
return false;
}
if (m_pContext->err)
{
LOG_ERROR(redis, "redis(host={}, port={}, dbnum={}) connect failed({}):{}", m_hostName, m_port, m_dbnum, m_pContext->err, m_pContext->errstr);
redisFree(m_pContext);
m_pContext = nullptr;
return false;
}
if (!m_password.empty())
{
m_pReply = (redisReply*)redisCommand(m_pContext, "AUTH %s", m_password.c_str());
if (m_pReply)
{
bool result = true;
if (m_pReply->type == REDIS_REPLY_ERROR) result = false;
freeReplyObject(m_pReply);
m_pReply = nullptr;
if (!result)
{
LOG_ERROR(redis, "redis(host={}, port={}, dbnum={}) auth failed", m_hostName, m_port, m_dbnum);
return false;
}
}
}
if (m_dbnum != 0)
{
m_pReply = (redisReply*)redisCommand(m_pContext, "SELECT %d", m_dbnum);
if (m_pReply)
{
bool result = true;
if (m_pReply->type == REDIS_REPLY_ERROR) result = false;
freeReplyObject(m_pReply);
m_pReply = nullptr;
if (!result)
{
LOG_ERROR(redis, "redis(host={}, port={}, dbnum={}) select dbnum failed", m_hostName, m_port, m_dbnum);
return false;
}
}
}
m_pReply = (redisReply*)redisCommand(m_pContext, "PING");
if (m_pReply)
{
bool result = true;
if (m_pReply->type == REDIS_REPLY_ERROR) result = false;
freeReplyObject(m_pReply);
m_pReply = nullptr;
if (!result)
{
LOG_ERROR(redis, "redis(host={}, port={}, dbnum={}) first ping failed", m_hostName, m_port, m_dbnum);
return false;
}
}
LOG_INFO(redis, "redis(host={}, port={}, dbnum={}) connect ok", m_hostName, m_port, m_dbnum);
return true;
}
void RedisSession::command(const char* cmd)
{
if (m_pContext)
{
freeReply();
m_pReply = (redisReply*)redisCommand(m_pContext, cmd);
}
if (m_pReply == nullptr || m_pContext == nullptr)
{
// 连接断开立即重连一次
close();
if (!connect())
{
return;
}
m_pReply = (redisReply*)redisCommand(m_pContext, cmd);
}
}
void RedisSession::commandArgv(int argc, const char** argv, const size_t* argvlen)
{
assert(argc > 0);
if (m_pContext)
{
freeReply();
m_pReply = (redisReply*)redisCommandArgv(m_pContext, argc, argv, argvlen);
}
if (m_pReply == nullptr || m_pContext == nullptr)
{
// 连接断开立即重连一次
close();
if (!connect())
{
return;
}
m_pReply = (redisReply*)redisCommandArgv(m_pContext, argc, argv, argvlen);
}
}