include/ccKVS/inline_util.h
static inline bool vector_read(struct extended_cache_op* ops, struct coalesce_inf* coalesce_struct, uint16_t* op_i_ptr,
							   uint16_t wr_i, uint8_t rm_id, int size_of_op, struct ibv_sge* rem_send_sgl, struct mica_resp* resp,
							   int local_client_id, uint8_t per_worker_outstanding, struct ibv_send_wr* rem_send_wr)
{
	/* a multiget is as such:
         key 16B Opcode 1B(Multiget) Val_len overloaded to say how many requests in the multiget,
         value contains only Keys and Opcode of the coalesced gets
           Sending the opcode for every key may look stupid but it makes life much easier on the worker size,
           where mica gets probed with an array of pointers to requests*/
	uint16_t op_i = *op_i_ptr;
	if (ENABLE_COALESCING == 1 && ops[op_i].opcode == CACHE_OP_GET) {
		if (coalesce_struct[rm_id].slots == 0 && per_worker_outstanding < WS_PER_WORKER) {
			coalesce_struct[rm_id].wr_i = wr_i;
			coalesce_struct[rm_id].op_i = op_i;
			coalesce_struct[rm_id].slots++;
			rem_send_sgl[wr_i].length = HERD_GET_REQ_SIZE;
			return false;
			// yellow_printf("Client %d Coalescing for rm %d at op_i %d and wr_ i %d tag %d \n", local_client_id, rm_id, op_i, wr_i, ops[op_i].key.tag);
		}
		else if (coalesce_struct[rm_id].slots > 0 && ops[op_i].opcode == CACHE_OP_GET) {
			coalesce_struct[rm_id].slots++;
			uint16_t cl_slots = coalesce_struct[rm_id].slots; // make the code a bit more readable
			uint16_t cl_wr_i = coalesce_struct[rm_id].wr_i;
			uint16_t cl_op_i = coalesce_struct[rm_id].op_i;
			if (cl_slots == 2) {
				ops[cl_op_i].opcode = MICA_OP_MULTI_GET;
				rem_send_sgl[cl_wr_i].length++; // we add the val_len field
			}
			if (ENABLE_ASSERTIONS == 1) assert(cl_slots <= MAX_COALESCE_PER_MACH);
			rem_send_sgl[cl_wr_i].length += HERD_GET_REQ_SIZE;
			/* this can only help with big objects where inlining is disabled and is used only for get reqs
			 * when inlining is enabled, it is also mandatory as NIC reads from the buffers asynchronously */
			if ((CLIENT_ENABLE_INLINING == 0) && rem_send_sgl[cl_wr_i].length > MAXIMUM_INLINE_SIZE) {
				if ((rem_send_wr[cl_wr_i].send_flags & IBV_SEND_INLINE) != 0) // inline is used and must be removed
					rem_send_wr[cl_wr_i].send_flags ^= IBV_SEND_INLINE;
			}
			//  printf("Increasing the length of wr_i %d to %d, op_i :%d, cl_op_i %d \n", cl_wr_i, rem_send_sgl[cl_wr_i].length, op_i, cl_op_i );
			if (ENABLE_ASSERTIONS == 1) {
				if (rem_send_sgl[cl_wr_i].length > MULTIGET_AVAILABLE_SIZE) {
					printf("local_client_id %d, length %d, cl_slots %d,\n", local_client_id, rem_send_sgl[cl_wr_i].length, cl_slots);
					assert(false);
				}
				assert(ops[op_i].opcode == CACHE_OP_GET);
				assert(cl_slots > 1);
				struct remote_meta *tmp = (struct remote_meta *)&(ops[op_i].key.meta);
				assert(tmp->clt_gid == local_client_id + CLIENTS_PER_MACHINE * machine_id);
				//yellow_printf("offset %d, max value %d\n",HERD_GET_REQ_SIZE * (cl_slots - 2), MICA_MAX_VALUE - HERD_GET_REQ_SIZE);
				//assert((HERD_GET_REQ_SIZE * (cl_slots - 2)) <= MICA_MAX_VALUE - HERD_GET_REQ_SIZE);
			}
			memcpy(ops[cl_op_i].value + (HERD_GET_REQ_SIZE * (cl_slots - 2)), ops + op_i, HERD_GET_REQ_SIZE);
			ops[cl_op_i].val_len = cl_slots;
			// yellow_printf("Client %d Adding for rm %d at op_i %d and wr_ i %d on slot %d, offset %llu, key with tag %d\n",
			// local_client_id, rm_id, op_i, wr_i, coalesce_struct[rm_id].slots, ops[cl_op_i].value + (HERD_GET_REQ_SIZE * (cl_slots - 2)),
			// ops[op_i].key.tag);
			if (coalesce_struct[rm_id].slots == MAX_COALESCE_PER_MACH) coalesce_struct[rm_id].slots = 0;
			resp[op_i].type = EMPTY;
			(*op_i_ptr)++;
			return true;
			// green_printf("OP_i %d Opcode %d, referring wr %d, wr size %d \n", coalesce_struct[rm_id].op_i, ops[coalesce_struct[rm_id].op_i].opcode,
			// 						coalesce_struct[rm_id].wr_i, rem_send_sgl[coalesce_struct[rm_id].wr_i].length);
		}
	}
	return false;
}
// Checks if an op can be coalaseced with previous ops and returns true if it can
Checks if an op can be coalaseced with previous ops and returns true if it can
Checks if an op can be coalaseced with previous ops and returns true if it can
static inline bool vector_read(struct extended_cache_op* ops, struct coalesce_inf* coalesce_struct, uint16_t* op_i_ptr,
							   uint16_t wr_i, uint8_t rm_id, int size_of_op, struct ibv_sge* rem_send_sgl, struct mica_resp* resp,
							   int local_client_id, uint8_t per_worker_outstanding, struct ibv_send_wr* rem_send_wr)
{
	uint16_t op_i = *op_i_ptr;
	if (ENABLE_COALESCING == 1 && ops[op_i].opcode == CACHE_OP_GET) {
		if (coalesce_struct[rm_id].slots == 0 && per_worker_outstanding < WS_PER_WORKER) {
			coalesce_struct[rm_id].wr_i = wr_i;
			coalesce_struct[rm_id].op_i = op_i;
			coalesce_struct[rm_id].slots++;
			rem_send_sgl[wr_i].length = HERD_GET_REQ_SIZE;
			return false;
		}
		else if (coalesce_struct[rm_id].slots > 0 && ops[op_i].opcode == CACHE_OP_GET) {
			coalesce_struct[rm_id].slots++;
			uint16_t cl_slots = coalesce_struct[rm_id].slots; 
			uint16_t cl_wr_i = coalesce_struct[rm_id].wr_i;
			uint16_t cl_op_i = coalesce_struct[rm_id].op_i;
			if (cl_slots == 2) {
				ops[cl_op_i].opcode = MICA_OP_MULTI_GET;
				rem_send_sgl[cl_wr_i].length++; 
			}
			if (ENABLE_ASSERTIONS == 1) assert(cl_slots <= MAX_COALESCE_PER_MACH);
			rem_send_sgl[cl_wr_i].length += HERD_GET_REQ_SIZE;
			if ((CLIENT_ENABLE_INLINING == 0) && rem_send_sgl[cl_wr_i].length > MAXIMUM_INLINE_SIZE) {
				if ((rem_send_wr[cl_wr_i].send_flags & IBV_SEND_INLINE) != 0) 
					rem_send_wr[cl_wr_i].send_flags ^= IBV_SEND_INLINE;
			}
			if (ENABLE_ASSERTIONS == 1) {
				if (rem_send_sgl[cl_wr_i].length > MULTIGET_AVAILABLE_SIZE) {
					printf("local_client_id %d, length %d, cl_slots %d,\n", local_client_id, rem_send_sgl[cl_wr_i].length, cl_slots);
					assert(false);
				}
				assert(ops[op_i].opcode == CACHE_OP_GET);
				assert(cl_slots > 1);
				struct remote_meta *tmp = (struct remote_meta *)&(ops[op_i].key.meta);
				assert(tmp->clt_gid == local_client_id + CLIENTS_PER_MACHINE * machine_id);
			}
			memcpy(ops[cl_op_i].value + (HERD_GET_REQ_SIZE * (cl_slots - 2)), ops + op_i, HERD_GET_REQ_SIZE);
			ops[cl_op_i].val_len = cl_slots;
			if (coalesce_struct[rm_id].slots == MAX_COALESCE_PER_MACH) coalesce_struct[rm_id].slots = 0;
			resp[op_i].type = EMPTY;
			(*op_i_ptr)++;
			return true;
		}
	}
	return false;
}
static inline bool vector_read ( struct extended_cache_op * ops , struct coalesce_inf * coalesce_struct , uint16_t * op_i_ptr , uint16_t wr_i , uint8_t rm_id , int size_of_op , struct ibv_sge * rem_send_sgl , struct mica_resp * resp , int local_client_id , uint8_t per_worker_outstanding , struct ibv_send_wr * rem_send_wr ) { uint16_t op_i = * op_i_ptr ; if ( ENABLE_COALESCING == 1 && ops [ op_i ] . opcode == CACHE_OP_GET ) { if ( coalesce_struct [ rm_id ] . slots == 0 && per_worker_outstanding < WS_PER_WORKER ) { coalesce_struct [ rm_id ] . wr_i = wr_i ; coalesce_struct [ rm_id ] . op_i = op_i ; coalesce_struct [ rm_id ] . slots ++ ; rem_send_sgl [ wr_i ] . length = HERD_GET_REQ_SIZE ; return false ; } else if ( coalesce_struct [ rm_id ] . slots > 0 && ops [ op_i ] . opcode == CACHE_OP_GET ) { coalesce_struct [ rm_id ] . slots ++ ; uint16_t cl_slots = coalesce_struct [ rm_id ] . slots ; uint16_t cl_wr_i = coalesce_struct [ rm_id ] . wr_i ; uint16_t cl_op_i = coalesce_struct [ rm_id ] . op_i ; if ( cl_slots == 2 ) { ops [ cl_op_i ] . opcode = MICA_OP_MULTI_GET ; rem_send_sgl [ cl_wr_i ] . length ++ ; } if ( ENABLE_ASSERTIONS == 1 ) assert ( cl_slots <= MAX_COALESCE_PER_MACH ) ; rem_send_sgl [ cl_wr_i ] . length += HERD_GET_REQ_SIZE ; if ( ( CLIENT_ENABLE_INLINING == 0 ) && rem_send_sgl [ cl_wr_i ] . length > MAXIMUM_INLINE_SIZE ) { if ( ( rem_send_wr [ cl_wr_i ] . send_flags & IBV_SEND_INLINE ) != 0 ) rem_send_wr [ cl_wr_i ] . send_flags ^= IBV_SEND_INLINE ; } if ( ENABLE_ASSERTIONS == 1 ) { if ( rem_send_sgl [ cl_wr_i ] . length > MULTIGET_AVAILABLE_SIZE ) { printf ( " \n " , local_client_id , rem_send_sgl [ cl_wr_i ] . length , cl_slots ) ; assert ( false ) ; } assert ( ops [ op_i ] . opcode == CACHE_OP_GET ) ; assert ( cl_slots > 1 ) ; struct remote_meta * tmp = ( struct remote_meta * ) & ( ops [ op_i ] . key . meta ) ; assert ( tmp -> clt_gid == local_client_id + CLIENTS_PER_MACHINE * machine_id ) ; } memcpy ( ops [ cl_op_i ] . value + ( HERD_GET_REQ_SIZE * ( cl_slots - 2 ) ) , ops + op_i , HERD_GET_REQ_SIZE ) ; ops [ cl_op_i ] . val_len = cl_slots ; if ( coalesce_struct [ rm_id ] . slots == MAX_COALESCE_PER_MACH ) coalesce_struct [ rm_id ] . slots = 0 ; resp [ op_i ] . type = EMPTY ; ( * op_i_ptr ) ++ ; return true ; } } return false ; }
Checks if an op can be coalaseced with previous ops and returns true if it can
Checks if an op can be coalaseced with previous ops and returns true if it can
/* a multiget is as such:
         key 16B Opcode 1B(Multiget) Val_len overloaded to say how many requests in the multiget,
         value contains only Keys and Opcode of the coalesced gets
           Sending the opcode for every key may look stupid but it makes life much easier on the worker size,
           where mica gets probed with an array of pointers to requests*/ // yellow_printf("Client %d Coalescing for rm %d at op_i %d and wr_ i %d tag %d \n", local_client_id, rm_id, op_i, wr_i, ops[op_i].key.tag); // make the code a bit more readable // we add the val_len field /* this can only help with big objects where inlining is disabled and is used only for get reqs
			 * when inlining is enabled, it is also mandatory as NIC reads from the buffers asynchronously */ // inline is used and must be removed //  printf("Increasing the length of wr_i %d to %d, op_i :%d, cl_op_i %d \n", cl_wr_i, rem_send_sgl[cl_wr_i].length, op_i, cl_op_i ); //yellow_printf("offset %d, max value %d\n",HERD_GET_REQ_SIZE * (cl_slots - 2), MICA_MAX_VALUE - HERD_GET_REQ_SIZE); //assert((HERD_GET_REQ_SIZE * (cl_slots - 2)) <= MICA_MAX_VALUE - HERD_GET_REQ_SIZE); // yellow_printf("Client %d Adding for rm %d at op_i %d and wr_ i %d on slot %d, offset %llu, key with tag %d\n", // local_client_id, rm_id, op_i, wr_i, coalesce_struct[rm_id].slots, ops[cl_op_i].value + (HERD_GET_REQ_SIZE * (cl_slots - 2)), // ops[op_i].key.tag); // green_printf("OP_i %d Opcode %d, referring wr %d, wr size %d \n", coalesce_struct[rm_id].op_i, ops[coalesce_struct[rm_id].op_i].opcode, // 						coalesce_struct[rm_id].wr_i, rem_send_sgl[coalesce_struct[rm_id].wr_i].length);