CICSとPL/Iの「深淵」:DFHCOMMAREAによるトランザクション間通信の極意
メインフレームの現場で長く戦っていると、「なぜあの時、あんなコードを書いたのか」と頭を抱えるようなレガシーコードに遭遇することがある。特にCICS環境下でのPL/Iプログラムにおいて、`DFHCOMMAREA`(通信域)を介したデータ受け渡しは、システム全体の整合性を左右する心臓部だ。
今日は、若手のエンジニアが真っ先に躓く、あるいはベテランがうっかりミスで落とし穴にはまる、この「トランザクション間通信の作法」について、現場の視点から紐解いていこう。
—
1. CICSプログラムの基本形と「お約束」
PL/IでCICSプログラムを書く際、`OPTIONS(MAIN)`は必須だが、それ以上に重要なのが「環境の理解」だ。CICSはあなたのプログラムを呼び出す際、`DFHEIBLK`(EXEC Interface Block)と`DFHCOMMAREA`という二つの特別なポインタをレジスタに載せてくる。
PL/I側でこれを受け取るには、`PROCEDURE`文の引数にこれらを明示的に記述する必要がある。
/i
/ プログラムの入り口:リンクされる側もメイン側もこの構造を意識する /
MYPROG: PROC(DFHEIBLK, DFHCOMMAREA) OPTIONS(MAIN);
/ CICS制御ブロックの宣言 /
DCL DFHEIBLK PTR;
DCL DFHCOMMAREA PTR;
/ 通信域の構造を定義するテンプレート(基底変数) /
DCL 1 COMM_AREA_STRUCT BASED(DFHCOMMAREA),
3 TRANSACTION_ID CHAR(4),
3 USER_ID CHAR(8),
3 DATA_PAYLOAD CHAR(100);
/ … 処理が続く … /
ここで重要なのは、`BASED`変数を使用することだ。CICSが確保したメモリ領域に対し、PL/Iの構造体を「被せる」イメージを持つこと。これを怠って自前で領域確保(`ALLOCATE`)などしようものなら、メモリリークや不正な領域参照で、深夜の障害呼び出しを食らうことになる。
—
2. データマッピングの「落とし穴」
多くのエンジニアが陥る罠が、「CICS側で定義したCOPYBOOKとPL/I構造体の不一致」だ。
特に、`BINARY`データの表現や、`ALIGN`(境界調整)の有無は要注意だ。PL/Iのデフォルトでは、構造体のメンバーはワード境界に合わせて配置されることがある。もし相手のCOBOLプログラムが`SYNCHRONIZED`を指定していない場合、あるいはCICSの通信域が特定のレイアウトを強制している場合、メモリ上のオフセットがずれてしまう。
/i
/ 安全なマッピングのためにUNALIGNEDを活用する /
DCL 1 COMM_AREA_STRUCT BASED(DFHCOMMAREA),
3 TRAN_CODE CHAR(4),
3 SEQ_NO FIXED BIN(15,0), / 2バイト /
3 FILLER CHAR(2), / 位置合わせ用 /
3 DATA CHAR(50) UNALIGNED;
実務では、`UNALIGNED`属性を明示的に指定し、構造体を「詰めて」配置させるのが定石だ。また、`LENGTH`ビルトイン関数を使い、実際に受け取った`EIBCALEN`(EIB内の長さ)と、期待する構造体のサイズを必ず突き合わせること。これだけで、多くの境界異常系バグは防げる。
—
3. ONユニットによる「防衛的コーディング」
CICS環境下では、予期せぬデータエラーでトランザクションが異常終了(ABEND)すると、後続の業務に甚大な影響が出る。特に`DFHCOMMAREA`からのデータ読み込み時に、型変換エラーや範囲外参照が発生する可能性があるなら、`ON`ユニットで制御フローを制御すべきだ。
/i
/ データ変換エラーをトラップして安全にログ出力する /
ON CONVERSION BEGIN;
/ 異常なデータが入ってきた場合のリカバリ処理 /
EXEC CICS SEND TEXT FROM(‘データ形式不正発生’);
SIGNAL FINISH; / 安全に終了処理へ /
END;
/ VSAMアクセス時のエラー制御 /
ON CONDITION(IO_ERROR) BEGIN;
/ 現場ではここに独自のトレース処理を入れる /
CALL LOG_ERROR(EIBFN, EIBRCODE);
END;
—
4. 現場の教訓:なぜ「デバッグ」が難しいのか
最後に、現場で生き残るための知恵を一つ。CICSトランザクション間でデータを渡す際、単なる「構造体の受け渡し」で済まそうとしないことだ。
1. バージョン管理: 構造体のレイアウトが変わる際は、必ず先頭に「バージョン番号」を持たせろ。これにより、古いトランザクションと新しいトランザクションが混在した際、即座に不整合を検知できる。
2. EIBの有効活用: `EIBTRNID`(トランザクションID)や`EIBCALEN`(通信域長)はデバッグの宝庫だ。エラーログには、これらの値を必ず埋め込むこと。「なぜ動かない?」と悩んだとき、EIBの情報があれば解決までの時間は半分になる。
PL/Iは古臭い言語だと言われることもあるが、メモリレイアウトをこれほど精密に制御できる言語は他にない。この特性を活かし、CICSという堅牢な基盤の上で、いかに「落ちない」プログラムを作るか。それが、君たちシステムアーキテクトに求められる職人技だ。
今日の解説が、君の次なる改修作業の一助となれば幸いだ。何か行き詰まったら、いつでもコンパイラの吐き出すリストと、EIBの中身を信じろ。答えは必ずそこにある。
