The Reference Message samples allow a large object to be transferred from one node to another (usually on different systems) without the need for the object to be stored on WebSphere MQ queues at either the source or the destination nodes.
A set of sample programs is provided to demonstrate how Reference Messages can be 1) put to a queue, 2) received by message exits, and 3) taken from a queue. The sample programs use Reference Messages to move files. If you want to move other objects such as databases, or if you want to perform security checks, you must define your own exit, based on our sample, amqsxrm. The following sections describe the Reference Message sample programs.
There are four versions of the Reference Message exit sample program. The one to use depends on the platform on which the channel is running. If the sender channel is running on:
To receive a Reference Message using the sample message exit, specify a file in the root file system of IFS or any sub-directory so that a stream file can be created. The sample message exit on OS/400 creates the file, converts the data to EBCDIC, and sets the code page to your system code page. You then have the option of copying this file to the QSYS.LIB file system using the CPYFRMSTMF command. For example:
CPYFRMSTMF FROMSTMF('JANEP/TEST.TXT') TOMBR('qsys.lib.janep.lib/test.fie/test.mbr') MBROPT(*REPLACE) CVTDTA(*NONE)
Note that the CPYFRMSTMF command does not create the file. You must create it before running this command.
If you send a file from QSYS.LIB no changes are required to the samples. For any other file system ensure that the CCSID specified in the CodedCharSetId field in the MQRMH structure matches the bulk data you are sending.
When using the integrated file system, create program modules with the SYSIFCOPT(*IFSIO) option set. If you want to move database or fixed-length record files, define your own exit based on the supplied sample AMQSXRM4.
The Reference Message samples run as follows:
Figure 34. Running the Reference Message samples
For the purposes of describing how to set-up the Reference Message example this refers to the sending machine as MACHINE1 with a queue manager called QMGR1 and the receiving machine as MACHINE2 with a queue manager called QMGR2.
The application that receives the Reference Message (AMQSGRM or AMQSGRMA on OS/400) is triggered using the initiation queue INITQ and process PROC. You need to ensure the CONNAME fields are set correctly and the MSGEXIT field reflects your directory structure, depending on machine type and where the WebSphere MQ product is installed.
The MQSC definitions have used an AIX style for defining the exits, so if you are using MQSC on OS/400 you will need to modify these accordingly. It is important to note that the message data FLATFILE is case sensitive and the sample will not work unless it is in uppercase.
On machine MACHINE1, queue manager QMGR1
MQSC syntax
define chl(chl1) chltype(sdr) trptype(tcp) conname('machine2') xmitq(xmitq) msgdata(FLATFILE) msgexit('/usr/lpp/mqm/samp/bin/amqsxrm(MsgExit)') define ql(xmitq) usage(xmitq) define chl(report) chltype(rcvr) trptype(tcp) replace define qr(qr) rname(dq) rqmname(qmgr2) xmitq(xmitq) replace
OS/400 command syntax
CRTMQMCHL CHLNAME(CHL1) CHLTYPE(*SDR) MQMNAME(QMGR1) + REPLACE(*YES) TRPTYPE(*TCP) + CONNAME('MACHINE2(60501)') TMQNAME(XMITQ) + MSGEXIT(QMQM/AMQSXRM4) MSGUSRDATA(FLATFILE) CRTMQMQ QNAME(XMITQ) QTYPE(*LCL) MQMNAME(QMGR1) + REPLACE(*YES) USAGE(*TMQ) CRTMQMCHL CHLNAME(REPORT) CHLTYPE(*RCVR) + MQMNAME(QMGR1) REPLACE(*YES) TRPTYPE(*TCP) CRTMQMQ QNAME(QR) QTYPE(*RMT) MQMNAME(QMGR1) + REPLACE(*YES) RMTQNAME(DQ) + RMTMQMNAME(QMGR2) TMQNAME(XMITQ)
On machine MACHINE2, queue manager QMGR2
MQSC syntax
define chl(chl1) chltype(rcvr) trptype(tcp) msgexit('/usr/lpp/mqm/samp/bin/amqsxrm(MsgExit)') msgdata(flatfile) define chl(report) chltype(sdr) trptype(tcp) conname('MACHINE1') xmitq(qmgr1) define ql(initq) define ql(qmgr1) usage(xmitq) define pro(proc) applicid('/usr/lpp/mqm/samp/bin/amqsgrm') define ql(dq) initq(initq) process(proc) trigger trigtype(first)
OS/400 command syntax
CRTMQMCHL CHLNAME(CHL1) CHLTYPE(*RCVR) MQMNAME(QMGR2) + REPLACE(*YES) TRPTYPE(*TCP) + MSGEXIT(QMQM/AMQSXRM4) MSGUSRDATA(FLATFILE) CRTMQMCHL CHLNAME(REPORT) CHLTYPE(*SDR) MQMNAME(QMGR2) + REPLACE(*YES) TRPTYPE(*TCP) + CONNAME('MACHINE1(60500)') TMQNAME(QMGR1) CRTMQMQ QNAME(INITQ) QTYPE(*LCL) MQMNAME(QMGR2) + REPLACE(*YES) USAGE(*NORMAL) CRTMQMQ QNAME(QMGR1) QTYPE(*LCL) MQMNAME(QMGR2) + REPLACE(*YES) USAGE(*TMQ) CRTMQMPRC PRCNAME(PROC) MQMNAME(QMGR2) REPLACE(*YES) + APPID('QMQM/AMQSGRM4') CRTMQMQ QNAME(DQ) QTYPE(*LCL) MQMNAME(QMGR2) + REPLACE(*YES) PRCNAME(PROC) TRGENBL(*YES) + INITQNAME(INITQ)
-m | Name of the local queue manager, this defaults to the default queue manager |
-i | Name and location of source file |
-o | Name and location of destination file |
-q | Name of queue |
-g | Name of queue manager where the queue, defined in the -q parameter exists This defaults to the queue manager specified in the -m parameter |
-t | Object type |
-w | Wait interval, that is, the waiting time for exception and COA reports from the receiving queue manager |
For example, to use the sample with the objects defined above you would use the following parameters:
-mQMGR1 -iInput File -oOutput File -qQR -tFLATFILE -w120
Increasing the waiting time will allow time for a large file to be sent across a network before the program putting the messages times out.
amqsprm -q QR -m QMGR1 -i d:\x\file.in -o d:\y\file.out -t FLATFILE
OS/400 users:
CALL PGM(QMQM/AMQSPRM4) PARM('-mQMGR1' + '-i/refmsgs/rmsg1' + '-o/refmsgs/rmsgx' '-qQR' + '-gQMGR1' '-tFLATFILE' '-w15')
This assumes that the original file rmsg1 is in IFS directory /refmsgs and you want the destination file to be rmsgx in IFS directory /refmsgs on the target system.
For example:
amqsprm /i d:\files\infile.dat /o e:\files\outfile.dat /q QR /m QMGR1 /w 30 /t FLATFILE
amqsprm -i /files/infile.dat -o e:\\files\\outfile.dat -q QR -m QMGR1 -w 30 -t FLATFILE
Running the put Reference Message program does the following:
msgexit('<pathname>\amqsxrm.dll(MsgExit)')
This is defined on WebSphere MQ for AIX, WebSphere MQ for HP-UX, MQSeries for DIGITAL UNIX (Compaq Tru64 UNIX), and WebSphere MQ for Solaris as follows:
msgexit('<pathname>/amqsxrm(MsgExit)')
If a pathname is specified, the complete name must be specified (including the extension .dll on OS/2). If a pathname is not specified, it is assumed that the program is in the path specified in the qm.ini file (or, on WebSphere MQ for Windows, the path specified in the registry). This is explained fully in WebSphere MQ Intercommunication.
This sample creates a Reference Message that refers to a file and puts it on a specified queue:
amqsprm -q QR -m QMGR1 -i d:\x\file.in -o d:\y\file.out -t FLATFILE
Where QR is a remote queue definition that refers to a target queue on QMGR2.
amqsprm -q QR -m QMGR1 -i /x/file.in -o d:\\y\\file.out -t FLATFILE
This sample recognizes Reference Messages with an object type that matches the object type in the message exit user data field of the channel definition. For these messages, the following happens:
For sender and server channels, if the DataLogicalLength field in the input Reference Message is zero, the remaining part of the file, from DataLogicalOffset to the end of the file, is to be sent along the channel. If it is not zero, only the length specified is sent.
If an error occurs (for example, if the sample is unable to open a file), MQCXP.ExitResponse is set to MQXCC_SUPPRESS_FUNCTION so that the message being processed is put to the dead-letter queue instead of continuing to the destination queue. A feedback code is returned in MQCXP.Feedback and returned to the application that put the message in the Feedback field of the message descriptor of a report message. This is because the putting application requested exception reports by setting MQRO_EXCEPTION in the Report field of the MQMD.
If the encoding or CodedCharacterSetId (CCSID) of the Reference Message is different from that of the queue manager, the Reference Message is converted to the local encoding and CCSID. In our sample, amqsprm, the format of the object is MQFMT_STRING, so amqsxrm converts the object data to the local CCSID at the receiving end before the data is written to the file.
The format of the file being transferred should not be specified as MQFMT_STRING if the file contains multibyte characters (for example, DBCS or Unicode). This is because a multibyte character could be split when the file is segmented at the sending end. To transfer and convert such a file, the format should be specified as something other than MQFMT_STRING so that the Reference Message exit does not convert it and the file should be converted at the receiving end when the transfer is complete.
To compile amqsxrma, use the following commands:
$xlc_r -c -I/usr/mqm/inc amqsxrma.c $ld -o amqsxrm amqsxrma.o -H512 -T512 -e MQStart \ -bM:SRE -bE:amqsxrm.exp -lc_r -ls_r -lmqm_r -lpthreads
In a non-threaded environment:
$ cc -std1 -c -I /opt/mqm/inc amqsxrma.c $ cc -std1 -shared -o amqsxrma amqsxrma.o -L /opt/mqm/lib -lmqm -e MQStart -lc
In a threaded environment:
$ cc -std1 -c -I /opt/mqm/inc amqsxrma.c $ cc -std1 -shared -pthread -o amqsxrma_r amqsxrma.o -L /opt/mqm/lib \ -lmqm_r -e MQStart -lc
$ cc -std1 -c -I /opt/mqm/inc amqsxrma.c $ cc -std1 -shared -pthread -o amqsxrma amqsxrma.o -L /opt/mqm/lib \ -lmqm -e MQStart -lc
$ cc -c -Aa +z -I/opt/mqm/inc amqsxrma.c $ ld -b -o amqsxrm amqsxrma.o -z +b : -lmqm -lc
$ gcc -c -I/opt/mqm/inc amqsxrma.c $ gcc -o amqsxrm amqsxrma.o -shared \ -L/opt/mqm/lib -lmqm
To create the module use the following command:
CRTCMOD MODULE(MYLIB/AMQSXRMA) SRCFILE(QMQMSAMP/QCSRC) TERASPACE(*YES *TSIFC)
Notes:
$ cc -c -KPIC -I/opt/mqm/inc amqsxrma.c $ ld -G -o amqsxrm amqsxrma.o -dy -lmqm -lc -lnsl -ldl
cl amqsxrma.c -o amqsxrm.dll -LD -DEFAULTLIB mqm.lib mqmvx.lib amqsxrm.def
The program logic is as follows: