Correct man page formatting in RST output
[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)