// File: /workspace/github_c_makefile_star2_O2/nilyang[P]redis-tdd-annotation/src/sentinel.c
// Function: sentinelCommand
void sentinelCommand(redisClient *c) {
    if (!strcasecmp(c->argv[1]->ptr,"masters")) {
        /* SENTINEL MASTERS */
        if (c->argc != 2) goto numargserr;
        addReplyDictOfRedisInstances(c,sentinel.masters);
    } else if (!strcasecmp(c->argv[1]->ptr,"master")) {
        /* SENTINEL MASTER <name> */
        sentinelRedisInstance *ri;

        if (c->argc != 3) goto numargserr;
        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))
            == NULL) return;
        addReplySentinelRedisInstance(c,ri);
    } else if (!strcasecmp(c->argv[1]->ptr,"slaves")) {
        /* SENTINEL SLAVES <master-name> */
        sentinelRedisInstance *ri;

        if (c->argc != 3) goto numargserr;
        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)
            return;
        addReplyDictOfRedisInstances(c,ri->slaves);
    } else if (!strcasecmp(c->argv[1]->ptr,"sentinels")) {
        /* SENTINEL SENTINELS <master-name> */
        sentinelRedisInstance *ri;

        if (c->argc != 3) goto numargserr;
        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)
            return;
        addReplyDictOfRedisInstances(c,ri->sentinels);
    } else if (!strcasecmp(c->argv[1]->ptr,"is-master-down-by-addr")) {
        /* SENTINEL IS-MASTER-DOWN-BY-ADDR <ip> <port> <current-epoch> <runid>*/
        sentinelRedisInstance *ri;
        long long req_epoch;
        uint64_t leader_epoch = 0;
        char *leader = NULL;
        long port;
        int isdown = 0;

        if (c->argc != 6) goto numargserr;
        if (getLongFromObjectOrReply(c,c->argv[3],&port,NULL) != REDIS_OK ||
            getLongLongFromObjectOrReply(c,c->argv[4],&req_epoch,NULL)
                                                              != REDIS_OK)
            return;
        ri = getSentinelRedisInstanceByAddrAndRunID(sentinel.masters,
            c->argv[2]->ptr,port,NULL);

        /* It exists? Is actually a master? Is subjectively down? It's down.
         * Note: if we are in tilt mode we always reply with "0". */
        if (!sentinel.tilt && ri && (ri->flags & SRI_S_DOWN) &&
                                    (ri->flags & SRI_MASTER))
            isdown = 1;

        /* Vote for the master (or fetch the previous vote) if the request
         * includes a runid, otherwise the sender is not seeking for a vote. */
        if (ri && ri->flags & SRI_MASTER && strcasecmp(c->argv[5]->ptr,"*")) {
            leader = sentinelVoteLeader(ri,(uint64_t)req_epoch,
                                            c->argv[5]->ptr,
                                            &leader_epoch);
        }

        /* Reply with a three-elements multi-bulk reply:
         * down state, leader, vote epoch. */
        // 多条回复
        // 1) <down_state>    1 代表下线， 0 代表未下线
        // 2) <leader_runid>  Sentinel 选举作为领头 Sentinel 的运行 ID
        // 3) <leader_epoch>  领头 Sentinel 目前的配置纪元
        addReplyMultiBulkLen(c,3);
        addReply(c, isdown ? shared.cone : shared.czero);
        addReplyBulkCString(c, leader ? leader : "*");
        addReplyLongLong(c, (long long)leader_epoch);
        if (leader) sdsfree(leader);
    } else if (!strcasecmp(c->argv[1]->ptr,"reset")) {
        /* SENTINEL RESET <pattern> */
        if (c->argc != 3) goto numargserr;
        addReplyLongLong(c,sentinelResetMastersByPattern(c->argv[2]->ptr,SENTINEL_GENERATE_EVENT));
    } else if (!strcasecmp(c->argv[1]->ptr,"get-master-addr-by-name")) {
        /* SENTINEL GET-MASTER-ADDR-BY-NAME <master-name> */
        sentinelRedisInstance *ri;

        if (c->argc != 3) goto numargserr;
        ri = sentinelGetMasterByName(c->argv[2]->ptr);
        if (ri == NULL) {
            addReply(c,shared.nullmultibulk);
        } else {
            sentinelAddr *addr = sentinelGetCurrentMasterAddress(ri);

            addReplyMultiBulkLen(c,2);
            addReplyBulkCString(c,addr->ip);
            addReplyBulkLongLong(c,addr->port);
        }
    } else if (!strcasecmp(c->argv[1]->ptr,"failover")) {
        /* SENTINEL FAILOVER <master-name> */
        sentinelRedisInstance *ri;

        if (c->argc != 3) goto numargserr;
        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2])) == NULL)
            return;
        if (ri->flags & SRI_FAILOVER_IN_PROGRESS) {
            addReplySds(c,sdsnew("-INPROG Failover already in progress\r\n"));
            return;
        }
        if (sentinelSelectSlave(ri) == NULL) {
            addReplySds(c,sdsnew("-NOGOODSLAVE No suitable slave to promote\r\n"));
            return;
        }
        redisLog(REDIS_WARNING,"Executing user requested FAILOVER of '%s'",
            ri->name);
        sentinelStartFailover(ri);
        ri->flags |= SRI_FORCE_FAILOVER;
        addReply(c,shared.ok);
    } else if (!strcasecmp(c->argv[1]->ptr,"pending-scripts")) {
        /* SENTINEL PENDING-SCRIPTS */

        if (c->argc != 2) goto numargserr;
        sentinelPendingScriptsCommand(c);
    } else if (!strcasecmp(c->argv[1]->ptr,"monitor")) {
        /* SENTINEL MONITOR <name> <ip> <port> <quorum> */
        sentinelRedisInstance *ri;
        long quorum, port;
        char buf[32];

        if (c->argc != 6) goto numargserr;
        if (getLongFromObjectOrReply(c,c->argv[5],&quorum,"Invalid quorum")
            != REDIS_OK) return;
        if (getLongFromObjectOrReply(c,c->argv[4],&port,"Invalid port")
            != REDIS_OK) return;
        /* Make sure the IP field is actually a valid IP before passing it
         * to createSentinelRedisInstance(), otherwise we may trigger a
         * DNS lookup at runtime. */
        if (anetResolveIP(NULL,c->argv[3]->ptr,buf,sizeof(buf)) == ANET_ERR) {
            addReplyError(c,"Invalid IP address specified");
            return;
        }

        /* Parameters are valid. Try to create the master instance. */
        ri = createSentinelRedisInstance(c->argv[2]->ptr,SRI_MASTER,
                c->argv[3]->ptr,port,quorum,NULL);
        if (ri == NULL) {
            switch(errno) {
            case EBUSY:
                addReplyError(c,"Duplicated master name");
                break;
            case EINVAL:
                addReplyError(c,"Invalid port number");
                break;
            default:
                addReplyError(c,"Unspecified error adding the instance");
                break;
            }
        } else {
            sentinelFlushConfig();
            sentinelEvent(REDIS_WARNING,"+monitor",ri,"%@ quorum %d",ri->quorum);
            addReply(c,shared.ok);
        }
    } else if (!strcasecmp(c->argv[1]->ptr,"remove")) {
        /* SENTINEL REMOVE <name> */
        sentinelRedisInstance *ri;

        if ((ri = sentinelGetMasterByNameOrReplyError(c,c->argv[2]))
            == NULL) return;
        sentinelEvent(REDIS_WARNING,"-monitor",ri,"%@");
        dictDelete(sentinel.masters,c->argv[2]->ptr);
        sentinelFlushConfig();
        addReply(c,shared.ok);
    } else if (!strcasecmp(c->argv[1]->ptr,"set")) {
        if (c->argc < 3 || c->argc % 2 == 0) goto numargserr;
        sentinelSetCommand(c);
    } else {
        addReplyErrorFormat(c,"Unknown sentinel subcommand '%s'",
                               (char*)c->argv[1]->ptr);
    }
    return;

numargserr:
    addReplyErrorFormat(c,"Wrong number of arguments for 'sentinel %s'",
                          (char*)c->argv[1]->ptr);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x30, %rsp
movq %rdi, %rbx
movq 0x38(%rdi), %r15
movq 0x8(%r15), %rax
movq 0x8(%rax), %r14
leaq 0x3fca2(%rip), %rsi     # 0x958f0
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x55d67
leaq 0x3d1a2(%rip), %rsi     # 0x92e07
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x55d8c
leaq 0x3f92f(%rip), %rsi     # 0x955ab
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x55dbe
leaq 0x3fbaf(%rip), %rsi     # 0x95842
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x55de2
leaq 0x3fc4e(%rip), %rsi     # 0x958f8
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x55e09
leaq 0x3d292(%rip), %rsi     # 0x92f53
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x55e9a
leaq 0x3fc37(%rip), %rsi     # 0x9590f
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x55ecd
leaq 0x4003f(%rip), %rsi     # 0x95d2e
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x55f26
leaq 0x3fc9e(%rip), %rsi     # 0x959a4
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x55f85
leaq 0x3f12a(%rip), %rsi     # 0x94e47
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x55fa3
leaq 0x3fce9(%rip), %rsi     # 0x95a1d
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x56092
leaq 0x357a3(%rip), %rsi     # 0x8b4ee
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x56106
leaq 0x3fccb(%rip), %rsi     # 0x95a2d
jmp 0x5611f
cmpl $0x2, 0x30(%rbx)
jne 0x56118
movq 0x85b78(%rip), %rsi     # 0xdb8f0
movq %rbx, %rdi
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x59c39
cmpl $0x3, 0x30(%rbx)
jne 0x56118
movq %rbx, %rdi
callq 0x59c87
testq %rax, %rax
je 0x56225
movq %rbx, %rdi
movq %rax, %rsi
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x595b9
cmpl $0x3, 0x30(%rbx)
jne 0x56118
movq %rbx, %rdi
callq 0x59c87
testq %rax, %rax
je 0x56225
movq 0xc8(%rax), %rsi
jmp 0x55d78
cmpl $0x3, 0x30(%rbx)
jne 0x56118
movq %rbx, %rdi
callq 0x59c87
testq %rax, %rax
je 0x56225
movq 0xc0(%rax), %rsi
jmp 0x55d78
andq $0x0, 0x8(%rsp)
cmpl $0x6, 0x30(%rbx)
jne 0x56118
movq 0x18(%r15), %rsi
movq %rsp, %rdx
movq %rbx, %rdi
xorl %ecx, %ecx
callq 0x2f672
testl %eax, %eax
jne 0x56225
movq 0x38(%rbx), %rax
movq 0x20(%rax), %rsi
leaq 0x10(%rsp), %rdx
movq %rbx, %rdi
xorl %ecx, %ecx
callq 0x2f617
testl %eax, %eax
jne 0x56225
movq 0x85a98(%rip), %rdi     # 0xdb8f0
movq 0x38(%rbx), %rax
movq 0x10(%rax), %rax
movq 0x8(%rax), %rsi
movl (%rsp), %edx
xorl %ecx, %ecx
callq 0x575a1
movq %rax, %r15
cmpl $0x0, 0x85a80(%rip)     # 0xdb8f8
jne 0x56138
testq %r15, %r15
je 0x56138
movl (%r15), %eax
movl %eax, %ecx
notl %ecx
testb $0x11, %cl
setne %bpl
jmp 0x56147
cmpl $0x3, 0x30(%rbx)
jne 0x56118
movq 0x10(%r15), %rax
movq 0x8(%rax), %rdi
movl $0x10000, %esi          # imm = 0x10000
callq 0x57837
movslq %eax, %rsi
movq %rbx, %rdi
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x2c794
cmpl $0x3, 0x30(%rbx)
jne 0x56118
movq 0x10(%r15), %rax
movq 0x8(%rax), %rdi
callq 0x5764f
testq %rax, %rax
je 0x56085
movq %rax, %rdi
callq 0x57ae9
movq %rax, %r14
pushq $0x2
popq %rsi
movq %rbx, %rdi
callq 0x2c7c7
movq (%r14), %rsi
movq %rbx, %rdi
callq 0x2c6b4
movslq 0x8(%r14), %rsi
movq %rbx, %rdi
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x2c8bb
cmpl $0x3, 0x30(%rbx)
jne 0x56118
movq %rbx, %rdi
callq 0x59c87
testq %rax, %rax
je 0x56225
movq %rax, %r14
testb $-0x80, (%rax)
jne 0x560fa
movq %r14, %rdi
callq 0x59dfb
testq %rax, %rax
je 0x561a2
movq 0x8(%r14), %rdx
leaq 0x3fa11(%rip), %rsi     # 0x9597a
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x22613
movq %r14, %rdi
callq 0x59f24
orb $0x10, 0x1(%r14)
jmp 0x560db
cmpl $0x2, 0x30(%rbx)
jne 0x56118
movq %rbx, %rdi
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x56f38
cmpl $0x6, 0x30(%rbx)
jne 0x56118
movq 0x28(%r15), %rsi
leaq 0x3f9fc(%rip), %rcx     # 0x959b4
leaq 0x8(%rsp), %rdx
movq %rbx, %rdi
callq 0x2f672
testl %eax, %eax
jne 0x56225
movq 0x38(%rbx), %rax
movq 0x20(%rax), %rsi
leaq 0x39762(%rip), %rcx     # 0x8f73e
movq %rsp, %rdx
movq %rbx, %rdi
callq 0x2f672
testl %eax, %eax
jne 0x56225
movq 0x38(%rbx), %rax
movq 0x18(%rax), %rax
movq 0x8(%rax), %rsi
leaq 0x10(%rsp), %rdx
pushq $0x20
popq %rcx
xorl %edi, %edi
callq 0x20d68
cmpl $-0x1, %eax
je 0x56232
movq 0x38(%rbx), %rax
movq 0x10(%rax), %rcx
movq 0x18(%rax), %rax
movq 0x8(%rcx), %rdi
movq 0x8(%rax), %rdx
movl (%rsp), %ecx
movl 0x8(%rsp), %r8d
pushq $0x1
popq %rsi
xorl %r9d, %r9d
callq 0x5715c
testq %rax, %rax
je 0x56243
movq %rax, %r14
callq 0x57a25
movl 0xd0(%r14), %r8d
leaq 0x3eded(%rip), %rsi     # 0x94e46
leaq 0x3edef(%rip), %rcx     # 0x94e4f
pushq $0x3
popq %rdi
movq %r14, %rdx
xorl %eax, %eax
callq 0x5678f
leaq 0x7178c(%rip), %rax     # 0xc7800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
callq 0x2c10d
jmp 0x56225
leaq 0x71774(%rip), %rax     # 0xc7800
movq 0x58(%rax), %rsi
jmp 0x560e6
movq %rbx, %rdi
callq 0x59c87
testq %rax, %rax
je 0x56225
leaq 0x3f97a(%rip), %rsi     # 0x95a24
leaq 0x3ef31(%rip), %rcx     # 0x94fe2
pushq $0x3
popq %rdi
movq %rax, %rdx
xorl %eax, %eax
callq 0x5678f
movq 0x8582b(%rip), %rdi     # 0xdb8f0
movq 0x38(%rbx), %rax
movq 0x10(%rax), %rax
movq 0x8(%rax), %rsi
callq 0x21c36
callq 0x57a25
leaq 0x7171e(%rip), %rax     # 0xc7800
movq 0x8(%rax), %rsi
movq %rbx, %rdi
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x2c10d
leaq 0x3f826(%rip), %rdi     # 0x95927
jmp 0x561a9
movl 0x30(%rbx), %eax
cmpl $0x3, %eax
setl %cl
testb $0x1, %al
sete %al
orb %cl, %al
je 0x5618e
leaq 0x3f92f(%rip), %rsi     # 0x95a4e
movq %rbx, %rdi
movq %r14, %rdx
xorl %eax, %eax
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x2c301
testq %r15, %r15
je 0x561c5
movl (%r15), %eax
movb $0x1, %bpl
xorl %r14d, %r14d
testb $0x1, %al
je 0x561cb
movq 0x38(%rbx), %rax
movq 0x28(%rax), %rax
movq 0x8(%rax), %r14
leaq 0x346e3(%rip), %rsi     # 0x8a844
movq %r14, %rdi
callq 0x1f2e0
testl %eax, %eax
je 0x561c8
movq 0x10(%rsp), %rsi
leaq 0x8(%rsp), %r12
movq %r15, %rdi
movq %r14, %rdx
movq %r12, %rcx
callq 0x59cc8
movq %rax, %r15
movq (%r12), %r14
jmp 0x561ce
movq %rbx, %rdi
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x59fe8
leaq 0x3f7a5(%rip), %rdi     # 0x9594e
callq 0x271cd
movq %rbx, %rdi
movq %rax, %rsi
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
jmp 0x2c20f
movb $0x1, %bpl
xorl %r14d, %r14d
xorl %r15d, %r15d
pushq $0x3
popq %rsi
movq %rbx, %rdi
callq 0x2c7c7
leaq 0x71620(%rip), %rax     # 0xc7800
notb %bpl
movzbl %bpl, %ecx
andl $0x1, %ecx
movq 0x20(%rax,%rcx,8), %rsi
movq %rbx, %rdi
callq 0x2c10d
testq %r15, %r15
leaq 0x34643(%rip), %rsi     # 0x8a844
cmovneq %r15, %rsi
movq %rbx, %rdi
callq 0x2c6b4
movq %rbx, %rdi
movq %r14, %rsi
callq 0x2c794
testq %r15, %r15
je 0x56225
movq %r15, %rdi
callq 0x271f7
addq $0x30, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3f78a(%rip), %rsi     # 0x959c3
movq %rbx, %rdi
callq 0x2c2da
jmp 0x56225
callq 0x1f810
movl (%rax), %eax
cmpl $0x16, %eax
je 0x5625d
cmpl $0x10, %eax
jne 0x56266
leaq 0x3f785(%rip), %rsi     # 0x959e0
jmp 0x56239
leaq 0x3ede5(%rip), %rsi     # 0x95049
jmp 0x56239
leaq 0x3f78a(%rip), %rsi     # 0x959f7
jmp 0x56239