MVSではプログラムがアクセスするデータセットは、ジョブを実行するJCLのDDステートメントで予め定義しておくのが一般的です。バッチ処理においては、殆どのジョブがDDステートメントによる事前の定義を行っています。
しかしながら、オンライン処理、特にTSOなどの対話型処理では、事前に使用するデータセットを決めることができません。例えば、エディターがそうです。編集するデータセットは、エディターを起動した後にパネルにそのDSNを指定します。つまり、エディターというプログラムでは、起動してみなければどのデータセットをアクセスするか決められません。バッチ処理であっても、プログラムの処理中にアクセスするデータセットを決めるということはありえないことではありません。
このような場合、データセットの割り振りはJCLのDDステートメントではなく、プログラムからMVSのAPIを呼び出してデータセットを割り振ります。これがダイナミック・アロケーション(動的割り振り)と呼ばれるものです。ダイナミック・アロケーションは、DYNALLOCマクロによってSVC99を発行することで行われます。
カタログ済みの既存データセットをアロケーションする
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
----+----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は、MVSのAPIの中では呼び出し手順が複雑なものです。覚えるまでは難しく見えますが、慣れの問題です。
必要なパラメーターは、大きく4種類に分かれます。1つ目がRBポインター・フィールドです。サンプルでは、ラベルDALRBPの箇所です。フルワード領域に、DYNALLOCのRBアドレスを格納して先頭ビットをONにします。
2つ目がRBです。DYNALLOCのパラメーター・リストで、要求する機能、復帰時のエラーコード、テキスト・ユニット・ポインター・リストのアドレス、オプション・フラグなどで構成されています。
3つ目がテキスト・ユニット・ポインター・リストです。各テキスト・ユニットのアドレスを格納したポインター・リストです。リストの最終エントリーの先頭ビットをONにします。
4つ目がテキスト・ユニットです。テキスト・ユニットは、JCL DDステートメントの各パラメーターに相当します。DDステートメントの各パラメーターに対応してテキスト・ユニットを用意します。
パラメーター領域を準備して初期設定したら、GR1にRBポインター・フィールドのアドレスを入れてDYNALLOCマクロを発行します。DYNALLOCマクロ自身にはパラメーターは無く、単にSVC 99命令を発行するだけのものです。直接SVC命令を書いても大差ありませんが、マクロを使用して呼び出せばそこでDYNALLOCしていることがはっきりしますから、後で保守する人にはわかりやすいでしょう。DYNALLOCが完了すると、GR15に復帰コードが返ります。0以外なら何らかの誤りが起きていますから、RBに設定されているエラー・コードと情報コードを参照して必要なエラー処理を行います。0で完了しても状況によっては情報コードでエラーが通知される場合もあります(特にアン・アロケーション時)。例えば、DISP=(NEW,KEEP)の指定をしてアロケーションしたデータセットに対して、後処理をCATLGに変更してアン・アロケーションした時、既に同名データセットがカタログされていたような場合です。このアン・アロケーション自体は成功していますが、データセットのカタログには失敗しています(NOT CATLGD 2と同じ)。同名DSNがカタログ済みの場合、アロケーション時にDISP=(NEW,CATLG)が指定されていると、アロケーション時に失敗しエラーで通知されます。この場合、データセットも作成されていません。
アン・アロケーションは必ずしも必要ではありません。アロケーションした後、OPENして入出力を行いその後にCLOSEを行う場合、CLOSE時にデータセットを自動的にアン・アロケーションさせるオプションも指定できます(アロケーション時にキーx001Cのテキスト・ユニットを指定する)。CLOSE後に再OPENしないのであれば、この機能を使うと便利です。
新しいデータセットを作成する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
----+----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サービスの中で自動的に行ってくれます。
SYSOUTデータセットをアロケーションする
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
----+----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は、一般のデータセットやSYSOUTデータセットのアロケーションでも利用しますが、その他にもJCLのDDステートメントではアロケーションできない特殊なデータセットにアクセスする場合などにも用います。例えば、JES2スプール内の書き込み済みSYSOUTデータセットがそうです。SDSFのように、他のジョブによってすでに書き込まれたSYSOUTデータセットを読み込んでその内容を表示するような場合です。