// File: tonymuu[P]distributed-kv-store/Application.cpp
// Function: Application::mp2Run()
void Application::mp2Run() {
	int i;

	// For all the nodes in the system
	for( i = 0; i <= par->EN_GPSZ-1; i++) {

		/*
		 * 1) Update the ring
		 * 2) Receive messages from the network and queue them in the KV store queue
		 */
		if ( par->getcurrtime() > (int)(par->STEP_RATE*i) && !mp2[i]->getMemberNode()->bFailed ) {
			if ( mp2[i]->getMemberNode()->inited && mp2[i]->getMemberNode()->inGroup ) {
				// Step 1
				mp2[i]->updateRing();
			}
			// Step 2
			mp2[i]->recvLoop();
		}
	}

	/**
	 * Handle messages from the queue and update the DHT
	 */
	for ( i = par->EN_GPSZ-1; i >= 0; i-- ) {
		if ( par->getcurrtime() > (int)(par->STEP_RATE*i) && !mp2[i]->getMemberNode()->bFailed ) {
			mp2[i]->checkMessages();
		}
	}

	/**
	 * Insert a set of test key value pairs into the system
	 */
	if ( par->getcurrtime() == INSERT_TIME ) {
		insertTestKVPairs();
	}

	/**
	 * Test CRUD operations
	 */
	if ( par->getcurrtime() >= TEST_TIME ) {
		/**************
		 * CREATE TEST
		 **************/
		/**
		 * TEST 1: Checks if there are RF * NUMBER_OF_INSERTS CREATE SUCCESS message are in the log
		 *
		 */
		if ( par->getcurrtime() == TEST_TIME && CREATE_TEST == par->CRUDTEST ) {
			cout<<endl<<"Doing create test at time: "<<par->getcurrtime()<<endl;
		} // End of create test

		/***************
		 * DELETE TESTS
		 ***************/
		/**
		 * TEST 1: NUMBER_OF_INSERTS/2 Key Value pair are deleted.
		 * 		   Check whether RF * NUMBER_OF_INSERTS/2 DELETE SUCCESS message are in the log
		 * TEST 2: Delete a non-existent key. Check for a DELETE FAIL message in the lgo
		 *
		 */
		else if ( par->getcurrtime() == TEST_TIME && DELETE_TEST == par->CRUDTEST ) {
			deleteTest();
		} // End of delete test

		/*************
		 * READ TESTS
		 *************/
		/**
		 * TEST 1: Read a key. Check for correct value being read in quorum of replicas
		 *
		 * Wait for some time after TEST 1
		 *
		 * TEST 2: Fail a single replica of a key. Check for correct value of the key
		 * 		   being read in quorum of replicas
		 *
		 * Wait for STABILIZE_TIME after TEST 2 (stabilization protocol should ensure at least
		 * 3 replicas for all keys at all times)
		 *
		 * TEST 3 part 1: Fail two replicas of a key. Read the key and check for READ FAIL message in the log.
		 * 				  READ should fail because quorum replicas of the key are not up
		 *
		 * Wait for another STABILIZE_TIME after TEST 3 part 1 (stabilization protocol should ensure at least
		 * 3 replicas for all keys at all times)
		 *
		 * TEST 3 part 2: Read the same key as TEST 3 part 1. Check for correct value of the key
		 * 		  		  being read in quorum of replicas
		 *
		 * Wait for some time after TEST 3 part 2
		 *
		 * TEST 4: Fail a non-replica. Check for correct value of the key
		 * 		   being read in quorum of replicas
		 *
		 * TEST 5: Read a non-existent key. Check for a READ FAIL message in the log
		 *
		 */
		else if ( par->getcurrtime() >= TEST_TIME && READ_TEST == par->CRUDTEST ) {
			readTest();
		} // end of read test

		/***************
		 * UPDATE TESTS
		 ***************/
		/**
		 * TEST 1: Update a key. Check for correct new value being updated in quorum of replicas
		 *
		 * Wait for some time after TEST 1
		 *
		 * TEST 2: Fail a single replica of a key. Update the key. Check for correct new value of the key
		 * 		   being updated in quorum of replicas
		 *
		 * Wait for STABILIZE_TIME after TEST 2 (stabilization protocol should ensure at least
		 * 3 replicas for all keys at all times)
		 *
		 * TEST 3 part 1: Fail two replicas of a key. Update the key and check for READ FAIL message in the log
		 * 				  UPDATE should fail because quorum replicas of the key are not up
		 *
		 * Wait for another STABILIZE_TIME after TEST 3 part 1 (stabilization protocol should ensure at least
		 * 3 replicas for all keys at all times)
		 *
		 * TEST 3 part 2: Update the same key as TEST 3 part 1. Check for correct new value of the key
		 * 		   		  being update in quorum of replicas
		 *
		 * Wait for some time after TEST 3 part 2
		 *
		 * TEST 4: Fail a non-replica. Check for correct new value of the key
		 * 		   being updated in quorum of replicas
		 *
		 * TEST 5: Update a non-existent key. Check for a UPDATE FAIL message in the log
		 *
		 */
		else if ( par->getcurrtime() >= TEST_TIME && UPDATE_TEST == par->CRUDTEST ) {
			updateTest();
		} // End of update test

	} // end of if ( par->getcurrtime == TEST_TIME)
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x20, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x18(%rbp)
movl $0x0, -0xc(%rbp)
movq -0x18(%rbp), %rcx
movl -0xc(%rbp), %eax
movq 0x58(%rcx), %rcx
movl 0x18(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jg 0x1043a
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x18c60
movq -0x18(%rbp), %rcx
movq 0x58(%rcx), %rcx
movsd 0x10(%rcx), %xmm0
cvtsi2sdl -0xc(%rbp), %xmm1
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
cmpl %ecx, %eax
jle 0x1042a
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x14b10
testb $0x1, 0x10(%rax)
jne 0x1042a
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x14b10
testb $0x1, 0xe(%rax)
je 0x10415
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x14b10
testb $0x1, 0xf(%rax)
je 0x10415
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x1de00
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x21860
jmp 0x1042c
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc(%rbp)
jmp 0x1036b
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rax
movl 0x18(%rax), %eax
subl $0x1, %eax
movl %eax, -0xc(%rbp)
cmpl $0x0, -0xc(%rbp)
jl 0x104b9
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x18c60
movq -0x18(%rbp), %rcx
movq 0x58(%rcx), %rcx
movsd 0x10(%rcx), %xmm0
cvtsi2sdl -0xc(%rbp), %xmm1
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
cmpl %ecx, %eax
jle 0x104ac
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x14b10
testb $0x1, 0x10(%rax)
jne 0x104ac
movq -0x18(%rbp), %rax
movq 0x48(%rax), %rax
movslq -0xc(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x203d0
jmp 0x104ae
movl -0xc(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0xc(%rbp)
jmp 0x1044b
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x18c60
cmpl $0x64, %eax
jne 0x104d4
movq -0x18(%rbp), %rdi
callq 0x10610
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x18c60
cmpl $0x96, %eax
jl 0x105fd
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x18c60
cmpl $0x96, %eax
jne 0x10564
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rcx
xorl %eax, %eax
cmpl 0x34(%rcx), %eax
jne 0x10564
movq 0x2daaa(%rip), %rdi     # 0x3dfc0
movq 0x2da8b(%rip), %rsi     # 0x3dfa8
callq 0x4390
movq %rax, %rdi
leaq 0x1be14(%rip), %rsi     # 0x2c340
callq 0x4330
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, -0x20(%rbp)
movq 0x58(%rax), %rdi
callq 0x18c60
movq -0x20(%rbp), %rdi
movl %eax, %esi
callq 0x45a0
movq %rax, %rdi
movq 0x2da4e(%rip), %rsi     # 0x3dfa8
callq 0x4390
jmp 0x105fb
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x18c60
cmpl $0x96, %eax
jne 0x10595
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rcx
movl $0x3, %eax
cmpl 0x34(%rcx), %eax
jne 0x10595
movq -0x18(%rbp), %rdi
callq 0x10840
jmp 0x105f9
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x18c60
cmpl $0x96, %eax
jl 0x105c6
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rcx
movl $0x1, %eax
cmpl 0x34(%rcx), %eax
jne 0x105c6
movq -0x18(%rbp), %rdi
callq 0x10c40
jmp 0x105f7
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rdi
callq 0x18c60
cmpl $0x96, %eax
jl 0x105f5
movq -0x18(%rbp), %rax
movq 0x58(%rax), %rcx
movl $0x2, %eax
cmpl 0x34(%rcx), %eax
jne 0x105f5
movq -0x18(%rbp), %rdi
callq 0x128a0
jmp 0x105f7
jmp 0x105f9
jmp 0x105fb
jmp 0x105fd
addq $0x20, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)