ibm-information-center/dist/eclipse/plugins/i5OS.ic.rbam6_5.4.0.1/rcvmsgpgm.htm

247 lines
13 KiB
HTML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en-us" xml:lang="en-us">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="security" content="public" />
<meta name="Robots" content="index,follow" />
<meta http-equiv="PICS-Label" content='(PICS-1.1 "http://www.icra.org/ratingsv02.html" l gen true r (cz 1 lz 1 nz 1 oz 1 vz 1) "http://www.rsac.org/ratingsv01.html" l gen true r (n 0 s 0 v 0 l 0) "http://www.classify.org/safesurf/" l gen true r (SS~~000 1))' />
<meta name="DC.Type" content="task" />
<meta name="DC.Title" content="Receive a message from a program or procedure that has ended" />
<meta name="abstract" content="This topic describes how to receive messages from an inactive call message queue." />
<meta name="description" content="This topic describes how to receive messages from an inactive call message queue." />
<meta name="DC.subject" content="break-handling program, program, break-handling" />
<meta name="keywords" content="break-handling program, program, break-handling" />
<meta name="DC.Relation" scheme="URI" content="wmsgs.htm" />
<meta name="DC.Relation" scheme="URI" content="msgcallqueue.htm" />
<meta name="copyright" content="(C) Copyright IBM Corporation 1998, 2006" />
<meta name="DC.Rights.Owner" content="(C) Copyright IBM Corporation 1998, 2006" />
<meta name="DC.Format" content="XHTML" />
<meta name="DC.Identifier" content="rcvmsgpgm" />
<meta name="DC.Language" content="en-us" />
<!-- All rights reserved. Licensed Materials Property of IBM -->
<!-- US Government Users Restricted Rights -->
<!-- Use, duplication or disclosure restricted by -->
<!-- GSA ADP Schedule Contract with IBM Corp. -->
<link rel="stylesheet" type="text/css" href="./ibmdita.css" />
<link rel="stylesheet" type="text/css" href="./ic.css" />
<title>Receive a message from a program or procedure that has ended</title>
</head>
<body id="rcvmsgpgm"><a name="rcvmsgpgm"><!-- --></a>
<img src="./delta.gif" alt="Start of change" /><!-- Java sync-link --><script language="Javascript" src="../rzahg/synch.js" type="text/javascript"></script>
<h1 class="topictitle1">Receive a message from a program or procedure that has ended</h1>
<div><p>This topic describes how to receive messages from an inactive call
message queue.</p>
<div class="section"> <p>Occasionally there is a need to receive messages from the job
log that were sent to a call message queue which is no longer active. For
example, PGMA calls PGMB, PGMB sends a diagnostic message to itself and an
escape message to PGMA. PGMA can easily receive the escape message that
was sent to it, but sometimes it necessary to also receive the diagnostic
message. Since the diagnostic is on a call message queue that is no longer
active, the message must be received by using a message reference key. This
can be done, but it takes more work than one simple receive message command.</p>
<p>The
following considerations are important in understanding how this works:</p>
<ul><li>If the <span class="cmdname">Receive Message (RCVMSG)</span> command (or <span class="apiname">QMHRCVPM</span> API)
is coded to receive a message by key from its own call message queue, it will
receive the message with that key (if it still exists) from the job log,
regardless of what call message queue the message was sent to or whether
or not that procedure is active.</li>
<li>The message reference key for messages in the job log can be treated as
a 4-byte unsigned integer that is incremented for each message sent (even
though it is documented externally as a 4-character value).</li>
</ul>
<p>The following steps are required to obtain a message from a program
or procedure that has ended:</p>
</div>
<ol><li><span>Send a message (and optionally remove it) to obtain a starting
message reference key.</span></li>
<li><span>Run the function that will send the messages you are interested
in.</span></li>
<li><span>Send another message to obtain an ending message reference key.</span></li>
<li><span>In a loop, increment the message reference key between the starting
and ending message keys identified in steps 1 and 3 and receive the message
for each key. There can be gaps in the message reference key so the CPF2410
exception from the receive message function must be handled. The gaps can
occur from a message that have been deleted or from internal exception handling.</span></li>
</ol>
<div class="example"><div class="note"><span class="notetitle">Note:</span> This topic provides a procedure and example for one way to
receive a message from a program or procedure that has ended. There are other
techniques that can be used to access some or all of the messages in the
job log. These are summarized in the following list, but are not explained
in detail, nor are sample programs provided:<ul><li>Write the job log to an outfile. This can be done either by specifying
OUTPUT(*OUTFILE) on the <span class="cmdname">Display Job Log (DSPJOBLOG)</span> command,
or using the <span class="apiname">QMHCTLJL</span> API to define the job log outfile
specifications and either ending the job or specifying OUTPUT(*APIDFN) on
the <span class="cmdname">Display Job Log (DSPJOBLOG)</span> command. When you do this
all messages in the job log will be written to the outfile. So messages that
were left on a call message queue when the program or procedure ended would
be included.</li>
<li>Use the <span class="apiname">List Job Log Messages (QMHLJOBL)</span> API to copy
messages from the job log into a user space. You can select all of the messages
in the job log or a subset, and you can select which fields are returned for
each message. There are APIs that can be used to access the contents of the
user space. The <span class="apiname">QUSPTRUS</span> API can be used to get a pointer
to the data in the user space. Then the pointer can be used with languages
that support pointers. API <span class="apiname">QUSRTVUS</span> can be used to retrieve
data from the user space in order to use languages that do not support pointers.</li>
</ul>
</div>
<p>A sample program of the procedure described above
is provided below using the RCVMSG command and the <span class="apiname">QMHRCVPM</span> API.</p>
<div class="note"><span class="notetitle">Note:</span> Read
the <a href="codedisclaimer.htm">Code license and disclaimer information</a> for important legal information.</div>
<pre>*******************************************************************************
*
* CL program example using the RCVMSG command
*
*
*******************************************************************************
This has the advantage of being easier to code and is easier to follow.
It has the disadvantage of requiring the program to monitor for and handle
the CPF2410 exception, which is not a good thing if performance is important.
PGM
DCL &amp;LOWKEY *CHAR 4
DCL &amp;HIKEY *CHAR 4
DCL &amp;MSGKEY *CHAR 4
DCL &amp;MSG *CHAR 256
/*-----------------------------------------------------------------*/
/* OBTAIN STARTING MESSAGE REFERENCE KEY */
/*-----------------------------------------------------------------*/
SNDPGMMSG MSG(TEST) TOPGMQ(*SAME) KEYVAR(&amp;LOWKEY)
RMVMSG MSGKEY(&amp;LOWKEY)
/*-----------------------------------------------------------------*/
/* EXECUTE FUNCTION */
/*-----------------------------------------------------------------*/
---- Insert whatever command(s) or program call(s) you want ----
---- to handle messages for here ----
/*-----------------------------------------------------------------*/
/* OBTAIN ENDING MESSAGE REFERENCE KEY */
/*-----------------------------------------------------------------*/
SNDPGMMSG MSG(TEST) TOPGMQ(*SAME) KEYVAR(&amp;HIKEY)
RMVMSG MSGKEY(&amp;HIKEY)
/*-----------------------------------------------------------------*/
/* LOOP TO RECEIVE MESSAGES ON INACTIVE INVOCATION */
/*-----------------------------------------------------------------*/
CHGVAR %BIN(&amp;MSGKEY 1 4) (%BIN(&amp;LOWKEY 1 4) + 1)
LOOP:
RCVMSG PGMQ(*SAME (*)) MSGKEY(&amp;MSGKEY) RMV(*NO) MSG(&amp;MSG)
MONMSG CPF2410 EXEC(DO) /* HANDLE MSGKEY NOT FOUND */
RCVMSG MSGTYPE(*EXCP) RMV(*YES) /* REMOVE UNWANTED EXCEPTION */
GOTO SKIP
ENDDO
---- Insert code here to do whatever processing is needed ----
---- for the message. You may need to add additional ----
---- values, such as message ID, message type, etc., to ----
---- the RCVMSG command. ----
SKIP:
CHGVAR %BIN(&amp;MSGKEY 1 4) (%BIN(&amp;MSGKEY 1 4) + 1)
IF (&amp;MSGKEY *LT &amp;HIKEY) GOTO LOOP
ENDPGM
*******************************************************************************
*
* CL program using the QMHRCVPM API.
*
*******************************************************************************
This sample is similar to the first sample. The only difference is that
it uses the QMHRCVPM API instead of the RCVMSG CL command. By using the error
code structure, it eliminates the need to handle the CPF2410 exception and the
overhead required to send the exception in the case of the message key not
being found. This example shows how to extract the message text from the
structure returned by the API. If the message is an immediate message (i.e. no
message ID), the message is in the 'Replacement data or impromptu message text'
area; otherwise it is in the 'Message' area which follows the 'Replacement
data' field. The example checks the message length to determine which of these
fields to use for the message.
PGM
DCL &amp;LOWKEY *CHAR 4
DCL &amp;HIKEY *CHAR 4
DCL &amp;MSGKEY *CHAR 4
DCL &amp;MSG *CHAR 256
/*------------------------------------------------------------------*/
/* Some messages have a large amount of message data, in which case */
/* the size of the &amp;MSGINFO variable will not be adequate. If you */
/* expect to receive messages with a large amount of message data, */
/* you will need to increase the size of this variable accordingly. */
/* Be sure to also change the value that is put into &amp;MSGINFOL to */
/* reflect the size of the variable. */
/*------------------------------------------------------------------*/
DCL &amp;MSGINFO *CHAR 1000
DCL &amp;MSGINFOL *CHAR 4
DCL &amp;ERRCODE *CHAR 16
DCL &amp;MSGOFFS *DEC (4 0)
DCL &amp;MSGLEN *DEC (4 0)
/*-----------------------------------------------------------------*/
/* OBTAIN STARTING MESSAGE REFERENCE KEY */
/*-----------------------------------------------------------------*/
SNDPGMMSG MSG(TEST) TOPGMQ(*SAME) KEYVAR(&amp;LOWKEY)
RMVMSG MSGKEY(&amp;LOWKEY)
/*-----------------------------------------------------------------*/
/* EXECUTE FUNCTION */
/*-----------------------------------------------------------------*/
---- Insert whatever command(s) or program call(s) you want ----
---- to handle messages for here ----
/*-----------------------------------------------------------------*/
/* OBTAIN ENDING MESSAGE REFERENCE KEY */
/*-----------------------------------------------------------------*/
SNDPGMMSG MSG(TEST) TOPGMQ(*SAME) KEYVAR(&amp;HIKEY)
RMVMSG MSGKEY(&amp;HIKEY)
/*-----------------------------------------------------------------*/
/* LOOP TO RECEIVE MESSAGES WITH QMHRCVPM API */
/*-----------------------------------------------------------------*/
CHGVAR %BIN(&amp;MSGKEY 1 4) (%BIN(&amp;LOWKEY 1 4) + 1)
CHGVAR %BIN(&amp;MSGINFOL 1 4) 1000
CHGVAR %BIN(&amp;ERRCODE 1 4) 16
LOOP2:
CALL QMHRCVPM (&amp;MSGINFO &amp;MSGINFOL RCVM0200 '* ' +
X'00000000' '*ANY ' &amp;MSGKEY X'00000000' +
'*SAME ' &amp;ERRCODE)
IF ((%BIN(&amp;MSGINFO 5 4) *GT 0) *AND (%BIN(&amp;ERRCODE 5 4) *EQ 0)) +
DO /* IF A MESSAGE WAS RECEIVED */
IF (%BIN(&amp;MSGINFO 161 4) *EQ 0) +
DO /* IMPROMPTU MESSAGE */
CHGVAR &amp;MSGLEN %BIN(&amp;MSGINFO 153 4)
CHGVAR &amp;MSGOFFS 177
ENDDO
ELSE +
DO /* STORED MESSAGE */
CHGVAR &amp;MSGLEN %BIN(&amp;MSGINFO 161 4)
CHGVAR &amp;MSGOFFS (177 + %BIN(&amp;MSGINFO 153 4))
ENDDO
CHGVAR &amp;MSG %SST(&amp;MSGINFO &amp;MSGOFFS &amp;MSGLEN)
---- Insert code here to do whatever processing is needed ----
---- for the message. You can extract additional ----
---- values, such as message ID, message type, etc., ----
---- from the message information structure if necessary. ----
ENDDO
CHGVAR %BIN(&amp;MSGKEY 1 4) (%BIN(&amp;MSGKEY 1 4) + 1)
IF (&amp;MSGKEY *LT &amp;HIKEY) GOTO LOOP2
ENDPGM</pre>
</div>
</div>
<div>
<div class="familylinks">
<div class="parentlink"><strong>Parent topic:</strong> <a href="wmsgs.htm" title="This discusses some of the ways that messages can be used to communicate between users and programs.">Messages</a></div>
</div>
<div class="relconcepts"><strong>Related concepts</strong><br />
<div><a href="msgcallqueue.htm" title="A call message queue is used to send messages between one program or procedure and another program or procedure.">Call message queue</a></div>
</div>
</div>
<img src="./deltaend.gif" alt="End of change" /></body>
</html>