// File: zkl94[P]distributed-key-value-store/MP1Node.cpp
// Function: MP1Node::nodeLoopOps()
void MP1Node::nodeLoopOps() {

    // 0. update self heartbeat and tiemstamp
    // 1. Check if any node hasn't responded within a timeout period and then delete the nodes
    // 2. Propagate your membership list to every other member (MEMBERLIST)

    // update self heartbeat
    memberNode->heartbeat++;

    // update the entry of self in self memberlist
    memberNode->memberList[0].setheartbeat(memberNode->heartbeat);
    memberNode->memberList[0].settimestamp(par->getcurrtime());

    memberNode->myPos = memberNode->memberList.begin();
    while (memberNode->myPos != memberNode->memberList.end()) {
        if(isEntryInvalid(memberNode, *memberNode->myPos)) {
            int id = memberNode->myPos->getid();
            short port = memberNode->myPos->getport();
            Address address;
            string _address = to_string(id) + ":" + to_string(port);
            address = Address(_address);

            // cout << "found invalid entry with id " << id <<endl;

            if (this->tobedeleted->count(id) == 0) {
                // may have already added to tobedeleted map
                this->tobedeleted->insert(std::make_pair(id, 0));
            }

            // can't remove it at once although we are using tobedeleted map
            // because we still have to send broadcast to it
            // memberNode->myPos = memberNode->memberList.erase(memberNode->myPos);
        }
        ++memberNode->myPos;
    }

    this->updateToBeDeletedMap();

    // construct MEMBERLIST message
    int entry_num = memberNode->memberList.size();
    int currentOffset = 0; 
    // allocate maximum space possibly needed
    size_t memberListMsgSize = sizeof(MessageHdr) + (6 + sizeof(long)) * entry_num;
    MessageHdr *memberListMsg;
    memberListMsg = (MessageHdr *) malloc(memberListMsgSize * sizeof(char));
    memberListMsg->msgType = MEMBERLIST;
    currentOffset += sizeof(int);

    // send / construct two kinds of messages
    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 MEMBERLIST
        memcpy((char *)(memberListMsg) + currentOffset, &address.addr, sizeof(address.addr));
        currentOffset += sizeof(address.addr);
        memcpy((char *)(memberListMsg) + currentOffset, &memberListEntry.heartbeat, sizeof(long));
        currentOffset += sizeof(long);
    }


    // Propagate your membership list; it is sent to even nodes (entries) to be deleted
    broadcast++;
    // decide whether broadcast or unicast
    if (broadcast >= BROADCAST_INTERVAL) {
        // broadcast
        for (MemberListEntry memberListEntry: memberNode->memberList) {
            Address address;
            string _address = to_string(memberListEntry.getid()) + ":" + to_string(memberListEntry.getport());
            address = Address(_address);
            emulNet->ENsend(&memberNode->addr, &address, (char *)memberListMsg, currentOffset);
        }
        broadcast = 0;
    } else {
        // unicast
        int member_num = memberNode->memberList.size();
        int index = rand() % member_num;
        Address address;
        string _address = to_string(memberNode->memberList.at(index).getid()) + ":" + to_string(memberNode->memberList.at(index).getport());
        address = Address(_address);
        emulNet->ENsend(&memberNode->addr, &address, (char *)memberListMsg, currentOffset);
    }

    #ifdef DEBUGLOG
        log->LOG(&memberNode->addr, "sent member list message");
    #endif

    free(memberListMsg);

    return;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x430, %rsp            # imm = 0x430
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x3a0(%rbp)
movq 0x20(%rax), %rcx
movq 0x18(%rcx), %rdx
addq $0x1, %rdx
movq %rdx, 0x18(%rcx)
movq 0x20(%rax), %rdi
addq $0x28, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x74c0
movq %rax, %rdi
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rax
movq 0x18(%rax), %rsi
callq 0x152f0
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rdi
addq $0x28, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x74c0
movq %rax, %rcx
movq -0x3a0(%rbp), %rax
movq %rcx, -0x3a8(%rbp)
movq 0x18(%rax), %rdi
callq 0x15020
movq -0x3a8(%rbp), %rdi
movslq %eax, %rsi
callq 0x15310
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rdi
addq $0x28, %rdi
callq 0x7250
movq %rax, %rcx
movq -0x3a0(%rbp), %rax
movq %rcx, -0x10(%rbp)
movq 0x20(%rax), %rax
movq -0x10(%rbp), %rcx
movq %rcx, 0x40(%rax)
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rcx
addq $0x40, %rcx
movq %rcx, -0x3b0(%rbp)
movq 0x20(%rax), %rdi
addq $0x28, %rdi
callq 0x7280
movq -0x3b0(%rbp), %rdi
movq %rax, -0x18(%rbp)
leaq -0x18(%rbp), %rsi
callq 0x72b0
testb $0x1, %al
jne 0x5121
jmp 0x53d7
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rcx
movq %rcx, -0x3b8(%rbp)
movq 0x20(%rax), %rdi
addq $0x40, %rdi
callq 0x72f0
movq -0x3b8(%rbp), %rdi
movq %rax, %rsi
callq 0x6800
testb $0x1, %al
jne 0x5158
jmp 0x53be
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rdi
addq $0x40, %rdi
callq 0x7590
movq %rax, %rdi
callq 0x15240
movl %eax, %ecx
movq -0x3a0(%rbp), %rax
movl %ecx, -0x1c(%rbp)
movq 0x20(%rax), %rdi
addq $0x40, %rdi
callq 0x7590
movq %rax, %rdi
callq 0x15250
movw %ax, -0x1e(%rbp)
leaq -0x24(%rbp), %rdi
callq 0x6d90
movl -0x1c(%rbp), %esi
leaq -0x88(%rbp), %rdi
movq %rdi, -0x3c0(%rbp)
callq 0x6f90
movq -0x3c0(%rbp), %rsi
leaq 0x22ae3(%rip), %rdx     # 0x27ca9
leaq -0x68(%rbp), %rdi
callq 0x6f40
jmp 0x51d1
movswl -0x1e(%rbp), %esi
leaq -0xb8(%rbp), %rdi
callq 0x6f90
jmp 0x51e3
leaq -0x48(%rbp), %rdi
leaq -0x68(%rbp), %rsi
leaq -0xb8(%rbp), %rdx
callq 0x6e70
jmp 0x51f9
leaq -0xb8(%rbp), %rdi
callq 0x41e0
leaq -0x68(%rbp), %rdi
callq 0x41e0
leaq -0x88(%rbp), %rdi
callq 0x41e0
leaq -0xe0(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x4150
jmp 0x522c
leaq -0xbe(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x70b0
jmp 0x5241
leaq -0x24(%rbp), %rdi
leaq -0xbe(%rbp), %rsi
callq 0x150a0
jmp 0x5253
leaq -0xe0(%rbp), %rdi
callq 0x41e0
movq -0x3a0(%rbp), %rax
movq 0x38(%rax), %rdi
leaq -0x1c(%rbp), %rsi
callq 0x7310
movq %rax, -0x3c8(%rbp)
jmp 0x527c
movq -0x3c8(%rbp), %rax
cmpq $0x0, %rax
jne 0x53a5
movq -0x3a0(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x3d8(%rbp)
movl $0x0, -0xec(%rbp)
leaq -0x1c(%rbp), %rdi
leaq -0xec(%rbp), %rsi
callq 0x75f0
movq %rax, -0x3d0(%rbp)
jmp 0x52c2
movq -0x3d8(%rbp), %rdi
movq -0x3d0(%rbp), %rax
movq %rax, -0xe8(%rbp)
leaq -0xe8(%rbp), %rsi
callq 0x75b0
movb %dl, -0x3e1(%rbp)
movq %rax, -0x3e0(%rbp)
jmp 0x52f2
movb -0x3e1(%rbp), %al
movq -0x3e0(%rbp), %rcx
movq %rcx, -0x100(%rbp)
movb %al, -0xf8(%rbp)
jmp 0x53a5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5360
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5357
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x41e0
leaq -0x68(%rbp), %rdi
callq 0x41e0
leaq -0x88(%rbp), %rdi
callq 0x41e0
jmp 0x5c25
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x53b0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0x41e0
jmp 0x53b0
leaq -0x48(%rbp), %rdi
callq 0x41e0
jmp 0x53be
leaq -0x48(%rbp), %rdi
callq 0x41e0
jmp 0x5c25
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rdi
addq $0x40, %rdi
callq 0x7370
jmp 0x50e1
movq -0x3a0(%rbp), %rdi
callq 0x6860
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rdi
addq $0x28, %rdi
callq 0x7220
movl %eax, -0x104(%rbp)
movl $0x0, -0x108(%rbp)
movslq -0x104(%rbp), %rax
imulq $0xe, %rax, %rax
addq $0x4, %rax
movq %rax, -0x110(%rbp)
movq -0x110(%rbp), %rdi
shlq $0x0, %rdi
callq 0x4440
movq %rax, %rcx
movq -0x3a0(%rbp), %rax
movq %rcx, -0x118(%rbp)
movq -0x118(%rbp), %rcx
movl $0x2, (%rcx)
movslq -0x108(%rbp), %rcx
addq $0x4, %rcx
movl %ecx, -0x108(%rbp)
movq 0x20(%rax), %rax
addq $0x28, %rax
movq %rax, -0x120(%rbp)
movq -0x120(%rbp), %rdi
callq 0x7250
movq %rax, -0x128(%rbp)
movq -0x120(%rbp), %rdi
callq 0x7280
movq %rax, -0x130(%rbp)
leaq -0x128(%rbp), %rdi
leaq -0x130(%rbp), %rsi
callq 0x72b0
testb $0x1, %al
jne 0x54ad
jmp 0x572c
leaq -0x128(%rbp), %rdi
callq 0x72f0
movq %rax, %rsi
leaq -0x148(%rbp), %rdi
callq 0x15180
movq -0x3a0(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x3f0(%rbp)
leaq -0x148(%rbp), %rdi
callq 0x15240
movq -0x3f0(%rbp), %rdi
movl %eax, -0x14c(%rbp)
leaq -0x14c(%rbp), %rsi
callq 0x7310
cmpq $0x0, %rax
je 0x550a
jmp 0x5675
leaq -0x152(%rbp), %rdi
callq 0x6d90
leaq -0x148(%rbp), %rdi
callq 0x15240
movl %eax, %esi
leaq -0x1b8(%rbp), %rdi
movq %rdi, -0x3f8(%rbp)
callq 0x6f90
movq -0x3f8(%rbp), %rsi
leaq 0x22764(%rip), %rdx     # 0x27ca9
leaq -0x198(%rbp), %rdi
callq 0x6f40
jmp 0x5553
leaq -0x148(%rbp), %rdi
callq 0x15250
movw %ax, -0x3fa(%rbp)
jmp 0x5568
movw -0x3fa(%rbp), %ax
movswl %ax, %esi
leaq -0x1d8(%rbp), %rdi
callq 0x6f90
jmp 0x5580
leaq -0x178(%rbp), %rdi
leaq -0x198(%rbp), %rsi
leaq -0x1d8(%rbp), %rdx
callq 0x6e70
jmp 0x559c
leaq -0x1d8(%rbp), %rdi
callq 0x41e0
leaq -0x198(%rbp), %rdi
callq 0x41e0
leaq -0x1b8(%rbp), %rdi
callq 0x41e0
leaq -0x200(%rbp), %rdi
leaq -0x178(%rbp), %rsi
callq 0x4150
jmp 0x55d5
leaq -0x1de(%rbp), %rdi
leaq -0x200(%rbp), %rsi
callq 0x70b0
jmp 0x55ea
leaq -0x152(%rbp), %rdi
leaq -0x1de(%rbp), %rsi
callq 0x150a0
jmp 0x55ff
leaq -0x200(%rbp), %rdi
callq 0x41e0
movq -0x118(%rbp), %rax
movslq -0x108(%rbp), %rcx
movl -0x152(%rbp), %edx
movl %edx, (%rax,%rcx)
movw -0x14e(%rbp), %dx
movw %dx, 0x4(%rax,%rcx)
movslq -0x108(%rbp), %rax
addq $0x6, %rax
movl %eax, -0x108(%rbp)
movq -0x118(%rbp), %rax
movslq -0x108(%rbp), %rcx
movq -0x140(%rbp), %rdx
movq %rdx, (%rax,%rcx)
movslq -0x108(%rbp), %rax
addq $0x8, %rax
movl %eax, -0x108(%rbp)
leaq -0x178(%rbp), %rdi
callq 0x41e0
leaq -0x128(%rbp), %rdi
callq 0x7370
jmp 0x5491
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x56d8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x56cc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x1d8(%rbp), %rdi
callq 0x41e0
leaq -0x198(%rbp), %rdi
callq 0x41e0
leaq -0x1b8(%rbp), %rdi
callq 0x41e0
jmp 0x5c25
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x571b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x200(%rbp), %rdi
callq 0x41e0
leaq -0x178(%rbp), %rdi
callq 0x41e0
jmp 0x5c25
movq -0x3a0(%rbp), %rax
movl 0x30(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x30(%rax)
cmpl $0x4, 0x30(%rax)
jl 0x59c6
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rax
addq $0x28, %rax
movq %rax, -0x208(%rbp)
movq -0x208(%rbp), %rdi
callq 0x7250
movq %rax, -0x210(%rbp)
movq -0x208(%rbp), %rdi
callq 0x7280
movq %rax, -0x218(%rbp)
leaq -0x210(%rbp), %rdi
leaq -0x218(%rbp), %rsi
callq 0x72b0
testb $0x1, %al
jne 0x579e
jmp 0x59b3
leaq -0x210(%rbp), %rdi
callq 0x72f0
movq %rax, %rsi
leaq -0x230(%rbp), %rdi
movq %rdi, -0x410(%rbp)
callq 0x15180
leaq -0x236(%rbp), %rdi
callq 0x6d90
movq -0x410(%rbp), %rdi
callq 0x15240
movl %eax, %esi
leaq -0x298(%rbp), %rdi
movq %rdi, -0x408(%rbp)
callq 0x6f90
movq -0x408(%rbp), %rsi
leaq 0x224ae(%rip), %rdx     # 0x27ca9
leaq -0x278(%rbp), %rdi
callq 0x6f40
jmp 0x5809
leaq -0x230(%rbp), %rdi
callq 0x15250
movw %ax, -0x412(%rbp)
jmp 0x581e
movw -0x412(%rbp), %ax
movswl %ax, %esi
leaq -0x2b8(%rbp), %rdi
callq 0x6f90
jmp 0x5836
leaq -0x258(%rbp), %rdi
leaq -0x278(%rbp), %rsi
leaq -0x2b8(%rbp), %rdx
callq 0x6e70
jmp 0x5852
leaq -0x2b8(%rbp), %rdi
callq 0x41e0
leaq -0x278(%rbp), %rdi
callq 0x41e0
leaq -0x298(%rbp), %rdi
callq 0x41e0
leaq -0x2e0(%rbp), %rdi
leaq -0x258(%rbp), %rsi
callq 0x4150
jmp 0x588b
leaq -0x2be(%rbp), %rdi
leaq -0x2e0(%rbp), %rsi
callq 0x70b0
jmp 0x58a0
leaq -0x236(%rbp), %rdi
leaq -0x2be(%rbp), %rsi
callq 0x150a0
jmp 0x58b5
leaq -0x2e0(%rbp), %rdi
callq 0x41e0
movq -0x3a0(%rbp), %rax
movq 0x8(%rax), %rdi
movq 0x20(%rax), %rsi
addq $0x8, %rsi
movq -0x118(%rbp), %rcx
movl -0x108(%rbp), %r8d
leaq -0x236(%rbp), %rdx
callq 0xac80
jmp 0x58f0
leaq -0x258(%rbp), %rdi
callq 0x41e0
leaq -0x210(%rbp), %rdi
callq 0x7370
jmp 0x5782
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x595f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5953
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x2b8(%rbp), %rdi
callq 0x41e0
leaq -0x278(%rbp), %rdi
callq 0x41e0
leaq -0x298(%rbp), %rdi
callq 0x41e0
jmp 0x5c25
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x59a2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x2e0(%rbp), %rdi
callq 0x41e0
leaq -0x258(%rbp), %rdi
callq 0x41e0
jmp 0x5c25
movq -0x3a0(%rbp), %rax
movl $0x0, 0x30(%rax)
jmp 0x5c10
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rdi
addq $0x28, %rdi
callq 0x7220
movl %eax, -0x2e4(%rbp)
callq 0x40e0
movl -0x2e4(%rbp), %ecx
cltd
idivl %ecx
movl %edx, -0x2e8(%rbp)
leaq -0x2ee(%rbp), %rdi
callq 0x6d90
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rdi
addq $0x28, %rdi
movslq -0x2e8(%rbp), %rsi
callq 0x7620
movq %rax, %rdi
callq 0x15240
movl %eax, %esi
leaq -0x350(%rbp), %rdi
movq %rdi, -0x420(%rbp)
callq 0x6f90
movq -0x420(%rbp), %rsi
leaq 0x22263(%rip), %rdx     # 0x27ca9
leaq -0x330(%rbp), %rdi
callq 0x6f40
jmp 0x5a54
movq -0x3a0(%rbp), %rax
movq 0x20(%rax), %rdi
addq $0x28, %rdi
movslq -0x2e8(%rbp), %rsi
callq 0x7620
movq %rax, -0x428(%rbp)
jmp 0x5a78
movq -0x428(%rbp), %rdi
callq 0x15250
movw %ax, -0x42a(%rbp)
jmp 0x5a8d
movw -0x42a(%rbp), %ax
movswl %ax, %esi
leaq -0x370(%rbp), %rdi
callq 0x6f90
jmp 0x5aa5
leaq -0x310(%rbp), %rdi
leaq -0x330(%rbp), %rsi
leaq -0x370(%rbp), %rdx
callq 0x6e70
jmp 0x5ac1
leaq -0x370(%rbp), %rdi
callq 0x41e0
leaq -0x330(%rbp), %rdi
callq 0x41e0
leaq -0x350(%rbp), %rdi
callq 0x41e0
leaq -0x398(%rbp), %rdi
leaq -0x310(%rbp), %rsi
callq 0x4150
jmp 0x5afa
leaq -0x376(%rbp), %rdi
leaq -0x398(%rbp), %rsi
callq 0x70b0
jmp 0x5b0f
leaq -0x2ee(%rbp), %rdi
leaq -0x376(%rbp), %rsi
callq 0x150a0
jmp 0x5b24
leaq -0x398(%rbp), %rdi
callq 0x41e0
movq -0x3a0(%rbp), %rax
movq 0x8(%rax), %rdi
movq 0x20(%rax), %rsi
addq $0x8, %rsi
movq -0x118(%rbp), %rcx
movl -0x108(%rbp), %r8d
leaq -0x2ee(%rbp), %rdx
callq 0xac80
jmp 0x5b5f
leaq -0x310(%rbp), %rdi
callq 0x41e0
jmp 0x5c10
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5bc2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5bb6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x370(%rbp), %rdi
callq 0x41e0
leaq -0x330(%rbp), %rdi
callq 0x41e0
leaq -0x350(%rbp), %rdi
callq 0x41e0
jmp 0x5c25
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x5c02
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x398(%rbp), %rdi
callq 0x41e0
leaq -0x310(%rbp), %rdi
callq 0x41e0
jmp 0x5c25
movq -0x118(%rbp), %rdi
callq 0x43e0
addq $0x430, %rsp            # imm = 0x430
popq %rbp
retq
movq -0x90(%rbp), %rdi
callq 0x4550
nopw %cs:(%rax,%rax)