E. Scott Daniels | 117030c | 2020-04-10 17:17:02 -0400 | [diff] [blame^] | 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_send_msg |
| 12 | ============================================================================================ |
| 13 | |
| 14 | RMR Library Functions |
| 15 | ============================================================================================ |
| 16 | |
| 17 | |
| 18 | NAME |
| 19 | -------------------------------------------------------------------------------------------- |
| 20 | |
| 21 | rmr_send_msg |
| 22 | |
| 23 | SYNOPSIS |
| 24 | -------------------------------------------------------------------------------------------- |
| 25 | |
| 26 | |
| 27 | :: |
| 28 | |
| 29 | #include <rmr/rmr.h> |
| 30 | rmr_mbuf_t* rmr_send_msg( void* vctx, rmr_mbuf_t* msg ); |
| 31 | |
| 32 | |
| 33 | |
| 34 | DESCRIPTION |
| 35 | -------------------------------------------------------------------------------------------- |
| 36 | |
| 37 | The rmr_send_msg function accepts a message buffer from the |
| 38 | user application and attempts to send it. The destination of |
| 39 | the message is selected based on the message type specified |
| 40 | in the message buffer, and the matching information in the |
| 41 | routing tables which are currently in use by the RMR library. |
| 42 | This may actually result in the sending of the message to |
| 43 | multiple destinations which could degrade expected overall |
| 44 | performance of the user application. (Limiting excessive |
| 45 | sending of messages is the responsibility of the |
| 46 | application(s) responsible for building the routing table |
| 47 | used by the RMR library, and not the responsibility of the |
| 48 | library.) |
| 49 | |
| 50 | Retries |
| 51 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 52 | |
| 53 | The send operations in RMR will retry *soft* send failures |
| 54 | until one of three conditions occurs: |
| 55 | |
| 56 | |
| 57 | |
| 58 | 1. |
| 59 | |
| 60 | The message is sent without error |
| 61 | |
| 62 | |
| 63 | 2. |
| 64 | |
| 65 | The underlying transport reports a *hard* failure |
| 66 | |
| 67 | |
| 68 | 3. |
| 69 | |
| 70 | The maximum number of retry loops has been attempted |
| 71 | |
| 72 | |
| 73 | A retry loop consists of approximately 1000 send attempts |
| 74 | **without** any intervening calls to *sleep()* or *usleep().* |
| 75 | The number of retry loops defaults to 1, thus a maximum of |
| 76 | 1000 send attempts is performed before returning to the user |
| 77 | application. This value can be set at any point after RMr |
| 78 | initialisation using the *rmr_set_stimeout()* function |
| 79 | allowing the user application to completely disable retires |
| 80 | (set to 0), or to increase the number of retry loops. |
| 81 | |
| 82 | Transport Level Blocking |
| 83 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 84 | |
| 85 | The underlying transport mechanism used to send messages is |
| 86 | configured in *non-blocking* mode. This means that if a |
| 87 | message cannot be sent immediately the transport mechanism |
| 88 | will **not** pause with the assumption that the inability to |
| 89 | send will clear quickly (within a few milliseconds). This |
| 90 | means that when the retry loop is completely disabled (set to |
| 91 | 0), that the failure to accept a message for sending by the |
| 92 | underlying mechanisms (software or hardware) will be reported |
| 93 | immediately to the user application. |
| 94 | |
| 95 | It should be noted that depending on the underlying transport |
| 96 | mechanism being used, it is extremely likely that retry |
| 97 | conditions will happen during normal operations. These are |
| 98 | completely out of RMR's control, and there is nothing that |
| 99 | RMR can do to avoid or mitigate these other than by allowing |
| 100 | RMR to retry the send operation, and even then it is possible |
| 101 | (e.g., during connection reattempts), that a single retry |
| 102 | loop is not enough to guarantee a successful send. |
| 103 | |
| 104 | RETURN VALUE |
| 105 | -------------------------------------------------------------------------------------------- |
| 106 | |
| 107 | On success, a new message buffer, with an empty payload, is |
| 108 | returned for the application to use for the next send. The |
| 109 | state in this buffer will reflect the overall send operation |
| 110 | state and will be RMR_OK when the send was successful. |
| 111 | |
| 112 | When the message cannot be successfully sent this function |
| 113 | will return the unsent (original) message buffer with the |
| 114 | state set to indicate the reason for failure. The value of |
| 115 | *errno* may also be set to reflect a more detailed failure |
| 116 | reason if it is known. |
| 117 | |
| 118 | In the event of extreme failure, a nil pointer is returned. |
| 119 | In this case the value of errno might be of some use, for |
| 120 | documentation, but there will be little that the user |
| 121 | application can do other than to move on. |
| 122 | |
| 123 | **CAUTION:** In some cases it is extremely likely that the |
| 124 | message returned by the send function does **not** reference |
| 125 | the same memory structure. Thus is important for the user |
| 126 | programme to capture the new pointer for future use or to be |
| 127 | passed to rmr_free(). If you are experiencing either double |
| 128 | free errors or segment faults in either rmr_free() or |
| 129 | rmr_send_msg(), ensure that the return value from this |
| 130 | function is being captured and used. |
| 131 | |
| 132 | ERRORS |
| 133 | -------------------------------------------------------------------------------------------- |
| 134 | |
| 135 | The following values may be passed back in the *state* field |
| 136 | of the returned message buffer. |
| 137 | |
| 138 | |
| 139 | |
| 140 | RMR_RETRY |
| 141 | |
| 142 | The message could not be sent, but the underlying |
| 143 | transport mechanism indicates that the failure is |
| 144 | temporary. If the send operation is tried again it might |
| 145 | be successful. |
| 146 | |
| 147 | RMR_SEND_FAILED |
| 148 | |
| 149 | The send operation was not successful and the underlying |
| 150 | transport mechanism indicates a permanent (hard) failure; |
| 151 | retrying the send is not possible. |
| 152 | |
| 153 | RMR_ERR_BADARG |
| 154 | |
| 155 | The message buffer pointer did not refer to a valid |
| 156 | message. |
| 157 | |
| 158 | RMR_ERR_NOHDR |
| 159 | |
| 160 | The header in the message buffer was not valid or |
| 161 | corrupted. |
| 162 | |
| 163 | RMR_ERR_NOENDPT |
| 164 | |
| 165 | The message type in the message buffer did not map to a |
| 166 | known endpoint. |
| 167 | |
| 168 | |
| 169 | The following values may be assigned to errno on failure. |
| 170 | |
| 171 | |
| 172 | INVAL |
| 173 | |
| 174 | Parameter(s) passed to the function were not valid, or the |
| 175 | underlying message processing environment was unable to |
| 176 | interpret the message. |
| 177 | |
| 178 | |
| 179 | ENOKEY |
| 180 | |
| 181 | The header information in the message buffer was invalid. |
| 182 | |
| 183 | |
| 184 | ENXIO |
| 185 | |
| 186 | No known endpoint for the message could be found. |
| 187 | |
| 188 | |
| 189 | EMSGSIZE |
| 190 | |
| 191 | The underlying transport refused to accept the message |
| 192 | because of a size value issue (message was not attempted |
| 193 | to be sent). |
| 194 | |
| 195 | |
| 196 | EFAULT |
| 197 | |
| 198 | The message referenced by the message buffer is corrupt |
| 199 | (nil pointer or bad internal length). |
| 200 | |
| 201 | |
| 202 | EBADF |
| 203 | |
| 204 | Internal RMR error; information provided to the message |
| 205 | transport environment was not valid. |
| 206 | |
| 207 | |
| 208 | ENOTSUP |
| 209 | |
| 210 | Sending was not supported by the underlying message |
| 211 | transport. |
| 212 | |
| 213 | |
| 214 | EFSM |
| 215 | |
| 216 | The device is not in a state that can accept the message. |
| 217 | |
| 218 | |
| 219 | EAGAIN |
| 220 | |
| 221 | The device is not able to accept a message for sending. |
| 222 | The user application should attempt to resend. |
| 223 | |
| 224 | |
| 225 | EINTR |
| 226 | |
| 227 | The operation was interrupted by delivery of a signal |
| 228 | before the message was sent. |
| 229 | |
| 230 | |
| 231 | ETIMEDOUT |
| 232 | |
| 233 | The underlying message environment timed out during the |
| 234 | send process. |
| 235 | |
| 236 | |
| 237 | ETERM |
| 238 | |
| 239 | The underlying message environment is in a shutdown state. |
| 240 | |
| 241 | |
| 242 | EXAMPLE |
| 243 | -------------------------------------------------------------------------------------------- |
| 244 | |
| 245 | The following is a simple example of how the rmr_send_msg |
| 246 | function is called. In this example, the send message buffer |
| 247 | is saved between calls and reused eliminating alloc/free |
| 248 | cycles. |
| 249 | |
| 250 | |
| 251 | :: |
| 252 | |
| 253 | static rmr_mbuf_t* send_msg = NULL; // message to send; reused on each call |
| 254 | msg_t* send_pm; // payload for send |
| 255 | msg_t* pm; // our message format in the received payload |
| 256 | if( send_msg == NULL ) { |
| 257 | send_msg = rmr_alloc_msg( mr, MAX_SIZE ); // new buffer to send |
| 258 | } |
| 259 | // reference payload and fill in message type |
| 260 | pm = (msg_t*) send_msg->payload; |
| 261 | send_msg->mtype = MT_ANSWER; |
| 262 | msg->len = generate_data( pm ); // something that fills the payload in |
| 263 | msg = rmr_send_msg( mr, send_msg ); // ensure new pointer used after send |
| 264 | if( ! msg ) { |
| 265 | return ERROR; |
| 266 | } else { |
| 267 | if( msg->state != RMR_OK ) { |
| 268 | // check for RMR_ERR_RETRY, and resend if needed |
| 269 | // else return error |
| 270 | } |
| 271 | } |
| 272 | return OK; |
| 273 | |
| 274 | |
| 275 | |
| 276 | SEE ALSO |
| 277 | -------------------------------------------------------------------------------------------- |
| 278 | |
| 279 | rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), |
| 280 | rmr_payload_size(3), rmr_rcv_msg(3), rmr_rcv_specific(3), |
| 281 | rmr_rts_msg(3), rmr_ready(3), rmr_mk_ring(3), |
| 282 | rmr_ring_free(3), rmr_torcv_rcv(3), rmr_wh_send_msg(3) |