// File: /workspace/github_c_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x7e88b(%rip), %r15     # 0xc9fa8
movq 0x7a8(%r15), %rdi
movq %r14, %rsi
callq 0x226ac
testq %rax, %rax
je 0x4b7ad
movq 0x8(%rax), %rdi
leaq 0x8(%rsp), %r15
movq %r15, %rsi
callq 0x20637
movq %r15, %rdi
callq 0x20654
xorl %ebp, %ebp
testq %rax, %rax
je 0x4b7a4
leaq 0x7f0a8(%rip), %r13     # 0xca800
leaq 0x8(%rsp), %r15
movq 0x10(%rax), %r12
movq 0x13a48(%r13), %rsi
movq %r12, %rdi
callq 0x2d97c
movq 0xf8(%r13), %rsi
movq %r12, %rdi
callq 0x2d97c
movq %r12, %rdi
movq %r14, %rsi
callq 0x2e204
movq %r12, %rdi
movq %rbx, %rsi
callq 0x2e204
incl %ebp
movq %r15, %rdi
callq 0x20654
testq %rax, %rax
jne 0x4b75d
leaq 0x7e7fd(%rip), %r15     # 0xc9fa8
jmp 0x4b7af
xorl %ebp, %ebp
movq 0x7b0(%r15), %rdi
cmpq $0x0, 0x28(%rdi)
je 0x4b876
leaq 0x8(%rsp), %r15
movq %r15, %rsi
callq 0x20637
movq %r14, %rdi
callq 0x30d93
movq %rax, %r14
movq %r15, %rdi
callq 0x20654
testq %rax, %rax
je 0x4b86e
leaq 0x8(%rsp), %r15
leaq 0x7f00a(%rip), %r12     # 0xca800
movq 0x10(%rax), %r13
movq 0x8(%r13), %rax
movq 0x8(%rax), %rdi
movl -0x8(%rdi), %esi
movq 0x8(%r14), %rdx
movl -0x8(%rdx), %ecx
xorl %r8d, %r8d
callq 0x2fc6c
testl %eax, %eax
je 0x4b861
movq (%r13), %rdi
movq 0x13a50(%r12), %rsi
callq 0x2d97c
movq (%r13), %rdi
movq 0x100(%r12), %rsi
callq 0x2d97c
movq (%r13), %rdi
movq 0x8(%r13), %rsi
callq 0x2e204
movq (%r13), %rdi
movq %r14, %rsi
callq 0x2e204
movq (%r13), %rdi
movq %rbx, %rsi
callq 0x2e204
incl %ebp
movq %r15, %rdi
callq 0x20654
testq %rax, %rax
jne 0x4b7f6
movq %r14, %rdi
callq 0x30b0c
movl %ebp, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq