2 ==================================================================================
3 Copyright (c) 2019 Nokia
4 Copyright (c) 2018-2019 AT&T Intellectual Property.
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 ==================================================================================
22 Mnemonic rmr_call_man.xfm
23 Abstract The manual page for the rmr_call function.
24 Author E. Scott Daniels
28 .** if formatting with tfm, the roff.im will cause roff output to be generated
29 .** if formatting with pfm, then pretty postscript will be generated
32 .im &{lib}/generic_ps.im
34 .gv e OUTPUT_RST use_rst
44 &h1(RMR Library Functions)
53 extern rmr_mbuf_t* rmr_call( void* vctx, rmr_mbuf_t* msg );
58 The &cw(rmr_call) function sends the user application message to a remote
59 endpoint, and waits for a corresponding response message before returning
60 control to the user application.
61 The user application supplies a completed message buffer, as it would for
62 a &cw(rmr_send) call, but unlike with the send, the buffer returned will have
63 the response from the application that received the message.
66 Messages which are received while waiting for the response are queued internally
67 by RMR, and are returned to the user application when &cw(rmr_rcv_msg) is
69 These messages are returned in th order received, one per call to &cw(rmr_rcv_msg.)
72 The &cw(rmr_call) function implements a timeout failsafe to prevent, in most cases, the
73 function from blocking forever.
74 The timeout period is &bold(not) based on time (calls to clock are deemed too expensive
75 for a low latency system level library, but instead the period is based on the number of
76 received messages which are not the response.
77 Using a non-time mechanism for &ital(timeout) prevents the async queue from filling
78 (which would lead to message drops) in an environment where there is heavy message traffic.
81 When the threshold number of messages have been queued without receiving a response message,
82 control is returned to the user application and a NULL pointer is returned to indicate that
83 no message was received to process.
84 Currently the threshold is fixed at 20 messages, though in future versions of the library
85 this might be extended to be a parameter which the user application may set.
88 The &cw(rmr_call) function returns a pointer to a message buffer with the state set to reflect
89 the overall state of call processing (see Errors below).
90 In some cases a NULL pointer will be returned; when this is the case only &ital(errno)
91 will be available to describe the reason for failure.
94 These values are reflected in the state field of the returned message.
97 &beg_dlist(.75i : ^&bold_font )
98 &di(RMR_OK) The call was successful and the message buffer references the response message.
100 &di(RMR_ERR_CALLFAILED) The call failed and the value of &ital(errno,) as described below,
101 should be checked for the specific reason.
105 The global "variable" &ital(errno) will be set to one of the following values if the
106 overall call processing was not successful.
109 &beg_dlist(.75i : ^&bold_font )
110 &di(ETIMEDOUT) Too many messages were queued before receiving the expected response
112 &di(ENOBUFS) The queued message ring is full, messages were dropped
114 &di(EINVAL) A parameter was not valid
116 &di(EAGAIN) The underlying message system wsa interrupted or the device was busy;
117 the message was &bold(not) sent, and user application should call
118 this function with the message again.
122 The following code bit shows one way of using the &cw(rmr_call) function, and illustrates
123 how the transaction ID must be set.
127 int retries_left = 5; // max retries on dev not available
128 int retry_delay = 50000; // retry delay (usec)
129 static rmr_mbuf_t* mbuf = NULL; // response msg
130 msg_t* pm; // private message (payload)
132 // get a send buffer and reference the payload
133 mbuf = rmr_alloc_msg( mr, RMR_MAX_RCV_BYTES );
134 pm = (msg_t*) mbuf->payload;
136 // generate an xaction ID and fill in payload with data and msg type
137 snprintf( mbuf->xaction, RMR_MAX_XID, "%s", gen_xaction() );
138 snprintf( pm->req, sizeof( pm->req ), "{ \"req\": \"num users\"}" );
139 mbuf->mtype = MT_REQ;
141 msg = rmr_call( mr, msg );
142 if( ! msg ) { // probably a timeout and no msg received
143 return NULL; // let errno trickle up
146 if( mbuf->state != RMR_OK ) {
147 while( retries_left-- > 0 && // loop as long as eagain
149 (msg = rmr_call( mr, msg )) != NULL &&
150 mbuf->state != RMR_OK ) {
152 usleep( retry_delay );
155 if( mbuf == NULL || mbuf->state != RMR_OK ) {
156 rmr_free_msg( mbuf ); // safe if nil
161 // do something with mbuf