// File: /workspace/github_c_makefile_star2_O2/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 0x585f4
movq %rdi, %rbx
cmpq $0x0, 0x28(%rdi)
jne 0x58586
movq 0x20(%rbx), %rax
movq (%rax), %rdi
movl 0x8(%rax), %esi
callq 0x5d5ac
movq %rax, 0x28(%rbx)
cmpl $0x0, 0xa0(%rax)
je 0x5851b
movq 0xa8(%rax), %r8
leaq 0x3cf5f(%rip), %rsi     # 0x95459
leaq 0x3cf0f(%rip), %rcx     # 0x95410
xorl %edi, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x5678f
movq 0x28(%rbx), %rsi
movq %rbx, %rdi
callq 0x5742b
jmp 0x58586
callq 0x22843
movq %rax, 0x40(%rbx)
movq 0x28(%rbx), %rsi
movq %rbx, 0xb0(%rsi)
leaq 0x6ea72(%rip), %rax     # 0xc6fa8
movq 0x28(%rax), %rdi
callq 0x58690
movq 0x28(%rbx), %rdi
leaq -0x184(%rip), %rsi      # 0x583c6
callq 0x5d65f
movq 0x28(%rbx), %rdi
leaq -0x15e(%rip), %rsi      # 0x583fc
callq 0x5d691
movq 0x28(%rbx), %rsi
movq %rbx, %rdi
callq 0x58401
movq 0x28(%rbx), %rsi
leaq 0x3cefa(%rip), %rdx     # 0x95470
movq %rbx, %rdi
callq 0x58456
movq %rbx, %rdi
callq 0x58717
testb $0x3, (%rbx)
je 0x585db
cmpq $0x0, 0x30(%rbx)
jne 0x585db
movq 0x20(%rbx), %rax
movq (%rax), %rdi
movl 0x8(%rax), %esi
callq 0x5d5ac
movq %rax, 0x30(%rbx)
cmpl $0x0, 0xa0(%rax)
je 0x585f6
movq 0xa8(%rax), %r8
leaq 0x3ceb8(%rip), %rsi     # 0x95474
leaq 0x3ce4d(%rip), %rcx     # 0x95410
xorl %edi, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x5678f
movq 0x30(%rbx), %rsi
movq %rbx, %rdi
callq 0x5742b
cmpq $0x0, 0x28(%rbx)
je 0x585f4
movl (%rbx), %eax
testb $0x4, %al
jne 0x585ef
cmpq $0x0, 0x30(%rbx)
je 0x585f4
andl $-0x9, %eax
movl %eax, (%rbx)
popq %rbx
retq
callq 0x22843
movq %rax, 0x48(%rbx)
movq 0x30(%rbx), %rsi
movq %rbx, 0xb0(%rsi)
leaq 0x6e997(%rip), %rax     # 0xc6fa8
movq 0x28(%rax), %rdi
callq 0x58690
movq 0x30(%rbx), %rdi
leaq -0x25f(%rip), %rsi      # 0x583c6
callq 0x5d65f
movq 0x30(%rbx), %rdi
leaq -0x239(%rip), %rsi      # 0x583fc
callq 0x5d691
movq 0x30(%rbx), %rsi
movq %rbx, %rdi
callq 0x58401
movq 0x30(%rbx), %rsi
leaq 0x31f81(%rip), %rdx     # 0x8a5d2
movq %rbx, %rdi
callq 0x58456
movq 0x30(%rbx), %rdi
leaq 0xfe(%rip), %rsi        # 0x58762
leaq 0x3ce23(%rip), %rcx     # 0x9548e
leaq 0x3ce29(%rip), %r8      # 0x9549b
xorl %edx, %edx
xorl %eax, %eax
callq 0x5e024
testl %eax, %eax
je 0x585db
movq 0x30(%rbx), %rsi
movq %rbx, %rdi
popq %rbx
jmp 0x5742b