// File: /workspace/github_c_makefile_star2_O1/nilyang[P]redis-tdd-annotation/src/sentinel.c
// Function: createSentinelRedisInstance
sentinelRedisInstance *createSentinelRedisInstance(char *name, int flags, char *hostname, int port, int quorum, sentinelRedisInstance *master) {
    sentinelRedisInstance *ri;
    sentinelAddr *addr;
    dict *table = NULL;
    char slavename[128], *sdsname;

    redisAssert(flags & (SRI_MASTER|SRI_SLAVE|SRI_SENTINEL));
    redisAssert((flags & SRI_MASTER) || master != NULL);

    /* Check address validity. */
    // 保存 IP 地址和端口号到 addr
    addr = createSentinelAddr(hostname,port);
    if (addr == NULL) return NULL;

    /* For slaves and sentinel we use ip:port as name. */
    // 如果实例是从服务器或者 sentinel ，那么使用 ip:port 格式为实例设置名字
    if (flags & (SRI_SLAVE|SRI_SENTINEL)) {
        snprintf(slavename,sizeof(slavename),
            strchr(hostname,':') ? "[%s]:%d" : "%s:%d",
            hostname,port);
        name = slavename;
    }

    /* Make sure the entry is not duplicated. This may happen when the same
     * name for a master is used multiple times inside the configuration or
     * if we try to add multiple times a slave or sentinel with same ip/port
     * to a master. */
    // 配置文件中添加了重复的主服务器配置
    // 或者尝试添加一个相同 ip 或者端口号的从服务器或者 sentinel 时
    // 就可能出现重复添加同一个实例的情况
    // 为了避免这种现象，程序在添加新实例之前，需要先检查实例是否已存在
    // 只有不存在的实例会被添加

    // 选择要添加的表
    // 注意主服务会被添加到 sentinel.masters 表
    // 而从服务器和 sentinel 则会被添加到 master 所属的 slaves 表和 sentinels 表中
    if (flags & SRI_MASTER) table = sentinel.masters;
    else if (flags & SRI_SLAVE) table = master->slaves;
    else if (flags & SRI_SENTINEL) table = master->sentinels;
    sdsname = sdsnew(name);
    if (dictFind(table,sdsname)) {

        // 实例已存在，函数直接返回

        sdsfree(sdsname);
        errno = EBUSY;
        return NULL;
    }

    /* Create the instance object. */
    // 创建实例对象
    ri = zmalloc(sizeof(*ri));
    /* Note that all the instances are started in the disconnected state,
     * the event loop will take care of connecting them. */
    // 所有连接都已断线为起始状态，sentinel 会在需要时自动为它创建连接
    ri->flags = flags | SRI_DISCONNECTED;
    ri->name = sdsname;
    ri->runid = NULL;
    ri->config_epoch = 0;
    ri->addr = addr;
    ri->cc = NULL;
    ri->pc = NULL;
    ri->pending_commands = 0;
    ri->cc_conn_time = 0;
    ri->pc_conn_time = 0;
    ri->pc_last_activity = 0;
    /* We set the last_ping_time to "now" even if we actually don't have yet
     * a connection with the node, nor we sent a ping.
     * This is useful to detect a timeout in case we'll not be able to connect
     * with the node at all. */
    ri->last_ping_time = mstime();
    ri->last_avail_time = mstime();
    ri->last_pong_time = mstime();
    ri->last_pub_time = mstime();
    ri->last_hello_time = mstime();
    ri->last_master_down_reply_time = mstime();
    ri->s_down_since_time = 0;
    ri->o_down_since_time = 0;
    ri->down_after_period = master ? master->down_after_period :
                            SENTINEL_DEFAULT_DOWN_AFTER;
    ri->master_link_down_time = 0;
    ri->auth_pass = NULL;
    ri->slave_priority = SENTINEL_DEFAULT_SLAVE_PRIORITY;
    ri->slave_reconf_sent_time = 0;
    ri->slave_master_host = NULL;
    ri->slave_master_port = 0;
    ri->slave_master_link_status = SENTINEL_MASTER_LINK_STATUS_DOWN;
    ri->slave_repl_offset = 0;
    ri->sentinels = dictCreate(&instancesDictType,NULL);
    ri->quorum = quorum;
    ri->parallel_syncs = SENTINEL_DEFAULT_PARALLEL_SYNCS;
    ri->master = master;
    ri->slaves = dictCreate(&instancesDictType,NULL);
    ri->info_refresh = 0;

    /* Failover state. */
    ri->leader = NULL;
    ri->leader_epoch = 0;
    ri->failover_epoch = 0;
    ri->failover_state = SENTINEL_FAILOVER_STATE_NONE;
    ri->failover_state_change_time = 0;
    ri->failover_start_time = 0;
    ri->failover_timeout = SENTINEL_DEFAULT_FAILOVER_TIMEOUT;
    ri->failover_delay_logged = 0;
    ri->promoted_slave = NULL;
    ri->notification_script = NULL;
    ri->client_reconfig_script = NULL;

    /* Role */
    ri->role_reported = ri->flags & (SRI_MASTER|SRI_SLAVE);
    ri->role_reported_time = mstime();
    ri->slave_conf_change_time = mstime();

    /* Add into the right table. */
    // 将实例添加到适当的表中
    dictAdd(table, ri->name, ri);

    // 返回实例
    return ri;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movl %esi, %r12d
testb $0x7, %r12b
je 0x5c3da
movq %r9, %rbx
movl %r8d, 0xc(%rsp)
testq %r9, %r9
setne %al
orb %r12b, %al
testb $0x1, %al
je 0x5c3ef
movl %ecx, %r14d
movq %rdx, %rbp
movq %rdi, %r15
movq %rdx, %rdi
movl %ecx, %esi
callq 0x5b595
testq %rax, %rax
je 0x5c232
movq %rax, %r13
testb $0x6, %r12b
je 0x5c1d1
movq %rbp, %rdi
movl $0x3a, %esi
callq 0x1f790
testq %rax, %rax
leaq 0x3c785(%rip), %rax     # 0x98931
leaq 0x3ae7b(%rip), %rdx     # 0x9702e
cmoveq %rax, %rdx
leaq 0x10(%rsp), %r15
movl $0x80, %esi
movq %r15, %rdi
movq %rbp, %rcx
movl %r14d, %r8d
xorl %eax, %eax
callq 0x1f120
testb $0x1, %r12b
je 0x5c1e0
leaq 0x82712(%rip), %rax     # 0xde8f0
jmp 0x5c201
testb $0x2, %r12b
jne 0x5c1f1
testb $0x4, %r12b
jne 0x5c1fa
xorl %r14d, %r14d
jmp 0x5c204
leaq 0xc8(%rbx), %rax
jmp 0x5c201
leaq 0xc0(%rbx), %rax
movq (%rax), %r14
movq %r15, %rdi
callq 0x281da
movq %rax, %rbp
movq %r14, %rdi
movq %rax, %rsi
callq 0x224dc
testq %rax, %rax
je 0x5c23a
movq %rbp, %rdi
callq 0x28204
callq 0x1f810
movl $0x10, (%rax)
xorl %r15d, %r15d
jmp 0x5c3c5
movl $0x170, %edi            # imm = 0x170
callq 0x29709
movq %rax, %r15
orl $0x8, %r12d
movl %r12d, (%rax)
movq %rbp, 0x8(%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rax)
movq %r13, 0x20(%rax)
movups %xmm0, 0x28(%rax)
movl $0x0, 0x38(%rax)
movups %xmm0, 0x40(%rax)
movq $0x0, 0x50(%rax)
callq 0x232a3
movq %rax, 0x60(%r15)
callq 0x232a3
movq %rax, 0x58(%r15)
callq 0x232a3
movq %rax, 0x68(%r15)
callq 0x232a3
movq %rax, 0x70(%r15)
callq 0x232a3
movq %rax, 0x78(%r15)
callq 0x232a3
movq %rax, 0x80(%r15)
xorps %xmm0, %xmm0
movups %xmm0, 0x88(%r15)
testq %rbx, %rbx
je 0x5c2c6
movq 0x98(%rbx), %rax
jmp 0x5c2cb
movl $0x7530, %eax           # imm = 0x7530
movq %rax, 0x98(%r15)
movups %xmm0, 0xd8(%r15)
movl $0x64, 0xe8(%r15)
xorl %r13d, %r13d
movq %r13, 0xf0(%r15)
movq %r13, 0x100(%r15)
movabsq $0x100000000, %rax      # imm = 0x100000000
movq %rax, 0x108(%r15)
movq %r13, 0x110(%r15)
leaq 0x6d86b(%rip), %r12     # 0xc9b80
movq %r12, %rdi
xorl %esi, %esi
callq 0x21f97
movq %rax, 0xc0(%r15)
movl 0xc(%rsp), %eax
movl %eax, 0xd0(%r15)
movl $0x1, 0xd4(%r15)
movq %rbx, 0xf8(%r15)
movq %r12, %rdi
xorl %esi, %esi
callq 0x21f97
movq %rax, 0xc8(%r15)
movq %r13, 0xa0(%r15)
xorps %xmm0, %xmm0
movups %xmm0, 0x118(%r15)
movups %xmm0, 0x124(%r15)
movups %xmm0, 0x138(%r15)
movq $0x2bf20, 0x148(%r15) # imm = 0x2BF20
movups %xmm0, 0x150(%r15)
movups %xmm0, 0x160(%r15)
movl (%r15), %eax
andl $0x3, %eax
movl %eax, 0xa8(%r15)
callq 0x232a3
movq %rax, 0xb0(%r15)
callq 0x232a3
movq %rax, 0xb8(%r15)
movq 0x8(%r15), %rsi
movq %r14, %rdi
movq %r15, %rdx
callq 0x222b6
movq %r15, %rax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x42b99(%rip), %rdi     # 0x9ef7a
leaq 0x429cc(%rip), %rsi     # 0x9edb4
movl $0x50c, %edx            # imm = 0x50C
jmp 0x5c402
leaq 0x42bb0(%rip), %rdi     # 0x9efa6
leaq 0x429b7(%rip), %rsi     # 0x9edb4
movl $0x50d, %edx            # imm = 0x50D
callq 0x4d037
movl $0x1, %edi
callq 0x1f3b0