hiredis C库调用的工具会话类封装。

调用函数:

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);
	}
}

你可能感兴趣的:(C/C++,c语言,bootstrap,开发语言)