247 lines
13 KiB
HTML
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 &LOWKEY *CHAR 4
|
|
DCL &HIKEY *CHAR 4
|
|
DCL &MSGKEY *CHAR 4
|
|
DCL &MSG *CHAR 256
|
|
/*-----------------------------------------------------------------*/
|
|
/* OBTAIN STARTING MESSAGE REFERENCE KEY */
|
|
/*-----------------------------------------------------------------*/
|
|
SNDPGMMSG MSG(TEST) TOPGMQ(*SAME) KEYVAR(&LOWKEY)
|
|
RMVMSG MSGKEY(&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(&HIKEY)
|
|
RMVMSG MSGKEY(&HIKEY)
|
|
/*-----------------------------------------------------------------*/
|
|
/* LOOP TO RECEIVE MESSAGES ON INACTIVE INVOCATION */
|
|
/*-----------------------------------------------------------------*/
|
|
CHGVAR %BIN(&MSGKEY 1 4) (%BIN(&LOWKEY 1 4) + 1)
|
|
LOOP:
|
|
RCVMSG PGMQ(*SAME (*)) MSGKEY(&MSGKEY) RMV(*NO) MSG(&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(&MSGKEY 1 4) (%BIN(&MSGKEY 1 4) + 1)
|
|
IF (&MSGKEY *LT &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 &LOWKEY *CHAR 4
|
|
DCL &HIKEY *CHAR 4
|
|
DCL &MSGKEY *CHAR 4
|
|
DCL &MSG *CHAR 256
|
|
/*------------------------------------------------------------------*/
|
|
/* Some messages have a large amount of message data, in which case */
|
|
/* the size of the &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 &MSGINFOL to */
|
|
/* reflect the size of the variable. */
|
|
/*------------------------------------------------------------------*/
|
|
DCL &MSGINFO *CHAR 1000
|
|
DCL &MSGINFOL *CHAR 4
|
|
DCL &ERRCODE *CHAR 16
|
|
DCL &MSGOFFS *DEC (4 0)
|
|
DCL &MSGLEN *DEC (4 0)
|
|
/*-----------------------------------------------------------------*/
|
|
/* OBTAIN STARTING MESSAGE REFERENCE KEY */
|
|
/*-----------------------------------------------------------------*/
|
|
SNDPGMMSG MSG(TEST) TOPGMQ(*SAME) KEYVAR(&LOWKEY)
|
|
RMVMSG MSGKEY(&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(&HIKEY)
|
|
RMVMSG MSGKEY(&HIKEY)
|
|
/*-----------------------------------------------------------------*/
|
|
/* LOOP TO RECEIVE MESSAGES WITH QMHRCVPM API */
|
|
/*-----------------------------------------------------------------*/
|
|
CHGVAR %BIN(&MSGKEY 1 4) (%BIN(&LOWKEY 1 4) + 1)
|
|
CHGVAR %BIN(&MSGINFOL 1 4) 1000
|
|
CHGVAR %BIN(&ERRCODE 1 4) 16
|
|
LOOP2:
|
|
CALL QMHRCVPM (&MSGINFO &MSGINFOL RCVM0200 '* ' +
|
|
X'00000000' '*ANY ' &MSGKEY X'00000000' +
|
|
'*SAME ' &ERRCODE)
|
|
IF ((%BIN(&MSGINFO 5 4) *GT 0) *AND (%BIN(&ERRCODE 5 4) *EQ 0)) +
|
|
DO /* IF A MESSAGE WAS RECEIVED */
|
|
IF (%BIN(&MSGINFO 161 4) *EQ 0) +
|
|
DO /* IMPROMPTU MESSAGE */
|
|
CHGVAR &MSGLEN %BIN(&MSGINFO 153 4)
|
|
CHGVAR &MSGOFFS 177
|
|
ENDDO
|
|
ELSE +
|
|
DO /* STORED MESSAGE */
|
|
CHGVAR &MSGLEN %BIN(&MSGINFO 161 4)
|
|
CHGVAR &MSGOFFS (177 + %BIN(&MSGINFO 153 4))
|
|
ENDDO
|
|
CHGVAR &MSG %SST(&MSGINFO &MSGOFFS &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(&MSGKEY 1 4) (%BIN(&MSGKEY 1 4) + 1)
|
|
IF (&MSGKEY *LT &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> |