// File: /workspace/github_c_makefile_star2_O3/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 0x5d155
movq %rdi, %rbx
cmpq $0x0, 0x28(%rdi)
jne 0x5d0e7
movq 0x20(%rbx), %rax
movq (%rax), %rdi
movl 0x8(%rax), %esi
callq 0x6252c
movq %rax, 0x28(%rbx)
cmpl $0x0, 0xa0(%rax)
je 0x5d07c
movq 0xa8(%rax), %r8
leaq 0x4248a(%rip), %rsi     # 0x9f4e5
leaq 0x4243a(%rip), %rcx     # 0x9f49c
xorl %edi, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x5b0ac
movq 0x28(%rbx), %rsi
movq %rbx, %rdi
callq 0x5be4f
jmp 0x5d0e7
callq 0x23461
movq %rax, 0x40(%rbx)
movq 0x28(%rbx), %rsi
movq %rbx, 0xb0(%rsi)
leaq 0x6cf11(%rip), %rax     # 0xc9fa8
movq 0x28(%rax), %rdi
callq 0x5d1f1
movq 0x28(%rbx), %rdi
leaq -0x186(%rip), %rsi      # 0x5cf25
callq 0x6261f
movq 0x28(%rbx), %rdi
leaq -0x160(%rip), %rsi      # 0x5cf5b
callq 0x62651
movq 0x28(%rbx), %rsi
movq %rbx, %rdi
callq 0x5cf60
movq 0x28(%rbx), %rsi
leaq 0x42425(%rip), %rdx     # 0x9f4fc
movq %rbx, %rdi
callq 0x5cfb5
movq %rbx, %rdi
callq 0x5d27d
testb $0x3, (%rbx)
je 0x5d13c
cmpq $0x0, 0x30(%rbx)
jne 0x5d13c
movq 0x20(%rbx), %rax
movq (%rax), %rdi
movl 0x8(%rax), %esi
callq 0x6252c
movq %rax, 0x30(%rbx)
cmpl $0x0, 0xa0(%rax)
je 0x5d157
movq 0xa8(%rax), %r8
leaq 0x423e3(%rip), %rsi     # 0x9f500
leaq 0x42378(%rip), %rcx     # 0x9f49c
xorl %edi, %edi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x5b0ac
movq 0x30(%rbx), %rsi
movq %rbx, %rdi
callq 0x5be4f
cmpq $0x0, 0x28(%rbx)
je 0x5d155
movl (%rbx), %eax
testb $0x4, %al
jne 0x5d150
cmpq $0x0, 0x30(%rbx)
je 0x5d155
andl $-0x9, %eax
movl %eax, (%rbx)
popq %rbx
retq
callq 0x23461
movq %rax, 0x48(%rbx)
movq 0x30(%rbx), %rsi
movq %rbx, 0xb0(%rsi)
leaq 0x6ce36(%rip), %rax     # 0xc9fa8
movq 0x28(%rax), %rdi
callq 0x5d1f1
movq 0x30(%rbx), %rdi
leaq -0x261(%rip), %rsi      # 0x5cf25
callq 0x6261f
movq 0x30(%rbx), %rdi
leaq -0x23b(%rip), %rsi      # 0x5cf5b
callq 0x62651
movq 0x30(%rbx), %rsi
movq %rbx, %rdi
callq 0x5cf60
movq 0x30(%rbx), %rsi
leaq 0x37460(%rip), %rdx     # 0x94612
movq %rbx, %rdi
callq 0x5cfb5
movq 0x30(%rbx), %rdi
leaq 0x105(%rip), %rsi       # 0x5d2ca
leaq 0x4234e(%rip), %rcx     # 0x9f51a
leaq 0x42354(%rip), %r8      # 0x9f527
xorl %edx, %edx
xorl %eax, %eax
callq 0x630fd
testl %eax, %eax
je 0x5d13c
movq 0x30(%rbx), %rsi
movq %rbx, %rdi
popq %rbx
jmp 0x5be4f