If you have ever tried to transfer data or have programs communicate between two different operating systems, then you know that the process can be fraught with perils. How do you translate the data? How do you know that you got the entire transmission? These are just a few of the problems that may be encountered. IBM developed MQSeries to remove these barriers to cross-platform development. When using MQSeries, the developer simply uses the IBM-supplied APIs to put a message on the appropriate queue. MQSeries handles the complexities of translating the data, making the transmission, and assuring it’s delivered completely and accurately.
The Nuts and Bolts of MQSeries
At the core of MQSeries are messages. Messages consist of two components: the application data and a descriptor. The application data is simply a string of bytes that is meaningful to some other application on a different platform or the same platform. The descriptor contains information that is meaningful to MQSeries such as the priority of the message, its type, and its length. There are four types of MQSeries messages:
• Datagram—Does not require a reply
• Request—Requires a reply
• Reply—A reply to a request message
• Report—Reports an event such as a transmission error
In order to be transmitted, messages are placed on queues by the queue manager. A queue can be thought of as a list of messages that are waiting to be processed by some application. Queues are defined as either local or remote depending on whether they exist on the local system. The queue manager handles the complexities of routing the messages to the appropriate queues on the desired system. (Note that the AS/400 implementation of MQSeries only supports one queue manager. Other platforms such as Windows NT support multiple queue managers on the same system.) Essentially, the queue manager is
the brains behind MQSeries. The manager manipulates the messages between queues, creates the message header, and translates the message data from EBCDIC to ASCII or vice versa. Messages are transferred to different queue managers through the use of channels.
Channels are one-way streets. Therefore, if two-way communication is required, two channels must be defined. (These are usually described as inbound and outbound.) There are six different types of queues that can be created for MQSeries:
• Initiation queues—Initiation queues are used for processing trigger messages. Trigger messages are a special type of message that are generally used to cause a program to be invoked when a predetermined number of messages are waiting on a queue.
• Transmission queues—These are used to store messages that will later be transferred to a remote system when it becomes available. For each remote queue manager defined on your system, at least one transmission queue must be defined.
• Event queues—When certain events occur in an application program, a message can be placed in an event queue to notify other applications.
• Undelivered-message queue—This is also known as a dead letter queue and is used to store messages that could not be successfully delivered.
• SYSTEM.ADMIN.COMMAND.QUEUE—This queue, which must be defined for each queue manager, is used to pass MQSeries commands to MQSeries for processing.
• System default queues—These are a series of queues that are provided with MQSeries by IBM that can be copied and used in your own applications.
MQSeries Interface—The Ties that Bind
The MQSeries Interface (MQI) is a set of 13 APIs that provide the tools necessary to allow your application programs to communicate with the queue manager. (Note that all APIs are not supported on every platform. See the MQSeries Application Programming Guide for more information.) Here’s a list of the APIs and their associated functions:
• MQCONN—Connects to a queue manager
• MQCONNX—Same as MQCONN, but adds additional options to control the call
• QOPEN—Opens an object such as a message queue
• MQOPEN1—Opens a queue, places one message on the queue, and then closes the queue in a single call
• MQGET—Retrieves a message from a queue
• MQCLOSE—Closes an object
• MQDISC—Disconnects from a queue manager
• MQINQ—Inquires about the attributes of an object
• MQSET—Sets the attributes of a queue
• MQBEGIN—Begins a unit of work
• MQCMIT—Commits changes
• MQROLL—Rolls back changes
In most applications, the following sequence of calls would be used: Call MQOPEN to open a queue object, use MQPUT/MQGET to either put or retrieve the message, and finally execute MQCLOSE to close the queue. The commitment control commands (MQCMIT and MQROLL) are not typically used on the AS/400 since OS/400 handles those functions automatically.
The available APIs can be called using numerous languages including C, RPG, Java, Visual Basic, and COBOL. The APIs are written in C and certain functions, such as exits, must be written in C as well. As far as APIs are concerned, these are some of the simplest to use that IBM has ever developed. In RPG, for example, to execute them, you simply need to call the C program QMQM. The first parameter identifies the specific function you want to invoke. MQGET, for example, is identified by “5”. The remaining parameters are specific to each API. (See the MQSeries Application Programming Reference Summary [SX33-6095-04] for the parameters required.) MQGET requires nine parameters that include such details as the queue the message is on, the message length, and completion codes. (See Figure 1 for details)
MQSeries Administration 101
Once MQSeries is installed and configured, the first thing you will want to learn how to do is start and stop MQSeries. This, unfortunately, isn’t as straightforward a process as you might think. Starting the queue manager is accomplished using STRMQM from a command line or option 8 from the MQSeries administration menu (GO CMDMQM). Once the queue manager is started, you need to start any custom programs that you have developed to use with MQSeries such as queue monitors.
The process of shutting down MQSeries in an orderly way, which is called quiescing, can be a complicated process when using the TCP/IP protocol. (MQSeries for AS/400 also works with SNA.) There are two separate procedures for quiescing MQSeries. Knowing which one to use depends on the reason for the shutdown. If you are going to power down the system, install PTFs, or upgrade MQSeries, use the following procedure:
1. Issue the End MQ Messaging (ENDMQM OPTION(*IMMED)) command to end immediately. This quiesces the queue manager.
2. CALL QMQM/AMQIQES4. This job performs the following actions:
• Ends all jobs with a lock on the QMQM library object
• Ends all MQSeries jobs
• Revokes all object authorities to libraries QMQM and QMQMADM
3. (Optional) CALL QMQM/AMQIQEM4. This releases all MQSeries user spaces. (MQSeries queues are implemented as user spaces.)
The second procedure is followed for quiescing MQSeries for the purposes of end of day shutdown or a daily backup.
4. CALL QMQM/AMQIQEJ4. This call ends the minimum number of MQSeries jobs to ensure a successful backup. It also performs the RCDMQMIMG (Record MQM Object Image) command.
Watch Out for the TCP/IP Trap!
A downside to using MQSeries with TCP/IP on an AS/400 is that, if TCP/IP drops unexpectedly, MQSeries hangs and only a manual recovery process can save it. When this situation arises, quick action is necessary because some of the MQSeries jobs drop while others remain active. The remaining active jobs can quickly chew up all of your processor resources. The only way that I have found to fix this problem is to manually end all MQSeries jobs by using the Work Active Job (WRKACTJOB) command and then restart MQSeries after TCP/IP communications are restored. This is a problem that certainly will have to be addressed by IBM in a future release of MQSeries.
Journals, Journals, Journals
Another minor issue with MQSeries is journaling. MQSeries uses journals to guarantee that a message is always delivered to its intended destination only one time. This reliability is one of the key elements to the success and popularity of MQSeries. Reliability comes with a price, however, and that price is the number of journals that are generated. Every time MQSeries is started, a new set of journals, AMQAxxxxxx and AMQRxxxxx, are created in library QMQMDATA. You must be extremely careful to have a backup before deleting any of the MQSeries journals. You need a backup since a certain number of the journals will be necessary in order to restart MQSeries after quiescing. If the necessary journals are not available, MQSeries will not restart until they are restored. If you do not have a backup copy of the needed journal, you may be looking for a new job! At the present time, IBM does not supply a method for dealing with journals other than to manually run the RCDMQMIMG command, view the job log to see what journals are still needed, and then delete the ones you no longer need. The RCDMQMIMG command is what allows journals to be deleted. This command records a marker in the most recent journal that determines where MQSeries looks in journal to begin the startup process. Once this command has completed successfully, all of the detached journals can be deleted. (Save them first, however, just to be safe.)
Reliability and Simplicity: A Winning Combo
The real beauty of MQSeries is that it removes the complexities of communicating between different platforms from the application developer and places it on the software. By handling these tasks with proven reliability, MQSeries has become the industry standard for middleware. In this article, I have merely scratched the surface of what you can do with MQSeries. IBM has a tremendous amount of resources available for MQSeries available at www.software.ibm.com/ts/mqseries/library/ mqpdfs.html.
[Editor’s Note: This article was originally published in the October/November 1999 issue of AS/400 NetJava Expert.]
REFERENCES AND RELATED MATERIALS
• MQSeries Administration Guide (GC33-1956-01)
• MQSeries Application Programming Guide (SC33-0807-09)
* Declare MQI structures needed
* /COPY members are supplied by IBM and located in QMQM/QRPGLESRC
* MQI named constants
D/COPY CMQR
* Message Descriptor
D MQMD DS
D/COPY CMQMDR
* Get message options
D MQGMO DS
I/COPY CMQGMOR
* Parameter definitions
* APICODE and constant values:
* MQCONN = 1, MQDISC = 2, MQOPEN = 3, MQCLOS = 4,
* MQGET = 5, MQPUT = 6, MQPUT1 = 7, MQINQ = 8
* HCONN - Connection Handle, use default value from data stucture.
* HOBJ - Object Handle, results from open call.
* MQMD - Message descriptor data structure.
* MQGMO - Specific options for MQGET.
* BUFLEN - Length of available buffer.
* BUFFER - Buffer for storing the retrieved message.
* MSGLEN - Actual length of retrieved message.
* CCODE - 0=OK 1=Warning 2=Fail -1=Unknown
* REASON - Message ID returned to identify events such as
* RC2033 = No more messages on the queue
C EVAL APICODE = MQGET
C EVAL HCONN = HCDEFH
C EVAL BUFLEN = 90
C CALL íQMQMí
C PARM APICODE 9 0
C PARM HCONN 9 0
C PARM HOBJ 9 0
C PARM MQMD
C PARM MQGMO
C PARM BUFLEN 9 0
C PARM BUFFER 60
C PARM MESLEN 9 0
C PARM CCODE 9 0
C PARM REASON 9 0
C RETURN
Figure 1: This is a sample MQGET call.
LATEST COMMENTS
MC Press Online