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_call( void* vctx, rmr_mbuf_t* msg );
35 --------------------------------------------------------------------------------------------
37 The rmr_call function sends the user application message to a
38 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 call, but unlike with the send, the
42 buffer returned will have the response from the application
43 that received the message.
45 Messages which are received while waiting for the response
46 are queued internally by RMR, and are returned to the user
47 application when rmr_rcv_msg is invoked. These messages are
48 returned in the order received, one per call to rmr_rcv_msg.
51 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53 The rmr_call function implements a timeout failsafe to
54 prevent, in most cases, the function from blocking forever.
55 The timeout period is **not** based on time (calls to clock
56 are deemed too expensive for a low latency system level
57 library), but instead the period is based on the number of
58 received messages which are not the response. Using a
59 non-time mechanism for *timeout* prevents the async queue
60 from filling (which would lead to message drops) in an
61 environment where there is heavy message traffic.
63 When the threshold number of messages have been queued
64 without receiving a response message, control is returned to
65 the user application and a nil pointer is returned to
66 indicate that no message was received to process. Currently
67 the threshold is fixed at 20 messages, though in future
68 versions of the library this might be extended to be a
69 parameter which the user application may set.
72 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74 The send operations in RMR will retry *soft* send failures
75 until one of three conditions occurs:
81 The message is sent without error
86 The underlying transport reports a *hard* failure
91 The maximum number of retry loops has been attempted
94 A retry loop consists of approximately 1000 send attempts
95 **without** any intervening calls to *sleep()* or *usleep().*
96 The number of retry loops defaults to 1, thus a maximum of
97 1000 send attempts is performed before returning to the user
98 application. This value can be set at any point after RMR
99 initialisation using the *rmr_set_stimeout()* function
100 allowing the user application to completely disable retires
101 (set to 0), or to increase the number of retry loops.
103 Transport Level Blocking
104 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106 The underlying transport mechanism used to send messages is
107 configured in *non-blocking* mode. This means that if a
108 message cannot be sent immediately the transport mechanism
109 will **not** pause with the assumption that the inability to
110 send will clear quickly (within a few milliseconds). This
111 means that when the retry loop is completely disabled (set to
112 0), that the failure to accept a message for sending by the
113 underlying mechanisms (software or hardware) will be reported
114 immediately to the user application.
116 It should be noted that depending on the underlying transport
117 mechanism being used, it is extremely likely that retry
118 conditions will happen during normal operations. These are
119 completely out of RMR's control, and there is nothing that
120 RMR can do to avoid or mitigate these other than by allowing
121 RMR to retry the send operation, and even then it is possible
122 (e.g., during connection reattempts), that a single retry
123 loop is not enough to guarantee a successful send.
126 --------------------------------------------------------------------------------------------
128 The rmr_call function returns a pointer to a message buffer
129 with the state set to reflect the overall state of call
130 processing (see Errors below). In some cases a nil pointer
131 will be returned; when this is the case only *errno* will be
132 available to describe the reason for failure.
135 --------------------------------------------------------------------------------------------
137 These values are reflected in the state field of the returned
144 The call was successful and the message buffer references
145 the response message.
150 The call failed and the value of *errno,* as described
151 below, should be checked for the specific reason.
154 The global "variable" *errno* will be set to one of the
155 following values if the overall call processing was not
162 Too many messages were queued before receiving the
168 The queued message ring is full, messages were dropped
173 A parameter was not valid
178 The underlying message system was interrupted or the
179 device was busy; the message was **not** sent, and the
180 user application should call this function with the
185 --------------------------------------------------------------------------------------------
187 The following code snippet shows one way of using the
188 rmr_call function, and illustrates how the transaction ID
194 int retries_left = 5; // max retries on dev not available
195 int retry_delay = 50000; // retry delay (usec)
196 static rmr_mbuf_t* mbuf = NULL; // response msg
197 msg_t* pm; // application struct for payload
198 // get a send buffer and reference the payload
199 mbuf = rmr_alloc_msg( mr, sizeof( pm->req ) );
200 pm = (msg_t*) mbuf->payload;
201 // generate an xaction ID and fill in payload with data and msg type
202 snprintf( mbuf->xaction, RMR_MAX_XID, "%s", gen_xaction() );
203 snprintf( pm->req, sizeof( pm->req ), "{ \\"req\\": \\"num users\\"}" );
204 mbuf->mtype = MT_REQ;
205 msg = rmr_call( mr, msg );
206 if( ! msg ) { // probably a timeout and no msg received
207 return NULL; // let errno trickle up
209 if( mbuf->state != RMR_OK ) {
210 while( retries_left-- > 0 && // loop as long as eagain
212 (msg = rmr_call( mr, msg )) != NULL &&
213 mbuf->state != RMR_OK ) {
214 usleep( retry_delay );
216 if( mbuf == NULL || mbuf->state != RMR_OK ) {
217 rmr_free_msg( mbuf ); // safe if nil
221 // do something with mbuf
226 --------------------------------------------------------------------------------------------
228 rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3),
229 rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3),
230 rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3),
231 rmr_fib(3), rmr_has_str(3), rmr_set_stimeout(3),
232 rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3)