Add safe connect, fix possible seg fault in RTC
[ric-plt/lib/rmr.git] / docs / rmr_mt_call.3.rst
1  
2  
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. 
8  
9  
10 ============================================================================================ 
11 Man Page: rmr_mt_call 
12 ============================================================================================ 
13  
14 RMR Library Functions 
15 ============================================================================================ 
16  
17  
18 NAME 
19 -------------------------------------------------------------------------------------------- 
20  
21 rmr_mt_call 
22  
23 SYNOPSIS 
24 -------------------------------------------------------------------------------------------- 
25  
26  
27 :: 
28   
29  #include <rmr/rmr.h>
30  extern rmr_mbuf_t* rmr_mt_call( void* vctx, rmr_mbuf_t* msg, int id, int timeout );
31  
32  
33  
34 DESCRIPTION 
35 -------------------------------------------------------------------------------------------- 
36  
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. 
48  
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 
54 fail. 
55  
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 
62 rmr_rcv_msg. 
63  
64 The Transaction ID 
65 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
66  
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. 
78  
79 Retries 
80 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
81  
82 The send operations in RMR will retry *soft* send failures 
83 until one of three conditions occurs: 
84  
85  
86  
87 1. 
88    
89   The message is sent without error 
90    
91  
92 2. 
93    
94   The underlying transport reports a *hard* failure 
95    
96  
97 3. 
98    
99   The maximum number of retry loops has been attempted 
100  
101  
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. 
110  
111 Transport Level Blocking 
112 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
113  
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. 
123  
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. 
132  
133 RETURN VALUE 
134 -------------------------------------------------------------------------------------------- 
135  
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. 
141  
142 If no response message is received when the timeout period 
143 has expired, a nil pointer will be returned (NULL). 
144  
145 ERRORS 
146 -------------------------------------------------------------------------------------------- 
147  
148 These values are reflected in the state field of the returned 
149 message. 
150  
151  
152  
153 RMR_OK 
154    
155   The call was successful and the message buffer references 
156   the response message. 
157    
158  
159 RMR_ERR_BADARG 
160    
161   An argument passed to the function was invalid. 
162    
163  
164 RMR_ERR_CALLFAILED 
165    
166   The call failed and the value of *errno,* as described 
167   below, should be checked for the specific reason. 
168    
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  
176 RMR_ERR_RETRY 
177    
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. 
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  
189 ETIMEDOUT 
190    
191   Too many messages were queued before receiving the 
192   expected response 
193    
194  
195 ENOBUFS 
196    
197   The queued message ring is full, messages were dropped 
198    
199  
200 EINVAL 
201    
202   A parameter was not valid 
203    
204  
205 EAGAIN 
206    
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 
210   again. 
211  
212  
213 EXAMPLE 
214 -------------------------------------------------------------------------------------------- 
215  
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. 
218  
219  
220 :: 
221   
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
235      }
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 );
242          }
243          if( mbuf == NULL || mbuf->state != RMR_OK ) {
244              rmr_free_msg( mbuf );        // safe if nil
245              return NULL;
246          }
247      }
248      // do something with mbuf
249  
250  
251  
252 SEE ALSO 
253 -------------------------------------------------------------------------------------------- 
254  
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), 
260 rmr_ring_free(3)