CICS® 環境では、 PSB スケジューリングの処理は、非 CICS 環境とは異なります。 以下のセクションでは、PSB スケジューリング、実行時に代替 PSB を使用する方法、および 呼び出し先プログラムで PSB を共用する方法について説明します。
プログラム制御権の移動を行うために CALL または DXFR 文を使用するとき、 プログラム制御権の移動先プログラムは、移動元プログラムが使用するものと同じ PSB を使用する必要はありません。
EGL は、PSB で定義されたセグメントに対し DL/I 呼び出しを作成するため、 また DL/I 呼び出しに行ったすべての変更を検証するために、プログラム仕様に名前が指定された PSB を使用します。 CICS 環境では、 Enterprise Developer Server for z/OS は、プログラムが実行された時点での PSB スケジューリングにも PSB 名を使用します。
しかし、ユーザーが同一のプログラムで代替 PSB の使用を望む場合があります。 代替 PSB は、プログラム PSB と全く同じ構造を持つデータベースを記述しますが、データベースそのものは異なる可能性があります。 例えば、ユーザーは、プログラム開発用のテスト・データベースのセットと、実動用の実データを含む、 対応する実動データベース・セットを持つことがあります。
何らかの理由で代替の PSB を使用したい場合、ご使用のプログラムで、最初の DL/I 関数を実行する前に、代替 PSB 名を DLIVar.dliPsbName へ移動することによって、スケジュールされている PSB を動的に変更することができます。 代替 PSB はプログラム PSB に一致しなければなりません (ただし、データベース名は異なってもかまいません)。
呼び出し先プログラムと呼び出し側プログラムは、両方が同じプログラム PSB を共用するか、 各呼び出しの前にコミットが PSB を終了させ、異なる PSB を使用するプログラムに戻らない限り、 どちらも DL/I プログラムにはなりません。 呼び出し先プログラムと呼び出し側プログラムの両方に対して、 呼び出し時に DLILib.psbData 構造または PCB レコードを受け渡すことにより、PSB は共用されます。
呼び出し先プログラムおよび呼び出し側プログラムが両方とも EGL プログラムである場合、および PSB が呼び出しの前にスケジュールされた場合、EGL は呼び出し先プログラムの PSB をスケジュール変更しません。
EGL プログラムと非 EGL プログラム間で PSB を共用することができます。DLILib.psbData 構造がパラメーターとして受け渡されるとき、実際には 12 バイトの領域が受け渡されます。 最初の 8 バイトは PSB 名を含み、最後の 4 バイトは、CICS ユーザー・インターフェース・ブロック (UIB) のアドレスを含みます。 PSB がスケジュールに入れられない場合、UIB アドレスは 0 です。 EGL プログラムと非 EGL プログラム間の PSB を共用する場合、 呼び出し先プログラムは、スケジュールに入れる前に UIB アドレスを確認しなければなりません。 UIB アドレスが 0 でない場合は、PSB はスケジュール変更をしてはなりません。 呼び出し先プログラムは、PSB を終了する場合、UIB アドレス・フィールドを 0 に設定しなければなりません。 PSB が再びスケジュールに入れられる場合、UIB アドレス・フィールドを、 CICS により戻された UIB アドレスに設定しなければなりません。
プログラムが、呼び出し先 EGL プログラムとスケジュールに入れられた PSB を共用する必要がある場合、 12 バイトの領域をプログラムに受け渡さなければなりません。 一方、最初の 8 バイトには PSB 名を含み、次の 4 バイトには UIB アドレスを含む必要があります。 PSB がスケジュールされない場合、UIB アドレスは 0 でなければなりません。 戻り時、UIB アドレスは PSB の現在のスケジューリング状況を反映します。
更新されたレコードは、PSB が終了するまで、実際にはデータベースに書き込まれていません。 EGL get...forUpdate I/O 文によって、 レコードがデータベースに実際に書き込まれるまで、他のプログラムが 再びレコードを変更しないようにロックアウトするので、プログラムは PSB 終了までレコードの排他使用権を得ます。 これにより、プログラムがなんらかのレコードをロックしたが、今度は、 ロックされたレコードを必要とする他のプログラムによりロックされたレコードを変更したいという、 デッドロック状態が発生する可能性があります。 CICS は、デッドロック状態を検出すると、 プログラムの 1 つを異常終了させ、データベースに行った変更を取り消し、 プログラムが終了した理由について説明するエラー・メッセージを端末に書き込みます。
プログラムのユーザーにとって、プログラムが異常終了することが容認できない場合、 CICS テーブルで、 プログラムを再起動可能と定義できます。プログラムの再始動に関する情報に関ついては、 このトピックの後半にある『DL/I デッドロック後の EGL 生成プログラムの再始動』を参照してください。
プログラムが再始動可能であり、かつ CICS がデッドロック状態を検出した場合、 CICS は PSB が スケジュールされた後にプログラムが行った変更を取り消し、 トランザクションの最初からプログラムを再始動します。
プログラムがセグメントされた (疑似会話型) モードで実行されている場合、プログラムの最新のセグメントが再始動されるため、 ユーザーが、プログラム内に特別な再始動コードを定義する必要はありません。
会話型プログラムが再始動されると、プログラムは先頭で再び開始されます。 DLIVar.cicsRestart フィールドの値が 1 であるかどうかをプログラムにテストさせることによって、 プログラムが再始動されたかどうか判別することができます。 DLIVar.cicsRestart が 1 である場合、 デッドロックによりプログラムが再始動されたというメッセージをプログラム・ユーザーに向けて書き出してから、 再び初期プログラム・マップを表示することができます。
DL/I プログラム分離機能が使用されている場合、同一レコードでロックしている 2 つのトランザクション間にデッドロックが起こる可能性があります。 それらのプログラムは同時に、同一レコードの更新を試みます。 両方の更新が受け入れられるならば、変更点の 1 つは失われます。 CICS は、データの逸失を検出した場合、ADLD 異常終了コードを出してトランザクションを異常終了します。
その他の場合、CICS は、プログラムの終了の理由を示すメッセージを書き込みます。 再始動されたプログラムは、実行されていた最後のトランザクションの先頭から再び始動されたプログラムです。 プログラム PSB が最後にスケジュールされて以降、データベースへ行われたすべての変更はロールバックされます。
セグメント化モードで実行中のプログラムは、再始動が要求された場合、すべての CICS リソース (更新される予定のリソース) をリカバリー可能と定義していなければなりません。 Enterprise Developer Server for z/OS のセグメンテーション関数で作成される一時ストレージ・キューの名前は、 4 文字の接頭部にユーザーの端末 ID を追加して組み合わせたものです。 使用される接頭部は、X‘EE‘ に続いて WRK または MSG が来る形式をとります。
再始動を処理するようにプログラムを設計しておかないと、 会話型プログラムに対して再始動を要求できません。 現行のプログラム・トランザクションが再始動されたかどうかをプログラムが知るには、 DLIVar.cicsRestart フィールドをテストすることができます。 再始動のためにプログラムを設計する簡単な方法の 1 つは、 プログラムの開始時に常に、cicsRestart をプログラムにテストさせることです。 再始動フラグが on の場合、ユーザー 2 が同時にデータベースを変更しているので、 トランザクションが先頭で再始動されたことを説明する特別なメッセージまたはマップがユーザー 1 に、表示されるはずです。 ユーザー 1 の変更点はバックアウトされ、変更点が失われるのを防ぐためにプログラムが再始動されました。