.. This work is licensed under a Creative Commons Attribution 4.0 International License. | |
.. SPDX-License-Identifier: CC-BY-4.0 | |
.. CAUTION: this document is generated from source in doc/src/rtd. | |
.. To make changes edit the source and recompile the document. | |
.. Do NOT make changes directly to .rst or .md files. | |
RMR User's Guide | |
============================================================================================ | |
The RIC Message Router (RMR) is a library for peer-to-peer | |
communication. Applications use the library to send and | |
receive messages where the message routing and endpoint | |
selection is based on the message type rather than DNS host | |
name-IP port combinations. | |
This document contains information that developers need to | |
know to use the RMR library. Because the primary | |
documentation for the RMR library is a collection of UNIX | |
manpages (included in the development package, and available | |
via the man command when installed), there is no separate | |
"User's Guide." To provide something for the document | |
scrapers to find, this is a collection of the RMR manual | |
pages formatted directly from their source, which might be a | |
bit ragged when combined into a single markup document. Read | |
the manual pages :) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_alloc_msg( void* ctx, int size ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_alloc_msg function is used to allocate a buffer which | |
the user programme can write into and then send through the | |
RMR library. The buffer is allocated such that sending it | |
requires no additional copying out of the buffer. If the | |
value passed in size is less than or equal to 0, then the | |
*normal maximum size* supplied on the *rmr_init* call will be | |
used. When *size* is greater than zero, the message allocated | |
will have at least the indicated number of bytes in the | |
payload. There is no maximum size imposed by RMR, however the | |
underlying system memory managerment (e.g. malloc) functions | |
may impose a limit. | |
The *ctx* parameter is the void context pointer that was | |
returned by the *rmr_init* function. | |
The pointer to the message buffer returned is a structure | |
which has some user application visible fields; the structure | |
is described in rmr.h, and is illustrated below. | |
:: | |
typedef struct { | |
int state; | |
int mtype; | |
int len; | |
unsigned char* payload; | |
unsigned char* xaction; | |
int sub_id; | |
int tp_state; | |
} rmr_mbuf_t; | |
state | |
Is the current buffer state. Following a call to | |
rmr_send_msg the state indicates whether the buffer was | |
successfully sent which determines exactly what the | |
payload points to. If the send failed, the payload | |
referenced by the buffer is the message that failed to | |
send (allowing the application to attempt a | |
retransmission). When the state is RMR_OK the buffer | |
represents an empty buffer that the application may fill | |
in in preparation to send. | |
mtype | |
When sending a message, the application is expected to set | |
this field to the appropriate message type value (as | |
determined by the user programme). Upon send this value | |
determines how the RMR library will route the message. For | |
a buffer which has been received, this field will contain | |
the message type that was set by the sending application. | |
len | |
The application using a buffer to send a message is | |
expected to set the length value to the actual number of | |
bytes that it placed into the message. This is likely less | |
than the total number of bytes that the message can carry. | |
For a message buffer that is passed to the application as | |
the result of a receive call, this will be the value that | |
the sending application supplied and should indicate the | |
number of bytes in the payload which are valid. | |
payload | |
The payload is a pointer to the actual received data. The | |
user programme may read and write from/to the memory | |
referenced by the payload up until the point in time that | |
the buffer is used on a rmr_send, rmr_call or rmr_reply | |
function call. Once the buffer has been passed back to a | |
RMR library function the user programme should **NOT** | |
make use of the payload pointer. | |
xaction | |
The *xaction* field is a pointer to a fixed sized area in | |
the message into which the user may write a transaction | |
ID. The ID is optional with the exception of when the user | |
application uses the rmr_call function to send a message | |
and wait for the reply; the underlying RMR processing | |
expects that the matching reply message will also contain | |
the same data in the *xaction* field. | |
sub_id | |
This value is the subscription ID. It, in combination with | |
the message type is used by rmr to determine the target | |
endpoint when sending a message. If the application to | |
application protocol does not warrant the use of a | |
subscription ID, the RMR constant RMR_VOID_SUBID should be | |
placed in this field. When an application is forwarding or | |
returning a buffer to the sender, it is the application's | |
responsibility to set/reset this value. | |
tp_state | |
For C applications making use of RMR, the state of a | |
transport based failure will often be available via errno. | |
However, some wrapper environments may not have direct | |
access to the C-lib errno value. RMR send and receive | |
operations will place the current value of errno into this | |
field which should make it available to wrapper functions. | |
User applications are strongly cautioned against relying | |
on the value of errno as some transport mechanisms may not | |
set this value on all calls. This value should also be | |
ignored any time the message status is RMR_OK. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The function returns a pointer to a rmr_mbuf structure, or | |
NULL on error. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
ENOMEM | |
Unable to allocate memory. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_tralloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_init(3), rmr_init_trace(3), rmr_get_trace(3), | |
rmr_get_trlen(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_set_trace(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_bytes2meid | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_bytes2meid( rmr_mbuf_t* mbuf, unsigned char* src, int len ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_bytes2meid function will copy up to *len* butes from | |
*src* to the managed entity ID (meid) field in the message. | |
The field is a fixed length, gated by the constant | |
RMR_MAX_MEID and if len is larger than this value, only | |
RMR_MAX_MEID bytes will actually be copied. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, the actual number of bytes copied is returned, or | |
-1 to indicate a hard error. If the length is less than 0, or | |
not the same as length passed in, errno is set to one of the | |
errors described in the *Errors* section. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
If the returned length does not match the length passed in, | |
errno will be set to one of the following constants with the | |
meaning listed below. | |
EINVAL | |
The message, or an internal portion of the message, was | |
corrupted or the pointer was invalid. | |
EOVERFLOW | |
The length passed in was larger than the maximum length of | |
the field; only a portion of the source bytes were copied. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_call(3), | |
rmr_free_msg(3), rmr_get_rcvfd(3), rmr_get_meid(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), | |
rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), | |
rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), | |
rmr_ring_free(3), rmr_str2meid(3), rmr_str2xact(3), | |
rmr_wh_open(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_bytes2payload | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
void rmr_bytes2payload( rmr_mbuf_t* mbuf, unsigned char* src, int len ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
This is a convenience function as some wrapper languages | |
might not have the ability to directly copy into the payload | |
buffer. The bytes from *src* for the length given are copied | |
to the payload. It is the caller's responsibility to ensure | |
that the payload is large enough. Upon successfully copy, the | |
len field in the message buffer is updated to reflect the | |
number of bytes copied. | |
There is little error checking, and no error reporting. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
None. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_bytes2payload(3), | |
rmr_call(3), rmr_free_msg(3), rmr_get_rcvfd(3), | |
rmr_get_meid(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), | |
rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_bytes2xact | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_bytes2xact( rmr_mbuf_t* mbuf, unsigned char* src, int len ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_bytes2xact function will copy up to *len* butes from | |
*src* to the transaction ID (xaction) field in the message. | |
The field is a fixed length, gated by the constant | |
RMR_MAX_XID and if len is larger than this value, only | |
RMR_MAX_XID bytes will actually be copied. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, the actual number of bytes copied is returned, | |
or -1 to indicate a hard error. If the length is less than | |
0, or not the same as length passed in, errno is set to | |
one of the errors described in the *Errors* section. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
If the returned length does not match the length passed | |
in, errno will be set to one of the following constants | |
with the meaning listed below. | |
EINVAL | |
The message, or an internal portion of the message, was | |
corrupted or the pointer was invalid. | |
EOVERFLOW | |
The length passed in was larger than the maximum length of | |
the field; only a portion of the source bytes were copied. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_bytes2meid(3), rmr_call(3), | |
rmr_free_msg(3), rmr_get_meid(3), rmr_get_rcvfd(3), | |
rmr_get_xact(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), | |
rmr_wh_open(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_call | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
extern rmr_mbuf_t* rmr_call( void* vctx, rmr_mbuf_t* msg ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_call function sends the user application message to a | |
remote endpoint, and waits for a corresponding response | |
message before returning control to the user application. The | |
user application supplies a completed message buffer, as it | |
would for a rmr_send call, but unlike with the send, the | |
buffer returned will have the response from the application | |
that received the message. | |
Messages which are received while waiting for the response | |
are queued internally by RMR, and are returned to the user | |
application when rmr_rcv_msg is invoked. These messages are | |
returned in the order received, one per call to rmr_rcv_msg. | |
Call Timeout | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The rmr_call function implements a timeout failsafe to | |
prevent, in most cases, the function from blocking forever. | |
The timeout period is **not** based on time (calls to clock | |
are deemed too expensive for a low latency system level | |
library), but instead the period is based on the number of | |
received messages which are not the response. Using a | |
non-time mechanism for *timeout* prevents the async queue | |
from filling (which would lead to message drops) in an | |
environment where there is heavy message traffic. | |
When the threshold number of messages have been queued | |
without receiving a response message, control is returned to | |
the user application and a nil pointer is returned to | |
indicate that no message was received to process. Currently | |
the threshold is fixed at 20 messages, though in future | |
versions of the library this might be extended to be a | |
parameter which the user application may set. | |
Retries | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The send operations in RMR will retry *soft* send failures | |
until one of three conditions occurs: | |
1. | |
The message is sent without error | |
2. | |
The underlying transport reports a *hard* failure | |
3. | |
The maximum number of retry loops has been attempted | |
A retry loop consists of approximately 1000 send attempts | |
**without** any intervening calls to *sleep()* or *usleep().* | |
The number of retry loops defaults to 1, thus a maximum of | |
1000 send attempts is performed before returning to the user | |
application. This value can be set at any point after RMr | |
initialisation using the *rmr_set_stimeout()* function | |
allowing the user application to completely disable retires | |
(set to 0), or to increase the number of retry loops. | |
Transport Level Blocking | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The underlying transport mechanism used to send messages is | |
configured in *non-blocking* mode. This means that if a | |
message cannot be sent immediately the transport mechanism | |
will **not** pause with the assumption that the inability to | |
send will clear quickly (within a few milliseconds). This | |
means that when the retry loop is completely disabled (set to | |
0), that the failure to accept a message for sending by the | |
underlying mechanisms (software or hardware) will be reported | |
immediately to the user application. | |
It should be noted that depending on the underlying transport | |
mechanism being used, it is extremely likely that retry | |
conditions will happen during normal operations. These are | |
completely out of RMR's control, and there is nothing that | |
RMR can do to avoid or mitigate these other than by allowing | |
RMR to retry the send operation, and even then it is possible | |
(e.g., during connection reattempts), that a single retry | |
loop is not enough to guarantee a successful send. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The rmr_call function returns a pointer to a message buffer | |
with the state set to reflect the overall state of call | |
processing (see Errors below). In some cases a nil pointer | |
will be returned; when this is the case only *errno* will be | |
available to describe the reason for failure. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
These values are reflected in the state field of the returned | |
message. | |
RMR_OK | |
The call was successful and the message buffer references | |
the response message. | |
RMR_ERR_CALLFAILED | |
The call failed and the value of *errno,* as described | |
below, should be checked for the specific reason. | |
The global "variable" *errno* will be set to one of the | |
following values if the overall call processing was not | |
successful. | |
ETIMEDOUT | |
Too many messages were queued before receiving the | |
expected response | |
ENOBUFS | |
The queued message ring is full, messages were dropped | |
EINVAL | |
A parameter was not valid | |
EAGAIN | |
The underlying message system was interrupted or the | |
device was busy; the message was **not** sent, and the | |
user application should call this function with the | |
message again. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
The following code snippet shows one way of using the | |
rmr_call function, and illustrates how the transaction ID | |
must be set. | |
:: | |
int retries_left = 5; // max retries on dev not available | |
int retry_delay = 50000; // retry delay (usec) | |
static rmr_mbuf_t* mbuf = NULL; // response msg | |
msg_t* pm; // application struct for payload | |
// get a send buffer and reference the payload | |
mbuf = rmr_alloc_msg( mr, sizeof( pm->req ) ); | |
pm = (msg_t*) mbuf->payload; | |
// generate an xaction ID and fill in payload with data and msg type | |
snprintf( mbuf->xaction, RMR_MAX_XID, "%s", gen_xaction() ); | |
snprintf( pm->req, sizeof( pm->req ), "{ \\"req\\": \\"num users\\"}" ); | |
mbuf->mtype = MT_REQ; | |
msg = rmr_call( mr, msg ); | |
if( ! msg ) { // probably a timeout and no msg received | |
return NULL; // let errno trickle up | |
} | |
if( mbuf->state != RMR_OK ) { | |
while( retries_left-- > 0 && // loop as long as eagain | |
errno == EAGAIN && | |
(msg = rmr_call( mr, msg )) != NULL && | |
mbuf->state != RMR_OK ) { | |
usleep( retry_delay ); | |
} | |
if( mbuf == NULL || mbuf->state != RMR_OK ) { | |
rmr_free_msg( mbuf ); // safe if nil | |
return NULL; | |
} | |
} | |
// do something with mbuf | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), | |
rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), | |
rmr_fib(3), rmr_has_str(3), rmr_set_stimeout(3), | |
rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_close | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
void rmr_close( void* vctx ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_close function closes the listen socket effectively | |
cutting the application off. The route table listener is also | |
stopped. Calls to rmr_rcv_msg() will fail with unpredictable | |
error codes, and calls to rmr_send_msg(), rmr_call(), and | |
rmr_rts_msg() will have unknown results. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_rcvfd(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_wh_open(3), | |
rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_free_msg | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
void rmr_free_msg( rmr_mbuf_t* mbuf ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The message buffer is returned to the pool, or the associated | |
memory is released depending on the needs of the underlying | |
messaging system. This allows the user application to release | |
a buffer that is not going to be used. It is safe to pass a | |
nil pointer to this function, and doing so does not result in | |
a change to the value of errrno. | |
After calling, the user application should **not** use any of | |
the pointers (transaction ID, or payload) which were | |
available. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_init(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), | |
rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), | |
rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), | |
rmr_ring_free(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_get_const | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
unsigned char* rmr_get_const(); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_get_const function is a convenience function for | |
wrappers which do not have the ability to "compile in" RMR | |
constants. The function will build a nil terminated string | |
containing JSON which defines the RMR constants that C and Go | |
applications have at compile time via the rmr.h header file. | |
All values are represented as strings and the JSON format is | |
illustrated in the following (partial) example: | |
:: | |
{ | |
"RMR_MAX_XID": "32", | |
"RMR_OK": "0", | |
"RMR_ERR_BADARG", "1", | |
"RMR_ERR_NOENDPT" "2" | |
} | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, a pointer to a string containing the JSON | |
defining constant and value pairs. On failure a nil pointer | |
is returned. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr(7) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_get_meid | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
char* rmr_get_meid( rmr_mbuf_t* mbuf, unsigned char* dest ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_get_meid function will copy the managed entity ID | |
(meid) field from the message into the *dest* buffer provided | |
by the user. The buffer referenced by *dest* is assumed to be | |
at least RMR_MAX_MEID bytes in length. If *dest* is NULL, | |
then a buffer is allocated (the calling application is | |
expected to free when the buffer is no longer needed). | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, a pointer to the extracted string is returned. If | |
*dest* was supplied, then this is just a pointer to the | |
caller's buffer. If *dest* was NULL, this is a pointer to the | |
allocated buffer. If an error occurs, a nil pointer is | |
returned and errno is set as described below. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
If an error occurs, the value of the global variable errno | |
will be set to one of the following with the indicated | |
meaning. | |
EINVAL | |
The message, or an internal portion of the message, was | |
corrupted or the pointer was invalid. | |
ENOMEM | |
A nil pointer was passed for *dest,* however it was not | |
possible to allocate a buffer using malloc(). | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_bytes2meid(3), | |
rmr_call(3), rmr_free_msg(3), rmr_get_rcvfd(3), | |
rmr_get_xact(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), | |
rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_get_rcvfd | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
void* rmr_get_rcvfd( void* ctx ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_get_rcvfd function returns a file descriptor which | |
may be given to epoll_wait() by an application that wishes to | |
use event poll in a single thread rather than block on the | |
arrival of a message via calls to rmr_rcv_msg(). When | |
epoll_wait() indicates that this file descriptor is ready, a | |
call to rmr_rcv_msg() will not block as at least one message | |
has been received. | |
The context (ctx) pointer passed in is the pointer returned | |
by the call to rmr_init(). | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The rmr_get_rcvfd function returns a file descriptor greater | |
or equal to 0 on success and -1 on error. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The following error values are specifically set by this RMR | |
function. In some cases the error message of a system call is | |
propagated up, and thus this list might be incomplete. | |
EINVAL | |
The use of this function is invalid in this environment. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
The following short code bit illustrates the use of this | |
function. Error checking has been omitted for clarity. | |
:: | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/epoll.h> | |
#include <rmr/rmr.h> | |
int main() { | |
int rcv_fd; // pollable fd | |
void* mrc; //msg router context | |
struct epoll_event events[10]; // support 10 events to poll | |
struct epoll_event epe; // event definition for event to listen to | |
int ep_fd = -1; | |
rmr_mbuf_t* msg = NULL; | |
int nready; | |
int i; | |
int norm_msg_size = 1500; // 95% messages are less than this | |
mrc = rmr_init( "43086", norm_msg_size, RMRFL_NONE ); | |
rcv_fd = rmr_get_rcvfd( mrc ); | |
ep_fd = epoll_create1( 0 ); // initialise epoll environment | |
epe.events = EPOLLIN; | |
epe.data.fd = rcv_fd; | |
epoll_ctl( ep_fd, EPOLL_CTL_ADD, rcv_fd, &epe ); // add our info to the mix | |
while( 1 ) { | |
nready = epoll_wait( ep_fd, events, 10, -1 ); // -1 == block forever (no timeout) | |
for( i = 0; i < nready && i < 10; i++ ) { // loop through to find what is ready | |
if( events[i].data.fd == rcv_fd ) { // RMR has something | |
msg = rmr_rcv_msg( mrc, msg ); | |
if( msg ) { | |
// do something with msg | |
} | |
} | |
// check for other ready fds.... | |
} | |
} | |
} | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), | |
rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), | |
rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), | |
rmr_ring_free(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_get_src | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
unsigned char* rmr_get_src( rmr_mbuf_t* mbuf, unsigned char* dest ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_get_src function will copy the *source* information | |
from the message to a buffer (dest) supplied by the user. In | |
an RMr message, the source is the sender's information that | |
is used for return to sender function calls, and is generally | |
the hostname and port in the form *name*. The source might be | |
an IP address port combination; the data is populated by the | |
sending process and the only requirement is that it be | |
capable of being used to start a TCP session with the sender. | |
The maximum size allowed by RMr is 64 bytes (including the | |
nil string terminator), so the user must ensure that the | |
destination buffer given is at least 64 bytes. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, a pointer to the destination buffer is given as a | |
convenience to the user programme. On failure, a nil pointer | |
is returned and the value of errno is set. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
If an error occurs, the value of the global variable errno | |
will be set to one of the following with the indicated | |
meaning. | |
EINVAL | |
The message, or an internal portion of the message, was | |
corrupted or the pointer was invalid. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_bytes2meid(3), | |
rmr_call(3), rmr_free_msg(3), rmr_get_rcvfd(3), | |
rmr_get_srcip(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), | |
rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_get_srcip | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
unsigned char* rmr_get_srcip( rmr_mbuf_t* mbuf, unsigned char* dest ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_get_srcip function will copy the *source IP address* | |
from the message to a buffer (dest) supplied by the user. In | |
an RMr message, the source IP address is the sender's | |
information that is used for return to sender function calls; | |
this function makes it available to the user application. The | |
address is maintained as IP:port where *IP* could be either | |
an IPv6 or IPv4 address depending on what was provided by the | |
sending application. | |
The maximum size allowed by RMr is 64 bytes (including the | |
nil string terminator), so the user must ensure that the | |
destination buffer given is at least 64 bytes. The user | |
application should use the RMr constant RMR_MAX_SRC to ensure | |
that the buffer supplied is large enough, and to protect | |
against future RMr enhancements which might increase the | |
address buffer size requirement. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, a pointer to the destination buffer is given as a | |
convenience to the user programme. On failure, a nil pointer | |
is returned and the value of errno is set. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
If an error occurs, the value of the global variable errno | |
will be set to one of the following with the indicated | |
meaning. | |
EINVAL | |
The message, or an internal portion of the message, was | |
corrupted or the pointer was invalid. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_bytes2meid(3), | |
rmr_call(3), rmr_free_msg(3), rmr_get_rcvfd(3), | |
rmr_get_src(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), | |
rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_get_trace | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_get_trace( rmr_mbuf_t* mbuf, unsigned char* dest, int size ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_get_trace function will copy the trace information | |
from the message into the user's allocated memory referenced | |
by dest. The size parameter is assumed to be the maximum | |
number of bytes which can be copied (size of the destination | |
buffer). | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, the number of bytes actually copied is returned. | |
If the return value is 0, no bytes copied, then the reason | |
could be that the message pointer was nil, or the size | |
parameter was <= 0. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_tralloc_msg(3), rmr_bytes2xact(3), | |
rmr_bytes2meid(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_rcvfd(3), rmr_get_trlen(3), rmr_init(3), | |
rmr_init_trace(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), | |
rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3), | |
rmr_set_trace(3), rmr_trace_ref(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_get_trlen | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_get_trlen( rmr_mbuf_t* msg ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
Given a message buffer, this function returns the amount of | |
space (bytes) that have been allocated for trace data. If no | |
trace data has been allocated, then 0 is returned. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The number of bytes allocated for trace information in the | |
given message. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
INVAL | |
Parameter(s) passed to the function were not valid. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_trace(3), rmr_init(3), rmr_init_trace(3), | |
rmr_send_msg(3), rmr_rcv_msg(3), rmr_rcv_specific(3), | |
rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), | |
rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3), | |
rmr_set_trace(3), rmr_tralloc_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_get_xact | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
char* rmr_get_xact( rmr_mbuf_t* mbuf, unsigned char* dest ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_get_xact function will copy the transaction field | |
from the message into the *dest* buffer provided by the user. | |
The buffer referenced by *dest* is assumed to be at least | |
RMR_MAX_XID bytes in length. If *dest* is NULL, then a buffer | |
is allocated (the calling application is expected to free | |
when the buffer is no longer needed). | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, a pointer to the extracted string is returned. If | |
*dest* was supplied, then this is just a pointer to the | |
caller's buffer. If *dest* was NULL, this is a pointer to the | |
allocated buffer. If an error occurs, a nil pointer is | |
returned and errno is set as described below. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
If an error occurs, the value of the global variable errno | |
will be set to one of the following with the indicated | |
meaning. | |
EINVAL | |
The message, or an internal portion of the message, was | |
corrupted or the pointer was invalid. | |
ENOMEM | |
A nil pointer was passed for *dest,* however it was not | |
possible to allocate a buffer using malloc(). | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_bytes2xact(3), rmr_bytes2meid(3), | |
rmr_call(3), rmr_free_msg(3), rmr_get_rcvfd(3), | |
rmr_get_meid(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), | |
rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_init | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
void* rmr_init( char* proto_port, int norm_msg_size, int flags ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_init function prepares the environment for sending | |
and receiving messages. It does so by establishing a worker | |
thread (pthread) which subscribes to a route table generator | |
which provides the necessary routing information for the RMR | |
library to send messages. | |
*Port* is used to listen for connection requests from other | |
RMR based applications. The *norm_msg_size* parameter is used | |
to allocate receive buffers and should be set to what the | |
user application expects to be a size which will hold the | |
vast majority of expected messages. When computing the size, | |
the application should consider the usual payload size | |
**and** the maximum trace data size that will be used. This | |
value is also used as the default message size when | |
allocating message buffers (when a zero size is given to | |
rmr_alloc_msg(); see the rmr_alloc_msg() manual page). | |
Messages arriving which are longer than the given normal size | |
will cause RMR to allocate a new buffer which is large enough | |
for the arriving message. | |
Starting with version 3.8.0 RMR no longer places a maximum | |
buffer size for received messages. The underlying system | |
memory manager might impose such a limit and the attempt to | |
allocate a buffer larger than that limit will likely result | |
in an application abort. Other than the potential performance | |
impact from extra memory allocation and release, there is no | |
penality to the user programme for specifyning a normal | |
buffer size which is usually smaller than received buffers. | |
Similarly, the only penality to the application for over | |
specifying the normal buffer size might be a larger memory | |
footprint. | |
*Flags* allows for selection of some RMr options at the time | |
of initialisation. These are set by ORing RMRFL constants | |
from the RMr header file. Currently the following flags are | |
supported: | |
RMRFL_NONE | |
No flags are set. | |
RMRFL_NOTHREAD | |
The route table collector thread is not to be started. | |
This should only be used by the route table generator | |
application if it is based on RMr. | |
RMRFL_MTCALL | |
Enable multi-threaded call support. | |
RMRFL_NOLOCK | |
Some underlying transport providers (e.g. SI95) enable | |
locking to be turned off if the user application is single | |
threaded, or otherwise can guarantee that RMR functions | |
will not be invoked concurrently from different threads. | |
Turning off locking can help make message receipt more | |
efficient. If this flag is set when the underlying | |
transport does not support disabling locks, it will be | |
ignored. | |
Multi-threaded Calling | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The support for an application to issue a *blocking call* by | |
the rmr_call() function was limited such that only user | |
applications which were operating in a single thread could | |
safely use the function. Further, timeouts were message count | |
based and not time unit based. Multi-threaded call support | |
adds the ability for a user application with multiple threads | |
to invoke a blocking call function with the guarantee that | |
the correct response message is delivered to the thread. The | |
additional support is implemented with the *rmr_mt_call()* | |
and *rmr_mt_rcv()* function calls. | |
Multi-threaded call support requires the user application to | |
specifically enable it when RMr is initialised. This is | |
necessary because a second, dedicated, receiver thread must | |
be started, and requires all messages to be examined and | |
queued by this thread. The additional overhead is minimal, | |
queuing information is all in the RMr message header, but as | |
an additional process is necessary the user application must | |
"opt in" to this approach. | |
ENVIRONMENT | |
-------------------------------------------------------------------------------------------- | |
As a part of the initialisation process rmr_init reads | |
environment variables to configure itself. The following | |
variables are used if found. | |
RMR_ASYNC_CONN | |
Allows the async connection mode to be turned off (by | |
setting the value to 0). When set to 1, or missing from | |
the environment, RMR will invoke the connection interface | |
in the transport mechanism using the non-blocking (async) | |
mode. This will likely result in many "soft failures" | |
(retry) until the connection is established, but allows | |
the application to continue unimpeded should the | |
connection be slow to set up. | |
RMR_BIND_IF | |
This provides the interface that RMR will bind listen | |
ports to, allowing for a single interface to be used | |
rather than listening across all interfaces. This should | |
be the IP address assigned to the interface that RMR | |
should listen on, and if not defined RMR will listen on | |
all interfaces. | |
RMR_CTL_PORT | |
This variable defines the port that RMR should open for | |
communications with Route Manager, and other RMR control | |
applications. If not defined, the port 4561 is assumed. | |
Previously, the RMR_RTG_SVC (route table generator service | |
port) was used to define this port. However, a future | |
version of Route Manager will require RMR to connect and | |
request tables, thus that variable is now used to supply | |
the Route Manager's well-known address and port. | |
To maintain backwards compatibility with the older Route | |
Manager versions, the presence of this variable in the | |
environment will shift RMR's behaviour with respect to the | |
default value used when RMR_RTG_SVC is **not** defined. | |
When RMR_CTL_PORT is **defined:** RMR assumes that Route | |
Manager requires RMR to connect and request table updates | |
is made, and the default well-known address for Route | |
manager is used (routemgr:4561). | |
When RMR_CTL_PORT is **undefined:** RMR assumes that Route | |
Manager will connect and push table updates, thus the | |
default listen port (4561) is used. | |
To avoid any possible misinterpretation and/or incorrect | |
assumptions on the part of RMR, it is recommended that | |
both the RMR_CTL_PORT and RMR_RTG_SVC be defined. In the | |
case where both variables are defined, RMR will behave | |
exactly as is communicated with the variable's values. | |
RMR_RTG_SVC | |
The value of this variable depends on the Route Manager in | |
use. | |
When the Route Manager is expecting to connect to an xAPP | |
and push route tables, this variable must indicate the | |
port which RMR should use to listen for these connections. | |
When the Route Manager is expecting RMR to connect and | |
request a table update during initialisation, the variable | |
should be the host of the Route Manager process. | |
The RMR_CTL_PORT variable (added with the support of | |
sending table update requests to Route manager), controls | |
the behaviour if this variable is not set. See the | |
description of that variable for details. | |
RMR_HR_LOG | |
By default RMR writes messages to standard error | |
(incorrectly referred to as log messages) in human | |
readable format. If this environment variable is set to 0, | |
the format of standard error messages might be written in | |
some format not easily read by humans. If missing, a value | |
of 1 is assumed. | |
RMR_LOG_VLEVEL | |
This is a numeric value which corresponds to the verbosity | |
level used to limit messages written to standard error. | |
The lower the number the less chatty RMR functions are | |
during execution. The following is the current | |
relationship between the value set on this variable and | |
the messages written: | |
0 | |
Off; no messages of any sort are written. | |
1 | |
Only critical messages are written (default if this | |
variable does not exist) | |
2 | |
Errors and all messages written with a lower value. | |
3 | |
Warnings and all messages written with a lower value. | |
4 | |
Informational and all messages written with a lower | |
value. | |
5 | |
Debugging mode -- all messages written, however this | |
requires RMR to have been compiled with debugging | |
support enabled. | |
RMR_RTG_ISRAW | |
**Deprecated.** Should be set to 1 if the route table | |
generator is sending "plain" messages (not using RMR to | |
send messages), 0 if the RTG is using RMR to send. The | |
default is 1 as we don't expect the RTG to use RMR. | |
This variable is only recognised when using the NNG | |
transport library as it is not possible to support NNG | |
"raw" communications with other transport libraries. It is | |
also necessary to match the value of this variable with | |
the capabilities of the Route Manager; at some point in | |
the future RMR will assume that all Route Manager messages | |
will arrive via an RMR connection and will ignore this | |
variable. | |
RMR_SEED_RT | |
This is used to supply a static route table which can be | |
used for debugging, testing, or if no route table | |
generator process is being used to supply the route table. | |
If not defined, no static table is used and RMR will not | |
report *ready* until a table is received. The static route | |
table may contain both the route table (between newrt | |
start and end records), and the MEID map (between meid_map | |
start and end records). | |
RMR_SRC_ID | |
This is either the name or IP address which is placed into | |
outbound messages as the message source. This will used | |
when an RMR based application uses the rmr_rts_msg() | |
function to return a response to the sender. If not | |
supplied RMR will use the hostname which in some container | |
environments might not be routable. | |
The value of this variable is also used for Route Manager | |
messages which are sent via an RMR connection. | |
RMR_VCTL_FILE | |
This supplies the name of a verbosity control file. The | |
core RMR functions do not produce messages unless there is | |
a critical failure. However, the route table collection | |
thread, not a part of the main message processing | |
component, can write additional messages to standard | |
error. If this variable is set, RMR will extract the | |
verbosity level for these messages (0 is silent) from the | |
first line of the file. Changes to the file are detected | |
and thus the level can be changed dynamically, however RMR | |
will only suss out this variable during initialisation, so | |
it is impossible to enable verbosity after startup. | |
RMR_WARNINGS | |
If set to 1, RMR will write some warnings which are | |
non-performance impacting. If the variable is not defined, | |
or set to 0, RMR will not write these additional warnings. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The rmr_init function returns a void pointer (a contex if you | |
will) that is passed as the first parameter to nearly all | |
other RMR functions. If rmr_init is unable to properly | |
initialise the environment, NULL is returned and errno is set | |
to an appropriate value. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The following error values are specifically set by this RMR | |
function. In some cases the error message of a system call is | |
propagated up, and thus this list might be incomplete. | |
ENOMEM | |
Unable to allocate memory. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
:: | |
void* uh; | |
rmr_mbuf* buf = NULL; | |
uh = rmr_init( "43086", 4096, 0 ); | |
buf = rmr_rcv_msg( uh, buf ); | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_rcvfd(3), rmr_mt_call(3), rmr_mt_rcv(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), | |
rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), | |
rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), | |
rmr_ring_free(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_init_trace | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
void* rmr_init_trace( void* ctx ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_init_trace function establishes the default trace | |
space placed in each message buffer allocated with | |
rmr_alloc_msg(). If this function is never called, then no | |
trace space is allocated by default into any message buffer. | |
Trace space allows the user application to pass some trace | |
token, or other data with the message, but outside of the | |
payload. Trace data may be added to any message with | |
rmr_set_trace(), and may be extracted from a message with | |
rmr_get_trace(). The number of bytes that a message contains | |
for/with trace data can be determined by invoking | |
rmr_get_trlen(). | |
This function may be safely called at any time during the | |
life of the user programme to (re)set the default trace space | |
reserved. If the user programme needs to allocate a message | |
with trace space of a different size than is allocated by | |
default, without fear of extra overhead of reallocating a | |
message later, the rmr_tralloc_msg() function can be used. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
A value of 1 is returned on success, and 0 on failure. A | |
failure indicates that the RMr context (a void pointer passed | |
to this function was not valid. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_tr_alloc_msg(3), rmr_call(3), | |
rmr_free_msg(3), rmr_get_rcvfd(3), rmr_get_trace(3), | |
rmr_get_trlen(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_set_trace(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_mt_call | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
extern rmr_mbuf_t* rmr_mt_call( void* vctx, rmr_mbuf_t* msg, int id, int timeout ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_mt_call function sends the user application message | |
to a remote endpoint, and waits for a corresponding response | |
message before returning control to the user application. The | |
user application supplies a completed message buffer, as it | |
would for a rmr_send_msg call, but unlike with a send, the | |
buffer returned will have the response from the application | |
that received the message. The thread invoking the | |
*rmr_mt_call()* will block until a message arrives or until | |
*timeout* milliseconds has passed; which ever comes first. | |
Using a timeout value of zero (0) will cause the thread to | |
block without a timeout. | |
The *id* supplied as the third parameter is an integer in the | |
range of 2 through 255 inclusive. This is a caller defined | |
"thread number" and is used to match the response message | |
with the correct user application thread. If the ID value is | |
not in the proper range, the attempt to make the call will | |
fail. | |
Messages which are received while waiting for the response | |
are queued on a *normal* receive queue and will be delivered | |
to the user application with the next invocation of | |
*rmr_mt_rcv()* or *rmr_rvv_msg().* by RMR, and are returned | |
to the user application when rmr_rcv_msg is invoked. These | |
messages are returned in the order received, one per call to | |
rmr_rcv_msg. | |
The Transaction ID | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The user application is responsible for setting the value of | |
the transaction ID field before invoking *rmr_mt_call.* The | |
transaction ID is a RMR_MAX_XID byte field that is used to | |
match the response message when it arrives. RMR will compare | |
**all** of the bytes in the field, so the caller must ensure | |
that they are set correctly to avoid missing the response | |
message. The application which returns the response message | |
is also expected to ensure that the return buffer has the | |
matching transaction ID. This can be done transparently if | |
the application uses the *rmr_rts_msg()* function and does | |
not adjust the transaction ID. | |
Retries | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The send operations in RMR will retry *soft* send failures | |
until one of three conditions occurs: | |
1. | |
The message is sent without error | |
2. | |
The underlying transport reports a *hard* failure | |
3. | |
The maximum number of retry loops has been attempted | |
A retry loop consists of approximately 1000 send attempts | |
**without** any intervening calls to *sleep()* or *usleep().* | |
The number of retry loops defaults to 1, thus a maximum of | |
1000 send attempts is performed before returning to the user | |
application. This value can be set at any point after RMr | |
initialisation using the *rmr_set_stimeout()* function | |
allowing the user application to completely disable retires | |
(set to 0), or to increase the number of retry loops. | |
Transport Level Blocking | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The underlying transport mechanism used to send messages is | |
configured in *non-blocking* mode. This means that if a | |
message cannot be sent immediately the transport mechanism | |
will **not** pause with the assumption that the inability to | |
send will clear quickly (within a few milliseconds). This | |
means that when the retry loop is completely disabled (set to | |
0), that the failure to accept a message for sending by the | |
underlying mechanisms (software or hardware) will be reported | |
immediately to the user application. | |
It should be noted that depending on the underlying transport | |
mechanism being used, it is extremely likely that retry | |
conditions will happen during normal operations. These are | |
completely out of RMR's control, and there is nothing that | |
RMR can do to avoid or mitigate these other than by allowing | |
RMR to retry the send operation, and even then it is possible | |
(e.g., during connection reattempts), that a single retry | |
loop is not enough to guarantee a successful send. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The rmr_mt_call function returns a pointer to a message | |
buffer with the state set to reflect the overall state of | |
call processing. If the state is RMR_OK then the buffer | |
contains the response message; otherwise the state indicates | |
the error encountered while attempting to send the message. | |
If no response message is received when the timeout period | |
has expired, a nil pointer will be returned (NULL). | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
These values are reflected in the state field of the returned | |
message. | |
RMR_OK | |
The call was successful and the message buffer references | |
the response message. | |
RMR_ERR_BADARG | |
An argument passed to the function was invalid. | |
RMR_ERR_CALLFAILED | |
The call failed and the value of *errno,* as described | |
below, should be checked for the specific reason. | |
RMR_ERR_NOENDPT | |
An endpoint associated with the message type could not be | |
found in the route table. | |
RMR_ERR_RETRY | |
The underlying transport mechanism was unable to accept | |
the message for sending. The user application can retry | |
the call operation if appropriate to do so. | |
The global "variable" *errno* will be set to one of the | |
following values if the overall call processing was not | |
successful. | |
ETIMEDOUT | |
Too many messages were queued before receiving the | |
expected response | |
ENOBUFS | |
The queued message ring is full, messages were dropped | |
EINVAL | |
A parameter was not valid | |
EAGAIN | |
The underlying message system wsa interrupted or the | |
device was busy; the message was **not** sent, and user | |
application should call this function with the message | |
again. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
The following code bit shows one way of using the rmr_mt_call | |
function, and illustrates how the transaction ID must be set. | |
:: | |
int retries_left = 5; // max retries on dev not available | |
static rmr_mbuf_t* mbuf = NULL; // response msg | |
msg_t* pm; // appl message struct (payload) | |
// get a send buffer and reference the payload | |
mbuf = rmr_alloc_msg( mr, sizeof( pm->req ) ); | |
pm = (msg_t*) mbuf->payload; | |
// generate an xaction ID and fill in payload with data and msg type | |
rmr_bytes2xact( mbuf, xid, RMR_MAX_XID ); | |
snprintf( pm->req, sizeof( pm->req ), "{ \\"req\\": \\"num users\\"}" ); | |
mbuf->mtype = MT_USR_RESP; | |
msg = rmr_mt_call( mr, msg, my_id, 100 ); // wait up to 100ms | |
if( ! msg ) { // probably a timeout and no msg received | |
return NULL; // let errno trickle up | |
} | |
if( mbuf->state != RMR_OK ) { | |
while( retries_left-- > 0 && // loop as long as eagain | |
mbuf->state == RMR_ERR_RETRY && | |
(msg = rmr_mt_call( mr, msg )) != NULL && | |
mbuf->state != RMR_OK ) { | |
usleep( retry_delay ); | |
} | |
if( mbuf == NULL || mbuf->state != RMR_OK ) { | |
rmr_free_msg( mbuf ); // safe if nil | |
return NULL; | |
} | |
} | |
// do something with mbuf | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3), | |
rmr_mt_rcv(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), | |
rmr_set_stimeout(3), rmr_tokenise(3), rmr_mk_ring(3), | |
rmr_ring_free(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_mt_rcv | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_mt_rcv( void* vctx, rmr_mbuf_t* old_msg, int timeout ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_mt_rcv function blocks until a message is received, | |
or the timeout period (milliseconds) has passed. The result | |
is an RMr message buffer which references a received message. | |
In the case of a timeout the state will be reflected in an | |
"empty buffer" (if old_msg was not nil, or simply with the | |
return of a nil pointer. If a timeout value of zero (0) is | |
given, then the function will block until the next message | |
received. | |
The *vctx* pointer is the pointer returned by the rmr_init | |
function. *Old_msg* is a pointer to a previously used message | |
buffer or NULL. The ability to reuse message buffers helps to | |
avoid alloc/free cycles in the user application. When no | |
buffer is available to supply, the receive function will | |
allocate one. | |
The *old_msg* parameter allows the user to pass a previously | |
generated RMR message back to RMR for reuse. Optionally, the | |
user application may pass a nil pointer if no reusable | |
message is available. When a timeout occurs, and old_msg was | |
not nil, the state will be returned by returning a pointer to | |
the old message with the state set. | |
It is possible to use the *rmr_rcv_msg()* function instead of | |
this function. Doing so might be advantageous if the user | |
programme does not always start the multi-threaded mode and | |
the use of *rmr_rcv_msg()* would make the flow of the code | |
more simple. The advantages of using this function are the | |
ability to set a timeout without using epoll, and a small | |
performance gain (if multi-threaded mode is enabled, and the | |
*rmr_rcv_msg()* function is used, it simply invokes this | |
function without a timeout value, thus there is the small | |
cost of a second call that results). Similarly, the | |
*rmr_torcv_msg()* call can be used when in multi-threaded | |
mode with the same "pass through" overhead to using this | |
function directly. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
When a message is received before the timeout period expires, | |
a pointer to the RMr message buffer which describes the | |
message is returned. This will, with a high probability, be a | |
different message buffer than *old_msg;* the user application | |
should not continue to use *old_msg* after it is passed to | |
this function. | |
In the event of a timeout the return value will be the old | |
msg with the state set, or a nil pointer if no old message | |
was provided. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The *state* field in the message buffer will be set to one of | |
the following values: | |
RMR_OK | |
The message was received without error. | |
RMR_ERR_BADARG | |
A parameter passed to the function was not valid (e.g. a | |
nil pointer). indicate either RMR_OK or RMR_ERR_EMPTY if | |
an empty message was received. | |
RMR_ERR_EMPTY | |
The message received had no associated data. The length of | |
the message will be 0. | |
RMR_ERR_NOTSUPP | |
The multi-threaded option was not enabled when RMr was | |
initialised. See the man page for *rmr_init()* for | |
details. | |
RMR_ERR_RCVFAILED | |
A hard error occurred preventing the receive from | |
completing. | |
When a nil pointer is returned, or any other state value was | |
set in the message buffer, errno will be set to one of the | |
following: | |
INVAL | |
Parameter(s) passed to the function were not valid. | |
EBADF | |
The underlying message transport is unable to process the | |
request. | |
ENOTSUP | |
The underlying message transport is unable to process the | |
request. | |
EFSM | |
The underlying message transport is unable to process the | |
request. | |
EAGAIN | |
The underlying message transport is unable to process the | |
request. | |
EINTR | |
The underlying message transport is unable to process the | |
request. | |
ETIMEDOUT | |
The underlying message transport is unable to process the | |
request. | |
ETERM | |
The underlying message transport is unable to process the | |
request. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
:: | |
rmr_mbuf_t* mbuf = NULL; // received msg | |
msg = rmr_mt_recv( mr, mbuf, 100 ); // wait up to 100ms | |
if( msg != NULL ) { | |
switch( msg->state ) { | |
case RMR_OK: | |
printf( "got a good message\\n" ); | |
break; | |
case RMR_ERR_EMPTY: | |
printf( "received timed out\\n" ); | |
break; | |
default: | |
printf( "receive error: %d\\n", mbuf->state ); | |
break; | |
} | |
} else { | |
printf( "receive timeout (nil)\\n" ); | |
} | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_rcvfd(3), rmr_init(3), rmr_mk_ring(3), | |
rmr_mt_call(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_torcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_ring_free(3), rmr_torcv_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_payload_size | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_payload_size( rmr_mbuf_t* msg ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
Given a message buffer, this function returns the amount of | |
space (bytes) available for the user application to consume | |
in the message payload. This is different than the message | |
length available as a field in the message buffer. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The number of bytes available in the payload. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
INVAL | |
Parameter(s) passed to the function were not valid. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), | |
rmr_send_msg(3), rmr_rcv_msg(3), rmr_rcv_specific(3), | |
rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), | |
rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_rcv_msg | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_rcv_msg( void* vctx, rmr_mbuf_t* old_msg ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_rcv_msg function blocks until a message is received, | |
returning the message to the caller via a pointer to a | |
rmr_mbuf_t structure type. If messages were queued while | |
waiting for the response to a previous invocation of | |
rmr_call, the oldest message is removed from the queue and | |
returned without delay. | |
The *vctx* pointer is the pointer returned by the rmr_init | |
function. *Old_msg* is a pointer to a previously used message | |
buffer or NULL. The ability to reuse message buffers helps to | |
avoid alloc/free cycles in the user application. When no | |
buffer is available to supply, the receive function will | |
allocate one. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The function returns a pointer to the rmr_mbuf_t structure | |
which references the message information (state, length, | |
payload), or a nil pointer in the case of an extreme error. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The *state* field in the message buffer will indicate RMR_OK | |
when the message receive process was successful and the | |
message can be used by the caller. Depending on the | |
underlying transport mechanism, one of the following RMR | |
error stats may be returned: | |
RMR_ERR_EMPTY | |
The message received had no payload, or was completely | |
empty. | |
RMR_ERR_TIMEOUT | |
For some transport mechanisms, or if reading the receive | |
queue from multiple threads, it is possible for one thread | |
to find no data waiting when it queries the queue. When | |
this state is reported, the message buffer does not | |
contain message data and the user application should | |
reinvoke the receive function. | |
When an RMR error state is reported, the underlying errno | |
value might provide more information. The following is a list | |
of possible values that might accompany the states listed | |
above: | |
RMR_ERR_EMPTY if an empty message was received. If a nil | |
pointer is returned, or any other state value was set in the | |
message buffer, errno will be set to one of the following: | |
INVAL | |
Parameter(s) passed to the function were not valid. | |
EBADF | |
The underlying message transport is unable to process the | |
request. | |
ENOTSUP | |
The underlying message transport is unable to process the | |
request. | |
EFSM | |
The underlying message transport is unable to process the | |
request. | |
EAGAIN | |
The underlying message transport is unable to process the | |
request. | |
EINTR | |
The underlying message transport is unable to process the | |
request. | |
ETIMEDOUT | |
The underlying message transport is unable to process the | |
request. | |
ETERM | |
The underlying message transport is unable to process the | |
request. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_rcvfd(3), rmr_init(3), rmr_mk_ring(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_torcv_msg(3), | |
rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), | |
rmr_ring_free(3), rmr_torcv_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_ready | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_ready( void* vctx ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_ready function checks to see if a routing table has | |
been successfully received and installed. The return value | |
indicates the state of readiness. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
A return value of 1 (true) indicates that the routing table | |
is in place and attempts to send messages can be made. When 0 | |
is returned (false) the routing table has not been received | |
and thus attempts to send messages will fail with *no | |
endpoint* errors. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), | |
rmr_rcv_specific(3), rmr_rts_msg(3), rmr_fib(3), | |
rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), | |
rmr_ring_free(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_realloc_payload | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
extern rmr_mbuf_t* rmr_realloc_payload( rmr_mbuf_t* msg, int new_len, int copy, int clone ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_realloc_payload function will return a pointer to an | |
RMR message buffer struct (rmr_mbuf_t) which has a payload | |
large enough to accomodate *new_len* bytes. If necessary, the | |
underlying payload is reallocated, and the bytes from the | |
original payload are copied if the *copy* parameter is true | |
(1). If the message passed in has a payload large enough, | |
there is no additional memory allocation and copying. | |
Cloning The Message Buffer | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
This function can also be used to generate a separate copy of | |
the original message, with the desired payload size, without | |
destroying the original message buffer or the original | |
payload. A standalone copy is made only when the *clone* | |
parameter is true (1). When cloning, the payload is copied to | |
the cloned message **only** if the *copy* parameter is true. | |
Message Buffer Metadata | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The metadata in the original message buffer (message type, | |
subscription ID, and payload length) will be preserved if the | |
*copy* parameter is true. When this parameter is not true | |
(0), then these values are set to the uninitialised value | |
(-1) for type and ID, and the length is set to 0. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The rmr_realloc_payload function returns a pointer to the | |
message buffer with the payload which is large enough to hold | |
*new_len* bytes. If the *clone* option is true, this will be | |
a pointer to the newly cloned message buffer; the original | |
message buffer pointer may still be used to reference that | |
message. It is the calling application's responsibility to | |
free the memory associateed with both messages using the | |
rmr_free_msg() function. | |
When the *clone* option is not used, it is still good | |
practice by the calling application to capture and use this | |
reference as it is possible that the message buffer, and not | |
just the payload buffer, was reallocated. In the event of an | |
error, a nil pointer will be returned and the value of | |
*errno* will be set to reflect the problem. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
These value of *errno* will reflect the error condition if a | |
nil pointer is returned: | |
ENOMEM | |
Memory allocation of the new payload failed. | |
EINVAL | |
The pointer passed in was nil, or refrenced an invalid | |
message, or the required length was not valid. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
The following code bit illustrates how this function can be | |
used to reallocate a buffer for a return to sender | |
acknowledgement message which is larger than the message | |
received. | |
:: | |
if( rmr_payload_size( msg ) < ack_sz ) { // received message too small for ack | |
msg = rmr_realloc_payload( msg, ack_sz, 0, 0 ); // reallocate the message with a payload big enough | |
if( msg == NULL ) { | |
fprintf( stderr, "[ERR] realloc returned a nil pointer: %s\\n", strerror( errno ) ); | |
} else { | |
// populate and send ack message | |
} | |
} | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_free_msg(3), rmr_init(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), | |
rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), | |
rmr_fib(3), rmr_has_str(3), rmr_set_stimeout(3), | |
rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_rts_msg | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_rts_msg( void* vctx, rmr_mbuf_t* msg ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_rts_msg function sends a message returning it to the | |
endpoint which sent the message rather than selecting an | |
endpoint based on the message type and routing table. Other | |
than this small difference, the behaviour is exactly the same | |
as rmr_send_msg. | |
Retries | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The send operations in RMR will retry *soft* send failures | |
until one of three conditions occurs: | |
1. | |
The message is sent without error | |
2. | |
The underlying transport reports a *hard* failure | |
3. | |
The maximum number of retry loops has been attempted | |
A retry loop consists of approximately 1000 send attempts | |
**without** any intervening calls to *sleep()* or *usleep().* | |
The number of retry loops defaults to 1, thus a maximum of | |
1000 send attempts is performed before returning to the user | |
application. This value can be set at any point after RMr | |
initialisation using the *rmr_set_stimeout()* function | |
allowing the user application to completely disable retires | |
(set to 0), or to increase the number of retry loops. | |
Transport Level Blocking | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The underlying transport mechanism used to send messages is | |
configured in *non-blocking* mode. This means that if a | |
message cannot be sent immediately the transport mechanism | |
will **not** pause with the assumption that the inability to | |
send will clear quickly (within a few milliseconds). This | |
means that when the retry loop is completely disabled (set to | |
0), that the failure to accept a message for sending by the | |
underlying mechanisms (software or hardware) will be reported | |
immediately to the user application. | |
It should be noted that depending on the underlying transport | |
mechanism being used, it is extremely likely that retry | |
conditions will happen during normal operations. These are | |
completely out of RMR's control, and there is nothing that | |
RMR can do to avoid or mitigate these other than by allowing | |
RMR to retry the send operation, and even then it is possible | |
(e.g., during connection reattempts), that a single retry | |
loop is not enough to guarantee a successful send. | |
PAYLOAD SIZE | |
-------------------------------------------------------------------------------------------- | |
When crafting a response based on a received message, the | |
user application must take care not to write more bytes to | |
the message payload than the allocated message has. In the | |
case of a received message, it is possible that the response | |
needs to be larger than the payload associated with the | |
inbound message. In order to use the return to sender | |
function, the source information in the original message must | |
be present in the response; information which cannot be added | |
to a message buffer allocated through the standard RMR | |
allocation function. To allocate a buffer with a larger | |
payload, and which retains the necessary sender data needed | |
by this function, the *rmr_realloc_payload()* function must | |
be used to extend the payload to a size suitable for the | |
response. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, a new message buffer, with an empty payload, is | |
returned for the application to use for the next send. The | |
state in this buffer will reflect the overall send operation | |
state and should be RMR_OK. | |
If the state in the returned buffer is anything other than | |
RMR_OK, the user application may need to attempt a | |
retransmission of the message, or take other action depending | |
on the setting of errno as described below. | |
In the event of extreme failure, a nil pointer is returned. | |
In this case the value of errno might be of some use, for | |
documentation, but there will be little that the user | |
application can do other than to move on. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The following values may be passed back in the *state* field | |
of the returned message buffer. | |
RMR_ERR_BADARG | |
The message buffer pointer did not refer to a valid | |
message. | |
RMR_ERR_NOHDR | |
The header in the message buffer was not valid or | |
corrupted. | |
RMR_ERR_NOENDPT | |
The message type in the message buffer did not map to a | |
known endpoint. | |
RMR_ERR_SENDFAILED | |
The send failed; errno has the possible reason. | |
The following values may be assigned to errno on failure. | |
INVAL | |
Parameter(s) passed to the function were not valid, or the | |
underlying message processing environment was unable to | |
interpret the message. | |
ENOKEY | |
The header information in the message buffer was invalid. | |
ENXIO | |
No known endpoint for the message could be found. | |
EMSGSIZE | |
The underlying transport refused to accept the message | |
because of a size value issue (message was not attempted | |
to be sent). | |
EFAULT | |
The message referenced by the message buffer is corrupt | |
(nil pointer or bad internal length). | |
EBADF | |
Internal RMR error; information provided to the message | |
transport environment was not valid. | |
ENOTSUP | |
Sending was not supported by the underlying message | |
transport. | |
EFSM | |
The device is not in a state that can accept the message. | |
EAGAIN | |
The device is not able to accept a message for sending. | |
The user application should attempt to resend. | |
EINTR | |
The operation was interrupted by delivery of a signal | |
before the message was sent. | |
ETIMEDOUT | |
The underlying message environment timed out during the | |
send process. | |
ETERM | |
The underlying message environment is in a shutdown state. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), | |
rmr_rcv_specific(3), rmr_ready(3), rmr_fib(3), | |
rmr_has_str(3), rmr_set_stimeout(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_send_msg | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_send_msg( void* vctx, rmr_mbuf_t* msg ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_send_msg function accepts a message buffer from the | |
user application and attempts to send it. The destination of | |
the message is selected based on the message type specified | |
in the message buffer, and the matching information in the | |
routing tables which are currently in use by the RMR library. | |
This may actually result in the sending of the message to | |
multiple destinations which could degrade expected overall | |
performance of the user application. (Limiting excessive | |
sending of messages is the responsibility of the | |
application(s) responsible for building the routing table | |
used by the RMR library, and not the responsibility of the | |
library.) | |
Retries | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The send operations in RMR will retry *soft* send failures | |
until one of three conditions occurs: | |
1. | |
The message is sent without error | |
2. | |
The underlying transport reports a *hard* failure | |
3. | |
The maximum number of retry loops has been attempted | |
A retry loop consists of approximately 1000 send attempts | |
**without** any intervening calls to *sleep()* or *usleep().* | |
The number of retry loops defaults to 1, thus a maximum of | |
1000 send attempts is performed before returning to the user | |
application. This value can be set at any point after RMr | |
initialisation using the *rmr_set_stimeout()* function | |
allowing the user application to completely disable retires | |
(set to 0), or to increase the number of retry loops. | |
Transport Level Blocking | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The underlying transport mechanism used to send messages is | |
configured in *non-blocking* mode. This means that if a | |
message cannot be sent immediately the transport mechanism | |
will **not** pause with the assumption that the inability to | |
send will clear quickly (within a few milliseconds). This | |
means that when the retry loop is completely disabled (set to | |
0), that the failure to accept a message for sending by the | |
underlying mechanisms (software or hardware) will be reported | |
immediately to the user application. | |
It should be noted that depending on the underlying transport | |
mechanism being used, it is extremely likely that retry | |
conditions will happen during normal operations. These are | |
completely out of RMR's control, and there is nothing that | |
RMR can do to avoid or mitigate these other than by allowing | |
RMR to retry the send operation, and even then it is possible | |
(e.g., during connection reattempts), that a single retry | |
loop is not enough to guarantee a successful send. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, a new message buffer, with an empty payload, is | |
returned for the application to use for the next send. The | |
state in this buffer will reflect the overall send operation | |
state and will be RMR_OK when the send was successful. | |
When the message cannot be successfully sent this function | |
will return the unsent (original) message buffer with the | |
state set to indicate the reason for failure. The value of | |
*errno* may also be set to reflect a more detailed failure | |
reason if it is known. | |
In the event of extreme failure, a nil pointer is returned. | |
In this case the value of errno might be of some use, for | |
documentation, but there will be little that the user | |
application can do other than to move on. | |
**CAUTION:** In some cases it is extremely likely that the | |
message returned by the send function does **not** reference | |
the same memory structure. Thus is important for the user | |
programme to capture the new pointer for future use or to be | |
passed to rmr_free(). If you are experiencing either double | |
free errors or segment faults in either rmr_free() or | |
rmr_send_msg(), ensure that the return value from this | |
function is being captured and used. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The following values may be passed back in the *state* field | |
of the returned message buffer. | |
RMR_RETRY | |
The message could not be sent, but the underlying | |
transport mechanism indicates that the failure is | |
temporary. If the send operation is tried again it might | |
be successful. | |
RMR_SEND_FAILED | |
The send operation was not successful and the underlying | |
transport mechanism indicates a permanent (hard) failure; | |
retrying the send is not possible. | |
RMR_ERR_BADARG | |
The message buffer pointer did not refer to a valid | |
message. | |
RMR_ERR_NOHDR | |
The header in the message buffer was not valid or | |
corrupted. | |
RMR_ERR_NOENDPT | |
The message type in the message buffer did not map to a | |
known endpoint. | |
The following values may be assigned to errno on failure. | |
INVAL | |
Parameter(s) passed to the function were not valid, or the | |
underlying message processing environment was unable to | |
interpret the message. | |
ENOKEY | |
The header information in the message buffer was invalid. | |
ENXIO | |
No known endpoint for the message could be found. | |
EMSGSIZE | |
The underlying transport refused to accept the message | |
because of a size value issue (message was not attempted | |
to be sent). | |
EFAULT | |
The message referenced by the message buffer is corrupt | |
(nil pointer or bad internal length). | |
EBADF | |
Internal RMR error; information provided to the message | |
transport environment was not valid. | |
ENOTSUP | |
Sending was not supported by the underlying message | |
transport. | |
EFSM | |
The device is not in a state that can accept the message. | |
EAGAIN | |
The device is not able to accept a message for sending. | |
The user application should attempt to resend. | |
EINTR | |
The operation was interrupted by delivery of a signal | |
before the message was sent. | |
ETIMEDOUT | |
The underlying message environment timed out during the | |
send process. | |
ETERM | |
The underlying message environment is in a shutdown state. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
The following is a simple example of how the rmr_send_msg | |
function is called. In this example, the send message buffer | |
is saved between calls and reused eliminating alloc/free | |
cycles. | |
:: | |
static rmr_mbuf_t* send_msg = NULL; // message to send; reused on each call | |
msg_t* send_pm; // payload for send | |
msg_t* pm; // our message format in the received payload | |
if( send_msg == NULL ) { | |
send_msg = rmr_alloc_msg( mr, MAX_SIZE ); // new buffer to send | |
} | |
// reference payload and fill in message type | |
pm = (msg_t*) send_msg->payload; | |
send_msg->mtype = MT_ANSWER; | |
msg->len = generate_data( pm ); // something that fills the payload in | |
msg = rmr_send_msg( mr, send_msg ); // ensure new pointer used after send | |
if( ! msg ) { | |
return ERROR; | |
} else { | |
if( msg->state != RMR_OK ) { | |
// check for RMR_ERR_RETRY, and resend if needed | |
// else return error | |
} | |
} | |
return OK; | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), | |
rmr_payload_size(3), rmr_rcv_msg(3), rmr_rcv_specific(3), | |
rmr_rts_msg(3), rmr_ready(3), rmr_mk_ring(3), | |
rmr_ring_free(3), rmr_torcv_rcv(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_set_fack | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
void rmr_set_fack( void* vctx ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_set_fack function enables *fast TCP acknowledgements* | |
if the underlying transport library supports it. This might | |
be useful for applications which must send messages at a | |
maximum rate. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
There is no return value. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
This function does not generate any errors. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_init(3), | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_set_stimeout | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_set_stimeout( void* vctx, int rloops ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_set_stimeout function sets the configuration for how | |
RMr will retry message send operations which complete with | |
either a *timeout* or *again* completion value. (Send | |
operations include all of the possible message send | |
functions: *rmr_send_msg(), rmr_call(), rmr_rts_msg()* and | |
*rmr_wh_send_msg().* The *rloops* parameter sets the maximum | |
number of retry loops that will be attempted before giving up | |
and returning the unsuccessful state to the user application. | |
Each retry loop is approximately 1000 attempts, and RMr does | |
**not** invoke any sleep function between retries in the | |
loop; a small, 1 mu-sec, sleep is executed between loop sets | |
if the *rloops* value is greater than 1. | |
Disabling Retries | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
By default, the send operations will execute with an *rloop* | |
setting of 1; each send operation will attempt to resend the | |
message approximately 1000 times before giving up. If the | |
user application does not want to have send operations retry | |
when the underlying transport mechanism indicates *timeout* | |
or *again,* the application should invoke this function and | |
pass a value of 0 (zero) for *rloops.* With this setting, all | |
RMr send operations will attempt a send operation only | |
**once,** returning immediately to the caller with the state | |
of that single attempt. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
This function returns a -1 to indicate that the *rloops* | |
value could not be set, and the value *RMR_OK* to indicate | |
success. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
Currently errno is **not** set by this function; the only | |
cause of a failure is an invalid context (*vctx*) pointer. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
The following is a simple example of how the rmr_set_stimeout | |
function is called. | |
:: | |
#define NO_FLAGS 0 | |
char* port = "43086"; // port for message router listen | |
int max_size = 4096; // max message size for default allocations | |
void* mr_context; // message router context | |
mr_context = rmr_init( port, max_size, NO_FLAGS ); | |
if( mr_context != NULL ) { | |
rmr_set_stimeout( mr_context, 0 ); // turn off retries | |
} | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), | |
rmr_payload_size(3), rmr_rcv_msg(3), rmr_rcv_specific(3), | |
rmr_rts_msg(3), rmr_ready(3), rmr_mk_ring(3), | |
rmr_ring_free(3), rmr_send_msg(3), rmr_torcv_rcv(3), | |
rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_set_trace | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_set_trace( rmr_mbuf_t* mbuf, unsigned char* data, int len ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_set_trace function will copy len bytes from data into | |
the trace portion of mbuf. If the trace area of mbuf is not | |
the correct size, the message buffer will be reallocated to | |
ensure that enough space is available for the trace data. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The rmr_set_trace function returns the number of bytes | |
successfully copied to the message. If 0 is returned either | |
the message pointer was nil, or the size in the parameters | |
was <= 0. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_tralloc_msg(3), rmr_bytes2xact(3), | |
rmr_bytes2payload(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_rcvfd(3), rmr_get_meid(3), rmr_get_trace(3), | |
rmr_get_trlen(3), rmr_init(3), rmr_init_trace(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), | |
rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), | |
rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), rmr_mk_ring(3), | |
rmr_ring_free(3), rmr_str2meid(3), rmr_str2xact(3), | |
rmr_wh_open(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_set_vlevel | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
#include <rmr/rmr_logging.h> | |
void rmr_set_vlevel( int new_level ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_set_vlevel allows the user programme to set the | |
verbosity level which is used to determine the messages RMR | |
writes to standard error. The new_vlevel value must be one of | |
the following constants which have the indicated meanings: | |
RMR_VL_OFF | |
Turns off all message writing. This includes the stats and | |
debugging messages generated by the route collector thread | |
which are normally affected only by the externally managed | |
verbose level file (and related environment variable). | |
RMR_VL_CRIT | |
Write only messages of critical importance. From the point | |
of view of RMR, when a critical proper behaviour of the | |
library cannot be expected or guaranteed. | |
RMR_VL_ERR | |
Include error messages in the output. An error is an event | |
from which RMR has no means to recover. Continued proper | |
execution is likely except where the affected connection | |
and/or component mentioned in the error is concerned. | |
RMR_VL_WARN | |
Include warning messages in the output. A warning | |
indicates an event which is not considered to be normal, | |
but is expected and continued acceptable behaviour of the | |
system is assured. | |
RMR_VL_INFO | |
Include informational messagees in the output. | |
Informational messages include some diagnostic information | |
which explain the activities of RMR. | |
RMR_VL_DEBUG | |
Include all debugging messages in the output. Debugging | |
must have also been enabled during the build as a | |
precaution to accidentally enabling this level of output | |
as it can grossly affect performance. | |
Generally RMR does not write messages to the standard error | |
device from *critical path* functions, therefore it is | |
usually not harmful to enable a verbosity level of either | |
RMR_VL_CRIT or RMR_VL_ERR. | |
Messages written from the route table collection thread are | |
still governed by the value placed into the verbose level | |
control file (see the man page for rmr_init()); those | |
messages are affected only when logging is completely | |
disabled by passing RMR_VL_OFF to this function. | |
The verbosity level can also be set via an environment | |
variable prior to the start of the RMR based application. The | |
environment variable is read only during initialisation; if | |
the programme must change the value during execution, this | |
function must be used. The default value, if this function is | |
never called, and the environment variable is not present, is | |
RMR_VL_ERR. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_init(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_str2meid | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_str2meid( rmr_mbuf_t* mbuf, unsigned char* src, int len ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_str2meid function will copy the string pointed to by | |
src to the managed entity ID (meid) field in the given | |
message. The field is a fixed length, gated by the constant | |
RMR_MAX_MEID and if string length is larger than this value, | |
then **nothing** will be copied. (Note, this differs slightly | |
from the behaviour of the lrmr_bytes2meid() function.) | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, the value RMR_OK is returned. If the string | |
cannot be copied to the message, the return value will be one | |
of the errors listed below. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
If the return value is not RMR_OK, then it will be set to one | |
of the values below. | |
RMR_ERR_BADARG | |
The message, or an internal portion of the message, was | |
corrupted or the pointer was invalid. | |
RMR_ERR_OVERFLOW | |
The length passed in was larger than the maximum length of | |
the field; only a portion of the source bytes were copied. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_meid(3), rmr_get_rcvfd(3), rmr_payload_size(3), | |
rmr_send_msg(3), rmr_rcv_msg(3), rmr_rcv_specific(3), | |
rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), | |
rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3), | |
rmr_bytes2meid(3), rmr_wh_open(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_str2xact | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_str2xact( rmr_mbuf_t* mbuf, unsigned char* src, int len ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_str2xact function will copy the string pointed to by | |
src to the transaction ID (xaction) field in the given | |
message. The field is a fixed length, gated by the constant | |
RMR_MAX_XID and if string length is larger than this value, | |
then **nothing** will be copied. (Note, this differs slightly | |
from the behaviour of the lrmr_bytes2xact() function.) | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, the value RMR_OK is returned. If the string | |
cannot be copied to the message, the return value will be | |
one of the errors listed below. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
If the return value is not RMR_OK, then it will be set to | |
one of the values below. | |
RMR_ERR_BADARG | |
The message, or an internal portion of the message, was | |
corrupted or the pointer was invalid. | |
RMR_ERR_OVERFLOW | |
The length passed in was larger than the maximum length of | |
the field; only a portion of the source bytes were copied. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_bytes2meid(3), rmr_bytes2xact(3), | |
rmr_call(3), rmr_free_msg(3), rmr_get_meid(3), | |
rmr_get_rcvfd(3), rmr_get_xact(3), rmr_payload_size(3), | |
rmr_send_msg(3), rmr_rcv_msg(3), rmr_rcv_specific(3), | |
rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), | |
rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3), | |
rmr_str2meid(3), rmr_wh_open(3), rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
RMR support functions | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
#include <rmr/ring_inline.h> | |
char* rmr_fib( char* fname ); | |
int rmr_has_str( char const* buf, char const* str, char sep, int max ); | |
int rmr_tokenise( char* buf, char** tokens, int max, char sep ); | |
void* rmr_mk_ring( int size ); | |
void rmr_ring_free( void* vr ); | |
static inline void* rmr_ring_extract( void* vr ) | |
static inline int rmr_ring_insert( void* vr, void* new_data ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
These functions support the RMR library, and are made | |
available to user applications as some (e.g. route table | |
generators) might need and/or want to make use of them. The | |
rmr_fib function accepts a file name and reads the entire | |
file into a single buffer. The intent is to provide an easy | |
way to load a static route table without a lot of buffered | |
I/O hoops. | |
The rmr_has_str function accepts a *buffer* containing a set | |
of delimited tokens (e.g. foo,bar,goo) and returns true if | |
the target string, *str,* matches one of the tokens. The | |
*sep* parameter provides the separation character in the | |
buffer (e.g a comma) and *max* indicates the maximum number | |
of tokens to split the buffer into before checking. | |
The rmr_tokenise function is a simple tokeniser which splits | |
*buf* into tokens at each occurrence of *sep*. Multiple | |
occurrences of the separator character (e.g. a,,b) result in | |
a nil token. Pointers to the tokens are placed into the | |
*tokens* array provided by the caller which is assumed to | |
have at least enough space for *max* entries. | |
The rmr_mk_ring function creates a buffer ring with *size* | |
entries. | |
The rmr_ring_free function accepts a pointer to a ring | |
context and frees the associated memory. | |
The rmr_ring_insert and rmr_ring_extract functions are | |
provided as static inline functions via the | |
*rmr/ring_inline.h* header file. These functions both accept | |
the ring *context* returned by mk_ring, and either insert a | |
pointer at the next available slot (tail) or extract the data | |
at the head. | |
RETURN VALUES | |
-------------------------------------------------------------------------------------------- | |
The following are the return values for each of these | |
functions. | |
The rmr_fib function returns a pointer to the buffer | |
containing the contents of the file. The buffer is terminated | |
with a single nil character (0) making it a legitimate C | |
string. If the file was empty or nonexistent, a buffer with | |
an immediate nil character. If it is important to the calling | |
programme to know if the file was empty or did not exist, the | |
caller should use the system stat function call to make that | |
determination. | |
The rmr_has_str function returns 1 if *buf* contains the | |
token referenced by &ita and false (0) if it does not. On | |
error, a -1 value is returned and errno is set accordingly. | |
The rmr_tokenise function returns the actual number of token | |
pointers placed into *tokens* | |
The rmr_mk_ring function returns a void pointer which is the | |
*context* for the ring. | |
The rmr_ring_insert function returns 1 if the data was | |
successfully inserted into the ring, and 0 if the ring is | |
full and the pointer could not be deposited. | |
The rmr_ring_extract will return the data which is at the | |
head of the ring, or NULL if the ring is empty. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
Not many of these functions set the value in errno, however | |
the value may be one of the following: | |
INVAL | |
Parameter(s) passed to the function were not valid. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), | |
rmr_payload_size(3), rmr_send_msg(3), rmr_rcv_msg(3), | |
rmr_rcv_specific(3), rmr_rts_msg(3), rmr_ready(3), | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_torcv_msg | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_torcv_msg( void* vctx, rmr_mbuf_t* old_msg, int ms_to ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_torcv_msg function will pause for *ms_to* | |
milliseconds waiting for a message to arrive. If a message | |
arrives before the timeout expires the message buffer | |
returned will have a status of RMR_OK and the payload will | |
contain the data received. If the timeout expires before the | |
message is received, the status will have the value | |
RMR_ERR_TIMEOUT. When a received message is returned the | |
message buffer will also contain the message type and length | |
set by the sender. If messages were queued while waiting for | |
the response to a previous invocation of rmr_call, the oldest | |
message is removed from the queue and returned without delay. | |
The *vctx* pointer is the pointer returned by the rmr_init | |
function. *Old_msg* is a pointer to a previously used message | |
buffer or NULL. The ability to reuse message buffers helps to | |
avoid alloc/free cycles in the user application. When no | |
buffer is available to supply, the receive function will | |
allocate one. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The function returns a pointer to the rmr_mbuf_t structure | |
which references the message information (state, length, | |
payload), or a nil pointer in the case of an extreme error. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The *state* field in the message buffer will be one of the | |
following: | |
RMR_OK | |
The message buffer (payload) references the received data. | |
RMR_ERR_INITFAILED | |
The first call to this function must initialise an | |
underlying system notification mechanism. On failure, this | |
error is returned and errno will have the system error | |
status set. If this function fails to intialise, the poll | |
mechansim, it is likely that message receives will never | |
be successful. | |
RMR_ERR_TIMEOUT | |
The timeout expired before a complete message was | |
received. All other fields in the message buffer are not | |
valid. | |
RMR_ERR_EMPTY | |
A message was received, but it had no payload. All other | |
fields in the message buffer are not valid. | |
INVAL | |
Parameter(s) passed to the function were not valid. | |
EBADF | |
The underlying message transport is unable to process the | |
request. | |
ENOTSUP | |
The underlying message transport is unable to process the | |
request. | |
EFSM | |
The underlying message transport is unable to process the | |
request. | |
EAGAIN | |
The underlying message transport is unable to process the | |
request. | |
EINTR | |
The underlying message transport is unable to process the | |
request. | |
ETIMEDOUT | |
The underlying message transport is unable to process the | |
request. | |
ETERM | |
The underlying message transport is unable to process the | |
request. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_rcvfd(3), rmr_init(3), rmr_payload_size(3), | |
rmr_rcv_msg(3), rmr_send_msg(3), rmr_rcv_specific(3), | |
rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), | |
rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_trace_ref | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_trace_ref( rmr_mbuf_t* mbuf, int* sizeptr ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_trace_ref function returns a pointer to the trace | |
area in the message, and optionally populates the user | |
programme supplied size integer with the trace area size, if | |
*sizeptr* is not nil. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, a void pointer to the trace area of the message | |
is returned. A nil pointer is returned if the message has no | |
trace data area allocated, or if the message itself is | |
invalid. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_tralloc_msg(3), rmr_bytes2xact(3), | |
rmr_bytes2meid(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_rcvfd(3), rmr_get_trlen(3), rmr_init(3), | |
rmr_init_trace(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_str2meid(3), | |
rmr_str2xact(3), rmr_wh_open(3), rmr_wh_send_msg(3), | |
rmr_set_trace(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_tralloc_msg | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_tralloc_msg( void* vctx, int size, | |
int trace_size, unsigned const char *tr_data ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_tralloc_msg function is used to allocate a buffer | |
which the user programme can write into and then send through | |
the library. The buffer is allocated such that sending it | |
requires no additional copying from the buffer as it passes | |
through the underlying transport mechanism. | |
The *size* parameter is used to set the payload length in the | |
message. If it is 0, then the default size supplied on the | |
*rmr_init* call will be used. In addition to allocating the | |
payload, a space in the buffer is reserved for *trace* data | |
(tr_size bytes), and the bytes pointed to by *tr_data* are | |
copied into that portion of the message. The *vctx* parameter | |
is the void context pointer that was returned by the | |
*rmr_init* function. | |
The pointer to the message buffer returned is a structure | |
which has some user application visible fields; the structure | |
is described in rmr.h, and is illustrated below. | |
:: | |
typedef struct { | |
int state; | |
int mtype; | |
int len; | |
unsigned char* payload; | |
unsigned char* xaction; | |
} rmr_mbuf_t; | |
state | |
Is the current buffer state. Following a call to | |
rmr_send_msg the state indicates whether the buffer was | |
successfully sent which determines exactly what the | |
payload points to. If the send failed, the payload | |
referenced by the buffer is the message that failed to | |
send (allowing the application to attempt a | |
retransmission). When the state is a_OK the buffer | |
represents an empty buffer that the application may fill | |
in in preparation to send. | |
mtype | |
When sending a message, the application is expected to set | |
this field to the appropriate message type value (as | |
determined by the user programme). Upon send this value | |
determines how the a library will route the message. For a | |
buffer which has been received, this field will contain | |
the message type that was set by the sending application. | |
len | |
The application using a buffer to send a message is | |
expected to set the length value to the actual number of | |
bytes that it placed into the message. This is likely less | |
than the total number of bytes that the message can carry. | |
For a message buffer that is passed to the application as | |
the result of a receive call, this will be the value that | |
the sending application supplied and should indicate the | |
number of bytes in the payload which are valid. | |
payload | |
The payload is a pointer to the actual received data. The | |
user programme may read and write from/to the memory | |
referenced by the payload up until the point in time that | |
the buffer is used on a rmr_send, rmr_call or rmr_reply | |
function call. Once the buffer has been passed back to a a | |
library function the user programme should **NOT** make | |
use of the payload pointer. | |
xaction | |
The *xaction* field is a pointer to a fixed sized area in | |
the message into which the user may write a transaction | |
ID. The ID is optional with the exception of when the user | |
application uses the rmr_call function to send a message | |
and wait for the reply; the underlying processing expects | |
that the matching reply message will also contain the same | |
data in the *xaction* field. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The function returns a pointer to a rmr_mbuf structure, or | |
NULL on error. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
ENOMEM | |
Unable to allocate memory. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_mbuf(3) rmr_call(3), rmr_free_msg(3), | |
rmr_init(3), rmr_init_trace(3), rmr_get_trace(3), | |
rmr_get_trlen(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_set_trace(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_wh_call | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_wh_call( void* vctx, rmr_whid_t whid, rmr_mbuf_t* msg, int call_id, int max_wait ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_wh_call function accepts a message buffer (msg) from | |
the user application and attempts to send it using the | |
wormhole ID provided (whid). If the send is successful, the | |
call will block until either a response message is received, | |
or the max_wait number of milliseconds has passed. In order | |
for the response to be recognised as a response, the remote | |
process **must** use rmr_rts_msg() to send their response. | |
Like *rmr_wh_send_msg,* this function attempts to send the | |
message directly to a process at the other end of a wormhole | |
which was created with *rmr_wh_open().* When sending message | |
via wormholes, the normal RMR routing based on message type | |
is ignored, and the caller may leave the message type | |
unspecified in the message buffer (unless it is needed by the | |
receiving process). The call_id parameter is a number in the | |
range of 2 through 255 and is used to identify the calling | |
thread in order to properly match a response message when it | |
arrives. Providing this value, and ensuring the proper | |
uniqueness, is the responsibility of the user application and | |
as such the ability to use the rmr_wh_call() function from | |
potentially non-threaded concurrent applications (such as | |
Go's goroutines) is possible. | |
Retries | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The send operations in RMR will retry *soft* send failures | |
until one of three conditions occurs: | |
1. | |
The message is sent without error | |
2. | |
The underlying transport reports a *hard* failure | |
3. | |
The maximum number of retry loops has been attempted | |
A retry loop consists of approximately 1000 send attempts | |
**without** any intervening calls to *sleep()* or *usleep().* | |
The number of retry loops defaults to 1, thus a maximum of | |
1000 send attempts is performed before returning to the user | |
application. This value can be set at any point after RMr | |
initialisation using the *rmr_set_stimeout()* function | |
allowing the user application to completely disable retires | |
(set to 0), or to increase the number of retry loops. | |
Transport Level Blocking | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The underlying transport mechanism used to send messages is | |
configured in *non-blocking* mode. This means that if a | |
message cannot be sent immediately the transport mechanism | |
will **not** pause with the assumption that the inability to | |
send will clear quickly (within a few milliseconds). This | |
means that when the retry loop is completely disabled (set to | |
0), that the failure to accept a message for sending by the | |
underlying mechanisms (software or hardware) will be reported | |
immediately to the user application. | |
It should be noted that depending on the underlying transport | |
mechanism being used, it is extremely likely that retry | |
conditions will happen during normal operations. These are | |
completely out of RMR's control, and there is nothing that | |
RMR can do to avoid or mitigate these other than by allowing | |
RMR to retry the send operation, and even then it is possible | |
(e.g., during connection reattempts), that a single retry | |
loop is not enough to guarantee a successful send. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, new message buffer, with the payload containing | |
the response from the remote endpoint is returned. The state | |
in this buffer will reflect the overall send operation state | |
and should be RMR_OK. | |
If a message is returned with a state which is anything other | |
than RMR_OK, the indication is that the send was not | |
successful. The user application must check the state and | |
determine the course of action. If the return value is NULL, | |
no message, the indication is that there was no response | |
received within the timeout (max_wait) period of time. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The following values may be passed back in the *state* field | |
of the returned message buffer. | |
RMR_ERR_WHID | |
The wormhole ID passed in was not associated with an open | |
wormhole, or was out of range for a valid ID. | |
RMR_ERR_NOWHOPEN | |
No wormholes exist, further attempt to validate the ID are | |
skipped. | |
RMR_ERR_BADARG | |
The message buffer pointer did not refer to a valid | |
message. | |
RMR_ERR_NOHDR | |
The header in the message buffer was not valid or | |
corrupted. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
The following is a simple example of how the a wormhole is | |
created (rmr_wh_open) and then how rmr_wh_send_msg function | |
is used to send messages. Some error checking is omitted for | |
clarity. | |
:: | |
#include <rmr/rmr.h> // system headers omitted for clarity | |
int main() { | |
rmr_whid_t whid = -1; // wormhole id for sending | |
void* mrc; //msg router context | |
int i; | |
rmr_mbuf_t* sbuf; // send buffer | |
int count = 0; | |
int norm_msg_size = 1500; // most messages fit in this size | |
mrc = rmr_init( "43086", norm_msg_size, RMRFL_NONE ); | |
if( mrc == NULL ) { | |
fprintf( stderr, "[FAIL] unable to initialise RMR environment\\n" ); | |
exit( 1 ); | |
} | |
while( ! rmr_ready( mrc ) ) { // wait for routing table info | |
sleep( 1 ); | |
} | |
sbuf = rmr_alloc_msg( mrc, 2048 ); | |
while( 1 ) { | |
if( whid < 0 ) { | |
whid = rmr_wh_open( mrc, "localhost:6123" ); // open fails if endpoint refuses conn | |
if( RMR_WH_CONNECTED( wh ) ) { | |
snprintf( sbuf->payload, 1024, "periodic update from sender: %d", count++ ); | |
sbuf->len = strlen( sbuf->payload ); | |
sbuf = rmr_wh_call( mrc, whid, sbuf, 1000 ); // expect a response in 1s or less | |
if( sbuf != NULL && sbuf->state = RMR_OK ) { | |
sprintf( stderr, "response: %s\\n", sbuf->payload ); // assume they sent a string | |
} else { | |
sprintf( stderr, "response not received, or send error\\n" ); | |
} | |
} | |
} | |
sleep( 5 ); | |
} | |
} | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), | |
rmr_payload_size(3), rmr_rcv_msg(3), rmr_rcv_specific(3), | |
rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), | |
rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3), | |
rmr_set_stimeout(3), rmr_wh_open(3), rmr_wh_close(3), | |
rmr_wh_state(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_wh_close | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
void rmr_close( void* vctx, rmr_whid_t whid ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_wh_close function closes the wormhole associated with | |
the wormhole id passed in. Future calls to rmr_wh_send_msg | |
with this ID will fail. | |
The underlying TCP connection to the remote endpoint is | |
**not** closed as this session may be required for regularly | |
routed messages (messages routed based on message type). | |
There is no way to force a TCP session to be closed at this | |
point in time. | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_rcvfd(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_wh_open(3), | |
rmr_wh_send_msg(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_wh_open | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
void* rmr_wh_open( void* vctx, char* target ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_wh_open function creates a direct link for sending, a | |
wormhole, to another RMr based process. Sending messages | |
through a wormhole requires that the connection be | |
established overtly by the user application (via this | |
function), and that the ID returned by rmr_wh_open be passed | |
to the rmr_wh_send_msg function. | |
*Target* is the *name* or *IP-address* combination of the | |
processess that the wormhole should be connected to. *Vctx* | |
is the RMr void context pointer that was returned by the | |
rmr_init function. | |
When invoked, this function immediatly attempts to connect to | |
the target process. If the connection cannot be established, | |
an error is returned to the caller, and no direct messages | |
can be sent to the target. Once a wormhole is connected, the | |
underlying transport mechanism (e.g. NNG) will provide | |
reconnects should the connection be lost, however the | |
handling of messages sent when a connection is broken is | |
undetermined as each underlying transport mechanism may | |
handle buffering and retries differently. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
The rmr_wh_open function returns a type rmr_whid_t which must | |
be passed to the rmr_wh_send_msg function when sending a | |
message. The id may also be tested to determine success or | |
failure of the connection by using the RMR_WH_CONNECTED macro | |
and passing the ID as the parameter; a result of 1 indicates | |
that the connection was esablished and that the ID is valid. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The following error values are specifically set by this RMR | |
function. In some cases the error message of a system call is | |
propagated up, and thus this list might be incomplete. | |
EINVAL | |
A parameter passed was not valid. | |
EACCESS | |
The user application does not have the ability to | |
establish a wormhole to the indicated target (or maybe any | |
target). | |
ECONNREFUSED | |
The connection was refused. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
:: | |
void* rmc; | |
rmr_whid_t wh; | |
rmc = rmr_init( "43086", 4096, 0 ); // init context | |
wh = rmr_wh_open( rmc, "localhost:6123" ); | |
if( !RMR_WH_CONNECTED( wh ) ) { | |
fprintf( stderr, "unable to connect wormhole: %s\\n", | |
strerror( errno ) ); | |
} | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), | |
rmr_get_rcvfd(3), rmr_payload_size(3), rmr_send_msg(3), | |
rmr_rcv_msg(3), rmr_rcv_specific(3), rmr_rts_msg(3), | |
rmr_ready(3), rmr_fib(3), rmr_has_str(3), rmr_tokenise(3), | |
rmr_mk_ring(3), rmr_ring_free(3), rmr_wh_close(3), | |
rmr_wh_send_msg(3), rmr_wh_state(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_wh_send_msg | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
rmr_mbuf_t* rmr_wh_send_msg( void* vctx, rmr_whid_t id, rmr_mbuf_t* msg ); | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_wh_send_msg function accepts a message buffer from | |
the user application and attempts to send it using the | |
wormhole ID provided (id). Unlike *rmr_send_msg,* this | |
function attempts to send the message directly to a process | |
at the other end of a wormhole which was created with | |
*rmr_wh_open().* When sending message via wormholes, the | |
normal RMR routing based on message type is ignored, and the | |
caller may leave the message type unspecified in the message | |
buffer (unless it is needed by the receiving process). | |
The message buffer (msg) used to send is the same format as | |
used for regular RMR send and reply to sender operations, | |
thus any buffer allocated by these means, or calls to | |
*rmr_rcv_msg()* can be passed to this function. | |
Retries | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The send operations in RMR will retry *soft* send failures | |
until one of three conditions occurs: | |
1. | |
The message is sent without error | |
2. | |
The underlying transport reports a *hard* failure | |
3. | |
The maximum number of retry loops has been attempted | |
A retry loop consists of approximately 1000 send attempts | |
**without** any intervening calls to *sleep()* or *usleep().* | |
The number of retry loops defaults to 1, thus a maximum of | |
1000 send attempts is performed before returning to the user | |
application. This value can be set at any point after RMr | |
initialisation using the *rmr_set_stimeout()* function | |
allowing the user application to completely disable retires | |
(set to 0), or to increase the number of retry loops. | |
Transport Level Blocking | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
The underlying transport mechanism used to send messages is | |
configured in *non-blocking* mode. This means that if a | |
message cannot be sent immediately the transport mechanism | |
will **not** pause with the assumption that the inability to | |
send will clear quickly (within a few milliseconds). This | |
means that when the retry loop is completely disabled (set to | |
0), that the failure to accept a message for sending by the | |
underlying mechanisms (software or hardware) will be reported | |
immediately to the user application. | |
It should be noted that depending on the underlying transport | |
mechanism being used, it is extremely likely that retry | |
conditions will happen during normal operations. These are | |
completely out of RMR's control, and there is nothing that | |
RMR can do to avoid or mitigate these other than by allowing | |
RMR to retry the send operation, and even then it is possible | |
(e.g., during connection reattempts), that a single retry | |
loop is not enough to guarantee a successful send. | |
RETURN VALUE | |
-------------------------------------------------------------------------------------------- | |
On success, a new message buffer, with an empty payload, is | |
returned for the application to use for the next send. The | |
state in this buffer will reflect the overall send operation | |
state and should be RMR_OK. | |
If the state in the returned buffer is anything other than | |
RMR_OK, the user application may need to attempt a | |
retransmission of the message, or take other action depending | |
on the setting of errno as described below. | |
In the event of extreme failure, a nil pointer is returned. | |
In this case the value of errno might be of some use, for | |
documentation, but there will be little that the user | |
application can do other than to move on. | |
ERRORS | |
-------------------------------------------------------------------------------------------- | |
The following values may be passed back in the *state* field | |
of the returned message buffer. | |
RMR_ERR_WHID | |
The wormhole ID passed in was not associated with an open | |
wormhole, or was out of range for a valid ID. | |
RMR_ERR_NOWHOPEN | |
No wormholes exist, further attempt to validate the ID are | |
skipped. | |
RMR_ERR_BADARG | |
The message buffer pointer did not refer to a valid | |
message. | |
RMR_ERR_NOHDR | |
The header in the message buffer was not valid or | |
corrupted. | |
The following values may be assigned to errno on failure. | |
INVAL | |
Parameter(s) passed to the function were not valid, or the | |
underlying message processing environment was unable to | |
interpret the message. | |
ENOKEY | |
The header information in the message buffer was invalid. | |
ENXIO | |
No known endpoint for the message could be found. | |
EMSGSIZE | |
The underlying transport refused to accept the message | |
because of a size value issue (message was not attempted | |
to be sent). | |
EFAULT | |
The message referenced by the message buffer is corrupt | |
(nil pointer or bad internal length). | |
EBADF | |
Internal RMR error; information provided to the message | |
transport environment was not valid. | |
ENOTSUP | |
Sending was not supported by the underlying message | |
transport. | |
EFSM | |
The device is not in a state that can accept the message. | |
EAGAIN | |
The device is not able to accept a message for sending. | |
The user application should attempt to resend. | |
EINTR | |
The operation was interrupted by delivery of a signal | |
before the message was sent. | |
ETIMEDOUT | |
The underlying message environment timed out during the | |
send process. | |
ETERM | |
The underlying message environment is in a shutdown state. | |
EXAMPLE | |
-------------------------------------------------------------------------------------------- | |
The following is a simple example of how the a wormhole is | |
created (rmr_wh_open) and then how rmr_wh_send_msg function | |
is used to send messages. Some error checking is omitted for | |
clarity. | |
:: | |
#include <rmr/rmr.h> // system headers omitted for clarity | |
int main() { | |
rmr_whid_t whid = -1; // wormhole id for sending | |
void* mrc; //msg router context | |
int i; | |
rmr_mbuf_t* sbuf; // send buffer | |
int count = 0; | |
int norm_msg_size = 1500; // most msg fit in this size | |
mrc = rmr_init( "43086", norm_msg_size, RMRFL_NONE ); | |
if( mrc == NULL ) { | |
fprintf( stderr, "[FAIL] unable to initialise RMR environment\\n" ); | |
exit( 1 ); | |
} | |
while( ! rmr_ready( mrc ) ) { // wait for routing table info | |
sleep( 1 ); | |
} | |
sbuf = rmr_alloc_msg( mrc, 2048 ); | |
while( 1 ) { | |
if( whid < 0 ) { | |
whid = rmr_wh_open( mrc, "localhost:6123" ); // open fails if endpoint refuses conn | |
if( RMR_WH_CONNECTED( wh ) ) { | |
snprintf( sbuf->payload, 1024, "periodic update from sender: %d", count++ ); | |
sbuf->len = strlen( sbuf->payload ); | |
sbuf = rmr_wh_send_msg( mrc, whid, sbuf ); | |
} | |
} | |
sleep( 5 ); | |
} | |
} | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_alloc_msg(3), rmr_call(3), rmr_free_msg(3), rmr_init(3), | |
rmr_payload_size(3), rmr_rcv_msg(3), rmr_rcv_specific(3), | |
rmr_rts_msg(3), rmr_ready(3), rmr_fib(3), rmr_has_str(3), | |
rmr_tokenise(3), rmr_mk_ring(3), rmr_ring_free(3), | |
rmr_set_stimeout(3), rmr_wh_open(3), rmr_wh_close(3), | |
rmr_wh_state(3) | |
NAME | |
-------------------------------------------------------------------------------------------- | |
rmr_wh_state | |
SYNOPSIS | |
-------------------------------------------------------------------------------------------- | |
:: | |
#include <rmr/rmr.h> | |
int rmr_wh_state( void* vctx, rmr_whid_t whid ) | |
DESCRIPTION | |
-------------------------------------------------------------------------------------------- | |
The rmr_wh_state function will return the current state of | |
the connection associated with the given wormhole (whid). The | |
return value indicates whether the connection is open | |
(RMR_OK), or closed (any other return value). | |
When using some transport mechanisms (e.g. NNG), it may not | |
be possible for RMR to know the actual state and the | |
connection may always be reported as "open." | |
RETURN | |
-------------------------------------------------------------------------------------------- | |
The following values are potential return values. | |
RMR_OK | |
The wormhole ID is valid and the connection is "open." | |
RMR_ERR_WHID | |
THe wormhole ID passed into the function was not valid. | |
RMR_ERR_NOENDPT | |
The wormhole is not open (not connected). | |
RMR_ERR_BADARG | |
The context passed to the function was nil or invalid. | |
RMR_ERR_NOWHOPEN | |
Wormholes have not been initialised (no wormhole open call | |
has been made). | |
SEE ALSO | |
-------------------------------------------------------------------------------------------- | |
rmr_wh_open(3), rmr_wh_send_msg(3), rmr_wh_close(3) |