非VSAMデータセット

本章では、レコード形式、DCB構造体、順次データセット、区分データセット、世代データセット・グループなど、非VSAMデータセットの特性と種類について記述します。

1. 概要

非VSAMデータセットとは、IBMのメインフレームでVSAMデータセットを提供する前に使われていたすべてのデータセットをいいます。したがって、VSAMデータセットでないデータセットは、すべて非VSAMデータセットです。

OpenFrameでは非VSAMデータセットをUNIXのファイル・システムで対応し、各データセットの種類に応じたアクセス方式は、別のOpenFrameインターフェースを提供しています。

2. レコード形式

OpenFrameでは、次の4つのレコード形式をサポートしています。

  • 固定長(RECFM=F)

  • 可変長(RECFM=V)

  • 行順次(RECFM=L)

  • 不定長(RECFM=U)

行順次レコード形式と不定長レコード形式以外のレコード形式は、RECFMパラメータに「B」を追加することでブロックI/Oが可能になります。データ・ブロックは、ディスク・ボリュームにデータが記録される前に、複数のレコードをまとめて1つのブロックとして構成したものです。

OpenFrameでは、RECFMパラメータに「B」が指定されていなくても、実際にディスクI/Oを実行するとき、内部バッファーを使用してバッファリングを行います。

固定長レコード形式

1つのデータセットにあるすべてのレコード・サイズは同じであり、ブロックI/O(RECFM=FB)をサポートします。ブロックI/Oでない場合、1つのレコードは1つのブロックとしてみなされます。

各レコードは、1つのブロック内で別のレコード区切り文字(Record Separator)なしで連続して保存されます。また、レコードを順次に読み取る場合、1つのブロックの中で、一度にレコードのサイズずつ読み取ります。

選択制御文字(Optional Control Character)は、各レコードをプリンターで出力するとき、キャリッジを制御する文字です。また、選択テーブル参照文字(Optional Table Reference Character)は、レコードの出力時にフォントを選択するためのコードです。

figure 2 1
固定長レコード
可変長レコード形式

可変長データセットに含まれている各レコードは、それぞれ異なる長さにすることができます。可変長レコード形式の場合、ブロックI/O(RECFM=VB)とスパン形式(RECFM=VS)を一緒に使用することができます。

スパン形式とは、論理レコードの長さが指定されたブロック・サイズより大きい場合、それをセグメント単位で分けてディスクに格納する形式です。OpenFrameでは、論理レコードをセグメント単位で分けて格納するのではなく、メインフレームとは異なる方式でブロックI/Oを実装しています。したがって、スパン形式が指定された状態で論理レコードの長さがブロック・サイズより大きい場合でも、読み書き動作が問題なく実行されます。

figure 2 2
可変長レコード

可変長のブロックは、BDW(Block Descriptor Word)と1つ以上の論理レコードから構成されています。BDWは、ブロックを付加説明する4バイト・サイズのフィールドです。OpenFrameではBDWは使用されません。

可変長レコードは、RDW(Record Descriptor Word)とデータから構成されます。RDWは、レコードを付加説明する4バイトのフィールドです。RDWの最初の2バイトは、RDWを含む論理レコードの長さを格納します。そして、3、4番目のバイトは、いずれも0に設定されています。

行順次レコード形式

行順次レコード形式は、UNIXのテキスト・ファイルと同じタイプのレコード形式です。ブロック単位のI/Oはサポートせず、データセット内の各レコードは、改行(LF)文字で区切られます。OpenFrame Batchのジョブで使用されるインストリーム・データセットやスプール出力データセットは、行順次レコード形式を使用します。

不定長レコード形式

不定長レコード形式は、特に決められた形式なしで入出力を行うためのレコード形式です。不定長レコード形式において、1ブロックは1つのレコードとみなされます。

選択制御文字

JCLのDD文やDCBパラメータには、データセット・レコードの一部として選択制御文字が含まれているかどうかを示すことができます。各レコードの先頭にある1バイトの出力制御文字は、データセットが出力されるときにキャリッジの制御を行います。この1バイトの文字は、レコードの一部としてデータセットに保存されますが、出力される際には表示されません。この制御文字の使用有無は、データ制御ブロック(DCB)のRECFMフィールドに「M」または「A」文字を指定することで決まります。「M」はマシン・コードを、「A」はANSIコードを意味します。

3. DCB構造体

OpenFrameでは、アプリケーションによってデータセットがオープンされる前に、処理するすべてのデータセットのデータ制御ブロック(DCB)が用意されている必要があります。データ制御ブロックは、データセットの適切な処理情報を持つ構造体であり、JCLのDD文、またはカタログのデータを抽出して構成されます。

一般的なJCLバッチ・ジョブを実行すると、システム内部でアプリケーションで必要とするすべてのデータセットの制御ブロックをJCLのDD文から作成し、アプリケーションに渡します。ただし、動的割り当てを使用するIDCAMS(JSCVSUT/KQCAMS)のようなユーティリティを使用して、直接データ制御ブロックを作成することもできます。

以下は、データ制御ブロックに指定されるデータセット情報の一部です。

項目 説明

Block Size (BLKSIZE)

入出力のためのデータ・ブロックの最大サイズを指定します。

指定しない場合、デバイスの種類によって32KBまたは64KBをデフォルト・ブロック・サイズとして使用します。OpenFrameでは、ブロック・サイズ・パラメータをサポートしていますが、実際にディスクI/Oを実行するときは、OpenFrame環境設定のdsサブジェクトのDATASET_DEFAULTセクションのNVSM_BUFFUR_SIZEキーに設定されているバッファー・サイズが使用されます。詳細については、OpenFrame Base『環境設定ガイド』を参照してください。

Data Set Organization (DSORG)

データセットの構造を指定します。

以下のような種類のデータセット構造を指定できます。

  • PS (Physical Sequential)

  • IS (Indexed Sequential)

  • PO (Partitioned)

  • DA (Direct)

Record Format (RECFM)

RECFMは、以下のようなレコードの特徴を持ちます。

  • 固定長(F)

  • 可変長(V)

  • 行順次(L)

  • 不定長(U)

ブロック単位の入出力をサポートする場合のRECFMはFBとVBが使用され、スパン形式のレコードをサポートする場合のRECFMはVS、VBSが使用されます。

Record Length (LRECL)

LRECLは、データセット・レコードの長さを指定します。可変長レコード形式または不定長レコード形式の場合は、最大レコード長を指定する必要があります。

4. スペースの割り当て

非VSAMデータセットのスペース・サイズを割り当てる方法について説明します。

1次スペースと2次スペースの決定

1次スペース(Primary Space)と2次スペース(Secondary Space)のサイズは以下のように決まります。

  1. データ・クラスのAVGREC、AVGVAL、PRIMARY、SECONDARYの値を使用する場合

    Primary Space = (PRIMARY * AVGVAL * AVGREC + 1023)/1024
    Secondary Space = (SECONDARY * AVGVAL * AVGREC + 1023)/1024
    項目 説明

    PRIMARY

    デフォルト値 : 4096

    SECONDARY

    デフォルト値 : 0

    AVGVAL

    CYL(768KB)、TRK(48KB)、またはLRECLに指定した値

  2. JCL DD文にLIKEまたはDCB=(dsname)が指定されている場合

    モデルとなるデータセットの1次スペースと2次スペースの値を使用します。

  3. JCL DD文のSPACEパラメータが指定されている場合

    SPACE=(AVGVAL、PRIMARY、SECONDARY)パラメータに対し、以下のように設定します。

    Primary Space = (PRIMARY * AVGVAL * AVGREC + 1023)/1024
    Secondary Space = (SECONDARY * AVGVAL * AVGREC + 1023)/1024
    項目 説明

    PRIMARY

    デフォルト値 : 4096

    SECONDARY

    デフォルト値 : 0

    AVGVAL

    CYL(768KB)、TRK(48KB)、またはLRECLに指定した値

  4. 1から3の方法で1次スペースが決まらなかった場合

    Primary Space = ボリュームデバイスの最大スペース値 (MB単位で指定)
    Secondary Space = 0
1次スペースと2次スペースで最大サイズを計算

決定された1次スペースと2次スペースの値を使って最大サイズを計算します。

Data Set Size Limit = (Primary Space + Secondary Space * conf_extent_limit) * 1024
項目 説明

conf_extent_limit

OpenFrame環境設定のdsサブジェクトのDATASET_DEFAULTセクションのNVSM_EXTENT_LIMITキーのVAUE項目の値であり、2次エクステントの最大回数を意味します。指定しない場合、デフォルト値は15です。

dsサブジェクトのDATASET_DEFAULTセクションに指定したDATASET_SIZE_LIMITキーのVALUE項目の値がデータセットの最大サイズより小さい場合は、DATASET_SIZE_LIMITキーの値を使用し、その逆の場合は、上記で計算したデータセットの最大サイズを使用します。

OpenFrame環境設定の詳細については、OpenFrame Base『環境設定ガイド』を参照してください。

5. 順次データセット

順次データセットは、OpenFrameシステムで最も一般的なデータセットです。レコードが格納された順にデータ処理が可能なデータセットです。順次データセットは、ハードディスクのボリュームやテープ・デバイス・ボリュームに格納することができます。

順次データセットの作成

QSAMまたはBSAMアクセス方式を使用すると、以下のような手順で順次データセットを作成することができます。

  1. DCBパラメータにDSORG=PSと指定します。

  2. DD文にデータセットの属性を記述します。

  3. データセットを開き、PUTまたはWRITE APIを実行した後、閉じます。

順次データセットの検索

以下は、順次データセットでレコードを読み取る手順です。

  1. DCBパラメータにDSORG=PSと指定します。

  2. DD文にデータセットの位置を指定します。

  3. データセットを開き、GETまたはREAD APIを使用した後、閉じます。

順次連結されたデータセット

OpenFrameシステムでは、2つ以上のデータセットを連結して、1つのデータセットであるかの連続的に検索できる方法を提供します。これを順次連結(Sequential Concatenation)といいます。

順次連結されたデータセットは逆読みができず、VSAMデータセットは順次連結をサポートしません。

以下は、BSAMを使用して複数のデータセットを順次連結する例です。

//INPUT DD  *
        ... (instream data set)
//      DD  DSN=IGKANG.MAIN.DATA,DISP=SHR
//      DD  DSN=IGKANG.SUPL.DATA,UNIT=3390,DISP=OLD,
             BLKSIZE=4096
順次データセットの変更

以下は、順次データセットを変更する2つの方法です。

  • 既存のレコード内容を変更(Update in place)

    既存のレコードの内容を変更するには、まず、レコードの内容を読み取って処理した後、変更されたレコードの内容を元の位置に書き込む必要があります。そのとき、以下のような規則が適用されます。

    • 既存のレコードは削除できません。

    • データセットはハードディスクのボリュームに存在している必要があります。

  • データセットの最後に新規レコードを追加(Extends the data set)

    データセットの最後に新規レコードを追加するには、DD文にDISP=MODを指定し、データセットをOUTPUTモードで開きます。その後、PUTまたはWRITE APIを使用することができます。順次データセットでの新規レコードは、常に最後のレコードとして追加されます。レコードとレコードの間に新規レコードを挿入することはできません。

6. 区分データセット

区分データセット(PDS)は、複数の順次構造を持つメンバーと、それぞれのメンバーを記述するディレクトリ項目で構成され、ハードディスクのボリュームにのみ格納されます。

各メンバーは、最大8文字の一意な名前を持ち、メンバーの各レコードは順次に読み書きすることができます。

figure 2 3
区分データセットの構造

区分データセットのメリットは、全体のデータセットを検索しなくても個別メンバーへのアクセスが可能な点です。たとえば、プログラム・ライブラリの場合、PDSの各メンバーは個別に実行可能なプログラムまたはサブルーチンです。必要に応じて、各メンバーの追加または削除が可能です。

OpenFrameでは、区分データセットをUNIXファイル・システムのディレクトリにマッピングし、メンバーは該当するディレクトリ内にある個別ファイルとして管理します。

区分データセットの作成

BSAM、QSAM、またはBPAMアクセス方式を使用して、区分データセットとPDSのメンバーを作成することができます。

以下は、データセットを作成してメンバーを追加する方法です。

  1. DCBパラメータにDSORG=PSと定義します。

  2. DD文に、データが新規PDSのメンバーとして格納されることを定義します。つまり、DSNAME=name(membername)、DISP=NEWと定義します。

  3. データセットを開き、PUTまたはWRITE APIを実行した後、閉じます。

以下は、区分データセットを作成するJCLの例です。

//PDSDD  DD   ---,DSNAME=MASTFILE(MEMBERK),SPACE=(TRK,(100,5,7)),
//            DISP=(NEW,CATLG),DCB=(DSORG=PS,RECFM=FB,LRECL=80),---

DSORG=PSの代わりにDSORG=POを指定し、PUT APIまたはWRITE APIの代わりにSTOW APIを使用すると、BPAMアクセス方式を使用してPDSを作成することができます。

既存のPDSに新規メンバーを追加する方法は前述した手順と同様ですが、ディスポジションだけ「変更」に指定します。(DISP=MOD)

以下は、一度に複数のメンバーを追加する方法です。

  1. DCBパラメータにDSORG=POと指定します。

  2. DD文でPDS全体のデータセットの位置を指定します。

  3. データセットを開き、STOW APIを使用して新規メンバーを追加します。

PDSメンバーの処理

PDSのメンバーは、一般の順次データセットと同じであるため、順次データセットの処理方法と同様にPDSのメンバーの入出力を行うことができます。ただし、ディレクトリ項目の管理やメンバーを検索するために、OpenFrameでは以下のような別のAPIを提供しています。

BLDL APIを使用すると、PDSのディレクトリ項目についての情報をすべて検索してメモリに読み込みます。FIND APIを使用すると、指定されたメンバーの位置にレポート・ポインターを移動させます。一方、STOW APIを使用すると、新しいメンバーの追加、既存メンバーの削除、メンバー名の変更などが可能になります。

上記のAPIを使用するためには、DCBパラメータにDSORG=POを指定する必要があります。

以下は、BPAMアクセス方式の各APIについての説明です。

API 説明

BLDL

ディレクトリ・リストを構成します。

BLDL APIを使用すると、ディレクトリ項目の情報をメモリに読み込みます。この情報を利用して、FIND APIからPDSのメンバーにアクセスできます。

FIND

メンバーの開始アドレス位置を取得します。

FIND APIを使用すると、レコード・ポインターを特定のメンバーの前に移動することができます。以降のI/O処理は、FINDによって指定された位置から実行されます。

STOW

ディレクトリをアップデートします。

1つ以上のメンバーをPDSに追加したい場合、STOW APIを使用してメンバーに該当するディレクトリ項目をPDSディレクトリに直接追加することができます。STOW APIを使用するには、DCBパラメータにDSORG=POを指定する必要があります。

PDSメンバーの検索

PDSで特定のメンバーを検索したい場合は、以下のようにBSAMまたはQSAMを使用します。

  1. DCBパラメータにDSORG=PSと指定します。

  2. DD文で既存のPDSのメンバーについて記述します。つまり、DSNAME=name(membername)と、DISP=OLD、DISP=SHR、またはDSIP=MODを指定します。

  3. データセットを開き、GETまたはREAD APIを使用した後、閉じます。

以下は、PDSのメンバーを処理するJCLの例です。

//PDSDD  DD   ---,DSN=MASTFILE(MEMBERK),
//            DISP=SHR,DCB=(DSORG=PS),---

7. 世代データ・グループ

OpenFrameでは、相互関係のある連続したデータセットをカタログする方法を提供します。これを世代データ・グループ(GDG:Generation Data Group)といいます。GDG内に含まれている各データセットを世代データセット、または世代と呼びます。

figure gdg concept
世代データ・グループの概念

世代データセットは、順次データセットでのみ構成でき、区分データセットやVSAMデータセットは世代データセットにはなれません。

相互関係のあるデータセットを世代データ・グループにまとめると、以下のようなメリットがあります。

  • 同じグループにあるデータセットは、同じ名前で参照できます。

  • システムはデータセットの世代を順番に管理することができます。

  • 古い世代のデータセットは、自動的にシステムから削除されます。

世代データセットは、自身の年齢を意味する絶対名と相対名を持っています。カタログ管理システムは、絶対世代名のみを使用します。年齢が多いデータセットは、小さい絶対数字を持っています。相対名の場合、最新のデータセットは(0)、その次の最新データセットは(-1)のような数字で表示されます。相対名は、新規世代(+1)をカタログ化するためにも使われます。

世代データ・グループ(GDG) BASEは、世代データセットがカタログされる前にカタログに登録されている必要があります。各世代データ・グループは、カタログされているGDG BASE項目によって代表されます。gdgcreateツールを使用して、GDG BASEをカタログに登録することができます。

gdgcreateプログラムについての詳細は、OpenFrame Base『ツールリファレンスガイド』を参照してください。

7.1. 絶対世代番号

絶対世代番号とバージョン番号は、GDGの世代を表すために使用されます。絶対世代番号とバージョン番号は、GxxxxVyyの形式を持ちます。xxxxは4桁の世代番号(0001から9999まで)、yyは2桁のバージョン番号(00から99まで)を示します。

以下は、絶対世代番号とバージョン番号の例です。

例) A.B.C.G0001V00

上記例は、A.B.Cという世代データ・グループの世代番号1、バージョン番号0のデータセットを表しています。

例) A.B.C.G0009V01

上記例は、A.B.Cという世代データ・グループの世代番号9、バージョン番号1のデータセットを表しています。

システムは世代番号を自動的に管理します。維持される世代の最大数は、GDG BASEに定義された限度(Limit)によって決まります。たとえば、限度が10のGDGは、最大10個の項目がGDGによって管理されます。

バージョン番号は、GDGによる世代管理を妨害せずに、一般的なデータセットの処理ができるようにします。たとえば、3つの世代が管理されているGDGで2番目の世代をアップデートしたい場合、G0002番の世代でV00番のバージョンをG0002番の世代でV01番のバージョンに変えることができます。1つの世代には1つのバージョンのみ、GDGによって管理されます。

世代データセットをカタログに登録する場合は、絶対名と相対名の両方を使用できます。世代が登録された場合は、その世代の世代番号がGDG項目に登録されます。バージョン番号がV00以外の世代データセットを登録するには、絶対世代とバージョン番号を使用する必要があります。

7.2. 相対世代番号

世代を指定するとき、絶対世代とバージョン番号を使用する代わりに、相対的な世代番号を使用することができます。相対世代番号を使用するには、A.B.C(-1)、A.B.C(+1)、A.B.C(0)のように、GDG名の後に括弧で囲まれた数字を指定します。

相対世代番号が与えられたら、システムは登録された最新の絶対世代番号を参考にして、与えられた相対世代番号に対応する絶対世代番号を検索します。たとえば、以前のジョブでA.B.C.G0005V00が最後にカタログされた世代データセットであるとした場合、A.B.C(+1)が与えられると、システムはA.B.C.G0006V00の絶対番号を割り当てます。

7.3. マルチステップ・ジョブにおける注意事項

マルチステップ・ジョブでデータセットをカタログ化あるいはアンカタログ化する場合は、IEHPROGM(JSGPROGM)や他のユーザー・プログラムを使用せずに、JCLのみを使用する必要があります。IEHPROGM(JSGPROGM)プログラムやユーザー・プログラムの実行中に割り当てられたデータセットは、データセット割り当て管理システムに通知されないため、その後のジョブ・ステップでデータセットの現在状態が失われ、衝突が生じるなどの問題が発生する可能性があるためです。

以前にカタログされた世代データセットの相対番号を使用して参照する場合、相対番号は以下のような意味を持ちます。

  • A.B.C(0)は、最後に登録された項目を示します。

  • A.B.C(-1)は、最後に登録された項目の1つ前の項目です。

JCLを使用してデータセットをカタログ化すると、実際のジョブはジョブ・ステップの終了時に実行されます。ただし、相対世代番号は実際のジョブが終了するまで保持されます。そのため、以下のような現象が起こります。

  • JCLで使用される相対世代番号は、バッチ・ジョブの実行中には常に同じ世代データセットを示します。

  • 世代データセットのGDGへのカタログ化が正常に終了したステップを再実行する場合、JCLをサブミットする前に相対世代番号をすべて変更する必要があります。たとえば、A.B.C(+1)はA.B.C(0)に、A.B.C(0)はA.B.C(-1)に、A.B.C(-1)はA.B.C(-2)に変更しなければなりません。

8. テープ・ボリュームの使用

テープ・ボリュームには、非VSAMデータセットを保管することができます。VSAMデータセットの保管はサポートしていません。

OpenFrameでテープ・ボリュームを割り当てて使用する場合は、実際に物理的なテープ・デバイスを使用するのではなく、DASDにボリュームをマッピングして使用し、テープ・ボリュームを仮想で使用することになります。テープ・ボリュームはvolmgrツールを使って作成できますが、テープ・デイバスを定義する際にデバイス・タイプ番号を3480に指定する必要があります。

volmgr define device -dn 0010 -dt 3480 -dg STAPE

そして、このテープ・デバイスに属する論理テープ・ボリュームと論理テープに属する物理テープ・ボリュームを定義します。

volmgr define volume -v STAPE1 -dn 0010
volmgr define volume -v ST0001 -lv STAPE1 -t

論理テープ・ボリュームには、物理テープ・ボリュームを2つ以上作成することができます。必要に応じてボリュームをスイッチして使用することもできます。

volmgr update volume -v STAPE1 -pv ST0002

8.1. ファイル・シーケンス番号

OpenFrameは、ファイル・シーケンス番号を利用したテープ・ボリュームのアクセスをサポートします。

ファイル・シーケンス番号を利用するためには、OpenFrame環境設定のdsサブジェクトのDATASET_DEFAULTセクションのUSE_TAPE_FILESEQキーの値をYESに指定します。

ofconfig update -n NODE1 -s ds -sec DATASET_DEFAULT -k USE_TAPE_FILESEQ -v YES

ファイル・シーケンス番号は、JCLを使ってデータセットにアクセスする場合に利用できます。XSPシステムではシーケンス番号をFILEに記述し、その他のシステムではDD文のLABELパラメータに記述します。シーケンス番号を利用すると、テープ・ボリュームでシーケンス番号に移動してデータセットを探します。データセット名は、シーケンス番号の位置にあるデータセットとの整合性を確認するために、または新規データセットを作成するときに利用されます。シーケンス番号が省略された場合は、データセット名でデータセットの場所を特定します。指定したデータセット名が存在しない場合は、シーケンス番号1番と見なされます。

8.2. データセットの削除

ファイル・シーケンス番号を利用しないテープ・データセットを削除する方法は、DASDに存在するデータセットを削除する方法と同じです。ここでは、ファイル・シーケンス番号を利用する場合のデータセットの削除方法について説明します。

テープ・デバイスでは新規データセットまたは既存のデータセットに新規レコードを作成する場合、その後ろにあるデータセットは破棄される特徴があります。OpenFrameでもこのような特徴をサポートします。テープの物理的な特徴によって削除されるのではなく、テープ・データセットがオープン(OUTPUTモード)されるときに、現在のデータセット以降のファイル・シーケンス番号のデータセットはすべて削除するように処理します。ただし、データセットがカタログに登録されている場合、カタログにはそのまま残ります。

テープ・データセットは、ジョブのDISPパラメータで削除することはできません。メインフレームではテープ・データセットをDISPパラメータでDELETEすることを禁じています。OpenFrameではDELETEを指定することは可能ですが、内部的にKEEPに変換されるため削除されません。ただし、dsdeleteツールを使用して削除することは可能です。dsdeleteツールを使ってデータセットを削除する場合、指定したデータセットとそれ以降のデータセットがすべて削除されます。

8.3. 注意事項

以下は、テープ・ボリュームを使用する際の注意事項です。

  • テープ・ボリュームのロック

    OpenFrameではファイル・シーケンス番号を利用する場合に限って、テープ・ボリュームを保護するためにデータセット・ロック以外に、ボリューム・ロックをかけられます。したがって、複数のジョブで同時に1つのテープ・ボリュームを使用することはできません。ただ、現在OpenFrameが提供するロックの特徴のため、同じアプリケーション・プログラムから1つのテープ・ボリュームにある複数のデータセットを同時に使用することを防ぐことはできません。このような場合は、データセットを使用するときに問題が発生することがあるので注意が必要です。

  • DCB Handling APIの使用

    ファイル・シーケンス番号を利用する場合は、DCB Handling APIを使用する際に注意が必要です。ファイル・シーケンス番号を利用する場合、テープ・データセット用のDCBはINPUTモード用に作成されます。OUTPUTモードで使用しようとするテープ・データセットは、オープンするまで正しい情報を持っていない可能性があります。したがって、DCB情報と属性の取得(Get Attributes)に関する関数は、テープ・データセットをオープンした後に実行してください。