// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/pubsub.c
// Function: pubsubPublishMessage
int pubsubPublishMessage(robj *channel, robj *message) {
    int receivers = 0;
    dictEntry *de;
    listNode *ln;
    listIter li;

    /* Send to clients listening for that channel */
    // 取出包含所有订阅频道 channel 的客户端的链表
    // 并将消息发送给它们
    de = dictFind(server.pubsub_channels,channel);
    if (de) {
        list *list = dictGetVal(de);
        listNode *ln;
        listIter li;

        // 遍历客户端链表，将 message 发送给它们
        listRewind(list,&li);
        while ((ln = listNext(&li)) != NULL) {
            redisClient *c = ln->value;

            // 回复客户端。
            // 示例：
            // 1) "message"
            // 2) "xxx"
            // 3) "hello"
            addReply(c,shared.mbulkhdr[3]);
            // "message" 字符串
            addReply(c,shared.messagebulk);
            // 消息的来源频道
            addReplyBulk(c,channel);
            // 消息内容
            addReplyBulk(c,message);

            // 接收客户端计数
            receivers++;
        }
    }

    /* Send to clients listening to matching channels */
    // 将消息也发送给那些和频道匹配的模式
    if (listLength(server.pubsub_patterns)) {

        // 遍历模式链表
        listRewind(server.pubsub_patterns,&li);
        channel = getDecodedObject(channel);
        while ((ln = listNext(&li)) != NULL) {

            // 取出 pubsubPattern
            pubsubPattern *pat = ln->value;

            // 如果 channel 和 pattern 匹配
            // 就给所有订阅该 pattern 的客户端发送消息
            if (stringmatchlen((char*)pat->pattern->ptr,
                                sdslen(pat->pattern->ptr),
                                (char*)channel->ptr,
                                sdslen(channel->ptr),0)) {

                // 回复客户端
                // 示例：
                // 1) "pmessage"
                // 2) "*"
                // 3) "xxx"
                // 4) "hello"
                addReply(pat->client,shared.mbulkhdr[4]);
                addReply(pat->client,shared.pmessagebulk);
                addReplyBulk(pat->client,pat->pattern);
                addReplyBulk(pat->client,channel);
                addReplyBulk(pat->client,message);

                // 对接收消息的客户端进行计数
                receivers++;
            }
        }

        decrRefCount(channel);
    }

    // 返回计数
    return receivers;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
leaq 0xb1877(%rip), %rax     # 0x1138f8
movq 0x7a8(%rax), %rdi
movq -0x8(%rbp), %rsi
callq 0x23aa0
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x6212d
movq -0x20(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x202b0
leaq -0x58(%rbp), %rdi
callq 0x20310
movq %rax, -0x48(%rbp)
cmpq $0x0, %rax
je 0x6212b
movq -0x48(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rdi
leaq 0xb206d(%rip), %rax     # 0x114150
movq 0x13a48(%rax), %rsi
callq 0x35a70
movq -0x60(%rbp), %rdi
leaq 0xb2056(%rip), %rax     # 0x114150
movq 0xf8(%rax), %rsi
callq 0x35a70
movq -0x60(%rbp), %rdi
movq -0x8(%rbp), %rsi
callq 0x36620
movq -0x60(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x36620
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x620b9
jmp 0x6212d
leaq 0xb17c4(%rip), %rax     # 0x1138f8
movq 0x7b0(%rax), %rax
cmpq $0x0, 0x28(%rax)
je 0x62263
leaq 0xb17ab(%rip), %rax     # 0x1138f8
movq 0x7b0(%rax), %rdi
leaq -0x38(%rbp), %rsi
callq 0x202b0
movq -0x8(%rbp), %rdi
callq 0x3aef0
movq %rax, -0x8(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x20310
movq %rax, -0x28(%rbp)
cmpq $0x0, %rax
je 0x6225a
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, -0x80(%rbp)
movq -0x68(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x8(%rax), %rdi
callq 0x61860
movl %eax, -0x74(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x70(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x61860
movq -0x80(%rbp), %rdi
movl -0x74(%rbp), %esi
movq -0x70(%rbp), %rdx
movl %eax, %ecx
xorl %r8d, %r8d
callq 0x38f60
cmpl $0x0, %eax
je 0x62255
movq -0x68(%rbp), %rax
movq (%rax), %rdi
leaq 0xb1f5e(%rip), %rax     # 0x114150
movq 0x13a50(%rax), %rsi
callq 0x35a70
movq -0x68(%rbp), %rax
movq (%rax), %rdi
leaq 0xb1f44(%rip), %rax     # 0x114150
movq 0x100(%rax), %rsi
callq 0x35a70
movq -0x68(%rbp), %rax
movq (%rax), %rdi
movq -0x68(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x36620
movq -0x68(%rbp), %rax
movq (%rax), %rdi
movq -0x8(%rbp), %rsi
callq 0x36620
movq -0x68(%rbp), %rax
movq (%rax), %rdi
movq -0x10(%rbp), %rsi
callq 0x36620
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x6216a
movq -0x8(%rbp), %rdi
callq 0x3aaa0
movl -0x14(%rbp), %eax
addq $0x80, %rsp
popq %rbp
retq
nop