// File: /workspace/github_c_makefile_star2_O1/zhou-yuxin[P]redis-aof-no-cow/src/multi.c
// Function: execCommand
void execCommand(client *c) {
    int j;
    robj **orig_argv;
    int orig_argc;
    struct redisCommand *orig_cmd;
    int must_propagate = 0; /* Need to propagate MULTI/EXEC to AOF / slaves? */

    if (!(c->flags & CLIENT_MULTI)) {
        addReplyError(c,"EXEC without MULTI");
        return;
    }

    /* Check if we need to abort the EXEC because:
     * 1) Some WATCHed key was touched.
     * 2) There was a previous error while queueing commands.
     * A failed EXEC in the first case returns a multi bulk nil object
     * (technically it is not an error but a special behavior), while
     * in the second an EXECABORT error is returned. */
    if (c->flags & (CLIENT_DIRTY_CAS|CLIENT_DIRTY_EXEC)) {
        addReply(c, c->flags & CLIENT_DIRTY_EXEC ? shared.execaborterr :
                                                  shared.nullmultibulk);
        discardTransaction(c);
        goto handle_monitor;
    }

    /* Exec all the queued commands */
    unwatchAllKeys(c); /* Unwatch ASAP otherwise we'll waste CPU cycles */
    orig_argv = c->argv;
    orig_argc = c->argc;
    orig_cmd = c->cmd;
    addReplyMultiBulkLen(c,c->mstate.count);
    for (j = 0; j < c->mstate.count; j++) {
        c->argc = c->mstate.commands[j].argc;
        c->argv = c->mstate.commands[j].argv;
        c->cmd = c->mstate.commands[j].cmd;

        /* Propagate a MULTI request once we encounter the first write op.
         * This way we'll deliver the MULTI/..../EXEC block as a whole and
         * both the AOF and the replication link will have the same consistency
         * and atomicity guarantees. */
        if (!must_propagate && !(c->cmd->flags & CMD_READONLY)) {
            execCommandPropagateMulti(c);
            must_propagate = 1;
        }

        call(c,CMD_CALL_FULL);

        /* Commands may alter argc/argv, restore mstate. */
        c->mstate.commands[j].argc = c->argc;
        c->mstate.commands[j].argv = c->argv;
        c->mstate.commands[j].cmd = c->cmd;
    }
    c->argv = orig_argv;
    c->argc = orig_argc;
    c->cmd = orig_cmd;
    discardTransaction(c);
    /* Make sure the EXEC command will be propagated as well if MULTI
     * was already propagated. */
    if (must_propagate) server.dirty++;

handle_monitor:
    /* Send EXEC to clients waiting data from MONITOR. We do it here
     * since the natural order of commands execution is actually:
     * MUTLI, EXEC, ... commands inside transaction ...
     * Instead EXEC is flagged as CMD_SKIP_MONITOR in the command
     * table, and we do it here with correct ordering. */
    if (listLength(server.monitors) && !server.loading)
        replicationFeedMonitors(c,server.monitors,c->db->id,c->argv,c->argc);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
movl 0x98(%rdi), %eax
testb $0x8, %al
jne 0x648ff
leaq 0x644ff(%rip), %rsi     # 0xc8de8
movq %rbx, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3ffcb
testl $0x1020, %eax           # imm = 0x1020
je 0x649b0
btl $0xc, %eax
leaq 0xa299b(%rip), %rax     # 0x1072b0
movl $0x58, %ecx
movl $0xc8, %edx
cmovaeq %rcx, %rdx
movq (%rax,%rdx), %rsi
movq %rbx, %rdi
callq 0x3fc19
movq %rbx, %rdi
callq 0x6458e
movq $0x0, 0x150(%rbx)
movl $0x0, 0x158(%rbx)
andl $0xffffefd7, 0x98(%rbx) # imm = 0xFFFFEFD7
movq %rbx, %rdi
callq 0x646d5
leaq 0xa1ef3(%rip), %rax     # 0x106858
movq 0x1e8(%rax), %rsi
cmpq $0x0, 0x28(%rsi)
je 0x649a1
cmpl $0x0, 0x31c(%rax)
jne 0x649a1
movq 0x10(%rbx), %rax
movl 0x30(%rax), %edx
movq 0x40(%rbx), %rcx
movl 0x38(%rbx), %r8d
movq %rbx, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x47615
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
callq 0x646d5
movq 0x40(%rbx), %r15
movl 0x38(%rbx), %ebp
movq 0x48(%rbx), %r14
movslq 0x158(%rbx), %rsi
movq %rbx, %rdi
callq 0x4063b
cmpl $0x0, 0x158(%rbx)
jle 0x64ad7
movl %ebp, 0xc(%rsp)
movq %r14, 0x10(%rsp)
xorl %r12d, %r12d
movl $0x10, %r13d
xorl %ebp, %ebp
movl %ebp, %ecx
movq 0x150(%rbx), %rax
movl -0x8(%rax,%r13), %edx
movl %edx, 0x38(%rbx)
movq -0x10(%rax,%r13), %rdx
movq %rdx, 0x40(%rbx)
movq (%rax,%r13), %rax
movq %rax, 0x48(%rbx)
xorl %ebp, %ebp
testl %ecx, %ecx
jne 0x64a2c
movb $0x1, %r14b
testb $0x2, 0x20(%rax)
jne 0x64a34
movq %rbx, %rdi
callq 0x64871
xorl %r14d, %r14d
movl $0x1, %ebp
movq %rbx, %rdi
movl $0xf, %esi
callq 0x35f45
movl 0x38(%rbx), %eax
movq 0x150(%rbx), %rcx
movl %eax, -0x8(%rcx,%r13)
movq 0x40(%rbx), %rax
movq %rax, -0x10(%rcx,%r13)
movq 0x48(%rbx), %rax
movq %rax, (%rcx,%r13)
incq %r12
movslq 0x158(%rbx), %rax
addq $0x18, %r13
cmpq %rax, %r12
jl 0x649f3
movq %r15, 0x40(%rbx)
movl 0xc(%rsp), %eax
movl %eax, 0x38(%rbx)
movq 0x10(%rsp), %rax
movq %rax, 0x48(%rbx)
movq %rbx, %rdi
callq 0x6458e
movq $0x0, 0x150(%rbx)
movl $0x0, 0x158(%rbx)
andl $0xffffefd7, 0x98(%rbx) # imm = 0xFFFFEFD7
movq %rbx, %rdi
callq 0x646d5
testb %r14b, %r14b
jne 0x6495e
leaq 0xa1d8d(%rip), %rax     # 0x106858
incq 0x710(%rax)
jmp 0x6495e
movq %r15, 0x40(%rbx)
movl %ebp, 0x38(%rbx)
movq %r14, 0x48(%rbx)
jmp 0x6492f