The work requires a simple encapsulation of the Hiredis to enable the function:
1, the API is unified, external only provide an interface;
2, the shielding upper layer application to the connection details processing;
3, the bottom of the queue to maintain the connection pool, save the connection session;
4, re-connect the use of time-stamp control, every time (3s) to re-connect once, to prevent frequent retries caused by unnecessary waste.
Let's take a look at Hiredis's common data structures and APIs:
hiredis/hiredis.h/* Context for a connection to Redis */typedef struct Rediscontext {int err;/* Error flags, 0 when There is no error */char errstr[128]; /* String representation of error when applicable */int fd; int flags; Char *obuf; /* Write buffer */Redisreader *reader; /* Protocol reader */} rediscontext;/* The Reply object returned by Rediscommand () */#define REDIS_REPLY_STRING # Define Redis_reply_array 2#define Redis_reply_integer 3#define redis_reply_nil 4#define REDIS_REPLY_STATUS 5#define Redis_reply_error 6typedef struct redisreply {int type;/* redis_reply_* */long long integer;/* The Integer when Type is Redis_reply_integer */int len; /* Length of String */char *str; /* used for both redis_reply_error and redis_reply_string */size_t elements; /* Number of elements, for Redis_reply_array */struct redisreply **element; /* Elements vector for Redis_reply_array */} redisreply;rediscontext *redisconnectwithtimeout (conSt Char *ip, int port, struct timeval TV), void Redisfree (Rediscontext *c);//issue a command to Redis, NULL if error, other Wise replyvoid *rediscommand (rediscontext *c, const char *format, ...); * Function to free the reply objects Hiredis returns by default. */void freereplyobject (void *reply);
The following directly on the encapsulated code:
Class kgredisclient{public:kgredisclient (string ip, int port, int timeout = 2000); Virtual ~kgredisclient (); BOOL Executecmd (const char *cmd, string &response); redisreply* executecmd (const char *cmd);p rivate:int m_timeout; int m_serverport; String M_setverip; CCriticalSection M_lock; Std::queue<rediscontext *> m_clients; time_t M_begininvalidtime; static const int m_maxreconnectinterval = 3; rediscontext* Createcontext (); void Releasecontext (Rediscontext *ctx, bool active); BOOL CheckStatus (Rediscontext *ctx);}; Kgredisclient::kgredisclient (string ip, int port, int timeout) {m_timeout = timeout; M_serverport = port; M_setverip = IP; M_begininvalidtime = 0;} Kgredisclient::~kgredisclient () {Cautolock autolock (m_lock); while (!m_clients.empty ()) {Rediscontext *ctx = M_clients.front (); Redisfree (CTX); M_clients.pop (); }}bool kgredisclient::executecmd (const char *cmd, string &response) { Redisreply *reply = executecmd (cmd); if (reply = = NULL) return false; Boost::shared_ptr<redisreply> Autofree (reply, freereplyobject); if (Reply->type = = Redis_reply_integer) {response = _inttostra (Reply->integer); return true; } else if (Reply->type = = redis_reply_string) {response.assign (reply->str, Reply->len); return true; } else if (Reply->type = = redis_reply_status) {response.assign (reply->str, Reply->len); return true; } else if (Reply->type = = Redis_reply_nil) {response = ""; return true; } else if (Reply->type = = Redis_reply_error) {response.assign (reply->str, Reply->len); return false; } else if (Reply->type = = Redis_reply_array) {response = "not a support ARRAY Result!!!"; return false; } else {response = "undefine Reply Type"; return false; }}redisreply* kgredisclient:: Executecmd (const char *cmd) {Rediscontext *ctx = Createcontext (); if (CTX = = null) return null; Redisreply *reply = (redisreply*) rediscommand (CTX, CMD); Releasecontext (CTX, reply! = NULL); return reply;} rediscontext* Kgredisclient::createcontext () {{Cautolock autolock (m_lock); if (!m_clients.empty ()) {Rediscontext *ctx = M_clients.front (); M_clients.pop (); return CTX; }} time_t now = time (NULL); if (now < M_begininvalidtime + m_maxreconnectinterval) return NULL; struct Timeval TV; Tv.tv_sec = m_timeout/1000; tv.tv_usec = (m_timeout% 1000) * 1000;; Rediscontext *ctx = Redisconnectwithtimeout (M_setverip.c_str (), M_serverport, TV); if (CTX = = NULL | | Ctx->err! = 0) {if (CTX! = null) Redisfree (CTX); M_begininvalidtime = time (NULL); return NULL; } return CTX;} void Kgredisclient::releasecontext (Rediscontext *ctx, bool active) {if (CTX = = NULL) return; if (!active) {redisfree (CTX); return;} Cautolock Autolock (M_lock); M_clients.push (CTX);} BOOL Kgredisclient::checkstatus (Rediscontext *ctx) {redisreply *reply = (redisreply*) rediscommand (CTX, "ping"); if (reply = = NULL) return false; Boost::shared_ptr<redisreply> Autofree (reply, freereplyobject); if (reply->type! = Redis_reply_status) return false; if (strcasecmp (Reply->str, "PONG")! = 0) return false; return true;}
Slightly explained:
Member variable: m_clients is used to save the connection pool.
Member variables: m_begininvalidtime, m_maxreconnectinterval are used to control frequent connections when they are broken off.
External api:executecmd (const char *cmd, string &response);
Redis Client Connection Mode Hiredis Simple package use, connection pooling, shielded connection details