a9861c3405a1ef04028a168fb683567df375f566
[ric-plt/lib/rmr.git] / docs / rmr_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_call 
12 ============================================================================================ 
13  
14 RMR Library Functions 
15 ============================================================================================ 
16  
17  
18 NAME 
19 -------------------------------------------------------------------------------------------- 
20  
21 rmr_call 
22  
23 SYNOPSIS 
24 -------------------------------------------------------------------------------------------- 
25  
26  
27 :: 
28   
29  #include <rmr/rmr.h>
30  extern rmr_mbuf_t* rmr_call( void* vctx, rmr_mbuf_t* msg );
31  
32  
33  
34 DESCRIPTION 
35 -------------------------------------------------------------------------------------------- 
36  
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. 
44  
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. 
49  
50 Call Timeout 
51 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
52  
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. 
62  
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. 
70  
71 Retries 
72 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
73  
74 The send operations in RMR will retry *soft* send failures 
75 until one of three conditions occurs: 
76  
77  
78  
79 1. 
80    
81   The message is sent without error 
82    
83  
84 2. 
85    
86   The underlying transport reports a *hard* failure 
87    
88  
89 3. 
90    
91   The maximum number of retry loops has been attempted 
92  
93  
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. 
102  
103 Transport Level Blocking 
104 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
105  
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. 
115  
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. 
124  
125 RETURN VALUE 
126 -------------------------------------------------------------------------------------------- 
127  
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. 
133  
134 ERRORS 
135 -------------------------------------------------------------------------------------------- 
136  
137 These values are reflected in the state field of the returned 
138 message. 
139  
140  
141  
142 RMR_OK 
143    
144   The call was successful and the message buffer references 
145   the response message. 
146    
147  
148 RMR_ERR_CALLFAILED 
149    
150   The call failed and the value of *errno,* as described 
151   below, should be checked for the specific reason. 
152  
153  
154 The global "variable" *errno* will be set to one of the 
155 following values if the overall call processing was not 
156 successful. 
157  
158  
159  
160 ETIMEDOUT 
161    
162   Too many messages were queued before receiving the 
163   expected response 
164    
165  
166 ENOBUFS 
167    
168   The queued message ring is full, messages were dropped 
169    
170  
171 EINVAL 
172    
173   A parameter was not valid 
174    
175  
176 EAGAIN 
177    
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 
181   message again. 
182  
183  
184 EXAMPLE 
185 -------------------------------------------------------------------------------------------- 
186  
187 The following code snippet shows one way of using the 
188 rmr_call function, and illustrates how the transaction ID 
189 must be set. 
190  
191  
192 :: 
193   
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
208      }
209      if( mbuf->state != RMR_OK ) {
210          while( retries_left-- > 0 &&             // loop as long as eagain
211                 errno == EAGAIN &&
212                 (msg = rmr_call( mr, msg )) != NULL &&
213                 mbuf->state != RMR_OK ) {
214              usleep( retry_delay );
215          }
216          if( mbuf == NULL || mbuf->state != RMR_OK ) {
217              rmr_free_msg( mbuf );        // safe if nil
218              return NULL;
219          }
220      }
221      // do something with mbuf
222  
223  
224  
225 SEE ALSO 
226 -------------------------------------------------------------------------------------------- 
227  
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)