/** Application callBack: THis the callback that is activated upon the recption of a disk operation from a remote client: There is 2 kinds of requests that are supported by this function: READ and WRITE @param socket_ctx_p: pointer to the af unix socket @param socketId: reference of the socket (not used) @retval : TRUE-> xmit ready event expected @retval : FALSE-> xmit ready event not expected */ void rozofs_storcli_req_rcv_cbk(void *userRef,uint32_t socket_ctx_idx, void *recv_buf) { uint32_t *com_hdr_p; rozofs_rpc_call_hdr_t hdr; int errcode = EINVAL; com_hdr_p = (uint32_t*) ruc_buf_getPayload(recv_buf); com_hdr_p +=1; /* skip the size of the rpc message */ memcpy(&hdr,com_hdr_p,sizeof(rozofs_rpc_call_hdr_t)); scv_call_hdr_ntoh(&hdr); /* ** get the opcode requested and dispatch the processing accordling to that opcode */ switch (hdr.proc) { case STORCLI_READ: rozofs_storcli_read_req_init(socket_ctx_idx,recv_buf,rozofs_storcli_remote_rsp_cbk,0,STORCLI_DO_QUEUE); return; case STORCLI_WRITE: rozofs_storcli_write_req_init(socket_ctx_idx,recv_buf,rozofs_storcli_remote_rsp_cbk); return; default: /* ** Put code here to format a reply with an error message */ rozofs_storcli_reply_error_with_recv_buf(socket_ctx_idx,recv_buf,NULL,rozofs_storcli_remote_rsp_cbk,errcode); return; } return; }
/** Initial truncate request @param socket_ctx_p: pointer to the af unix socket @param socketId: reference of the socket (not used) @param rozofs_storcli_remote_rsp_cbk: callback for sending out the response @retval : TRUE-> xmit ready event expected @retval : FALSE-> xmit ready event not expected */ void rozofs_storcli_truncate_req_init(uint32_t socket_ctx_idx, void *recv_buf,rozofs_storcli_resp_pf_t rozofs_storcli_remote_rsp_cbk) { rozofs_rpc_call_hdr_with_sz_t *com_hdr_p; rozofs_storcli_ctx_t *working_ctx_p = NULL; int i; uint32_t msg_len; /* length of the rpc messsage including the header length */ storcli_truncate_arg_t *storcli_truncate_rq_p = NULL; rozofs_rpc_call_hdr_t hdr; /* structure that contains the rpc header in host format */ int len; /* effective length of application message */ uint8_t *pmsg; /* pointer to the first available byte in the application message */ uint32_t header_len; XDR xdrs; int errcode = EINVAL; /* ** allocate a context for the duration of the write */ working_ctx_p = rozofs_storcli_alloc_context(); if (working_ctx_p == NULL) { /* ** that situation MUST not occur since there the same number of receive buffer and working context!! */ severe("out of working read/write saved context"); goto failure; } storcli_truncate_rq_p = &working_ctx_p->storcli_truncate_arg; STORCLI_START_NORTH_PROF(working_ctx_p,truncate,0); /* ** Get the full length of the message and adjust it the the length of the applicative part (RPC header+application msg) */ msg_len = ruc_buf_getPayloadLen(recv_buf); msg_len -=sizeof(uint32_t); /* ** save the reference of the received socket since it will be needed for sending back the ** response */ working_ctx_p->socketRef = socket_ctx_idx; working_ctx_p->user_param = NULL; working_ctx_p->recv_buf = recv_buf; working_ctx_p->response_cbk = rozofs_storcli_remote_rsp_cbk; /* ** Get the payload of the receive buffer and set the pointer to the array that describes the write request */ com_hdr_p = (rozofs_rpc_call_hdr_with_sz_t*) ruc_buf_getPayload(recv_buf); memcpy(&hdr,&com_hdr_p->hdr,sizeof(rozofs_rpc_call_hdr_t)); /* ** swap the rpc header */ scv_call_hdr_ntoh(&hdr); pmsg = rozofs_storcli_set_ptr_on_nfs_call_msg((char*)&com_hdr_p->hdr,&header_len); if (pmsg == NULL) { errcode = EFAULT; goto failure; } /* ** map the memory on the first applicative RPC byte available and prepare to decode: ** notice that we will not call XDR_FREE since the application MUST ** provide a pointer for storing the file handle */ len = msg_len - header_len; xdrmem_create(&xdrs,(char*)pmsg,len,XDR_DECODE); /* ** store the source transaction id needed for the reply */ working_ctx_p->src_transaction_id = hdr.hdr.xid; /* ** decode the RPC message of the truncate request */ if (xdr_storcli_truncate_arg_t(&xdrs,storcli_truncate_rq_p) == FALSE) { /* ** decoding error */ errcode = EFAULT; severe("rpc trucnate request decoding error"); goto failure; } /* ** init of the load balancing group/ projection association table: ** That table is ordered: the first corresponds to the storage associated with projection 0, second with 1, etc.. ** When build that table, we MUST consider the value of the base which is associated with the distribution */ uint8_t rozofs_safe = rozofs_get_rozofs_safe(storcli_truncate_rq_p->layout); int lbg_in_distribution = 0; for (i = 0; i <rozofs_safe ; i ++) { /* ** Get the load balancing group associated with the sid */ int lbg_id = rozofs_storcli_get_lbg_for_sid(storcli_truncate_rq_p->cid,storcli_truncate_rq_p->dist_set[i]); if (lbg_id < 0) { /* ** there is no associated between the sid and the lbg. It is typically the case ** when a new cluster has been added to the configuration and the client does not ** know yet the configuration change */ severe("sid is unknown !! %d\n",storcli_truncate_rq_p->dist_set[i]); continue; } rozofs_storcli_lbg_prj_insert_lbg_and_sid(working_ctx_p->lbg_assoc_tb,lbg_in_distribution, lbg_id, storcli_truncate_rq_p->dist_set[i]); rozofs_storcli_lbg_prj_insert_lbg_state(working_ctx_p->lbg_assoc_tb, lbg_in_distribution, NORTH_LBG_GET_STATE(working_ctx_p->lbg_assoc_tb[lbg_in_distribution].lbg_id)); lbg_in_distribution++; if (lbg_in_distribution == rozofs_safe) break; } /* ** allocate a small buffer that will be used for sending the response to the truncate request */ working_ctx_p->xmitBuf = ruc_buf_getBuffer(ROZOFS_STORCLI_NORTH_SMALL_POOL); if (working_ctx_p == NULL) { /* ** that situation MUST not occur since there the same number of receive buffer and working context!! */ errcode = ENOMEM; severe("out of small buffer"); goto failure; } /* ** allocate a sequence number for the working context (same aas for read) */ working_ctx_p->read_seqnum = rozofs_storcli_allocate_read_seqnum(); /* ** set now the working variable specific for handling the truncate ** we re-use the structure used for writing even if nothing is written */ uint8_t forward_projection = rozofs_get_rozofs_forward(storcli_truncate_rq_p->layout); for (i = 0; i < forward_projection; i++) { working_ctx_p->prj_ctx[i].prj_state = ROZOFS_PRJ_READ_IDLE; working_ctx_p->prj_ctx[i].prj_buf = ruc_buf_getBuffer(ROZOFS_STORCLI_SOUTH_LARGE_POOL); if (working_ctx_p->prj_ctx[i].prj_buf == NULL) { /* ** that situation MUST not occur since there the same number of receive buffer and working context!! */ errcode = ENOMEM; severe("out of large buffer"); goto failure; } /* ** increment inuse counter on each buffer since we might need to re-use that packet in case ** of retransmission */ working_ctx_p->prj_ctx[i].inuse_valid = 1; ruc_buf_inuse_increment(working_ctx_p->prj_ctx[i].prj_buf); /* ** set the pointer to the bins */ int position = rozofs_storcli_get_position_of_first_byte2write_in_truncate(); uint8_t *pbuf = (uint8_t*)ruc_buf_getPayload(working_ctx_p->prj_ctx[i].prj_buf); working_ctx_p->prj_ctx[i].bins = (bin_t*)(pbuf+position); } /* ** Prepare for request serialization */ memcpy(working_ctx_p->fid_key, storcli_truncate_rq_p->fid, sizeof (sp_uuid_t)); working_ctx_p->opcode_key = STORCLI_TRUNCATE; { /** * lock all the file for a truncate */ uint64_t nb_blocks = 0; nb_blocks--; int ret; ret = stc_rng_insert((void*)working_ctx_p, STORCLI_READ,working_ctx_p->fid_key, 0,nb_blocks, &working_ctx_p->sched_idx); if (ret == 0) { /* ** there is a current request that is processed with the same fid and there is a collision */ return; } /* ** no request pending with that fid, so we can process it right away */ return rozofs_storcli_truncate_req_processing(working_ctx_p); } /* **_____________________________________________ ** Exception cases **_____________________________________________ */ /* ** there was a failure while attempting to allocate a memory ressource. */ failure: /* ** send back the response with the appropriated error code. ** note: The received buffer (rev_buf) is ** intended to be released by this service in case of error or the TCP transmitter ** once it has been passed to the TCP stack. */ rozofs_storcli_reply_error_with_recv_buf(socket_ctx_idx,recv_buf,NULL,rozofs_storcli_remote_rsp_cbk,errcode); /* ** check if the root context was allocated. Free it if is exist */ if (working_ctx_p != NULL) { /* ** remove the reference to the recvbuf to avoid releasing it twice */ STORCLI_STOP_NORTH_PROF(working_ctx_p,truncate,0); working_ctx_p->recv_buf = NULL; rozofs_storcli_release_context(working_ctx_p); } return; }