summaryrefslogtreecommitdiff
path: root/hiredis.c
diff options
context:
space:
mode:
authorJan-Erik Rediger <janerik@fnordig.de>2015-04-16 19:28:12 +0200
committerJan-Erik Rediger <janerik@fnordig.de>2015-04-16 21:00:30 +0200
commitd9e0b0f6abfbb8918f73607bdfcc707d0df3fd41 (patch)
tree18a642cfca4697e0349767238ddf6d6ff368ea38 /hiredis.c
parentb872919463fbc04c3a8fde113cb9ae89dfcb3859 (diff)
Implement a reconnect method for the client context
Originally implemented by @abedra as part of #306. In case a write or read times out, we force an error state, because we can't guarantuee that the next read will get the right data. Instead we need to reconnect to have a clean-state connection, which is now easily possible with this method.
Diffstat (limited to 'hiredis.c')
-rw-r--r--hiredis.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/hiredis.c b/hiredis.c
index d2b6103..6e8ad3b 100644
--- a/hiredis.c
+++ b/hiredis.c
@@ -598,6 +598,10 @@ static redisContext *redisContextInit(void) {
c->errstr[0] = '\0';
c->obuf = sdsempty();
c->reader = redisReaderCreate();
+ c->tcp.host = NULL;
+ c->tcp.source_addr = NULL;
+ c->unix.path = NULL;
+ c->timeout = NULL;
if (c->obuf == NULL || c->reader == NULL) {
redisFree(c);
@@ -616,6 +620,14 @@ void redisFree(redisContext *c) {
sdsfree(c->obuf);
if (c->reader != NULL)
redisReaderFree(c->reader);
+ if (c->tcp.host)
+ free(c->tcp.host);
+ if (c->tcp.source_addr)
+ free(c->tcp.source_addr);
+ if (c->unix.path)
+ free(c->unix.path);
+ if (c->timeout)
+ free(c->timeout);
free(c);
}
@@ -626,6 +638,34 @@ int redisFreeKeepFd(redisContext *c) {
return fd;
}
+int redisReconnect(redisContext *c) {
+ c->err = 0;
+ memset(c->errstr, '\0', strlen(c->errstr));
+
+ if (c->fd > 0) {
+ close(c->fd);
+ }
+
+ sdsfree(c->obuf);
+ redisReaderFree(c->reader);
+
+ c->obuf = sdsempty();
+ c->reader = redisReaderCreate();
+
+ if (c->connection_type == REDIS_CONN_TCP) {
+ return redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port,
+ c->timeout, c->tcp.source_addr);
+ } else if (c->connection_type == REDIS_CONN_UNIX) {
+ return redisContextConnectUnix(c, c->unix.path, c->timeout);
+ } else {
+ /* Something bad happened here and shouldn't have. There isn't
+ enough information in the context to reconnect. */
+ __redisSetError(c,REDIS_ERR_OTHER,"Not enough information to reconnect");
+ }
+
+ return REDIS_ERR;
+}
+
/* Connect to a Redis instance. On error the field error in the returned
* context will be set to the return value of the error function.
* When no set of reply functions is given, the default set will be used. */