int rozofs_storcli_send_common(exportclt_t * clt,uint32_t timeout_sec,uint32_t prog,uint32_t vers, int opcode,xdrproc_t encode_fct,void *msg2encode_p, sys_recv_pf_t recv_cbk,void *fuse_ctx_p, int storcli_idx,fid_t fid) { DEBUG_FUNCTION; uint8_t *arg_p; uint32_t *header_size_p; rozofs_tx_ctx_t *rozofs_tx_ctx_p = NULL; void *xmit_buf = NULL; int bufsize; int ret; int position; XDR xdrs; struct rpc_msg call_msg; uint32_t null_val = 0; int lbg_id; /* ** allocate a transaction context */ rozofs_tx_ctx_p = rozofs_tx_alloc(); if (rozofs_tx_ctx_p == NULL) { /* ** out of context ** --> put a pending list for the future to avoid repluing ENOMEM */ TX_STATS(ROZOFS_TX_NO_CTX_ERROR); errno = ENOMEM; goto error; } /* ** insert the storcli load balancing context in the stclbg_hash_table hash table. ** the context is embedded in the transaction context */ stclbg_hash_table_insert_ctx(&rozofs_tx_ctx_p->rw_lbg,fid,storcli_idx); /* ** Get the load balancing group reference associated with the storcli */ lbg_id = storcli_lbg_get_load_balancing_reference(storcli_idx); /* ** allocate an xmit buffer */ xmit_buf = ruc_buf_getBuffer(ROZOFS_TX_LARGE_TX_POOL); if (xmit_buf == NULL) { /* ** something rotten here, we exit we an error ** without activating the FSM */ TX_STATS(ROZOFS_TX_NO_BUFFER_ERROR); errno = ENOMEM; goto error; } /* ** store the reference of the xmit buffer in the transaction context: might be useful ** in case we want to remove it from a transmit list of the underlying network stacks */ rozofs_tx_save_xmitBuf(rozofs_tx_ctx_p,xmit_buf); /* ** get the pointer to the payload of the buffer */ header_size_p = (uint32_t*) ruc_buf_getPayload(xmit_buf); arg_p = (uint8_t*)(header_size_p+1); /* ** create the xdr_mem structure for encoding the message */ bufsize = ruc_buf_getMaxPayloadLen(xmit_buf)-sizeof(uint32_t); xdrmem_create(&xdrs,(char*)arg_p,bufsize,XDR_ENCODE); /* ** fill in the rpc header */ call_msg.rm_direction = CALL; /* ** allocate a xid for the transaction */ call_msg.rm_xid = rozofs_tx_alloc_xid(rozofs_tx_ctx_p); /* ** check the case of the READ since, we must set the value of the xid ** at the top of the buffer */ #if 1 if ((opcode == STORCLI_READ)||(opcode == STORCLI_WRITE)) { uint32_t *share_p; void *shared_buf_ref; RESTORE_FUSE_PARAM(fuse_ctx_p,shared_buf_ref); if (shared_buf_ref != NULL) { share_p = (uint32_t*)ruc_buf_getPayload(shared_buf_ref); *share_p = (uint32_t)call_msg.rm_xid; /** * copy the buffer for the case of the write */ if (opcode == STORCLI_WRITE) { storcli_write_arg_t *wr_args = (storcli_write_arg_t*)msg2encode_p; /* ** get the length to copy from the sshared memory */ int len = share_p[1]; /* ** Compute and write data offset considering 128bits alignment */ int alignment = wr_args->off%16; share_p[2] = alignment; /* ** Set pointer to the buffer start and adjust with alignment */ uint8_t * buf_start = (uint8_t *)&share_p[4]; buf_start += alignment; memcpy(buf_start,wr_args->data.data_val,len); } } } #endif call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; /* XXX: prog and vers have been long historically :-( */ call_msg.rm_call.cb_prog = (uint32_t)prog; call_msg.rm_call.cb_vers = (uint32_t)vers; if (! xdr_callhdr(&xdrs, &call_msg)) { /* ** THIS MUST NOT HAPPEN */ TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** insert the procedure number, NULL credential and verifier */ XDR_PUTINT32(&xdrs, (int32_t *)&opcode); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); /* ** ok now call the procedure to encode the message */ if ((*encode_fct)(&xdrs,msg2encode_p) == FALSE) { TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** Now get the current length and fill the header of the message */ position = XDR_GETPOS(&xdrs); /* ** update the length of the message : must be in network order */ *header_size_p = htonl(0x80000000 | position); /* ** set the payload length in the xmit buffer */ int total_len = sizeof(*header_size_p)+ position; ruc_buf_setPayloadLen(xmit_buf,total_len); /* ** store the receive call back and its associated parameter */ rozofs_tx_ctx_p->recv_cbk = recv_cbk; rozofs_tx_ctx_p->user_param = fuse_ctx_p; /* ** now send the message */ // int lbg_id = storcli_lbg_get_load_balancing_reference(); /* ** increment the number of pending request towards the storcli */ rozofs_storcli_pending_req_count++; ret = north_lbg_send(lbg_id,xmit_buf); if (ret < 0) { if (rozofs_storcli_pending_req_count > 0) rozofs_storcli_pending_req_count--; TX_STATS(ROZOFS_TX_SEND_ERROR); errno = EFAULT; goto error; } TX_STATS(ROZOFS_TX_SEND); /* ** OK, so now finish by starting the guard timer */ rozofs_tx_start_timer(rozofs_tx_ctx_p,timeout_sec); // if (*tx_ptr != NULL) *tx_ptr = rozofs_tx_ctx_p; return 0; error: if (rozofs_tx_ctx_p != NULL) rozofs_tx_free_from_ptr(rozofs_tx_ctx_p); // if (xmit_buf != NULL) ruc_buf_freeBuffer(xmit_buf); return -1; }
/** * ROZOFS Generic RPC Request transaction in non-blocking mode That service initiates RPC call towards the destination referenced by its associated load balancing group WHen the transaction is started, the application will received the response thanks the provided callback The first parameter is a user dependent reference and the second pointer is the pointer to the decoded area. In case of decoding error, transmission error, the second pointer is NULL and errno is asserted with the error. The array provided for decoding the response might be a static variable within the user context or can be an allocated array. If that array has be allocated by the application it is up to the application to release it @param lbg_id : reference of the load balancing group of the exportd @param prog : program @param vers : program version @param opcode : metadata opcode @param encode_fct : encoding function @param msg2encode_p : pointer to the message to encode @param decode_fct : xdr function for message decoding @param ret: pointer to the array that is used for message decoding @parem ret_len : length of the array used for decoding @param recv_cbk : receive callback function (for interpretation of the rpc result @param ctx_p : pointer to the user context @retval 0 on success; @retval -1 on error,, errno contains the cause */ int rozofs_rpc_non_blocking_req_send (int lbg_id,uint32_t prog,uint32_t vers, int opcode,xdrproc_t encode_fct,void *msg2encode_p, xdrproc_t decode_fct, sys_recv_pf_t recv_cbk,void *ctx_p, void *ret,int ret_len) { DEBUG_FUNCTION; uint8_t *arg_p; uint32_t *header_size_p; rozofs_tx_ctx_t *rozofs_tx_ctx_p = NULL; void *xmit_buf = NULL; int bufsize; int ret; int position; XDR xdrs; struct rpc_msg call_msg; uint32_t null_val = 0; rozofs_tx_rpc_ctx_t *rpc_ctx_p = NULL; /* ** allocate a rpc context */ rozofs_rpc_p = rozofs_rpc_req_alloc(); if (rozofs_rpc_p == NULL) { /* ** out of context */ errno = ENOMEM; goto error; } /* ** save the rpc parameter of the caller */ rpc_ctx_p = &rozofs_tx_ctx_p->rpc_ctx; rpc_ctx_p->user_ref = ctx_p; /* save the user reference of the caller */ rpc_ctx_p->xdr_result = decode_fct; /* save the decoding procedure */ rpc_ctx_p->response_cbk = recv_cbk ; rpc_ctx_p->ret_len = ret_len; rpc_ctx_p->ret_p = ret; START_RPC_REQ_PROFILING_START(rpc_ctx_p); /* ** allocate a transaction context */ rozofs_tx_ctx_p = rozofs_tx_alloc(); if (rozofs_tx_ctx_p == NULL) { /* ** out of context ** --> put a pending list for the future to avoid repluing ENOMEM */ TX_STATS(ROZOFS_TX_NO_CTX_ERROR); errno = ENOMEM; goto error; } /* ** allocate an xmit buffer */ xmit_buf = ruc_buf_getBuffer(ROZOFS_TX_LARGE_TX_POOL); if (xmit_buf == NULL) { /* ** something rotten here, we exit we an error ** without activating the FSM */ TX_STATS(ROZOFS_TX_NO_BUFFER_ERROR); errno = ENOMEM; goto error; } /* ** store the reference of the xmit buffer in the transaction context: might be useful ** in case we want to remove it from a transmit list of the underlying network stacks */ rozofs_tx_save_xmitBuf(rozofs_tx_ctx_p,xmit_buf); /* ** get the pointer to the payload of the buffer */ header_size_p = (uint32_t*) ruc_buf_getPayload(xmit_buf); arg_p = (uint8_t*)(header_size_p+1); /* ** create the xdr_mem structure for encoding the message */ bufsize = ruc_buf_getMaxPayloadLen(xmit_buf); xdrmem_create(&xdrs,(char*)arg_p,bufsize,XDR_ENCODE); /* ** fill in the rpc header */ call_msg.rm_direction = CALL; /* ** allocate a xid for the transaction */ call_msg.rm_xid = rozofs_tx_alloc_xid(rozofs_tx_ctx_p); call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; /* XXX: prog and vers have been long historically :-( */ call_msg.rm_call.cb_prog = (uint32_t)prog; call_msg.rm_call.cb_vers = (uint32_t)vers; if (! xdr_callhdr(&xdrs, &call_msg)) { /* ** THIS MUST NOT HAPPEN */ TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** insert the procedure number, NULL credential and verifier */ XDR_PUTINT32(&xdrs, (int32_t *)&opcode); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); /* ** ok now call the procedure to encode the message */ if ((*encode_fct)(&xdrs,msg2encode_p) == FALSE) { TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** Now get the current length and fill the header of the message */ position = XDR_GETPOS(&xdrs); /* ** update the length of the message : must be in network order */ *header_size_p = htonl(0x80000000 | position); /* ** set the payload length in the xmit buffer */ int total_len = sizeof(*header_size_p)+ position; ruc_buf_setPayloadLen(xmit_buf,total_len); /* ** store the receive call back and its associated parameter */ rozofs_tx_ctx_p->recv_cbk = rozofs_rpc_generic_reply_cbk; rozofs_tx_ctx_p->user_param = rpc_ctx_p; /* ** now send the message */ ret = north_lbg_send(lbg_id,xmit_buf); if (ret < 0) { TX_STATS(ROZOFS_TX_SEND_ERROR); errno = EFAULT; goto error; } TX_STATS(ROZOFS_TX_SEND); /* ** OK, so now finish by starting the guard timer */ rozofs_tx_start_timer(rozofs_tx_ctx_p, 25); return 0; error: if (rozofs_tx_ctx_p != NULL) rozofs_tx_free_from_ptr(rozofs_tx_ctx_p); if (rpc_ctx_p != NULL) rozofs_rpc_req_free(rpc_ctx_p); return -1; }
/** * API for creation a transaction towards an exportd The reference of the north load balancing is extracted for the client structure fuse_ctx_p: That API needs the pointer to the current fuse context. That nformation will be saved in the transaction context as userParam. It is intended to be used later when the client gets the response from the server encoding function; For making that API generic, the caller is intended to provide the function that will encode the message in XDR format. The source message that is encoded is supposed to be pointed by msg2encode_p. Since the service is non-blocking, the caller MUST provide the callback function that will be used for decoding the message @param rozofs_tx_ctx_p : transaction context @param recv_cbk : callback function (may be NULL) @param fuse_buffer_ctx_p : buffer containing the fuse context @param vers : program version @retval 0 on success; @retval -1 on error,, errno contains the cause */ int rozofs_expgateway_resend_routing_common(rozofs_tx_ctx_t *rozofs_tx_ctx_p, sys_recv_pf_t recv_cbk,void *fuse_buffer_ctx_p) { DEBUG_FUNCTION; void *xmit_buf = NULL; int ret; int lbg_id; rozofs_fuse_save_ctx_t *fuse_ctx_p; GET_FUSE_CTX_P(fuse_ctx_p,fuse_buffer_ctx_p); expgw_tx_routing_ctx_t *routing_ctx_p = &fuse_ctx_p->expgw_routing_ctx ; /* ** get the xmit buffer from the current routing context */ xmit_buf = routing_ctx_p->xmit_buf; if (xmit_buf == NULL) { /* ** something rotten here, we exit we an error ** without activating the FSM */ severe("rozofs_expgateway_resend_routing_common : not xmit_buf in routing context"); TX_STATS(ROZOFS_TX_NO_BUFFER_ERROR); errno = ENOMEM; goto error; } /* ** The system attempts first to forward the message toward load balancing group ** of an export gateway and then to the master export if the load balancing group ** of the export gateway is not available */ lbg_id = expgw_routing_get_next(routing_ctx_p,xmit_buf); if (lbg_id == -1) { errno = EPROTO; goto error; } /* ** store the reference of the xmit buffer in the transaction context: might be useful ** in case we want to remove it from a transmit list of the underlying network stacks */ rozofs_tx_save_xmitBuf(rozofs_tx_ctx_p,xmit_buf); /* ** get the pointer to the payload of the buffer */ rozofs_rpc_call_hdr_with_sz_t *com_hdr_p = (rozofs_rpc_call_hdr_with_sz_t*) ruc_buf_getPayload(xmit_buf); com_hdr_p->hdr.xid = ntohl(rozofs_tx_alloc_xid(rozofs_tx_ctx_p)); ; /* ** store the receive call back and its associated parameter */ if (recv_cbk != NULL) { rozofs_tx_ctx_p->recv_cbk = recv_cbk; } rozofs_tx_ctx_p->user_param = fuse_buffer_ctx_p; /* ** now send the message */ reloop: ret = north_lbg_send(lbg_id,xmit_buf); if (ret < 0) { TX_STATS(ROZOFS_TX_SEND_ERROR); /* ** attempt to get the next available load balancing group */ lbg_id = expgw_routing_get_next(routing_ctx_p,xmit_buf); if (lbg_id >= 0) goto reloop; errno = EFAULT; goto error; } TX_STATS(ROZOFS_TX_SEND); /* ** OK, so now finish by starting the guard timer */ rozofs_tx_start_timer(rozofs_tx_ctx_p, ROZOFS_TMR_GET(TMR_EXPORT_PROGRAM)); return 0; error: if (rozofs_tx_ctx_p != NULL) rozofs_tx_free_from_ptr(rozofs_tx_ctx_p); return -1; }
/** * API for creation a transaction towards an exportd The reference of the north load balancing is extracted for the client structure fuse_ctx_p: That API needs the pointer to the current fuse context. That nformation will be saved in the transaction context as userParam. It is intended to be used later when the client gets the response from the server encoding function; For making that API generic, the caller is intended to provide the function that will encode the message in XDR format. The source message that is encoded is supposed to be pointed by msg2encode_p. Since the service is non-blocking, the caller MUST provide the callback function that will be used for decoding the message @param eid : export id @param fid : unique file id (directory, regular file, etc...) @param prog : program @param vers : program version @param opcode : metadata opcode @param encode_fct : encoding function @msg2encode_p : pointer to the message to encode @param recv_cbk : receive callback function @param fuse_buffer_ctx_p : pointer to the fuse context @retval 0 on success; @retval -1 on error,, errno contains the cause */ int rozofs_expgateway_send_routing_common(uint32_t eid,fid_t fid,uint32_t prog,uint32_t vers, int opcode,xdrproc_t encode_fct,void *msg2encode_p, sys_recv_pf_t recv_cbk,void *fuse_buffer_ctx_p) { DEBUG_FUNCTION; uint8_t *arg_p; uint32_t *header_size_p; rozofs_tx_ctx_t *rozofs_tx_ctx_p = NULL; void *xmit_buf = NULL; int bufsize; int ret; int position; XDR xdrs; struct rpc_msg call_msg; uint32_t null_val = 0; int lbg_id; expgw_tx_routing_ctx_t local_routing_ctx; expgw_tx_routing_ctx_t *routing_ctx_p; rozofs_fuse_save_ctx_t *fuse_ctx_p=NULL; /* ** Retrieve fuse context when a buffer is given */ fuse_ctx_p = NULL; if (fuse_buffer_ctx_p != NULL) { if (ruc_buf_checkBuffer(fuse_buffer_ctx_p)) { GET_FUSE_CTX_P(fuse_ctx_p,fuse_buffer_ctx_p); } } if (fuse_ctx_p != NULL) { routing_ctx_p = &fuse_ctx_p->expgw_routing_ctx ; } else { routing_ctx_p = &local_routing_ctx; } /* ** get the available load balancing group(s) for routing the request */ ret = expgw_get_export_routing_lbg_info(eid,fid,routing_ctx_p); if (ret < 0) { /* ** no load balancing group available */ errno = EPROTO; goto error; } /* ** allocate a transaction context */ rozofs_tx_ctx_p = rozofs_tx_alloc(); if (rozofs_tx_ctx_p == NULL) { /* ** out of context ** --> put a pending list for the future to avoid repluing ENOMEM */ TX_STATS(ROZOFS_TX_NO_CTX_ERROR); errno = ENOMEM; goto error; } /* ** allocate an xmit buffer */ xmit_buf = ruc_buf_getBuffer(ROZOFS_TX_SMALL_TX_POOL); if (xmit_buf == NULL) { /* ** something rotten here, we exit we an error ** without activating the FSM */ TX_STATS(ROZOFS_TX_NO_BUFFER_ERROR); errno = ENOMEM; goto error; } /* ** The system attempts first to forward the message toward load balancing group ** of an export gateway and then to the master export if the load balancing group ** of the export gateway is not available */ lbg_id = expgw_routing_get_next(routing_ctx_p,xmit_buf); /* ** store the reference of the xmit buffer in the transaction context: might be useful ** in case we want to remove it from a transmit list of the underlying network stacks */ rozofs_tx_save_xmitBuf(rozofs_tx_ctx_p,xmit_buf); /* ** get the pointer to the payload of the buffer */ header_size_p = (uint32_t*) ruc_buf_getPayload(xmit_buf); arg_p = (uint8_t*)(header_size_p+1); /* ** create the xdr_mem structure for encoding the message */ bufsize = rozofs_tx_get_small_buffer_size()-sizeof(uint32_t); xdrmem_create(&xdrs,(char*)arg_p,bufsize,XDR_ENCODE); /* ** fill in the rpc header */ call_msg.rm_direction = CALL; /* ** allocate a xid for the transaction */ call_msg.rm_xid = rozofs_tx_alloc_xid(rozofs_tx_ctx_p); call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; /* XXX: prog and vers have been long historically :-( */ call_msg.rm_call.cb_prog = (uint32_t)prog; call_msg.rm_call.cb_vers = (uint32_t)vers; if (! xdr_callhdr(&xdrs, &call_msg)) { /* ** THIS MUST NOT HAPPEN */ TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** insert the procedure number, NULL credential and verifier */ XDR_PUTINT32(&xdrs, (int32_t *)&opcode); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); /* ** ok now call the procedure to encode the message */ if ((*encode_fct)(&xdrs,msg2encode_p) == FALSE) { TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** Now get the current length and fill the header of the message */ position = XDR_GETPOS(&xdrs); /* ** update the length of the message : must be in network order */ *header_size_p = htonl(0x80000000 | position); /* ** set the payload length in the xmit buffer */ int total_len = sizeof(*header_size_p)+ position; ruc_buf_setPayloadLen(xmit_buf,total_len); /* ** store the receive call back and its associated parameter */ rozofs_tx_ctx_p->recv_cbk = recv_cbk; rozofs_tx_ctx_p->user_param = fuse_buffer_ctx_p; /* ** now send the message */ reloop: ret = north_lbg_send(lbg_id,xmit_buf); if (ret < 0) { TX_STATS(ROZOFS_TX_SEND_ERROR); /* ** attempt to get the next available load balancing group */ lbg_id = expgw_routing_get_next(routing_ctx_p,xmit_buf); if (lbg_id >= 0) goto reloop; errno = EFAULT; goto error; } TX_STATS(ROZOFS_TX_SEND); /* ** OK, so now finish by starting the guard timer */ if (opcode == EP_STATFS) { /* df must give a response (even negative) in less than 2 seconds !!! */ rozofs_tx_start_timer(rozofs_tx_ctx_p, 2); } else { rozofs_tx_start_timer(rozofs_tx_ctx_p, ROZOFS_TMR_GET(TMR_EXPORT_PROGRAM)); } return 0; error: if (rozofs_tx_ctx_p != NULL) rozofs_tx_free_from_ptr(rozofs_tx_ctx_p); return -1; }
int rozofs_export_poll_tx(af_unix_ctx_generic_t *sock_p, uint32_t prog,uint32_t vers, int opcode,xdrproc_t encode_fct,void *msg2encode_p, void *xmit_buf, int extra_len, int applicative_tmo_sec, sys_recv_pf_t recv_cbk,void *user_ctx_p) { DEBUG_FUNCTION; uint8_t *arg_p; uint32_t *header_size_p; rozofs_tx_ctx_t *rozofs_tx_ctx_p = NULL; int bufsize; int ret; int position; XDR xdrs; struct rpc_msg call_msg; uint32_t null_val = 0; uint32_t sock_idx_in_lbg = -1; /* ** get the entry within the load balancing group */ { north_lbg_ctx_t *lbg_p; int lbg_id = sock_p->availability_param; int start_idx; /* ** Get the pointer to the lbg */ lbg_p = north_lbg_getObjCtx_p(lbg_id); if (lbg_p == NULL) { severe("rozofs_export_poll_tx: no such instance %d ",lbg_id); return -1; } for (start_idx = 0; start_idx < lbg_p->nb_entries_conf; start_idx++) { if (lbg_p->entry_tb[start_idx].sock_ctx_ref == sock_p->index) break; } if (lbg_p->nb_entries_conf == start_idx) { severe("rozofs_export_poll_tx: no such instance %d ",sock_p->index); return -1; } /** ** start_idx is the index within the load balancing */ sock_idx_in_lbg = start_idx; //info("JPM poll lbg %d %s entry %d",lbg_id,lbg_p->name,sock_idx_in_lbg); } /* ** allocate a transaction context */ rozofs_tx_ctx_p = rozofs_tx_alloc(); if (rozofs_tx_ctx_p == NULL) { /* ** out of context ** --> put a pending list for the future to avoid repluing ENOMEM */ TX_STATS(ROZOFS_TX_NO_CTX_ERROR); errno = ENOMEM; goto error; } /* ** get the pointer to the payload of the buffer */ header_size_p = (uint32_t*) ruc_buf_getPayload(xmit_buf); arg_p = (uint8_t*)(header_size_p+1); /* ** create the xdr_mem structure for encoding the message */ bufsize = (int)ruc_buf_getMaxPayloadLen(xmit_buf); xdrmem_create(&xdrs,(char*)arg_p,bufsize,XDR_ENCODE); /* ** fill in the rpc header */ call_msg.rm_direction = CALL; /* ** allocate a xid for the transaction */ call_msg.rm_xid = rozofs_tx_alloc_xid(rozofs_tx_ctx_p); call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; /* XXX: prog and vers have been long historically :-( */ call_msg.rm_call.cb_prog = (uint32_t)prog; call_msg.rm_call.cb_vers = (uint32_t)vers; if (! xdr_callhdr(&xdrs, &call_msg)) { /* ** THIS MUST NOT HAPPEN */ TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** insert the procedure number, NULL credential and verifier */ XDR_PUTINT32(&xdrs, (int32_t *)&opcode); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); /* ** ok now call the procedure to encode the message */ if ((*encode_fct)(&xdrs,msg2encode_p) == FALSE) { TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** Now get the current length and fill the header of the message */ position = XDR_GETPOS(&xdrs); /* ** add the extra_len if any */ position +=extra_len; /* ** update the length of the message : must be in network order */ *header_size_p = htonl(0x80000000 | position); /* ** set the payload length in the xmit buffer */ int total_len = sizeof(*header_size_p)+ position; ruc_buf_setPayloadLen(xmit_buf,total_len); /* ** store the receive call back and its associated parameter */ rozofs_tx_ctx_p->recv_cbk = recv_cbk; rozofs_tx_ctx_p->user_param = user_ctx_p; rozofs_tx_write_opaque_data(rozofs_tx_ctx_p,1,1); /* lock */ rozofs_tx_write_opaque_data(rozofs_tx_ctx_p,2,sock_p->availability_param); /* lock */ rozofs_tx_write_opaque_data(rozofs_tx_ctx_p,3,sock_idx_in_lbg); /* lock */ /* ** now send the message */ ret = af_unix_generic_stream_send(sock_p,xmit_buf); if (ret < 0) { TX_STATS(ROZOFS_TX_SEND_ERROR); errno = EFAULT; goto error; } TX_STATS(ROZOFS_TX_SEND); /* ** just iunlock the context and don't care about the end of transaction ** the transaction might end because of a direct error sending (tcp ** disconnection) ** ** By not releasing the tx context the end of the transaction ends upon receiving ** the tx timer expiration */ rozofs_tx_write_opaque_data(rozofs_tx_ctx_p,1,0); /* unlock */ /* ** OK, so now finish by starting the guard timer */ rozofs_tx_start_timer(rozofs_tx_ctx_p,applicative_tmo_sec); return 0; error: if (rozofs_tx_ctx_p != NULL) rozofs_tx_free_from_ptr(rozofs_tx_ctx_p); return -1; }
int rozofs_sorcli_poll_tx(af_unix_ctx_generic_t *sock_p, uint32_t prog,uint32_t vers, int opcode,xdrproc_t encode_fct,void *msg2encode_p, void *xmit_buf, int extra_len, int applicative_tmo_sec, sys_recv_pf_t recv_cbk,void *user_ctx_p) { DEBUG_FUNCTION; uint8_t *arg_p; uint32_t *header_size_p; rozofs_tx_ctx_t *rozofs_tx_ctx_p = NULL; int bufsize; int ret; int position; XDR xdrs; struct rpc_msg call_msg; uint32_t null_val = 0; /* ** allocate a transaction context */ rozofs_tx_ctx_p = rozofs_tx_alloc(); if (rozofs_tx_ctx_p == NULL) { /* ** out of context ** --> put a pending list for the future to avoid repluing ENOMEM */ TX_STATS(ROZOFS_TX_NO_CTX_ERROR); errno = ENOMEM; goto error; } /* ** store the reference of the xmit buffer in the transaction context: might be useful ** in case we want to remove it from a transmit list of the underlying network stacks */ rozofs_tx_save_xmitBuf(rozofs_tx_ctx_p,xmit_buf); /* ** get the pointer to the payload of the buffer */ header_size_p = (uint32_t*) ruc_buf_getPayload(xmit_buf); arg_p = (uint8_t*)(header_size_p+1); /* ** create the xdr_mem structure for encoding the message */ bufsize = (int)ruc_buf_getMaxPayloadLen(xmit_buf); bufsize -= sizeof(uint32_t); /* skip length*/ xdrmem_create(&xdrs,(char*)arg_p,bufsize,XDR_ENCODE); /* ** fill in the rpc header */ call_msg.rm_direction = CALL; /* ** allocate a xid for the transaction */ call_msg.rm_xid = rozofs_tx_alloc_xid(rozofs_tx_ctx_p); call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; /* XXX: prog and vers have been long historically :-( */ call_msg.rm_call.cb_prog = (uint32_t)prog; call_msg.rm_call.cb_vers = (uint32_t)vers; if (! xdr_callhdr(&xdrs, &call_msg)) { /* ** THIS MUST NOT HAPPEN */ TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** insert the procedure number, NULL credential and verifier */ XDR_PUTINT32(&xdrs, (int32_t *)&opcode); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); /* ** ok now call the procedure to encode the message */ if ((*encode_fct)(&xdrs,msg2encode_p) == FALSE) { TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** Now get the current length and fill the header of the message */ position = XDR_GETPOS(&xdrs); /* ** add the extra_len if any */ position +=extra_len; /* ** update the length of the message : must be in network order */ *header_size_p = htonl(0x80000000 | position); /* ** set the payload length in the xmit buffer */ int total_len = sizeof(*header_size_p)+ position; ruc_buf_setPayloadLen(xmit_buf,total_len); /* ** store the receive call back and its associated parameter */ rozofs_tx_ctx_p->recv_cbk = recv_cbk; rozofs_tx_ctx_p->user_param = user_ctx_p; rozofs_tx_write_opaque_data(rozofs_tx_ctx_p,1,1); /* lock */ /* ** now send the message */ ret = af_unix_generic_stream_send(sock_p,xmit_buf); if (ret < 0) { TX_STATS(ROZOFS_TX_SEND_ERROR); errno = EFAULT; goto error; } TX_STATS(ROZOFS_TX_SEND); /* ** just iunlock the context and don't care about the end of transaction ** the transaction might end because of a direct error sending (tcp ** disconnection) ** ** By not releasing the tx context the end of the transaction ends upon receiving ** the tx timer expiration */ rozofs_tx_write_opaque_data(rozofs_tx_ctx_p,1,0); /* unlock */ /* ** OK, so now finish by starting the guard timer */ rozofs_tx_start_timer(rozofs_tx_ctx_p,applicative_tmo_sec); return 0; error: if (rozofs_tx_ctx_p != NULL) rozofs_tx_free_from_ptr(rozofs_tx_ctx_p); return -1; }
int rozofs_sorcli_send_rq_common(uint32_t lbg_id,uint32_t timeout_sec, uint32_t prog,uint32_t vers, int opcode,xdrproc_t encode_fct,void *msg2encode_p, void *xmit_buf, uint32_t seqnum, uint32_t opaque_value_idx1, int extra_len, sys_recv_pf_t recv_cbk,void *user_ctx_p) { DEBUG_FUNCTION; uint8_t *arg_p; uint32_t *header_size_p; rozofs_tx_ctx_t *rozofs_tx_ctx_p = NULL; int bufsize; int ret; int position; XDR xdrs; struct rpc_msg call_msg; uint32_t null_val = 0; /* ** allocate a transaction context */ rozofs_tx_ctx_p = rozofs_tx_alloc(); if (rozofs_tx_ctx_p == NULL) { /* ** out of context ** --> put a pending list for the future to avoid repluing ENOMEM */ TX_STATS(ROZOFS_TX_NO_CTX_ERROR); errno = ENOMEM; goto error; } /* ** store the reference of the xmit buffer in the transaction context: might be useful ** in case we want to remove it from a transmit list of the underlying network stacks */ rozofs_tx_save_xmitBuf(rozofs_tx_ctx_p,xmit_buf); /* ** get the pointer to the payload of the buffer */ header_size_p = (uint32_t*) ruc_buf_getPayload(xmit_buf); arg_p = (uint8_t*)(header_size_p+1); /* ** create the xdr_mem structure for encoding the message */ bufsize = (int)ruc_buf_getMaxPayloadLen(xmit_buf); xdrmem_create(&xdrs,(char*)arg_p,bufsize,XDR_ENCODE); /* ** fill in the rpc header */ call_msg.rm_direction = CALL; /* ** allocate a xid for the transaction */ call_msg.rm_xid = rozofs_tx_alloc_xid(rozofs_tx_ctx_p); call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; /* XXX: prog and vers have been long historically :-( */ call_msg.rm_call.cb_prog = (uint32_t)prog; call_msg.rm_call.cb_vers = (uint32_t)vers; if (! xdr_callhdr(&xdrs, &call_msg)) { /* ** THIS MUST NOT HAPPEN */ TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** insert the procedure number, NULL credential and verifier */ XDR_PUTINT32(&xdrs, (int32_t *)&opcode); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); XDR_PUTINT32(&xdrs, (int32_t *)&null_val); /* ** ok now call the procedure to encode the message */ if ((*encode_fct)(&xdrs,msg2encode_p) == FALSE) { TX_STATS(ROZOFS_TX_ENCODING_ERROR); errno = EPROTO; goto error; } /* ** Now get the current length and fill the header of the message */ position = XDR_GETPOS(&xdrs); /* ** add the extra_len if any */ position +=extra_len; /* ** update the length of the message : must be in network order */ *header_size_p = htonl(0x80000000 | position); /* ** set the payload length in the xmit buffer */ int total_len = sizeof(*header_size_p)+ position; ruc_buf_setPayloadLen(xmit_buf,total_len); /* ** store the receive call back and its associated parameter */ rozofs_tx_ctx_p->recv_cbk = recv_cbk; rozofs_tx_ctx_p->user_param = user_ctx_p; /* ** store the sequence number in one of the opaque user data array of the transaction */ rozofs_tx_write_opaque_data( rozofs_tx_ctx_p,0,seqnum); rozofs_tx_write_opaque_data( rozofs_tx_ctx_p,1,opaque_value_idx1); rozofs_tx_write_opaque_data( rozofs_tx_ctx_p,2,lbg_id); /* ** now send the message */ // STORCLI_STOP_NORTH_PROF_SRV((rozofs_storcli_ctx_t*)user_ctx_p,read_req,0); // FDL #ifndef TEST_STORCLI_TEST ret = north_lbg_send(lbg_id,xmit_buf); #else ret = test_north_lbg_send(lbg_id,xmit_buf); #endif if (ret < 0) { TX_STATS(ROZOFS_TX_SEND_ERROR); errno = EFAULT; goto error; } TX_STATS(ROZOFS_TX_SEND); /* ** OK, so now finish by starting the guard timer */ rozofs_tx_start_timer(rozofs_tx_ctx_p,timeout_sec); return 0; error: if (rozofs_tx_ctx_p != NULL) rozofs_tx_free_from_ptr(rozofs_tx_ctx_p); return -1; }