3 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
4 .. SPDX-License-Identifier: CC-BY-4.0
5 .. CAUTION: this document is generated from source in doc/src/rtd.
6 .. To make changes edit the source and recompile the document.
7 .. Do NOT make changes directly to .rst or .md files.
10 ============================================================================================
12 ============================================================================================
15 ============================================================================================
19 --------------------------------------------------------------------------------------------
24 --------------------------------------------------------------------------------------------
30 extern rmr_mbuf_t* rmr_mt_call( void* vctx, rmr_mbuf_t* msg, int id, int timeout );
35 --------------------------------------------------------------------------------------------
37 The rmr_mt_call function sends the user application message
38 to a remote endpoint, and waits for a corresponding response
39 message before returning control to the user application. The
40 user application supplies a completed message buffer, as it
41 would for a rmr_send_msg call, but unlike with a send, the
42 buffer returned will have the response from the application
43 that received the message. The thread invoking the
44 *rmr_mt_call()* will block until a message arrives or until
45 *timeout* milliseconds has passed; which ever comes first.
46 Using a timeout value of zero (0) will cause the thread to
47 block without a timeout.
49 The *id* supplied as the third parameter is an integer in the
50 range of 2 through 255 inclusive. This is a caller defined
51 "thread number" and is used to match the response message
52 with the correct user application thread. If the ID value is
53 not in the proper range, the attempt to make the call will
56 Messages which are received while waiting for the response
57 are queued on a *normal* receive queue and will be delivered
58 to the user application with the next invocation of
59 *rmr_mt_rcv()* or *rmr_rvv_msg().* by RMR, and are returned
60 to the user application when rmr_rcv_msg is invoked. These
61 messages are returned in the order received, one per call to
65 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67 The user application is responsible for setting the value of
68 the transaction ID field before invoking *rmr_mt_call.* The
69 transaction ID is a RMR_MAX_XID byte field that is used to
70 match the response message when it arrives. RMR will compare
71 **all** of the bytes in the field, so the caller must ensure
72 that they are set correctly to avoid missing the response
73 message. The application which returns the response message
74 is also expected to ensure that the return buffer has the
75 matching transaction ID. This can be done transparently if
76 the application uses the *rmr_rts_msg()* function and does
77 not adjust the transaction ID.
80 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
82 The send operations in RMR will retry *soft* send failures
83 until one of three conditions occurs:
89 The message is sent without error
94 The underlying transport reports a *hard* failure
99 The maximum number of retry loops has been attempted
102 A retry loop consists of approximately 1000 send attempts
103 **without** any intervening calls to *sleep()* or *usleep().*
104 The number of retry loops defaults to 1, thus a maximum of
105 1000 send attempts is performed before returning to the user
106 application. This value can be set at any point after RMR
107 initialisation using the *rmr_set_stimeout()* function
108 allowing the user application to completely disable retires
109 (set to 0), or to increase the number of retry loops.
111 Transport Level Blocking
112 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
114 The underlying transport mechanism used to send messages is
115 configured in *non-blocking* mode. This means that if a
116 message cannot be sent immediately the transport mechanism
117 will **not** pause with the assumption that the inability to
118 send will clear quickly (within a few milliseconds). This
119 means that when the retry loop is completely disabled (set to
120 0), that the failure to accept a message for sending by the
121 underlying mechanisms (software or hardware) will be reported
122 immediately to the user application.
124 It should be noted that depending on the underlying transport
125 mechanism being used, it is extremely likely that retry
126 conditions will happen during normal operations. These are
127 completely out of RMR's control, and there is nothing that
128 RMR can do to avoid or mitigate these other than by allowing
129 RMR to retry the send operation, and even then it is possible
130 (e.g., during connection reattempts), that a single retry
131 loop is not enough to guarantee a successful send.
134 --------------------------------------------------------------------------------------------
136 The rmr_mt_call function returns a pointer to a message
137 buffer with the state set to reflect the overall state of
138 call processing. If the state is RMR_OK then the buffer
139 contains the response message; otherwise the state indicates
140 the error encountered while attempting to send the message.
142 If no response message is received when the timeout period
143 has expired, a nil pointer will be returned (NULL).
146 --------------------------------------------------------------------------------------------
148 These values are reflected in the state field of the returned
155 The call was successful and the message buffer references
156 the response message.
161 An argument passed to the function was invalid.
166 The call failed and the value of *errno,* as described
167 below, should be checked for the specific reason.
172 An endpoint associated with the message type could not be
173 found in the route table.
178 The underlying transport mechanism was unable to accept
179 the message for sending. The user application can retry
180 the call operation if appropriate to do so.
183 The global "variable" *errno* will be set to one of the
184 following values if the overall call processing was not
191 Too many messages were queued before receiving the
197 The queued message ring is full, messages were dropped
202 A parameter was not valid
207 The underlying message system wsa interrupted or the
208 device was busy; the message was **not** sent, and user
209 application should call this function with the message
214 --------------------------------------------------------------------------------------------
216 The following code bit shows one way of using the rmr_mt_call
217 function, and illustrates how the transaction ID must be set.
222 int retries_left = 5; // max retries on dev not available
223 static rmr_mbuf_t* mbuf = NULL; // response msg
224 msg_t* pm; // appl message struct (payload)
225 // get a send buffer and reference the payload
226 mbuf = rmr_alloc_msg( mr, sizeof( pm->req ) );
227 pm = (msg_t*) mbuf->payload;
228 // generate an xaction ID and fill in payload with data and msg type
229 rmr_bytes2xact( mbuf, xid, RMR_MAX_XID );
230 snprintf( pm->req, sizeof( pm->req ), "{ \\"req\\": \\"num users\\"}" );
231 mbuf->mtype = MT_USR_RESP;
232 msg = rmr_mt_call( mr, msg, my_id, 100 ); // wait up to 100ms
233 if( ! msg ) { // probably a timeout and no msg received
234 return NULL; // let errno trickle up
236 if( mbuf->state != RMR_OK ) {
237 while( retries_left-- > 0 && // loop as long as eagain
238 mbuf->state == RMR_ERR_RETRY &&
239 (msg = rmr_mt_call( mr, msg )) != NULL &&
240 mbuf->state != RMR_OK ) {
241 usleep( retry_delay );
243 if( mbuf == NULL || mbuf->state != RMR_OK ) {
244 rmr_free_msg( mbuf ); // safe if nil
248 // do something with mbuf
253 --------------------------------------------------------------------------------------------
255 rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3),
256 rmr_mt_rcv(3), rmr_payload_size(3), rmr_send_msg(3),
257 rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3),
258 rmr_ready(3), rmr_fib(3), rmr_has_str(3),
259 rmr_set_stimeout(3), rmr_tokenise(3), rmr_mk_ring(3),