// File: /workspace/github_c_makefile_star2_O1/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
movq %r9, %rbx
movq %r8, 0x38(%rsp)
movl %ecx, %ebp
movl %edx, %r13d
movl %esi, 0x14(%rsp)
movq %rdi, 0x30(%rsp)
movq 0x8108(%rsp), %r15
leaq 0xa0(%rsp), %rax
movq %rax, 0x20(%rsp)
movq $0x4000, 0x40(%rsp)     # imm = 0x4000
leaq 0x13ba2(%rip), %rax     # 0x193a4
movl (%rax), %r14d
callq 0x23a0
cmpl %eax, %r14d
je 0x5828
leaq 0x13c1a(%rip), %rax     # 0x19430
xorl %ecx, %ecx
movl %ecx, (%rax)
leaq 0x13b87(%rip), %rax     # 0x193a8
movl %ecx, (%rax)
callq 0x6a3e
movq 0x8120(%rsp), %r12
movq 0x8100(%rsp), %rdx
movq 0x80f0(%rsp), %rsi
movq 0x80e8(%rsp), %rax
movq 0x80e0(%rsp), %r9
testq %r15, %r15
je 0x5867
movq %rsi, %rcx
orq %rdx, %rcx
je 0x5867
testq %rsi, %rsi
je 0x58af
movq (%rsi), %r10
jmp 0x58b2
subq $0x8, %rsp
xorl %r10d, %r10d
leaq 0x66(%rsp), %r11
leaq 0x48(%rsp), %r14
leaq 0x28(%rsp), %r15
movl 0x1c(%rsp), %edi
movl %r13d, %esi
movl %ebp, %edx
movq 0x40(%rsp), %rbp
movq %rbp, %rcx
movq %rbx, %r8
pushq %r10
pushq (%r12)
pushq %r11
movq 0x8138(%rsp), %r12
pushq %r12
pushq %r14
pushq %r15
pushq %r10
pushq %r10
pushq %r10
jmp 0x590d
xorl %r10d, %r10d
testq %rdx, %rdx
movl 0x14(%rsp), %edi
je 0x58c0
movq (%rdx), %r14
jmp 0x58c3
xorl %r14d, %r14d
movl (%r15), %r15d
subq $0x8, %rsp
leaq 0x66(%rsp), %r11
movl %r13d, %esi
movl %ebp, %edx
movq 0x40(%rsp), %rbp
movq %rbp, %rcx
movq %rbx, %r8
pushq $0x0
pushq (%r12)
pushq %r11
movq 0x8138(%rsp), %r12
pushq %r12
leaq 0x68(%rsp), %r11
pushq %r11
leaq 0x50(%rsp), %r11
pushq %r11
pushq %r15
pushq %r14
movl 0x8140(%rsp), %r11d
pushq %r11
pushq %r10
pushq %rax
callq 0x4b69
addq $0x60, %rsp
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
testl %eax, %eax
jne 0x5ca7
movl %r13d, %r15d
xorl %r13d, %r13d
testq %r12, %r12
je 0x598f
movl 0xc(%r12), %eax
testl %eax, %eax
movq 0x30(%rsp), %rbx
je 0x599e
leaq 0x40a0(%rsp), %rbx
movl $0x1, %edi
movq %rbx, %rsi
cmpl $0x2bd, %eax            # imm = 0x2BD
jl 0x59ad
callq 0x2230
movabsq $0x431bde82d7b634db, %rax # imm = 0x431BDE82D7B634DB
mulq 0x8(%rbx)
shrq $0x12, %rdx
imulq $0x3e8, (%rbx), %r14    # imm = 0x3E8
addq %rdx, %r14
movslq 0xc(%r12), %rax
addq %rax, %r14
movl %eax, %ecx
shrl $0x1f, %ecx
addl %eax, %ecx
sarl %ecx
movq %rcx, 0x28(%rsp)
jmp 0x59db
movl $0x32, %eax
movq %rax, 0x28(%rsp)
xorl %r14d, %r14d
jmp 0x59db
movl $0x32, %eax
movq %rax, 0x28(%rsp)
xorl %r14d, %r14d
jmp 0x59e0
callq 0x2230
movabsq $0x431bde82d7b634db, %rax # imm = 0x431BDE82D7B634DB
mulq 0x8(%rbx)
shrq $0x12, %rdx
imulq $0x3e8, (%rbx), %r14    # imm = 0x3E8
addq %rdx, %r14
movslq 0xc(%r12), %rcx
movq %rcx, 0x28(%rsp)
addq %rcx, %r14
movq 0x30(%rsp), %rbx
movl %r15d, %ecx
movl %r15d, %eax
andl $0x2, %eax
movl %eax, 0x4c(%rsp)
sete %al
testb $0x8, 0x14(%rsp)
sete %dl
orb %al, %dl
movb %dl, 0xf(%rsp)
movl $0xffffffff, 0x10(%rsp) # imm = 0xFFFFFFFF
leaq 0x40a0(%rsp), %rax
andl $0x1, %ecx
movl %ecx, 0x14(%rsp)
leaq 0x5e(%rsp), %r15
movq %rax, 0x18(%rsp)
movq %rbx, %rdi
movq %rbp, %rsi
movq %r15, %rdx
movl 0x14(%rsp), %ecx
callq 0x7f33
movq %rax, %r12
testq %rax, %rax
je 0x5ad4
movzbl 0x15(%rbx), %edx
movq %r12, %rdi
xorl %esi, %esi
callq 0x864f
cmpl $-0x1, %eax
je 0x5adb
movl %eax, %ebx
movq %r13, %r15
movq %rbp, %r13
cmpb $0x0, 0xf(%rsp)
jne 0x5a6c
movq 0x20(%rsp), %rax
andb $-0x9, 0x9(%rax)
movq 0x20(%rsp), %rsi
movq 0x40(%rsp), %rdx
movl %ebx, %edi
movq %r14, %rcx
movq 0x28(%rsp), %rbp
movl %ebp, %r8d
callq 0xdf14
testl %eax, %eax
jne 0x5aab
movl $0x1e, %edx
movl %ebx, %edi
leaq 0x72(%rsp), %rsi
movq %r14, %rcx
movl %ebp, %r8d
callq 0xd8bc
testl %eax, %eax
je 0x5b6c
movl %eax, 0x10(%rsp)
cmpl $0x6e, %eax
movl $0x32, %esi
movl $0x1, %eax
cmovel %eax, %esi
movq %r12, %rdi
callq 0x842b
movq %r13, %rbp
movq %r15, %r13
leaq 0x5e(%rsp), %r15
jmp 0x5aea
movl $0x2710, %edi           # imm = 0x2710
jmp 0x5ae0
movl $0x3e8, %edi            # imm = 0x3E8
callq 0x2360
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
cmpl $-0x1, %ebx
je 0x5af6
movl %ebx, %edi
callq 0x2550
testq %r12, %r12
je 0x5b03
movq %r12, %rdi
callq 0x8426
testq %r14, %r14
movq 0x30(%rsp), %rbx
je 0x5b4d
movl $0x1, %edi
leaq 0x90(%rsp), %rsi
callq 0x2230
movabsq $0x431bde82d7b634db, %rax # imm = 0x431BDE82D7B634DB
mulq 0x98(%rsp)
shrq $0x12, %rdx
imulq $0x3e8, 0x90(%rsp), %rax # imm = 0x3E8
addq %rdx, %rax
cmpq %rax, %r14
jb 0x5c4a
movq 0x8118(%rsp), %rax
testq %rax, %rax
je 0x5b64
cmpl $0x2, 0x14(%rax)
jne 0x5c52
decl %r13d
jmp 0x5a1f
leaq 0x72(%rsp), %rdi
callq 0xccb0
leaq 0x7a(%rsp), %rdi
callq 0xcccd
movq 0x8110(%rsp), %rcx
testq %rcx, %rcx
je 0x5b96
movl 0x80(%rsp), %eax
movl %eax, (%rcx)
movl 0x74(%rsp), %eax
movzwl 0x78(%rsp), %ebp
shlq $0x20, %rbp
orq %rax, %rbp
movzbl 0x7a(%rsp), %eax
subq %rax, %rbp
movq %r15, %r13
je 0x5cc0
cmpq $0x4001, %rbp           # imm = 0x4001
jb 0x5bd6
movq %rbp, %rdi
callq 0x22e0
movq %rax, 0x18(%rsp)
testq %rax, %rax
je 0x5d84
movq %r13, 0x50(%rsp)
movl %ebx, %edi
movq 0x18(%rsp), %r13
movq %r13, %rsi
movq %rbp, %rdx
movq %r14, %rcx
movq 0x28(%rsp), %r8
callq 0xd8bc
testl %eax, %eax
je 0x5cbb
leaq 0x40a0(%rsp), %rcx
cmpq %rcx, %r13
je 0x5c16
movq %r13, %rdi
movl %eax, %ebp
callq 0x22c0
movl %ebp, %eax
movl %eax, 0x10(%rsp)
cmpl $0x6e, %eax
movl $0x32, %esi
movl $0x1, %eax
cmovel %eax, %esi
movq %r12, %rdi
callq 0x842b
movq $0x0, 0x18(%rsp)
movq 0x38(%rsp), %rbp
movq 0x50(%rsp), %r13
jmp 0x5acd
movl $0xfffffffe, 0x10(%rsp) # imm = 0xFFFFFFFE
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
leaq 0xa0(%rsp), %r14
cmpl $-0x1, %ebx
je 0x5c6b
movl %ebx, %edi
callq 0x2550
movq 0x20(%rsp), %rdi
cmpq %r14, %rdi
movq 0x18(%rsp), %rbx
je 0x5c7f
callq 0x22c0
testq %rbx, %rbx
setne %al
leaq 0x40a0(%rsp), %rcx
cmpq %rcx, %rbx
setne %cl
testb %cl, %al
movl 0x10(%rsp), %ecx
je 0x5ca7
movq %rbx, %rdi
movl %ecx, %ebx
callq 0x22c0
movl %ebx, %ecx
movl %ecx, %eax
addq $0x80a8, %rsp           # imm = 0x80A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x50(%rsp), %r13
movq %r12, %rdi
callq 0x8446
movq %r12, %rdi
movl %ebx, %esi
xorl %edx, %edx
callq 0x86b0
movq %r12, %rdi
callq 0x8426
movq 0x20(%rsp), %rdi
leaq 0xa0(%rsp), %rax
cmpq %rax, %rdi
je 0x5cf3
callq 0x22c0
movl $0x1, %r15d
movq 0x18(%rsp), %rsi
testq %rsi, %rsi
je 0x5d5b
leaq 0x7a(%rsp), %rdi
movq %rbp, %rdx
movq 0x80f0(%rsp), %rcx
movq 0x8100(%rsp), %r8
movq 0x8108(%rsp), %r9
pushq 0x8128(%rsp)
pushq 0x8128(%rsp)
callq 0x53cb
addq $0x10, %rsp
testl %eax, %eax
jne 0x5d5b
movb 0x7f(%rsp), %al
movzbl %al, %eax
movl 0x4c(%rsp), %r15d
xorl $0x2, %r15d
cmpb $0x2, %al
cmovnel %eax, %r15d
testl %r13d, %r13d
cmovel %eax, %r15d
movq 0x18(%rsp), %rbx
testq %rbx, %rbx
sete %al
leaq 0x40a0(%rsp), %rcx
cmpq %rcx, %rbx
sete %cl
orb %al, %cl
movl %r15d, %ecx
je 0x5c9b
jmp 0x5ca7
leaq 0x1153d(%rip), %rax     # 0x172c8
movl $0xffffffff, 0x10(%rsp) # imm = 0xFFFFFFFF
cmpl $0x0, (%rax)
js 0x5dc0
leaq 0x11531(%rip), %rax     # 0x172d0
movq (%rax), %rcx
leaq 0xab5f(%rip), %rsi      # 0x10908
movq $0x0, 0x18(%rsp)
xorl %edi, %edi
movq %rbp, %rdx
xorl %eax, %eax
callq *%rcx
jmp 0x5c57
movq $0x0, 0x18(%rsp)
jmp 0x5c57