From f14bb551a6fbc4ba9605fe02c4f4095b76131abb Mon Sep 17 00:00:00 2001 From: root Date: Wed, 16 May 2018 09:15:26 +0000 Subject: [PATCH 1/6] Add auth support for cluster --- .gitignore | 0 .travis.yml | 0 CHANGELOG.md | 0 COPYING | 0 Makefile | 0 README.md | 8 ++ adapters/ae.h | 0 adapters/glib.h | 0 adapters/libev.h | 0 adapters/libevent.h | 0 adapters/libuv.h | 0 adlist.c | 0 adlist.h | 0 async.c | 0 async.h | 0 command.c | 0 command.h | 0 crc16.c | 0 dict.c | 0 dict.h | 0 examples/example-ae.c | 0 examples/example-glib.c | 0 examples/example-libev.c | 0 examples/example-libevent.c | 0 examples/example-libuv.c | 0 examples/example.c | 0 fmacros.h | 0 hiarray.c | 0 hiarray.h | 0 hircluster.c | 154 +++++++++++++++++++++++++++++++++++- hircluster.h | 7 ++ hiredis.c | 0 hiredis.h | 0 hiutil.c | 0 hiutil.h | 0 net.c | 2 +- net.h | 2 +- read.c | 0 read.h | 0 sds.c | 0 sds.h | 0 test.c | 0 win32.h | 0 43 files changed, 170 insertions(+), 3 deletions(-) mode change 100644 => 100755 .gitignore mode change 100644 => 100755 .travis.yml mode change 100644 => 100755 CHANGELOG.md mode change 100644 => 100755 COPYING mode change 100644 => 100755 Makefile mode change 100644 => 100755 README.md mode change 100644 => 100755 adapters/ae.h mode change 100644 => 100755 adapters/glib.h mode change 100644 => 100755 adapters/libev.h mode change 100644 => 100755 adapters/libevent.h mode change 100644 => 100755 adapters/libuv.h mode change 100644 => 100755 adlist.c mode change 100644 => 100755 adlist.h mode change 100644 => 100755 async.c mode change 100644 => 100755 async.h mode change 100644 => 100755 command.c mode change 100644 => 100755 command.h mode change 100644 => 100755 crc16.c mode change 100644 => 100755 dict.c mode change 100644 => 100755 dict.h mode change 100644 => 100755 examples/example-ae.c mode change 100644 => 100755 examples/example-glib.c mode change 100644 => 100755 examples/example-libev.c mode change 100644 => 100755 examples/example-libevent.c mode change 100644 => 100755 examples/example-libuv.c mode change 100644 => 100755 examples/example.c mode change 100644 => 100755 fmacros.h mode change 100644 => 100755 hiarray.c mode change 100644 => 100755 hiarray.h mode change 100644 => 100755 hircluster.c mode change 100644 => 100755 hircluster.h mode change 100644 => 100755 hiredis.c mode change 100644 => 100755 hiredis.h mode change 100644 => 100755 hiutil.c mode change 100644 => 100755 hiutil.h mode change 100644 => 100755 net.c mode change 100644 => 100755 net.h mode change 100644 => 100755 read.c mode change 100644 => 100755 read.h mode change 100644 => 100755 sds.c mode change 100644 => 100755 sds.h mode change 100644 => 100755 test.c mode change 100644 => 100755 win32.h diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.travis.yml b/.travis.yml old mode 100644 new mode 100755 diff --git a/CHANGELOG.md b/CHANGELOG.md old mode 100644 new mode 100755 diff --git a/COPYING b/COPYING old mode 100644 new mode 100755 diff --git a/Makefile b/Makefile old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 120a7f1..71921c8 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ void redisClusterFree(redisClusterContext *cc); int redisClusterSetOptionAddNode(redisClusterContext *cc, const char *addr); int redisClusterSetOptionAddNodes(redisClusterContext *cc, const char *addrs); +int redisClusterSetOptionSetAuth(redisClusterContext *cc, const char *auth); int redisClusterSetOptionConnectBlock(redisClusterContext *cc); int redisClusterSetOptionConnectNonBlock(redisClusterContext *cc); int redisClusterSetOptionParseSlaves(redisClusterContext *cc); @@ -73,8 +74,11 @@ redisAsyncContext *actx_get_by_node(redisClusterAsyncContext *acc, cluster_node ```c redisClusterContext *redisClusterConnect(const char *addrs, int flags); +redisClusterContext *redisClusterConnectWithAuth(const char *addrs, const char *auth, int flags); redisClusterContext *redisClusterConnectWithTimeout(const char *addrs, const struct timeval tv, int flags); +redisClusterContext *redisClusterConnectWithTimeoutWithAuth(const char *addrs, const char *auth, const struct timeval tv, int flags); redisClusterContext *redisClusterConnectNonBlock(const char *addrs, int flags); +redisClusterContext *redisClusterConnectNonBlockWithAuth(const char *addrs, const char *auth, int flags); void redisClusterFree(redisClusterContext *cc); void redisClusterSetMaxRedirect(redisClusterContext *cc, int max_redirect_count); void *redisClusterFormattedCommand(redisClusterContext *cc, char *cmd, int len); @@ -90,6 +94,7 @@ int redisClusterGetReply(redisClusterContext *cc, void **reply); void redisClusterReset(redisClusterContext *cc); redisClusterAsyncContext *redisClusterAsyncConnect(const char *addrs, int flags); +redisClusterAsyncContext *redisClusterAsyncConnectWithAuth(const char *addrs, const char *auth, int flags); int redisClusterAsyncSetConnectCallback(redisClusterAsyncContext *acc, redisConnectCallback *fn); int redisClusterAsyncSetDisconnectCallback(redisClusterAsyncContext *acc, redisDisconnectCallback *fn); int redisClusterAsyncFormattedCommand(redisClusterAsyncContext *acc, redisClusterCallbackFn *fn, void *privdata, char *cmd, int len); @@ -113,6 +118,7 @@ To consume the synchronous API, there are only a few function calls that need to ```c redisClusterContext *redisClusterContextInit(void); int redisClusterSetOptionAddNodes(redisClusterContext *cc, const char *addrs); +int redisClusterSetOptionSetAuth(redisClusterContext *cc, const char *auth); int redisClusterSetOptionMaxRedirect(redisClusterContext *cc, int max_redirect_count); int redisClusterSetOptionConnectTimeout(redisClusterContext *cc, const struct timeval tv); int redisClusterSetOptionTimeout(redisClusterContext *cc, const struct timeval tv); @@ -125,6 +131,7 @@ void redisClusterFree(redisClusterContext *cc); The function `redisClusterContextInit` is used to create a so-called `redisClusterContext`. The function `redisClusterSetOptionAddNodes` is used to add the redis cluster address. +The function `redisClusterSetOptionSetAuth` is used to add the redis cluster password. The function `redisClusterConnect2` is used to connect to the redis cluser. The context is where Hiredis-vip Cluster holds state for connections. The `redisClusterContext` struct has an integer `err` field that is non-zero when the connection is in @@ -135,6 +142,7 @@ check the `err` field to see if establishing the connection was successful: ```c redisClusterContext *cc = redisClusterContextInit(); redisClusterSetOptionAddNodes(cc, "127.0.0.1:6379,127.0.0.1:6380"); +redisClusterSetOptionSetAuth(cc, "P@ssw0rd"); redisClusterConnect2(cc); if (cc != NULL && cc->err) { printf("Error: %s\n", cc->errstr); diff --git a/adapters/ae.h b/adapters/ae.h old mode 100644 new mode 100755 diff --git a/adapters/glib.h b/adapters/glib.h old mode 100644 new mode 100755 diff --git a/adapters/libev.h b/adapters/libev.h old mode 100644 new mode 100755 diff --git a/adapters/libevent.h b/adapters/libevent.h old mode 100644 new mode 100755 diff --git a/adapters/libuv.h b/adapters/libuv.h old mode 100644 new mode 100755 diff --git a/adlist.c b/adlist.c old mode 100644 new mode 100755 diff --git a/adlist.h b/adlist.h old mode 100644 new mode 100755 diff --git a/async.c b/async.c old mode 100644 new mode 100755 diff --git a/async.h b/async.h old mode 100644 new mode 100755 diff --git a/command.c b/command.c old mode 100644 new mode 100755 diff --git a/command.h b/command.h old mode 100644 new mode 100755 diff --git a/crc16.c b/crc16.c old mode 100644 new mode 100755 diff --git a/dict.c b/dict.c old mode 100644 new mode 100755 diff --git a/dict.h b/dict.h old mode 100644 new mode 100755 diff --git a/examples/example-ae.c b/examples/example-ae.c old mode 100644 new mode 100755 diff --git a/examples/example-glib.c b/examples/example-glib.c old mode 100644 new mode 100755 diff --git a/examples/example-libev.c b/examples/example-libev.c old mode 100644 new mode 100755 diff --git a/examples/example-libevent.c b/examples/example-libevent.c old mode 100644 new mode 100755 diff --git a/examples/example-libuv.c b/examples/example-libuv.c old mode 100644 new mode 100755 diff --git a/examples/example.c b/examples/example.c old mode 100644 new mode 100755 diff --git a/fmacros.h b/fmacros.h old mode 100644 new mode 100755 diff --git a/hiarray.c b/hiarray.c old mode 100644 new mode 100755 diff --git a/hiarray.h b/hiarray.h old mode 100644 new mode 100755 diff --git a/hircluster.c b/hircluster.c old mode 100644 new mode 100755 index b051936..d18c28d --- a/hircluster.c +++ b/hircluster.c @@ -11,6 +11,7 @@ #include "adlist.h" #include "hiarray.h" #include "command.h" +#include "net.h" #include "dict.c" #define REDIS_COMMAND_CLUSTER_NODES "CLUSTER NODES" @@ -338,6 +339,21 @@ static void cluster_node_deinit(cluster_node *node) } } + +static int auth_after_connect (redisClusterContext *cc, redisContext *c) +{ + if(cc->auth){ + redisReply *reply ; + reply = redisCommand(c, "auth %s", cc->auth); + if(reply == NULL){ + __redisClusterSetError(cc,REDIS_ERR_OTHER, "Command(auth XXXXX) reply error(NULL)."); + return 1; + } + freeReplyObject(reply); + } + return 0; +} + static int cluster_slot_init(cluster_slot *slot, cluster_node *node) { slot->start = 0; @@ -1294,6 +1310,10 @@ cluster_update_route_by_addr(redisClusterContext *cc, goto error; } + if (auth_after_connect (cc, c) == 1) { + goto error; + } + if (cc->timeout) { redisSetTimeout(c, *cc->timeout); } @@ -1547,6 +1567,10 @@ cluster_update_route_with_nodes_old(redisClusterContext *cc, goto error; } + if (auth_after_connect (cc, c) == 1) { + goto error; + } + reply = redisCommand(c, REDIS_COMMAND_CLUSTER_NODES); if(reply == NULL) @@ -2015,6 +2039,7 @@ redisClusterContext *redisClusterContextInit(void) { cc->err = 0; cc->errstr[0] = '\0'; + cc->auth[0] = '\0'; cc->ip = NULL; cc->port = 0; cc->flags = 0; @@ -2133,6 +2158,26 @@ redisClusterContext *redisClusterConnect(const char *addrs, int flags) return _redisClusterConnect(cc, addrs); } +redisClusterContext *redisClusterConnectWithAuth(const char *addrs, const char *auth, int flags) +{ + redisClusterContext *cc; + cc = redisClusterContextInit(); + if(cc == NULL) { + return NULL; + } + + cc->flags |= REDIS_BLOCK; + if(flags) { + cc->flags |= flags; + } + + if(auth){ + memcpy(cc->auth, auth, strlen(auth)); + } + + return _redisClusterConnect(cc, addrs); +} + redisClusterContext *redisClusterConnectWithTimeout( const char *addrs, const struct timeval tv, int flags) { @@ -2161,6 +2206,38 @@ redisClusterContext *redisClusterConnectWithTimeout( return _redisClusterConnect(cc, addrs); } +redisClusterContext *redisClusterConnectWithTimeoutWithAuth(const char *addrs, const char *auth, const struct timeval tv, int flags) +{ + redisClusterContext *cc; + + cc = redisClusterContextInit(); + + if(cc == NULL) + { + return NULL; + } + + cc->flags |= REDIS_BLOCK; + if(flags) + { + cc->flags |= flags; + } + + if (cc->connect_timeout == NULL) + { + cc->connect_timeout = malloc(sizeof(struct timeval)); + } + + memcpy(cc->connect_timeout, &tv, sizeof(struct timeval)); + + if(auth) + { + memcpy(cc->auth, auth, strlen(auth)); + } + + return _redisClusterConnect(cc, addrs); +} + redisClusterContext *redisClusterConnectNonBlock(const char *addrs, int flags) { redisClusterContext *cc; @@ -2181,6 +2258,31 @@ redisClusterContext *redisClusterConnectNonBlock(const char *addrs, int flags) { return _redisClusterConnect(cc, addrs); } +redisClusterContext *redisClusterConnectNonBlockWithAuth(const char *addrs, const char *auth, int flags) { + + redisClusterContext *cc; + + cc = redisClusterContextInit(); + + if(cc == NULL) + { + return NULL; + } + + cc->flags &= ~REDIS_BLOCK; + if(flags) + { + cc->flags |= flags; + } + + if(auth) + { + memcpy(cc->auth, auth, strlen(auth)); + } + + return _redisClusterConnect(cc, addrs); +} + int redisClusterSetOptionAddNode(redisClusterContext *cc, const char *addr) { dictEntry *node_entry; @@ -2265,6 +2367,18 @@ int redisClusterSetOptionAddNode(redisClusterContext *cc, const char *addr) return REDIS_OK; } + +int redisClusterSetOptionSetAuth(redisClusterContext *cc, const char *auth) +{ + if(cc == NULL) { + return REDIS_ERR; + } + if(auth) { + memcpy(cc->auth, auth, strlen(auth)); + } + return 0; +} + int redisClusterSetOptionAddNodes(redisClusterContext *cc, const char *addrs) { int ret; @@ -2503,6 +2617,11 @@ redisContext *ctx_get_by_node(redisClusterContext *cc, cluster_node *node) c = redisConnect(node->host, node->port); } + if (auth_after_connect (cc, c) == 1) { + redisFree(c); + c = NULL; + } + if (cc->timeout && c != NULL && c->err == 0) { redisSetTimeout(c, *cc->timeout); } @@ -4365,8 +4484,19 @@ redisAsyncContext * actx_get_by_node(redisClusterAsyncContext *acc, ac->data = node; ac->dataHandler = unlinkAsyncContextAndNode; + + if (acc->cc->auth) { + ac->c.flags |= REDIS_BLOCK; + redisSetBlocking(&ac->c, 1); + if (auth_after_connect (acc->cc, &ac->c) == 1) { + redisAsyncFree(ac); + ac = NULL; + return ac; + } + redisSetBlocking(&ac->c, 0); + ac->c.flags &= ~REDIS_BLOCK; + } node->acon = ac; - return ac; } @@ -4443,6 +4573,28 @@ redisClusterAsyncContext *redisClusterAsyncConnect(const char *addrs, int flags) return acc; } +redisClusterAsyncContext *redisClusterAsyncConnectWithAuth(const char *addrs, const char *auth, int flags) { + + redisClusterContext *cc; + redisClusterAsyncContext *acc; + + cc = redisClusterConnectNonBlockWithAuth(addrs, auth, flags); + if(cc == NULL) + { + return NULL; + } + + acc = redisClusterAsyncInitialize(cc); + if (acc == NULL) { + redisClusterFree(cc); + return NULL; + } + + __redisClusterAsyncCopyError(acc); + + return acc; +} + int redisClusterAsyncSetConnectCallback( redisClusterAsyncContext *acc, redisConnectCallback *fn) diff --git a/hircluster.h b/hircluster.h old mode 100644 new mode 100755 index 95585c9..2cf4830 --- a/hircluster.h +++ b/hircluster.h @@ -74,6 +74,7 @@ extern "C" { typedef struct redisClusterContext { int err; /* Error flags, 0 when there is no error */ char errstr[128]; /* String representation of error when applicable */ + char auth[128]; sds ip; int port; @@ -101,15 +102,20 @@ typedef struct redisClusterContext { } redisClusterContext; redisClusterContext *redisClusterConnect(const char *addrs, int flags); +redisClusterContext *redisClusterConnectWithAuth(const char *addrs, const char *auth, int flags); redisClusterContext *redisClusterConnectWithTimeout(const char *addrs, const struct timeval tv, int flags); +redisClusterContext *redisClusterConnectWithTimeoutWithAuth(const char *addrs, const char *auth, + const struct timeval tv, int flags); redisClusterContext *redisClusterConnectNonBlock(const char *addrs, int flags); +redisClusterContext *redisClusterConnectNonBlockWithAuth(const char *addrs, const char *auth, int flags); redisClusterContext *redisClusterContextInit(void); void redisClusterFree(redisClusterContext *cc); int redisClusterSetOptionAddNode(redisClusterContext *cc, const char *addr); int redisClusterSetOptionAddNodes(redisClusterContext *cc, const char *addrs); +int redisClusterSetOptionSetAuth(redisClusterContext *cc, const char *auth); int redisClusterSetOptionConnectBlock(redisClusterContext *cc); int redisClusterSetOptionConnectNonBlock(redisClusterContext *cc); int redisClusterSetOptionParseSlaves(redisClusterContext *cc); @@ -176,6 +182,7 @@ typedef struct redisClusterAsyncContext { } redisClusterAsyncContext; redisClusterAsyncContext *redisClusterAsyncConnect(const char *addrs, int flags); +redisClusterAsyncContext *redisClusterAsyncConnectWithAuth(const char *addrs, const char *auth, int flags); int redisClusterAsyncSetConnectCallback(redisClusterAsyncContext *acc, redisConnectCallback *fn); int redisClusterAsyncSetDisconnectCallback(redisClusterAsyncContext *acc, redisDisconnectCallback *fn); int redisClusterAsyncFormattedCommand(redisClusterAsyncContext *acc, redisClusterCallbackFn *fn, void *privdata, char *cmd, int len); diff --git a/hiredis.c b/hiredis.c old mode 100644 new mode 100755 diff --git a/hiredis.h b/hiredis.h old mode 100644 new mode 100755 diff --git a/hiutil.c b/hiutil.c old mode 100644 new mode 100755 diff --git a/hiutil.h b/hiutil.h old mode 100644 new mode 100755 diff --git a/net.c b/net.c old mode 100644 new mode 100755 index 60a2dc7..caaf643 --- a/net.c +++ b/net.c @@ -99,7 +99,7 @@ static int redisCreateSocket(redisContext *c, int type) { return REDIS_OK; } -static int redisSetBlocking(redisContext *c, int blocking) { +int redisSetBlocking(redisContext *c, int blocking) { int flags; /* Set the socket nonblocking. diff --git a/net.h b/net.h old mode 100644 new mode 100755 index 2f1a0bf..011f651 --- a/net.h +++ b/net.h @@ -49,5 +49,5 @@ int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, const char *source_addr); int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout); int redisKeepAlive(redisContext *c, int interval); - +int redisSetBlocking(redisContext *c, int blocking); #endif diff --git a/read.c b/read.c old mode 100644 new mode 100755 diff --git a/read.h b/read.h old mode 100644 new mode 100755 diff --git a/sds.c b/sds.c old mode 100644 new mode 100755 diff --git a/sds.h b/sds.h old mode 100644 new mode 100755 diff --git a/test.c b/test.c old mode 100644 new mode 100755 diff --git a/win32.h b/win32.h old mode 100644 new mode 100755 From 4b101bd8a8230ad9fbdef37d561a62607d08e1fc Mon Sep 17 00:00:00 2001 From: tanjunxian Date: Thu, 16 Aug 2018 10:54:58 +0800 Subject: [PATCH 2/6] fix memleak fix memleak for mget/mset commands --- hircluster.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hircluster.c b/hircluster.c index b051936..ae98059 100644 --- a/hircluster.c +++ b/hircluster.c @@ -3447,12 +3447,14 @@ static void *command_post_fragment(redisClusterContext *cc, if(reply->type != REDIS_REPLY_ARRAY) { __redisClusterSetError(cc,REDIS_ERR_OTHER,"reply type is error(here only can be array)"); + listReleaseIterator(list_iter); return NULL; } }else if(command->type == CMD_REQ_REDIS_DEL){ if(reply->type != REDIS_REPLY_INTEGER) { __redisClusterSetError(cc,REDIS_ERR_OTHER,"reply type is error(here only can be integer)"); + listReleaseIterator(list_iter); return NULL; } @@ -3462,12 +3464,14 @@ static void *command_post_fragment(redisClusterContext *cc, reply->len != 2 || strcmp(reply->str, REDIS_STATUS_OK) != 0) { __redisClusterSetError(cc,REDIS_ERR_OTHER,"reply type is error(here only can be status and ok)"); + listReleaseIterator(list_iter); return NULL; } }else { NOT_REACHED(); } } + listReleaseIterator(list_iter); reply = hi_calloc(1,sizeof(*reply)); From c7617bd271e6007c31b2a8f44190b2599d54a65e Mon Sep 17 00:00:00 2001 From: tanjunxian Date: Thu, 16 Aug 2018 11:14:31 +0800 Subject: [PATCH 3/6] add testcase add testcase for integation test --- .gitignore | 2 + Makefile | 7 + testcases/cluster.c | 431 +++++++++++++++++++++++++++++++++++++++++++ testcases/redis.c | 434 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 874 insertions(+) create mode 100644 testcases/cluster.c create mode 100644 testcases/redis.c diff --git a/.gitignore b/.gitignore index c44b5c5..ad6d5d8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ /*.dylib /*.a /*.pc +testcases/testcase-cluster +testcases/testcase-redis diff --git a/Makefile b/Makefile index a321bd1..94e5335 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,7 @@ EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev hiredis- TESTS=hiredis-test LIBNAME=libhiredis_vip PKGCONFNAME=hiredis_vip.pc +TESTCASES=testcase-cluster HIREDIS_VIP_MAJOR=$(shell grep HIREDIS_VIP_MAJOR hircluster.h | awk '{print $$3}') HIREDIS_VIP_MINOR=$(shell grep HIREDIS_VIP_MINOR hircluster.h | awk '{print $$3}') @@ -125,6 +126,12 @@ hiredis-example: examples/example.c $(STLIBNAME) examples: $(EXAMPLES) +testcase-cluster: testcases/cluster.c $(STLIBNAME) + $(CC) -o testcases/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME) + +testcase-redis: testcases/redis.c $(STLIBNAME) + $(CC) -o testcases/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME) + hiredis-test: test.o $(STLIBNAME) hiredis-%: %.o $(STLIBNAME) diff --git a/testcases/cluster.c b/testcases/cluster.c new file mode 100644 index 0000000..a876d2d --- /dev/null +++ b/testcases/cluster.c @@ -0,0 +1,431 @@ +#include +#include +#include +#include +#include +#include +#include + + +void print_qps(struct timeval* begin, int* count) { + struct timeval now; + gettimeofday(&now, NULL); + long diff_ms = (now.tv_sec - begin->tv_sec) * 1000 + (now.tv_usec - begin->tv_usec) / 1000; + if (diff_ms > 1000) { + printf("qps = %d\n", *count*1000 / (int)diff_ms); + if (diff_ms > 60000) { + *begin = now; + *count = 0; + } + } +} + +void _print_reply(redisReply* reply, size_t index, size_t depth) { + size_t i; + for (i=1; i 0) { + printf("%d) ", (int)index-1); + } + + switch(reply->type) { + case REDIS_REPLY_STRING: + printf("\"%s\"", reply->str); + break; + case REDIS_REPLY_INTEGER: + printf("%lld", reply->integer); + break; + case REDIS_REPLY_ERROR: + printf("(ERROR) %s", reply->str); + break; + case REDIS_REPLY_STATUS: + printf("(STATUS) %s", reply->str); + break; + case REDIS_REPLY_NIL: + printf("(NIL)"); + break; + case REDIS_REPLY_ARRAY: + for (i=0; ielements; i++) { + _print_reply(reply->element[i], i+1, depth+1); + } + return; + default: + assert(0); + break; + } + printf("\n"); +} + +void print_reply(redisReply* reply) { + _print_reply(reply, 0, 0); +} + +int main(int argc, char **argv) { + const int keyrange = 10000; + const int interval = 10000; + redisClusterContext *cc; + redisReply *reply; + const char *addrs = (argc > 1) ? argv[1] : "127.0.0.1:6379"; + const char *testcase = (argc > 2) ? argv[2] : "setget"; + int keystart = (argc > 3) ? atoi(argv[3]) * keyrange : keyrange; + int limit = (argc > 4) ? atoi(argv[4]) : 0; + int count; + char key[256]; + char member[256]; + char value[256]; + char msg[1024]; + int line; + + struct timeval timeout = { 1, 500000 }; // 1.5 seconds + cc = redisClusterContextInit(); + redisClusterSetOptionAddNodes(cc, addrs); + redisClusterSetOptionRouteUseSlots(cc); + redisClusterSetOptionParseSlaves(cc); + redisClusterSetOptionConnectTimeout(cc, timeout); + redisClusterConnect2(cc); + if (cc == NULL || cc->err) { + if (cc) { + printf("Connection error: %s\n", cc->errstr); + redisClusterFree(cc); + } else { + printf("Connection error: can't allocate redis cluster context\n"); + } + exit(1); + } + + struct timeval begin; + gettimeofday(&begin, NULL); + srand(time(NULL)); + if (strcmp(testcase, "setget") == 0) { + for (count=1;limit<=0||counttype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_STATUS); + freeReplyObject(reply); + reply = redisClusterCommand(cc, "GET %s", key); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + if (reply->type == REDIS_REPLY_NIL) { + line = __LINE__; + sprintf(msg, "nil reply value"); + goto reply_fail; + } + assert(reply->type == REDIS_REPLY_STRING); + if (strcmp(reply->str, value) != 0) { + line = __LINE__; + sprintf(msg, "unexpected reply value '%s' vs '%s'", reply->str, value); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + } else if (strcmp(testcase, "hsethget") == 0) { + for (count=1;limit<=0||counttype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + freeReplyObject(reply); + reply = redisClusterCommand(cc, "HGET %s %s", key, member); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + if (reply->type == REDIS_REPLY_NIL) { + line = __LINE__; + sprintf(msg, "nil reply value"); + goto reply_fail; + } + assert(reply->type == REDIS_REPLY_STRING); + if (strcmp(reply->str, value) != 0) { + line = __LINE__; + sprintf(msg, "unexpected reply value '%s' vs '%s'", reply->str, value); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + }else if (strcmp(testcase, "zaddzrank") == 0) { + const int ZSET_SIZE = 1000; + for (count=1;limit<=0||counttype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + freeReplyObject(reply); + reply = redisClusterCommand(cc, "ZRANK %s %s", key, member); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + if (reply->type == REDIS_REPLY_NIL) { + line = __LINE__; + sprintf(msg, "nil reply rank"); + goto reply_fail; + } + assert(reply->type == REDIS_REPLY_INTEGER); + /*if (reply->integer) { + line = __LINE__; + sprintf(msg, "unexpected reply rank %d vs %d", reply->integer); + goto reply_fail; + }*/ + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + }else if (strcmp(testcase, "saddsismem") == 0) { + const int SET_SIZE = 1000; + for (count=1;limit<=0||counttype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + freeReplyObject(reply); + reply = redisClusterCommand(cc, "ZISMEMBER %s %s", key, member); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + if (reply->integer != 1) { + line = __LINE__; + sprintf(msg, "unexpected reply rank %d vs %d", reply->integer, 1); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + }else if (strcmp(testcase, "lpushlpop") == 0) { + for (count=1;limit<=0||counttype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + freeReplyObject(reply); + reply = redisClusterCommand(cc, "LPOP %s", key); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + if (reply->type == REDIS_REPLY_NIL) { + line = __LINE__; + sprintf(msg, "nil reply value"); + goto reply_fail; + } + assert(reply->type == REDIS_REPLY_STRING); + if (strcmp(reply->str, value) != 0) { + line = __LINE__; + sprintf(msg, "unexpected reply value '%s' vs '%s'", reply->str, value); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + }else if (strcmp(testcase, "msetmget") == 0) { + const size_t MSET_MGET_COUNT = 5; + const char* _argv[MSET_MGET_COUNT*2+1]; + char keyvalues[MSET_MGET_COUNT*2][256]; + size_t _argc, i; + for (count=1;limit<=0||counttype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_STATUS); + freeReplyObject(reply); + + _argc = 0; + _argv[_argc] = "MGET"; + _argc ++; + for (i=0; itype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_ARRAY); + for (i=0; ielements; i++) { + if (reply->element[i]->type == REDIS_REPLY_NIL) { + line = __LINE__; + sprintf(msg, "nil reply value"); + goto reply_fail; + } + assert(reply->element[i]->type == REDIS_REPLY_STRING); + if (strcmp(reply->element[i]->str, keyvalues[i*2+1]) != 0) { + line = __LINE__; + sprintf(msg, "unexpected reply value '%s' vs '%s'", reply->element[i]->str, keyvalues[i*2+1]); + goto reply_fail; + } + } + freeReplyObject(reply); + + if (count % (interval/MSET_MGET_COUNT) == 0) { + print_qps(&begin, &count); + } + } + } else if (strcmp(testcase, "eval") == 0) { + const char* SCRIPT = "local sum=0; for i,k in ipairs(KEYS) do sum=sum+redis.call('INCR', k) end return sum"; + const size_t SCRIPT_KEYS_COUNT = 5; + const char* _argv[SCRIPT_KEYS_COUNT+3]; + char keys[SCRIPT_KEYS_COUNT][256]; + size_t _argc, i; + for (count=0;limit<=0||counttype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + if ((int)reply->integer < (int)SCRIPT_KEYS_COUNT) { + line = __LINE__; + sprintf(msg, "unexpected reply value %d < %d", (int)reply->integer, (int)SCRIPT_KEYS_COUNT); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + } else if (strcmp(testcase, "pipeline") == 0) { + for (count=1;limit<=0||counttype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_STATUS); + freeReplyObject(reply); + redisClusterGetReply(cc, &reply); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_STRING); + if (strcmp(reply->str, value) != 0) { + line = __LINE__; + sprintf(msg, "unexpected reply value '%s' vs '%s'", reply->str, value); + goto reply_fail; + } + freeReplyObject(reply); + redisClusterReset(cc); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + } else if (strcmp(testcase, "once") == 0) { + reply = redisClusterCommandArgv(cc, argc-3, argv+3, NULL); + if (reply == NULL) { + line = __LINE__; + goto reply_error; + } + print_reply(reply); + freeReplyObject(reply); + } else if (strcmp(testcase, "loop") == 0) { + for (count=1;limit<=0||counttype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + freeReplyObject(reply); + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + } else { + printf("invalid testcase: %s\n", testcase); + } + + redisClusterFree(cc); + return 0; + +reply_error: + if (reply) { + printf("line %d: Command error: %s\n", line, reply->str); + freeReplyObject(reply); + } else { + printf("line %d: Connection error: %s\n", line, cc->errstr); + } + redisClusterFree(cc); + return 1; + +reply_fail: + printf("line %d: %s\n", line, msg); + freeReplyObject(reply); + redisClusterFree(cc); + return 2; +} diff --git a/testcases/redis.c b/testcases/redis.c new file mode 100644 index 0000000..b103d68 --- /dev/null +++ b/testcases/redis.c @@ -0,0 +1,434 @@ +#include +#include +#include +#include +#include +#include +#include + + +void print_qps(struct timeval* begin, int* count) { + struct timeval now; + gettimeofday(&now, NULL); + long diff_ms = (now.tv_sec - begin->tv_sec) * 1000 + (now.tv_usec - begin->tv_usec) / 1000; + if (diff_ms > 1000) { + printf("qps = %d\n", *count*1000 / (int)diff_ms); + if (diff_ms > 60000) { + *begin = now; + *count = 0; + } + } +} + +void _print_reply(redisReply* reply, size_t index, size_t depth) { + size_t i; + for (i=1; i 0) { + printf("%d) ", (int)index-1); + } + + switch(reply->type) { + case REDIS_REPLY_STRING: + printf("\"%s\"", reply->str); + break; + case REDIS_REPLY_INTEGER: + printf("%lld", reply->integer); + break; + case REDIS_REPLY_ERROR: + printf("(ERROR) %s", reply->str); + break; + case REDIS_REPLY_STATUS: + printf("(STATUS) %s", reply->str); + break; + case REDIS_REPLY_NIL: + printf("(NIL)"); + break; + case REDIS_REPLY_ARRAY: + for (i=0; ielements; i++) { + _print_reply(reply->element[i], i+1, depth+1); + } + return; + default: + assert(0); + break; + } + printf("\n"); +} + +void print_reply(redisReply* reply) { + _print_reply(reply, 0, 0); +} + +int main(int argc, char **argv) { + redisContext *cc; + redisReply *reply; + const char *addr = (argc > 1) ? argv[1] : "127.0.0.1:6379"; + const char *testcase = (argc > 2) ? argv[2] : "setget"; + int keystart = (argc > 3) ? atoi(argv[3]) : 10000; + int keyrange = (argc > 4) ? atoi(argv[4]) : 10000; + + const int interval = 10000; + int count; + char key[256]; + char member[256]; + char value[256]; + char msg[1024]; + int line; + + struct timeval timeout = { 1, 500000 }; // 1.5 seconds + char* port = strchr(addr, ':'); + if (port == NULL) { + printf("invalid addr: %s", addr); + return 1; + } else { + *port = '\0'; + port ++; + } + cc = redisConnectWithTimeout(addr, atoi(port), timeout); + if (cc == NULL || cc->err) { + if (cc) { + printf("Connection error: %s\n", cc->errstr); + redisFree(cc); + } else { + printf("Connection error: can't allocate redis cluster context\n"); + } + exit(1); + } + + + struct timeval begin; + gettimeofday(&begin, NULL); + srand(time(NULL)); + if (strcmp(testcase, "setget") == 0) { + for (count=1;;count++) { + sprintf(key, "%s_key_%d", testcase, keystart + count % keyrange); + sprintf(value, "%d", rand()); + reply = redisCommand(cc, "SET %s %s", key, value); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_STATUS); + freeReplyObject(reply); + reply = redisCommand(cc, "GET %s", key); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + if (reply->type == REDIS_REPLY_NIL) { + line = __LINE__; + sprintf(msg, "nil reply value"); + goto reply_fail; + } + assert(reply->type == REDIS_REPLY_STRING); + if (strcmp(reply->str, value) != 0) { + line = __LINE__; + sprintf(msg, "unexpected reply value '%s' vs '%s'", reply->str, value); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + } else if (strcmp(testcase, "hsethget") == 0) { + for (count=1;;count++) { + sprintf(key, "%s_key_%d", testcase, keystart + count % keyrange); + sprintf(member, "%d", rand()); + sprintf(value, "%d", rand()); + reply = redisCommand(cc, "HSET %s %s %s", key, member, value); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + freeReplyObject(reply); + reply = redisCommand(cc, "HGET %s %s", key, member); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + if (reply->type == REDIS_REPLY_NIL) { + line = __LINE__; + sprintf(msg, "nil reply value"); + goto reply_fail; + } + assert(reply->type == REDIS_REPLY_STRING); + if (strcmp(reply->str, value) != 0) { + line = __LINE__; + sprintf(msg, "unexpected reply value '%s' vs '%s'", reply->str, value); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + }else if (strcmp(testcase, "zaddzrank") == 0) { + const int ZSET_SIZE = 1000; + for (count=1;;count++) { + sprintf(key, "%s_key_%d", testcase, keystart + count % keyrange); + sprintf(member, "%d", rand() % ZSET_SIZE); + sprintf(value, "%d", rand()); + reply = redisCommand(cc, "ZADD %s %s %s", key, value, member); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + freeReplyObject(reply); + reply = redisCommand(cc, "ZRANK %s %s", key, member); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + if (reply->type == REDIS_REPLY_NIL) { + line = __LINE__; + sprintf(msg, "nil reply rank"); + goto reply_fail; + } + assert(reply->type == REDIS_REPLY_INTEGER); + /*if (reply->integer) { + line = __LINE__; + sprintf(msg, "unexpected reply rank %d vs %d", reply->integer); + goto reply_fail; + }*/ + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + } else if (strcmp(testcase, "saddsismem") == 0) { + const int SET_SIZE = 1000; + for (count=1;;count++) { + sprintf(key, "%s_key_%d", testcase, keystart + count % keyrange); + sprintf(member, "%d", rand() % SET_SIZE); + reply = redisCommand(cc, "SADD %s %s", key, member); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + freeReplyObject(reply); + reply = redisCommand(cc, "SISMEMBER %s %s", key, member); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + if (reply->integer != 1) { + line = __LINE__; + sprintf(msg, "unexpected reply value %lld vs %d", reply->integer, 1); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + } else if (strcmp(testcase, "lpushlpop") == 0) { + for (count=1;;count++) { + sprintf(key, "%s_key_%d", testcase, keystart + count % keyrange); + sprintf(value, "%d", rand()); + reply = redisCommand(cc, "LPUSH %s %s", key, value); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + freeReplyObject(reply); + reply = redisCommand(cc, "LPOP %s", key); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + if (reply->type == REDIS_REPLY_NIL) { + line = __LINE__; + sprintf(msg, "nil reply value"); + goto reply_fail; + } + assert(reply->type == REDIS_REPLY_STRING); + if (strcmp(reply->str, value) != 0) { + line = __LINE__; + sprintf(msg, "unexpected reply value '%s' vs '%s'", reply->str, value); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + }else if (strcmp(testcase, "msetmget") == 0) { + const size_t MSET_MGET_COUNT = 5; + const char* _argv[MSET_MGET_COUNT*2+1]; + char keyvalues[MSET_MGET_COUNT*2][256]; + size_t _argc, i; + for (count=1;;count++) { + _argc = 0; + _argv[_argc] = "MSET"; + _argc ++; + for (i=0; itype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_STATUS); + freeReplyObject(reply); + + _argc = 0; + _argv[_argc] = "MGET"; + _argc ++; + for (i=0; itype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_ARRAY); + for (i=0; ielements; i++) { + if (reply->element[i]->type == REDIS_REPLY_NIL) { + line = __LINE__; + sprintf(msg, "nil reply value"); + goto reply_fail; + } + assert(reply->type == REDIS_REPLY_STRING); + if (strcmp(reply->element[i]->str, keyvalues[i*2+1]) != 0) { + line = __LINE__; + sprintf(msg, "unexpected reply value '%s' vs '%s'", reply->element[i]->str, keyvalues[i*2+1]); + goto reply_fail; + } + } + freeReplyObject(reply); + + if (count % (interval/MSET_MGET_COUNT) == 0) { + print_qps(&begin, &count); + } + } + } else if (strcmp(testcase, "eval") == 0) { + const char* SCRIPT = "local sum=0; for i,k in ipairs(KEYS) do sum=sum+redis.call('INCR', k) end return sum"; + const size_t SCRIPT_KEYS_COUNT = 5; + const char* _argv[SCRIPT_KEYS_COUNT+3]; + char keys[SCRIPT_KEYS_COUNT][256]; + size_t _argc, i; + for (count=0;;count++) { + _argc = 0; + _argv[_argc] = "EVAL"; + _argc ++; + _argv[_argc] = SCRIPT; + _argc ++; + sprintf(value, "%d", (int)SCRIPT_KEYS_COUNT); + _argv[_argc] = value; + _argc ++; + for (i=0; itype == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_INTEGER); + if ((int)reply->integer < (int)SCRIPT_KEYS_COUNT) { + line = __LINE__; + sprintf(msg, "unexpected reply value %d < %d", (int)reply->integer, (int)SCRIPT_KEYS_COUNT); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + } else if (strcmp(testcase, "pipeline") == 0) { + for (count=1;;count++) { + sprintf(key, "%s_key_%d", testcase, keystart + count % keyrange); + sprintf(value, "%d", rand()); + redisAppendCommand(cc, "SET %s %s", key, value); + redisAppendCommand(cc, "GET %s", key); + redisGetReply(cc, &reply); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_STATUS); + freeReplyObject(reply); + redisGetReply(cc, &reply); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + assert(reply->type == REDIS_REPLY_STRING); + if (strcmp(reply->str, value) != 0) { + line = __LINE__; + sprintf(msg, "unexpected reply value '%s' vs '%s'", reply->str, value); + goto reply_fail; + } + freeReplyObject(reply); + + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + } else if (strcmp(testcase, "once") == 0) { + reply = redisCommandArgv(cc, argc-3, argv+3, NULL); + if (reply == NULL) { + line = __LINE__; + goto reply_error; + } + print_reply(reply); + freeReplyObject(reply); + } else if (strcmp(testcase, "loop") == 0) { + for (count=1;;count++) { + reply = redisCommandArgv(cc, argc-3, argv+3, NULL); + if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { + line = __LINE__; + goto reply_error; + } + freeReplyObject(reply); + if (count % interval == 0) { + print_qps(&begin, &count); + } + } + } else { + printf("invalid testcase: %s\n", testcase); + } + + redisFree(cc); + return 0; + +reply_error: + if (reply) { + printf("line %d: Command error: %s\n", line, reply->str); + freeReplyObject(reply); + } else { + printf("line %d: Connection error: %s\n", line, cc->errstr); + } + redisFree(cc); + return 1; + +reply_fail: + printf("line %d: %s\n", line, msg); + freeReplyObject(reply); + redisFree(cc); + return 2; +} From a3f072f8bc90dc9d0ec9b23d9fed73d3902cb9ae Mon Sep 17 00:00:00 2001 From: tanjunxian Date: Thu, 16 Aug 2018 11:56:21 +0800 Subject: [PATCH 4/6] fix memleak fix memleak for command mget/mset --- hircluster.c | 1 + testcases/cluster.c | 1 + 2 files changed, 2 insertions(+) diff --git a/hircluster.c b/hircluster.c index 0afc958..87771f4 100755 --- a/hircluster.c +++ b/hircluster.c @@ -3555,6 +3555,7 @@ static void *command_post_fragment(redisClusterContext *cc, reply = sub_command->reply; if(reply == NULL) { + listReleaseIterator(list_iter); return NULL; } else if(reply->type == REDIS_REPLY_ERROR) diff --git a/testcases/cluster.c b/testcases/cluster.c index a876d2d..a812b57 100644 --- a/testcases/cluster.c +++ b/testcases/cluster.c @@ -82,6 +82,7 @@ int main(int argc, char **argv) { redisClusterSetOptionAddNodes(cc, addrs); redisClusterSetOptionRouteUseSlots(cc); redisClusterSetOptionParseSlaves(cc); + redisClusterSetOptionSetAuth(cc, "abc"); redisClusterSetOptionConnectTimeout(cc, timeout); redisClusterConnect2(cc); if (cc == NULL || cc->err) { From fbfd16437d22771c3594bfd70137383dde8de04c Mon Sep 17 00:00:00 2001 From: tanjunxian Date: Thu, 16 Aug 2018 14:21:55 +0800 Subject: [PATCH 5/6] fix memleak fix memleak for mget/mgset command --- hircluster.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hircluster.c b/hircluster.c index 87771f4..60891cd 100755 --- a/hircluster.c +++ b/hircluster.c @@ -3560,6 +3560,7 @@ static void *command_post_fragment(redisClusterContext *cc, } else if(reply->type == REDIS_REPLY_ERROR) { + listReleaseIterator(list_iter); return reply; } From c8d6e95a1a0b77487909d362b761f0ba657d01fa Mon Sep 17 00:00:00 2001 From: tanjunxian Date: Thu, 16 Aug 2018 14:42:36 +0800 Subject: [PATCH 6/6] export print method export print method --- hircluster.c | 14 +------------- hircluster.h | 2 +- testcases/cluster.c | 1 + 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/hircluster.c b/hircluster.c index 60891cd..f7bac2a 100755 --- a/hircluster.c +++ b/hircluster.c @@ -1974,7 +1974,7 @@ cluster_update_route(redisClusterContext *cc) return REDIS_ERR; } -static void print_cluster_node_list(redisClusterContext *cc) +void print_cluster_node_list(redisClusterContext *cc) { dictIterator *di = NULL; dictEntry *de; @@ -2018,18 +2018,6 @@ static void print_cluster_node_list(redisClusterContext *cc) } } - -int test_cluster_update_route(redisClusterContext *cc) -{ - int ret; - - ret = cluster_update_route(cc); - - //print_cluster_node_list(cc); - - return ret; -} - redisClusterContext *redisClusterContextInit(void) { redisClusterContext *cc; diff --git a/hircluster.h b/hircluster.h index 2cf4830..6c624ef 100755 --- a/hircluster.h +++ b/hircluster.h @@ -144,7 +144,7 @@ int redisClusterGetReply(redisClusterContext *cc, void **reply); void redisClusterReset(redisClusterContext *cc); int cluster_update_route(redisClusterContext *cc); -int test_cluster_update_route(redisClusterContext *cc); +void print_cluster_node_list(redisClusterContext *cc); struct dict *parse_cluster_nodes(redisClusterContext *cc, char *str, int str_len, int flags); struct dict *parse_cluster_slots(redisClusterContext *cc, redisReply *reply, int flags); diff --git a/testcases/cluster.c b/testcases/cluster.c index a812b57..22bbf28 100644 --- a/testcases/cluster.c +++ b/testcases/cluster.c @@ -94,6 +94,7 @@ int main(int argc, char **argv) { } exit(1); } + print_cluster_node_list(cc); struct timeval begin; gettimeofday(&begin, NULL);