.if false ================================================================================== Copyright (c) 2019 Nokia Copyright (c) 2018-2019 AT&T Intellectual Property. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================================================== .fi .if false Mnemonic rmr_call_man.xfm Abstract The manual page for the rmr_call function. Author E. Scott Daniels Date 28 January 2019 .fi .gv e LIB lib .im &{lib}/man/setup.im &line_len(6i) &h1(RMR Library Functions) &h2(NAME) rmr_call &h2(SYNOPSIS ) &indent &ex_start #include extern rmr_mbuf_t* rmr_call( void* vctx, rmr_mbuf_t* msg ); &ex_end &uindent &h2(DESCRIPTION) The &cw(rmr_call) function sends the user application message to a remote endpoint, and waits for a corresponding response message before returning control to the user application. The user application supplies a completed message buffer, as it would for a &cw(rmr_send) call, but unlike with the send, the buffer returned will have the response from the application that received the message. &space Messages which are received while waiting for the response are queued internally by RMR, and are returned to the user application when &cw(rmr_rcv_msg) is invoked. These messages are returned in the order received, one per call to &cw(rmr_rcv_msg.) &h3(Call Timeout) The &cw(rmr_call) function implements a timeout failsafe to prevent, in most cases, the function from blocking forever. The timeout period is &bold(not) based on time (calls to clock are deemed too expensive for a low latency system level library), but instead the period is based on the number of received messages which are not the response. Using a non-time mechanism for &ital(timeout) prevents the async queue from filling (which would lead to message drops) in an environment where there is heavy message traffic. &space When the threshold number of messages have been queued without receiving a response message, control is returned to the user application and a nil pointer is returned to indicate that no message was received to process. Currently the threshold is fixed at 20 messages, though in future versions of the library this might be extended to be a parameter which the user application may set. .** pull in common retry text .im &{lib}/man/retry.im &h2(RETURN VALUE) The &cw(rmr_call) function returns a pointer to a message buffer with the state set to reflect the overall state of call processing (see Errors below). In some cases a nil pointer will be returned; when this is the case only &ital(errno) will be available to describe the reason for failure. &h2(ERRORS) These values are reflected in the state field of the returned message. &half_space &beg_dlist(.75i : ^&bold_font ) &di(RMR_OK) The call was successful and the message buffer references the response message. &half_space &di(RMR_ERR_CALLFAILED) The call failed and the value of &ital(errno,) as described below, should be checked for the specific reason. &end_dlist &space The global "variable" &ital(errno) will be set to one of the following values if the overall call processing was not successful. &half_space &beg_dlist(.75i : ^&bold_font ) &di(ETIMEDOUT) Too many messages were queued before receiving the expected response &half_space &di(ENOBUFS) The queued message ring is full, messages were dropped &half_space &di(EINVAL) A parameter was not valid &half_space &di(EAGAIN) The underlying message system was interrupted or the device was busy; the message was &bold(not) sent, and the user application should call this function with the message again. &end_dlist &h2(EXAMPLE) The following code snippet shows one way of using the &cw(rmr_call) function, and illustrates how the transaction ID must be set. &space &ex_start int retries_left = 5; // max retries on dev not available int retry_delay = 50000; // retry delay (usec) static rmr_mbuf_t* mbuf = NULL; // response msg msg_t* pm; // application struct for payload // get a send buffer and reference the payload mbuf = rmr_alloc_msg( mr, sizeof( pm->req ) ); pm = (msg_t*) mbuf->payload; // generate an xaction ID and fill in payload with data and msg type snprintf( mbuf->xaction, RMR_MAX_XID, "%s", gen_xaction() ); snprintf( pm->req, sizeof( pm->req ), "{ \"req\": \"num users\"}" ); mbuf->mtype = MT_REQ; msg = rmr_call( mr, msg ); if( ! msg ) { // probably a timeout and no msg received return NULL; // let errno trickle up } if( mbuf->state != RMR_OK ) { while( retries_left-- > 0 && // loop as long as eagain errno == EAGAIN && (msg = rmr_call( mr, msg )) != NULL && mbuf->state != RMR_OK ) { usleep( retry_delay ); } if( mbuf == NULL || mbuf->state != RMR_OK ) { rmr_free_msg( mbuf ); // safe if nil return NULL; } } // do something with mbuf &ex_end &h2(SEE ALSO ) .ju off rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3), rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_set_stimeout(3), rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3) .ju on