1 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
2 .. SPDX-License-Identifier: CC-BY-4.0
3 .. CAUTION: this document is generated from source in doc/src/rtd.
4 .. To make changes edit the source and recompile the document.
5 .. Do NOT make changes directly to .rst or .md files.
7 ============================================================================================
9 ============================================================================================
33 extern rmr_mbuf_t* rmr_call( void* vctx, rmr_mbuf_t* msg );
40 The ``rmr_call`` function sends the user application message
41 to a remote endpoint, and waits for a corresponding response
42 message before returning control to the user application. The
43 user application supplies a completed message buffer, as it
44 would for a ``rmr_send`` call, but unlike with the send, the
45 buffer returned will have the response from the application
46 that received the message.
48 Messages which are received while waiting for the response
49 are queued internally by RMR, and are returned to the user
50 application when ``rmr_rcv_msg`` is invoked. These messages
51 are returned in the order received, one per call to
58 The ``rmr_call`` function implements a timeout failsafe to
59 prevent, in most cases, the function from blocking forever.
60 The timeout period is **not** based on time (calls to clock
61 are deemed too expensive for a low latency system level
62 library), but instead the period is based on the number of
63 received messages which are not the response. Using a
64 mechanism which is not time based for *timeout* prevents the
65 async queue from filling (which would lead to message drops)
66 in an environment where there is heavy message traffic.
68 When the threshold number of messages have been queued
69 without receiving a response message, control is returned to
70 the user application and a nil pointer is returned to
71 indicate that no message was received to process. Currently
72 the threshold is fixed at 20 messages, though in future
73 versions of the library this might be extended to be a
74 parameter which the user application may set.
80 The send operations in RMR will retry *soft* send failures
81 until one of three conditions occurs:
84 * The message is sent without error
86 * The underlying transport reports a *hard* failure
88 * The maximum number of retry loops has been attempted
91 A retry loop consists of approximately 1000 send attempts
92 **without** any intervening calls to *sleep()* or *usleep().*
93 The number of retry loops defaults to 1, thus a maximum of
94 1000 send attempts is performed before returning to the user
95 application. This value can be set at any point after RMR
96 initialisation using the *rmr_set_stimeout()* function
97 allowing the user application to completely disable retires
98 (set to 0), or to increase the number of retry loops.
101 Transport Level Blocking
102 ------------------------
104 The underlying transport mechanism used to send messages is
105 configured in *non-blocking* mode. This means that if a
106 message cannot be sent immediately the transport mechanism
107 will **not** pause with the assumption that the inability to
108 send will clear quickly (within a few milliseconds). This
109 means that when the retry loop is completely disabled (set to
110 0), that the failure to accept a message for sending by the
111 underlying mechanisms (software or hardware) will be reported
112 immediately to the user application.
114 It should be noted that depending on the underlying transport
115 mechanism being used, it is extremely likely that retry
116 conditions will happen during normal operations. These are
117 completely out of RMR's control, and there is nothing that
118 RMR can do to avoid or mitigate these other than by allowing
119 RMR to retry the send operation, and even then it is possible
120 (e.g., during connection reattempts), that a single retry
121 loop is not enough to guarantee a successful send.
127 The ``rmr_call`` function returns a pointer to a message
128 buffer with the state set to reflect the overall state of
129 call processing (see Errors below). In some cases a nil
130 pointer will be returned; when this is the case only *errno*
131 will be available to describe the reason for failure.
137 These values are reflected in the state field of the returned
148 The call was successful and the message buffer references the
151 * - **RMR_ERR_CALLFAILED**
153 The call failed and the value of *errno,* as described below,
154 should be checked for the specific reason.
158 The global "variable" *errno* will be set to one of the
159 following values if the overall call processing was not
170 Too many messages were queued before receiving the expected
175 The queued message ring is full, messages were dropped
179 A parameter was not valid
183 The underlying message system was interrupted or the device
184 was busy; the message was **not** sent, and the user
185 application should call this function with the message again.
193 The following code snippet shows one way of using the
194 ``rmr_call`` function, and illustrates how the transaction ID
200 int retries_left = 5; // max retries on dev not available
201 int retry_delay = 50000; // retry delay (usec)
202 static rmr_mbuf_t* mbuf = NULL; // response msg
203 msg_t* pm; // application struct for payload
205 // get a send buffer and reference the payload
206 mbuf = rmr_alloc_msg( mr, sizeof( pm->req ) );
207 pm = (msg_t*) mbuf->payload;
209 // generate an xaction ID and fill in payload with data and msg type
210 snprintf( mbuf->xaction, RMR_MAX_XID, "%s", gen_xaction() );
211 snprintf( pm->req, sizeof( pm->req ), "{ \\"req\\": \\"num users\\"}" );
212 mbuf->mtype = MT_REQ;
214 msg = rmr_call( mr, msg );
215 if( ! msg ) { // probably a timeout and no msg received
216 return NULL; // let errno trickle up
219 if( mbuf->state != RMR_OK ) {
220 while( retries_left-- > 0 && // loop as long as eagain
222 (msg = rmr_call( mr, msg )) != NULL &&
223 mbuf->state != RMR_OK ) {
225 usleep( retry_delay );
228 if( mbuf == NULL || mbuf->state != RMR_OK ) {
229 rmr_free_msg( mbuf ); // safe if nil
234 // do something with mbuf
241 rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3),
242 rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3),
243 rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3),
244 rmr_fib(3), rmr_has_str(3), rmr_set_stimeout(3),
245 rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3)