5#include6#include

redis源码笔记 - redis-cli.c

系统 1620 0

这份代码是redis的client接口,其和server端的交互使用了deps目录下的hiredis c库,同时,在这部分代码中,应用了linenoise库完成类似history命令查询、自动补全等终端控制功能。

      
          1
      
       #include 
      
        "
      
      
        fmacros.h
      
      
        "       //用于mac下的兼容性处理
      
      
          2
      
       #include 
      
        "
      
      
        version.h
      
      
        "       //版本信息头文件,当前版本是2.4.10
      
      
          3
      
      
          4
      
       #include <stdio.h>

      
          5
      
       #include <
      
        string
      
      .h>

      
          6
      
       #include <stdlib.h>

      
          7
      
       #include <unistd.h>

      
          8
      
       #include <ctype.h>

      
          9
      
       #include <errno.h>

      
         10
      
       #include <sys/stat.h>

      
         11
      
       #include <sys/time.h>

      
         12
      
       #include <assert.h>

      
         13
      
      
         14
      
       #include 
      
        "
      
      
        hiredis.h
      
      
        "        //redis 客户端库的头文件
      
      
         15
      
       #include 
      
        "
      
      
        sds.h
      
      
        "
      
      
         16
      
       #include 
      
        "
      
      
        zmalloc.h
      
      
        "
      
      
         17
      
       #include 
      
        "
      
      
        linenoise.h
      
      
        "      //终端控制库的头文件
      
      
         18
      
       #include 
      
        "
      
      
        help.h
      
      
        "           //当前所有的命令文件汇总,用于tab自动补全功能的源数据
        
/* help entry的结构如下:

struct commandHelp {
20 char *name;          //命令名字
21 char *params;        //参数格式
22 char *summary;       //简单的解释信息
23 int group;           //命令类型(当前版本共分10种不同类型的命令)
24 char *since;         //从哪个版本开始支持此命令
25 } */

      
         19
      
      
         20
      
      
        #define
      
       REDIS_NOTUSED(V) ((void) V)

      
         21
      
      
         22
      
      
        static
      
       redisContext *
      
        context;            //维护client和server端的连接信息,包括文件描述符,错误信息等,参见deps/hiredis/hiredis.h

      
      
         23
      
      
        static
      
      
        struct
      
      
         config {

      
      
         24
      
      
        char
      
       *
      
        hostip;

      
      
         25
      
      
        int
      
      
         hostport;

      
      
         26
      
      
        char
      
       *
      
        hostsocket;

      
      
         27
      
      
        long
      
      
         repeat;                         //命令重复执行次数

      
      
         28
      
      
        long
      
      
         interval;                       //命令重复执行间隔

      
      
         29
      
      
        int
      
      
         dbnum;                           // db no.

      
      
         30
      
      
        int
      
      
         interactive;                     //交互模式 or 命令模式

      
      
         31
      
      
        int
      
      
         shutdown;

      
      
         32
      
      
        int
      
      
         monitor_mode;                    //监控模式

      
      
         33
      
      
        int
      
      
         pubsub_mode;                     //pub sub模式

      
      
         34
      
      
        int
      
      
         latency_mode;                    //该模式测试cli到server执行ping命令的时间间隔(应用层ping)

      
      
         35
      
      
        int
      
       stdinarg; 
      
        /*
      
      
         get last arg from stdin. (-x option) 
      
      
        */
      
      
         36
      
      
        char
      
       *
      
        auth;                          //需要鉴权时的密码信息

      
      
         37
      
      
        int
      
       raw_output; 
      
        /*
      
      
         output mode per command 
      
      
        */      //选择该模式,将不会添加类似(interger),参见
        
          http://blog.sina.com.cn/s/blog_6262a50e0100zw83.html
        
      
      
         38
      
      
            sds mb_delim;

      
      
         39
      
      
        char
      
       prompt[
      
        128
      
      
        ];           

      
      
         40
      
      
        } config;

      
      
         41
      
      
         42
      
      
        static
      
      
        void
      
      
         usage();

      
      
         43
      
      
        char
      
       *redisGitSHA1(
      
        void
      
      
        );

      
      
         44
      
      
        char
      
       *redisGitDirty(
      
        void
      
      
        );

      
      
         45
      
      
         46
      
      
        /*
      
      
        ------------------------------------------------------------------------------

      
      
         47
      
      
         * Utility functions

      
      
         48
      
      
         *--------------------------------------------------------------------------- 
      
      
        */
      
      
         49
      
      
         50
      
      
        static
      
      
        long
      
      
        long
      
       mstime(
      
        void
      
      
        ) {

      
      
         51
      
      
        struct
      
      
         timeval tv;

      
      
         52
      
      
        long
      
      
        long
      
      
         mst;

      
      
         53
      
      
         54
      
           gettimeofday(&
      
        tv, NULL);

      
      
         55
      
           mst = ((
      
        long
      
      )tv.tv_sec)*
      
        1000
      
      
        ;

      
      
         56
      
           mst += tv.tv_usec/
      
        1000
      
      
        ;

      
      
         57
      
      
        return
      
      
         mst;

      
      
         58
      
      
        }

      
      
         59
      
      
         60
      
      
        static
      
      
        void
      
       cliRefreshPrompt(
      
        void
      
      
        ) {

      
      
         61
      
      
        int
      
      
         len;

      
      
         62
      
      
         63
      
      
        if
      
       (config.hostsocket !=
      
         NULL)

      
      
         64
      
               len = snprintf(config.prompt,
      
        sizeof
      
      (config.prompt),
      
        "
      
      
        redis %s
      
      
        "
      
      
        ,

      
      
         65
      
      
                               config.hostsocket);

      
      
         66
      
      
        else
      
      
         67
      
               len = snprintf(config.prompt,
      
        sizeof
      
      (config.prompt),
      
        "
      
      
        redis %s:%d
      
      
        "
      
      
        ,

      
      
         68
      
      
                               config.hostip, config.hostport);

      
      
         69
      
      
        /*
      
      
         Add [dbnum] if needed 
      
      
        */
      
      
         70
      
      
        if
      
       (config.dbnum != 
      
        0
      
      
        )

      
      
         71
      
               len += snprintf(config.prompt+len,
      
        sizeof
      
      (config.prompt)-len,
      
        "
      
      
        [%d]
      
      
        "
      
      
        ,

      
      
         72
      
      
                    config.dbnum);

      
      
         73
      
           snprintf(config.prompt+len,
      
        sizeof
      
      (config.prompt)-len,
      
        "
      
      
        > 
      
      
        "
      
      
        );

      
      
         74
      
      
        }

      
      
         75
      
      
         76
      
      
        /*
      
      
        ------------------------------------------------------------------------------

      
      
         77
      
      
         * Help functions

      
      
         78
      
      
         *--------------------------------------------------------------------------- 
      
      
        */
      
      
         79
      
      
         80
      
      
        #define
      
       CLI_HELP_COMMAND 1

      
         81
      
      
        #define
      
       CLI_HELP_GROUP 2

      
         82
      
      
         83
      
       typedef 
      
        struct
      
      
         {

      
      
         84
      
      
        int
      
      
         type;

      
      
         85
      
      
        int
      
      
         argc;

      
      
         86
      
           sds *
      
        argv;

      
      
         87
      
      
            sds full;

      
      
         88
      
      
         89
      
      
        /*
      
      
         Only used for help on commands 
      
      
        */
      
      
         90
      
      
        struct
      
       commandHelp *
      
        org;

      
      
         91
      
      
        } helpEntry;

      
      
         92
      
      
         93
      
      
        static
      
       helpEntry *
      
        helpEntries;

      
      
         94
      
      
        static
      
      
        int
      
      
         helpEntriesLen;

      
      
         95
      
      
         96
      
      
        static
      
      
         sds cliVersion() {

      
      
         97
      
      
            sds version;

      
      
         98
      
           version = sdscatprintf(sdsempty(), 
      
        "
      
      
        %s
      
      
        "
      
      
        , REDIS_VERSION);

      
      
         99
      
      
        100
      
      
        /*
      
      
         Add git commit and working tree status when available 
      
      
        */
      
      
        101
      
      
        if
      
       (strtoll(redisGitSHA1(),NULL,
      
        16
      
      
        )) {

      
      
        102
      
               version = sdscatprintf(version, 
      
        "
      
      
         (git:%s
      
      
        "
      
      
        , redisGitSHA1());

      
      
        103
      
      
        if
      
       (strtoll(redisGitDirty(),NULL,
      
        10
      
      
        ))

      
      
        104
      
                   version = sdscatprintf(version, 
      
        "
      
      
        -dirty
      
      
        "
      
      
        );

      
      
        105
      
               version = sdscat(version, 
      
        "
      
      
        )
      
      
        "
      
      
        );

      
      
        106
      
      
            }

      
      
        107
      
      
        return
      
      
         version;

      
      
        108
      
      
        }

      
      
        109
      
      
        110
      
      
        static
      
      
        void
      
      
         cliInitHelp() {

      
      
        111
      
      
        int
      
       commandslen = 
      
        sizeof
      
      (commandHelp)/
      
        sizeof
      
      (
      
        struct
      
      
         commandHelp);

      
      
        112
      
      
        int
      
       groupslen = 
      
        sizeof
      
      (commandGroups)/
      
        sizeof
      
      (
      
        char
      
      *
      
        );

      
      
        113
      
      
        int
      
       i, len, pos = 
      
        0
      
      
        ;

      
      
        114
      
      
            helpEntry tmp;

      
      
        115
      
      
        116
      
           helpEntriesLen = len = commandslen+
      
        groupslen;

      
      
        117
      
           helpEntries = malloc(
      
        sizeof
      
      (helpEntry)*
      
        len);

      
      
        118
      
      
        119
      
      
        for
      
       (i = 
      
        0
      
      ; i < groupslen; i++
      
        ) {

      
      
        120
      
               tmp.argc = 
      
        1
      
      
        ;

      
      
        121
      
               tmp.argv = malloc(
      
        sizeof
      
      
        (sds));

      
      
        122
      
               tmp.argv[
      
        0
      
      ] = sdscatprintf(sdsempty(),
      
        "
      
      
        @%s
      
      
        "
      
      
        ,commandGroups[i]);

      
      
        123
      
               tmp.full = tmp.argv[
      
        0
      
      
        ];

      
      
        124
      
               tmp.type =
      
         CLI_HELP_GROUP;

      
      
        125
      
               tmp.org =
      
         NULL;

      
      
        126
      
               helpEntries[pos++] =
      
         tmp;

      
      
        127
      
      
            }

      
      
        128
      
      
        129
      
      
        for
      
       (i = 
      
        0
      
      ; i < commandslen; i++
      
        ) {

      
      
        130
      
               tmp.argv = sdssplitargs(commandHelp[i].name,&
      
        tmp.argc);

      
      
        131
      
               tmp.full =
      
         sdsnew(commandHelp[i].name);

      
      
        132
      
               tmp.type =
      
         CLI_HELP_COMMAND;

      
      
        133
      
               tmp.org = &
      
        commandHelp[i];

      
      
        134
      
               helpEntries[pos++] =
      
         tmp;

      
      
        135
      
      
            }

      
      
        136
      
      
        }

      
      
        137
      
      
        138
      
      
        /*
      
      
         Output command help to stdout. 
      
      
        */
      
      
        139
      
      
        static
      
      
        void
      
       cliOutputCommandHelp(
      
        struct
      
       commandHelp *help, 
      
        int
      
      
         group) {

      
      
        140
      
           printf(
      
        "
      
      
        \r\n  \x1b[1m%s\x1b[0m \x1b[90m%s\x1b[0m\r\n
      
      
        "
      
      , help->name, help->
      
        params
      
      
        );

      
      
        141
      
           printf(
      
        "
      
      
          \x1b[33msummary:\x1b[0m %s\r\n
      
      
        "
      
      , help->
      
        summary);

      
      
        142
      
           printf(
      
        "
      
      
          \x1b[33msince:\x1b[0m %s\r\n
      
      
        "
      
      , help->
      
        since);

      
      
        143
      
      
        if
      
      
         (group) {

      
      
        144
      
               printf(
      
        "
      
      
          \x1b[33mgroup:\x1b[0m %s\r\n
      
      
        "
      
      , commandGroups[help->
      
        group]);

      
      
        145
      
      
            }

      
      
        146
      
      
        }

      
      
        147
      
      
        148
      
      
        /*
      
      
         Print generic help. 
      
      
        */
      
      
        149
      
      
        static
      
      
        void
      
      
         cliOutputGenericHelp() {

      
      
        150
      
           sds version =
      
         cliVersion();

      
      
        151
      
      
            printf(

      
      
        152
      
      
        "
      
      
        redis-cli %s\r\n
      
      
        "
      
      
        153
      
      
        "
      
      
        Type: \"help @<group>\" to get a list of commands in <group>\r\n
      
      
        "
      
      
        154
      
      
        "
      
      
              \"help <command>\" for help on <command>\r\n
      
      
        "
      
      
        155
      
      
        "
      
      
              \"help <tab>\" to get a list of possible help topics\r\n
      
      
        "
      
      
        156
      
      
        "
      
      
              \"quit\" to exit\r\n
      
      
        "
      
      
        ,

      
      
        157
      
      
                version

      
      
        158
      
      
            );

      
      
        159
      
      
            sdsfree(version);

      
      
        160
      
      
        }

      
      
        161
      
      
        162
      
      
        /*
      
      
         Output all command help, filtering by group or command name. 
      
      
        */
      
      
        163
      
      
        static
      
      
        void
      
       cliOutputHelp(
      
        int
      
       argc, 
      
        char
      
       **
      
        argv) {

      
      
        164
      
      
        int
      
      
         i, j, len;

      
      
        165
      
      
        int
      
       group = -
      
        1
      
      
        ;

      
      
        166
      
           helpEntry *
      
        entry;

      
      
        167
      
      
        struct
      
       commandHelp *
      
        help;

      
      
        168
      
      
        169
      
      
        if
      
       (argc == 
      
        0
      
      
        ) {

      
      
        170
      
      
                cliOutputGenericHelp();

      
      
        171
      
      
        return
      
      
        ;

      
      
        172
      
           } 
      
        else
      
      
        if
      
       (argc > 
      
        0
      
       && argv[
      
        0
      
      ][
      
        0
      
      ] == 
      
        '
      
      
        @
      
      
        '
      
      
        ) {

      
      
        173
      
               len = 
      
        sizeof
      
      (commandGroups)/
      
        sizeof
      
      (
      
        char
      
      *
      
        );

      
      
        174
      
      
        for
      
       (i = 
      
        0
      
      ; i < len; i++
      
        ) {

      
      
        175
      
      
        if
      
       (strcasecmp(argv[
      
        0
      
      ]+
      
        1
      
      ,commandGroups[i]) == 
      
        0
      
      
        ) {

      
      
        176
      
                       group =
      
         i;

      
      
        177
      
      
        break
      
      
        ;

      
      
        178
      
      
                    }

      
      
        179
      
      
                }

      
      
        180
      
      
            }

      
      
        181
      
      
        182
      
           assert(argc > 
      
        0
      
      
        );

      
      
        183
      
      
        for
      
       (i = 
      
        0
      
      ; i < helpEntriesLen; i++
      
        ) {

      
      
        184
      
               entry = &
      
        helpEntries[i];

      
      
        185
      
      
        if
      
       (entry->type != CLI_HELP_COMMAND) 
      
        continue
      
      
        ;

      
      
        186
      
      
        187
      
               help = entry->
      
        org;

      
      
        188
      
      
        if
      
       (group == -
      
        1
      
      
        ) {

      
      
        189
      
      
        /*
      
      
         Compare all arguments 
      
      
        */
      
      
        190
      
      
        if
      
       (argc == entry->
      
        argc) {

      
      
        191
      
      
        for
      
       (j = 
      
        0
      
      ; j < argc; j++
      
        ) {

      
      
        192
      
      
        if
      
       (strcasecmp(argv[j],entry->argv[j]) != 
      
        0
      
      ) 
      
        break
      
      
        ;

      
      
        193
      
      
                        }

      
      
        194
      
      
        if
      
       (j ==
      
         argc) {

      
      
        195
      
                           cliOutputCommandHelp(help,
      
        1
      
      
        );

      
      
        196
      
      
                        }

      
      
        197
      
      
                    }

      
      
        198
      
               } 
      
        else
      
      
         {

      
      
        199
      
      
        if
      
       (group == help->
      
        group) {

      
      
        200
      
                       cliOutputCommandHelp(help,
      
        0
      
      
        );

      
      
        201
      
      
                    }

      
      
        202
      
      
                }

      
      
        203
      
      
            }

      
      
        204
      
           printf(
      
        "
      
      
        \r\n
      
      
        "
      
      
        );

      
      
        205
      
      
        }

      
      
        206
      
      
        207
      
      
        static
      
      
        void
      
       completionCallback(
      
        const
      
      
        char
      
       *buf, linenoiseCompletions *
      
        lc) {

      
      
        208
      
           size_t startpos = 
      
        0
      
      
        ;

      
      
        209
      
      
        int
      
      
         mask;

      
      
        210
      
      
        int
      
      
         i;

      
      
        211
      
      
            size_t matchlen;

      
      
        212
      
      
            sds tmp;

      
      
        213
      
      
        214
      
      
        if
      
       (strncasecmp(buf,
      
        "
      
      
        help 
      
      
        "
      
      ,
      
        5
      
      ) == 
      
        0
      
      
        ) {

      
      
        215
      
               startpos = 
      
        5
      
      
        ;

      
      
        216
      
      
        while
      
       (isspace(buf[startpos])) startpos++
      
        ;

      
      
        217
      
               mask = CLI_HELP_COMMAND |
      
         CLI_HELP_GROUP;

      
      
        218
      
           } 
      
        else
      
      
         {

      
      
        219
      
               mask =
      
         CLI_HELP_COMMAND;

      
      
        220
      
      
            }

      
      
        221
      
      
        222
      
      
        for
      
       (i = 
      
        0
      
      ; i < helpEntriesLen; i++
      
        ) {

      
      
        223
      
      
        if
      
       (!(helpEntries[i].type & mask)) 
      
        continue
      
      
        ;

      
      
        224
      
      
        225
      
               matchlen = strlen(buf+
      
        startpos);

      
      
        226
      
      
        if
      
       (strncasecmp(buf+startpos,helpEntries[i].full,matchlen) == 
      
        0
      
      
        ) {

      
      
        227
      
                   tmp =
      
         sdsnewlen(buf,startpos);

      
      
        228
      
                   tmp =
      
         sdscat(tmp,helpEntries[i].full);

      
      
        229
      
      
                    linenoiseAddCompletion(lc,tmp);

      
      
        230
      
      
                    sdsfree(tmp);

      
      
        231
      
      
                }

      
      
        232
      
      
            }

      
      
        233
      
      
        }

      
      
        234
      
      
        235
      
      
        /*
      
      
        ------------------------------------------------------------------------------

      
      
        236
      
      
         * Networking / parsing

      
      
        237
      
      
         *--------------------------------------------------------------------------- 
      
      
        */
      
      
        238
      
      
        239
      
      
        /*
      
      
         Send AUTH command to the server 
      
      
        */
      
      
        240
      
      
        static
      
      
        int
      
      
         cliAuth() {

      
      
        241
      
           redisReply *
      
        reply;

      
      
        242
      
      
        if
      
       (config.auth == NULL) 
      
        return
      
      
         REDIS_OK;

      
      
        243
      
      
        244
      
           reply = redisCommand(context,
      
        "
      
      
        AUTH %s
      
      
        "
      
      
        ,config.auth);

      
      
        245
      
      
        if
      
       (reply !=
      
         NULL) {

      
      
        246
      
      
                freeReplyObject(reply);

      
      
        247
      
      
        return
      
      
         REDIS_OK;

      
      
        248
      
      
            }

      
      
        249
      
      
        return
      
      
         REDIS_ERR;

      
      
        250
      
      
        }

      
      
        251
      
      
        252
      
      
        /*
      
      
         Send SELECT dbnum to the server 
      
      
        */
      
      
        253
      
      
        static
      
      
        int
      
      
         cliSelect() {

      
      
        254
      
           redisReply *
      
        reply;

      
      
        255
      
      
        if
      
       (config.dbnum == 
      
        0
      
      ) 
      
        return
      
      
         REDIS_OK;

      
      
        256
      
      
        257
      
           reply = redisCommand(context,
      
        "
      
      
        SELECT %d
      
      
        "
      
      
        ,config.dbnum);

      
      
        258
      
      
        if
      
       (reply !=
      
         NULL) {

      
      
        259
      
      
                freeReplyObject(reply);

      
      
        260
      
      
        return
      
      
         REDIS_OK;

      
      
        261
      
      
            }

      
      
        262
      
      
        return
      
      
         REDIS_ERR;

      
      
        263
      
      
        }

      
      
        264
      
      
        265
      
      
        /*
      
      
         Connect to the client. If force is not zero the connection is performed

      
      
        266
      
      
         * even if there is already a connected socket. 
      
      
        */
      
      
        267
      
      
        static
      
      
        int
      
       cliConnect(
      
        int
      
      
         force) {

      
      
        268
      
      
        if
      
       (context == NULL ||
      
         force) {

      
      
        269
      
      
        if
      
       (context !=
      
         NULL)

      
      
        270
      
      
                    redisFree(context);

      
      
        271
      
      
        272
      
      
        if
      
       (config.hostsocket ==
      
         NULL) {

      
      
        273
      
                   context =
      
         redisConnect(config.hostip,config.hostport);

      
      
        274
      
               } 
      
        else
      
      
         {

      
      
        275
      
                   context =
      
         redisConnectUnix(config.hostsocket);

      
      
        276
      
      
                }

      
      
        277
      
      
        278
      
      
        if
      
       (context->
      
        err) {

      
      
        279
      
                   fprintf(stderr,
      
        "
      
      
        Could not connect to Redis at 
      
      
        "
      
      
        );

      
      
        280
      
      
        if
      
       (config.hostsocket ==
      
         NULL)

      
      
        281
      
                       fprintf(stderr,
      
        "
      
      
        %s:%d: %s\n
      
      
        "
      
      ,config.hostip,config.hostport,context->
      
        errstr);

      
      
        282
      
      
        else
      
      
        283
      
                       fprintf(stderr,
      
        "
      
      
        %s: %s\n
      
      
        "
      
      ,config.hostsocket,context->
      
        errstr);

      
      
        284
      
      
                    redisFree(context);

      
      
        285
      
                   context =
      
         NULL;

      
      
        286
      
      
        return
      
      
         REDIS_ERR;

      
      
        287
      
      
                }

      
      
        288
      
      
        289
      
      
        /*
      
      
         Do AUTH and select the right DB. 
      
      
        */
      
      
        290
      
      
        if
      
       (cliAuth() !=
      
         REDIS_OK)

      
      
        291
      
      
        return
      
      
         REDIS_ERR;

      
      
        292
      
      
        if
      
       (cliSelect() !=
      
         REDIS_OK)

      
      
        293
      
      
        return
      
      
         REDIS_ERR;

      
      
        294
      
      
            }

      
      
        295
      
      
        return
      
      
         REDIS_OK;

      
      
        296
      
      
        }

      
      
        297
      
      
        298
      
      
        static
      
      
        void
      
      
         cliPrintContextError() {

      
      
        299
      
      
        if
      
       (context == NULL) 
      
        return
      
      
        ;

      
      
        300
      
           fprintf(stderr,
      
        "
      
      
        Error: %s\n
      
      
        "
      
      ,context->
      
        errstr);

      
      
        301
      
      
        }

      
      
        302
      
      
        303
      
      
        static
      
       sds cliFormatReplyTTY(redisReply *r, 
      
        char
      
       *
      
        prefix) {

      
      
        304
      
           sds 
      
        out
      
       =
      
         sdsempty();

      
      
        305
      
      
        switch
      
       (r->
      
        type) {

      
      
        306
      
      
        case
      
      
         REDIS_REPLY_ERROR:

      
      
        307
      
      
        out
      
       = sdscatprintf(
      
        out
      
      ,
      
        "
      
      
        (error) %s\n
      
      
        "
      
      , r->
      
        str);

      
      
        308
      
      
        break
      
      
        ;

      
      
        309
      
      
        case
      
      
         REDIS_REPLY_STATUS:

      
      
        310
      
      
        out
      
       = sdscat(
      
        out
      
      ,r->
      
        str);

      
      
        311
      
      
        out
      
       = sdscat(
      
        out
      
      ,
      
        "
      
      
        \n
      
      
        "
      
      
        );

      
      
        312
      
      
        break
      
      
        ;

      
      
        313
      
      
        case
      
      
         REDIS_REPLY_INTEGER:

      
      
        314
      
      
        out
      
       = sdscatprintf(
      
        out
      
      ,
      
        "
      
      
        (integer) %lld\n
      
      
        "
      
      ,r->
      
        integer);

      
      
        315
      
      
        break
      
      
        ;

      
      
        316
      
      
        case
      
      
         REDIS_REPLY_STRING:

      
      
        317
      
      
        /*
      
      
         If you are producing output for the standard output we want

      
      
        318
      
      
                * a more interesting output with quoted characters and so forth 
      
      
        */
      
      
        319
      
      
        out
      
       = sdscatrepr(
      
        out
      
      ,r->str,r->
      
        len);

      
      
        320
      
      
        out
      
       = sdscat(
      
        out
      
      ,
      
        "
      
      
        \n
      
      
        "
      
      
        );

      
      
        321
      
      
        break
      
      
        ;

      
      
        322
      
      
        case
      
      
         REDIS_REPLY_NIL:

      
      
        323
      
      
        out
      
       = sdscat(
      
        out
      
      ,
      
        "
      
      
        (nil)\n
      
      
        "
      
      
        );

      
      
        324
      
      
        break
      
      
        ;

      
      
        325
      
      
        case
      
      
         REDIS_REPLY_ARRAY:

      
      
        326
      
      
        if
      
       (r->elements == 
      
        0
      
      
        ) {

      
      
        327
      
      
        out
      
       = sdscat(
      
        out
      
      ,
      
        "
      
      
        (empty list or set)\n
      
      
        "
      
      
        );

      
      
        328
      
               } 
      
        else
      
      
         {

      
      
        329
      
                   unsigned 
      
        int
      
       i, idxlen = 
      
        0
      
      
        ;

      
      
        330
      
      
        char
      
       _prefixlen[
      
        16
      
      
        ];

      
      
        331
      
      
        char
      
       _prefixfmt[
      
        16
      
      
        ];

      
      
        332
      
      
                    sds _prefix;

      
      
        333
      
      
                    sds tmp;

      
      
        334
      
      
        335
      
      
        /*
      
      
         Calculate chars needed to represent the largest index 
      
      
        */
      
      
        336
      
                   i = r->
      
        elements;

      
      
        337
      
      
        do
      
      
         {

      
      
        338
      
                       idxlen++
      
        ;

      
      
        339
      
                       i /= 
      
        10
      
      
        ;

      
      
        340
      
                   } 
      
        while
      
      
        (i);

      
      
        341
      
      
        342
      
      
        /*
      
      
         Prefix for nested multi bulks should grow with idxlen+2 spaces 
      
      
        */
      
      
        343
      
                   memset(_prefixlen,
      
        '
      
      
        '
      
      ,idxlen+
      
        2
      
      
        );

      
      
        344
      
                   _prefixlen[idxlen+
      
        2
      
      ] = 
      
        '
      
      
        \0
      
      
        '
      
      
        ;

      
      
        345
      
                   _prefix =
      
         sdscat(sdsnew(prefix),_prefixlen);

      
      
        346
      
      
        347
      
      
        /*
      
      
         Setup prefix format for every entry 
      
      
        */
      
      
        348
      
                   snprintf(_prefixfmt,
      
        sizeof
      
      (_prefixfmt),
      
        "
      
      
        %%s%%%dd) 
      
      
        "
      
      
        ,idxlen);

      
      
        349
      
      
        350
      
      
        for
      
       (i = 
      
        0
      
      ; i < r->elements; i++
      
        ) {

      
      
        351
      
      
        /*
      
      
         Don't use the prefix for the first element, as the parent

      
      
        352
      
      
                         * caller already prepended the index number. 
      
      
        */
      
      
        353
      
      
        out
      
       = sdscatprintf(
      
        out
      
      ,_prefixfmt,i == 
      
        0
      
       ? 
      
        ""
      
       : prefix,i+
      
        1
      
      
        );

      
      
        354
      
      
        355
      
      
        /*
      
      
         Format the multi bulk entry 
      
      
        */
      
      
        356
      
                       tmp = cliFormatReplyTTY(r->
      
        element[i],_prefix);

      
      
        357
      
      
        out
      
       = sdscatlen(
      
        out
      
      
        ,tmp,sdslen(tmp));

      
      
        358
      
      
                        sdsfree(tmp);

      
      
        359
      
      
                    }

      
      
        360
      
      
                    sdsfree(_prefix);

      
      
        361
      
      
                }

      
      
        362
      
      
        break
      
      
        ;

      
      
        363
      
      
        default
      
      
        :

      
      
        364
      
               fprintf(stderr,
      
        "
      
      
        Unknown reply type: %d\n
      
      
        "
      
      , r->
      
        type);

      
      
        365
      
               exit(
      
        1
      
      
        );

      
      
        366
      
      
            }

      
      
        367
      
      
        return
      
      
        out
      
      
        ;

      
      
        368
      
      
        }

      
      
        369
      
      
        370
      
      
        static
      
       sds cliFormatReplyRaw(redisReply *
      
        r) {

      
      
        371
      
           sds 
      
        out
      
       =
      
         sdsempty(), tmp;

      
      
        372
      
      
            size_t i;

      
      
        373
      
      
        374
      
      
        switch
      
       (r->
      
        type) {

      
      
        375
      
      
        case
      
      
         REDIS_REPLY_NIL:

      
      
        376
      
      
        /*
      
      
         Nothing... 
      
      
        */
      
      
        377
      
      
        break
      
      
        ;

      
      
        378
      
      
        case
      
      
         REDIS_REPLY_ERROR:

      
      
        379
      
      
        out
      
       = sdscatlen(
      
        out
      
      ,r->str,r->
      
        len);

      
      
        380
      
      
        out
      
       = sdscatlen(
      
        out
      
      ,
      
        "
      
      
        \n
      
      
        "
      
      ,
      
        1
      
      
        );

      
      
        381
      
      
        break
      
      
        ;

      
      
        382
      
      
        case
      
      
         REDIS_REPLY_STATUS:

      
      
        383
      
      
        case
      
      
         REDIS_REPLY_STRING:

      
      
        384
      
      
        out
      
       = sdscatlen(
      
        out
      
      ,r->str,r->
      
        len);

      
      
        385
      
      
        break
      
      
        ;

      
      
        386
      
      
        case
      
      
         REDIS_REPLY_INTEGER:

      
      
        387
      
      
        out
      
       = sdscatprintf(
      
        out
      
      ,
      
        "
      
      
        %lld
      
      
        "
      
      ,r->
      
        integer);

      
      
        388
      
      
        break
      
      
        ;

      
      
        389
      
      
        case
      
      
         REDIS_REPLY_ARRAY:

      
      
        390
      
      
        for
      
       (i = 
      
        0
      
      ; i < r->elements; i++
      
        ) {

      
      
        391
      
      
        if
      
       (i > 
      
        0
      
      ) 
      
        out
      
       = sdscat(
      
        out
      
      
        ,config.mb_delim);

      
      
        392
      
                   tmp = cliFormatReplyRaw(r->
      
        element[i]);

      
      
        393
      
      
        out
      
       = sdscatlen(
      
        out
      
      
        ,tmp,sdslen(tmp));

      
      
        394
      
      
                    sdsfree(tmp);

      
      
        395
      
      
                }

      
      
        396
      
      
        break
      
      
        ;

      
      
        397
      
      
        default
      
      
        :

      
      
        398
      
               fprintf(stderr,
      
        "
      
      
        Unknown reply type: %d\n
      
      
        "
      
      , r->
      
        type);

      
      
        399
      
               exit(
      
        1
      
      
        );

      
      
        400
      
      
            }

      
      
        401
      
      
        return
      
      
        out
      
      
        ;

      
      
        402
      
      
        }

      
      
        403
      
      
        404
      
      
        static
      
      
        int
      
       cliReadReply(
      
        int
      
      
         output_raw_strings) {

      
      
        405
      
      
        void
      
       *
      
        _reply;

      
      
        406
      
           redisReply *
      
        reply;

      
      
        407
      
           sds 
      
        out
      
      
        ;

      
      
        408
      
      
        409
      
      
        if
      
       (redisGetReply(context,&_reply) !=
      
         REDIS_OK) {

      
      
        410
      
      
        if
      
      
         (config.shutdown)

      
      
        411
      
      
        return
      
      
         REDIS_OK;

      
      
        412
      
      
        if
      
      
         (config.interactive) {

      
      
        413
      
      
        /*
      
      
         Filter cases where we should reconnect 
      
      
        */
      
      
        414
      
      
        if
      
       (context->err == REDIS_ERR_IO && errno ==
      
         ECONNRESET)

      
      
        415
      
      
        return
      
      
         REDIS_ERR;

      
      
        416
      
      
        if
      
       (context->err ==
      
         REDIS_ERR_EOF)

      
      
        417
      
      
        return
      
      
         REDIS_ERR;

      
      
        418
      
      
                }

      
      
        419
      
      
                cliPrintContextError();

      
      
        420
      
               exit(
      
        1
      
      
        );

      
      
        421
      
      
        return
      
       REDIS_ERR; 
      
        /*
      
      
         avoid compiler warning 
      
      
        */
      
      
        422
      
      
            }

      
      
        423
      
      
        424
      
           reply = (redisReply*
      
        )_reply;

      
      
        425
      
      
        if
      
      
         (output_raw_strings) {

      
      
        426
      
      
        out
      
       =
      
         cliFormatReplyRaw(reply);

      
      
        427
      
           } 
      
        else
      
      
         {

      
      
        428
      
      
        if
      
      
         (config.raw_output) {

      
      
        429
      
      
        out
      
       =
      
         cliFormatReplyRaw(reply);

      
      
        430
      
      
        out
      
       = sdscat(
      
        out
      
      ,
      
        "
      
      
        \n
      
      
        "
      
      
        );

      
      
        431
      
               } 
      
        else
      
      
         {

      
      
        432
      
      
        out
      
       = cliFormatReplyTTY(reply,
      
        ""
      
      
        );

      
      
        433
      
      
                }

      
      
        434
      
      
            }

      
      
        435
      
           fwrite(
      
        out
      
      ,sdslen(
      
        out
      
      ),
      
        1
      
      
        ,stdout);

      
      
        436
      
           sdsfree(
      
        out
      
      
        );

      
      
        437
      
      
            freeReplyObject(reply);

      
      
        438
      
      
        return
      
      
         REDIS_OK;

      
      
        439
      
      
        }

      
      
        440
      
      
        441
      
      
        static
      
      
        int
      
       cliSendCommand(
      
        int
      
       argc, 
      
        char
      
       **argv, 
      
        int
      
      
         repeat) {

      
      
        442
      
      
        char
      
       *command = argv[
      
        0
      
      
        ];

      
      
        443
      
           size_t *
      
        argvlen;

      
      
        444
      
      
        int
      
      
         j, output_raw;

      
      
        445
      
      
        446
      
      
        if
      
       (!strcasecmp(command,
      
        "
      
      
        help
      
      
        "
      
      ) || !strcasecmp(command,
      
        "
      
      
        ?
      
      
        "
      
      
        )) {

      
      
        447
      
               cliOutputHelp(--argc, ++
      
        argv);

      
      
        448
      
      
        return
      
      
         REDIS_OK;

      
      
        449
      
      
            }

      
      
        450
      
      
        451
      
      
        if
      
       (context == NULL) 
      
        return
      
      
         REDIS_ERR;

      
      
        452
      
      
        453
      
           output_raw = 
      
        0
      
      
        ;

      
      
        454
      
      
        if
      
       (!strcasecmp(command,
      
        "
      
      
        info
      
      
        "
      
      ) ||

      
        455
      
               (argc == 
      
        2
      
       && !strcasecmp(command,
      
        "
      
      
        client
      
      
        "
      
      ) &&

      
        456
      
                              !strcasecmp(argv[
      
        1
      
      ],
      
        "
      
      
        list
      
      
        "
      
      
        )))

      
      
        457
      
      
        458
      
      
            {

      
      
        459
      
               output_raw = 
      
        1
      
      
        ;

      
      
        460
      
      
            }

      
      
        461
      
      
        462
      
      
        if
      
       (!strcasecmp(command,
      
        "
      
      
        shutdown
      
      
        "
      
      )) config.shutdown = 
      
        1
      
      
        ;

      
      
        463
      
      
        if
      
       (!strcasecmp(command,
      
        "
      
      
        monitor
      
      
        "
      
      )) config.monitor_mode = 
      
        1
      
      
        ;

      
      
        464
      
      
        if
      
       (!strcasecmp(command,
      
        "
      
      
        subscribe
      
      
        "
      
      ) ||

      
        465
      
               !strcasecmp(command,
      
        "
      
      
        psubscribe
      
      
        "
      
      )) config.pubsub_mode = 
      
        1
      
      
        ;

      
      
        466
      
      
        467
      
      
        /*
      
      
         Setup argument length 
      
      
        */
      
      
        468
      
           argvlen = malloc(argc*
      
        sizeof
      
      
        (size_t));

      
      
        469
      
      
        for
      
       (j = 
      
        0
      
      ; j < argc; j++
      
        )

      
      
        470
      
               argvlen[j] =
      
         sdslen(argv[j]);

      
      
        471
      
      
        472
      
      
        while
      
      (repeat--
      
        ) {

      
      
        473
      
               redisAppendCommandArgv(context,argc,(
      
        const
      
      
        char
      
      **
      
        )argv,argvlen);

      
      
        474
      
      
        while
      
      
         (config.monitor_mode) {

      
      
        475
      
      
        if
      
       (cliReadReply(output_raw) != REDIS_OK) exit(
      
        1
      
      
        );

      
      
        476
      
      
                    fflush(stdout);

      
      
        477
      
      
                }

      
      
        478
      
      
        479
      
      
        if
      
      
         (config.pubsub_mode) {

      
      
        480
      
      
        if
      
       (!
      
        config.raw_output)

      
      
        481
      
                       printf(
      
        "
      
      
        Reading messages... (press Ctrl-C to quit)\n
      
      
        "
      
      
        );

      
      
        482
      
      
        while
      
       (
      
        1
      
      
        ) {

      
      
        483
      
      
        if
      
       (cliReadReply(output_raw) != REDIS_OK) exit(
      
        1
      
      
        );

      
      
        484
      
      
                    }

      
      
        485
      
      
                }

      
      
        486
      
      
        487
      
      
        if
      
       (cliReadReply(output_raw) !=
      
         REDIS_OK) {

      
      
        488
      
      
                    free(argvlen);

      
      
        489
      
      
        return
      
      
         REDIS_ERR;

      
      
        490
      
               } 
      
        else
      
      
         {

      
      
        491
      
      
        /*
      
      
         Store database number when SELECT was successfully executed. 
      
      
        */
      
      
        492
      
      
        if
      
       (!strcasecmp(command,
      
        "
      
      
        select
      
      
        "
      
      ) && argc == 
      
        2
      
      
        ) {

      
      
        493
      
                       config.dbnum = atoi(argv[
      
        1
      
      
        ]);

      
      
        494
      
      
                        cliRefreshPrompt();

      
      
        495
      
      
                    }

      
      
        496
      
      
                }

      
      
        497
      
      
        if
      
      
         (config.interval) usleep(config.interval);

      
      
        498
      
               fflush(stdout); 
      
        /*
      
      
         Make it grep friendly 
      
      
        */
      
      
        499
      
      
            }

      
      
        500
      
      
        501
      
      
            free(argvlen);

      
      
        502
      
      
        return
      
      
         REDIS_OK;

      
      
        503
      
      
        }

      
      
        504
      
      
        505
      
      
        /*
      
      
        ------------------------------------------------------------------------------

      
      
        506
      
      
         * User interface

      
      
        507
      
      
         *--------------------------------------------------------------------------- 
      
      
        */
      
      
        508
      
      
        509
      
      
        static
      
      
        int
      
       parseOptions(
      
        int
      
       argc, 
      
        char
      
       **
      
        argv) {

      
      
        510
      
      
        int
      
      
         i;

      
      
        511
      
      
        512
      
      
        for
      
       (i = 
      
        1
      
      ; i < argc; i++
      
        ) {

      
      
        513
      
      
        int
      
       lastarg = i==argc-
      
        1
      
      
        ;

      
      
        514
      
      
        515
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -h
      
      
        "
      
      ) && !
      
        lastarg) {

      
      
        516
      
      
                    sdsfree(config.hostip);

      
      
        517
      
                   config.hostip = sdsnew(argv[i+
      
        1
      
      
        ]);

      
      
        518
      
                   i++
      
        ;

      
      
        519
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -h
      
      
        "
      
      ) &&
      
         lastarg) {

      
      
        520
      
      
                    usage();

      
      
        521
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        --help
      
      
        "
      
      
        )) {

      
      
        522
      
      
                    usage();

      
      
        523
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -x
      
      
        "
      
      
        )) {

      
      
        524
      
                   config.stdinarg = 
      
        1
      
      
        ;

      
      
        525
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -p
      
      
        "
      
      ) && !
      
        lastarg) {

      
      
        526
      
                   config.hostport = atoi(argv[i+
      
        1
      
      
        ]);

      
      
        527
      
                   i++
      
        ;

      
      
        528
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -s
      
      
        "
      
      ) && !
      
        lastarg) {

      
      
        529
      
                   config.hostsocket = argv[i+
      
        1
      
      
        ];

      
      
        530
      
                   i++
      
        ;

      
      
        531
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -r
      
      
        "
      
      ) && !
      
        lastarg) {

      
      
        532
      
                   config.repeat = strtoll(argv[i+
      
        1
      
      ],NULL,
      
        10
      
      
        );

      
      
        533
      
                   i++
      
        ;

      
      
        534
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -i
      
      
        "
      
      ) && !
      
        lastarg) {

      
      
        535
      
      
        double
      
       seconds = atof(argv[i+
      
        1
      
      
        ]);

      
      
        536
      
                   config.interval = seconds*
      
        1000000
      
      
        ;

      
      
        537
      
                   i++
      
        ;

      
      
        538
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -n
      
      
        "
      
      ) && !
      
        lastarg) {

      
      
        539
      
                   config.dbnum = atoi(argv[i+
      
        1
      
      
        ]);

      
      
        540
      
                   i++
      
        ;

      
      
        541
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -a
      
      
        "
      
      ) && !
      
        lastarg) {

      
      
        542
      
                   config.auth = argv[i+
      
        1
      
      
        ];

      
      
        543
      
                   i++
      
        ;

      
      
        544
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        --raw
      
      
        "
      
      
        )) {

      
      
        545
      
                   config.raw_output = 
      
        1
      
      
        ;

      
      
        546
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        --latency
      
      
        "
      
      
        )) {

      
      
        547
      
                   config.latency_mode = 
      
        1
      
      
        ;

      
      
        548
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -d
      
      
        "
      
      ) && !
      
        lastarg) {

      
      
        549
      
      
                    sdsfree(config.mb_delim);

      
      
        550
      
                   config.mb_delim = sdsnew(argv[i+
      
        1
      
      
        ]);

      
      
        551
      
                   i++
      
        ;

      
      
        552
      
               } 
      
        else
      
      
        if
      
       (!strcmp(argv[i],
      
        "
      
      
        -v
      
      
        "
      
      ) || !strcmp(argv[i], 
      
        "
      
      
        --version
      
      
        "
      
      
        )) {

      
      
        553
      
                   sds version =
      
         cliVersion();

      
      
        554
      
                   printf(
      
        "
      
      
        redis-cli %s\n
      
      
        "
      
      
        , version);

      
      
        555
      
      
                    sdsfree(version);

      
      
        556
      
                   exit(
      
        0
      
      
        );

      
      
        557
      
               } 
      
        else
      
      
         {

      
      
        558
      
      
        break
      
      
        ;

      
      
        559
      
      
                }

      
      
        560
      
      
            }

      
      
        561
      
      
        return
      
      
         i;

      
      
        562
      
      
        }

      
      
        563
      
      
        564
      
      
        static
      
       sds readArgFromStdin(
      
        void
      
      
        ) {

      
      
        565
      
      
        char
      
       buf[
      
        1024
      
      
        ];

      
      
        566
      
           sds arg =
      
         sdsempty();

      
      
        567
      
      
        568
      
      
        while
      
      (
      
        1
      
      
        ) {

      
      
        569
      
      
        int
      
       nread = read(fileno(stdin),buf,
      
        1024
      
      
        );

      
      
        570
      
      
        571
      
      
        if
      
       (nread == 
      
        0
      
      ) 
      
        break
      
      
        ;

      
      
        572
      
      
        else
      
      
        if
      
       (nread == -
      
        1
      
      
        ) {

      
      
        573
      
                   perror(
      
        "
      
      
        Reading from standard input
      
      
        "
      
      
        );

      
      
        574
      
                   exit(
      
        1
      
      
        );

      
      
        575
      
      
                }

      
      
        576
      
               arg =
      
         sdscatlen(arg,buf,nread);

      
      
        577
      
      
            }

      
      
        578
      
      
        return
      
      
         arg;

      
      
        579
      
      
        }

      
      
        580
      
      
        581
      
      
        static
      
      
        void
      
      
         usage() {

      
      
        582
      
           sds version =
      
         cliVersion();

      
      
        583
      
      
            fprintf(stderr,

      
      
        584
      
      
        "
      
      
        redis-cli %s\n
      
      
        "
      
      
        585
      
      
        "
      
      
        \n
      
      
        "
      
      
        586
      
      
        "
      
      
        Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]\n
      
      
        "
      
      
        587
      
      
        "
      
      
          -h <hostname>    Server hostname (default: 127.0.0.1)\n
      
      
        "
      
      
        588
      
      
        "
      
      
          -p <port>        Server port (default: 6379)\n
      
      
        "
      
      
        589
      
      
        "
      
      
          -s <socket>      Server socket (overrides hostname and port)\n
      
      
        "
      
      
        590
      
      
        "
      
      
          -a <password>    Password to use when connecting to the server\n
      
      
        "
      
      
        591
      
      
        "
      
      
          -r <repeat>      Execute specified command N times\n
      
      
        "
      
      
        592
      
      
        "
      
      
          -i <interval>    When -r is used, waits <interval> seconds per command.\n
      
      
        "
      
      
        593
      
      
        "
      
      
                           It is possible to specify sub-second times like -i 0.1.\n
      
      
        "
      
      
        594
      
      
        "
      
      
          -n <db>          Database number\n
      
      
        "
      
      
        595
      
      
        "
      
      
          -x               Read last argument from STDIN\n
      
      
        "
      
      
        596
      
      
        "
      
      
          -d <delimiter>   Multi-bulk delimiter in for raw formatting (default: \\n)\n
      
      
        "
      
      
        597
      
      
        "
      
      
          --raw            Use raw formatting for replies (default when STDOUT is not a tty)\n
      
      
        "
      
      
        598
      
      
        "
      
      
          --latency        Enter a special mode continuously sampling latency.\n
      
      
        "
      
      
        599
      
      
        "
      
      
          --help           Output this help and exit\n
      
      
        "
      
      
        600
      
      
        "
      
      
          --version        Output version and exit\n
      
      
        "
      
      
        601
      
      
        "
      
      
        \n
      
      
        "
      
      
        602
      
      
        "
      
      
        Examples:\n
      
      
        "
      
      
        603
      
      
        "
      
      
          cat /etc/passwd | redis-cli -x set mypasswd\n
      
      
        "
      
      
        604
      
      
        "
      
      
          redis-cli get mypasswd\n
      
      
        "
      
      
        605
      
      
        "
      
      
          redis-cli -r 100 lpush mylist x\n
      
      
        "
      
      
        606
      
      
        "
      
      
          redis-cli -r 100 -i 1 info | grep used_memory_human:\n
      
      
        "
      
      
        607
      
      
        "
      
      
        \n
      
      
        "
      
      
        608
      
      
        "
      
      
        When no command is given, redis-cli starts in interactive mode.\n
      
      
        "
      
      
        609
      
      
        "
      
      
        Type \"help\" in interactive mode for information on available commands.\n
      
      
        "
      
      
        610
      
      
        "
      
      
        \n
      
      
        "
      
      
        ,

      
      
        611
      
      
                version);

      
      
        612
      
      
            sdsfree(version);

      
      
        613
      
           exit(
      
        1
      
      
        );

      
      
        614
      
      
        }

      
      
        615
      
      
        616
      
      
        /*
      
      
         Turn the plain C strings into Sds strings 
      
      
        */
      
      
        617
      
      
        static
      
      
        char
      
       **convertToSds(
      
        int
      
       count, 
      
        char
      
      **
      
         args) {

      
      
        618
      
      
        int
      
      
         j;

      
      
        619
      
      
        char
      
       **sds = zmalloc(
      
        sizeof
      
      (
      
        char
      
      *)*
      
        count);

      
      
        620
      
      
        621
      
      
        for
      
      (j = 
      
        0
      
      ; j < count; j++
      
        )

      
      
        622
      
           sds[j] =
      
         sdsnew(args[j]);

      
      
        623
      
      
        624
      
      
        return
      
      
         sds;

      
      
        625
      
      
        }

      
      
        626
      
      
        627
      
      
        #define
      
       LINE_BUFLEN 4096

      
        628
      
      
        static
      
      
        void
      
      
         repl() {

      
      
        629
      
           sds historyfile =
      
         NULL;

      
      
        630
      
      
        int
      
       history = 
      
        0
      
      
        ;

      
      
        631
      
      
        char
      
       *
      
        line;

      
      
        632
      
      
        int
      
      
         argc;

      
      
        633
      
           sds *
      
        argv;

      
      
        634
      
      
        635
      
           config.interactive = 
      
        1
      
      
        ;

      
      
        636
      
      
            linenoiseSetCompletionCallback(completionCallback);

      
      
        637
      
      
        638
      
      
        /*
      
      
         Only use history when stdin is a tty. 
      
      
        */
      
      
        639
      
      
        if
      
      
         (isatty(fileno(stdin))) {

      
      
        640
      
               history = 
      
        1
      
      
        ;

      
      
        641
      
      
        642
      
      
        if
      
       (getenv(
      
        "
      
      
        HOME
      
      
        "
      
      ) !=
      
         NULL) {

      
      
        643
      
                   historyfile = sdscatprintf(sdsempty(),
      
        "
      
      
        %s/.rediscli_history
      
      
        "
      
      ,getenv(
      
        "
      
      
        HOME
      
      
        "
      
      
        ));

      
      
        644
      
      
                    linenoiseHistoryLoad(historyfile);

      
      
        645
      
      
                }

      
      
        646
      
      
            }

      
      
        647
      
      
        648
      
      
            cliRefreshPrompt();

      
      
        649
      
      
        while
      
      ((line = linenoise(context ? config.prompt : 
      
        "
      
      
        not connected> 
      
      
        "
      
      )) !=
      
         NULL) {

      
      
        650
      
      
        if
      
       (line[
      
        0
      
      ] != 
      
        '
      
      
        \0
      
      
        '
      
      
        ) {

      
      
        651
      
                   argv = sdssplitargs(line,&
      
        argc);

      
      
        652
      
      
        if
      
      
         (history) linenoiseHistoryAdd(line);

      
      
        653
      
      
        if
      
      
         (historyfile) linenoiseHistorySave(historyfile);

      
      
        654
      
      
        655
      
      
        if
      
       (argv ==
      
         NULL) {

      
      
        656
      
                       printf(
      
        "
      
      
        Invalid argument(s)\n
      
      
        "
      
      
        );

      
      
        657
      
      
                        free(line);

      
      
        658
      
      
        continue
      
      
        ;

      
      
        659
      
                   } 
      
        else
      
      
        if
      
       (argc > 
      
        0
      
      
        ) {

      
      
        660
      
      
        if
      
       (strcasecmp(argv[
      
        0
      
      ],
      
        "
      
      
        quit
      
      
        "
      
      ) == 
      
        0
      
       ||

      
        661
      
                           strcasecmp(argv[
      
        0
      
      ],
      
        "
      
      
        exit
      
      
        "
      
      ) == 
      
        0
      
      
        )

      
      
        662
      
      
                        {

      
      
        663
      
                           exit(
      
        0
      
      
        );

      
      
        664
      
                       } 
      
        else
      
      
        if
      
       (argc == 
      
        3
      
       && !strcasecmp(argv[
      
        0
      
      ],
      
        "
      
      
        connect
      
      
        "
      
      
        )) {

      
      
        665
      
      
                            sdsfree(config.hostip);

      
      
        666
      
                           config.hostip = sdsnew(argv[
      
        1
      
      
        ]);

      
      
        667
      
                           config.hostport = atoi(argv[
      
        2
      
      
        ]);

      
      
        668
      
                           cliConnect(
      
        1
      
      
        );

      
      
        669
      
                       } 
      
        else
      
      
        if
      
       (argc == 
      
        1
      
       && !strcasecmp(argv[
      
        0
      
      ],
      
        "
      
      
        clear
      
      
        "
      
      
        )) {

      
      
        670
      
      
                            linenoiseClearScreen();

      
      
        671
      
                       } 
      
        else
      
      
         {

      
      
        672
      
      
        long
      
      
        long
      
       start_time =
      
         mstime(), elapsed;

      
      
        673
      
      
        int
      
       repeat, skipargs = 
      
        0
      
      
        ;

      
      
        674
      
      
        675
      
                           repeat = atoi(argv[
      
        0
      
      
        ]);

      
      
        676
      
      
        if
      
       (argc > 
      
        1
      
       &&
      
         repeat) {

      
      
        677
      
                               skipargs = 
      
        1
      
      
        ;

      
      
        678
      
                           } 
      
        else
      
      
         {

      
      
        679
      
                               repeat = 
      
        1
      
      
        ;

      
      
        680
      
      
                            }

      
      
        681
      
      
        682
      
      
        if
      
       (cliSendCommand(argc-skipargs,argv+
      
        skipargs,repeat)

      
      
        683
      
                               !=
      
         REDIS_OK)

      
      
        684
      
      
                            {

      
      
        685
      
                               cliConnect(
      
        1
      
      
        );

      
      
        686
      
      
        687
      
      
        /*
      
      
         If we still cannot send the command print error.

      
      
        688
      
      
                                 * We'll try to reconnect the next time. 
      
      
        */
      
      
        689
      
      
        if
      
       (cliSendCommand(argc-skipargs,argv+
      
        skipargs,repeat)

      
      
        690
      
                                   !=
      
         REDIS_OK)

      
      
        691
      
      
                                    cliPrintContextError();

      
      
        692
      
      
                            }

      
      
        693
      
                           elapsed = mstime()-
      
        start_time;

      
      
        694
      
      
        if
      
       (elapsed >= 
      
        500
      
      
        ) {

      
      
        695
      
                               printf(
      
        "
      
      
        (%.2fs)\n
      
      
        "
      
      ,(
      
        double
      
      )elapsed/
      
        1000
      
      
        );

      
      
        696
      
      
                            }

      
      
        697
      
      
                        }

      
      
        698
      
      
                    }

      
      
        699
      
      
        /*
      
      
         Free the argument vector 
      
      
        */
      
      
        700
      
      
        while
      
      (argc--
      
        ) sdsfree(argv[argc]);

      
      
        701
      
      
                    zfree(argv);

      
      
        702
      
      
                }

      
      
        703
      
      
        /*
      
      
         linenoise() returns malloc-ed lines like readline() 
      
      
        */
      
      
        704
      
      
                free(line);

      
      
        705
      
      
            }

      
      
        706
      
           exit(
      
        0
      
      
        );

      
      
        707
      
      
        }

      
      
        708
      
      
        709
      
      
        static
      
      
        int
      
       noninteractive(
      
        int
      
       argc, 
      
        char
      
       **
      
        argv) {

      
      
        710
      
      
        int
      
       retval = 
      
        0
      
      
        ;

      
      
        711
      
      
        if
      
      
         (config.stdinarg) {

      
      
        712
      
               argv = zrealloc(argv, (argc+
      
        1
      
      )*
      
        sizeof
      
      (
      
        char
      
      *
      
        ));

      
      
        713
      
               argv[argc] =
      
         readArgFromStdin();

      
      
        714
      
               retval = cliSendCommand(argc+
      
        1
      
      
        , argv, config.repeat);

      
      
        715
      
           } 
      
        else
      
      
         {

      
      
        716
      
      
        /*
      
      
         stdin is probably a tty, can be tested with S_ISCHR(s.st_mode) 
      
      
        */
      
      
        717
      
               retval =
      
         cliSendCommand(argc, argv, config.repeat);

      
      
        718
      
      
            }

      
      
        719
      
      
        return
      
      
         retval;

      
      
        720
      
      
        }

      
      
        721
      
      
        722
      
      
        static
      
      
        void
      
       latencyMode(
      
        void
      
      
        ) {

      
      
        723
      
           redisReply *
      
        reply;

      
      
        724
      
      
        long
      
      
        long
      
       start, latency, min, max, tot, count = 
      
        0
      
      
        ;

      
      
        725
      
      
        double
      
      
         avg;

      
      
        726
      
      
        727
      
      
        if
      
       (!context) exit(
      
        1
      
      
        );

      
      
        728
      
      
        while
      
      (
      
        1
      
      
        ) {

      
      
        729
      
               start =
      
         mstime();

      
      
        730
      
               reply = redisCommand(context,
      
        "
      
      
        PING
      
      
        "
      
      
        );

      
      
        731
      
      
        if
      
       (reply ==
      
         NULL) {

      
      
        732
      
                   fprintf(stderr,
      
        "
      
      
        \nI/O error\n
      
      
        "
      
      
        );

      
      
        733
      
                   exit(
      
        1
      
      
        );

      
      
        734
      
      
                }

      
      
        735
      
               latency = mstime()-
      
        start;

      
      
        736
      
      
                freeReplyObject(reply);

      
      
        737
      
               count++
      
        ;

      
      
        738
      
      
        if
      
       (count == 
      
        1
      
      
        ) {

      
      
        739
      
                   min = max = tot =
      
         latency;

      
      
        740
      
                   avg = (
      
        double
      
      
        ) latency;

      
      
        741
      
               } 
      
        else
      
      
         {

      
      
        742
      
      
        if
      
       (latency < min) min =
      
         latency;

      
      
        743
      
      
        if
      
       (latency > max) max =
      
         latency;

      
      
        744
      
                   tot +=
      
         latency;

      
      
        745
      
                   avg = (
      
        double
      
      ) tot/
      
        count;

      
      
        746
      
      
                }

      
      
        747
      
               printf(
      
        "
      
      
        \x1b[0G\x1b[2Kmin: %lld, max: %lld, avg: %.2f (%lld samples)
      
      
        "
      
      
        ,

      
      
        748
      
      
                    min, max, avg, count);

      
      
        749
      
      
                fflush(stdout);

      
      
        750
      
               usleep(
      
        10000
      
      
        );

      
      
        751
      
      
            }

      
      
        752
      
      
        }

      
      
        753
      
      
        754
      
      
        int
      
       main(
      
        int
      
       argc, 
      
        char
      
       **
      
        argv) {

      
      
        755
      
      
        int
      
      
         firstarg;

      
      
        756
      
      
        757
      
           config.hostip = sdsnew(
      
        "
      
      
        127.0.0.1
      
      
        "
      
      
        );

      
      
        758
      
           config.hostport = 
      
        6379
      
      
        ;

      
      
        759
      
           config.hostsocket =
      
         NULL;

      
      
        760
      
           config.repeat = 
      
        1
      
      
        ;

      
      
        761
      
           config.interval = 
      
        0
      
      
        ;

      
      
        762
      
           config.dbnum = 
      
        0
      
      
        ;

      
      
        763
      
           config.interactive = 
      
        0
      
      
        ;

      
      
        764
      
           config.shutdown = 
      
        0
      
      
        ;

      
      
        765
      
           config.monitor_mode = 
      
        0
      
      
        ;

      
      
        766
      
           config.pubsub_mode = 
      
        0
      
      
        ;

      
      
        767
      
           config.latency_mode = 
      
        0
      
      
        ;

      
      
        768
      
           config.stdinarg = 
      
        0
      
      
        ;

      
      
        769
      
           config.auth =
      
         NULL;

      
      
        770
      
           config.raw_output = !isatty(fileno(stdout)) && (getenv(
      
        "
      
      
        FAKETTY
      
      
        "
      
      ) ==
      
         NULL);

      
      
        771
      
           config.mb_delim = sdsnew(
      
        "
      
      
        \n
      
      
        "
      
      
        );

      
      
        772
      
      
            cliInitHelp();

      
      
        773
      
      
        774
      
           firstarg =
      
         parseOptions(argc,argv);

      
      
        775
      
           argc -=
      
         firstarg;

      
      
        776
      
           argv +=
      
         firstarg;

      
      
        777
      
      
        778
      
      
        /*
      
      
         Start in latency mode if appropriate 
      
      
        */
      
      
        779
      
      
        if
      
      
         (config.latency_mode) {

      
      
        780
      
               cliConnect(
      
        0
      
      
        );

      
      
        781
      
      
                latencyMode();

      
      
        782
      
      
            }

      
      
        783
      
      
        784
      
      
        /*
      
      
         Start interactive mode when no command is provided 
      
      
        */
      
      
        785
      
      
        if
      
       (argc == 
      
        0
      
      
        ) {

      
      
        786
      
      
        /*
      
      
         Note that in repl mode we don't abort on connection error.

      
      
        787
      
      
                 * A new attempt will be performed for every command send. 
      
      
        */
      
      
        788
      
               cliConnect(
      
        0
      
      
        );

      
      
        789
      
      
                repl();

      
      
        790
      
      
            }

      
      
        791
      
      
        792
      
      
        /*
      
      
         Otherwise, we have some arguments to execute 
      
      
        */
      
      
        793
      
      
        if
      
       (cliConnect(
      
        0
      
      ) != REDIS_OK) exit(
      
        1
      
      
        );

      
      
        794
      
      
        return
      
      
         noninteractive(argc,convertToSds(argc,argv));

      
      
        795
      
       }
    

redis源码笔记 - redis-cli.c


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论