Add root level docs control files
[ric-plt/lib/rmr.git] / doc / src / man / rmr_mt_call.3.xfm
1 .if false
2 ==================================================================================
3         Copyright (c) 2019 Nokia 
4         Copyright (c) 2018-2019 AT&T Intellectual Property.
5
6    Licensed under the Apache License, Version 2.0 (the "License");
7    you may not use this file except in compliance with the License.
8    You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17 ==================================================================================
18 .fi
19
20
21 .if false
22         Mnemonic        rmr_mt_call_man.xfm
23         Abstract        The manual page for the rmr multi-threaded call function.
24         Author          E. Scott Daniels
25         Date            24 May 2019
26 .fi
27
28 .gv e LIB lib
29 .im &{lib}/man/setup.im 
30
31 &line_len(6i)
32
33 &h1(RMR Library Functions)
34 &h2(NAME)
35         rmr_mt_call
36
37 &h2(SYNOPSIS )
38 &indent
39 &ex_start
40 #include <rmr/rmr.h>
41
42 extern rmr_mbuf_t* rmr_mt_call( void* vctx, rmr_mbuf_t* msg, int id, int timeout );
43 &ex_end
44 &uindent
45
46 &h2(DESCRIPTION)
47 The &cw(rmr_mt_call) function sends the user application message to a remote
48 endpoint, and waits for a corresponding response message before returning
49 control to the user application.
50 The user application supplies a completed message buffer, as it would for
51 a &cw(rmr_send_msg) call, but unlike with a send, the buffer returned will have
52 the response from the application that received the message.
53 The thread invoking the &ital(rmr_mt_call())  will block until a message arrives
54 or until &ital(timeout) milliseconds has passed; which ever comes first.  
55 Using a timeout value of zero (0) will cause the thread to block without a timeout.
56
57 &space
58 The &ital(id) supplied as the third parameter is an integer in the range of 2 through
59 255 inclusive. 
60 This is a caller defined "thread number" and is used to match the response message
61 with the correct user application thread.
62 If the ID value is not in the proper range, the attempt to make the call will fail.
63
64 &space
65 Messages which are received while waiting for the response are queued on a &ital(normal)
66 receive queue and will be delivered to the user application with the next invocation 
67 of &ital(rmr_mt_rcv()) or &ital(rmr_rvv_msg().) 
68 by RMR, and are returned to the user application when &cw(rmr_rcv_msg) is 
69 invoked.
70 These messages are returned in th order received, one per call to &cw(rmr_rcv_msg.)
71
72 &space
73 NOTE: Currently the multi-threaded functions are supported only when the NNG 
74 transport mechanism is being used. It will not be possible to link a programme
75 using the Nanomsg version of the library when references to this function are
76 present.
77
78 &h3(The Transaction ID)
79 The user application is responsible for setting the value of the transaction ID field
80 before invoking &ital(rmr_mt_call.)  
81 The transaction ID is a &cw(RMR_MAX_XID) byte field that is used to match the 
82 response message when it arrives. 
83 RMr will compare &bold(all) of the bytes in the field, so the caller must ensure
84 that they are set correctly to avoid missing the response message. 
85 (The application which returns the response message is also expected to ensure that
86 the return buffer has the matching transaction ID. This can be done transparently if
87 the application uses the &ital(rmr_rts_msg()) function and does not adjust the 
88 transaction ID.
89
90 .** pull in common retry text
91 .im &{lib}/man/retry.im 
92
93 &h2(RETURN VALUE)
94 The &cw(rmr_mt_call) function returns a pointer to a message buffer with the state set to reflect
95 the overall state of call processing.
96 If the state is &cw(RMR_OK) then the buffer contains the response message; otherwise
97 the state indicates the error encountered while attempting to send the message.
98
99 &space
100 If no response message is received when the timeout period has expired, a nil pointer
101 will be returned (NULL).  
102
103 &h2(ERRORS)
104 These values are reflected in the state field of the returned message. 
105
106 &half_space
107 &beg_dlist(.75i : ^&bold_font )
108 &di(RMR_OK) The call was successful and the message buffer references the response message.
109
110 &half_space
111 &di(RMR_ERR_BADARG) An argument passed to the function was invalid.
112
113 &half_space
114 &di(RMR_ERR_CALLFAILED) The call failed and the value of &ital(errno,) as described below, 
115         should be checked for the specific reason.
116
117 &half_space
118 &di(RMR_ERR_NOENDPT) An endpoint associated with the message type could not be found in the
119         route table.
120
121 &half_space
122 &di(RMR_ERR_RETRY) The underlying transport mechanism was unable to accept the message
123         for sending. The user application can retry the call operation if appropriate to
124         do so.
125
126 &end_dlist
127
128 &space
129 The global "variable" &ital(errno) will be set to one of the following values if the 
130 overall call processing was not successful. 
131 &half_space
132
133 &beg_dlist(.75i : ^&bold_font )
134 &di(ETIMEDOUT) Too many messages were queued before receiving the expected response
135
136 &half_space
137 &di(ENOBUFS)   The queued message ring is full, messages were dropped
138
139 &half_space
140 &di(EINVAL)     A parameter was not valid
141
142 &half_space
143 &di(EAGAIN)    The underlying message system wsa interrupted or the device was busy;
144         the message was &bold(not) sent, and user application should call 
145         this function with the message again.
146 &end_dlist
147
148 &h2(EXAMPLE)
149 The following code bit shows one way of using the &cw(rmr_mt_call) function, and illustrates
150 how the transaction ID must be set.
151
152 &space
153 &ex_start
154     int retries_left = 5;               // max retries on dev not available
155     static rmr_mbuf_t*  mbuf = NULL;    // response msg
156     msg_t*  pm;                         // private message (payload)
157
158         // get a send buffer and reference the payload 
159     mbuf = rmr_alloc_msg( mr, RMR_MAX_RCV_BYTES );
160     pm = (msg_t*) mbuf->payload;
161
162         // generate an xaction ID and fill in payload with data and msg type
163     rmr_bytes2xact( mbuf, xid, RMR_MAX_XID );
164     snprintf( pm->req, sizeof( pm->req ), "{ \"req\": \"num users\"}" );
165     mbuf->mtype = MT_USR_RESP;
166     
167     msg = rmr_mt_call( mr, msg, my_id, 100 );           // wait up to 100ms
168     if( ! msg ) {               // probably a timeout and no msg received
169         return NULL;            // let errno trickle up
170     } 
171
172     if( mbuf->state != RMR_OK ) {
173         while( retries_left-- > 0 &&             // loop as long as eagain
174                mbuf->state == RMR_ERR_RETRY && 
175                (msg = rmr_mt_call( mr, msg )) != NULL && 
176                mbuf->state != RMR_OK ) {
177
178             usleep( retry_delay );
179         }
180     
181         if( mbuf == NULL || mbuf->state != RMR_OK ) {
182             rmr_free_msg( mbuf );        // safe if nil
183             return NULL;
184         }
185     }
186
187     // do something with mbuf
188 &ex_end
189
190
191 &h2(SEE ALSO )
192 .ju off
193 rmr_alloc_msg(3),
194 rmr_free_msg(3),
195 rmr_init(3),
196 rmr_mt_rcv(3),
197 rmr_payload_size(3),
198 rmr_send_msg(3),
199 rmr_rcv_msg(3),
200 rmr_rcv_specific(3),
201 rmr_rts_msg(3),
202 rmr_ready(3),
203 rmr_fib(3),
204 rmr_has_str(3),
205 rmr_set_stimeout(3),
206 rmr_tokenise(3),
207 rmr_mk_ring(3),
208 rmr_ring_free(3)
209 .ju on
210