// File: /workspace/github_c_makefile_star2_O0/nilyang[P]redis-tdd-annotation/src/networking.c
// Function: freeClient
void freeClient(redisClient *c) {
    listNode *ln;

    /* If this is marked as current client unset it */
    if (server.current_client == c) server.current_client = NULL;

    /* If it is our master that's beging disconnected we should make sure
     * to cache the state to try a partial resynchronization later.
     *
     * Note that before doing this we make sure that the client is not in
     * some unexpected state, by checking its flags. */
    if (server.master && c->flags & REDIS_MASTER) {
        redisLog(REDIS_WARNING,"Connection with master lost.");
        if (!(c->flags & (REDIS_CLOSE_AFTER_REPLY|
                          REDIS_CLOSE_ASAP|
                          REDIS_BLOCKED|
                          REDIS_UNBLOCKED)))
        {
            replicationCacheMaster(c);
            return;
        }
    }

    /* Log link disconnection with slave */
    if ((c->flags & REDIS_SLAVE) && !(c->flags & REDIS_MONITOR)) {
        char ip[REDIS_IP_STR_LEN];

        if (anetPeerToString(c->fd,ip,sizeof(ip),NULL) != -1) {
            redisLog(REDIS_WARNING,"Connection with slave %s:%d lost.",
                ip, c->slave_listening_port);
        }
    }

    /* Free the query buffer */
    sdsfree(c->querybuf);
    c->querybuf = NULL;

    /* Deallocate structures used to block on blocking ops. */
    if (c->flags & REDIS_BLOCKED) unblockClient(c);
    dictRelease(c->bpop.keys);

    /* UNWATCH all the keys */
    // 清空 WATCH 信息
    unwatchAllKeys(c);
    listRelease(c->watched_keys);

    /* Unsubscribe from all the pubsub channels */
    // 退订所有频道和模式
    pubsubUnsubscribeAllChannels(c,0);
    pubsubUnsubscribeAllPatterns(c,0);
    dictRelease(c->pubsub_channels);
    listRelease(c->pubsub_patterns);

    /* Close socket, unregister events, and remove list of replies and
     * accumulated arguments. */
    // 关闭套接字，并从事件处理器中删除该套接字的事件
    if (c->fd != -1) {
        aeDeleteFileEvent(server.el,c->fd,AE_READABLE);
        aeDeleteFileEvent(server.el,c->fd,AE_WRITABLE);
        close(c->fd);
    }

    // 清空回复缓冲区
    listRelease(c->reply);

    // 清空命令参数
    freeClientArgv(c);

    /* Remove from the list of clients */
    // 从服务器的客户端链表中删除自身
    if (c->fd != -1) {
        ln = listSearchKey(server.clients,c);
        redisAssert(ln != NULL);
        listDelNode(server.clients,ln);
    }

    /* When client was just unblocked because of a blocking operation,
     * remove it from the list of unblocked clients. */
    // 删除客户端的阻塞信息
    if (c->flags & REDIS_UNBLOCKED) {
        ln = listSearchKey(server.unblocked_clients,c);
        redisAssert(ln != NULL);
        listDelNode(server.unblocked_clients,ln);
    }

    /* Master/slave cleanup Case 1:
     * we lost the connection with a slave. */
    if (c->flags & REDIS_SLAVE) {
        if (c->replstate == REDIS_REPL_SEND_BULK) {
            if (c->repldbfd != -1) close(c->repldbfd);
            if (c->replpreamble) sdsfree(c->replpreamble);
        }
        list *l = (c->flags & REDIS_MONITOR) ? server.monitors : server.slaves;
        ln = listSearchKey(l,c);
        redisAssert(ln != NULL);
        listDelNode(l,ln);
        /* We need to remember the time when we started to have zero
         * attached slaves, as after some time we'll free the replication
         * backlog. */
        if (c->flags & REDIS_SLAVE && listLength(server.slaves) == 0)
            server.repl_no_slaves_since = server.unixtime;
        refreshGoodSlavesCount();
    }

    /* Master/slave cleanup Case 2:
     * we lost the connection with the master. */
    if (c->flags & REDIS_MASTER) replicationHandleMasterDisconnection();

    /* If this client was scheduled for async freeing we need to remove it
     * from the queue. */
    if (c->flags & REDIS_CLOSE_ASAP) {
        ln = listSearchKey(server.clients_to_close,c);
        redisAssert(ln != NULL);
        listDelNode(server.clients_to_close,ln);
    }

    /* Release other dynamically allocated client structure fields,
     * and finally release the client structure itself. */
    if (c->name) decrRefCount(c->name);
    // 清除参数空间
    zfree(c->argv);
    // 清除事务状态信息
    freeClientMultiState(c);
    sdsfree(c->peerid);
    // 释放客户端 redisClient 结构本身
    zfree(c);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
leaq 0xdce65(%rip), %rax     # 0x1138f8
movq 0x1d0(%rax), %rax
cmpq -0x8(%rbp), %rax
jne 0x36ab2
leaq 0xdce51(%rip), %rax     # 0x1138f8
movq $0x0, 0x1d0(%rax)
leaq 0xdce3f(%rip), %rax     # 0x1138f8
cmpq $0x0, 0x660(%rax)
je 0x36b0c
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x36b0c
movl $0x3, %edi
leaq 0xaa42f(%rip), %rsi     # 0xe0f10
movb $0x0, %al
callq 0x24fb0
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x4d0, %eax            # imm = 0x4D0
cmpl $0x0, %eax
jne 0x36b0a
movq -0x8(%rbp), %rdi
callq 0x42330
jmp 0x36f39
jmp 0x36b0c
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x36b70
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
jne 0x36b70
movq -0x8(%rbp), %rax
movl (%rax), %edi
leaq -0x40(%rbp), %rsi
movl $0x2e, %edx
xorl %eax, %eax
movl %eax, %ecx
callq 0x22be0
cmpl $-0x1, %eax
je 0x36b6e
leaq -0x40(%rbp), %rdx
movq -0x8(%rbp), %rax
movl 0xfc(%rax), %ecx
movl $0x3, %edi
leaq 0xaa3c6(%rip), %rsi     # 0xe0f2d
movb $0x0, %al
callq 0x24fb0
jmp 0x36b70
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x2c160
movq -0x8(%rbp), %rax
movq $0x0, 0x20(%rax)
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0x36ba4
movq -0x8(%rbp), %rdi
callq 0x81f80
movq -0x8(%rbp), %rax
movq 0x128(%rax), %rdi
callq 0x24000
movq -0x8(%rbp), %rdi
callq 0x62990
movq -0x8(%rbp), %rax
movq 0x150(%rax), %rdi
callq 0x1fe30
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0x61e70
movq -0x8(%rbp), %rdi
xorl %esi, %esi
callq 0x61f70
movq -0x8(%rbp), %rax
movq 0x158(%rax), %rdi
callq 0x24000
movq -0x8(%rbp), %rax
movq 0x160(%rax), %rdi
callq 0x1fe30
movq -0x8(%rbp), %rax
cmpl $-0x1, (%rax)
je 0x36c4d
leaq 0xdcce5(%rip), %rax     # 0x1138f8
movq 0x28(%rax), %rdi
movq -0x8(%rbp), %rax
movl (%rax), %esi
movl $0x1, %edx
callq 0x20c60
leaq 0xdccca(%rip), %rax     # 0x1138f8
movq 0x28(%rax), %rdi
movq -0x8(%rbp), %rax
movl (%rax), %esi
movl $0x2, %edx
callq 0x20c60
movq -0x8(%rbp), %rax
movl (%rax), %edi
callq 0x1f170
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x1fe30
movq -0x8(%rbp), %rdi
callq 0x36fa0
movq -0x8(%rbp), %rax
cmpl $-0x1, (%rax)
je 0x36cc9
leaq 0xdcc85(%rip), %rax     # 0x1138f8
movq 0x1b0(%rax), %rdi
movq -0x8(%rbp), %rsi
callq 0x20480
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x36c90
jmp 0x36cb2
leaq 0xac3e2(%rip), %rdi     # 0xe3079
leaq 0xaa1ca(%rip), %rsi     # 0xe0e68
movl $0x3bf, %edx            # imm = 0x3BF
callq 0x63ca0
movl $0x1, %edi
callq 0x1f3b0
leaq 0xdcc3f(%rip), %rax     # 0x1138f8
movq 0x1b0(%rax), %rdi
movq -0x10(%rbp), %rsi
callq 0x20170
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0x36d3a
leaq 0xdcc14(%rip), %rax     # 0x1138f8
movq 0x738(%rax), %rdi
movq -0x8(%rbp), %rsi
callq 0x20480
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x36d01
jmp 0x36d23
leaq 0xac371(%rip), %rdi     # 0xe3079
leaq 0xaa159(%rip), %rsi     # 0xe0e68
movl $0x3c8, %edx            # imm = 0x3C8
callq 0x63ca0
movl $0x1, %edi
callq 0x1f3b0
leaq 0xdcbce(%rip), %rax     # 0x1138f8
movq 0x738(%rax), %rdi
movq -0x10(%rbp), %rsi
callq 0x20170
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x36e6a
movq -0x8(%rbp), %rax
cmpl $0x8, 0x98(%rax)
jne 0x36d99
movq -0x8(%rbp), %rax
cmpl $-0x1, 0x9c(%rax)
je 0x36d79
movq -0x8(%rbp), %rax
movl 0x9c(%rax), %edi
callq 0x1f170
movq -0x8(%rbp), %rax
cmpq $0x0, 0xb0(%rax)
je 0x36d97
movq -0x8(%rbp), %rax
movq 0xb0(%rax), %rdi
callq 0x2c160
jmp 0x36d99
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x36dbf
leaq 0xdcb46(%rip), %rax     # 0x1138f8
movq 0x1c8(%rax), %rax
movq %rax, -0x50(%rbp)
jmp 0x36dd1
leaq 0xdcb32(%rip), %rax     # 0x1138f8
movq 0x1c0(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rdi
movq -0x8(%rbp), %rsi
callq 0x20480
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x36df3
jmp 0x36e15
leaq 0xac27f(%rip), %rdi     # 0xe3079
leaq 0xaa067(%rip), %rsi     # 0xe0e68
movl $0x3d5, %edx            # imm = 0x3D5
callq 0x63ca0
movl $0x1, %edi
callq 0x1f3b0
movq -0x48(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x20170
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x36e65
leaq 0xdcabd(%rip), %rax     # 0x1138f8
movq 0x1c0(%rax), %rax
cmpq $0x0, 0x28(%rax)
jne 0x36e65
leaq 0xdcaa8(%rip), %rax     # 0x1138f8
movq 0x798(%rax), %rcx
leaq 0xdca9a(%rip), %rax     # 0x1138f8
movq %rcx, 0x630(%rax)
callq 0x3fc30
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x36e81
callq 0x36f40
movq -0x8(%rbp), %rax
movl 0x90(%rax), %eax
andl $0x400, %eax            # imm = 0x400
cmpl $0x0, %eax
je 0x36ef2
leaq 0xdca5c(%rip), %rax     # 0x1138f8
movq 0x1b8(%rax), %rdi
movq -0x8(%rbp), %rsi
callq 0x20480
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x36eb9
jmp 0x36edb
leaq 0xac1b9(%rip), %rdi     # 0xe3079
leaq 0xa9fa1(%rip), %rsi     # 0xe0e68
movl $0x3e7, %edx            # imm = 0x3E7
callq 0x63ca0
movl $0x1, %edi
callq 0x1f3b0
leaq 0xdca16(%rip), %rax     # 0x1138f8
movq 0x1b8(%rax), %rdi
movq -0x10(%rbp), %rsi
callq 0x20170
movq -0x8(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0x36f0a
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x3aaa0
movq -0x8(%rbp), %rax
movq 0x38(%rax), %rdi
callq 0x2e3a0
movq -0x8(%rbp), %rdi
callq 0x62790
movq -0x8(%rbp), %rax
movq 0x168(%rax), %rdi
callq 0x2c160
movq -0x8(%rbp), %rdi
callq 0x2e3a0
addq $0x50, %rsp
popq %rbp
retq
nop