Infrastructure Messaging Layer
The msg (messaging) API is a wrapper for the MO (message object) layer
, the IO layer, and
ORB.
The msg layer uses integer handles for referencing messages.
A message object is partitioned into records containing fields.
The first record is number 1 (one) and always contains the fields:
"type", "code", "status",
and "reqid".
For an explanation of the use of these fields, please see the
ORB documentation.
Fields are name/value pairs and are opaque as to actual storage type.
Messages are created for a specific destination or to be sent across a
specific virtual circuit.
As in an MO, a field may be inserted at the integer 1234 and retrieved as the
ascii string "1234".
All message API functions return an integer except msgGetMp() which
returns a character pointer.
When a message is transmitted via socket, only the required data is actually
moved, thus, when it arrives, the message is no longer the default size.
Also remember that the received message handle contains all the information
about the sender and how to return information to the sender.
Messages are created with a destination defined (attached to a virtual circuit)
and as fields and records are added to the message transmissions of
packets may occur unbeknownst to the caller.
The final msgSnd will alert the receiving end that the last data has been
transmitted.
Also be aware that as information is extracted, from the received message,
waits may occur unbeknownst to the caller so that more information may be
made available from the sender.
One paradigm to consider is that a requester (process) may be unloading fields
from a message while the sender, on a different process (and on another
machine), is still placing fields into the message.
The size of things:
There are some restrictions on the size of fields so that multi-packeting works correctly.
Integers are not a problem, that is, if you attempt to place an integer into a message that is full, the system will send the current packet, marked DTF, create a new packet, and place the new integer into it as the first field.
If you attempt to place a single string field into a message that overflows the max message size (see Big String below), the string will be broken into two or more pieces and multiple packets transmitted until the string is completely moved where it will be reassembled at the peer "Gets" the field.
Note that msgGetFldLen() can tell how much memory must be allocated to hold a string the applicaiton is about to "Get".
Binary fields may now be handled just as big strings, using msgPutB(),,,,,,,, msgGetB(), and msgGetBa().
And while mentioning msgGetBa (which allocates space for the entire fetched binary field) there is also a msgGetSa() which allocates the space for the entire string (note these uchar arrays must be freed by the caller).
The default message size is 40K, but can be changed with the
"MSG_DFLT_LEN" configuration keyword (in milliseconds).
Message layer ioRcv timeout is set at 10 seconds (10000 Milliseconds) but may
be changed using the "MSG_DFLT_TIMOT" configuration keyword.
Caveat: When processing a received multi-packet message, if you need to re-access field data, you must save the data from the first access, since the current packet will be deleted if another packet (multi-packet receive) must be received to fill in a large field.
So when using large fields requiring multi-packets, you should ask for them in the same order they were placed in the message.
This is one of the few times that field order is important.
Internally there are four sub-layers:
Rtr, BigString, Multi-Pkt, and Basic messaging.
Basic messaging
creates, transmitts, receives, and frees single packet
Mos.
Multi-Pkt
handles a sort of session which delivers an extended mo (actually multiple
Mos) for moving large numbers of fields.
BigString
sub-layer
breaks string fields into about 30K characters and then moves them as
multiple fields, usually involving multi-pkt.
The
Rtr
sub-layer adds information used by the router for
determining the path and final type and code of a request which must
be executed at a remote
ORB.
msgAckNak, msgDup, msgFree, msgFwdDst, msgFwdId, msgGetFldInfo,
msgGetB, msgGetFldLen, msgGetI, msgGetId, msgGetLen,
msgGetMp, msgGetS, msgInit, msgMkDst, msgMkId, msgMkReq,
msgMkRsp, msgNxtFld, msgPutB, msgPutFmt, msgPutI, msgPutS,
msgRcd, msgRcv, msgRew, msgRst, msgRtn, msgSnd, and last but
not least, rtrMkReq.
msgAckNak( int hndl, int status )
Create and send a response message to the message referencde by "hndl"
with "status" = the "status" msgFwdId( int hndl, int sd)
argument.
msgDup( int hndl )
Duplicate the message referenced by "hndl". This may be necessary
if you need to send a message to two places, or if a higher process layer
expects to free the message and a lower layer needs to send it
somewhere else. Returns the new message handle.
msgFree( int hndl )
Frees / releases the space allocated to the message.
msgFwdDst( int hndl, char *dest )
Forward the message referenced by "hndl" to the destination "dest".
This consittues a redirection of the messages's original destination.
Returns OK is send works, else ERR. May, on occasion, return a
NOTFND if the system is under heavy load, meaning the message is
queued for output but not yet transmitted.
msgFwdId( int hndl, int sd )
Same as msgFwdDst except message is redirected along the IO path handle
"sd".
msgGetB( int hndl, char *name, uchar *data )
Get the information named "name" from the current record and store it
as binary into "data". Returns the number of bytes stored.
msgGetFldInfo( int hndl, char *fnam, int *len )
Get the type, name and length of the current field. This is normally
used with msgNxtFld(). Returns field type else ERR.
msgGetFldLen( int hndl, char *fldNam )
Get the length of the named field in the current record. Returns field
length in byts else NOTFND or ERR.
msgGetI( int hndl, char *name, int *data )
Get the information named "name" from the current record and store
it, as an integer into "data". Returns the number of bytes
stored.
msgGetId( int hndl )
Returns the actual IO layer circuit ID that the message is attached.
msgGetLen( hndl )
Return the overall length of the message.
msgGetMp( int hndl )
Get the underlying character pointer to the I/O message and Message
Object. Note that you must be very careful using this pointer due
to the msg API sending multi-packets based on calls to msgPutFld and
msgRcd.
msgGetS( int hndl, char *name, char *data )
Get the information named "name" from the current record and store it
as a string in "data".
msgInit( int argc, char *argv[] )
Initialize the message interface reading a configuration file.
msgMkDst( char *dest )
Creates a message of the default size. The destination is established to the
named process for the first and any additional packets. Returns an
integer handle for referencing the message.
msgMkId( int id )
Creates a message of the default size. The destination is established via
the supplied I/O Virtual Circuit ID for the first and any additional
packets. Returns an integer handle for referencing the new message.
msgMkReq( char *dest, int type, int code )
Creates a message of the default size. The destination is established to the
named process for the first and any additional packets. Adds fields
"type" = argument "type", "code" = argument "code",
"status" =0, and "reqId" =0. Returns an integer handle for
referencing the new message.
msgMkRsp( int oldHndl, int stat )
Creates a message of the default size. The destination is established to the
source of the message referenced by "oldHndl" for the first and
any additional packets. Returns an integer handle for referencing
the new message.
msgNxtFld( int hndl, char *fName, int *fLen )
Move the internal field pointer to the next field. Returns the type of
the next field.
msgPutB( int hndl, char *name, uchar *data )
Add a new field to the current record named "name". The data is
taken from the binary "data".
msgPutFmt( int hndl, char *name, char *fmt, ... )
Add a new field to the current record named "name". The data will be
type STRING and consists of the foramat string "fmt" and any
converted arguments (...). Conversions and arguments are identical
to sprintf.
msgPutI( int hndl, char *name, int data )
Add a new field to the current record named "name". The data is
taken from the integer "data".
msgPutS( int hndl, char *name, char *data )
Add a new field to the current record named "name". The data is
taken from the string "data".
msgRcd( int hndl, int rcdNbr )
Move the internal "current record indicator" to a specific record within the
message object, indicated by
"rcdNbr". If "rcdNbr" is zero, move the the next available
record, or if in the create / put mode, add another record.
msgRcv( int waitTime )
Wait for "waitTime" milliseconds or until a message is received. If
"waitTime" is negative, wait forever. The handle is returned if
a message is received else a zero (timeout) or negative is returned
(error).
msgRew( int hndl )
The internal pointers in the message are all set back to the beginning
record and fields. This call is made after building a new message
and transmitting it, by the msgSnd() call. Is should also be used
before running moPnt() (see mo description).
msgRst( int hndl )
Re-initializes the message object within the message and restores the message to
it's default size.
msgRtn( hndl )
Return the message to it's origin. This is usually used with msgRst and
following msgPutFld calls.
rtrMkReq( char *dest, char *path, int xType, int xCode )
Creates a message of the default size. The destination is established to the
named process (usually the local Orb) for the first and any
additional packets. Adds fields "type" = OSRVRTR, "code" =
RTRFWD, "status" =0, "reqId" =0, "rtrPath" = "path"
"execType" = "xType", "execCode" = xCode, and "questor"
= localProcessName + HostName. Returns an integer handle for
referencing the new message.