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; }