【テクニカル・上級編】ON ENDFILEユニットによるファイル終端処理の制御構造 – PL/Iの基本構文とデータ制御実践ガイド

プロローグ:予約語なき言語の魔力と、基幹システムを支える「終わり方」

ようこそ、メインフレームの深淵へ。
現代のモダン言語、例えばJavaやC#、あるいはPythonに慣れ親しんだエンジニアが初めてPL/Iのソースコードを見たとき、彼らは決まってこう驚愕する。「なぜ、この言語には明確な予約語(Reserved Words)が存在しないのか?」と。

そう、PL/Iにおいて `IF` や `READ`、さらには `ENDFILE` さえも、文脈によってただの変数名になり得る。コンパイラは、その前後関係(Context)から高度な構文解析を行い、プログラマの意図を汲み取る。この自由度の高さは、かつてIBM 360の時代から膨大な業務ロジックを紡ぎ上げてきたレガシーシステムにおいて最大の武器であった反面、一歩間違えばコンパイラを欺き、本番障害という名の悪夢を引き起こす諸刃の剣でもあった。

今回は、そのPL/Iのデータ制御および例外処理の中でも、特にバッチ処理の生命線である「ON ENDFILEユニットによるファイル終端処理」と、それにまつわる極限の信頼性担保、そして将来的なJava/C#等へのマイグレーション(レガシー移行)における致命的な罠について、実務の現場を知り尽くしたアーキテクチャの視点から徹底的に紐解いていこう。

1. ON ENDFILEのアーキテクチャと、見落とされがちな「割り込み」のメカニズム

基幹システムの月次バッチなどで、数千万件のマスターファイルをシーケンシャルリードするプログラムを想像してほしい。ファイルの終わり(End of File)に到達した瞬間、OS(z/OSのBSAM/QSAMアクセス方式)とPL/Iランタイム環境(Language Environment / LE)は連携し、プログラムに対してシグナルを送る。

これが `ON ENDFILE` 割り込みだ。

1
DCL IN_FILE FILE RECORD SEQUENTIAL INPUT;
DCL EOF_FLG BIT(1) INIT(‘0’B);

/ ファイル終端(ENDFILE)発生時のONユニット定義 /
ON ENDFILE(IN_FILE)
BEGIN;
EOF_FLG = ‘1’B;
DISPLAY(‘INFO: 入力ファイルの終端を検知しました。‘);
END;

OPEN FILE(IN_FILE);

/ メインの読み込みループ /
READ FILE(IN_FILE) INTO(RECORD_AREA);
DO WHILE(^EOF_FLG);
/ 業務ロジックの処理 /
CALL PROCESS_RECORD();

READ FILE(IN_FILE) INTO(RECORD_AREA);
END;

CLOSE FILE(IN_FILE);

このコード、一見すると非常に美しく、教科書通りに動くように見える。しかし、テックリードたる者、ここで満足してはならない。この `ON` ユニットは、「条件発生時割り込み(Condition-Enabled Interruption)」である点に留意が必要だ。

LE(Language Environment)の管理下において、`ON` 文は一種のイベントハンドラとして機能するが、コールスタックの深部でこれを多重定義(Nested ON-units)したり、ゴーストのようにスコープが曖昧な状態で `SIGNAL ENDFILE` を誤爆させたりすると、意図せぬ制御フローのジャンプ(非局所脱出:Non-local transfer)を引き起こす。特に、エラーハンドリングとファイルクローズの順序を誤ると、未開放ファイルのリークや、最悪の場合はABEND(S0C4やU4038など)を引き起こし、夜間バッチのオペレータを叩き起こす惨事につながるのだ。

2. 現場の裏技:`SIGNAL ENDFILE` によるテスト駆動シミュレーション

単体テスト(Unit Testing)のフェーズにおいて、巨大なテスト用データファイルを用意せずに、ファイル終端の挙動をテストしたいという要求はよくある。ここでPL/Iの柔軟性、すなわち `SIGNAL` ステートメントが活きてくる。

1
/ 異常系テスト:強制的にENDFILE条件を発生させる /
SIGNAL ENDFILE(IN_FILE);

これをテストドライバ内に埋め込むことで、物理的なI/Oを行わずにファイル終端時のフラグ制御や後処理ルーチン(集計処理やログ出力)を完璧にシミュレートできる。
しかし、ここにはコンパイラ最適化(OPTIMIZEコンパイラオプション)との深刻なジレンマが存在する。

コンパイラ最適化とレジスタの生死

IBM Enterprise PL/Iコンパイラで `OPTIMIZE(2)` 以上の高水準最適化をかけると、コンパイラは「この変数の値はループ内で変化しない」と勝手に判断し、レジスタ上に変数の値をキャッシュしてしまう。
もし、非同期的な割り込み(ONユニット内)によってフラグ変数が書き換えられる可能性があるにもかかわらず、その変数が `VOLATILE` 属性を持っていない場合、ループが無限地獄(Infinite Loop)に陥るという、コンパイラ最適化特有のエッジケースに直面する。

実務でバッチを改修する際は、フラグ変数には必ず以下のような配慮が必要だ。

1
Dcl EOF_FLG Bit(1) Init(‘0’B) Volatile; / コンパイラの過度な最適化を抑止 /

この一行をケチったばかりに、本番環境でCPU使用率が100%に張り付き、ジョブが強制停止させられた苦い記憶を持つエンジニアは私だけではないはずだ。

3. マイグレーション(Java / C#化)における致命的断層

さて、ここからがレガシー移行スペシャリストとしての本題だ。
顧客から「この古いPL/Iバッチ群を、完全オープンなJava(Spring Batch)あるいはC#(.NET Core)にリライトしてくれ」と頼まれたとする。

多くのモダン開発者は、PL/Iの `ON ENDFILE` を見てこう考える。
> 「あぁ、ファイルの終端判定ね。Javaなら `BufferedReader.readLine() != null` でループを回せば一発だろ。簡単簡単」

――甘い。甘すぎる。

基幹システムのデータ構造、特にパックデシマル(COMP-3)や、ポインタとベース変数(Based Variables)を駆使した可変長レコードの扱い、そして何より「ファイル構造の物理的な不整合」「DB2埋め込みSQL(Embedded SQL)とのトランザクション同期」において、PL/Iの例外処理モデルとJava/C#の例外モデルの間には、埋めがたい断層が存在する。

エッジケース①:パックデシマルの内部符号反転バグ

PL/Iでは `PIC S9(7) COMP-3` のように定義されたフィールドに、もし不正なゾーンやパック文字(例えばスペースや英字)が混入していた場合、読み込み時や演算時に `CONVERSION` 条件が発生し、それに対応する `ON CONVERSION` ユニットでトラップすることが可能だった。
しかし、これをJavaに移行した際、単純な数値型へのキャストやライブラリの解釈ミスにより、符号部分(ニブル)の読み取りに失敗し、サイレント・コラプション(沈黙のデータ破壊)を引き起こすケースが後を絶たない。エラーを検知できずに、誤った金額データがDB2へ書き込まれてしまうのだ。

エッジケース②:CICSオンラインとファイル制御の非同期

もしこの処理がバッチではなく、CICS(Customer Information Control System)オンラインのトランザクション内で疑似的にファイルアクセスを行っている場合(非常に悪趣味な設計だが、レガシーではよくある)、`ENDFILE` の制御を誤ると、タスク異常終了時のバックアウト処理やストレージ解放(FREEMAIN)が正常に行われず、CICS領域全体を巻き込んだSOS(Storage Shortage)を引き起こす。

移行設計への提言

Java/C#へのマイグレーションを行う際、単に構文を機械的に置き換える(トランスコンパイラ頼み)アプローチは、99%の確率で失敗する。
PL/Iの `ON` ユニット(条件管理機構)が持っている「スコープ内での動的エラー捕捉」の哲学を理解し、移行先のモダン言語側でAOP(アスペクト指向プログラミング)や堅牢な例外ハンドリング・パイプラインとして再設計しなければならない。特にファイル終端やデータ変換エラーは、業務継続性(Business Continuity)に直結するからだ。

エピローグ:コードの背後にある「思想」を継承せよ

PL/Iは、古い。しかし、古いからといってそのアーキテクチャが陳腐化しているわけではない。むしろ、ハードウェアの資源が極限まで限られていた時代に、システムが予期せぬ異常(End of FileやOverflowなど)にどう立ち向かうべきかという、「システム高信頼化の原点」がそこには詰まっている。

あなたが今、レガシーシステムのモダナイゼーションやマイグレーションの最前線にいるのなら、単に「動くコードを書く」のではなく、「元のPL/Iがどのようなコンパイラ挙動と例外制御の思想で作られていたか」を深く洞察してほしい。

その深い理解こそが、新旧システムの間にかかる、最も安全で強固な橋となるのだから。

タイトルとURLをコピーしました