CICS 環境での PSB スケジューリング

CICS® 環境では、PSB スケジューリングは非 CICS 環境とは異なる方法で処理されます。

以下のセクションでは、PSB スケジューリング、ランタイムに代替 PSB を使用する方法、および PSB を呼び出し先プログラムと共用する方法について説明します。

PSB スケジューリング

CICS DL/I プログラムが PSB に定義されているデータベースにアクセスするには、プログラムで PSB をスケジュールに入れる必要があります。 プログラムは、データベース・アクセスの完了時に PSB を終了する必要があります。 Rational® COBOL Runtime では、プログラムの PSB スケジューリングを自動的に処理します。 しかし、以下の機能が PSB スケジューリングの影響を受けるため、PSB がいつスケジュールされているかを知っておく必要があります。
セグメント・レコードのロック
セグメントの更新ロックは、PSB が終了すると解除されます。
データベース位置
データベース位置は、PSB が終了すると失われます。
更新のコミットメント
変更は、PSB の終了時にコミットされます (データベースに書き込まれます)。

PSB は、DL/I 呼び出しがプログラムに対して発行されると、いつでもスケジュールに入れられます。PSB は現時点ではスケジュールに入っていません。 dliLib.psbData.psbName で指名されている PSB が、スケジュールに入る PSB です。

call または transfer to program ステートメントを使用してプログラムの制御権を移動する場合、ターゲット・プログラムは移動元のプログラムと同じ PSB を使用する必要はありません。

PSB は、いつでも CICS SYNCPOINT または SYNCPOINT ROLLBACK が発行されると終了します。SYNCPOINT は、以下のいずれか 1 つが起きたときに発生します。
  • 実行単位内のトップレベルのプログラムが正常に終了し、制御権が CICS に戻される。 CICS の場合、実行単位は、単一のトランザクションと同等であり、transfer to program ステートメントまたは call ステートメントを使用して制御を転送し合うすべての EGL および非 EGL プログラムで構成されます。 非 EGL プログラムの場合、これには CALL ステートメント、CICS LINK コマンド、または CICS XCTL コマンドを使用するすべての移動が含まれます。
  • プログラムが converse ステートメントを使用し、以下のいずれかが 1 に設定される。
    • converseVar.segmentedMode (プログラム・プロパティーが YES に設定されている場合のデフォルトは 1)
    • converseVar.commitOnConverse
  • transfer to transaction ステートメントを使用した移動が発生する。
  • プログラムが sysLib.commit 関数を呼び出す。
  • 現在、PSB がスケジュールされており、EGL プログラムが transfer to program ステートメントを使用して制御権を移動する場合で、以下のいずれか 1 つが発生する。
    • 制御権移動が非 EGL (および非 VisualAge Generator) プログラムに対するものである。
    • synchOnPgmTransfer ビルド記述子オプションが制御権移動元プログラムで YES に設定されている。
    • synchOnPgmTransfer ビルド記述子オプションが制御権の移動元プログラムで NO に設定されていて、移動元プログラムの PSB レコードで参照されているデフォルトの PSB が、ターゲット・プログラムの PSB レコードで参照されているデフォルトの PSB と異なっている。 制御権移動元プログラムが CICS および IMS/VS の両方に対して生成された場合の動作の違いを最小化するには、synchOnPgmTransfer ビルド記述子オプションを NO に設定します。
  • EGL によって呼び出された DL/I プログラムが呼び出し元の非 EGL プログラムに戻る場合で、PSB は dliLib.psbData 構造に渡されず、PCB も PCB レコードを使用して渡されない。
SYNCPOINT ROLLBACK は、以下の場合に発生します。
  • EGL プログラムが sysLib.rollback 関数を呼び出す。
  • エラー状態のため、プログラムが終了した。
ロールバックが発生すると、作業論理単位 (LUW) の開始以降にデータベースおよびリカバリー可能ファイルに行われた変更のすべてがバックアウトされます。

実行時における代替 PSB

DL/I プログラムを作成する場合には、psb プロパティーを使用して PSBRecord パーツに基づいたプログラム変数の名前を指定します。 EGL はこの変数と関連付けられている PSBRecord を使用して、PSB で定義されているセグメントの DL/I 呼び出しを作成し、その DL/I 呼び出しに対して加えた変更の妥当性検査を行います。CICS 環境では、Rational COBOL Runtime は、プログラムの実行時に PSB スケジューリングに PSB 名も使用します。

しかし、同じプログラムで代替 PSB を使用する場合があります。代替 PSB はプログラムの PSB と同じ構造のデータベースを記述しますが、そのデータベースそのものとは異なる可能性があります。 例えば、プログラム開発のためのテスト・データベースのセット、および、実動のための本物のデータが入った、対応する実働データベースのセットが存在する可能性があります。

代替 PSB を使用する場合、プログラムは最初の DL/I 関数を実行する前にその代替 PSB の名前を dliVar.dliPsbName に移動することで、スケジュールに入っている PSB を動的に変更することができます。 代替 PSB はプログラム PSB と一致している必要がありますが、データベース名は除きます。

呼び出し先プログラムとのスケジュール済み PSB の共用

呼び出し先プログラムと呼び出し側プログラムが同じプログラム PSB を共用している場合や、各呼び出しの前に PSB を終了するコミットが行われた場合を除き、両方のプログラムを DL/I プログラムにすることはできません。そうした場合には、別の PSB を使用するプログラムに戻ります。 プログラムが callInterface プロパティーを CBLTDLI に設定した場合には、dliLib.psbData 構造または呼び出し先プログラムと呼び出し側プログラムの両方の呼び出し上の PCB レコードを渡すことで、別のプログラムと PSB を共用できます。 プログラムが callInterface プロパティーを AIBTDLI (デフォルト) に設定した場合は、呼び出し側プログラムまたは呼び出し先プログラムが非 EGL プログラムであれば、dliLib.psbData 構造または PCB レコードを渡します。

呼び出し先プログラムと呼び出し側プログラムがどちらの EGL プログラムで、その呼び出しの前に PSB がスケジュールされている場合、EGL は呼び出し先プログラム内の PSB のスケジュールを変更しません。

EGL プログラムと非 EGL プログラムの間で PSB を共用することは可能です。dliLib.psbData 構造をパラメーターとして渡す場合、12 バイトの領域が渡されます。 最初の 8 バイトには PSB 名が入り、残りの 4 バイトには CICS User Interface Block (UIB) のアドレスが入ります。 PSB がスケジュールされていない場合、UIB アドレスは 0 です。

EGL プログラムと非 EGL プログラムの間で PSB を共用する場合、呼び出し先プログラムはスケジューリングを行う前に、その UIB アドレスを検査する必要があります。 UIB が 0 以外の場合は、PSB のスケジュールを変更できません。 呼び出し先プログラムが PSB を終了する場合、そのプログラムは UIB アドレスを 0 に設定する必要があります。 PSB が再度スケジュールされる場合、UIB アドレス・フィールドは、CICS から戻された UIB アドレスに設定する必要があります。

プログラムが、スケジュールされている PSB を呼び出し先 EGL プログラムと共用する必要がある場合、そのプログラムは呼び出し先プログラムに、12 バイトの領域を渡す必要があります。最初の 8 バイトには PSB 名が入り、次の 4 バイトには UIB アドレスが入ります。 PSB がスケジュールされていない場合、UIB アドレスは 0 です。 それ以外の場合、UIB アドレスには、PSB の現在のスケジューリング状況が反映されます。

レコード・キューイング中のデッドロックからのリカバリー

更新済みのレコードは、PSB が終了するまでデータベースには書き込まれません。他のプログラムがそのレコードを変更できないように、それらのレコードがデータベースに書き込まれるまで、EGL get...forUpdate I/O ステートメントによって他のプログラムはロックアウトされるため、PSB が終了するまでは、ご使用のプログラムがこれらのレコードの排他使用権を獲得します。この結果、以下のデッドロック状態になる可能性があります。
  • プログラム (Program1) が RecordA をロックします。
  • 別のプログラム (Program2) が RecordB をロックします。
  • Program1 が RecordB を変更しようとします。
  • 同時に、Program2 が RecordA を変更しようとします。

CICS がデッドロック状態を検出する場合、それはプログラムの 1 つを自動的に異常終了させ、データベースに行った変更をバックアウトし、プログラムが終了した理由を説明するエラー・メッセージを端末に書き込みます。

プログラムのユーザーがそのプログラムの異常終了を容認できない場合は、CICS テーブルでそのプログラムを restartable として定義することができます。 プログラムの再始動については、このトピックの『DL/I デッドロック後の EGL 生成プログラムの再始動』を参照してください。

プログラムが再始動可能に設定されている場合に CICS がデッドロック状態を検出すると、CICS は PSB のスケジューリング以降にそのプログラムが行った変更を取り消し、そのトランザクションの最初からプログラムを再始動します。

プログラムがセグメント化モード (CICS 疑似会話型) で実行されている場合には、そのプログラムの最新のセグメントが再始動されるため、プログラムの中に特別な再始動コードを組み込む必要はありません。

非セグメント化プログラム (CICS 会話型) が再始動される場合は、そのプログラムの最初からやり直しになります。 プログラムが再始動されたかどうかを判別するには、dliVar.cicsRestart フィールドに値 1 を入力して、プログラム・テストを行います。 dliVar.cicsRestart が 1 の場合、デッドロックが原因でプログラムが再始動したことをプログラムのユーザーに説明するメッセージを作成することができます。 そのメッセージの後には、初期プログラム・マップが再表示されます。

DL/I デッドロック後の EGL 生成プログラムの再始動

DL/I プログラム分離機能を使用している場合、デッドロックは同じレコード上の 2 つのトランザクション・ロックの間で発生する可能性があります。 複数のプログラムが同時に同じレコードの更新を試行したとします。 どちらの更新も受け入れられた場合、片方の変更は失われます。 データが失われたことを CICS が検出すると、そのトランザクションは ADLD 異常終了コードで異常終了します。

Rational COBOL Runtime の異常終了ハンドラーによって、デッドロック異常終了によって終了したプログラムの再始動が要求されます。CICS は、以下の場合にそのトランザクションを最初から再始動します。
  • トランザクション・プログラムの PCT で DTB=YES と RESTART=YES を指定した。
  • CICS トランザクション再始動プログラム (DFHRTY) が、トランザクションの再始動を指定した。
  • 一時ストレージ・キューがリカバリー可能として定義されている。

その他の場合、CICS はプログラム終了処理の理由を示すメッセージを書き込みます。 再始動されるプログラムは、実行していた最後のトランザクションの最初から再始動されます。 プログラム PSB が最後にスケジュールされてから後にデータベースに加えられた変更はすべて、ロールバックされます。

CICS 再始動プログラム (DFHRTY) の分散バージョンは、EGL 生成プログラムを、実行中の最後のデータベース・トランザクションの最初から再始動しません。 EGL データベース・トランザクションを再始動するには、DFHRTY にコードを追加します。プログラムが以下の条件を満たしていることを 確認する必要があります。
  • 現在の異常終了コードが ADLD である。
  • トランザクション ID が、再始動するトランザクションの ID である。
  • 再始動のカウントが、指定された数より小さい。 これは再始動ループ検査です。
検査の結果、これらがすべて当てはまる場合、プログラムは再始動フラグをオンに設定し、再始動の続行を CICS に指示する必要があります。 DFHRTY の変更について詳しくは、ご使用の CICS システムのリカバリー、再始動、およびカスタマイズに関する資料を参照してください。

再始動が要求される場合、セグメント化モード (CICS 疑似会話型) で実行されているプログラムでは、更新済みのすべての CICS リソースがリカバリー可能として定義されている必要があります。Rational COBOL Runtime のセグメンテーション機能によって作成される一時ストレージ・キューの名前は、4 文字の接頭部と、これに追加したユーザーの端末 ID で構成されます。使用される接頭部の書式は X'EE' で、その後に WRK または MSG が続きます。

非セグメント化プログラム (CICS 会話型) の再始動は、 再始動を処理するようにそのプログラムを設計していない限り、再始動しないでください。 単純な方法としては、始動時に毎回 dliVar. cicsRestart のプログラム・テストを行うようにします。 再始動フラグがオンになっている場合は、次の情報を含む特別メッセージまたはフォームがユーザー 1 に対して出されます。
  • ユーザー 2 が同時にデータベースに対して変更を行っていたため、トランザクションが最初から再始動された。
  • ユーザー 1 が行った変更はバックアウトされた。
  • 変更が失われるのを防ぐためにプログラムは再始動された。

分散 DL/I データベースへのアクセス

CICS で実行されているプログラムは、DL/I データベースが配置されているシステム上で実行される基本プログラムを呼び出すことで、リモート・システム上にあるその DL/I データベースにアクセスすることができます。


フィードバック