S/36 の OCL で唯一、S/38 や AS400, IBM i になかった命令は
プログラムが活動中であるかどうかを調べるコマンドである。
たまにプログラムが現在、この実行ジョブのスタックで実行しているのかどうかを知りたいことがある。
( S/36 の If-Active はすべてのシステム空間を検査していた)
手軽に実行中のプログラムを検査する方法はないだろうか ?
幸い、実行スタックの中身はAPI : QWVRCSTK
で調べることができるが
API にまだ不慣れな人や C言語の苦手な人のために CLP で手軽に検査することのできる
コマンド: IFACTIVE
を作成したのでここで紹介する。
IFACTIVE
コマンドでプログラム/ライブラリー名を指定して実行すると
実行中であれば単に実行が正常終了するだけであるが
指定したプログラムが実行されていない場合はCPF9897
が *ESCAPE
で戻される。
従って MONMSG CPF9800
で上位の呼び出しプログラムでモニターしておけば
そのプログラムが活動中であるかどうかを容易に知ることができる。
0001.00 CMD PROMPT(' プログラム活動検査 ') 0002.00 PARM KWD(PGM) TYPE(PGM) + 0003.00 PROMPT(' プログラム ') 0004.00 PGM: QUAL TYPE(*NAME) LEN(10) SPCVAL((*PRV)) MIN(1) 0005.00 QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) + 0006.00 SPCVAL((*LIBL) (*CURLIB) (*PRV)) + 0007.00 PROMPT(' ライブラリー ')
CRTCMD CMD(MYLIB/IFACTIVE) PGM(MYLIB/IFACTIVECL) SRCFILE(MYSRCLIB/QCMDSRC) AUT(*ALL)
0001.00 PGM PARM(&PGMOBJLIB) 0002.00 /*-------------------------------------------------------------------*/ 0003.00 /* IFACTIVECL : プログラム活動検査 */ 0004.00 /* */ 0005.00 /* 2015/11/24 作成 */ 0006.00 /*-------------------------------------------------------------------*/ 0007.00 DCL VAR(&PGMOBJLIB) TYPE(*CHAR) LEN(20) 0008.00 DCL VAR(&CMPOBJLIB) TYPE(*CHAR) LEN(20) 0009.00 DCL VAR(&PGM) TYPE(*CHAR) LEN(10) 0010.00 DCL VAR(&OBJLIB) TYPE(*CHAR) LEN(10) 0011.00 DCL VAR(&JOBINFO) TYPE(*CHAR) LEN(56) 0012.00 DCL VAR(&IND) TYPE(*CHAR) LEN(4) + 0013.00 VALUE(X'00000002') 0014.00 DCL VAR(&JOB) TYPE(*CHAR) LEN(10) 0015.00 DCL VAR(&USER) TYPE(*CHAR) LEN(10) 0016.00 DCL VAR(&NBR) TYPE(*CHAR) LEN(6) 0017.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(132) 0018.00 DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) 0019.00 DCL VAR(&MSGF) TYPE(*CHAR) LEN(10) 0020.00 DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10) 0021.00 DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132) 0022.00 DCL VAR(&TYPE) TYPE(*CHAR) LEN(1) 0023.00 DCL VAR(&TOPGMQ) TYPE(*CHAR) LEN(10) 0024.00 DCL VAR(&RCVVAR) TYPE(*CHAR) LEN(3000) 0025.00 DCL VAR(&RCVLEN) TYPE(*CHAR) LEN(4) + 0026.00 VALUE(X'00000BB8') /* 3000 バイト */ 0027.00 DCL VAR(&APIERR) TYPE(*CHAR) LEN(116) + 0028.00 VALUE(X'000074') /* 2 進数 */ 0029.00 DCL VAR(&NULL2) TYPE(*CHAR) LEN(2) + 0030.00 VALUE(X'0000') 0031.00 DCL VAR(&NULL4) TYPE(*CHAR) LEN(4) + 0032.00 VALUE(X'00000000') 0033.00 DCL VAR(&NULL8) TYPE(*CHAR) LEN(8) + 0034.00 VALUE(X'0000000000000000') 0035.00 DCL VAR(&ENTRY) TYPE(*CHAR) LEN(4) 0036.00 DCL VAR(&ENTRYS) TYPE(*DEC) LEN(8 0) 0037.00 DCL VAR(&N) TYPE(*DEC) LEN(8 0) 0038.00 DCL VAR(&OFFSET) TYPE(*CHAR) LEN(4) 0039.00 DCL VAR(&OFFSETS) TYPE(*DEC) LEN(8 0) 0040.00 DCL VAR(&LENGTH) TYPE(*CHAR) LEN(4) 0041.00 DCL VAR(&LENGTHS) TYPE(*DEC) LEN(8 0) 0042.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) 0043.00 0044.00 RTVJOBA JOB(&JOB) USER(&USER) NBR(&NBR) TYPE(&TYPE) 0045.00 IF COND(&TYPE *EQ '0') THEN(DO) /* バッチ */ 0046.00 CHGVAR VAR(&TOPGMQ) VALUE('*SYSOPR ') 0047.00 ENDDO /* バッチ */ 0048.00 ELSE CMD(DO) /* 対話式 */ 0049.00 CHGVAR VAR(&TOPGMQ) VALUE('*TOPGMQ ') 0050.00 ENDDO /* 対話式 */ 0051.00 0052.00 CHGVAR VAR(%SST(&JOBINFO 1 10)) VALUE(&JOB) 0053.00 CHGVAR VAR(%SST(&JOBINFO 11 10)) VALUE(&USER) 0054.00 CHGVAR VAR(%SST(&JOBINFO 21 6)) VALUE(&NBR) 0055.00 CHGVAR VAR(%SST(&JOBINFO 43 2)) VALUE(&NULL2) 0056.00 CHGVAR VAR(%SST(&JOBINFO 45 4)) VALUE(&IND) 0057.00 CHGVAR VAR(%SST(&JOBINFO 49 8)) VALUE(&NULL8) 0058.00 CALL PGM(QWVRCSTK) PARM(&RCVVAR &RCVLEN + 0059.00 'CSTK0100' &JOBINFO 'JIDF0100' &APIERR) 0060.00 IF COND(%SST(&APIERR 5 4) *NE &NULL4) THEN(DO) 0061.00 SNDPGMMSG + 0062.00 MSG('API: QWVRCSTK の実行で次のエラーが発生 + 0063.00 しました。 ') MSGTYPE(*DIAG) 0064.00 GOTO APIERR 0065.00 ENDDO 0066.00 CHGVAR VAR(&LENGTH) VALUE(%SST(&RCVVAR 1 4)) 0067.00 CHGVAR VAR(&LENGTHS) VALUE(%BIN(&LENGTH)) 0068.00 CHGVAR VAR(&ENTRY) VALUE(%SST(&RCVVAR 17 4)) 0069.00 CHGVAR VAR(&ENTRYS) VALUE(%BIN(&ENTRY)) 0070.00 CHGVAR VAR(&N) VALUE(1) 0071.00 CHGVAR VAR(&OFFSET) VALUE(%SST(&RCVVAR 13 4)) 0072.00 CHGVAR VAR(&OFFSETS) VALUE(%BIN(&OFFSET)) 0073.00 CHGVAR VAR(&OFFSETS) VALUE(&OFFSETS + 1) 0074.00 LOOP: CHGVAR VAR(&LENGTH) VALUE(%SST(&RCVVAR &OFFSETS 4)) 0075.00 CHGVAR VAR(&LENGTHS) VALUE(%BIN(&LENGTH)) 0076.00 CHGVAR VAR(&OFFSETS) VALUE(&OFFSETS + 24) 0077.00 CHGVAR VAR(&CMPOBJLIB) VALUE(%SST(&RCVVAR &OFFSETS + 0078.00 20)) 0079.00 IF COND(&CMPOBJLIB *EQ &PGMOBJLIB) THEN(DO) /* + 0080.00 活動中 */ 0081.00 RETURN 0082.00 ENDDO /* 活動中 */ 0083.00 IF COND(&N < &ENTRYS) THEN(DO) 0084.00 CHGVAR VAR(&OFFSETS) VALUE(&OFFSETS + &LENGTHS - 24) 0085.00 CHGVAR VAR(&N) VALUE(&N + 1) 0086.00 GOTO LOOP 0087.00 ENDDO 0088.00 /* 非活動 */ 0089.00 CHGVAR VAR(&PGM) VALUE(%SST(&PGMOBJLIB 1 10)) 0090.00 CHGVAR VAR(&OBJLIB) VALUE(%SST(&PGMOBJLIB 11 10)) 0091.00 CHGVAR VAR(&MSGDTA) VALUE(' プログラム ' *CAT + 0092.00 &OBJLIB *TCAT '/' *CAT &PGM *TCAT + 0093.00 ' は活動していません。 ') 0094.00 SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + 0095.00 TOPGMQ(*PRV) TOMSGQ(*TOPGMQ) MSGTYPE(*ESCAPE) 0096.00 RETURN 0097.00 0098.00 APIERR: 0099.00 CHGVAR VAR(&MSGID) VALUE(%SST(&APIERR 9 7)) 0100.00 CHGVAR VAR(&MSGDTA) VALUE(%SST(&APIERR 17 100)) 0101.00 CHGVAR VAR(&MSGF) VALUE('QCPFMSG ') 0102.00 CHGVAR VAR(&MSGFLIB) VALUE('QSYS ') 0103.00 GOTO SNDMSG 0104.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) + 0105.00 MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) + 0106.00 MSGFLIB(&MSGFLIB) 0107.00 SNDMSG: IF COND(&MSGID *EQ ' ') THEN(DO) 0108.00 SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) + 0109.00 TOMSGQ(&TOPGMQ) MSGTYPE(*ESCAPE) 0110.00 ENDDO 0111.00 ELSE CMD(DO) 0112.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + 0113.00 MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) + 0114.00 MSGTYPE(*ESCAPE) 0115.00 ENDDO 0116.00 ENDPGM
CRTCLPGM PGM(MYLIB/IFACTIVECL) SRCFILE(MYSRCLIB/QCLSRC) AUT(*ALL)
原理的には至って簡単であり API : QWVRCSTK
でスタックを &RCVVAR
に入れたものを
LOOP して階層を取り出して指定したプログラム: &PGMOBJLIB
があるかどうかを調べる。
もし見つかった場合は、何もせずにそのまま RETURN で戻るが
見つからなかった場合は SNDPGMMSG
で CPF9897
を *ESCAPE
で戻す。
0001.00 PGM PARM(&MSGID &MSGF &MSGFLIB &MSGDTA) 0002.00 /*-------------------------------------------------------------------*/ 0003.00 /* SNDPGMMSG: RPG 内での PGM メッセージ送信 */ 0004.00 /* */ 0005.00 /* 2015/11/24: HTML ドライバーから呼ばれた場合だけは */ 0006.00 /* MAIN モジュールのエラーである旨を告げる */ 0007.00 /*-------------------------------------------------------------------*/ 0008.00 DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) 0009.00 DCL VAR(&MSGF) TYPE(*CHAR) LEN(10) 0010.00 DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10) 0011.00 DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132) 0012.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(132) 0013.00 DCL VAR(&TYPE) TYPE(*CHAR) LEN(1) 0014.00 DCL VAR(&TOPGMQ) TYPE(*CHAR) LEN(10) 0015.00 DCL VAR(&HTMLDVR) TYPE(*CHAR) LEN(1) VALUE('*') 0016.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) 0017.00 0018.00 RTVJOBA TYPE(&TYPE) 0019.00 IF COND(&TYPE *EQ '0') THEN(DO) /* + 0020.00 バッチ・ジョブ */ 0021.00 CHGVAR VAR(&TOPGMQ) VALUE('*SYSOPR ') 0022.00 ENDDO /* バッチ・ジョブ */ 0023.00 ELSE CMD(DO) /* 対話式 */ 0024.00 CHGVAR VAR(&TOPGMQ) VALUE('*TOPGMQ ') 0025.00 ENDDO /* 対話式 */ 0026.00 ASNET.COM/IFACTIVE PGM(ASNET.COM/HTMLDVR) 0027.00 MONMSG MSGID(CPF9800) EXEC(DO) 0028.00 CHGVAR VAR(&HTMLDVR) VALUE(' ') 0029.00 ENDDO 0030.00 0031.00 IF COND(&HTMLDVR *EQ '*') THEN(DO) /* + 0032.00 HTML ドライバー */ 0033.00 SNDPGMMSG MSG('[ERROR] + 0034.00 MAIN モジュールで次のエラーが検出されまし + 0035.00 た。 ') TOMSGQ(&TOPGMQ) MSGTYPE(*INFO) 0036.00 ENDDO /* HTML ドライバー */ 0037.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + 0038.00 MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) + 0039.00 MSGTYPE(*ESCAPE) 0040.00 RETURN 0041.00 0042.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) + 0043.00 MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) + 0044.00 MSGFLIB(&MSGFLIB) 0045.00 SNDMSG: IF COND(&MSGID *EQ ' ') THEN(DO) 0046.00 SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) + 0047.00 TOMSGQ(&TOPGMQ) MSGTYPE(*ESCAPE) 0048.00 ENDDO 0049.00 ELSE CMD(DO) 0050.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + 0051.00 MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) + 0052.00 MSGTYPE(*ESCAPE) 0053.00 ENDDO 0054.00 ENDPGM
この SNDPGMMSG
というCLプログラムは
HTMLドライバーと呼ばれる(HTMLDVR)プログラム中、
それも例外サブルーチン : *PSSR
で呼び出されて実行される。
ただし SNDPGMMSG
は汎用的なエラー・メッセージ送信のプログラムなので
他の場面での使用も想定している。
ただ HTMLDVR
というプログラムから呼ばれたときは
「MAIN モジュールで次のエラーが検出されました。」というメッセージも合わせて送りたいのである。
つまり HTMLDVR
というプログラムが実行中の場合はこのメッセージも付記するのである。
このことを判断させるために IFACTIVE
コマンドを使って検査して結果を MONMSG
で監視している。
0026.00 ASNET.COM/IFACTIVE PGM(ASNET.COM/HTMLDVR) 0027.00 MONMSG MSGID(CPF9800) EXEC(DO) 0028.00 CHGVAR VAR(&HTMLDVR) VALUE(' ') 0029.00 ENDDO