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データセットを読み込んで、その内容を表示するような場合です。