// File: /workspace/github_c_makefile_star2_O3/sharpyfox[P]citrusleaf-client/src/citrusleaf.c
// Function: do_the_full_monte
static int
do_the_full_monte(cl_cluster *asc, int info1, int info2, int info3, const char *ns, const char *set, const cl_object *key,
	const cf_digest *digest, cl_bin **values, cl_operator operator, cl_operation **operations, int *n_values, 
	uint32_t *cl_gen, const cl_write_parameters *cl_w_p, uint64_t *trid, char **setname_r)
{
	int rv = -1;
#ifdef DEBUG_HISTOGRAM	
    uint64_t start_time = cf_getms();
#endif	
	

	uint8_t		rd_stack_buf[STACK_BUF_SZ];	
	uint8_t		*rd_buf = rd_stack_buf;
	size_t		rd_buf_sz = 0;
    
	uint8_t		wr_stack_buf[STACK_BUF_SZ];
	uint8_t		*wr_buf = wr_stack_buf;
	size_t		wr_buf_sz = sizeof(wr_stack_buf);

	as_msg 		msg;
    
    uint        progress_timeout_ms;
	uint64_t deadline_ms;
	cl_cluster_node *node = 0;

	int fd = -1;

//	if( *values ){
//		dump_values(*values, null, *n_values);
//	}else if( *operations ){
//		dump_values(null, *operations, *n_values);
//	}	
	 
	/* 
	 * Check if the current process is the one which spawned the background threads (tend,batch).
	 * If it is not, it means that this process is a forked child process. The threads would not
	 * be running in this case. So, spawn the background threads and remember that this process
	 * has started the threads.
	 */
	if(g_init_pid != getpid()) {
		cf_atomic32_set(&batch_initialized,0);
		g_clust_initialized = 0;
		citrusleaf_init();
	}

	cf_digest d_ret;	
	if (n_values && ( values || operations) ){
		if (cl_compile(info1, info2, info3, ns, set, key, digest, values?*values:NULL, operator, operations?*operations:NULL,
				*n_values , &wr_buf, &wr_buf_sz, cl_w_p, &d_ret, *trid, NULL)) {
			return(rv);
		}
	}else{
		if (cl_compile(info1, info2, info3, ns, set, key, digest, 0, 0, 0, 0, &wr_buf, &wr_buf_sz, cl_w_p, &d_ret, *trid, NULL)) {
			return(rv);
		}
	}	

#ifdef DEBUG_VERBOSE
	dump_buf("sending request to cluster:", wr_buf, wr_buf_sz);
#endif	

	int try = 0;

#ifdef DEBUG_TIME
	uint64_t before_write_time = 0;
	uint64_t after_write_time = 0;
	uint64_t before_read_header_time = 0;
	uint64_t after_read_header_time = 0;
	uint64_t before_read_body_time = 0;
    uint64_t after_read_body_time = 0;	
#endif

    deadline_ms = 0;
    progress_timeout_ms = 0;
    if (cl_w_p && cl_w_p->timeout_ms) {
    	// policy: if asking for a long timeout, give enough time to try two servers
    	if (cl_w_p->timeout_ms > 700) {
			deadline_ms = cf_getms() + cl_w_p->timeout_ms;
			progress_timeout_ms = cl_w_p->timeout_ms / 2;
		}
		else {
			deadline_ms = cf_getms() + cl_w_p->timeout_ms;
			progress_timeout_ms = cl_w_p->timeout_ms;
		}
#ifdef DEBUG_VERBOSE        
        cf_debug("transaction has deadline: in %d deadlinems %"PRIu64" progress %d",
        	(int)cl_w_p->timeout_ms,deadline_ms,progress_timeout_ms);
#endif        
    }
    else {
        progress_timeout_ms = DEFAULT_PROGRESS_TIMEOUT;
    }
	
	// retry request based on the write_policy
	do {

#ifdef DEBUG_TIME
		before_write_time = 0;
		after_write_time = 0;
		before_read_header_time = 0;
		after_read_header_time = 0;
		before_read_body_time = 0;
		after_read_body_time = 0;
#endif
        
#ifdef DEBUG		
		if (try > 0)
			cf_debug("request retrying try %d tid %zu", try, (uint64_t)pthread_self());
#endif        
		try++;
		
		// Get an FD from a cluster
		node = cl_cluster_node_get(asc, ns, &d_ret, info2 & CL_MSG_INFO2_WRITE ? true : false);
		if (!node) {
#ifdef DEBUG
			cf_debug("warning: no healthy nodes in cluster, retrying");
#endif
			usleep(10000);
			goto Retry;
		}
		fd = cl_cluster_node_fd_get(node, false, asc->nbconnect);
		if (fd == -1) {
#ifdef DEBUG			
			cf_debug("warning: node %s has no file descriptors, retrying transaction (tid %zu)", node->name, (uint64_t)pthread_self());
#endif			
			usleep(1000);
			goto Retry;
		}

#ifdef DEBUG_VERBOSE
		cf_debug("node %s fd %d", node->name, fd);
#endif		
		
		// Hate special cases, but we have to clear the verify bit on delete verify
		if ( (info2 & CL_MSG_INFO2_DELETE) && (info1 & CL_MSG_INFO1_VERIFY))
		{
			as_msg *msgp = (as_msg *)wr_buf;
			msgp->m.info1 &= ~CL_MSG_INFO1_VERIFY;
		}
		
		// send it to the cluster - non blocking socket, but we're blocking

#ifdef DEBUG_TIME
        before_write_time = cf_getms();
#endif
		rv = cf_socket_write_timeout(fd, wr_buf, wr_buf_sz, deadline_ms, progress_timeout_ms);
#ifdef DEBUG_TIME
        after_write_time = cf_getms();
#endif

		if (rv != 0) {
#ifdef DEBUG			
			cf_debug("Citrusleaf: write timeout or error when writing header to server - %d fd %d errno %d (tid %zu)",rv,fd,errno,(uint64_t)pthread_self());
#endif
#ifdef DEBUG_TIME
            debug_printf(before_write_time, after_write_time, before_read_header_time, after_read_header_time, before_read_body_time, after_read_body_time,
                         deadline_ms, progress_timeout_ms);           	
#endif

			cl_cluster_node_dun(node, rv == ETIMEDOUT ? NODE_DUN_TIMEOUT : NODE_DUN_NET_ERR);
			goto Retry;
		}

#ifdef DEBUG		
		memset(&msg, 0, sizeof(as_msg));
#endif
#ifdef DEBUG_TIME
        before_read_header_time = cf_getms();
#endif		
		
		// Now turn around and read into this fine cl_msg, which is the short header
		rv = cf_socket_read_timeout(fd, (uint8_t *) &msg, sizeof(as_msg), deadline_ms, progress_timeout_ms);
#ifdef DEBUG_TIME
        after_read_header_time = cf_getms();
#endif

		if (rv) {

#ifdef DEBUG            
			cf_debug("Citrusleaf: error when reading header from server - rv %d fd %d", rv, fd);
#endif
#ifdef DEBUG_TIME
            debug_printf(before_write_time, after_write_time, before_read_header_time, after_read_header_time, before_read_body_time, after_read_body_time,
                         deadline_ms, progress_timeout_ms);           	
#endif            

			cl_cluster_node_dun(node, rv == ETIMEDOUT ? NODE_DUN_TIMEOUT : NODE_DUN_NET_ERR);
			goto Retry;
	
		}
#ifdef DEBUG_VERBOSE
		dump_buf("read header from cluster", (uint8_t *) &msg, sizeof(cl_msg));
#endif	
		cl_proto_swap(&msg.proto);
		cl_msg_swap_header(&msg.m);

		if (/*(info1 & CL_MSG_INFO1_READ) &&*/ cl_gen) {
			*cl_gen = msg.m.generation;
		}
	
		
		// second read for the remainder of the message - expect this to cover everything requested
		// if there's no error
		rd_buf_sz =  msg.proto.sz  - msg.m.header_sz;
		if (rd_buf_sz > 0) {
			if (rd_buf_sz > sizeof(rd_stack_buf)) {
				rd_buf = malloc(rd_buf_sz);
				if (!rd_buf) {
                    cf_error("malloc fail: trying %zu", rd_buf_sz);
                    rv = -1; 
                    goto Error; 
                }
			}
#ifdef DEBUG_TIME
        before_read_body_time = cf_getms();
#endif            
			rv = cf_socket_read_timeout(fd, rd_buf, rd_buf_sz, deadline_ms, progress_timeout_ms);
#ifdef DEBUG_TIME
        after_read_body_time = cf_getms();
#endif
			if (rv) {
				if (rd_buf != rd_stack_buf) { free(rd_buf); }
                rd_buf = 0;
                
#ifdef DEBUG            
                cf_debug("Citrusleaf: error when reading from server - rv %d fd %d", rv, fd);
#endif
#ifdef DEBUG_TIME
				debug_printf(before_write_time, after_write_time, before_read_header_time, after_read_header_time, before_read_body_time, after_read_body_time, 
                             deadline_ms, progress_timeout_ms);           	
#endif

				cl_cluster_node_dun(node, rv == ETIMEDOUT ? NODE_DUN_TIMEOUT : NODE_DUN_NET_ERR);
				goto Retry;
			}

#ifdef DEBUG_VERBOSE
			dump_buf("read body from cluster", rd_buf, rd_buf_sz);
#endif	
			
			// todo: check error!!?!?!
		}

        goto Ok;
		
Retry:		

		if (fd != -1) {
			close(fd);
			fd = -1;
		}

		if (node) {
            cl_cluster_node_put(node); 
            node = 0; 
        }

        if (deadline_ms && (deadline_ms < cf_getms() ) ) {
#ifdef DEBUG            
            cf_debug("out of luck out of time : deadline %"PRIu64" now %"PRIu64,
                deadline_ms, cf_getms());
#endif            
            rv = CITRUSLEAF_FAIL_TIMEOUT;
            goto Error;
        }
		
	} while ( (cl_w_p == 0) || (cl_w_p->w_pol == CL_WRITE_RETRY) );
	
Error:	
	
#ifdef DEBUG	
	cf_debug("exiting with failure: wpol %d timeleft %d rv %d",
		(int)(cl_w_p ? cl_w_p->w_pol : 0),
		(int)(deadline_ms - cf_getms() ), rv );
#endif	

    if (fd != -1)   close(fd);

	if (wr_buf != wr_stack_buf)		free(wr_buf);
	if (rd_buf && (rd_buf != rd_stack_buf))		free(rd_buf);
	
	return(rv);
    
Ok:    

	cl_cluster_node_ok(node);
    cl_cluster_node_fd_put(node, fd, false);
	cl_cluster_node_put(node);
   
	if (wr_buf != wr_stack_buf)		free(wr_buf);

	if (rd_buf) {
		if (0 != cl_parse(&msg.m, rd_buf, rd_buf_sz, values, operations, n_values, trid, setname_r)) {
			rv = CITRUSLEAF_FAIL_UNKNOWN;
		}
		else {
			rv = msg.m.result_code;
			// special case: if there was a retry, and we're doing a delete, force 'not found'
			// errors to 'ok' because the first delete might have succeeded
			if ((try > 1) && (rv == 2) && (info2 & CL_MSG_INFO2_DELETE)) {
//				dump_key("delete: stomping error code on retransmitted delete", key);
				rv = 0;
			}
		}
    }
    else {
        rv = CITRUSLEAF_FAIL_UNKNOWN;
    }    
	if (rd_buf && (rd_buf != rd_stack_buf))		free(rd_buf);
	
	if (rv == 0 && (values || operations) && n_values) {
		for (int i=0;i<*n_values;i++) {
			cl_bin *bin = values? &(*values)[i] : &((*operations)[i].bin);
//			if ( bin->object.type == CL_NULL ) {
//				// raise(SIGINT);
//			}
		}
	}
#ifdef DEBUG_HISTOGRAM	
    cf_histogram_insert_data_point(cf_hist, start_time);
#endif	
#ifdef DEBUG_VERBOSE
	if (rv != 0) {
		cf_debug("exiting OK clause with failure: wpol %d timeleft %d rv %d",
			(int)(cl_w_p ? cl_w_p->w_pol : 0),
			(int)(deadline_ms - cf_getms() ), rv );
	}
#endif	

	return(rv);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x80a8, %rsp           # imm = 0x80A8
leaq 0x40a0(%rsp), %rax
movq 0x8108(%rsp), %r15
movq %r9, %rbx
movq %r8, %r13
movl %ecx, %ebp
movl %edx, (%rsp)
movl %esi, 0x8(%rsp)
movq %rdi, 0x20(%rsp)
movq $0x4000, 0x30(%rsp)     # imm = 0x4000
movq %rax, 0x18(%rsp)
leaq 0x12c5d(%rip), %rax     # 0x183a4
movl (%rax), %r14d
callq 0x23a0
cmpl %eax, %r14d
je 0x576d
leaq 0x12cd5(%rip), %rax     # 0x18430
xorl %ecx, %ecx
movl %ecx, (%rax)
leaq 0x12c42(%rip), %rax     # 0x183a8
movl %ecx, (%rax)
callq 0x6982
movq 0x8120(%rsp), %r12
movq 0x8100(%rsp), %rdx
movq 0x80f0(%rsp), %rsi
movq 0x80e8(%rsp), %rax
movq 0x80e0(%rsp), %r9
testq %r15, %r15
je 0x57ac
movq %rsi, %rcx
orq %rdx, %rcx
je 0x57ac
testq %rsi, %rsi
je 0x57f2
movq (%rsi), %r10
jmp 0x57f5
subq $0x8, %rsp
movl 0x10(%rsp), %edi
movl 0x8(%rsp), %esi
xorl %r10d, %r10d
movl %ebp, %edx
movq %r13, %rcx
movq %rbx, %r8
leaq 0x94(%rsp), %r11
leaq 0x38(%rsp), %r14
leaq 0x20(%rsp), %r15
pushq %r10
pushq (%r12)
pushq %r11
movq 0x8138(%rsp), %rbx
pushq %rbx
pushq %r14
pushq %r15
pushq %r10
pushq %r10
pushq %r10
jmp 0x5851
xorl %r10d, %r10d
movq %r13, %rcx
testq %rdx, %rdx
je 0x5802
movq (%rdx), %r14
jmp 0x5805
xorl %r14d, %r14d
movl (%r15), %r15d
subq $0x8, %rsp
movl 0x10(%rsp), %edi
movl 0x8(%rsp), %esi
leaq 0x38(%rsp), %r13
movl %ebp, %edx
movq %rbx, %r8
leaq 0x94(%rsp), %r11
pushq $0x0
pushq (%r12)
pushq %r11
movq 0x8138(%rsp), %rbx
pushq %rbx
pushq %r13
movq %rcx, %r13
leaq 0x48(%rsp), %r11
pushq %r11
pushq %r15
pushq %r14
movl 0x8140(%rsp), %r11d
pushq %r11
pushq %r10
pushq %rax
callq 0x4b3f
addq $0x60, %rsp
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
testl %eax, %eax
jne 0x5bb7
movq %r13, %r15
movl $0x32, %ecx
testq %rbx, %rbx
movq $0x0, 0x28(%rsp)
je 0x58e2
movl 0xc(%rbx), %eax
movl (%rsp), %r13d
movq 0x20(%rsp), %r12
movl 0x8(%rsp), %ebp
movq %rbx, %r14
testl %eax, %eax
je 0x58ef
leaq 0xa0(%rsp), %rbx
movl $0x1, %edi
cmpl $0x2bd, %eax            # imm = 0x2BD
movq %rbx, %rsi
jl 0x58f3
callq 0x2230
movabsq $0x431bde82d7b634db, %rax # imm = 0x431BDE82D7B634DB
mulq 0x8(%rbx)
movslq 0xc(%r14), %rax
imulq $0x3e8, (%rbx), %rbx    # imm = 0x3E8
movl %eax, %ecx
shrq $0x12, %rdx
shrl $0x1f, %ecx
addq %rdx, %rbx
addl %eax, %ecx
addq %rax, %rbx
sarl %ecx
jmp 0x591b
movl (%rsp), %r13d
movq 0x20(%rsp), %r12
movl 0x8(%rsp), %ebp
xorl %ebx, %ebx
jmp 0x591b
callq 0x2230
movabsq $0x431bde82d7b634db, %rax # imm = 0x431BDE82D7B634DB
movslq 0xc(%r14), %rcx
mulq 0x8(%rbx)
imulq $0x3e8, (%rbx), %rbx    # imm = 0x3E8
shrq $0x12, %rdx
addq %rdx, %rbx
addq %rcx, %rbx
movl %r13d, %eax
movq %rcx, 0x50(%rsp)
movq %r15, %r14
movq %r15, 0x40(%rsp)
movq %rbx, 0x8(%rsp)
andl $0x2, %eax
sete %dl
testb $0x8, %bpl
movl %eax, 0x3c(%rsp)
leaq 0xa0(%rsp), %rax
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
sete %cl
andl $0x1, %r13d
movq %rax, 0x10(%rsp)
orb %dl, %cl
movl %r13d, (%rsp)
movb %cl, 0x7(%rsp)
movq %r12, %rdi
movq %r14, %rsi
leaq 0x8c(%rsp), %rdx
movl %r13d, %ecx
callq 0x7daf
testq %rax, %rax
je 0x59d3
movzbl 0x15(%r12), %edx
movq %rax, %rdi
xorl %esi, %esi
movq %rax, %r15
callq 0x83f3
cmpl $-0x1, %eax
je 0x59df
movq 0x18(%rsp), %rbp
cmpb $0x0, 0x7(%rsp)
movl %eax, %r12d
jne 0x59a7
andb $-0x9, 0x9(%rbp)
movq 0x8(%rsp), %rbx
movq 0x50(%rsp), %r13
movq 0x30(%rsp), %rdx
movl %r12d, %edi
movq %rbp, %rsi
movq %rbx, %rcx
movl %r13d, %r8d
callq 0xdae9
testl %eax, %eax
je 0x59eb
movl %eax, %ecx
movl (%rsp), %r13d
jmp 0x5a1e
movl $0x2710, %edi           # imm = 0x2710
callq 0x2360
jmp 0x5a4c
movl $0x3e8, %edi            # imm = 0x3E8
callq 0x2360
jmp 0x5a3f
movq %rbp, 0x48(%rsp)
leaq 0x5a(%rsp), %rbp
movl $0x1e, %edx
movl %r12d, %edi
movq %rbx, %rcx
movl %r13d, %r8d
movq %rbp, %rsi
callq 0xd4c5
testl %eax, %eax
je 0x5ab4
movl (%rsp), %r13d
movq 0x8(%rsp), %rbx
movl %eax, %ecx
movl %ecx, %ebp
cmpl $0x6e, %ecx
movl $0x1, %esi
je 0x5a2f
movl $0x32, %esi
movq %r15, %rdi
callq 0x822c
movl %r12d, %edi
callq 0x2550
movq %r15, %rdi
callq 0x8227
movq 0x20(%rsp), %r12
movq 0x8118(%rsp), %r15
testq %rbx, %rbx
je 0x5a93
movl $0x1, %edi
leaq 0x78(%rsp), %rsi
callq 0x2230
movabsq $0x431bde82d7b634db, %rax # imm = 0x431BDE82D7B634DB
mulq 0x80(%rsp)
imulq $0x3e8, 0x78(%rsp), %rax # imm = 0x3E8
shrq $0x12, %rdx
addq %rdx, %rax
cmpq %rax, %rbx
jb 0x5b6d
testq %r15, %r15
je 0x5aa3
cmpl $0x2, 0x14(%r15)
jne 0x5b75
movq 0x28(%rsp), %rax
decl %eax
movq %rax, 0x28(%rsp)
jmp 0x5961
movq %rbp, %rdi
callq 0xc8a8
leaq 0x62(%rsp), %rdi
callq 0xc8c5
movq 0x8110(%rsp), %rcx
testq %rcx, %rcx
je 0x5ad9
movl 0x68(%rsp), %eax
movl %eax, (%rcx)
movzwl 0x60(%rsp), %r13d
movl 0x5c(%rsp), %eax
movq 0x8(%rsp), %rbx
shlq $0x20, %r13
orq %rax, %r13
movzbl 0x62(%rsp), %eax
subq %rax, %r13
je 0x5bcc
cmpq $0x4001, %r13           # imm = 0x4001
jb 0x5b1c
movq %r13, %rdi
callq 0x22e0
testq %rax, %rax
movq %rax, 0x10(%rsp)
je 0x5c98
movq 0x10(%rsp), %rbp
movl %r12d, %edi
movq %r13, %rdx
movq %rbx, %rcx
movq 0x50(%rsp), %r8
movq %rbp, %rsi
callq 0xd4c5
testl %eax, %eax
je 0x5bd3
leaq 0xa0(%rsp), %rdx
movl %eax, %ecx
cmpq %rdx, %rbp
je 0x5b5a
movq %rbp, %rdi
movl %ecx, %ebp
callq 0x22c0
movl %ebp, %ecx
movq 0x40(%rsp), %r14
movq $0x0, 0x10(%rsp)
jmp 0x59cd
movl $0xfffffffe, %r14d      # imm = 0xFFFFFFFE
jmp 0x5b78
movl %ebp, %r14d
movq 0x18(%rsp), %rbx
leaq 0x40a0(%rsp), %rax
cmpq %rax, %rbx
je 0x5b92
movq %rbx, %rdi
callq 0x22c0
movq 0x10(%rsp), %rbx
leaq 0xa0(%rsp), %rcx
testq %rbx, %rbx
setne %al
cmpq %rcx, %rbx
setne %cl
testb %cl, %al
je 0x5bb7
movq %rbx, %rdi
callq 0x22c0
movl %r14d, %eax
addq $0x80a8, %rsp           # imm = 0x80A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x48(%rsp), %rbx
jmp 0x5bd8
movq 0x18(%rsp), %rbx
movq %r15, %rdi
callq 0x8247
movq %r15, %rdi
movl %r12d, %esi
xorl %edx, %edx
callq 0x844f
movq %r15, %rdi
callq 0x8227
leaq 0x40a0(%rsp), %rax
cmpq %rax, %rbx
je 0x5c0a
movq %rbx, %rdi
callq 0x22c0
movq 0x10(%rsp), %rbx
movq 0x8108(%rsp), %r9
testq %rbx, %rbx
je 0x5c8d
movq 0x80f0(%rsp), %rcx
movq 0x8100(%rsp), %r8
leaq 0x62(%rsp), %rdi
movq %rbx, %rsi
movq %r13, %rdx
pushq 0x8128(%rsp)
pushq 0x8128(%rsp)
callq 0x535d
addq $0x10, %rsp
movl $0x1, %r14d
testl %eax, %eax
jne 0x5c77
movb 0x67(%rsp), %al
movl 0x3c(%rsp), %r14d
movzbl %al, %eax
xorl $0x2, %r14d
cmpb $0x2, %al
cmovnel %eax, %r14d
cmpl $0x0, 0x28(%rsp)
cmovel %eax, %r14d
leaq 0xa0(%rsp), %rax
cmpq %rax, %rbx
jne 0x5baf
jmp 0x5bb7
movl $0x1, %r14d
jmp 0x5bb7
leaq 0x10629(%rip), %rax     # 0x162c8
cmpl $0x0, (%rax)
movq 0x48(%rsp), %rbx
js 0x5cc3
leaq 0x10620(%rip), %rax     # 0x162d0
leaq 0x9c6f(%rip), %rsi      # 0xf926
xorl %edi, %edi
movq %r13, %rdx
movq (%rax), %rcx
xorl %eax, %eax
callq *%rcx
movl %r12d, %edi
callq 0x2550
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
movq $0x0, 0x10(%rsp)
jmp 0x5b7d