// File: zkl94[P]distributed-key-value-store/MP1Node.cpp
// Function: MP1Node::handleJOINREQ(void*, char*, int)
void MP1Node::handleJOINREQ(void *env, char *data, int size) {
    #ifdef DEBUG_JOINREQ
        cout << "received a join request" << endl;
    #endif

    // when introducer receives JOINREQ, add the node to member list, and return JOINREP with cluster member list
    char addr[6];
    // msg: sizeof(MessageHdr) + 6 + sizeof(long)
    MessageHdr *msg = (MessageHdr *)data;
    memcpy(&addr, (char *)(msg)+4, 6);
    int id = 0;
    short port;
    memcpy(&id, &addr[0], sizeof(int));
    memcpy(&port, &addr[4], sizeof(short));

    #ifdef DEBUG_JOINREQ
        cout << "id = " << id << "; port = " << port << endl;
    #endif

    #ifdef DEBUG_JOINREQ
        cout << "before adding member list entry, there are " << memberNode->memberList.size() << " entries" << endl;
    #endif

    // newly added node have 0 heartbeat
    MemberListEntry *newEntry = new MemberListEntry(id, port, 0, par->getcurrtime());
    memberNode->memberList.push_back(*newEntry);

    logNodeAddWrapper(memberNode, id, port);

    #ifdef DEBUG_JOINREQ
        cout << "after adding member list entry, there are " << memberNode->memberList.size() << " entries" << endl;
    #endif

    // return JOINREP with cluster member list
    int entry_num = memberNode->memberList.size();
    int currentOffset = 0;
    // allocate maximum space possibly needed
    size_t JOINREPMsgSize = sizeof(MessageHdr) + (sizeof(addr) + sizeof(long)) * entry_num;
    MessageHdr *JOINREPMsg;
    JOINREPMsg = (MessageHdr *) malloc(JOINREPMsgSize * sizeof(char));
    JOINREPMsg->msgType = JOINREP;
    // for the message type offset
    currentOffset += sizeof(int);

    for (MemberListEntry memberListEntry: memberNode->memberList) {
        // if it is to be deleted, don't add it to member list messages
        if (this->tobedeleted->count(memberListEntry.getid()) != 0) {
            continue;
        }

        Address address;
        string _address = to_string(memberListEntry.getid()) + ":" + to_string(memberListEntry.getport());
        address = Address(_address);
        // add to JOINREPMsg
        memcpy((char *)(JOINREPMsg) + currentOffset, &address.addr, sizeof(address.addr));
        currentOffset += sizeof(address.addr);
        memcpy((char *)(JOINREPMsg) + currentOffset, &memberListEntry.heartbeat, sizeof(long));
        currentOffset += sizeof(long);
        // only send heartbeat, timestamp is set by receivers with par->getcurrtime()
        // also, timestamp is not global and thus no need to sync
    }

    #ifdef DEBUG_JOINREQ
        cout << "currentOffset = " << currentOffset << " JOINREPMsgSize = " << JOINREPMsgSize << endl;
    #endif

    // not necessarily because to be deleted entries are not included
    // assert(currentOffset == (int)JOINREPMsgSize);

    string _address = to_string(id) + ":" + to_string(port);
    Address address = Address(_address);
    emulNet->ENsend(&memberNode->addr, &address, (char *)JOINREPMsg, currentOffset);
    #ifdef DEBUG_JOINREQ
        cout << "JOINREP successfully sent" <<endl;
    #endif
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x240, %rsp            # imm = 0x240
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x218(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movw 0x8(%rax), %cx
movw %cx, -0x20(%rbp)
movl 0x4(%rax), %eax
movl %eax, -0x24(%rbp)
movl $0x0, -0x34(%rbp)
movl -0x24(%rbp), %eax
movl %eax, -0x34(%rbp)
movw -0x20(%rbp), %ax
movw %ax, -0x36(%rbp)
movl $0x18, %edi
callq 0x4310
movq %rax, %rcx
movq -0x218(%rbp), %rax
movq %rcx, -0x210(%rbp)
movl -0x34(%rbp), %ecx
movl %ecx, -0x204(%rbp)
movw -0x36(%rbp), %cx
movw %cx, -0x1fe(%rbp)
movq 0x18(%rax), %rdi
callq 0x15020
movl %eax, -0x1fc(%rbp)
jmp 0x5f54
movl -0x204(%rbp), %esi
movq -0x210(%rbp), %rdi
movw -0x1fe(%rbp), %ax
movl -0x1fc(%rbp), %ecx
movslq %ecx, %r8
movswl %ax, %edx
xorl %eax, %eax
movl %eax, %ecx
callq 0x15110
jmp 0x5f7f
movq -0x218(%rbp), %rax
movq -0x210(%rbp), %rcx
movq %rcx, -0x40(%rbp)
movq 0x20(%rax), %rdi
addq $0x28, %rdi
movq -0x40(%rbp), %rsi
callq 0x6da0
movq -0x218(%rbp), %rdi
movq 0x20(%rdi), %rsi
movl -0x34(%rbp), %edx
movswl -0x36(%rbp), %ecx
callq 0x5d00
movq -0x218(%rbp), %rax
movq 0x20(%rax), %rdi
addq $0x28, %rdi
callq 0x7220
movl %eax, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
movslq -0x50(%rbp), %rax
imulq $0xe, %rax, %rax
addq $0x4, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rdi
shlq $0x0, %rdi
callq 0x4440
movq %rax, %rcx
movq -0x218(%rbp), %rax
movq %rcx, -0x68(%rbp)
movq -0x68(%rbp), %rcx
movl $0x1, (%rcx)
movslq -0x54(%rbp), %rcx
addq $0x4, %rcx
movl %ecx, -0x54(%rbp)
movq 0x20(%rax), %rax
addq $0x28, %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rdi
callq 0x7250
movq %rax, -0x78(%rbp)
movq -0x70(%rbp), %rdi
callq 0x7280
movq %rax, -0x80(%rbp)
leaq -0x78(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x72b0
testb $0x1, %al
jne 0x6053
jmp 0x62b8
leaq -0x78(%rbp), %rdi
callq 0x72f0
movq %rax, %rsi
leaq -0x98(%rbp), %rdi
callq 0x15180
movq -0x218(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x220(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x15240
movq -0x220(%rbp), %rdi
movl %eax, -0x9c(%rbp)
leaq -0x9c(%rbp), %rsi
callq 0x7310
cmpq $0x0, %rax
je 0x60cf
jmp 0x6222
movq -0x210(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
movl $0x18, %esi
callq 0x4320
jmp 0x6430
leaq -0xa2(%rbp), %rdi
callq 0x6d90
leaq -0x98(%rbp), %rdi
callq 0x15240
movl %eax, %esi
leaq -0x108(%rbp), %rdi
movq %rdi, -0x228(%rbp)
callq 0x6f90
movq -0x228(%rbp), %rsi
leaq 0x21b9f(%rip), %rdx     # 0x27ca9
leaq -0xe8(%rbp), %rdi
callq 0x6f40
jmp 0x6118
leaq -0x98(%rbp), %rdi
callq 0x15250
movw %ax, -0x22a(%rbp)
jmp 0x612d
movw -0x22a(%rbp), %ax
movswl %ax, %esi
leaq -0x128(%rbp), %rdi
callq 0x6f90
jmp 0x6145
leaq -0xc8(%rbp), %rdi
leaq -0xe8(%rbp), %rsi
leaq -0x128(%rbp), %rdx
callq 0x6e70
jmp 0x6161
leaq -0x128(%rbp), %rdi
callq 0x41e0
leaq -0xe8(%rbp), %rdi
callq 0x41e0
leaq -0x108(%rbp), %rdi
callq 0x41e0
leaq -0x150(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x4150
jmp 0x619a
leaq -0x12e(%rbp), %rdi
leaq -0x150(%rbp), %rsi
callq 0x70b0
jmp 0x61af
leaq -0xa2(%rbp), %rdi
leaq -0x12e(%rbp), %rsi
callq 0x150a0
jmp 0x61c4
leaq -0x150(%rbp), %rdi
callq 0x41e0
movq -0x68(%rbp), %rax
movslq -0x54(%rbp), %rcx
movl -0xa2(%rbp), %edx
movl %edx, (%rax,%rcx)
movw -0x9e(%rbp), %dx
movw %dx, 0x4(%rax,%rcx)
movslq -0x54(%rbp), %rax
addq $0x6, %rax
movl %eax, -0x54(%rbp)
movq -0x68(%rbp), %rax
movslq -0x54(%rbp), %rcx
movq -0x90(%rbp), %rdx
movq %rdx, (%rax,%rcx)
movslq -0x54(%rbp), %rax
addq $0x8, %rax
movl %eax, -0x54(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x41e0
leaq -0x78(%rbp), %rdi
callq 0x7370
jmp 0x603d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x6270
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x6264
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x128(%rbp), %rdi
callq 0x41e0
leaq -0xe8(%rbp), %rdi
callq 0x41e0
leaq -0x108(%rbp), %rdi
callq 0x41e0
jmp 0x6430
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x62a7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x150(%rbp), %rdi
callq 0x41e0
leaq -0xc8(%rbp), %rdi
callq 0x41e0
jmp 0x6430
movl -0x34(%rbp), %esi
leaq -0x1b0(%rbp), %rdi
movq %rdi, -0x238(%rbp)
callq 0x6f90
movq -0x238(%rbp), %rsi
leaq 0x219cd(%rip), %rdx     # 0x27ca9
leaq -0x190(%rbp), %rdi
callq 0x6f40
jmp 0x62ea
movswl -0x36(%rbp), %esi
leaq -0x1d0(%rbp), %rdi
callq 0x6f90
jmp 0x62fc
leaq -0x170(%rbp), %rdi
leaq -0x190(%rbp), %rsi
leaq -0x1d0(%rbp), %rdx
callq 0x6e70
jmp 0x6318
leaq -0x1d0(%rbp), %rdi
callq 0x41e0
leaq -0x190(%rbp), %rdi
callq 0x41e0
leaq -0x1b0(%rbp), %rdi
callq 0x41e0
leaq -0x1f8(%rbp), %rdi
leaq -0x170(%rbp), %rsi
callq 0x4150
jmp 0x6351
leaq -0x1d6(%rbp), %rdi
leaq -0x1f8(%rbp), %rsi
callq 0x70b0
jmp 0x6366
leaq -0x1f8(%rbp), %rdi
callq 0x41e0
movq -0x218(%rbp), %rax
movq 0x8(%rax), %rdi
movq 0x20(%rax), %rsi
addq $0x8, %rsi
movq -0x68(%rbp), %rcx
movl -0x54(%rbp), %r8d
leaq -0x1d6(%rbp), %rdx
callq 0xac80
jmp 0x639b
leaq -0x170(%rbp), %rdi
callq 0x41e0
addq $0x240, %rsp            # imm = 0x240
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x63f0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x63e4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x1d0(%rbp), %rdi
callq 0x41e0
leaq -0x190(%rbp), %rdi
callq 0x41e0
leaq -0x1b0(%rbp), %rdi
callq 0x41e0
jmp 0x6430
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x6424
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x1f8(%rbp), %rdi
callq 0x41e0
leaq -0x170(%rbp), %rdi
callq 0x41e0
movq -0x48(%rbp), %rdi
callq 0x4550
nopl (%rax)