CL

102. データ待ち行列を検査するには ?

他のトピックでデータ待ち行列 (*DTAQ) は読取ると同時に
データ待ち行列のデータそのものが消えてしまうことを紹介した。

確かにそのとおりであり、データ待ち行列 (*DTAQ) は
データを読取るとそのデータは消失してしまう。
では *DTAQ にデータが存在しているのか、確認する方法は
ないのだろうか?

ここで CHKDTAQCL という CLP を紹介しよう。
実は *DTAQ を読取るときの 11 番目の任意パラメータ : Remove Message (char(10))
というのがリリース・アップで追加されていて

*YES : The message is removed from the data queue.
This is the default value if this parameter is not specified
*NO : The message is not removed from the data queue.

と追加されている。
このパラメータが指定されなければ省略値は *YES であり
メッセージはデータ待ち行列から削除される。
しかし *NO であれば「メッセージは *DTAQ から削除されない」とある。
API : QRCVDTAQ の機能が拡張されているのである。

それを利用したのが次に紹介するサンプル CL : CHKDTAQCL である。
CHKDTAQCL は 指定した *DTAQ にデータがあれば正常に終了するが、
データが何もなければ *ESCAPE メッセージを返す。
上位のプログラムは MONMSG CPF9800 によって結果を監視することができる。

【 サンプル・コマンド : CHKDTAQ 】
0001.00              CMD        PROMPT(' データ待ち行列の検査 ')
0002.00              PARM       KWD(DTAQ) TYPE(DTAQ) PROMPT(' データ待ち行列 ')
0003.00  DTAQ:       QUAL       TYPE(*NAME) LEN(10) MIN(1)
0004.00              QUAL       TYPE(*NAME) LEN(10) DFT(*LIBL) +
0005.00                           SPCVAL((*LIBL) (*CURLIB)) +
0006.00                           PROMPT(' ライブラリー ')
【 サンプル CLP : CHKDTAQCL 】
0001.00              PGM        PARM(&DTAQQLIB)
0002.00 /*-------------------------------------------------------------------*/
0003.00 /*   CHKDTAQCL   : *DTAQ のデータの検査                              */
0004.00 /*                                                                   */
0005.00 /*   2017/07/17  作成                                                */
0006.00 /*-------------------------------------------------------------------*/
0007.00              DCL        VAR(&DTAQQLIB) TYPE(*CHAR) LEN(20)
0008.00              DCL        VAR(&DTAQ) TYPE(*CHAR) LEN(10)
0009.00              DCL        VAR(&DTAQLIB) TYPE(*CHAR) LEN(10)
0010.00              DCL        VAR(&MSG) TYPE(*CHAR) LEN(132)
0011.00              DCL        VAR(&MSGID) TYPE(*CHAR) LEN(7)
0012.00              DCL        VAR(&MSGF) TYPE(*CHAR) LEN(10)
0013.00              DCL        VAR(&MSGFLIB) TYPE(*CHAR) LEN(10)
0014.00              DCL        VAR(&MSGDTA) TYPE(*CHAR) LEN(132)
0015.00              DCL        VAR(&TYPE) TYPE(*CHAR) LEN(1)
0016.00              DCL        VAR(&TOPGMQ) TYPE(*CHAR) LEN(10)
0017.00              DCL        VAR(&MSGTYPE) TYPE(*CHAR) LEN(10) +
0018.00                           VALUE('*ESCAPE   ')
0019.00              DCL        VAR(&APIERR) TYPE(*CHAR) LEN(116) +
0020.00                           VALUE(X'000074') /* 2 進数  */
0021.00              DCL        VAR(&NULL4) TYPE(*CHAR) LEN(4) +
0022.00                           VALUE(X'00000000')
0023.00              DCL        VAR(&WAIT) TYPE(*DEC) LEN(5 0) VALUE(0)
0024.00              DCL        VAR(&MSGBUF) TYPE(*CHAR) LEN(4096)
0025.00              DCL        VAR(&MSGLEN) TYPE(*DEC) LEN(8 0)
0026.00              DCL        VAR(&KEYLEN) TYPE(*DEC) LEN(3 0)
0027.00              DCL        VAR(&SENDER) TYPE(*DEC) LEN(3 0)
0028.00              DCL        VAR(&DTA_REC) TYPE(*DEC) LEN(5 0)
0029.00              MONMSG     MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
0030.00
0031.00 /*( 環境の取得 )*/
0032.00              RTVJOBA    TYPE(&TYPE)
0033.00              IF         COND(&TYPE *EQ '0') THEN(DO) /*  バッチ  */
0034.00              CHGVAR     VAR(&TOPGMQ) VALUE('*SYSOPR   ')
0035.00              ENDDO      /*  バッチ  */
0036.00              ELSE       CMD(DO) /*  対話式  */
0037.00              CHGVAR     VAR(&TOPGMQ) VALUE('*TOPGMQ   ')
0038.00              ENDDO      /*  対話式  */
0039.00
0040.00 /*( パラメータの読取り )*/
0041.00              CHGVAR     VAR(&DTAQ) VALUE(%SST(&DTAQQLIB 01 10))
0042.00              CHGVAR     VAR(&DTAQLIB) VALUE(%SST(&DTAQQLIB 11 10))
0043.00
0044.00 /*( *DTAQ の読取り )*/
0045.00              CHGVAR     VAR(&WAIT) VALUE(0) /*  即時読取り  */
0046.00              CALL       PGM(QRCVDTAQ) PARM(&DTAQ &DTAQLIB &MSGLEN +
0047.00                           &MSGBUF &WAIT '  ' &KEYLEN '' &SENDER '' +
0048.00                           '*NO       ' &DTA_REC &APIERR)
0049.00              IF         COND(%SST(&APIERR 5 4) *NE &NULL4) THEN(DO)
0050.00              SNDPGMMSG  +
0051.00                           MSG('API: QRCVDTAQ の実行で次のエラーが発生 +
0052.00                            しました。 ') MSGTYPE(*DIAG)
0053.00              GOTO       APIERR
0054.00              ENDDO
0055.00              IF         COND(&MSGLEN > 0) THEN(RETURN)
0056.00              ELSE       CMD(DO)
0057.00              CHGVAR     VAR(&MSGDTA) +
0058.00                           VALUE(' データ待ち行列にはデータはありませ +
0059.00                            ん。 ')
0060.00              GOTO       SNDMSG
0061.00              ENDDO
0062.00              RETURN
0063.00
0064.00  APIERR:
0065.00              CHGVAR     VAR(&MSGID) VALUE(%SST(&APIERR 9 7))
0066.00              CHGVAR     VAR(&MSGDTA) VALUE(%SST(&APIERR 17 100))
0067.00              CHGVAR     VAR(&MSGF) VALUE('QCPFMSG   ')
0068.00              CHGVAR     VAR(&MSGFLIB) VALUE('QSYS      ')
0069.00              GOTO       SNDMSG
0070.00
0071.00  ERROR:      RCVMSG     MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) +
0072.00                           MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) +
0073.00                           MSGFLIB(&MSGFLIB)
0074.00  SNDMSG:     IF         COND(&MSGID *EQ ' ') THEN(DO)
0075.00              SNDPGMMSG  MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) +
0076.00                           TOMSGQ(&TOPGMQ) MSGTYPE(&MSGTYPE)
0077.00              ENDDO
0078.00              ELSE       CMD(DO)
0079.00              SNDPGMMSG  MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
0080.00                           MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) +
0081.00                           MSGTYPE(&MSGTYPE)
0082.00              ENDDO
0083.00              ENDPGM
【 解説 】

ポイントは

0046.00              CALL       PGM(QRCVDTAQ) PARM(&DTAQ &DTAQLIB &MSGLEN +
0047.00                           &MSGBUF &WAIT '  ' &KEYLEN '' &SENDER '' +
0048.00                           '*NO       ' &DTA_REC &APIERR)

で示されている 11 番目のパラメータに *NO が明示的に指定されていることである。
*DTAQ にデータがあれば MSGLEN> 0 として返ってくるがメッセージの除去が
*NO として指定されているのでデータが *DTAQ から除去されることはない。
データがない場合は MSGLEN = 0 で戻るので CPF9887 の *ESCAPE メッセージが
呼び出し元のプログラムに戻る。