Attachments consist of multiple physical
messages. The beginning of an attachment is recognized by having a
message type of 100000. To identify this message, it will be referred
to as the attachment header.
Layout of an attachment
header message:
Note: All character strings are
null terminated.
byte[24] - header correlid
(correlationid of this header
message)
long - original msg type (msg type
provided
by the
sending application)
byte[24] - original msg correlid (msg correlationid
provided by the sending application)
byte[24] - message correlid (generated correlationid for
the msg)
int - number of attachments
--------------------------------------------------------
int - attachment type
1 - SAS data set
2 - External text file
3 - External binary file
byte[24] - attachment correlid (correlationid associated
with this attachment)
int - length of qualifier 1
char[] - qualifier 1
external files: designates the sending file
specification "FILENAME" or "FILEREF"
dataset: designates the sending library name
int - length of qualifier 2
char[] - qualifier 2
external files: designates the sending
filename or fileref
dataset: designates the sending member name
int - length of attachment description
char[] - attachment description
int - user specified minor version number
int - user specified major version number
--------------------------------------------------------
.
.
. repeat for each attachment in the list
Other physical messages
are also needed to make up a complete attachment. These messages will
be called subordinated messages, and they all have a message type
of 100001.
The subordinate message
that usually follows after the attachment header message is the application
message. It can be filtered by using the message correlid located
in the attachment header message. It contains the actual application-generated
message.
The attachment (external
file or SAS data set) subordinate messages follow next. They contain
the necessary information to re-create the file or data set.
To locate the subordinate
message that contains the number of physical messages that are associated
with this attachment, filter it by using the attachment correlid that
is located in the attachment header message. The content of this message
is a single numeric integer that corresponds to the number of messages
that are associated with this attachment, excluding this message.
To filter the rest of the messages that are associated with this attachment,
use the same attachment correlid that is located in the attachment
header message (16 bytes) with a sequence number (4 bytes) added to
the end of it. For example, if the attachment correlid was 000102030405060708090A0B0C0D0E0F,
you would filter this message to find out how many more messages are
associated with this attachment. For example, if three more messages
make up this attachment, then you can locate these messages by filtering
a correlid of 000102030405060708090A0B0C0D0E0F00000001, 000102030405060708090A0B0C0D0E0F00000002,
and 000102030405060708090A0B0C0D0E0F00000003, respectively. The sequenced
attachment correlid messages are actually sent to the queue before
the non-sequenced attachment correlid message. Therefore, if you are
able to receive the non-sequenced attachment correlid message (that
is, a message that tells you how many messages make up this attachment),
then you can make sure that the complete attachment has been queued.
At this point, attachment
processing differs depending on the attachment type.
For external files,
the first sequenced attachment correlid message (attachment_correlid+00000001)
contains two numeric integers that correspond to the file's logical
record length and size, respectively. The rest of the attachment correlid
messages make up the file itself. The contents of these messages are
as follows:
--------------------------------
long - size of logical record
char[] - actual record
--------------------------------
.
.
. repeat until the end of file or 32K limit is reached
These messages are limited
to 32K. If a file is too large to fit, then it spans multiple physical
messages.
Here is an example of
an external file attachment residing on a queue:
msg type
msg correlid msg contents
-------- ------------
------------
100000 1111111111111111111111111111111100000000
1111111111111111111111111111111100000000
00000001
0000000000000000000000000000000000000000
2222222222222222222222222222222200000000
00000001
00000003
3333333333333333333333333333333300000000
00000008
"FILENAME"
0000000D
"d:\mytext.txt"
0000000C
"Text file..."
00000000
00000000
100001 2222222222222222222222222222222200000000 "This is the actual
application message."
100001 3333333333333333333333333333333300000001 lrecl|filesize
100001 3333333333333333333333333333333300000002
len|record|len|record|len|record...
100001 3333333333333333333333333333333300000003
len|record|len|record|len|record...
100001 3333333333333333333333333333333300000000 00000003
For data sets, the sequenced
attachment correlid messages begin with a type identifier. This identifier
signifies the type of information that is in this message. A type
identifier of one signifies data set definitions. A type identifier
of two signifies variable definitions. A type identifier of three
signifies actual observations. Type identifiers four (indexes) and
five (integrity constraints) usually have no use and can be ignored.
Note: All character strings are null
terminated.
Layout of a data set definition
message:
int - type (data set definition=1)
int - version (future)
long - data set type length
char[] - data set type
long - data set label length
char[] - data set label
long - number of observations
long - number of variables
long - observation length
long - length of compress
char[] - compress
char - reuse
long - length of encrypt
char[] - encrypt
long - number of variables in sort key
long - length of sort collating sequence
char[] - sort collating sequence
short - sort flags
int - read password flag
byte[4] - read password (encrypted)
int - write password flag
byte[4] - write password (encrypted)
int - alter password flag
byte[4] - alter password (encrypted)
Layout of a variable definition message:
int - type (variable definition=2)
-----------------------------------
long - length of variable name
char[] - variable name
long - length of format name
char[] - format name
long - length of informat name
char[] - informat name
long - variable label length
char[] - variable label
char - variable type (1=double, otherwise character)
long - variable length
long - format field length
long - format decimal
long - informat field length
long - informat decimal
char - nsort
-----------------------------------
.
.
. repeat for each variable
Note: Variable definitions might span multiple physical
messages if definitions are larger than 32K.
Layout of an observation message:
int - type (observation=3)
data - the layout of data is defined by the variable
definition above
Note: Observations might span multiple physical messages
if they are larger than 32K.
Layout of an index message:
int - type (index=4)
-----------------------------------
long - upercmx
long - length of index/key name
char[] - index/key name
long - flags
long - number of variables in the index/key
long - variable lengths added together
char[] - all variables null terminated
-----------------------------------
.
.
. repeat for each index