// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/sentinel.c
// Function: sentinelReconnectInstance
void sentinelReconnectInstance(sentinelRedisInstance *ri) {

    // 示例未断线（已连接），返回
    if (!(ri->flags & SRI_DISCONNECTED)) return;

    /* Commands connection. */
    // 对所有实例创建一个用于发送 Redis 命令的连接
    if (ri->cc == NULL) {

        // 连接实例
        ri->cc = redisAsyncConnect(ri->addr->ip,ri->addr->port);

        // 连接出错
        if (ri->cc->err) {
            sentinelEvent(REDIS_DEBUG,"-cmd-link-reconnection",ri,"%@ #%s",
                ri->cc->errstr);
            sentinelKillLink(ri,ri->cc);

        // 连接成功
        } else {
            // 设置连接属性
            ri->cc_conn_time = mstime();
            ri->cc->data = ri;
            redisAeAttach(server.el,ri->cc);
            // 设置连线 callback
            redisAsyncSetConnectCallback(ri->cc,
                                            sentinelLinkEstablishedCallback);
            // 设置断线 callback
            redisAsyncSetDisconnectCallback(ri->cc,
                                            sentinelDisconnectCallback);
            // 发送 AUTH 命令，验证身份
            sentinelSendAuthIfNeeded(ri,ri->cc);
            sentinelSetClientName(ri,ri->cc,"cmd");

            /* Send a PING ASAP when reconnecting. */
            sentinelSendPing(ri);
        }
    }

    /* Pub / Sub */
    // 对主服务器和从服务器，创建一个用于订阅频道的连接
    if ((ri->flags & (SRI_MASTER|SRI_SLAVE)) && ri->pc == NULL) {

        // 连接实例
        ri->pc = redisAsyncConnect(ri->addr->ip,ri->addr->port);

        // 连接出错
        if (ri->pc->err) {
            sentinelEvent(REDIS_DEBUG,"-pubsub-link-reconnection",ri,"%@ #%s",
                ri->pc->errstr);
            sentinelKillLink(ri,ri->pc);

        // 连接成功
        } else {
            int retval;

            // 设置连接属性
            ri->pc_conn_time = mstime();
            ri->pc->data = ri;
            redisAeAttach(server.el,ri->pc);
            // 设置连接 callback
            redisAsyncSetConnectCallback(ri->pc,
                                            sentinelLinkEstablishedCallback);
            // 设置断线 callback
            redisAsyncSetDisconnectCallback(ri->pc,
                                            sentinelDisconnectCallback);
            // 发送 AUTH 命令，验证身份
            sentinelSendAuthIfNeeded(ri,ri->pc);

            // 为客户但设置名字 "pubsub"
            sentinelSetClientName(ri,ri->pc,"pubsub");

            /* Now we subscribe to the Sentinels "Hello" channel. */
            // 发送 SUBSCRIBE __sentinel__:hello 命令，订阅频道
            retval = redisAsyncCommand(ri->pc,
                sentinelReceiveHelloMessages, NULL, "SUBSCRIBE %s",
                    SENTINEL_HELLO_CHANNEL);
            
            // 订阅出错，断开连接
            if (retval != REDIS_OK) {
                /* If we can't subscribe, the Pub/Sub connection is useless
                 * and we can simply disconnect it and try again. */
                sentinelKillLink(ri,ri->pc);
                return;
            }
        }
    }

    /* Clear the DISCONNECTED flags only if we have both the connections
     * (or just the commands connection if this is a sentinel instance). */
    // 如果实例是主服务器或者从服务器，那么当 cc 和 pc 两个连接都创建成功时，关闭 DISCONNECTED 标识
    // 如果实例是 Sentinel ，那么当 cc 连接创建成功时，关闭 DISCONNECTED 标识
    if (ri->cc && (ri->flags & SRI_SENTINEL || ri->pc))
        ri->flags &= ~SRI_DISCONNECTED;
}

// Assembly:
pushq %rbx
testb $0x8, (%rdi)
je 0x5d761
movq %rdi, %rbx
cmpq $0x0, 0x28(%rdi)
jne 0x5d6f3
movq 0x20(%rbx), %rax
movq (%rax), %rdi
movl 0x8(%rax), %esi
callq 0x62a18
movq %rax, 0x28(%rbx)
cmpl $0x0, 0xa0(%rax)
je 0x5d688
movq 0xa8(%rax), %r8
leaq 0x41e0e(%rip), %rsi     # 0x9f475
leaq 0x41dbe(%rip), %rcx     # 0x9f42c
xorl %edi, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x5b66f
movq 0x28(%rbx), %rsi
movq %rbx, %rdi
callq 0x5c411
jmp 0x5d6f3
callq 0x232a3
movq %rax, 0x40(%rbx)
movq 0x28(%rbx), %rsi
movq %rbx, 0xb0(%rsi)
leaq 0x6c905(%rip), %rax     # 0xc9fa8
movq 0x28(%rax), %rdi
callq 0x5d7fd
movq 0x28(%rbx), %rdi
leaq -0x186(%rip), %rsi      # 0x5d531
callq 0x62b0b
movq 0x28(%rbx), %rdi
leaq -0x160(%rip), %rsi      # 0x5d567
callq 0x62b3d
movq 0x28(%rbx), %rsi
movq %rbx, %rdi
callq 0x5d56c
movq 0x28(%rbx), %rsi
leaq 0x41da9(%rip), %rdx     # 0x9f48c
movq %rbx, %rdi
callq 0x5d5c1
movq %rbx, %rdi
callq 0x5d889
testb $0x3, (%rbx)
je 0x5d748
cmpq $0x0, 0x30(%rbx)
jne 0x5d748
movq 0x20(%rbx), %rax
movq (%rax), %rdi
movl 0x8(%rax), %esi
callq 0x62a18
movq %rax, 0x30(%rbx)
cmpl $0x0, 0xa0(%rax)
je 0x5d763
movq 0xa8(%rax), %r8
leaq 0x41d67(%rip), %rsi     # 0x9f490
leaq 0x41cfc(%rip), %rcx     # 0x9f42c
xorl %edi, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x5b66f
movq 0x30(%rbx), %rsi
movq %rbx, %rdi
callq 0x5c411
cmpq $0x0, 0x28(%rbx)
je 0x5d761
movl (%rbx), %eax
testb $0x4, %al
jne 0x5d75c
cmpq $0x0, 0x30(%rbx)
je 0x5d761
andl $-0x9, %eax
movl %eax, (%rbx)
popq %rbx
retq
callq 0x232a3
movq %rax, 0x48(%rbx)
movq 0x30(%rbx), %rsi
movq %rbx, 0xb0(%rsi)
leaq 0x6c82a(%rip), %rax     # 0xc9fa8
movq 0x28(%rax), %rdi
callq 0x5d7fd
movq 0x30(%rbx), %rdi
leaq -0x261(%rip), %rsi      # 0x5d531
callq 0x62b0b
movq 0x30(%rbx), %rdi
leaq -0x23b(%rip), %rsi      # 0x5d567
callq 0x62b3d
movq 0x30(%rbx), %rsi
movq %rbx, %rdi
callq 0x5d56c
movq 0x30(%rbx), %rsi
leaq 0x36e04(%rip), %rdx     # 0x945c2
movq %rbx, %rdi
callq 0x5d5c1
movq 0x30(%rbx), %rdi
leaq 0x105(%rip), %rsi       # 0x5d8d6
leaq 0x41cd2(%rip), %rcx     # 0x9f4aa
leaq 0x41cd8(%rip), %r8      # 0x9f4b7
xorl %edx, %edx
xorl %eax, %eax
callq 0x63612
testl %eax, %eax
je 0x5d748
movq 0x30(%rbx), %rsi
movq %rbx, %rdi
popq %rbx
jmp 0x5c411