# 1 "src/redis-cli.c" # 1 "" # 1 "" # 1 "src/redis-cli.c" # 31 "src/redis-cli.c" # 1 "src/fmacros.h" 1 # 32 "src/redis-cli.c" 2 # 1 "src/version.h" 1 # 33 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_typedefs.h" 1 typedef int size_t; typedef int __builtin_va_list; typedef int __gnuc_va_list; typedef int va_list; typedef int __int8_t; typedef int __uint8_t; typedef int __int16_t; typedef int __uint16_t; typedef int __int_least16_t; typedef int __uint_least16_t; typedef int __int32_t; typedef int __uint32_t; typedef int __int64_t; typedef int __uint64_t; typedef int __int_least32_t; typedef int __uint_least32_t; typedef int __s8; typedef int __u8; typedef int __s16; typedef int __u16; typedef int __s32; typedef int __u32; typedef int __s64; typedef int __u64; typedef int _LOCK_T; typedef int _LOCK_RECURSIVE_T; typedef int _off_t; typedef int __dev_t; typedef int __uid_t; typedef int __gid_t; typedef int _off64_t; typedef int _fpos_t; typedef int _ssize_t; typedef int wint_t; typedef int _mbstate_t; typedef int _flock_t; typedef int _iconv_t; typedef int __ULong; typedef int __FILE; typedef int ptrdiff_t; typedef int wchar_t; typedef int __off_t; typedef int __pid_t; typedef int __loff_t; typedef int u_char; typedef int u_short; typedef int u_int; typedef int u_long; typedef int ushort; typedef int uint; typedef int clock_t; typedef int time_t; typedef int daddr_t; typedef int caddr_t; typedef int ino_t; typedef int off_t; typedef int dev_t; typedef int uid_t; typedef int gid_t; typedef int pid_t; typedef int key_t; typedef int ssize_t; typedef int mode_t; typedef int nlink_t; typedef int fd_mask; typedef int _types_fd_set; typedef int clockid_t; typedef int timer_t; typedef int useconds_t; typedef int suseconds_t; typedef int FILE; typedef int fpos_t; typedef int cookie_read_function_t; typedef int cookie_write_function_t; typedef int cookie_seek_function_t; typedef int cookie_close_function_t; typedef int cookie_io_functions_t; typedef int div_t; typedef int ldiv_t; typedef int lldiv_t; typedef int sigset_t; typedef int __sigset_t; typedef int _sig_func_ptr; typedef int sig_atomic_t; typedef int __tzrule_type; typedef int __tzinfo_type; typedef int mbstate_t; typedef int sem_t; typedef int pthread_t; typedef int pthread_attr_t; typedef int pthread_mutex_t; typedef int pthread_mutexattr_t; typedef int pthread_cond_t; typedef int pthread_condattr_t; typedef int pthread_key_t; typedef int pthread_once_t; typedef int pthread_rwlock_t; typedef int pthread_rwlockattr_t; typedef int pthread_spinlock_t; typedef int pthread_barrier_t; typedef int pthread_barrierattr_t; typedef int jmp_buf; typedef int rlim_t; typedef int sa_family_t; typedef int sigjmp_buf; typedef int stack_t; typedef int siginfo_t; typedef int z_stream; typedef int int8_t; typedef int uint8_t; typedef int int16_t; typedef int uint16_t; typedef int int32_t; typedef int uint32_t; typedef int int64_t; typedef int uint64_t; typedef int int_least8_t; typedef int uint_least8_t; typedef int int_least16_t; typedef int uint_least16_t; typedef int int_least32_t; typedef int uint_least32_t; typedef int int_least64_t; typedef int uint_least64_t; typedef int int_fast8_t; typedef int uint_fast8_t; typedef int int_fast16_t; typedef int uint_fast16_t; typedef int int_fast32_t; typedef int uint_fast32_t; typedef int int_fast64_t; typedef int uint_fast64_t; typedef int intptr_t; typedef int uintptr_t; typedef int intmax_t; typedef int uintmax_t; typedef _Bool bool; typedef void* MirEGLNativeWindowType; typedef void* MirEGLNativeDisplayType; typedef struct MirConnection MirConnection; typedef struct MirSurface MirSurface; typedef struct MirSurfaceSpec MirSurfaceSpec; typedef struct MirScreencast MirScreencast; typedef struct MirPromptSession MirPromptSession; typedef struct MirBufferStream MirBufferStream; typedef struct MirPersistentId MirPersistentId; typedef struct MirBlob MirBlob; typedef struct MirDisplayConfig MirDisplayConfig; typedef struct xcb_connection_t xcb_connection_t; typedef uint32_t xcb_window_t; typedef uint32_t xcb_visualid_t; # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2 # 35 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 2 # 36 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 2 # 37 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/signal.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/signal.h" 2 # 38 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/unistd.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/unistd.h" 2 # 39 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 2 # 40 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/ctype.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/ctype.h" 2 # 41 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/errno.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/errno.h" 2 # 42 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/stat.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/stat.h" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_typedefs.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/stat.h" 2 # 43 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 2 # 44 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/assert.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/assert.h" 2 # 45 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/fcntl.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/fcntl.h" 2 # 46 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/limits.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/limits.h" 2 # 47 "src/redis-cli.c" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/math.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/math.h" 2 # 48 "src/redis-cli.c" 2 # 1 "deps/hiredis/hiredis.h" 1 # 36 "deps/hiredis/hiredis.h" # 1 "deps/hiredis/read.h" 1 # 35 "deps/hiredis/read.h" # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2 # 36 "deps/hiredis/read.h" 2 # 63 "deps/hiredis/read.h" typedef struct redisReadTask { int type; int elements; int idx; void *obj; struct redisReadTask *parent; void *privdata; } redisReadTask; typedef struct redisReplyObjectFunctions { void *(*createString)(const redisReadTask*, char*, size_t); void *(*createArray)(const redisReadTask*, int); void *(*createInteger)(const redisReadTask*, long long); void *(*createNil)(const redisReadTask*); void (*freeObject)(void*); } redisReplyObjectFunctions; typedef struct redisReader { int err; char errstr[128]; char *buf; size_t pos; size_t len; size_t maxbuf; redisReadTask rstack[9]; int ridx; void *reply; redisReplyObjectFunctions *fn; void *privdata; } redisReader; redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn); void redisReaderFree(redisReader *r); int redisReaderFeed(redisReader *r, const char *buf, size_t len); int redisReaderGetReply(redisReader *r, void **reply); # 37 "deps/hiredis/hiredis.h" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 2 # 38 "deps/hiredis/hiredis.h" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/time.h" 2 # 39 "deps/hiredis/hiredis.h" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdint.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdint.h" 2 # 40 "deps/hiredis/hiredis.h" 2 # 1 "deps/hiredis/sds.h" 1 # 38 "deps/hiredis/sds.h" # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/types.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/types.h" 2 # 39 "deps/hiredis/sds.h" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 2 # 40 "deps/hiredis/sds.h" 2 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdint.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdint.h" 2 # 41 "deps/hiredis/sds.h" 2 typedef char *sds; struct sdshdr5 { unsigned char flags; char buf[]; }; struct sdshdr8 { uint8_t len; uint8_t alloc; unsigned char flags; char buf[]; }; struct sdshdr16 { uint16_t len; uint16_t alloc; unsigned char flags; char buf[]; }; struct sdshdr32 { uint32_t len; uint32_t alloc; unsigned char flags; char buf[]; }; struct sdshdr64 { uint64_t len; uint64_t alloc; unsigned char flags; char buf[]; }; # 86 "deps/hiredis/sds.h" static inline size_t sdslen(const sds s) { unsigned char flags = s[-1]; switch(flags&7) { case 0: return ((flags)>>3); case 1: return ((struct sdshdr8 *)((s)-(sizeof(struct sdshdr8))))->len; case 2: return ((struct sdshdr16 *)((s)-(sizeof(struct sdshdr16))))->len; case 3: return ((struct sdshdr32 *)((s)-(sizeof(struct sdshdr32))))->len; case 4: return ((struct sdshdr64 *)((s)-(sizeof(struct sdshdr64))))->len; } return 0; } static inline size_t sdsavail(const sds s) { unsigned char flags = s[-1]; switch(flags&7) { case 0: { return 0; } case 1: { struct sdshdr8 *sh = (struct sdshdr8 *)((s)-(sizeof(struct sdshdr8)));; return sh->alloc - sh->len; } case 2: { struct sdshdr16 *sh = (struct sdshdr16 *)((s)-(sizeof(struct sdshdr16)));; return sh->alloc - sh->len; } case 3: { struct sdshdr32 *sh = (struct sdshdr32 *)((s)-(sizeof(struct sdshdr32)));; return sh->alloc - sh->len; } case 4: { struct sdshdr64 *sh = (struct sdshdr64 *)((s)-(sizeof(struct sdshdr64)));; return sh->alloc - sh->len; } } return 0; } static inline void sdssetlen(sds s, size_t newlen) { unsigned char flags = s[-1]; switch(flags&7) { case 0: { unsigned char *fp = ((unsigned char*)s)-1; *fp = 0 | (newlen << 3); } break; case 1: ((struct sdshdr8 *)((s)-(sizeof(struct sdshdr8))))->len = newlen; break; case 2: ((struct sdshdr16 *)((s)-(sizeof(struct sdshdr16))))->len = newlen; break; case 3: ((struct sdshdr32 *)((s)-(sizeof(struct sdshdr32))))->len = newlen; break; case 4: ((struct sdshdr64 *)((s)-(sizeof(struct sdshdr64))))->len = newlen; break; } } static inline void sdsinclen(sds s, size_t inc) { unsigned char flags = s[-1]; switch(flags&7) { case 0: { unsigned char *fp = ((unsigned char*)s)-1; unsigned char newlen = ((flags)>>3)+inc; *fp = 0 | (newlen << 3); } break; case 1: ((struct sdshdr8 *)((s)-(sizeof(struct sdshdr8))))->len += inc; break; case 2: ((struct sdshdr16 *)((s)-(sizeof(struct sdshdr16))))->len += inc; break; case 3: ((struct sdshdr32 *)((s)-(sizeof(struct sdshdr32))))->len += inc; break; case 4: ((struct sdshdr64 *)((s)-(sizeof(struct sdshdr64))))->len += inc; break; } } static inline size_t sdsalloc(const sds s) { unsigned char flags = s[-1]; switch(flags&7) { case 0: return ((flags)>>3); case 1: return ((struct sdshdr8 *)((s)-(sizeof(struct sdshdr8))))->alloc; case 2: return ((struct sdshdr16 *)((s)-(sizeof(struct sdshdr16))))->alloc; case 3: return ((struct sdshdr32 *)((s)-(sizeof(struct sdshdr32))))->alloc; case 4: return ((struct sdshdr64 *)((s)-(sizeof(struct sdshdr64))))->alloc; } return 0; } static inline void sdssetalloc(sds s, size_t newlen) { unsigned char flags = s[-1]; switch(flags&7) { case 0: break; case 1: ((struct sdshdr8 *)((s)-(sizeof(struct sdshdr8))))->alloc = newlen; break; case 2: ((struct sdshdr16 *)((s)-(sizeof(struct sdshdr16))))->alloc = newlen; break; case 3: ((struct sdshdr32 *)((s)-(sizeof(struct sdshdr32))))->alloc = newlen; break; case 4: ((struct sdshdr64 *)((s)-(sizeof(struct sdshdr64))))->alloc = newlen; break; } } sds sdsnewlen(const void *init, size_t initlen); sds sdsnew(const char *init); sds sdsempty(void); sds sdsdup(const sds s); void sdsfree(sds s); sds sdsgrowzero(sds s, size_t len); sds sdscatlen(sds s, const void *t, size_t len); sds sdscat(sds s, const char *t); sds sdscatsds(sds s, const sds t); sds sdscpylen(sds s, const char *t, size_t len); sds sdscpy(sds s, const char *t); sds sdscatvprintf(sds s, const char *fmt, va_list ap); sds sdscatprintf(sds s, const char *fmt, ...) ; sds sdscatfmt(sds s, char const *fmt, ...); sds sdstrim(sds s, const char *cset); void sdsrange(sds s, int start, int end); void sdsupdatelen(sds s); void sdsclear(sds s); int sdscmp(const sds s1, const sds s2); sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count); void sdsfreesplitres(sds *tokens, int count); void sdstolower(sds s); void sdstoupper(sds s); sds sdsfromlonglong(long long value); sds sdscatrepr(sds s, const char *p, size_t len); sds *sdssplitargs(const char *line, int *argc); sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen); sds sdsjoin(char **argv, int argc, char *sep); sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen); sds sdsMakeRoomFor(sds s, size_t addlen); void sdsIncrLen(sds s, int incr); sds sdsRemoveFreeSpace(sds s); size_t sdsAllocSize(sds s); void *sdsAllocPtr(sds s); void *sds_malloc(size_t size); void *sds_realloc(void *ptr, size_t size); void sds_free(void *ptr); # 41 "deps/hiredis/hiredis.h" 2 # 112 "deps/hiredis/hiredis.h" typedef struct redisReply { int type; long long integer; size_t len; char *str; size_t elements; struct redisReply **element; } redisReply; redisReader *redisReaderCreate(void); void freeReplyObject(void *reply); int redisvFormatCommand(char **target, const char *format, va_list ap); int redisFormatCommand(char **target, const char *format, ...); int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen); int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen); void redisFreeCommand(char *cmd); void redisFreeSdsCommand(sds cmd); enum redisConnectionType { REDIS_CONN_TCP, REDIS_CONN_UNIX }; typedef struct redisContext { int err; char errstr[128]; int fd; int flags; char *obuf; redisReader *reader; enum redisConnectionType connection_type; struct timeval *timeout; struct { char *host; char *source_addr; int port; } tcp; struct { char *path; } unix_sock; } redisContext; redisContext *redisConnect(const char *ip, int port); redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv); redisContext *redisConnectNonBlock(const char *ip, int port); redisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr); redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, const char *source_addr); redisContext *redisConnectUnix(const char *path); redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv); redisContext *redisConnectUnixNonBlock(const char *path); redisContext *redisConnectFd(int fd); # 184 "deps/hiredis/hiredis.h" int redisReconnect(redisContext *c); int redisSetTimeout(redisContext *c, const struct timeval tv); int redisEnableKeepAlive(redisContext *c); void redisFree(redisContext *c); int redisFreeKeepFd(redisContext *c); int redisBufferRead(redisContext *c); int redisBufferWrite(redisContext *c, int *done); int redisGetReply(redisContext *c, void **reply); int redisGetReplyFromReader(redisContext *c, void **reply); int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len); int redisvAppendCommand(redisContext *c, const char *format, va_list ap); int redisAppendCommand(redisContext *c, const char *format, ...); int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); void *redisvCommand(redisContext *c, const char *format, va_list ap); void *redisCommand(redisContext *c, const char *format, ...); void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); # 50 "src/redis-cli.c" 2 # 1 "src/sds.h" 1 # 51 "src/redis-cli.c" 2 # 1 "src/zmalloc.h" 1 # 75 "src/zmalloc.h" void *zmalloc(size_t size); void *zcalloc(size_t size); void *zrealloc(void *ptr, size_t size); void zfree(void *ptr); char *zstrdup(const char *s); size_t zmalloc_used_memory(void); void zmalloc_set_oom_handler(void (*oom_handler)(size_t)); float zmalloc_get_fragmentation_ratio(size_t rss); size_t zmalloc_get_rss(void); size_t zmalloc_get_private_dirty(long pid); size_t zmalloc_get_smap_bytes_by_field(char *field, long pid); size_t zmalloc_get_memory_size(void); void zlibc_free(void *ptr); size_t zmalloc_size(void *ptr); # 52 "src/redis-cli.c" 2 # 1 "deps/linenoise/linenoise.h" 1 # 46 "deps/linenoise/linenoise.h" typedef struct linenoiseCompletions { size_t len; char **cvec; } linenoiseCompletions; typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); typedef char*(linenoiseHintsCallback)(const char *, int *color, int *bold); typedef void(linenoiseFreeHintsCallback)(void *); void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); void linenoiseSetHintsCallback(linenoiseHintsCallback *); void linenoiseSetFreeHintsCallback(linenoiseFreeHintsCallback *); void linenoiseAddCompletion(linenoiseCompletions *, const char *); char *linenoise(const char *prompt); void linenoiseFree(void *ptr); int linenoiseHistoryAdd(const char *line); int linenoiseHistorySetMaxLen(int len); int linenoiseHistorySave(const char *filename); int linenoiseHistoryLoad(const char *filename); void linenoiseClearScreen(void); void linenoiseSetMultiLine(int ml); void linenoisePrintKeyCodes(void); # 53 "src/redis-cli.c" 2 # 1 "src/help.h" 1 static char *commandGroups[] = { "generic", "string", "list", "set", "sorted_set", "hash", "pubsub", "transactions", "connection", "server", "scripting", "hyperloglog", "cluster", "geo" }; struct commandHelp { char *name; char *params; char *summary; int group; char *since; } commandHelp[] = { { "APPEND", "key value", "Append a value to a key", 1, "2.0.0" }, { "AUTH", "password", "Authenticate to the server", 8, "1.0.0" }, { "BGREWRITEAOF", "-", "Asynchronously rewrite the append-only file", 9, "1.0.0" }, { "BGSAVE", "-", "Asynchronously save the dataset to disk", 9, "1.0.0" }, { "BITCOUNT", "key [start end]", "Count set bits in a string", 1, "2.6.0" }, { "BITFIELD", "key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP|SAT|FAIL]", "Perform arbitrary bitfield integer operations on strings", 1, "3.2.0" }, { "BITOP", "operation destkey key [key ...]", "Perform bitwise operations between strings", 1, "2.6.0" }, { "BITPOS", "key bit [start] [end]", "Find first bit set or clear in a string", 1, "2.8.7" }, { "BLPOP", "key [key ...] timeout", "Remove and get the first element in a list, or block until one is available", 2, "2.0.0" }, { "BRPOP", "key [key ...] timeout", "Remove and get the last element in a list, or block until one is available", 2, "2.0.0" }, { "BRPOPLPUSH", "source destination timeout", "Pop a value from a list, push it to another list and return it; or block until one is available", 2, "2.2.0" }, { "CLIENT GETNAME", "-", "Get the current connection name", 9, "2.6.9" }, { "CLIENT KILL", "[ip:port] [ID client-id] [TYPE normal|master|slave|pubsub] [ADDR ip:port] [SKIPME yes/no]", "Kill the connection of a client", 9, "2.4.0" }, { "CLIENT LIST", "-", "Get the list of client connections", 9, "2.4.0" }, { "CLIENT PAUSE", "timeout", "Stop processing commands from clients for some time", 9, "2.9.50" }, { "CLIENT REPLY", "ON|OFF|SKIP", "Instruct the server whether to reply to commands", 9, "3.2" }, { "CLIENT SETNAME", "connection-name", "Set the current connection name", 9, "2.6.9" }, { "CLUSTER ADDSLOTS", "slot [slot ...]", "Assign new hash slots to receiving node", 12, "3.0.0" }, { "CLUSTER COUNT-FAILURE-REPORTS", "node-id", "Return the number of failure reports active for a given node", 12, "3.0.0" }, { "CLUSTER COUNTKEYSINSLOT", "slot", "Return the number of local keys in the specified hash slot", 12, "3.0.0" }, { "CLUSTER DELSLOTS", "slot [slot ...]", "Set hash slots as unbound in receiving node", 12, "3.0.0" }, { "CLUSTER FAILOVER", "[FORCE|TAKEOVER]", "Forces a slave to perform a manual failover of its master.", 12, "3.0.0" }, { "CLUSTER FORGET", "node-id", "Remove a node from the nodes table", 12, "3.0.0" }, { "CLUSTER GETKEYSINSLOT", "slot count", "Return local key names in the specified hash slot", 12, "3.0.0" }, { "CLUSTER INFO", "-", "Provides info about Redis Cluster node state", 12, "3.0.0" }, { "CLUSTER KEYSLOT", "key", "Returns the hash slot of the specified key", 12, "3.0.0" }, { "CLUSTER MEET", "ip port", "Force a node cluster to handshake with another node", 12, "3.0.0" }, { "CLUSTER NODES", "-", "Get Cluster config for the node", 12, "3.0.0" }, { "CLUSTER REPLICATE", "node-id", "Reconfigure a node as a slave of the specified master node", 12, "3.0.0" }, { "CLUSTER RESET", "[HARD|SOFT]", "Reset a Redis Cluster node", 12, "3.0.0" }, { "CLUSTER SAVECONFIG", "-", "Forces the node to save cluster state on disk", 12, "3.0.0" }, { "CLUSTER SET-CONFIG-EPOCH", "config-epoch", "Set the configuration epoch in a new node", 12, "3.0.0" }, { "CLUSTER SETSLOT", "slot IMPORTING|MIGRATING|STABLE|NODE [node-id]", "Bind a hash slot to a specific node", 12, "3.0.0" }, { "CLUSTER SLAVES", "node-id", "List slave nodes of the specified master node", 12, "3.0.0" }, { "CLUSTER SLOTS", "-", "Get array of Cluster slot to node mappings", 12, "3.0.0" }, { "COMMAND", "-", "Get array of Redis command details", 9, "2.8.13" }, { "COMMAND COUNT", "-", "Get total number of Redis commands", 9, "2.8.13" }, { "COMMAND GETKEYS", "-", "Extract keys given a full Redis command", 9, "2.8.13" }, { "COMMAND INFO", "command-name [command-name ...]", "Get array of specific Redis command details", 9, "2.8.13" }, { "CONFIG GET", "parameter", "Get the value of a configuration parameter", 9, "2.0.0" }, { "CONFIG RESETSTAT", "-", "Reset the stats returned by INFO", 9, "2.0.0" }, { "CONFIG REWRITE", "-", "Rewrite the configuration file with the in memory configuration", 9, "2.8.0" }, { "CONFIG SET", "parameter value", "Set a configuration parameter to the given value", 9, "2.0.0" }, { "DBSIZE", "-", "Return the number of keys in the selected database", 9, "1.0.0" }, { "DEBUG OBJECT", "key", "Get debugging information about a key", 9, "1.0.0" }, { "DEBUG SEGFAULT", "-", "Make the server crash", 9, "1.0.0" }, { "DECR", "key", "Decrement the integer value of a key by one", 1, "1.0.0" }, { "DECRBY", "key decrement", "Decrement the integer value of a key by the given number", 1, "1.0.0" }, { "DEL", "key [key ...]", "Delete a key", 0, "1.0.0" }, { "DISCARD", "-", "Discard all commands issued after MULTI", 7, "2.0.0" }, { "DUMP", "key", "Return a serialized version of the value stored at the specified key.", 0, "2.6.0" }, { "ECHO", "message", "Echo the given string", 8, "1.0.0" }, { "EVAL", "script numkeys key [key ...] arg [arg ...]", "Execute a Lua script server side", 10, "2.6.0" }, { "EVALSHA", "sha1 numkeys key [key ...] arg [arg ...]", "Execute a Lua script server side", 10, "2.6.0" }, { "EXEC", "-", "Execute all commands issued after MULTI", 7, "1.2.0" }, { "EXISTS", "key [key ...]", "Determine if a key exists", 0, "1.0.0" }, { "EXPIRE", "key seconds", "Set a key's time to live in seconds", 0, "1.0.0" }, { "EXPIREAT", "key timestamp", "Set the expiration for a key as a UNIX timestamp", 0, "1.2.0" }, { "FLUSHALL", "-", "Remove all keys from all databases", 9, "1.0.0" }, { "FLUSHDB", "-", "Remove all keys from the current database", 9, "1.0.0" }, { "GEOADD", "key longitude latitude member [longitude latitude member ...]", "Add one or more geospatial items in the geospatial index represented using a sorted set", 13, "3.2.0" }, { "GEODIST", "key member1 member2 [unit]", "Returns the distance between two members of a geospatial index", 13, "3.2.0" }, { "GEOHASH", "key member [member ...]", "Returns members of a geospatial index as standard geohash strings", 13, "3.2.0" }, { "GEOPOS", "key member [member ...]", "Returns longitude and latitude of members of a geospatial index", 13, "3.2.0" }, { "GEORADIUS", "key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]", "Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a point", 13, "3.2.0" }, { "GEORADIUSBYMEMBER", "key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]", "Query a sorted set representing a geospatial index to fetch members matching a given maximum distance from a member", 13, "3.2.0" }, { "GET", "key", "Get the value of a key", 1, "1.0.0" }, { "GETBIT", "key offset", "Returns the bit value at offset in the string value stored at key", 1, "2.2.0" }, { "GETRANGE", "key start end", "Get a substring of the string stored at a key", 1, "2.4.0" }, { "GETSET", "key value", "Set the string value of a key and return its old value", 1, "1.0.0" }, { "HDEL", "key field [field ...]", "Delete one or more hash fields", 5, "2.0.0" }, { "HEXISTS", "key field", "Determine if a hash field exists", 5, "2.0.0" }, { "HGET", "key field", "Get the value of a hash field", 5, "2.0.0" }, { "HGETALL", "key", "Get all the fields and values in a hash", 5, "2.0.0" }, { "HINCRBY", "key field increment", "Increment the integer value of a hash field by the given number", 5, "2.0.0" }, { "HINCRBYFLOAT", "key field increment", "Increment the float value of a hash field by the given amount", 5, "2.6.0" }, { "HKEYS", "key", "Get all the fields in a hash", 5, "2.0.0" }, { "HLEN", "key", "Get the number of fields in a hash", 5, "2.0.0" }, { "HMGET", "key field [field ...]", "Get the values of all the given hash fields", 5, "2.0.0" }, { "HMSET", "key field value [field value ...]", "Set multiple hash fields to multiple values", 5, "2.0.0" }, { "HSCAN", "key cursor [MATCH pattern] [COUNT count]", "Incrementally iterate hash fields and associated values", 5, "2.8.0" }, { "HSET", "key field value", "Set the string value of a hash field", 5, "2.0.0" }, { "HSETNX", "key field value", "Set the value of a hash field, only if the field does not exist", 5, "2.0.0" }, { "HSTRLEN", "key field", "Get the length of the value of a hash field", 5, "3.2.0" }, { "HVALS", "key", "Get all the values in a hash", 5, "2.0.0" }, { "INCR", "key", "Increment the integer value of a key by one", 1, "1.0.0" }, { "INCRBY", "key increment", "Increment the integer value of a key by the given amount", 1, "1.0.0" }, { "INCRBYFLOAT", "key increment", "Increment the float value of a key by the given amount", 1, "2.6.0" }, { "INFO", "[section]", "Get information and statistics about the server", 9, "1.0.0" }, { "KEYS", "pattern", "Find all keys matching the given pattern", 0, "1.0.0" }, { "LASTSAVE", "-", "Get the UNIX time stamp of the last successful save to disk", 9, "1.0.0" }, { "LINDEX", "key index", "Get an element from a list by its index", 2, "1.0.0" }, { "LINSERT", "key BEFORE|AFTER pivot value", "Insert an element before or after another element in a list", 2, "2.2.0" }, { "LLEN", "key", "Get the length of a list", 2, "1.0.0" }, { "LPOP", "key", "Remove and get the first element in a list", 2, "1.0.0" }, { "LPUSH", "key value [value ...]", "Prepend one or multiple values to a list", 2, "1.0.0" }, { "LPUSHX", "key value", "Prepend a value to a list, only if the list exists", 2, "2.2.0" }, { "LRANGE", "key start stop", "Get a range of elements from a list", 2, "1.0.0" }, { "LREM", "key count value", "Remove elements from a list", 2, "1.0.0" }, { "LSET", "key index value", "Set the value of an element in a list by its index", 2, "1.0.0" }, { "LTRIM", "key start stop", "Trim a list to the specified range", 2, "1.0.0" }, { "MGET", "key [key ...]", "Get the values of all the given keys", 1, "1.0.0" }, { "MIGRATE", "host port key|"" destination-db timeout [COPY] [REPLACE] [KEYS key]", "Atomically transfer a key from a Redis instance to another one.", 0, "2.6.0" }, { "MONITOR", "-", "Listen for all requests received by the server in real time", 9, "1.0.0" }, { "MOVE", "key db", "Move a key to another database", 0, "1.0.0" }, { "MSET", "key value [key value ...]", "Set multiple keys to multiple values", 1, "1.0.1" }, { "MSETNX", "key value [key value ...]", "Set multiple keys to multiple values, only if none of the keys exist", 1, "1.0.1" }, { "MULTI", "-", "Mark the start of a transaction block", 7, "1.2.0" }, { "OBJECT", "subcommand [arguments [arguments ...]]", "Inspect the internals of Redis objects", 0, "2.2.3" }, { "PERSIST", "key", "Remove the expiration from a key", 0, "2.2.0" }, { "PEXPIRE", "key milliseconds", "Set a key's time to live in milliseconds", 0, "2.6.0" }, { "PEXPIREAT", "key milliseconds-timestamp", "Set the expiration for a key as a UNIX timestamp specified in milliseconds", 0, "2.6.0" }, { "PFADD", "key element [element ...]", "Adds the specified elements to the specified HyperLogLog.", 11, "2.8.9" }, { "PFCOUNT", "key [key ...]", "Return the approximated cardinality of the set(s) observed by the HyperLogLog at key(s).", 11, "2.8.9" }, { "PFMERGE", "destkey sourcekey [sourcekey ...]", "Merge N different HyperLogLogs into a single one.", 11, "2.8.9" }, { "PING", "[message]", "Ping the server", 8, "1.0.0" }, { "PSETEX", "key milliseconds value", "Set the value and expiration in milliseconds of a key", 1, "2.6.0" }, { "PSUBSCRIBE", "pattern [pattern ...]", "Listen for messages published to channels matching the given patterns", 6, "2.0.0" }, { "PTTL", "key", "Get the time to live for a key in milliseconds", 0, "2.6.0" }, { "PUBLISH", "channel message", "Post a message to a channel", 6, "2.0.0" }, { "PUBSUB", "subcommand [argument [argument ...]]", "Inspect the state of the Pub/Sub subsystem", 6, "2.8.0" }, { "PUNSUBSCRIBE", "[pattern [pattern ...]]", "Stop listening for messages posted to channels matching the given patterns", 6, "2.0.0" }, { "QUIT", "-", "Close the connection", 8, "1.0.0" }, { "RANDOMKEY", "-", "Return a random key from the keyspace", 0, "1.0.0" }, { "READONLY", "-", "Enables read queries for a connection to a cluster slave node", 12, "3.0.0" }, { "READWRITE", "-", "Disables read queries for a connection to a cluster slave node", 12, "3.0.0" }, { "RENAME", "key newkey", "Rename a key", 0, "1.0.0" }, { "RENAMENX", "key newkey", "Rename a key, only if the new key does not exist", 0, "1.0.0" }, { "RESTORE", "key ttl serialized-value [REPLACE]", "Create a key using the provided serialized value, previously obtained using DUMP.", 0, "2.6.0" }, { "ROLE", "-", "Return the role of the instance in the context of replication", 9, "2.8.12" }, { "RPOP", "key", "Remove and get the last element in a list", 2, "1.0.0" }, { "RPOPLPUSH", "source destination", "Remove the last element in a list, prepend it to another list and return it", 2, "1.2.0" }, { "RPUSH", "key value [value ...]", "Append one or multiple values to a list", 2, "1.0.0" }, { "RPUSHX", "key value", "Append a value to a list, only if the list exists", 2, "2.2.0" }, { "SADD", "key member [member ...]", "Add one or more members to a set", 3, "1.0.0" }, { "SAVE", "-", "Synchronously save the dataset to disk", 9, "1.0.0" }, { "SCAN", "cursor [MATCH pattern] [COUNT count]", "Incrementally iterate the keys space", 0, "2.8.0" }, { "SCARD", "key", "Get the number of members in a set", 3, "1.0.0" }, { "SCRIPT DEBUG", "YES|SYNC|NO", "Set the debug mode for executed scripts.", 10, "3.2.0" }, { "SCRIPT EXISTS", "script [script ...]", "Check existence of scripts in the script cache.", 10, "2.6.0" }, { "SCRIPT FLUSH", "-", "Remove all the scripts from the script cache.", 10, "2.6.0" }, { "SCRIPT KILL", "-", "Kill the script currently in execution.", 10, "2.6.0" }, { "SCRIPT LOAD", "script", "Load the specified Lua script into the script cache.", 10, "2.6.0" }, { "SDIFF", "key [key ...]", "Subtract multiple sets", 3, "1.0.0" }, { "SDIFFSTORE", "destination key [key ...]", "Subtract multiple sets and store the resulting set in a key", 3, "1.0.0" }, { "SELECT", "index", "Change the selected database for the current connection", 8, "1.0.0" }, { "SET", "key value [EX seconds] [PX milliseconds] [NX|XX]", "Set the string value of a key", 1, "1.0.0" }, { "SETBIT", "key offset value", "Sets or clears the bit at offset in the string value stored at key", 1, "2.2.0" }, { "SETEX", "key seconds value", "Set the value and expiration of a key", 1, "2.0.0" }, { "SETNX", "key value", "Set the value of a key, only if the key does not exist", 1, "1.0.0" }, { "SETRANGE", "key offset value", "Overwrite part of a string at key starting at the specified offset", 1, "2.2.0" }, { "SHUTDOWN", "[NOSAVE|SAVE]", "Synchronously save the dataset to disk and then shut down the server", 9, "1.0.0" }, { "SINTER", "key [key ...]", "Intersect multiple sets", 3, "1.0.0" }, { "SINTERSTORE", "destination key [key ...]", "Intersect multiple sets and store the resulting set in a key", 3, "1.0.0" }, { "SISMEMBER", "key member", "Determine if a given value is a member of a set", 3, "1.0.0" }, { "SLAVEOF", "host port", "Make the server a slave of another instance, or promote it as master", 9, "1.0.0" }, { "SLOWLOG", "subcommand [argument]", "Manages the Redis slow queries log", 9, "2.2.12" }, { "SMEMBERS", "key", "Get all the members in a set", 3, "1.0.0" }, { "SMOVE", "source destination member", "Move a member from one set to another", 3, "1.0.0" }, { "SORT", "key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination]", "Sort the elements in a list, set or sorted set", 0, "1.0.0" }, { "SPOP", "key [count]", "Remove and return one or multiple random members from a set", 3, "1.0.0" }, { "SRANDMEMBER", "key [count]", "Get one or multiple random members from a set", 3, "1.0.0" }, { "SREM", "key member [member ...]", "Remove one or more members from a set", 3, "1.0.0" }, { "SSCAN", "key cursor [MATCH pattern] [COUNT count]", "Incrementally iterate Set elements", 3, "2.8.0" }, { "STRLEN", "key", "Get the length of the value stored in a key", 1, "2.2.0" }, { "SUBSCRIBE", "channel [channel ...]", "Listen for messages published to the given channels", 6, "2.0.0" }, { "SUNION", "key [key ...]", "Add multiple sets", 3, "1.0.0" }, { "SUNIONSTORE", "destination key [key ...]", "Add multiple sets and store the resulting set in a key", 3, "1.0.0" }, { "SYNC", "-", "Internal command used for replication", 9, "1.0.0" }, { "TIME", "-", "Return the current server time", 9, "2.6.0" }, { "TTL", "key", "Get the time to live for a key", 0, "1.0.0" }, { "TYPE", "key", "Determine the type stored at key", 0, "1.0.0" }, { "UNSUBSCRIBE", "[channel [channel ...]]", "Stop listening for messages posted to the given channels", 6, "2.0.0" }, { "UNWATCH", "-", "Forget about all watched keys", 7, "2.2.0" }, { "WAIT", "numslaves timeout", "Wait for the synchronous replication of all the write commands sent in the context of the current connection", 0, "3.0.0" }, { "WATCH", "key [key ...]", "Watch the given keys to determine execution of the MULTI/EXEC block", 7, "2.2.0" }, { "ZADD", "key [NX|XX] [CH] [INCR] score member [score member ...]", "Add one or more members to a sorted set, or update its score if it already exists", 4, "1.2.0" }, { "ZCARD", "key", "Get the number of members in a sorted set", 4, "1.2.0" }, { "ZCOUNT", "key min max", "Count the members in a sorted set with scores within the given values", 4, "2.0.0" }, { "ZINCRBY", "key increment member", "Increment the score of a member in a sorted set", 4, "1.2.0" }, { "ZINTERSTORE", "destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]", "Intersect multiple sorted sets and store the resulting sorted set in a new key", 4, "2.0.0" }, { "ZLEXCOUNT", "key min max", "Count the number of members in a sorted set between a given lexicographical range", 4, "2.8.9" }, { "ZRANGE", "key start stop [WITHSCORES]", "Return a range of members in a sorted set, by index", 4, "1.2.0" }, { "ZRANGEBYLEX", "key min max [LIMIT offset count]", "Return a range of members in a sorted set, by lexicographical range", 4, "2.8.9" }, { "ZRANGEBYSCORE", "key min max [WITHSCORES] [LIMIT offset count]", "Return a range of members in a sorted set, by score", 4, "1.0.5" }, { "ZRANK", "key member", "Determine the index of a member in a sorted set", 4, "2.0.0" }, { "ZREM", "key member [member ...]", "Remove one or more members from a sorted set", 4, "1.2.0" }, { "ZREMRANGEBYLEX", "key min max", "Remove all members in a sorted set between the given lexicographical range", 4, "2.8.9" }, { "ZREMRANGEBYRANK", "key start stop", "Remove all members in a sorted set within the given indexes", 4, "2.0.0" }, { "ZREMRANGEBYSCORE", "key min max", "Remove all members in a sorted set within the given scores", 4, "1.2.0" }, { "ZREVRANGE", "key start stop [WITHSCORES]", "Return a range of members in a sorted set, by index, with scores ordered from high to low", 4, "1.2.0" }, { "ZREVRANGEBYLEX", "key max min [LIMIT offset count]", "Return a range of members in a sorted set, by lexicographical range, ordered from higher to lower strings.", 4, "2.8.9" }, { "ZREVRANGEBYSCORE", "key max min [WITHSCORES] [LIMIT offset count]", "Return a range of members in a sorted set, by score, with scores ordered from high to low", 4, "2.2.0" }, { "ZREVRANK", "key member", "Determine the index of a member in a sorted set, with scores ordered from high to low", 4, "2.0.0" }, { "ZSCAN", "key cursor [MATCH pattern] [COUNT count]", "Incrementally iterate sorted sets elements and associated scores", 4, "2.8.0" }, { "ZSCORE", "key member", "Get the score associated with the given member in a sorted set", 4, "1.2.0" }, { "ZUNIONSTORE", "destination numkeys key [key ...] [WEIGHTS weight] [AGGREGATE SUM|MIN|MAX]", "Add multiple sorted sets and store the resulting sorted set in a new key", 4, "2.0.0" } }; # 54 "src/redis-cli.c" 2 # 1 "src/anet.h" 1 # 34 "src/anet.h" # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/types.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/sys/types.h" 2 # 35 "src/anet.h" 2 # 52 "src/anet.h" int anetTcpConnect(char *err, char *addr, int port); int anetTcpNonBlockConnect(char *err, char *addr, int port); int anetTcpNonBlockBindConnect(char *err, char *addr, int port, char *source_addr); int anetTcpNonBlockBestEffortBindConnect(char *err, char *addr, int port, char *source_addr); int anetUnixConnect(char *err, char *path); int anetUnixNonBlockConnect(char *err, char *path); int anetRead(int fd, char *buf, int count); int anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len); int anetResolveIP(char *err, char *host, char *ipbuf, size_t ipbuf_len); int anetTcpServer(char *err, int port, char *bindaddr, int backlog); int anetTcp6Server(char *err, int port, char *bindaddr, int backlog); int anetUnixServer(char *err, char *path, mode_t perm, int backlog); int anetTcpAccept(char *err, int serversock, char *ip, size_t ip_len, int *port); int anetUnixAccept(char *err, int serversock); int anetWrite(int fd, char *buf, int count); int anetNonBlock(char *err, int fd); int anetBlock(char *err, int fd); int anetEnableTcpNoDelay(char *err, int fd); int anetDisableTcpNoDelay(char *err, int fd); int anetTcpKeepAlive(char *err, int fd); int anetSendTimeout(char *err, int fd, long long ms); int anetPeerToString(int fd, char *ip, size_t ip_len, int *port); int anetKeepAlive(char *err, int fd, int interval); int anetSockName(int fd, char *ip, size_t ip_len, int *port); int anetFormatAddr(char *fmt, size_t fmt_len, char *ip, int port); int anetFormatPeer(int fd, char *fmt, size_t fmt_len); int anetFormatSock(int fd, char *fmt, size_t fmt_len); # 55 "src/redis-cli.c" 2 # 1 "src/ae.h" 1 # 36 "src/ae.h" # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 1 # 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1 # 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/time.h" 2 # 37 "src/ae.h" 2 # 57 "src/ae.h" struct aeEventLoop; typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask); typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData); typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData); typedef void aeBeforeSleepProc(struct aeEventLoop *eventLoop); typedef struct aeFileEvent { int mask; aeFileProc *rfileProc; aeFileProc *wfileProc; void *clientData; } aeFileEvent; typedef struct aeTimeEvent { long long id; long when_sec; long when_ms; aeTimeProc *timeProc; aeEventFinalizerProc *finalizerProc; void *clientData; struct aeTimeEvent *next; } aeTimeEvent; typedef struct aeFiredEvent { int fd; int mask; } aeFiredEvent; typedef struct aeEventLoop { int maxfd; int setsize; long long timeEventNextId; time_t lastTime; aeFileEvent *events; aeFiredEvent *fired; aeTimeEvent *timeEventHead; int stop; void *apidata; aeBeforeSleepProc *beforesleep; aeBeforeSleepProc *aftersleep; } aeEventLoop; aeEventLoop *aeCreateEventLoop(int setsize); void aeDeleteEventLoop(aeEventLoop *eventLoop); void aeStop(aeEventLoop *eventLoop); int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask, aeFileProc *proc, void *clientData); void aeDeleteFileEvent(aeEventLoop *eventLoop, int fd, int mask); int aeGetFileEvents(aeEventLoop *eventLoop, int fd); long long aeCreateTimeEvent(aeEventLoop *eventLoop, long long milliseconds, aeTimeProc *proc, void *clientData, aeEventFinalizerProc *finalizerProc); int aeDeleteTimeEvent(aeEventLoop *eventLoop, long long id); int aeProcessEvents(aeEventLoop *eventLoop, int flags); int aeWait(int fd, int mask, long long milliseconds); void aeMain(aeEventLoop *eventLoop); char *aeGetApiName(void); void aeSetBeforeSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *beforesleep); void aeSetAfterSleepProc(aeEventLoop *eventLoop, aeBeforeSleepProc *aftersleep); int aeGetSetSize(aeEventLoop *eventLoop); int aeResizeSetSize(aeEventLoop *eventLoop, int setsize); # 56 "src/redis-cli.c" 2 # 70 "src/redis-cli.c" int spectrum_palette_color_size = 19; int spectrum_palette_color[] = {0,233,234,235,237,239,241,243,245,247,144,143,142,184,226,214,208,202,196}; int spectrum_palette_mono_size = 13; int spectrum_palette_mono[] = {0,233,234,235,237,239,241,243,245,247,249,251,253}; int *spectrum_palette; int spectrum_palette_size; static redisContext *context; static struct config { char *hostip; int hostport; char *hostsocket; long repeat; long interval; int dbnum; int interactive; int shutdown; int monitor_mode; int pubsub_mode; int latency_mode; int latency_dist_mode; int latency_history; int lru_test_mode; long long lru_test_sample_size; int cluster_mode; int cluster_reissue_command; int slave_mode; int pipe_mode; int pipe_timeout; int getrdb_mode; int stat_mode; int scan_mode; int intrinsic_latency_mode; int intrinsic_latency_duration; char *pattern; char *rdb_filename; int bigkeys; int hotkeys; int stdinarg; char *auth; int output; sds mb_delim; char prompt[128]; char *eval; int eval_ldb; int eval_ldb_sync; int eval_ldb_end; int enable_ldb_on_eval; int last_cmd_type; } config; static struct pref { int hints; } pref; static volatile sig_atomic_t force_cancel_loop = 0; static void usage(void); static void slaveMode(void); char *redisGitSHA1(void); char *redisGitDirty(void); static int cliConnect(int force); static long long ustime(void) { struct timeval tv; long long ust; gettimeofday(&tv, 0); ust = ((long long)tv.tv_sec)*1000000; ust += tv.tv_usec; return ust; } static long long mstime(void) { return ustime()/1000; } static void cliRefreshPrompt(void) { int len; if (config.eval_ldb) return; if (config.hostsocket != 0) len = snprintf(config.prompt,sizeof(config.prompt),"redis %s", config.hostsocket); else len = anetFormatAddr(config.prompt, sizeof(config.prompt), config.hostip, config.hostport); if (config.dbnum != 0) len += snprintf(config.prompt+len,sizeof(config.prompt)-len,"[%d]", config.dbnum); snprintf(config.prompt+len,sizeof(config.prompt)-len,"> "); } # 179 "src/redis-cli.c" static sds getDotfilePath(char *envoverride, char *dotfilename) { char *path = 0; sds dotPath = 0; path = getenv(envoverride); if (path != 0 && *path != '\0') { if (!strcmp("/dev/null", path)) { return 0; } dotPath = sdsnew(path); } else { char *home = getenv("HOME"); if (home != 0 && *home != '\0') { dotPath = sdscatprintf(sdsempty(), "%s/%s", home, dotfilename); } } return dotPath; } static sds percentDecode(const char *pe, size_t len) { const char *end = pe + len; sds ret = sdsempty(); const char *curr = pe; while (curr < end) { if (*curr == '%') { if ((end - curr) < 2) { fprintf(stderr, "Incomplete URI encoding\n"); exit(1); } char h = tolower(*(++curr)); char l = tolower(*(++curr)); if (!(isdigit(h) || (h >= 'a' && h <= 'f')) || !(isdigit(l) || (l >= 'a' && l <= 'f'))) { fprintf(stderr, "Illegal character in URI encoding\n"); exit(1); } char c = (((isdigit(h) ? h - '0' : h - 'a' + 10) << 4) + (isdigit(l) ? l - '0' : l - 'a' + 10)); ret = sdscatlen(ret, &c, 1); curr++; } else { ret = sdscatlen(ret, curr++, 1); } } return ret; } # 244 "src/redis-cli.c" static void parseRedisUri(const char *uri) { const char *scheme = "redis://"; const char *curr = uri; const char *end = uri + strlen(uri); const char *userinfo, *username, *port, *host, *path; if (strncasecmp(scheme, curr, strlen(scheme))) { fprintf(stderr,"Invalid URI scheme\n"); exit(1); } curr += strlen(scheme); if (curr == end) return; if ((userinfo = strchr(curr,'@'))) { if ((username = strchr(curr, ':')) && username < userinfo) { curr = username + 1; } config.auth = percentDecode(curr, userinfo - curr); curr = userinfo + 1; } if (curr == end) return; path = strchr(curr, '/'); if (*curr != '/') { host = path ? path - 1 : end; if ((port = strchr(curr, ':'))) { config.hostport = atoi(port + 1); host = port - 1; } config.hostip = sdsnewlen(curr, host - curr + 1); } curr = path ? path + 1 : end; if (curr == end) return; config.dbnum = atoi(curr); } # 295 "src/redis-cli.c" typedef struct { int type; int argc; sds *argv; sds full; struct commandHelp *org; } helpEntry; static helpEntry *helpEntries; static int helpEntriesLen; static sds cliVersion(void) { sds version; version = sdscatprintf(sdsempty(), "%s", "4.0.8"); if (strtoll(redisGitSHA1(),0,16)) { version = sdscatprintf(version, " (git:%s", redisGitSHA1()); if (strtoll(redisGitDirty(),0,10)) version = sdscatprintf(version, "-dirty"); version = sdscat(version, ")"); } return version; } static void cliInitHelp(void) { int commandslen = sizeof(commandHelp)/sizeof(struct commandHelp); int groupslen = sizeof(commandGroups)/sizeof(char*); int i, len, pos = 0; helpEntry tmp; helpEntriesLen = len = commandslen+groupslen; helpEntries = zmalloc(sizeof(helpEntry)*len); for (i = 0; i < groupslen; i++) { tmp.argc = 1; tmp.argv = zmalloc(sizeof(sds)); tmp.argv[0] = sdscatprintf(sdsempty(),"@%s",commandGroups[i]); tmp.full = tmp.argv[0]; tmp.type = 2; tmp.org = 0; helpEntries[pos++] = tmp; } for (i = 0; i < commandslen; i++) { tmp.argv = sdssplitargs(commandHelp[i].name,&tmp.argc); tmp.full = sdsnew(commandHelp[i].name); tmp.type = 1; tmp.org = &commandHelp[i]; helpEntries[pos++] = tmp; } } static void cliIntegrateHelp(void) { if (cliConnect(0) == -1) return; redisReply *reply = redisCommand(context, "COMMAND"); if(reply == 0 || reply->type != 2) return; for (size_t j = 0; j < reply->elements; j++) { redisReply *entry = reply->element[j]; if (entry->type != 2 || entry->elements < 4 || entry->element[0]->type != 1 || entry->element[1]->type != 3 || entry->element[3]->type != 3) return; char *cmdname = entry->element[0]->str; int i; for (i = 0; i < helpEntriesLen; i++) { helpEntry *he = helpEntries+i; if (!strcasecmp(he->argv[0],cmdname)) break; } if (i != helpEntriesLen) continue; helpEntriesLen++; helpEntries = zrealloc(helpEntries,sizeof(helpEntry)*helpEntriesLen); helpEntry *new = helpEntries+(helpEntriesLen-1); new->argc = 1; new->argv = zmalloc(sizeof(sds)); new->argv[0] = sdsnew(cmdname); new->full = new->argv[0]; new->type = 1; sdstoupper(new->argv[0]); struct commandHelp *ch = zmalloc(sizeof(*ch)); ch->name = new->argv[0]; ch->params = sdsempty(); int args = llabs(entry->element[1]->integer); if (entry->element[3]->integer == 1) { ch->params = sdscat(ch->params,"key "); args--; } while(args--) ch->params = sdscat(ch->params,"arg "); if (entry->element[1]->integer < 0) ch->params = sdscat(ch->params,"...options..."); ch->summary = "Help not available"; ch->group = 0; ch->since = "not known"; new->org = ch; } freeReplyObject(reply); } static void cliOutputCommandHelp(struct commandHelp *help, int group) { printf("\r\n \x1b[1m%s\x1b[0m \x1b[90m%s\x1b[0m\r\n", help->name, help->params); printf(" \x1b[33msummary:\x1b[0m %s\r\n", help->summary); printf(" \x1b[33msince:\x1b[0m %s\r\n", help->since); if (group) { printf(" \x1b[33mgroup:\x1b[0m %s\r\n", commandGroups[help->group]); } } static void cliOutputGenericHelp(void) { sds version = cliVersion(); printf( "redis-cli %s\n" "To get help about Redis commands type:\n" " \"help @\" to get a list of commands in \n" " \"help \" for help on \n" " \"help \" to get a list of possible help topics\n" " \"quit\" to exit\n" "\n" "To set redis-cli preferences:\n" " \":set hints\" enable online hints\n" " \":set nohints\" disable online hints\n" "Set your preferences in ~/.redisclirc\n", version ); sdsfree(version); } static void cliOutputHelp(int argc, char **argv) { int i, j, len; int group = -1; helpEntry *entry; struct commandHelp *help; if (argc == 0) { cliOutputGenericHelp(); return; } else if (argc > 0 && argv[0][0] == '@') { len = sizeof(commandGroups)/sizeof(char*); for (i = 0; i < len; i++) { if (strcasecmp(argv[0]+1,commandGroups[i]) == 0) { group = i; break; } } } assert(argc > 0); for (i = 0; i < helpEntriesLen; i++) { entry = &helpEntries[i]; if (entry->type != 1) continue; help = entry->org; if (group == -1) { if (argc == entry->argc) { for (j = 0; j < argc; j++) { if (strcasecmp(argv[j],entry->argv[j]) != 0) break; } if (j == argc) { cliOutputCommandHelp(help,1); } } } else { if (group == help->group) { cliOutputCommandHelp(help,0); } } } printf("\r\n"); } static void completionCallback(const char *buf, linenoiseCompletions *lc) { size_t startpos = 0; int mask; int i; size_t matchlen; sds tmp; if (strncasecmp(buf,"help ",5) == 0) { startpos = 5; while (isspace(buf[startpos])) startpos++; mask = 1 | 2; } else { mask = 1; } for (i = 0; i < helpEntriesLen; i++) { if (!(helpEntries[i].type & mask)) continue; matchlen = strlen(buf+startpos); if (strncasecmp(buf+startpos,helpEntries[i].full,matchlen) == 0) { tmp = sdsnewlen(buf,startpos); tmp = sdscat(tmp,helpEntries[i].full); linenoiseAddCompletion(lc,tmp); sdsfree(tmp); } } } static char *hintsCallback(const char *buf, int *color, int *bold) { if (!pref.hints) return 0; int i, argc, buflen = strlen(buf); sds *argv = sdssplitargs(buf,&argc); int endspace = buflen && isspace(buf[buflen-1]); if (argc == 0) { sdsfreesplitres(argv,argc); return 0; } for (i = 0; i < helpEntriesLen; i++) { if (!(helpEntries[i].type & 1)) continue; if (strcasecmp(argv[0],helpEntries[i].full) == 0) { *color = 90; *bold = 0; sds hint = sdsnew(helpEntries[i].org->params); int toremove = argc-1; while(toremove > 0 && sdslen(hint)) { if (hint[0] == '[') break; if (hint[0] == ' ') toremove--; sdsrange(hint,1,-1); } if (!endspace) { sds newhint = sdsnewlen(" ",1); newhint = sdscatsds(newhint,hint); sdsfree(hint); hint = newhint; } sdsfreesplitres(argv,argc); return hint; } } sdsfreesplitres(argv,argc); return 0; } static void freeHintsCallback(void *ptr) { sdsfree(ptr); } static int cliAuth(void) { redisReply *reply; if (config.auth == 0) return 0; reply = redisCommand(context,"AUTH %s",config.auth); if (reply != 0) { freeReplyObject(reply); return 0; } return -1; } static int cliSelect(void) { redisReply *reply; if (config.dbnum == 0) return 0; reply = redisCommand(context,"SELECT %d",config.dbnum); if (reply != 0) { int result = 0; if (reply->type == 6) result = -1; freeReplyObject(reply); return result; } return -1; } static int cliConnect(int force) { if (context == 0 || force) { if (context != 0) { redisFree(context); } if (config.hostsocket == 0) { context = redisConnect(config.hostip,config.hostport); } else { context = redisConnectUnix(config.hostsocket); } if (context->err) { fprintf(stderr,"Could not connect to Redis at "); if (config.hostsocket == 0) fprintf(stderr,"%s:%d: %s\n",config.hostip,config.hostport,context->errstr); else fprintf(stderr,"%s: %s\n",config.hostsocket,context->errstr); redisFree(context); context = 0; return -1; } anetKeepAlive(0, context->fd, 15); if (cliAuth() != 0) return -1; if (cliSelect() != 0) return -1; } return 0; } static void cliPrintContextError(void) { if (context == 0) return; fprintf(stderr,"Error: %s\n",context->errstr); } static sds cliFormatReplyTTY(redisReply *r, char *prefix) { sds out = sdsempty(); switch (r->type) { case 6: out = sdscatprintf(out,"(error) %s\n", r->str); break; case 5: out = sdscat(out,r->str); out = sdscat(out,"\n"); break; case 3: out = sdscatprintf(out,"(integer) %lld\n",r->integer); break; case 1: out = sdscatrepr(out,r->str,r->len); out = sdscat(out,"\n"); break; case 4: out = sdscat(out,"(nil)\n"); break; case 2: if (r->elements == 0) { out = sdscat(out,"(empty list or set)\n"); } else { unsigned int i, idxlen = 0; char _prefixlen[16]; char _prefixfmt[16]; sds _prefix; sds tmp; i = r->elements; do { idxlen++; i /= 10; } while(i); memset(_prefixlen,' ',idxlen+2); _prefixlen[idxlen+2] = '\0'; _prefix = sdscat(sdsnew(prefix),_prefixlen); snprintf(_prefixfmt,sizeof(_prefixfmt),"%%s%%%ud) ",idxlen); for (i = 0; i < r->elements; i++) { out = sdscatprintf(out,_prefixfmt,i == 0 ? "" : prefix,i+1); tmp = cliFormatReplyTTY(r->element[i],_prefix); out = sdscatlen(out,tmp,sdslen(tmp)); sdsfree(tmp); } sdsfree(_prefix); } break; default: fprintf(stderr,"Unknown reply type: %d\n", r->type); exit(1); } return out; } int isColorTerm(void) { char *t = getenv("TERM"); return t != 0 && strstr(t,"xterm") != 0; } sds sdscatcolor(sds o, char *s, size_t len, char *color) { if (!isColorTerm()) return sdscatlen(o,s,len); int bold = strstr(color,"bold") != 0; int ccode = 37; if (strstr(color,"red")) ccode = 31; else if (strstr(color,"green")) ccode = 32; else if (strstr(color,"yellow")) ccode = 33; else if (strstr(color,"blue")) ccode = 34; else if (strstr(color,"magenta")) ccode = 35; else if (strstr(color,"cyan")) ccode = 36; else if (strstr(color,"white")) ccode = 37; o = sdscatfmt(o,"\033[%i;%i;49m",bold,ccode); o = sdscatlen(o,s,len); o = sdscat(o,"\033[0m"); return o; } sds sdsCatColorizedLdbReply(sds o, char *s, size_t len) { char *color = "white"; if (strstr(s,"")) color = "bold"; if (strstr(s,"")) color = "green"; if (strstr(s,"")) color = "cyan"; if (strstr(s,"")) color = "red"; if (strstr(s,"")) color = "bold"; if (strstr(s,"") || strstr(s,"")) color = "magenta"; if (len > 4 && isdigit(s[3])) { if (s[1] == '>') color = "yellow"; else if (s[2] == '#') color = "bold"; } return sdscatcolor(o,s,len,color); } static sds cliFormatReplyRaw(redisReply *r) { sds out = sdsempty(), tmp; size_t i; switch (r->type) { case 4: break; case 6: out = sdscatlen(out,r->str,r->len); out = sdscatlen(out,"\n",1); break; case 5: case 1: if (r->type == 5 && config.eval_ldb) { if (strstr(r->str,"") == r->str) { config.enable_ldb_on_eval = 0; config.eval_ldb = 0; config.eval_ldb_end = 1; config.output = 0; cliRefreshPrompt(); } else { out = sdsCatColorizedLdbReply(out,r->str,r->len); } } else { out = sdscatlen(out,r->str,r->len); } break; case 3: out = sdscatprintf(out,"%lld",r->integer); break; case 2: for (i = 0; i < r->elements; i++) { if (i > 0) out = sdscat(out,config.mb_delim); tmp = cliFormatReplyRaw(r->element[i]); out = sdscatlen(out,tmp,sdslen(tmp)); sdsfree(tmp); } break; default: fprintf(stderr,"Unknown reply type: %d\n", r->type); exit(1); } return out; } static sds cliFormatReplyCSV(redisReply *r) { unsigned int i; sds out = sdsempty(); switch (r->type) { case 6: out = sdscat(out,"ERROR,"); out = sdscatrepr(out,r->str,strlen(r->str)); break; case 5: out = sdscatrepr(out,r->str,r->len); break; case 3: out = sdscatprintf(out,"%lld",r->integer); break; case 1: out = sdscatrepr(out,r->str,r->len); break; case 4: out = sdscat(out,"NIL"); break; case 2: for (i = 0; i < r->elements; i++) { sds tmp = cliFormatReplyCSV(r->element[i]); out = sdscatlen(out,tmp,sdslen(tmp)); if (i != r->elements-1) out = sdscat(out,","); sdsfree(tmp); } break; default: fprintf(stderr,"Unknown reply type: %d\n", r->type); exit(1); } return out; } static int cliReadReply(int output_raw_strings) { void *_reply; redisReply *reply; sds out = 0; int output = 1; if (redisGetReply(context,&_reply) != 0) { if (config.shutdown) { redisFree(context); context = 0; return 0; } if (config.interactive) { if (context->err == 1 && (errno == ECONNRESET || errno == EPIPE)) return -1; if (context->err == 3) return -1; } cliPrintContextError(); exit(1); return -1; } reply = (redisReply*)_reply; config.last_cmd_type = reply->type; if (config.cluster_mode && reply->type == 6 && (!strncmp(reply->str,"MOVED",5) || !strcmp(reply->str,"ASK"))) { char *p = reply->str, *s; int slot; output = 0; s = strchr(p,' '); p = strchr(s+1,' '); *p = '\0'; slot = atoi(s+1); s = strrchr(p+1,':'); *s = '\0'; sdsfree(config.hostip); config.hostip = sdsnew(p+1); config.hostport = atoi(s+1); if (config.interactive) printf("-> Redirected to slot [%d] located at %s:%d\n", slot, config.hostip, config.hostport); config.cluster_reissue_command = 1; cliRefreshPrompt(); } if (output) { if (output_raw_strings) { out = cliFormatReplyRaw(reply); } else { if (config.output == 1) { out = cliFormatReplyRaw(reply); out = sdscat(out,"\n"); } else if (config.output == 0) { out = cliFormatReplyTTY(reply,""); } else if (config.output == 2) { out = cliFormatReplyCSV(reply); out = sdscat(out,"\n"); } } fwrite(out,sdslen(out),1,stdout); sdsfree(out); } freeReplyObject(reply); return 0; } static int cliSendCommand(int argc, char **argv, int repeat) { char *command = argv[0]; size_t *argvlen; int j, output_raw; if (!config.eval_ldb && (!strcasecmp(command,"help") || !strcasecmp(command,"?"))) { cliOutputHelp(--argc, ++argv); return 0; } if (context == 0) return -1; output_raw = 0; if (!strcasecmp(command,"info") || (argc >= 2 && !strcasecmp(command,"debug") && !strcasecmp(argv[1],"htstats")) || (argc >= 2 && !strcasecmp(command,"memory") && (!strcasecmp(argv[1],"malloc-stats") || !strcasecmp(argv[1],"doctor"))) || (argc == 2 && !strcasecmp(command,"cluster") && (!strcasecmp(argv[1],"nodes") || !strcasecmp(argv[1],"info"))) || (argc == 2 && !strcasecmp(command,"client") && !strcasecmp(argv[1],"list")) || (argc == 3 && !strcasecmp(command,"latency") && !strcasecmp(argv[1],"graph")) || (argc == 2 && !strcasecmp(command,"latency") && !strcasecmp(argv[1],"doctor"))) { output_raw = 1; } if (!strcasecmp(command,"shutdown")) config.shutdown = 1; if (!strcasecmp(command,"monitor")) config.monitor_mode = 1; if (!strcasecmp(command,"subscribe") || !strcasecmp(command,"psubscribe")) config.pubsub_mode = 1; if (!strcasecmp(command,"sync") || !strcasecmp(command,"psync")) config.slave_mode = 1; if (argc == 3 && !strcasecmp(argv[0],"script") && !strcasecmp(argv[1],"debug")) { if (!strcasecmp(argv[2],"yes") || !strcasecmp(argv[2],"sync")) { config.enable_ldb_on_eval = 1; } else { config.enable_ldb_on_eval = 0; } } if (!strcasecmp(command,"eval") && config.enable_ldb_on_eval) { config.eval_ldb = 1; config.output = 1; } argvlen = zmalloc(argc*sizeof(size_t)); for (j = 0; j < argc; j++) argvlen[j] = sdslen(argv[j]); while(repeat--) { redisAppendCommandArgv(context,argc,(const char**)argv,argvlen); while (config.monitor_mode) { if (cliReadReply(output_raw) != 0) exit(1); fflush(stdout); } if (config.pubsub_mode) { if (config.output != 1) printf("Reading messages... (press Ctrl-C to quit)\n"); while (1) { if (cliReadReply(output_raw) != 0) exit(1); } } if (config.slave_mode) { printf("Entering slave output mode... (press Ctrl-C to quit)\n"); slaveMode(); config.slave_mode = 0; zfree(argvlen); return -1; } if (cliReadReply(output_raw) != 0) { zfree(argvlen); return -1; } else { if (!strcasecmp(command,"select") && argc == 2 && config.last_cmd_type != 6) { config.dbnum = atoi(argv[1]); cliRefreshPrompt(); } else if (!strcasecmp(command,"auth") && argc == 2) { cliSelect(); } } if (config.interval) usleep(config.interval); fflush(stdout); } zfree(argvlen); return 0; } static redisReply *reconnectingRedisCommand(redisContext *c, const char *fmt, ...) { redisReply *reply = 0; int tries = 0; va_list ap; assert(!c->err); while(reply == 0) { while (c->err & (1 | 3)) { printf("\r\x1b[0K"); printf("Reconnecting... %d\r", ++tries); fflush(stdout); redisFree(c); c = redisConnect(config.hostip,config.hostport); usleep(1000000); } __builtin_va_start((ap)); reply = redisvCommand(c,fmt,ap); ; if (c->err && !(c->err & (1 | 3))) { fprintf(stderr, "Error: %s\n", c->errstr); exit(1); } else if (tries > 0) { printf("\r\x1b[0K"); } } context = c; return reply; } static int parseOptions(int argc, char **argv) { int i; for (i = 1; i < argc; i++) { int lastarg = i==argc-1; if (!strcmp(argv[i],"-h") && !lastarg) { sdsfree(config.hostip); config.hostip = sdsnew(argv[++i]); } else if (!strcmp(argv[i],"-h") && lastarg) { usage(); } else if (!strcmp(argv[i],"--help")) { usage(); } else if (!strcmp(argv[i],"-x")) { config.stdinarg = 1; } else if (!strcmp(argv[i],"-p") && !lastarg) { config.hostport = atoi(argv[++i]); } else if (!strcmp(argv[i],"-s") && !lastarg) { config.hostsocket = argv[++i]; } else if (!strcmp(argv[i],"-r") && !lastarg) { config.repeat = strtoll(argv[++i],0,10); } else if (!strcmp(argv[i],"-i") && !lastarg) { double seconds = atof(argv[++i]); config.interval = seconds*1000000; } else if (!strcmp(argv[i],"-n") && !lastarg) { config.dbnum = atoi(argv[++i]); } else if (!strcmp(argv[i],"-a") && !lastarg) { config.auth = argv[++i]; } else if (!strcmp(argv[i],"-u") && !lastarg) { parseRedisUri(argv[++i]); } else if (!strcmp(argv[i],"--raw")) { config.output = 1; } else if (!strcmp(argv[i],"--no-raw")) { config.output = 0; } else if (!strcmp(argv[i],"--csv")) { config.output = 2; } else if (!strcmp(argv[i],"--latency")) { config.latency_mode = 1; } else if (!strcmp(argv[i],"--latency-dist")) { config.latency_dist_mode = 1; } else if (!strcmp(argv[i],"--mono")) { spectrum_palette = spectrum_palette_mono; spectrum_palette_size = spectrum_palette_mono_size; } else if (!strcmp(argv[i],"--latency-history")) { config.latency_mode = 1; config.latency_history = 1; } else if (!strcmp(argv[i],"--lru-test") && !lastarg) { config.lru_test_mode = 1; config.lru_test_sample_size = strtoll(argv[++i],0,10); } else if (!strcmp(argv[i],"--slave")) { config.slave_mode = 1; } else if (!strcmp(argv[i],"--stat")) { config.stat_mode = 1; } else if (!strcmp(argv[i],"--scan")) { config.scan_mode = 1; } else if (!strcmp(argv[i],"--pattern") && !lastarg) { config.pattern = argv[++i]; } else if (!strcmp(argv[i],"--intrinsic-latency") && !lastarg) { config.intrinsic_latency_mode = 1; config.intrinsic_latency_duration = atoi(argv[++i]); } else if (!strcmp(argv[i],"--rdb") && !lastarg) { config.getrdb_mode = 1; config.rdb_filename = argv[++i]; } else if (!strcmp(argv[i],"--pipe")) { config.pipe_mode = 1; } else if (!strcmp(argv[i],"--pipe-timeout") && !lastarg) { config.pipe_timeout = atoi(argv[++i]); } else if (!strcmp(argv[i],"--bigkeys")) { config.bigkeys = 1; } else if (!strcmp(argv[i],"--hotkeys")) { config.hotkeys = 1; } else if (!strcmp(argv[i],"--eval") && !lastarg) { config.eval = argv[++i]; } else if (!strcmp(argv[i],"--ldb")) { config.eval_ldb = 1; config.output = 1; } else if (!strcmp(argv[i],"--ldb-sync-mode")) { config.eval_ldb = 1; config.eval_ldb_sync = 1; config.output = 1; } else if (!strcmp(argv[i],"-c")) { config.cluster_mode = 1; } else if (!strcmp(argv[i],"-d") && !lastarg) { sdsfree(config.mb_delim); config.mb_delim = sdsnew(argv[++i]); } else if (!strcmp(argv[i],"-v") || !strcmp(argv[i], "--version")) { sds version = cliVersion(); printf("redis-cli %s\n", version); sdsfree(version); exit(0); } else { if (argv[i][0] == '-') { fprintf(stderr, "Unrecognized option or bad number of args for: '%s'\n", argv[i]); exit(1); } else { break; } } } if (config.eval_ldb && config.eval == 0) { fprintf(stderr,"Options --ldb and --ldb-sync-mode require --eval.\n"); fprintf(stderr,"Try %s --help for more information.\n", argv[0]); exit(1); } return i; } static sds readArgFromStdin(void) { char buf[1024]; sds arg = sdsempty(); while(1) { int nread = read(fileno(stdin),buf,1024); if (nread == 0) break; else if (nread == -1) { perror("Reading from standard input"); exit(1); } arg = sdscatlen(arg,buf,nread); } return arg; } static void usage(void) { sds version = cliVersion(); fprintf(stderr, "redis-cli %s\n" "\n" "Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]\n" " -h Server hostname (default: 127.0.0.1).\n" " -p Server port (default: 6379).\n" " -s Server socket (overrides hostname and port).\n" " -a Password to use when connecting to the server.\n" " -u Server URI.\n" " -r Execute specified command N times.\n" " -i When -r is used, waits seconds per command.\n" " It is possible to specify sub-second times like -i 0.1.\n" " -n Database number.\n" " -x Read last argument from STDIN.\n" " -d Multi-bulk delimiter in for raw formatting (default: \\n).\n" " -c Enable cluster mode (follow -ASK and -MOVED redirections).\n" " --raw Use raw formatting for replies (default when STDOUT is\n" " not a tty).\n" " --no-raw Force formatted output even when STDOUT is not a tty.\n" " --csv Output in CSV format.\n" " --stat Print rolling stats about server: mem, clients, ...\n" " --latency Enter a special mode continuously sampling latency.\n" " If you use this mode in an interactive session it runs\n" " forever displaying real-time stats. Otherwise if --raw or\n" " --csv is specified, or if you redirect the output to a non\n" " TTY, it samples the latency for 1 second (you can use\n" " -i to change the interval), then produces a single output\n" " and exits.\n" " --latency-history Like --latency but tracking latency changes over time.\n" " Default time interval is 15 sec. Change it using -i.\n" " --latency-dist Shows latency as a spectrum, requires xterm 256 colors.\n" " Default time interval is 1 sec. Change it using -i.\n" " --lru-test Simulate a cache workload with an 80-20 distribution.\n" " --slave Simulate a slave showing commands received from the master.\n" " --rdb Transfer an RDB dump from remote server to local file.\n" " --pipe Transfer raw Redis protocol from stdin to server.\n" " --pipe-timeout In --pipe mode, abort with error if after sending all data.\n" " no reply is received within seconds.\n" " Default timeout: %d. Use 0 to wait forever.\n" " --bigkeys Sample Redis keys looking for big keys.\n" " --hotkeys Sample Redis keys looking for hot keys.\n" " only works when maxmemory-policy is *lfu.\n" " --scan List all keys using the SCAN command.\n" " --pattern Useful with --scan to specify a SCAN pattern.\n" " --intrinsic-latency Run a test to measure intrinsic system latency.\n" " The test will run for the specified amount of seconds.\n" " --eval Send an EVAL command using the Lua script at .\n" " --ldb Used with --eval enable the Redis Lua debugger.\n" " --ldb-sync-mode Like --ldb but uses the synchronous Lua debugger, in\n" " this mode the server is blocked and script changes are\n" " are not rolled back from the server memory.\n" " --help Output this help and exit.\n" " --version Output version and exit.\n" "\n" "Examples:\n" " cat /etc/passwd | redis-cli -x set mypasswd\n" " redis-cli get mypasswd\n" " redis-cli -r 100 lpush mylist x\n" " redis-cli -r 100 -i 1 info | grep used_memory_human:\n" " redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3\n" " redis-cli --scan --pattern '*:12345*'\n" "\n" " (Note: when using --eval the comma separates KEYS[] from ARGV[] items)\n" "\n" "When no command is given, redis-cli starts in interactive mode.\n" "Type \"help\" in interactive mode for information on available commands\n" "and settings.\n" "\n", version, 30); sdsfree(version); exit(1); } static char **convertToSds(int count, char** args) { int j; char **sds = zmalloc(sizeof(char*)*count); for(j = 0; j < count; j++) sds[j] = sdsnew(args[j]); return sds; } static int issueCommandRepeat(int argc, char **argv, long repeat) { while (1) { config.cluster_reissue_command = 0; if (cliSendCommand(argc,argv,repeat) != 0) { cliConnect(1); if (cliSendCommand(argc,argv,repeat) != 0) { cliPrintContextError(); return -1; } } if (config.cluster_mode && config.cluster_reissue_command) { cliConnect(1); } else { break; } } return 0; } static int issueCommand(int argc, char **argv) { return issueCommandRepeat(argc, argv, config.repeat); } static sds *cliSplitArgs(char *line, int *argc) { if (config.eval_ldb && (strstr(line,"eval ") == line || strstr(line,"e ") == line)) { sds *argv = sds_malloc(sizeof(sds)*2); *argc = 2; int len = strlen(line); int elen = line[1] == ' ' ? 2 : 5; argv[0] = sdsnewlen(line,elen-1); argv[1] = sdsnewlen(line+elen,len-elen); return argv; } else { return sdssplitargs(line,argc); } } void cliSetPreferences(char **argv, int argc, int interactive) { if (!strcasecmp(argv[0],":set") && argc >= 2) { if (!strcasecmp(argv[1],"hints")) pref.hints = 1; else if (!strcasecmp(argv[1],"nohints")) pref.hints = 0; else { printf("%sunknown redis-cli preference '%s'\n", interactive ? "" : ".redisclirc: ", argv[1]); } } else { printf("%sunknown redis-cli internal command '%s'\n", interactive ? "" : ".redisclirc: ", argv[0]); } } void cliLoadPreferences(void) { sds rcfile = getDotfilePath("REDISCLI_RCFILE",".redisclirc"); if (rcfile == 0) return; FILE *fp = fopen(rcfile,"r"); char buf[1024]; if (fp) { while(fgets(buf,sizeof(buf),fp) != 0) { sds *argv; int argc; argv = sdssplitargs(buf,&argc); if (argc > 0) cliSetPreferences(argv,argc,0); sdsfreesplitres(argv,argc); } fclose(fp); } sdsfree(rcfile); } static void repl(void) { sds historyfile = 0; int history = 0; char *line; int argc; sds *argv; cliInitHelp(); cliIntegrateHelp(); config.interactive = 1; linenoiseSetMultiLine(1); linenoiseSetCompletionCallback(completionCallback); linenoiseSetHintsCallback(hintsCallback); linenoiseSetFreeHintsCallback(freeHintsCallback); if (isatty(fileno(stdin))) { historyfile = getDotfilePath("REDISCLI_HISTFILE",".rediscli_history"); history = 1; if (historyfile != 0) { linenoiseHistoryLoad(historyfile); } cliLoadPreferences(); } cliRefreshPrompt(); while((line = linenoise(context ? config.prompt : "not connected> ")) != 0) { if (line[0] != '\0') { argv = cliSplitArgs(line,&argc); if (history) linenoiseHistoryAdd(line); if (historyfile) linenoiseHistorySave(historyfile); if (argv == 0) { printf("Invalid argument(s)\n"); linenoiseFree(line); continue; } else if (argc > 0) { if (strcasecmp(argv[0],"quit") == 0 || strcasecmp(argv[0],"exit") == 0) { exit(0); } else if (argv[0][0] == ':') { cliSetPreferences(argv,argc,1); continue; } else if (strcasecmp(argv[0],"restart") == 0) { if (config.eval) { config.eval_ldb = 1; config.output = 1; return; } else { printf("Use 'restart' only in Lua debugging mode."); } } else if (argc == 3 && !strcasecmp(argv[0],"connect")) { sdsfree(config.hostip); config.hostip = sdsnew(argv[1]); config.hostport = atoi(argv[2]); cliRefreshPrompt(); cliConnect(1); } else if (argc == 1 && !strcasecmp(argv[0],"clear")) { linenoiseClearScreen(); } else { long long start_time = mstime(), elapsed; int repeat, skipargs = 0; char *endptr; repeat = strtol(argv[0], &endptr, 10); if (argc > 1 && *endptr == '\0' && repeat) { skipargs = 1; } else { repeat = 1; } issueCommandRepeat(argc-skipargs, argv+skipargs, repeat); if (config.eval_ldb_end) { config.eval_ldb_end = 0; cliReadReply(0); printf("\n(Lua debugging session ended%s)\n\n", config.eval_ldb_sync ? "" : " -- dataset changes rolled back"); } elapsed = mstime()-start_time; if (elapsed >= 500 && config.output == 0) { printf("(%.2fs)\n",(double)elapsed/1000); } } } sdsfreesplitres(argv,argc); } linenoiseFree(line); } exit(0); } static int noninteractive(int argc, char **argv) { int retval = 0; if (config.stdinarg) { argv = zrealloc(argv, (argc+1)*sizeof(char*)); argv[argc] = readArgFromStdin(); retval = issueCommand(argc+1, argv); } else { retval = issueCommand(argc, argv); } return retval; } static int evalMode(int argc, char **argv) { sds script = 0; FILE *fp; char buf[1024]; size_t nread; char **argv2; int j, got_comma, keys; int retval = 0; while(1) { if (config.eval_ldb) { printf( "Lua debugging session started, please use:\n" "quit -- End the session.\n" "restart -- Restart the script in debug mode again.\n" "help -- Show Lua script debugging commands.\n\n" ); } sdsfree(script); script = sdsempty(); got_comma = 0; keys = 0; fp = fopen(config.eval,"r"); if (!fp) { fprintf(stderr, "Can't open file '%s': %s\n", config.eval, strerror(errno)); exit(1); } while((nread = fread(buf,1,sizeof(buf),fp)) != 0) { script = sdscatlen(script,buf,nread); } fclose(fp); if (config.eval_ldb) { redisReply *reply = redisCommand(context, config.eval_ldb_sync ? "SCRIPT DEBUG sync": "SCRIPT DEBUG yes"); if (reply) freeReplyObject(reply); } argv2 = zmalloc(sizeof(sds)*(argc+3)); argv2[0] = sdsnew("EVAL"); argv2[1] = script; for (j = 0; j < argc; j++) { if (!got_comma && argv[j][0] == ',' && argv[j][1] == 0) { got_comma = 1; continue; } argv2[j+3-got_comma] = sdsnew(argv[j]); if (!got_comma) keys++; } argv2[2] = sdscatprintf(sdsempty(),"%d",keys); int eval_ldb = config.eval_ldb; retval = issueCommand(argc+3-got_comma, argv2); if (eval_ldb) { if (!config.eval_ldb) { printf("Eval debugging session can't start:\n"); cliReadReply(0); break; } else { strncpy(config.prompt,"lua debugger> ",sizeof(config.prompt)); repl(); cliConnect(1); printf("\n"); } } else { break; } } return retval; } static void latencyModePrint(long long min, long long max, double avg, long long count) { if (config.output == 0) { printf("min: %lld, max: %lld, avg: %.2f (%lld samples)", min, max, avg, count); fflush(stdout); } else if (config.output == 2) { printf("%lld,%lld,%.2f,%lld\n", min, max, avg, count); } else if (config.output == 1) { printf("%lld %lld %.2f %lld\n", min, max, avg, count); } } static void latencyMode(void) { redisReply *reply; long long start, latency, min = 0, max = 0, tot = 0, count = 0; long long history_interval = config.interval ? config.interval/1000 : 15000; double avg; long long history_start = mstime(); if (config.interval == 0) { config.interval = 1000; } else { config.interval /= 1000; } if (!context) exit(1); while(1) { start = mstime(); reply = reconnectingRedisCommand(context,"PING"); if (reply == 0) { fprintf(stderr,"\nI/O error\n"); exit(1); } latency = mstime()-start; freeReplyObject(reply); count++; if (count == 1) { min = max = tot = latency; avg = (double) latency; } else { if (latency < min) min = latency; if (latency > max) max = latency; tot += latency; avg = (double) tot/count; } if (config.output == 0) { printf("\x1b[0G\x1b[2K"); latencyModePrint(min,max,avg,count); } else { if (config.latency_history) { latencyModePrint(min,max,avg,count); } else if (mstime()-history_start > config.interval) { latencyModePrint(min,max,avg,count); exit(0); } } if (config.latency_history && mstime()-history_start > history_interval) { printf(" -- %.2f seconds range\n", (float)(mstime()-history_start)/1000); history_start = mstime(); min = max = tot = count = 0; } usleep(10 * 1000); } } # 1657 "src/redis-cli.c" struct distsamples { long long max; long long count; int character; }; # 1674 "src/redis-cli.c" void showLatencyDistSamples(struct distsamples *samples, long long tot) { int j; printf("\033[38;5;0m"); for (j = 0; ; j++) { int coloridx = ceil((float) samples[j].count / tot * (spectrum_palette_size-1)); int color = spectrum_palette[coloridx]; printf("\033[48;5;%dm%c", (int)color, samples[j].character); samples[j].count = 0; if (samples[j].max == 0) break; } printf("\033[0m\n"); fflush(stdout); } void showLatencyDistLegend(void) { int j; printf("---------------------------------------------\n"); printf(". - * # .01 .125 .25 .5 milliseconds\n"); printf("1,2,3,...,9 from 1 to 9 milliseconds\n"); printf("A,B,C,D,E 10,20,30,40,50 milliseconds\n"); printf("F,G,H,I,J .1,.2,.3,.4,.5 seconds\n"); printf("K,L,M,N,O,P,Q,? 1,2,4,8,16,30,60,>60 seconds\n"); printf("From 0 to 100%%: "); for (j = 0; j < spectrum_palette_size; j++) { printf("\033[48;5;%dm ", spectrum_palette[j]); } printf("\033[0m\n"); printf("---------------------------------------------\n"); } static void latencyDistMode(void) { redisReply *reply; long long start, latency, count = 0; long long history_interval = config.interval ? config.interval/1000 : 1000; long long history_start = ustime(); int j, outputs = 0; struct distsamples samples[] = { {10,0,'.'}, {125,0,'-'}, {250,0,'*'}, {500,0,'#'}, {1000,0,'1'}, {2000,0,'2'}, {3000,0,'3'}, {4000,0,'4'}, {5000,0,'5'}, {6000,0,'6'}, {7000,0,'7'}, {8000,0,'8'}, {9000,0,'9'}, {10000,0,'A'}, {20000,0,'B'}, {30000,0,'C'}, {40000,0,'D'}, {50000,0,'E'}, {100000,0,'F'}, {200000,0,'G'}, {300000,0,'H'}, {400000,0,'I'}, {500000,0,'J'}, {1000000,0,'K'}, {2000000,0,'L'}, {4000000,0,'M'}, {8000000,0,'N'}, {16000000,0,'O'}, {30000000,0,'P'}, {60000000,0,'Q'}, {0,0,'?'}, }; if (!context) exit(1); while(1) { start = ustime(); reply = reconnectingRedisCommand(context,"PING"); if (reply == 0) { fprintf(stderr,"\nI/O error\n"); exit(1); } latency = ustime()-start; freeReplyObject(reply); count++; for (j = 0; ; j++) { if (samples[j].max == 0 || latency <= samples[j].max) { samples[j].count++; break; } } if (count && (ustime()-history_start)/1000 > history_interval) { if ((outputs++ % 20) == 0) showLatencyDistLegend(); showLatencyDistSamples(samples,count); history_start = ustime(); count = 0; } usleep(10 * 1000); } } unsigned long long sendSync(int fd) { char buf[4096], *p; ssize_t nread; if (write(fd,"SYNC\r\n",6) != 6) { fprintf(stderr,"Error writing to master\n"); exit(1); } p = buf; while(1) { nread = read(fd,p,1); if (nread <= 0) { fprintf(stderr,"Error reading bulk length while SYNCing\n"); exit(1); } if (*p == '\n' && p != buf) break; if (*p != '\n') p++; } *p = '\0'; if (buf[0] == '-') { printf("SYNC with master failed: %s\n", buf); exit(1); } return strtoull(buf+1,0,10); } static void slaveMode(void) { int fd = context->fd; unsigned long long payload = sendSync(fd); char buf[1024]; int original_output = config.output; fprintf(stderr,"SYNC with master, discarding %llu " "bytes of bulk transfer...\n", payload); while(payload) { ssize_t nread; nread = read(fd,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload); if (nread <= 0) { fprintf(stderr,"Error reading RDB payload while SYNCing\n"); exit(1); } payload -= nread; } fprintf(stderr,"SYNC done. Logging commands from master.\n"); config.output = 2; while (cliReadReply(0) == 0); config.output = original_output; } static void getRDB(void) { int s = context->fd; int fd; unsigned long long payload = sendSync(s); char buf[4096]; fprintf(stderr,"SYNC sent to master, writing %llu bytes to '%s'\n", payload, config.rdb_filename); if (!strcmp(config.rdb_filename,"-")) { fd = STDOUT_FILENO; } else { fd = open(config.rdb_filename, O_CREAT|O_WRONLY, 0644); if (fd == -1) { fprintf(stderr, "Error opening '%s': %s\n", config.rdb_filename, strerror(errno)); exit(1); } } while(payload) { ssize_t nread, nwritten; nread = read(s,buf,(payload > sizeof(buf)) ? sizeof(buf) : payload); if (nread <= 0) { fprintf(stderr,"I/O Error reading RDB payload from socket\n"); exit(1); } nwritten = write(fd, buf, nread); if (nwritten != nread) { fprintf(stderr,"Error writing data to file: %s\n", strerror(errno)); exit(1); } payload -= nread; } close(s); fsync(fd); fprintf(stderr,"Transfer finished with success.\n"); exit(0); } static void pipeMode(void) { int fd = context->fd; long long errors = 0, replies = 0, obuf_len = 0, obuf_pos = 0; char ibuf[1024*16], obuf[1024*16]; char aneterr[256]; redisReader *reader = redisReaderCreate(); redisReply *reply; int eof = 0; int done = 0; char magic[20]; time_t last_read_time = time(0); srand(time(0)); if (anetNonBlock(aneterr,fd) == -1) { fprintf(stderr, "Can't set the socket in non blocking mode: %s\n", aneterr); exit(1); } while(!done) { int mask = 1; if (!eof || obuf_len != 0) mask |= 2; mask = aeWait(fd,mask,1000); if (mask & 1) { ssize_t nread; do { nread = read(fd,ibuf,sizeof(ibuf)); if (nread == -1 && errno != EAGAIN && errno != EINTR) { fprintf(stderr, "Error reading from the server: %s\n", strerror(errno)); exit(1); } if (nread > 0) { redisReaderFeed(reader,ibuf,nread); last_read_time = time(0); } } while(nread > 0); do { if (redisReaderGetReply(reader,(void**)&reply) == -1) { fprintf(stderr, "Error reading replies from server\n"); exit(1); } if (reply) { if (reply->type == 6) { fprintf(stderr,"%s\n", reply->str); errors++; } else if (eof && reply->type == 1 && reply->len == 20) { if (memcmp(reply->str,magic,20) == 0) { printf("Last reply received from server.\n"); done = 1; replies--; } } replies++; freeReplyObject(reply); } } while(reply); } if (mask & 2) { ssize_t loop_nwritten = 0; while(1) { if (obuf_len != 0) { ssize_t nwritten = write(fd,obuf+obuf_pos,obuf_len); if (nwritten == -1) { if (errno != EAGAIN && errno != EINTR) { fprintf(stderr, "Error writing to the server: %s\n", strerror(errno)); exit(1); } else { nwritten = 0; } } obuf_len -= nwritten; obuf_pos += nwritten; loop_nwritten += nwritten; if (obuf_len != 0) break; } if (obuf_len == 0 && !eof) { ssize_t nread = read(STDIN_FILENO,obuf,sizeof(obuf)); if (nread == 0) { char echo[] = "\r\n*2\r\n$4\r\nECHO\r\n$20\r\n01234567890123456789\r\n"; int j; eof = 1; for (j = 0; j < 20; j++) magic[j] = rand() & 0xff; memcpy(echo+21,magic,20); memcpy(obuf,echo,sizeof(echo)-1); obuf_len = sizeof(echo)-1; obuf_pos = 0; printf("All data transferred. Waiting for the last reply...\n"); } else if (nread == -1) { fprintf(stderr, "Error reading from stdin: %s\n", strerror(errno)); exit(1); } else { obuf_len = nread; obuf_pos = 0; } } if ((obuf_len == 0 && eof) || loop_nwritten > (128*1024)) break; } } if (eof && config.pipe_timeout > 0 && time(0)-last_read_time > config.pipe_timeout) { fprintf(stderr,"No replies for %d seconds: exiting.\n", config.pipe_timeout); errors++; break; } } redisReaderFree(reader); printf("errors: %lld, replies: %lld\n", errors, replies); if (errors) exit(1); else exit(0); } # 2079 "src/redis-cli.c" static redisReply *sendScan(unsigned long long *it) { redisReply *reply = redisCommand(context, "SCAN %llu", *it); if(reply == 0) { fprintf(stderr, "\nI/O error\n"); exit(1); } else if(reply->type == 6) { fprintf(stderr, "SCAN error: %s\n", reply->str); exit(1); } else if(reply->type != 2) { fprintf(stderr, "Non ARRAY response from SCAN!\n"); exit(1); } else if(reply->elements != 2) { fprintf(stderr, "Invalid element count from SCAN!\n"); exit(1); } assert(reply->element[0]->type == 1); assert(reply->element[1]->type == 2); *it = strtoull(reply->element[0]->str, 0, 10); return reply; } static int getDbSize(void) { redisReply *reply; int size; reply = redisCommand(context, "DBSIZE"); if(reply == 0 || reply->type != 3) { fprintf(stderr, "Couldn't determine DBSIZE!\n"); exit(1); } size = reply->integer; freeReplyObject(reply); return size; } static int toIntType(char *key, char *type) { if(!strcmp(type, "string")) { return 0; } else if(!strcmp(type, "list")) { return 1; } else if(!strcmp(type, "set")) { return 2; } else if(!strcmp(type, "hash")) { return 3; } else if(!strcmp(type, "zset")) { return 4; } else if(!strcmp(type, "none")) { return 5; } else { fprintf(stderr, "Unknown type '%s' for key '%s'\n", type, key); exit(1); } } static void getKeyTypes(redisReply *keys, int *types) { redisReply *reply; unsigned int i; for(i=0;ielements;i++) { redisAppendCommand(context, "TYPE %s", keys->element[i]->str); } for(i=0;ielements;i++) { if(redisGetReply(context, (void**)&reply)!=0) { fprintf(stderr, "Error getting type for key '%s' (%d: %s)\n", keys->element[i]->str, context->err, context->errstr); exit(1); } else if(reply->type != 5) { if(reply->type == 6) { fprintf(stderr, "TYPE returned an error: %s\n", reply->str); } else { fprintf(stderr, "Invalid reply type (%d) for TYPE on key '%s'!\n", reply->type, keys->element[i]->str); } exit(1); } types[i] = toIntType(keys->element[i]->str, reply->str); freeReplyObject(reply); } } static void getKeySizes(redisReply *keys, int *types, unsigned long long *sizes) { redisReply *reply; char *sizecmds[] = {"STRLEN","LLEN","SCARD","HLEN","ZCARD"}; unsigned int i; for(i=0;ielements;i++) { if(types[i]==5) continue; redisAppendCommand(context, "%s %s", sizecmds[types[i]], keys->element[i]->str); } for(i=0;ielements;i++) { if(types[i] == 5) { sizes[i] = 0; continue; } if(redisGetReply(context, (void**)&reply)!=0) { fprintf(stderr, "Error getting size for key '%s' (%d: %s)\n", keys->element[i]->str, context->err, context->errstr); exit(1); } else if(reply->type != 3) { fprintf(stderr, "Warning: %s on '%s' failed (may have changed type)\n", sizecmds[types[i]], keys->element[i]->str); sizes[i] = 0; } else { sizes[i] = reply->integer; } freeReplyObject(reply); } } static void findBigKeys(void) { unsigned long long biggest[5] = {0}, counts[5] = {0}, totalsize[5] = {0}; unsigned long long sampled = 0, total_keys, totlen=0, *sizes=0, it=0; sds maxkeys[5] = {0}; char *typename[] = {"string","list","set","hash","zset"}; char *typeunit[] = {"bytes","items","members","fields","members"}; redisReply *reply, *keys; unsigned int arrsize=0, i; int type, *types=0; double pct; total_keys = getDbSize(); printf("\n# Scanning the entire keyspace to find biggest keys as well as\n"); printf("# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec\n"); printf("# per 100 SCAN commands (not usually needed).\n\n"); for(i=0;i<5; i++) { maxkeys[i] = sdsempty(); if(!maxkeys[i]) { fprintf(stderr, "Failed to allocate memory for largest key names!\n"); exit(1); } } do { pct = 100 * (double)sampled/total_keys; reply = sendScan(&it); keys = reply->element[1]; if(keys->elements > arrsize) { types = zrealloc(types, sizeof(int)*keys->elements); sizes = zrealloc(sizes, sizeof(unsigned long long)*keys->elements); if(!types || !sizes) { fprintf(stderr, "Failed to allocate storage for keys!\n"); exit(1); } arrsize = keys->elements; } getKeyTypes(keys, types); getKeySizes(keys, types, sizes); for(i=0;ielements;i++) { if((type = types[i]) == 5) continue; totalsize[type] += sizes[i]; counts[type]++; totlen += keys->element[i]->len; sampled++; if(biggest[type]element[i]->str, sizes[i], typeunit[type]); maxkeys[type] = sdscpy(maxkeys[type], keys->element[i]->str); if(!maxkeys[type]) { fprintf(stderr, "Failed to allocate memory for key!\n"); exit(1); } biggest[type] = sizes[i]; } if(sampled % 1000000 == 0) { printf("[%05.2f%%] Sampled %llu keys so far\n", pct, sampled); } } if(sampled && (sampled %100) == 0 && config.interval) { usleep(config.interval); } freeReplyObject(reply); } while(it != 0); if(types) zfree(types); if(sizes) zfree(sizes); printf("\n-------- summary -------\n\n"); printf("Sampled %llu keys in the keyspace!\n", sampled); printf("Total key length in bytes is %llu (avg len %.2f)\n\n", totlen, totlen ? (double)totlen/sampled : 0); for(i=0;i<5;i++) { if(sdslen(maxkeys[i])>0) { printf("Biggest %6s found '%s' has %llu %s\n", typename[i], maxkeys[i], biggest[i], typeunit[i]); } } printf("\n"); for(i=0;i<5;i++) { printf("%llu %ss with %llu %s (%05.2f%% of keys, avg size %.2f)\n", counts[i], typename[i], totalsize[i], typeunit[i], sampled ? 100 * (double)counts[i]/sampled : 0, counts[i] ? (double)totalsize[i]/counts[i] : 0); } for(i=0;i<5;i++) { sdsfree(maxkeys[i]); } exit(0); } static void getKeyFreqs(redisReply *keys, unsigned long long *freqs) { redisReply *reply; unsigned int i; for(i=0;ielements;i++) { redisAppendCommand(context, "OBJECT freq %s", keys->element[i]->str); } for(i=0;ielements;i++) { if(redisGetReply(context, (void**)&reply)!=0) { fprintf(stderr, "Error getting freq for key '%s' (%d: %s)\n", keys->element[i]->str, context->err, context->errstr); exit(1); } else if(reply->type != 3) { if(reply->type == 6) { fprintf(stderr, "Error: %s\n", reply->str); exit(1); } else { fprintf(stderr, "Warning: OBJECT freq on '%s' failed (may have been deleted)\n", keys->element[i]->str); freqs[i] = 0; } } else { freqs[i] = reply->integer; } freeReplyObject(reply); } } static void findHotKeys(void) { redisReply *keys, *reply; unsigned long long counters[16] = {0}; sds hotkeys[16] = {0}; unsigned long long sampled = 0, total_keys, *freqs = 0, it = 0; unsigned int arrsize = 0, i, k; double pct; total_keys = getDbSize(); printf("\n# Scanning the entire keyspace to find hot keys as well as\n"); printf("# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec\n"); printf("# per 100 SCAN commands (not usually needed).\n\n"); do { pct = 100 * (double)sampled/total_keys; reply = sendScan(&it); keys = reply->element[1]; if(keys->elements > arrsize) { freqs = zrealloc(freqs, sizeof(unsigned long long)*keys->elements); if(!freqs) { fprintf(stderr, "Failed to allocate storage for keys!\n"); exit(1); } arrsize = keys->elements; } getKeyFreqs(keys, freqs); for(i=0;ielements;i++) { sampled++; if(sampled % 1000000 == 0) { printf("[%05.2f%%] Sampled %llu keys so far\n", pct, sampled); } k = 0; while (k < 16 && freqs[i] > counters[k]) k++; if (k == 0) continue; k--; if (k == 0 || counters[k] == 0) { sdsfree(hotkeys[k]); } else { sdsfree(hotkeys[0]); memmove(counters,counters+1,sizeof(counters[0])*k); memmove(hotkeys,hotkeys+1,sizeof(hotkeys[0])*k); } counters[k] = freqs[i]; hotkeys[k] = sdsnew(keys->element[i]->str); printf( "[%05.2f%%] Hot key '%s' found so far with counter %llu\n", pct, keys->element[i]->str, freqs[i]); } if(sampled && (sampled %100) == 0 && config.interval) { usleep(config.interval); } freeReplyObject(reply); } while(it != 0); if (freqs) zfree(freqs); printf("\n-------- summary -------\n\n"); printf("Sampled %llu keys in the keyspace!\n", sampled); for (i=1; i<= 16; i++) { k = 16 - i; if(counters[k]>0) { printf("hot key found with counter: %llu\tkeyname: %s\n", counters[k], hotkeys[k]); sdsfree(hotkeys[k]); } } exit(0); } # 2481 "src/redis-cli.c" static char *getInfoField(char *info, char *field) { char *p = strstr(info,field); char *n1, *n2; char *result; if (!p) return 0; p += strlen(field)+1; n1 = strchr(p,'\r'); n2 = strchr(p,','); if (n2 && n2 < n1) n1 = n2; result = zmalloc(sizeof(char)*(n1-p)+1); memcpy(result,p,(n1-p)); result[n1-p] = '\0'; return result; } static long getLongInfoField(char *info, char *field) { char *value = getInfoField(info,field); long l; if (!value) return LONG_MIN; l = strtol(value,0,10); zfree(value); return l; } void bytesToHuman(char *s, long long n) { double d; if (n < 0) { *s = '-'; s++; n = -n; } if (n < 1024) { sprintf(s,"%lldB",n); return; } else if (n < (1024*1024)) { d = (double)n/(1024); sprintf(s,"%.2fK",d); } else if (n < (1024LL*1024*1024)) { d = (double)n/(1024*1024); sprintf(s,"%.2fM",d); } else if (n < (1024LL*1024*1024*1024)) { d = (double)n/(1024LL*1024*1024); sprintf(s,"%.2fG",d); } } static void statMode(void) { redisReply *reply; long aux, requests = 0; int i = 0; while(1) { char buf[64]; int j; reply = reconnectingRedisCommand(context,"INFO"); if (reply->type == 6) { printf("ERROR: %s\n", reply->str); exit(1); } if ((i++ % 20) == 0) { printf( "------- data ------ --------------------- load -------------------- - child -\n" "keys mem clients blocked requests connections \n"); } aux = 0; for (j = 0; j < 20; j++) { long k; sprintf(buf,"db%d:keys",j); k = getLongInfoField(reply->str,buf); if (k == LONG_MIN) continue; aux += k; } sprintf(buf,"%ld",aux); printf("%-11s",buf); aux = getLongInfoField(reply->str,"used_memory"); bytesToHuman(buf,aux); printf("%-8s",buf); aux = getLongInfoField(reply->str,"connected_clients"); sprintf(buf,"%ld",aux); printf(" %-8s",buf); aux = getLongInfoField(reply->str,"blocked_clients"); sprintf(buf,"%ld",aux); printf("%-8s",buf); aux = getLongInfoField(reply->str,"total_commands_processed"); sprintf(buf,"%ld (+%ld)",aux,requests == 0 ? 0 : aux-requests); printf("%-19s",buf); requests = aux; aux = getLongInfoField(reply->str,"total_connections_received"); sprintf(buf,"%ld",aux); printf(" %-12s",buf); aux = getLongInfoField(reply->str,"bgsave_in_progress"); aux |= getLongInfoField(reply->str,"aof_rewrite_in_progress") << 1; aux |= getLongInfoField(reply->str,"loading") << 2; switch(aux) { case 0: break; case 1: printf("SAVE"); break; case 2: printf("AOF"); break; case 3: printf("SAVE+AOF"); break; case 4: printf("LOAD"); break; } printf("\n"); freeReplyObject(reply); usleep(config.interval); } } static void scanMode(void) { redisReply *reply; unsigned long long cur = 0; do { if (config.pattern) reply = redisCommand(context,"SCAN %llu MATCH %s", cur,config.pattern); else reply = redisCommand(context,"SCAN %llu",cur); if (reply == 0) { printf("I/O error\n"); exit(1); } else if (reply->type == 6) { printf("ERROR: %s\n", reply->str); exit(1); } else { unsigned int j; cur = strtoull(reply->element[0]->str,0,10); for (j = 0; j < reply->element[1]->elements; j++) printf("%s\n", reply->element[1]->element[j]->str); } freeReplyObject(reply); } while(cur != 0); exit(0); } # 2664 "src/redis-cli.c" long long powerLawRand(long long min, long long max, double alpha) { double pl, r; max += 1; r = ((double)rand()) / 32767; pl = pow( ((pow(max,alpha+1) - pow(min,alpha+1))*r + pow(min,alpha+1)), (1.0/(alpha+1))); return (max-1-(long long)pl)+min; } void LRUTestGenKey(char *buf, size_t buflen) { snprintf(buf, buflen, "lru:%lld", powerLawRand(1, config.lru_test_sample_size, 6.2)); } static void LRUTestMode(void) { redisReply *reply; char key[128]; long long start_cycle; int j; srand(time(0)^getpid()); while(1) { start_cycle = mstime(); long long hits = 0, misses = 0; while(mstime() - start_cycle < 1000) { for (j = 0; j < 250; j++) { char val[6]; val[5] = '\0'; for (int i = 0; i < 5; i++) val[i] = 'A'+rand()%('z'-'A'); LRUTestGenKey(key,sizeof(key)); redisAppendCommand(context, "SET %s %s",key,val); } for (j = 0; j < 250; j++) redisGetReply(context, (void**)&reply); for (j = 0; j < 250; j++) { LRUTestGenKey(key,sizeof(key)); redisAppendCommand(context, "GET %s",key); } for (j = 0; j < 250; j++) { if (redisGetReply(context, (void**)&reply) == 0) { switch(reply->type) { case 6: printf("%s\n", reply->str); break; case 4: misses++; break; default: hits++; break; } } } if (context->err) { fprintf(stderr,"I/O error during LRU test\n"); exit(1); } } printf( "%lld Gets/sec | Hits: %lld (%.2f%%) | Misses: %lld (%.2f%%)\n", hits+misses, hits, (double)hits/(hits+misses)*100, misses, (double)misses/(hits+misses)*100); } exit(0); } # 2756 "src/redis-cli.c" unsigned long compute_something_fast(void) { unsigned char s[256], i, j, t; int count = 1000, k; unsigned long output = 0; for (k = 0; k < 256; k++) s[k] = k; i = 0; j = 0; while(count--) { i++; j = j + s[i]; t = s[i]; s[i] = s[j]; s[j] = t; output += s[(s[i]+s[j])&255]; } return output; } static void intrinsicLatencyModeStop(int s) { ((void) s); force_cancel_loop = 1; } static void intrinsicLatencyMode(void) { long long test_end, run_time, max_latency = 0, runs = 0; run_time = config.intrinsic_latency_duration*1000000; test_end = ustime() + run_time; signal(SIGINT, intrinsicLatencyModeStop); while(1) { long long start, end, latency; start = ustime(); compute_something_fast(); end = ustime(); latency = end-start; runs++; if (latency <= 0) continue; if (latency > max_latency) { max_latency = latency; printf("Max latency so far: %lld microseconds.\n", max_latency); } double avg_us = (double)run_time/runs; double avg_ns = avg_us * 1e3; if (force_cancel_loop || end > test_end) { printf("\n%lld total runs " "(avg latency: " "%.4f microseconds / %.2f nanoseconds per run).\n", runs, avg_us, avg_ns); printf("Worst run took %.0fx longer than the average latency.\n", max_latency / avg_us); exit(0); } } } int main(int argc, char **argv) { int firstarg; config.hostip = sdsnew("127.0.0.1"); config.hostport = 6379; config.hostsocket = 0; config.repeat = 1; config.interval = 0; config.dbnum = 0; config.interactive = 0; config.shutdown = 0; config.monitor_mode = 0; config.pubsub_mode = 0; config.latency_mode = 0; config.latency_dist_mode = 0; config.latency_history = 0; config.lru_test_mode = 0; config.lru_test_sample_size = 0; config.cluster_mode = 0; config.slave_mode = 0; config.getrdb_mode = 0; config.stat_mode = 0; config.scan_mode = 0; config.intrinsic_latency_mode = 0; config.pattern = 0; config.rdb_filename = 0; config.pipe_mode = 0; config.pipe_timeout = 30; config.bigkeys = 0; config.hotkeys = 0; config.stdinarg = 0; config.auth = 0; config.eval = 0; config.eval_ldb = 0; config.eval_ldb_end = 0; config.eval_ldb_sync = 0; config.enable_ldb_on_eval = 0; config.last_cmd_type = -1; pref.hints = 1; spectrum_palette = spectrum_palette_color; spectrum_palette_size = spectrum_palette_color_size; if (!isatty(fileno(stdout)) && (getenv("FAKETTY") == 0)) config.output = 1; else config.output = 0; config.mb_delim = sdsnew("\n"); firstarg = parseOptions(argc,argv); argc -= firstarg; argv += firstarg; if (config.latency_mode) { if (cliConnect(0) == -1) exit(1); latencyMode(); } if (config.latency_dist_mode) { if (cliConnect(0) == -1) exit(1); latencyDistMode(); } if (config.slave_mode) { if (cliConnect(0) == -1) exit(1); slaveMode(); } if (config.getrdb_mode) { if (cliConnect(0) == -1) exit(1); getRDB(); } if (config.pipe_mode) { if (cliConnect(0) == -1) exit(1); pipeMode(); } if (config.bigkeys) { if (cliConnect(0) == -1) exit(1); findBigKeys(); } if (config.hotkeys) { if (cliConnect(0) == -1) exit(1); findHotKeys(); } if (config.stat_mode) { if (cliConnect(0) == -1) exit(1); if (config.interval == 0) config.interval = 1000000; statMode(); } if (config.scan_mode) { if (cliConnect(0) == -1) exit(1); scanMode(); } if (config.lru_test_mode) { if (cliConnect(0) == -1) exit(1); LRUTestMode(); } if (config.intrinsic_latency_mode) intrinsicLatencyMode(); if (argc == 0 && !config.eval) { signal(SIGPIPE, SIG_IGN); cliConnect(0); repl(); } if (cliConnect(0) != 0) exit(1); if (config.eval) { return evalMode(argc,argv); } else { return noninteractive(argc,convertToSds(argc,argv)); } }