Browse Source

* backend/redis : connection management

master
Alex 'AdUser' Z 8 years ago
parent
commit
6aa251641a
  1. 90
      src/backends/redis.c

90
src/backends/redis.c

@ -37,19 +37,24 @@ static bool
redis_connect(cfg_t *cfg) { redis_connect(cfg_t *cfg) {
assert(cfg != NULL); assert(cfg != NULL);
redisReply *reply; if (cfg->conn && !cfg->conn->err)
struct timeval timeout = { cfg->timeout, 0 }; return true; /* connected */
redisContext *conn = NULL;
redisReply *reply = NULL;
do { do {
cfg->conn = redisConnectWithTimeout(cfg->host, cfg->port, timeout); struct timeval timeout = { cfg->timeout, 0 };
if (cfg->conn->err) { conn = redisConnectWithTimeout(cfg->host, cfg->port, timeout);
if (!conn)
break;
if (conn->err) {
snprintf(cfg->error, sizeof(cfg->error), "Connection error: %s", cfg->conn->errstr); snprintf(cfg->error, sizeof(cfg->error), "Connection error: %s", cfg->conn->errstr);
return false; break;
} }
if (cfg->password[0]) { if (cfg->password[0]) {
reply = redisCommand(cfg->conn, "AUTH %s", cfg->password); reply = redisCommand(cfg->conn, "AUTH %s", cfg->password);
if (reply->type == REDIS_REPLY_ERROR) { if (reply->type == REDIS_REPLY_ERROR) {
snprintf(cfg->error, sizeof(cfg->error), "auth error: %s", reply->str); snprintf(cfg->error, sizeof(cfg->error), "auth error: %s", reply->str);
freeReplyObject(reply);
break; break;
} }
freeReplyObject(reply); freeReplyObject(reply);
@ -58,16 +63,21 @@ redis_connect(cfg_t *cfg) {
reply = redisCommand(cfg->conn, "SELECT %d", cfg->database); reply = redisCommand(cfg->conn, "SELECT %d", cfg->database);
if (reply->type == REDIS_REPLY_ERROR) { if (reply->type == REDIS_REPLY_ERROR) {
snprintf(cfg->error, sizeof(cfg->error), "auth error: %s", reply->str); snprintf(cfg->error, sizeof(cfg->error), "auth error: %s", reply->str);
freeReplyObject(reply);
break; break;
} }
freeReplyObject(reply); freeReplyObject(reply);
} }
if (cfg->conn)
redisFree(cfg->conn);
cfg->conn = conn;
return true; return true;
} while (0); } while (0);
redisFree(cfg->conn); if (conn)
cfg->conn = NULL; redisFree(conn);
if (reply)
freeReplyObject(reply);
return false; return false;
} }
@ -80,13 +90,6 @@ redis_disconnect(cfg_t *cfg) {
return true; return true;
} }
static bool
redis_reconnect(cfg_t *cfg) {
redis_disconnect(cfg);
return redis_connect(cfg);
}
/* handlers */
cfg_t * cfg_t *
create(const char *id) { create(const char *id) {
cfg_t *cfg = NULL; cfg_t *cfg = NULL;
@ -159,8 +162,7 @@ start(cfg_t *cfg) {
if (cfg->shared && usage_inc(cfg->name) > 1) if (cfg->shared && usage_inc(cfg->name) > 1)
return true; return true;
redis_connect(cfg); return redis_connect(cfg);
return false;
} }
bool bool
@ -170,14 +172,16 @@ stop(cfg_t *cfg) {
if (cfg->shared && usage_dec(cfg->name) > 0) if (cfg->shared && usage_dec(cfg->name) > 0)
return true; return true;
redis_disconnect(cfg); return redis_disconnect(cfg);
return true;
} }
bool bool
ban(cfg_t *cfg, const char *ip) { ban(cfg_t *cfg, const char *ip) {
assert(cfg != NULL); assert(cfg != NULL);
if (!redis_connect(cfg))
return false;
redisReply *reply; redisReply *reply;
do { do {
reply = redisCommand(cfg->conn, "HINCRBY %s %s %d", cfg->hash, ip, 1); reply = redisCommand(cfg->conn, "HINCRBY %s %s %d", cfg->hash, ip, 1);
@ -204,6 +208,7 @@ ban(cfg_t *cfg, const char *ip) {
bool bool
unban(cfg_t *cfg, const char *ip) { unban(cfg_t *cfg, const char *ip) {
assert(cfg != NULL); assert(cfg != NULL);
(void)(ip); /* suppress warning for unused variable 'ip' */ (void)(ip); /* suppress warning for unused variable 'ip' */
return true; return true;
} }
@ -212,43 +217,36 @@ bool
check(cfg_t *cfg, const char *ip) { check(cfg_t *cfg, const char *ip) {
assert(cfg != NULL); assert(cfg != NULL);
bool exists; (void)(ip); /* suppress warning for unused variable 'ip' */
redisReply *reply;
do {
reply = redisCommand(cfg->conn, "HEXISTS %s %s", cfg->hash, ip);
if (reply && reply->type == REDIS_REPLY_ERROR) {
snprintf(cfg->error, sizeof(cfg->error), "PUBLISH: %s", reply->str);
break;
}
if (reply && reply->integer == REDIS_REPLY_INTEGER)
exists = reply->integer ? true : false;
freeReplyObject(reply);
return exists;
} while (0);
if (reply)
freeReplyObject(reply);
return false; return false;
} }
bool bool
ping(cfg_t *cfg) { ping(cfg_t *cfg) {
assert(cfg != NULL); assert(cfg != NULL);
redisReply *reply = redisCommand(cfg->conn, "PING");
if (!cfg->conn || cfg->conn->err)
redis_connect(cfg);
if (!cfg->conn)
return false; /* reconnect failure */
if (cfg->conn->err) { if (cfg->conn->err) {
snprintf(cfg->error, sizeof(cfg->error), "connection error: %s", cfg->conn->errstr); snprintf(cfg->error, sizeof(cfg->error), "connection error: %s", cfg->conn->errstr);
redis_reconnect(cfg); return false;
return cfg->conn->err ? false : true;
} }
if (reply && reply->type == REDIS_REPLY_ERROR) {
snprintf(cfg->error, sizeof(cfg->error), "%s", reply->str); redisReply *reply = redisCommand(cfg->conn, "PING");
if (reply) {
bool result = true;
if (reply->type == REDIS_REPLY_ERROR) {
snprintf(cfg->error, sizeof(cfg->error), "%s", reply->str);
result = false;
}
freeReplyObject(reply); freeReplyObject(reply);
return false; return result;
} else {
return false;
} }
return true;
return false;
} }
void void

Loading…
Cancel
Save