// File: /workspace/github_c_makefile_star2_O3/nilyang[P]redis-tdd-annotation/src/t_list.c
// Function: pushxGenericCommand
void pushxGenericCommand(redisClient *c, robj *refval, robj *val, int where) {
    robj *subject;
    listTypeIterator *iter;
    listTypeEntry entry;
    int inserted = 0;

    // 取出列表对象
    if ((subject = lookupKeyReadOrReply(c,c->argv[1],shared.czero)) == NULL ||
        checkType(c,subject,REDIS_LIST)) return;

    // 执行的是 LINSERT 命令
    if (refval != NULL) {
        /* We're not sure if this value can be inserted yet, but we cannot
         * convert the list inside the iterator. We don't want to loop over
         * the list twice (once to see if the value can be inserted and once
         * to do the actual insert), so we assume this value can be inserted
         * and convert the ziplist to a regular list if necessary. */
        // 看保存值 value 是否需要将列表编码转换为双端链表
        listTypeTryConversion(subject,val);

        /* Seek refval from head to tail */
        // 在列表中查找 refval 对象
        iter = listTypeInitIterator(subject,0,REDIS_TAIL);
        while (listTypeNext(iter,&entry)) {
            if (listTypeEqual(&entry,refval)) {
                // 找到了，将值插入到节点的前面或后面
                listTypeInsert(&entry,val,where);
                inserted = 1;
                break;
            }
        }
        listTypeReleaseIterator(iter);

        if (inserted) {
            /* Check if the length exceeds the ziplist length threshold. */
            // 查看插入之后是否需要将编码转换为双端链表
            if (subject->encoding == REDIS_ENCODING_ZIPLIST &&
                ziplistLen(subject->ptr) > server.list_max_ziplist_entries)
                    listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);

            signalModifiedKey(c->db,c->argv[1]);

            notifyKeyspaceEvent(REDIS_NOTIFY_LIST,"linsert",
                                c->argv[1],c->db->id);
            server.dirty++;
        } else {
            /* Notify client of a failed insert */
            // refval 不存在，插入失败
            addReply(c,shared.cnegone);
            return;
        }

    // 执行的是 LPUSHX 或 RPUSHX 命令
    } else {
        char *event = (where == REDIS_HEAD) ? "lpush" : "rpush";

        listTypePush(subject,val,where);

        signalModifiedKey(c->db,c->argv[1]);

        notifyKeyspaceEvent(REDIS_NOTIFY_LIST,event,c->argv[1],c->db->id);

        server.dirty++;
    }

    addReplyLongLong(c,listTypeLength(subject));
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %ecx, %ebp
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %rbx
movq 0x38(%rdi), %rax
movq 0x8(%rax), %rsi
leaq 0x90802(%rip), %rax     # 0xca800
movq 0x20(%rax), %rdx
callq 0x31745
testq %rax, %rax
je 0x3a023
movq %rax, %r14
movq %rbx, %rdi
movq %rax, %rsi
movl $0x1, %edx
callq 0x30bbf
testl %eax, %eax
je 0x3a032
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testq %r12, %r12
je 0x3a0da
movl %ebp, 0xc(%rsp)
movq %r14, %rdi
movq %r15, %rsi
callq 0x39684
movq %r14, %rdi
xorl %esi, %esi
movl $0x1, %edx
callq 0x399c5
movq %rax, %r13
leaq 0x10(%rsp), %rbp
movq %r13, %rdi
movq %rbp, %rsi
callq 0x39a5a
testl %eax, %eax
je 0x3a157
movq %rbp, %rdi
movq %r12, %rsi
callq 0x39cb9
testl %eax, %eax
je 0x3a061
leaq 0x10(%rsp), %rdi
movq %r15, %rsi
movl 0xc(%rsp), %edx
callq 0x39be1
movq %r13, %rdi
callq 0x29af7
movl $0xf0, %eax
andl (%r14), %eax
leaq 0x5a266(%rip), %r12     # 0x94311
cmpl $0x50, %eax
jne 0x3a0fb
movq 0x8(%r14), %rdi
callq 0x2cc17
movl %eax, %eax
leaq 0x8fee6(%rip), %rcx     # 0xc9fa8
cmpq %rax, 0x768(%rcx)
jae 0x3a0fb
movq %r14, %rdi
movl $0x4, %esi
callq 0x396bc
jmp 0x3a0fb
testl %ebp, %ebp
leaq 0x5a244(%rip), %rax     # 0x94327
leaq 0x5a213(%rip), %r12     # 0x942fd
cmoveq %rax, %r12
movq %r14, %rdi
movq %r15, %rsi
movl %ebp, %edx
callq 0x397a9
movq 0x8(%rbx), %rdi
movq 0x38(%rbx), %rax
movq 0x8(%rax), %rsi
callq 0x319b8
movq 0x8(%rbx), %rax
movq 0x38(%rbx), %rcx
movq 0x8(%rcx), %rdx
movl 0x30(%rax), %ecx
movl $0x10, %edi
movq %r12, %rsi
callq 0x60371
leaq 0x8fe79(%rip), %rax     # 0xc9fa8
incq 0x560(%rax)
movq %r14, %rdi
callq 0x39979
movq %rbx, %rdi
movq %rax, %rsi
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2e133
movq %r13, %rdi
callq 0x29af7
leaq 0x9069a(%rip), %rax     # 0xca800
movq 0x30(%rax), %rsi
movq %rbx, %rdi
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2d97c