【テクニカル・上級編】RECORDファイルにおけるKEYED/SEQUENTIALアクセスの内部制御 – PL/Iの基本構文とデータ制御実践ガイド

基幹システムの心臓部を暴く:VSAM RECORDアクセスの内部制御とポインタマジック

こんにちは。金融や公共の巨大システムで、何十年も動き続けてきたメインフレームの「泥臭さ」と「美しさ」の双方に魅せられてやまないシステムアーキテクトです。

現代のオープン系エンジニアから見れば、PL/Iという言語は「古臭い恐竜の化石」のように映るかもしれません。しかし、コンパイラの挙動、OSのアクセス・メソッド、そしてハードウェアのキャッシュラインの動きまでを意識して書かれたPL/Iのコードは、現代のどの高水準言語よりもハードウェアに直結した鋭い牙を持っています。

今回は、基幹システムのバッチ処理において避けて通れない、VSAMファイル等におけるRECORD入出力(KEYED/SEQUENTIALアクセス)の内部制御について、コンパイラの裏側まで踏み込んで徹底的に解説します。JavaやC#へのマイグレーション(レガシー移行)を控えたアーキテクトにとっても、オープン系へロジックを再構築する際に「絶対に踏んではいけない地雷」が見えてくるはずです。

1. 予約語なき世界:PL/Iの識別子とポインタの自由度

まず、PL/Iの根底にある思想に触れておきましょう。C言語やJavaとは異なり、PL/Iには「厳格な予約語(Reserved Words)」という概念がほとんど存在しません。`IF` や `READ` でさえも文脈キーワードであり、変数名として使うことすら理論上は可能です(推奨はしませんが)。

この「何でもありの柔軟性」は、ベース変数とポインタを組み合わせた動的なメモリ操作において、極限のパフォーマンスを発揮します。

1
/ ポインタとベース変数を用いた動的レコード操作の例 /
DCL 1 VSAM_REC BASED(P_REC),
5 KEY_FLD CHAR(8),
5 DATA_FLD CHAR(100);

DCL P_REC POINTER;
DCL MY_FILE FILE RECORD SEQUENTIAL;

オープン系のプログラマがここで驚くのは、`READ FILE(MY_FILE) SET(P_REC);` という構文です。アプリケーション側でバッファ領域を `DECLARE` してそこにデータを「読み込む」のではなく、VSAMのアクセスメソッドが管理する内部バッファのポインタを、こちらのポインタ変数に直接突っ込む(ロケール参照)。これがPL/IのRECORDアクセスにおける最大の武器であり、同時に「諸刃の剣」です。

2. KEYEDアクセスとSEQUENTIALアクセスの内部ポインタ管理

VSAM(KSDS:Key-Sequenced Data Set)に対する処理を考えるとき、私たちは `KEY()` オプションを用いた直接アクセス(KEYED)と、順次読み込み(SEQUENTIAL)を使い分けます。

内部で何が起きているか?

  • SEQUENTIALアクセス: アクセス・メソッドは論理レコードのチェーン、あるいはCI(コントロール・インターバル)の物理的順序に従って、シーケンシャルにレコードポインタを進めます。
  • KEYEDアクセス: 索引(Index)構造を辿って該当するCIを特定し、レコードをピンポイントでヒットさせます。

ここでバッチ処理の現場でよくある事故が、「KEYEDでランダムアクセスした直後に、何の断りもなくSEQUENTIALのREADを発行する」ケースです。

1
/ キー指定でランダム読み込み /
READ FILE(MASTER_FILE) INTO(REC_BUF) KEY(W_KEY);

/ その直後に順次読み込みを継続しようとする /
READ FILE(MASTER_FILE) INTO(REC_BUF); / ⚠️危険な領域 /

OSのVSAM管理ブロック(ACB/RPL)の視点から見ると、ランダムアクセスによってカレント・レコード・ポインタ(CRP)の文脈が一度破壊(あるいは再設定)されています。コンパイラやOSの種類、VSAMの定義(REUSEの有無など)によっては、予期せぬ位置から順次読み込みが再開され、重複処理やレコードのスキップ(データ欠損)という、監査で一発レッドカード級の致命的なサイレントバグを引き起こします。

KEYEDからSEQUENTIALへ移行する際は、必ず `POINT` ステートメントなどで明示的にポインタ(CRP)の位置を再確立する。これがメインフレーム前線における鉄則です。

3. アベンド(ABEND)解析とダンプの読み方

万が一、ストレージの破損や不正なポインタ参照によって `S0C4`(保護例外)や `ASRA` などのアベンドが発生したとき、システムアーキテクトとしての真価が問われます。

PL/Iのダンプ(SYSUDUMP / CEEDUMP)を解析する際、注目すべきは以下の点です。

1. OFFSETとCEEDUMPのトレースバック:
どのステートメントの、どの `READ` / `WRITE` でポインタが無効(`NULL()` または解放済み領域を指している)になったか。
2. ベース変数のオフセット:
`P_REC` が指すアドレスの16進数ダンプを確認し、VSAMのキー部分が正しくセットされていたか、あるいはパディング(位置合わせ)のズレによってパックデシマル(COMP-3)の符号が壊れていないか。

特に、マイグレーション時にありがちなのが、C#やJava側でバイトアライメントの解釈を誤り、PL/Iが期待する構造体のパディング(境界調整)とズレが生じるケースです。PL/I側で `ALIGNED` 属性と `UNALIGNED` 属性をどう定義しているか、コンパイルリストのストレージ・マップを直視してデバッグしなければなりません。

4. エッジケース:パックデシマルの符号反転とDB2/CICSの罠

基幹システムのデータ不整合で最も嫌らしいものの一つが、パックデシマル(COMP-3)の内部符号反転バグです。

PL/Iで `DCL 5NUM_AMT FIXED DECIMAL(7,2);` と定義されたフィールドは、内部的に Packed Decimal として保持されます。VSAMのレコードをダイレクトにバイナリ転送したり、オープン系への移行過程で文字コード変換(EBCDICからASCIIへの誤ったキャスト等)を通したりすると、最下位ニブルの符号部(C, D, Fなど)が破壊されます。

この状態で算術演算やKEYとしての比較を行うと、コンパイラが生成するハードウェア命令(Zアーキテクチャの `AP` や `CP` など)がデータ例外(S0C7アベンド)を引き起こすか、最悪の場合、符号が反転してマイナスの金額がプラスとして処理されるという、会計システムにとって悪夢のような事態を招きます。

埋め込みSQL(DB2)やCICSとの統合

CICSオンラインやDB2を伴う環境では、RECORDファイルの操作はさらに複雑化します。

  • CICSの `EXEC CICS READ FILE(…) INTO(…)` を使用する場合、PL/Iのポインタ制御とCICSのストレージ管理(DFHStorage)が密接に絡み合います。
  • タスク終了時のストレージ解放漏れは、CICS領域全体を巻き込む `AKER` などのストレージ・オールド・エイジ(Storage Violation)を引き起こします。

動的に割り当てたメモリや、VSAMが返したポインタ領域のライフサイクル管理は、JavaのGC(ガベージコレクション)に慣れた世代のエンジニアが最も見落としやすいポイントです。

5. マイグレーション(レガシー移行)への示唆

もしあなたが、今まさにこのPL/Iで書かれた巨大なVSAM処理を、Java(Spring Bootなど)やC#(.NET Core)へ移行するプロジェクトのテックリードであるならば、以下の設計方針を強く推奨します。

1. 「ポインタによる直接参照」の模倣を諦める:
オープン系言語でポインタやアンセーフティなメモリ操作を無理に再現しようとすると、保守性の低い「動かないスパゲッティコード」が完成します。データ構造を一度明確なオブジェクト/DTOにシリアライズ/デシリアライズするアーキテクチャへ割り切ってください。
2. VSAM KSDSの振る舞いをリレーショナルDB(RDB)でエミュレートする:
VSAMのKEYED/SEQUENTIALの混在アクセスがビジネスロジックのどこに依存しているかを徹底的に洗い出し、RDBのカーソル制御(Cursor Control)やインデックス設計に正しくマッピングします。「とりあえず全件フェッチしてメモリ上で処理する」という力技は、メインフレームのバッチスループットを基準にした場合、必ず性能劣化を招きます。

結びに代えて

PL/IのRECORDアクセスにおけるKEYEDとSEQUENTIALの内部制御、そしてポインタを駆使したメモリ管理は、ハードウェアの制約と極限まで向き合ってきた先人たちの知恵の結晶です。

単なる「古い言語の置き換え」として機械的な自動変換ツール(トランスレータ)に頼るだけでは、基幹システムが何十年もかけて培ってきた「堅牢性」の牙城を崩してしまうことになりかねません。

コンパイラが裏側でどのようなコードを吐き出し、OSのアクセスメソッドがどう動いているのか。その「底の底」を知るアーキテクトだけが、次世代の堅牢なシステムを作り上げることができます。さあ、今日もコードの深淵へ潜りましょう。

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