10.1データセットを割り振る(DYNALLOC)
MVSではプログラムがアクセスするデータセットは、ジョブを実行するJCLのDD文で、あらかじめ定義しておくのが一般的です。バッチ処理においては、ほとんどのジョブがDD文による事前の定義を行っています。
しかしオンライン処理、特にTSOなどの対話型処理では、事前に使用するデータセットを決めることができません。例えばエディターがそうです。編集するデータセットは、エディターを起動した後に、パネルにそのDSNを指定します。つまりエディターと言うプログラムは、起動してみなければどのデータセットをアクセスするか決められないわけです。
またバッチ処理であっても、プログラムの処理中にアクセスするデータセットを決める、と言うことはありえないことではありません。
このような場合、データセットの割り振りはJCLのDD文ではなく、プログラムからMVSのAPIを呼び出してデータセットを割り振ります。これがダイナミック・アロケーション(動的割り振り)と呼ばれるものです。ダイナミック・アロケーションはDYNALLOCマクロによってSVC99を発行することで行われます。
カタログ済みの既存データセットをアロケーションする
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
MVI DALFUNC,1 INDICATE ALLOCATION
LA R1,DALRBP GR1 --> SVC99 RB POINTER
DYNALLOC , ALLOCATE DATASET BY SVC99
LTR RF,RF SUCCESSFUL ?
BNZ ERROR NO,
MVC DDNAME+6(8),RTNDDN+6 SET DDNAME FOR UN-ALLOCATION
:
:
MVI DALFUNC,2 INDICATE UNALLOCATION
LA R1,DALTUPL2 LOAD TUPL FOR UNALLOCATION
ST R1,DALTUP SET IT INTO RB
LA R1,DALRBP GR1 --> SVC99 RB POINTER
DYNALLOC , ALLOCATE DATASET BY SVC99
LTR RF,RF SUCCESSFUL ?
BNZ ERROR NO,
:
:
:
DALRBP DC A(DALRB+X'80000000') SVC99 RB POINTER
SPACE ,
DALRB DC XL20'00' SVC99 RB
ORG DALRB
DC AL1(20) RB LENGTH
DALFUNC DC AL1(0) FUNCTION CODE
DC XL2'00' OPTION-1
DALERRO DC AL2(0) ERROR CODE
DALINFO DC AL2(0) INFORMATION CODE
DALTUP DC A(DALTUPL1) PTR TO TEXT UNIT POINTER LIST
DC A(0) PTR TO RB EXTENSION
DC XL4'00' OPTION-2
ORG ,
DALTUPL1 CALL ,(RTNDDN,DSNAME,DISP1), SVC99 TEXT UNIT POINTER LIST +
VL,MF=L
DALTUPL2 CALL ,(DDNAME),VL,MF=L SVC99 TEXT UNIT POINTER LIST
SPACE ,
DDNAME DC XL2'0001' ALLOCATED DDNAME FOR UNALLOC
DC AL2(1) NUM
DC AL2(8) LNG
DC CL8' ' PARM
DSNAME DC XL2'0002' ALLOCATING DSNAME
DC AL2(1) NUM
DC AL2(44) LNG
DC CL44'MY.TEST.DATA1' PARM:DSN=
DISP1 DC XL2'0004' DS STATUS(DISP-1)
DC AL2(1) NUM
DC AL2(1) LNG
DC XL1'08' PARM:DISP=SHR
RTNDDN DC XL2'0055' RETURN DDNAME
DC AL2(1) NUM
DC AL2(8) LNG
DC CL8' ' PARM
既存のデータセットをアロケーションする例です。わかりやすくするために、アロケーションとアンアロケーションのテキストユニットを分けていますが、実際のプログラムではもう少しすっきりさせる方がいいでしょう。
DYNALLOCは、APIの中では呼び出し手順が複雑なものです。覚えるまではむずかしく思えますが、慣れの問題です。
必要なパラメーターは大きく、4種類に分かれます。1つ目が、RBポインター・フィールド、サンプルではDALRBPです。フルワードの領域に、DYNALLOCのRBアドレスを格納して先頭ビットをONにします。
2つ目が、RBです。DYNALLOCのパラメーター・リストで、要求する機能、復帰時のエラーコード、テキストユニット・ポインター・リストのアドレス、オプション・フラグなどで構成されています。
3つ目が、テキストユニット・ポインター・リストです。各テキストユニットのアドレスを格納したポインター・リストです。リストの最終エントリーの先頭ビットをONにします。
4つ目が、テキストユニットです。テキストユニットはJCLのDD文の各パラメーターに相当します。基本的にDD文の各パラメーターに対応してテキストユニットを用意します。
パラメーターを準備し、初期設定したら、GR1にRBポインター・フィールドのアドレスを入れ、DYNALLOCマクロを発行します。DYNALLOCマクロ自身にはパラメーターはなく、単にSVC 99命令を発行するだけのものです。直接SVC命令を書いても大差ありませんが、マクロを使用して呼び出すのがオーソドックスな手順です。
GR15が復帰コードです。0以外であれば何らかの誤りが起きていますから、RBに設定されているエラーコードを参照して必要なエラー処理を行います。0で完了しても状況によっては情報コードで、エラーが通知される場合もあります(特にアンアロケーション時)。例えば、DISP=(NEW,KEEP)の指定をしてアロケーションしたデータセットを、後処理をCATLGに変更してアンアロケーションした時、すでに同名データセットがカタログされていたような場合です。このアンアロケーション自体は成功していますが、データセットのカタログには失敗しています(NOT CATLGD 2と同じ)。なおアロケーション時にDISP=(NEW,CATLG)を指定していれば、アロケーション時に失敗しエラーで通知されます。この場合、データセットも作成されていません。
なおアンアロケーションは必ずしも必要ではありません。アロケーションした後、OPEN?I/O?CLOSEを行う場合、CLOSE時にデータセットを自動的にアンアロケーションするオプションも指定できます(アロケーション時にキーx001Cのテキストユニットを指定する)。OPEN/CLOSEを繰り返さないのであれば、この機能を使うと便利です。
新しいデータセットを作成する
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
USING S99RBP,DALRBP ADDRESS TO SVC99 RB POINTER
USING S99RB,DALRB ADDRESS TO SVC99 RB
USING S99RBX,DALRBX ADDRESS TO SVC99 RB EXTENSION
SPACE ,
MVI S99VERB,S99VRBAL INDICATE ALLOCATION
LA R1,S99RBP GR1 --> SVC99 RB POINTER
DYNALLOC , ALLOCATE DATASET BY SVC99
LTR RF,RF SUCCESSFUL ?
BNZ ERROR NO,
:
:
:
MVC DDNAME,=AL2(DUNDDNAM) TEXT UNIT = DDNAME
OI DALTUPL,X'80' INDICATES TUPL HAS DDNAME ONLY
MVI S99VERB,S99VRBUN INDICATE UNALLOCATION
LA R1,S99RBP GR1 --> SVC99 RB POINTER
DYNALLOC , ALLOCATE DATASET BY SVC99
LTR RF,RF SUCCESSFUL ?
BNZ ERROR NO,
:
:
:
DALRBP DC A(DALRB+X'80000000') SVC99 RB POINTER
SPACE ,
DALRB DC (S99RBEND-S99RB)X'00' SVC99 RB
ORG DALRB
DC AL1(S99RBEND-S99RB) RB LENGTH
DC AL1(0) FUNCTION CODE
DC XL2'00' OPTION-1
DC AL2(0) ERROR CODE
DC AL2(0) INFORMATION CODE
DC A(DALTUPL) PTR TO TEXT UNIT POINTER LIST
DC A(DALRBX) PTR TO RB EXTENSION
DC XL4'00' OPTION-2
ORG ,
DALRBX DC (S99ERSN+L'S99ERSN-S99RBX)X'00' SVC99 RB EXTENSION
ORG DALRBX
DC CL6'S99RBX'
DC AL1(S99RBXVR)
DC AL1(S99EIMSG+S99ERMSG+S99EWTP) (SVC99 EXTEND ERROR MSG)
DC AL1(0)
DC AL1(0)
DC AL1(S99XINFO)
ORG ,
DALTUPL CALL ,(DDNAME,DSNAME, SVC99 TEXT UNIT POINTER LIST +
DISP1,DISP2, +
UNIT,VOLSER, +
SPACE,PRIME,SECND), +
VL,MF=L
SPACE ,
DDNAME DC AL2(DALRTDDN) RETURN/ALLOCATED DDNAME
DC AL2(1) NUM
DC AL2(8) LNG
DC CL8' ' PARM
DSNAME DC AL2(DALDSNAM) ALLOCATING DSNAME
DC AL2(1) NUM
DC AL2(44) LNG
DC CL44'MY.TEST.DATA2' PARM:DSN=
DISP1 DC AL2(DALSTATS) DS STATUS(DISP-1)
DC AL2(1) NUM
DC AL2(1) LNG
DC XL1'04' PARM:DISP=(NEW)
DISP2 DC AL2(DALNDISP) DS DISPOSITION(DISP-2)
DC AL2(1) NUM
DC AL2(1) LNG
DC XL1'02' PARM:DISP=(,CATLG)
UNIT DC AL2(DALUNIT) UNIT NAME
DC AL2(1) NUM
DC AL2(8) LNG
DC CL8'SYSALLDA' PARM:UNIT=SYSALLDA
VOLSER DC AL2(DALVLSER) VOLUME NAME
DC AL2(1) NUM
DC AL2(6) LNG
DC CL6'WRKVOL' PARM:VOL=SER=WRKVOL
SPACE DC AL2(DALTRK) SPACE UNITS
DC AL2(0) NUM
DC AL2(0) LNG
PRIME DC AL2(DALPRIME) PRIMARY SPACE QUANTITY
DC AL2(1) NUM
DC AL2(3) LNG
DC AL3(10) PARM:SPACE=(TRK,(10))
SECND DC AL2(DALSECND) SECONDARY SPACE QUANTITY
DC AL2(1) NUM
DC AL2(3) LNG
DC AL3(2) PARM:SPACE=(TRK,(10,2))
:
:
:
IEFZB4D0 DYNALLOC PLIST
IEFZB4D2 DYNALLOC KEY LIST
新規のデータセットをDYNALLOCで割り振るサンプルです。DYNALLOC自体の出し方は既存のデータセットと変わりません。指定するテキストユニットが増えるだけです。DCB属性に関するテキストユニットは指定していませんが、アロケーション後に、OUTPUTオープンすればDCBに指定したRECFMやLRECLなどで設定されます。
先ほどは、DYNALLOCのパラメーターを直接コーディングする方法で使いましたが、今度はOSが提供するDYNALLOCのパラメーター・リストのDSECTを使って、OS標準のフィールド名でアクセスしています。簡単なプログラムではDSECTを使う方が逆に面倒になりますが、きちんとした正式なプログラムや商用プログラムの場合、提供されているのなら、OSのマッピング・マクロを使うのがオーソドックスな作り方になります。
またRBエクステンションも指定して、DYNALLOCがエラーになった時、コンソールにメッセージが出力されるようにしています。この機能を使えば、エラーコードを解析しなくても診断情報を簡単に得ることができます。編集されたメッセージをプログラムで処理できるように、そのメッセージが格納されたアドレスなどを通知してもらうこともできます。RBエクステンションで指定すれば、メッセージの作成と出力はDYNALLOCサービスの中で自動的に行ってくれます。RBエクステンションはMVSでのみ有効な機能です。
SYSOUTデータセットをアロケーションする
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
USING S99RBP,DALRBP ADDRESS TO SVC99 RB POINTER
USING S99RB,DALRB ADDRESS TO SVC99 RB
SPACE ,
MVI S99VERB,S99VRBAL INDICATE ALLOCATION
LA R1,S99RBP GR1 --> SVC99 RB POINTER
DYNALLOC , ALLOCATE DATASET BY SVC99
LTR RF,RF SUCCESSFUL ?
BNZ ERROR NO,
:
:
:
MVC DCBDDNAM,DDNAME+6 SET ALLOCATED DDNAME
OPEN (SYSPRINT,OUTPUT) OPEN SYSPRINT DATASET
PUT SYSPRINT,DATA PUT DATA LINE
CLOSE SYSPRINT CLOSE AND UNALLOCATE SYSOUT
:
:
:
DALRBP DC A(DALRB+X'80000000') SVC99 RB POINTER
SPACE ,
DALRB DC (S99RBEND-S99RB)X'00' SVC99 RB
ORG DALRB
DC AL1(S99RBEND-S99RB) RB LENGTH
DC AL1(0) FUNCTION CODE
DC XL2'00' OPTION-1
DC AL2(0) ERROR CODE
DC AL2(0) INFORMATION CODE
DC A(DALTUPL) PTR TO TEXT UNIT POINTER LIST
DC A(0) PTR TO RB EXTENSION
DC XL4'00' OPTION-2
ORG ,
DALTUPL CALL ,(CLSFREE,DDNAME, SVC99 TEXT UNIT POINTER LIST +
SYSOUT), +
VL,MF=L
SPACE ,
CLSFREE DC AL2(DALCLOSE) AUTO UNALLOCATION AT CLOSE
DC AL2(0) NUM
DDNAME DC AL2(DALRTDDN) RETURN/ALLOCATED DDNAME
DC AL2(1) NUM
DC AL2(8) LNG
DC CL8' ' PARM
SYSOUT DC AL2(DALSYSOU) SYSOUT DATASET
DC AL2(1) NUM
DC AL2(1) LNG
DC CL1'K' PARM:SYSOUT=K
:
:
:
IEFZB4D0 DYNALLOC PLIST
IEFZB4D2 DYNALLOC KEY LIST
SYSOUTデータセットをDYNALLOCで割り振るサンプルです。SYSOUTの場合、パラメーターでSYSOUTクラスを指定します。その他のライタープログラム名、フォーム名、出力ライン数リミットなどは、追加のテキストユニットを定義することで指定できます。
SYSOUT=*と同じことを行うには、DALSYSOUキーでパラメーター数を0にします。クラス値として’*'を指定してはなりません。パラメーターエラーでDYNALLOCは失敗します。勘違いしやすいので注意します。
以上DYNALLOCの機能を、3つのサンプルを使って紹介しました。DYNALLOCは、一般のデータセットやSYSOUTデータセットのアロケーションでも利用しますが、その他にもJCLのDD文ではアロケーションできない特殊なデータセットにアクセスする場合などにも用います。例えばJES2スプール内の書き込み済みSYSOUTデータセットがそうです。SDSFのように、他のジョブによってすでに書き込まれたSYSOUTデータセットを読み込んで、その内容を表示するような場合です。

