CI: Add silent cmake SonarCloud scan
[ric-plt/lib/rmr.git] / docs / rmr_mt_call.3.rst
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.
6
7 ============================================================================================
8 Man Page: rmr_mt_call
9 ============================================================================================
10
11
12
13
14 RMR LIBRARY FUNCTIONS
15 =====================
16
17
18
19 NAME
20 ----
21
22 rmr_mt_call
23
24
25 SYNOPSIS
26 --------
27
28
29 ::
30
31   #include <rmr/rmr.h>
32
33   extern rmr_mbuf_t* rmr_mt_call( void* vctx, rmr_mbuf_t* msg, int id, int timeout );
34
35
36
37 DESCRIPTION
38 -----------
39
40 The ``rmr_mt_call`` function sends the user application
41 message to a remote endpoint, and waits for a corresponding
42 response message before returning control to the user
43 application. The user application supplies a completed
44 message buffer, as it would for a ``rmr_send_msg`` call, but
45 unlike with a send, the buffer returned will have the
46 response from the application that received the message. The
47 thread invoking the *rmr_mt_call()* will block until a
48 message arrives or until *timeout* milliseconds has passed;
49 which ever comes first. Using a timeout value of zero (0)
50 will cause the thread to block without a timeout.
51
52 The *id* supplied as the third parameter is an integer in the
53 range of 2 through 255 inclusive. This is a caller defined
54 "thread number" and is used to match the response message
55 with the correct user application thread. If the ID value is
56 not in the proper range, the attempt to make the call will
57 fail.
58
59 Messages which are received while waiting for the response
60 are queued on a *normal* receive queue and will be delivered
61 to the user application with the next invocation of
62 *rmr_mt_rcv()* or *rmr_rvv_msg().* by RMR, and are returned
63 to the user application when ``rmr_rcv_msg`` is invoked.
64 These messages are returned in the order received, one per
65 call to ``rmr_rcv_msg.``
66
67
68 The Transaction ID
69 ------------------
70
71 The user application is responsible for setting the value of
72 the transaction ID field before invoking *rmr_mt_call.* The
73 transaction ID is a ``RMR_MAX_XID`` byte field that is used
74 to match the response message when it arrives. RMR will
75 compare **all** of the bytes in the field, so the caller must
76 ensure that they are set correctly to avoid missing the
77 response message. The application which returns the response
78 message is also expected to ensure that the return buffer has
79 the matching transaction ID. This can be done transparently
80 if the application uses the *rmr_rts_msg()* function and does
81 not adjust the transaction ID.
82
83
84 Retries
85 -------
86
87 The send operations in RMR will retry *soft* send failures
88 until one of three conditions occurs:
89
90
91 * The message is sent without error
92
93 * The underlying transport reports a *hard* failure
94
95 * The maximum number of retry loops has been attempted
96
97
98 A retry loop consists of approximately 1000 send attempts
99 **without** any intervening calls to *sleep()* or *usleep().*
100 The number of retry loops defaults to 1, thus a maximum of
101 1000 send attempts is performed before returning to the user
102 application. This value can be set at any point after RMR
103 initialisation using the *rmr_set_stimeout()* function
104 allowing the user application to completely disable retires
105 (set to 0), or to increase the number of retry loops.
106
107
108 Transport Level Blocking
109 ------------------------
110
111 The underlying transport mechanism used to send messages is
112 configured in *non-blocking* mode. This means that if a
113 message cannot be sent immediately the transport mechanism
114 will **not** pause with the assumption that the inability to
115 send will clear quickly (within a few milliseconds). This
116 means that when the retry loop is completely disabled (set to
117 0), that the failure to accept a message for sending by the
118 underlying mechanisms (software or hardware) will be reported
119 immediately to the user application.
120
121 It should be noted that depending on the underlying transport
122 mechanism being used, it is extremely likely that retry
123 conditions will happen during normal operations. These are
124 completely out of RMR's control, and there is nothing that
125 RMR can do to avoid or mitigate these other than by allowing
126 RMR to retry the send operation, and even then it is possible
127 (e.g., during connection reattempts), that a single retry
128 loop is not enough to guarantee a successful send.
129
130
131 RETURN VALUE
132 ------------
133
134 The ``rmr_mt_call`` function returns a pointer to a message
135 buffer with the state set to reflect the overall state of
136 call processing. If the state is ``RMR_OK`` then the buffer
137 contains the response message; otherwise the state indicates
138 the error encountered while attempting to send the message.
139
140 If no response message is received when the timeout period
141 has expired, a nil pointer will be returned (NULL).
142
143
144 ERRORS
145 ------
146
147 These values are reflected in the state field of the returned
148 message.
149
150
151     .. list-table::
152       :widths: auto
153       :header-rows: 0
154       :class: borderless
155
156       * - **RMR_OK**
157         -
158           The call was successful and the message buffer references the
159           response message.
160
161       * - **RMR_ERR_BADARG**
162         -
163           An argument passed to the function was invalid.
164
165       * - **RMR_ERR_CALLFAILED**
166         -
167           The call failed and the value of *errno,* as described below,
168           should be checked for the specific reason.
169
170       * - **RMR_ERR_NOENDPT**
171         -
172           An endpoint associated with the message type could not be
173           found in the route table.
174
175       * - **RMR_ERR_RETRY**
176         -
177           The underlying transport mechanism was unable to accept the
178           message for sending. The user application can retry the call
179           operation if appropriate to do so.
180
181
182
183 The global "variable" *errno* will be set to one of the
184 following values if the overall call processing was not
185 successful.
186
187
188     .. list-table::
189       :widths: auto
190       :header-rows: 0
191       :class: borderless
192
193       * - **ETIMEDOUT**
194         -
195           Too many messages were queued before receiving the expected
196           response
197
198       * - **ENOBUFS**
199         -
200           The queued message ring is full, messages were dropped
201
202       * - **EINVAL**
203         -
204           A parameter was not valid
205
206       * - **EAGAIN**
207         -
208           The underlying message system wsa interrupted or the device
209           was busy; the message was **not** sent, and user application
210           should call this function with the message again.
211
212
213
214
215 EXAMPLE
216 -------
217
218 The following code bit shows one way of using the
219 ``rmr_mt_call`` function, and illustrates how the transaction
220 ID must be set.
221
222
223 ::
224
225       int retries_left = 5;               // max retries on dev not available
226       static rmr_mbuf_t*  mbuf = NULL;    // response msg
227       msg_t*  pm;                         // appl message struct (payload)
228
229       // get a send buffer and reference the payload
230       mbuf = rmr_alloc_msg( mr, sizeof( pm->req ) );
231       pm = (msg_t*) mbuf->payload;
232
233       // generate an xaction ID and fill in payload with data and msg type
234       rmr_bytes2xact( mbuf, xid, RMR_MAX_XID );
235       snprintf( pm->req, sizeof( pm->req ), "{ \\"req\\": \\"num users\\"}" );
236       mbuf->mtype = MT_USR_RESP;
237
238       msg = rmr_mt_call( mr, msg, my_id, 100 );        // wait up to 100ms
239       if( ! msg ) {               // probably a timeout and no msg received
240           return NULL;            // let errno trickle up
241       }
242
243       if( mbuf->state != RMR_OK ) {
244           while( retries_left-- > 0 &&             // loop as long as eagain
245                  mbuf->state == RMR_ERR_RETRY &&
246                  (msg = rmr_mt_call( mr, msg )) != NULL &&
247                  mbuf->state != RMR_OK ) {
248
249               usleep( retry_delay );
250           }
251
252           if( mbuf == NULL || mbuf->state != RMR_OK ) {
253               rmr_free_msg( mbuf );        // safe if nil
254               return NULL;
255           }
256       }
257
258       // do something with mbuf
259
260
261
262 SEE ALSO
263 --------
264
265 rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3),
266 rmr_mt_rcv(3), rmr_payload_size(3), rmr_send_msg(3),
267 rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3),
268 rmr_ready(3), rmr_fib(3), rmr_has_str(3),
269 rmr_set_stimeout(3), rmr_tokenise(3), rmr_mk_ring(3),
270 rmr_ring_free(3)