int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen) { char *cmd; int len; len = redisFormatCommandArgv(&cmd,argc,argv,argvlen); if (len == -1) { __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); return REDIS_ERR; } if (__redisAppendCommand(c,cmd,len) != REDIS_OK) { free(cmd); return REDIS_ERR; } free(cmd); return REDIS_OK; }
int main(int argc, const char **argv) { int i; char *data, *cmd; int len; client c; signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); config.numclients = 50; config.requests = 10000; config.liveclients = 0; config.el = aeCreateEventLoop(1024*10); aeCreateTimeEvent(config.el,1,showThroughput,NULL,NULL); config.keepalive = 1; config.datasize = 3; config.pipeline = 1; config.randomkeys = 0; config.randomkeys_keyspacelen = 0; config.quiet = 0; config.csv = 0; config.loop = 0; config.idlemode = 0; config.latency = NULL; config.clients = listCreate(); config.hostip = "127.0.0.1"; config.hostport = 6379; config.hostsocket = NULL; config.tests = NULL; config.dbnum = 0; i = parseOptions(argc,argv); argc -= i; argv += i; // printf ("SET PAGE POOL SIZE\n"); // set_page_pool_size(config.requests); config.latency = zmalloc(sizeof(long long)*config.requests); if (config.keepalive == 0) { printf("WARNING: keepalive disabled, you probably need 'echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse' for Linux and 'sudo sysctl -w net.inet.tcp.msl=1000' for Mac OS X in order to use a lot of clients/requests\n"); } if (config.idlemode) { printf("Creating %d idle connections and waiting forever (Ctrl+C when done)\n", config.numclients); c = createClient("",0,NULL); /* will never receive a reply */ createMissingClients(c); aeMain(config.el); /* and will wait for every */ } /* Run benchmark with command in the remainder of the arguments. */ if (argc) { sds title = sdsnew(argv[0]); for (i = 1; i < argc; i++) { title = sdscatlen(title, " ", 1); title = sdscatlen(title, (char*)argv[i], strlen(argv[i])); } do { len = redisFormatCommandArgv(&cmd,argc,argv,NULL); benchmark(title,cmd,len); free(cmd); } while(config.loop); return 0; } /* Run default benchmark suite. */ do { data = zmalloc(config.datasize+1); memset(data,'x',config.datasize); data[config.datasize] = '\0'; if (test_is_selected("ping_inline") || test_is_selected("ping")) benchmark("PING_INLINE","PING\r\n",6); if (test_is_selected("ping_mbulk") || test_is_selected("ping")) { len = redisFormatCommand(&cmd,"PING"); benchmark("PING_BULK",cmd,len); free(cmd); } if (test_is_selected("set")) { len = redisFormatCommand(&cmd,"SET key:__rand_int__ %s",data); benchmark("SET",cmd,len); free(cmd); } if (test_is_selected("get")) { len = redisFormatCommand(&cmd,"GET key:__rand_int__"); benchmark("GET",cmd,len); free(cmd); } if (test_is_selected("incr")) { len = redisFormatCommand(&cmd,"INCR counter:__rand_int__"); benchmark("INCR",cmd,len); free(cmd); } if (test_is_selected("lpush")) { len = redisFormatCommand(&cmd,"LPUSH mylist %s",data); benchmark("LPUSH",cmd,len); free(cmd); } if (test_is_selected("lpop")) { len = redisFormatCommand(&cmd,"LPOP mylist"); benchmark("LPOP",cmd,len); free(cmd); } if (test_is_selected("sadd")) { len = redisFormatCommand(&cmd, "SADD myset element:__rand_int__"); benchmark("SADD",cmd,len); free(cmd); } if (test_is_selected("spop")) { len = redisFormatCommand(&cmd,"SPOP myset"); benchmark("SPOP",cmd,len); free(cmd); } if (test_is_selected("lrange") || test_is_selected("lrange_100") || test_is_selected("lrange_300") || test_is_selected("lrange_500") || test_is_selected("lrange_600")) { len = redisFormatCommand(&cmd,"LPUSH mylist %s",data); benchmark("LPUSH (needed to benchmark LRANGE)",cmd,len); free(cmd); } if (test_is_selected("lrange") || test_is_selected("lrange_100")) { len = redisFormatCommand(&cmd,"LRANGE mylist 0 99"); benchmark("LRANGE_100 (first 100 elements)",cmd,len); free(cmd); } if (test_is_selected("lrange") || test_is_selected("lrange_300")) { len = redisFormatCommand(&cmd,"LRANGE mylist 0 299"); benchmark("LRANGE_300 (first 300 elements)",cmd,len); free(cmd); } if (test_is_selected("lrange") || test_is_selected("lrange_500")) { len = redisFormatCommand(&cmd,"LRANGE mylist 0 449"); benchmark("LRANGE_500 (first 450 elements)",cmd,len); free(cmd); } if (test_is_selected("lrange") || test_is_selected("lrange_600")) { len = redisFormatCommand(&cmd,"LRANGE mylist 0 599"); benchmark("LRANGE_600 (first 600 elements)",cmd,len); free(cmd); } if (test_is_selected("mset")) { const char *argv[21]; argv[0] = "MSET"; for (i = 1; i < 21; i += 2) { argv[i] = "key:__rand_int__"; argv[i+1] = data; } len = redisFormatCommandArgv(&cmd,21,argv,NULL); benchmark("MSET (10 keys)",cmd,len); free(cmd); } if (!config.csv) printf("\n"); } while(config.loop); return 0; }
static void test_format_commands(void) { char *cmd; int len; test("Format command without interpolation: "); len = redisFormatCommand(&cmd,"SET foo bar"); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(3+2)); free(cmd); test("Format command with %%s string interpolation: "); len = redisFormatCommand(&cmd,"SET %s %s","foo","bar"); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(3+2)); free(cmd); test("Format command with %%s and an empty string: "); len = redisFormatCommand(&cmd,"SET %s %s","foo",""); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(0+2)); free(cmd); test("Format command with an empty string in between proper interpolations: "); len = redisFormatCommand(&cmd,"SET %s %s","","foo"); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$0\r\n\r\n$3\r\nfoo\r\n",len) == 0 && len == 4+4+(3+2)+4+(0+2)+4+(3+2)); free(cmd); test("Format command with %%b string interpolation: "); len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"b\0r",3); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(3+2)); free(cmd); test("Format command with %%b and an empty string: "); len = redisFormatCommand(&cmd,"SET %b %b","foo",3,"",0); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(0+2)); free(cmd); test("Format command with literal %%: "); len = redisFormatCommand(&cmd,"SET %% %%"); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$1\r\n%\r\n$1\r\n%\r\n",len) == 0 && len == 4+4+(3+2)+4+(1+2)+4+(1+2)); free(cmd); test("Format command with printf-delegation (long long): "); len = redisFormatCommand(&cmd,"key:%08lld",1234ll); test_cond(strncmp(cmd,"*1\r\n$12\r\nkey:00001234\r\n",len) == 0 && len == 4+5+(12+2)); free(cmd); test("Format command with printf-delegation (float): "); len = redisFormatCommand(&cmd,"v:%06.1f",12.34f); test_cond(strncmp(cmd,"*1\r\n$8\r\nv:0012.3\r\n",len) == 0 && len == 4+4+(8+2)); free(cmd); test("Format command with printf-delegation and extra interpolation: "); len = redisFormatCommand(&cmd,"key:%d %b",1234,"foo",3); test_cond(strncmp(cmd,"*2\r\n$8\r\nkey:1234\r\n$3\r\nfoo\r\n",len) == 0 && len == 4+4+(8+2)+4+(3+2)); free(cmd); test("Format command with wrong printf format and extra interpolation: "); len = redisFormatCommand(&cmd,"key:%08p %b",1234,"foo",3); test_cond(strncmp(cmd,"*2\r\n$6\r\nkey:8p\r\n$3\r\nfoo\r\n",len) == 0 && len == 4+4+(6+2)+4+(3+2)); free(cmd); const char *argv[3]; argv[0] = "SET"; argv[1] = "foo\0xxx"; argv[2] = "bar"; size_t lens[3] = { 3, 7, 3 }; int argc = 3; test("Format command by passing argc/argv without lengths: "); len = redisFormatCommandArgv(&cmd,argc,argv,NULL); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(3+2)); free(cmd); test("Format command by passing argc/argv with lengths: "); len = redisFormatCommandArgv(&cmd,argc,argv,lens); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 && len == 4+4+(3+2)+4+(7+2)+4+(3+2)); free(cmd); }
static void test_format_commands(void) { char *cmd; int len; test("Format command without interpolation: "); len = redisFormatCommand(&cmd,"SET foo bar"); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(3+2)); free(cmd); test("Format command with %%s string interpolation: "); len = redisFormatCommand(&cmd,"SET %s %s","foo","bar"); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(3+2)); free(cmd); test("Format command with %%s and an empty string: "); len = redisFormatCommand(&cmd,"SET %s %s","foo",""); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(0+2)); free(cmd); test("Format command with an empty string in between proper interpolations: "); len = redisFormatCommand(&cmd,"SET %s %s","","foo"); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$0\r\n\r\n$3\r\nfoo\r\n",len) == 0 && len == 4+4+(3+2)+4+(0+2)+4+(3+2)); free(cmd); test("Format command with %%b string interpolation: "); len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"b\0r",(size_t)3); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nb\0r\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(3+2)); free(cmd); test("Format command with %%b and an empty string: "); len = redisFormatCommand(&cmd,"SET %b %b","foo",(size_t)3,"",(size_t)0); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$0\r\n\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(0+2)); free(cmd); test("Format command with literal %%: "); len = redisFormatCommand(&cmd,"SET %% %%"); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$1\r\n%\r\n$1\r\n%\r\n",len) == 0 && len == 4+4+(3+2)+4+(1+2)+4+(1+2)); free(cmd); /* Vararg width depends on the type. These tests make sure that the * width is correctly determined using the format and subsequent varargs * can correctly be interpolated. */ #define INTEGER_WIDTH_TEST(fmt, type) do { \ type value = 123; \ test("Format command with printf-delegation (" #type "): "); \ len = redisFormatCommand(&cmd,"key:%08" fmt " str:%s", value, "hello"); \ test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:00000123\r\n$9\r\nstr:hello\r\n",len) == 0 && \ len == 4+5+(12+2)+4+(9+2)); \ free(cmd); \ } while(0) #define FLOAT_WIDTH_TEST(type) do { \ type value = 123.0; \ test("Format command with printf-delegation (" #type "): "); \ len = redisFormatCommand(&cmd,"key:%08.3f str:%s", value, "hello"); \ test_cond(strncmp(cmd,"*2\r\n$12\r\nkey:0123.000\r\n$9\r\nstr:hello\r\n",len) == 0 && \ len == 4+5+(12+2)+4+(9+2)); \ free(cmd); \ } while(0) INTEGER_WIDTH_TEST("d", int); INTEGER_WIDTH_TEST("hhd", char); INTEGER_WIDTH_TEST("hd", short); INTEGER_WIDTH_TEST("ld", long); INTEGER_WIDTH_TEST("lld", long long); INTEGER_WIDTH_TEST("u", unsigned int); INTEGER_WIDTH_TEST("hhu", unsigned char); INTEGER_WIDTH_TEST("hu", unsigned short); INTEGER_WIDTH_TEST("lu", unsigned long); INTEGER_WIDTH_TEST("llu", unsigned long long); FLOAT_WIDTH_TEST(float); FLOAT_WIDTH_TEST(double); test("Format command with invalid printf format: "); len = redisFormatCommand(&cmd,"key:%08p %b",(void*)1234,"foo",(size_t)3); test_cond(len == -1); const char *argv[3]; argv[0] = "SET"; argv[1] = "foo\0xxx"; argv[2] = "bar"; size_t lens[3] = { 3, 7, 3 }; int argc = 3; test("Format command by passing argc/argv without lengths: "); len = redisFormatCommandArgv(&cmd,argc,argv,NULL); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",len) == 0 && len == 4+4+(3+2)+4+(3+2)+4+(3+2)); free(cmd); test("Format command by passing argc/argv with lengths: "); len = redisFormatCommandArgv(&cmd,argc,argv,lens); test_cond(strncmp(cmd,"*3\r\n$3\r\nSET\r\n$7\r\nfoo\0xxx\r\n$3\r\nbar\r\n",len) == 0 && len == 4+4+(3+2)+4+(7+2)+4+(3+2)); free(cmd); }
int main(int argc, const char **argv) { int i; char *data, *cmd; int len; client c; #ifdef _WIN32 w32initWinSock(); #endif signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); config.numclients = 50; config.requests = 10000; config.liveclients = 0; config.el = aeCreateEventLoop(); aeCreateTimeEvent(config.el,1,showThroughput,NULL,NULL); config.keepalive = 1; config.datasize = 3; config.randomkeys = 0; config.randomkeys_keyspacelen = 0; config.quiet = 0; config.loop = 0; config.idlemode = 0; config.latency = NULL; config.clients = listCreate(); config.hostip = "127.0.0.1"; config.hostport = 6379; config.hostsocket = NULL; i = parseOptions(argc,argv); argc -= i; argv += i; config.latency = zmalloc(sizeof(long long)*config.requests); if (config.keepalive == 0) { printf("WARNING: keepalive disabled, you probably need 'echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse' for Linux and 'sudo sysctl -w net.inet.tcp.msl=1000' for Mac OS X in order to use a lot of clients/requests\n"); } if (config.idlemode) { printf("Creating %d idle connections and waiting forever (Ctrl+C when done)\n", config.numclients); c = createClient("",0); /* will never receive a reply */ createMissingClients(c); aeMain(config.el); /* and will wait for every */ } /* Run benchmark with command in the remainder of the arguments. */ if (argc) { sds title = sdsnew(argv[0]); for (i = 1; i < argc; i++) { title = sdscatlen(title, " ", 1); title = sdscatlen(title, (char*)argv[i], strlen(argv[i])); } do { len = redisFormatCommandArgv(&cmd,argc,argv,NULL); benchmark(title,cmd,len); free(cmd); } while(config.loop); return 0; } /* Run default benchmark suite. */ do { data = zmalloc(config.datasize+1); memset(data,'x',config.datasize); data[config.datasize] = '\0'; benchmark("PING (inline)","PING\r\n",6); len = redisFormatCommand(&cmd,"PING"); benchmark("PING",cmd,len); free(cmd); const char *argv[21]; argv[0] = "MSET"; for (i = 1; i < 21; i += 2) { argv[i] = "foo:rand:000000000000"; argv[i+1] = data; } len = redisFormatCommandArgv(&cmd,21,argv,NULL); benchmark("MSET (10 keys)",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"SET foo:rand:000000000000 %s",data); benchmark("SET",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"GET foo:rand:000000000000"); benchmark("GET",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"INCR counter:rand:000000000000"); benchmark("INCR",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"LPUSH mylist %s",data); benchmark("LPUSH",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"LPOP mylist"); benchmark("LPOP",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"SADD myset counter:rand:000000000000"); benchmark("SADD",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"SPOP myset"); benchmark("SPOP",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"LPUSH mylist %s",data); benchmark("LPUSH (again, in order to bench LRANGE)",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"LRANGE mylist 0 99"); benchmark("LRANGE (first 100 elements)",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"LRANGE mylist 0 299"); benchmark("LRANGE (first 300 elements)",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"LRANGE mylist 0 449"); benchmark("LRANGE (first 450 elements)",cmd,len); free(cmd); len = redisFormatCommand(&cmd,"LRANGE mylist 0 599"); benchmark("LRANGE (first 600 elements)",cmd,len); free(cmd); printf("\n"); } while(config.loop); #ifdef _WIN32 WSACleanup(); #endif return 0; }