RPG

290. API エラー報告

i5/OS の API ( = Application Programing Interface ) とは
IBM が i5/OS で実際に使用しているプログラムをユーザーでも使えるようにと
その仕様を公開したものである。
例えばオブジェクトの一覧: QUSLOBJ やユーザー・スペースの作成: QUSCRTUS など
かなりの数の便利プログラムとして公開されている。
API を苦もなく使えるようになればあなたの開発者としての実力は
飛躍的に向上するはずである。

API の内容についてはこちらで紹介しているし
API の使い方の一部もこちらで過去に紹介している。
ここでは API を使うに当たって API のエラー・コードの使い方を解説する。
API のエラー・コードの設定や使い方によって
API の特性をより生かすことができるようになる。
また合わせて IBM マニュアルのあいまいさや間違いについても言及していく。

最初に API のエラー・コードはすべての API で統一された同じ形式である。

【API エラー・コードの構造体】
  * API エラー・コード
 D APIERR          DS                  QUALIFIED
 D  GETBYT                 1      4B 0 INZ(160)
 D  AVLBYT                 5      8B 0 INZ(0)
 D  MSGID                  9     15
 D  MSGDTA                17    160
【解説】
GETBYT :
API エラー構造体の長さを入れる。ここでは全体の長さ 160
定義しておく。
この長さも意味があり GETBYT の長さが 8 バイト以上に設定されていると
API エラーが発生したときは少なくとも MSGID の値を戻す。
これによって開発者はエラーの MSGID を知ることはできる。
しかしエラーのときは MSGDTA も受け取らないとエラーの詳細は
不明となるのでエラーの詳細を受け取りたいのであれば
GETBYT を 160 に設定しておくべきである。

一方、GETBYT を 0 に設定することもできる。
GETBYT が 0 に設定されていると API はエラーを戻すことができないので
そのまま CPF エラー・メッセージが送信される。
この場合は MSGID や MSGDTA を調べる必要がなく、
自動的にエラー・メッセージが送出されるのである意味、便利である。
API の使用がまだ初心者のうちはむしろ GETBYT は 0 に設定しておくことを
お勧めする。
GETBYT が 0 であるということは API エラー・コードがないのと同じである。

AVLBYT :
最初は 0 にセットして API に渡すとエラーが発生したときは
MSGDTA の長さが戻される。
IBM マニュアルには「使用可能なエラー情報の長さ」とあいまいな表現で
解説されているがエラーとして戻したときの MSGDTA の長さのことである。
また注意して欲しいのは IBMマニュアルには
「この値が 0 であれば、それはエラーがなかったことを意味します。」と
あるのは完全な誤りであり、ABLBYT が MSGDTA の長さを示している限り
MSGDTA がない CPF エラーが発生したときはこの値は 0 であるが
結果はエラーであることがある。
多くの場合は AVLBYT が 0 であればエラーは発生せず成功裡に完了したという
確率がかなり高いというに過ぎない。
一般的にはエラーかどうかは、この AVLBYT の値が 0 かどうか
(つまり 0 であれば成功)ということで判断してよいが
ごく稀に 0 であってもエラーである場合がある、ということを
覚えていて欲しい。
IBM のマニュアルの解説はほぼ合格点ではあるが完全な正解とはいえない。
MSGID  :
API がエラーを戻したときの CPF エラー・メッセージ識別コード (MSGID) が
ここに戻される。
メッセージ・ファイルやライブラリーの記述はないが MSGID は
必ず QSYS/QCPFMSG のものが戻されるのでメッセージ・ファイルなどの
定義は行われていない。
MSGDTA :
CPF メッセージとともに与えられるメッセージ・データであり
この長さは AVLBYT に定義されている。
従って MSGID と MSGDTA, ABLBYT を組み合わせれば
API: QMHRTVM (メッセージの検索) を使えばメッセージに組み立てることが
できる。

(1) AVLBYT を 0 に設定したエラー API 報告の受取り

この場合は API でエラーが発生した場合も API エラー構造体が
エラーを監視することはない。
従って CPF エラーがそのままの形で *ESCAPE メッセージとして
出力される。

エラーの内容はメッセージで報告されるのでわかりやすいが
CPF エラーがそのまま出力されるのでエンド・ユーザーには
不信感を与えて心配させてしまう可能性がある。
ソフトウェア製品の場合はこの設定はお勧めではない。

【AVLBYT = 0 の API エラー報告サンプル】
  D APIERR          DS
  D  GETBYT                 1      4B 0 INZ(0)
  D  AVLBYT                 5      8B 0 INZ(0)
  D  ECPERR                 9     15
  D  ECP                   16     16
  :
  C*----------------------------------------------------+
  C                   CALL      'QUSRJOBI'
  C                   PARM                    RCV400
  C                   PARM                    RCVLEN
  C                   PARM      'JOBI0400'    FORMAT            8
  C                   PARM                    JOBINFO
  C                   PARM                    JOBID            16
  C                   PARM                    APIERR
  C*----------------------------------------------------+
【解説】

ジョブ記述の取得 API: QUSRJOBI を実行してエラーになれば
CPF エラーが発生してこのプログラムは異常終了します。
これは APIERR 構造体の GETBYT が 0 に初期設定されているからです。
つまりエラーは監視されていない記述です。

(2) AVLBYT を 160 に設定したエラー API 報告の受取り

API エラー構造体がエラーの内容を監視していて
エラーがあれば API エラー構造体の MSGID と MSGDTA として
報告されるのでエラーがあってもいきなりプログラムが
中断して CPF エラーが送出されてしまうことはない。
しかし CPF エラーの制御はプログラム自身で
監視しておいて必要なエラーは QMHRTVM と QMHSNDPM を
使って送出するようにしなければならず
AVLBYT が 0 のときより手間がかなり多くなる。
しかしソフトウェア製品である場合は
このような制御をしっかりしておかないと
エラーが発生したときの調査や対応を難しくしてしまう。

ソフトウェア製品はユーザーの使用環境や操作によっては
エラーが発生することも想定しておかねばならない。
想定範囲でできうる限り広く考えて対応しておくことが
ソフトウェアの品質を保証することに繋がる。

【AVLBYT = 160 の API エラー報告サンプル】
 D APIERR          DS                  QUALIFIED
 D  GETBYT                 1      4B 0 INZ(160)
 D  AVLBYT                 5      8B 0 INZ(0)
 D  MSGID                  9     15
 D  MSGDTA                17    160

 C*----------------------------------------------------+
 C                   CALL      QMHRTVM
 C                   PARM                    RTVM0300
 C                   PARM                    RCVLEN
 C                   PARM      'RTVM0300'    FORMAT
 C                   PARM                    MSGID
 C                   PARM                    JPNMSGLIB
 C                   PARM                    MSGDTA
 C                   PARM                    MSGDTALEN
 C                   PARM      '*YES      '  REPDTA           10
 C                   PARM      '*YES      '  REPCHR           10
 C                   PARM                    APIERR
 C                   PARM                    OPTION
 C                   PARM                    CCSID_FROM
 C                   PARM                    CCSID_TO
 C*----------------------------------------------------+
  * CPF2419: EOF
 C                   IF        APIERR.AVLBYT > 0
 :
 C                   ENDIF
【解説】

ここでは GETBYT が 160 として
APIERR 構造体が 160 バイトで存在していることを
API に知らせているので API はエラーが発生すれば API 構造体の MSGID に
発生したメッセージ ID を入れ、MSGDTA にはエラー・データを入れて戻す。
API を呼び出したプログラムは MSGID と MSGDTA によって
API: QMHRTVM を使えばエラー・メッセージそのものを取り出すことができる。

まとめ

API エラー構造体の GETBYT の長さを 0 にして API を実行すると
エラーは監視されないでエラー・メッセージが表示されて異常終了する。
GETBYT を 160 に設定すると MSGID と MSGDTA を取り出すことができる。