プログラミングの考察


コマンド ID の使用

コントロールブロックのコマンド ID フィールドは、Adabas コマンド実行中に重要な機能を果たします。ここでは、このフィールドの使用についてまとめ、コマンド ID の使用時に行うべき手順について説明します。

コマンド ID は、次の情報に関連付けられています。

  • 読み込みシーケンシャルコマンド(L2/L5、L3/L6、L9)を実行する場合、Adabas は次のコマンドで処理するレコードを識別するための情報を必要とします。この目的で、Adabas にはすべてのアクティブなシーケンシャルコマンドシーケンスのテーブルがあり、コマンド ID によってこのテーブル内のエントリが識別されます。

  • 検索コマンドを実行する場合、Adabas は、検索コマンドで返された ISN リストに関する情報を必要とします。この目的で、Adabas にはすべてのアクティブな ISN リストのテーブルがあり、コマンド ID によってこのテーブル内のエントリが識別されます。

  • フォーマットバッファが読み込みコマンド、S1/S2/S4 検索コマンド、または更新コマンドに関連付けられている場合、Adabas はフォーマットバッファを、レコードの圧縮または圧縮解除に使用される内部フォーマットバッファに変換します。Adabas は、同じフォーマットバッファでの以後のコマンドで再使用できるように、これらの内部フォーマットバッファをメモリに保持します。これにより、フォーマットバッファを新たに変換しないで済むようになります。コマンド ID をフォーマットバッファ ID として使用して、すでに存在する内部フォーマットバッファを識別できます。

読み込みシーケンシャルコマンドで使用するコマンド ID

読み込みシーケンシャルコマンド(L2/L3、L5/L6、L9)では、空白/ゼロ以外のコマンド ID を指定する必要があります。コマンド ID は、Adabas が正しい順序でレコードをユーザーに返すために必要となります。これらのコマンド ID は、Adabas によりシーケンシャルコマンドテーブルに保持されます。

順次読み込み処理中にエンドオブファイル条件(Adabas レスポンスコード 3)が検出されると、Adabas により(シーケンシャルコマンドテーブルからのみ)コマンド ID が解放されます。

これらのコマンドで使用するコマンド ID も、内部フォーマットバッファプールに入力され、保持されます。これは明示的な RC コマンドでのみ解放されます。

ISN リストで使用するコマンド ID

ISN リストを返すすべてのコマンド(S1、S2、S4、S8、S9)で空白/ゼロ以外のコマンド ID を指定すると、後でリストを識別するためにこのコマンド ID 値を使用できます。

Sx コマンドで SAVE ISN LIST オプションを使用する場合は、空白/ゼロ以外のコマンド ID を与えなければなりません。SAVE ISN LIST オプションにより、全 ISN リストが Adabas 一時ワークスペースに格納されます。リスト内の ISN は後で、Sx コマンド、または L1/L4 コマンドの GET NEXT オプションを使用して読み取ることができます。

SAVE ISN LIST オプションを使わず、ISN バッファオーバーフローが起こる(ISN リスト全体が ISN バッファに入り切らない)と、空白/ゼロ以外のコマンド ID を使用したときに限り、オーバーフローした ISN は Adabas 一時ワークスペースに格納されます。この場合、コマンド ID は Adabas によって(ISN リストテーブルからのみ)解放されます。コマンド ID で識別される ISN リストは、後続の Sx コマンドですべての ISN がユーザーに返されたとき、またはエンドオブファイル条件(Adabas レスポンスコード 3)が検出されたときの GET NEXT オプション付きの L1 コマンドで解放されます。

コマンド ID の自動生成

16 進数 FFFFFFFF のコマンド ID を指定すると、自動コマンド ID 生成が呼び出されます。これにより、Adabas ニュークリアスはコマンド ID を自動的に生成できます。このとき新規コマンド ID は、16 進数の 00000001 から始まって 1 つずつ追加されます。

コマンド ID の解放

ユーザーは、コマンド ID とその関連エントリ(または ISN リスト)を RC または CL コマンドで解放することができます。RC コマンドには、内部フォーマットバッファプールか、シーケンシャルコマンドのテーブルか、または ISN リストテーブルにあるコマンド ID だけを解放するオプションがあります。

CL コマンドは、そのユーザーに対して現在アクティブである全コマンド ID を解放します。

グローバルトランザクションの終了時には、コマンド ID は解放されません。

コマンド ID の内部識別

Adabas は、各コマンド ID エントリをコマンド ID 値と内部ユーザー番号で識別しています。

ユーザーは、他のユーザーが使用中のコマンド ID 値を意識する必要はありません。ただし、別々のコマンドで同一コマンド ID 値(特に読み込みシーケンシャルコマンドの L2/L5、L3/L6、L9 コマンドと Sx コマンドで使用するコマンド ID)を使用しているときには十分注意しなければなりません。このマニュアルで使用する Sx 表記のコマンドはすべての検索コマンド(S1、S2、S4、S8、S9)を示します。

空白のコマンド ID

シーケンシャルコマンドテーブル、ISN リストテーブル、または内部フォーマットバッファプールにコマンド ID を格納せずに、Adabas コマンドを実行することが必要になる場合があります。コマンド ID フィールドに、次のいずれかの値を格納することで、これが可能になります。

  • バイナリのゼロ。

  • ASCII の空白(0x20202020)。これは、コマンド ID フィールドがバイナリとして定義されているにもかかわらず、文字値がコマンド ID として使用されることが多いためです。

  • EBCDIC の空白(0x40404040)。これは、プラットフォーム間のコールを実行するメインフレームユーザーが、空白のコマンド ID として空白も指定できるようにするためです。

コマンド ID フィールドにこれらの値のいずれかを指定すると、次のようになります。

  • コマンド ID は、シーケンシャルコマンドのテーブル、ISN リストテーブルおよび内部フォーマットバッファプールに格納されません。

  • コマンド ID を解放するための RC コマンドは必要ありません。

  • フォーマットバッファは、コールごとに再変換されます(次のセクションで説明しているように、アディション 5 にフォーマットバッファ ID を指定した場合を除く)。

  • このコマンドに対して、後続のコマンドは実行できません。

コマンド ID の使用例

ここでは、コマンド ID の使用例を示します。

例 1:検索/読み込み処理

レコードセットを選択して、読み込みます。各レコードに対して同一フォーマットバッファを使用します。

Find (S1)   CID=EX1B
Read (L1)   CID=EX1B
Read (L1)   CID=EX1B
    

例 2:GET NEXT オプションを使用した検索/読み込み処理

L1/L4 コマンドの GET NEXT オプションを使用してレコードセットを選択し、読み込みます。

Find (S1)    CID=EX2A
Read (L1)    CID=EX2A
Read (L1)    CID=EX2A
Read (L1)    CID=EX2A
...

例 3:読み込み/更新処理

ファイルを論理順に読み込んで、更新します。読み込みと更新で同じフォーマットバッファを使用します。

Read Log Seq (L6)  CID=EX3A
Update (A1)         CID=EX3A
Read Log Seq (L6)  CID=EX3A
Update (A1)         CID=EX3A
...

例 4:読み込み/検索処理

ファイルを論理順に読み込みます。第 1 ファイルから読んだフィールドの値を使って、第 2 ファイルを検索するために FIND コマンドを出し、FIND コマンドで検索されたレコードをその後、GET NEXT オプションを使って読みます。

Read Log Seq (L3)  CID=EX4A
Find (S1)          CID=EX4B
Read (L1)          CID=EX4B
Read (L1)          CID=EX4B (RSP 3)
Read Log Seq (L3)  CID=EX4A
Find (S1)          CID=EX4B
Read (L1)          CID=EX4B

フォーマットバッファ ID の使用

内部フォーマットバッファへのフォーマットバッファ変換には時間がかかります。そのため、Adabas は他の Adabas コマンドで再使用できるように、内部フォーマットバッファをメモリに保存でき、再使用する内部フォーマットバッファを識別するためのフォーマットバッファ ID が導入されました。

通常、コマンド ID がフォーマットバッファ ID として使用されますが、アディション 5 を使用してフォーマットバッファ ID を個別に指定することもできます。

  • 同じフォーマットバッファを使用するアクティブな読み込みシーケンシャルコマンドまたは検索コマンドが複数ある場合は、個別のローカルフォーマットバッファ ID が有用です。この場合、「ローカル」は、ユーザー固有であることを意味します。

  • 複数のユーザーが、Adabas コールを実行する同じアプリケーションプログラムを並行して実行する場合は、個別のグローバルフォーマットバッファ ID が有用です。この場合、「グローバル」は、すべての Adabas ユーザーに有効であることを意味します。

コマンド ID と個別のローカルフォーマットバッファ ID の使用

コマンド ID とフォーマットバッファ ID には別々の値を使用できます。アディション 5 フィールドの先頭バイトが英数字でなければ、コマンド ID をフォーマットバッファ ID としても使用できます。ただし、アディション 5 フィールドの 1 バイト目が英数字である場合は、アディション 5 フィールドの 5 から 8 バイトが(ローカル)フォーマットバッファ ID として使用されます(例 2 参照)。Tフォーマットバッファ ID を 16 進の FF で始めることはできません。

グローバルフォーマットバッファ ID の使用

同一プログラムを使用する多数のユーザーが、1 つのファイル中の同一フィールドを読み込みまたは更新することはよくあり、同一フォーマットバッファが使われます。このようなプログラムのグローバルフォーマットバッファ ID を定義すれば、Adabas でプログラムごとに内部フォーマットバッファに同一フォーマットバッファを格納する必要がなくなります。このオプションにより、各ユーザーの指定するフォーマットバッファは、フォーマットバッファ ID と内部コミュニケーション ID ではなく、フォーマットバッファ ID のみによって識別されます。この結果、多くのユーザーが 1 つの内部フォーマットバッファを「共有」することができ、Adabas がフォーマットバッファプールにあるエントリを書き換える必要がなくなります。

注意:
フォーマットバッファに W フィールドが含まれていて、かつフォーマットバッファで文字セットが明示的に指定されていない場合、Adabas はパラメータ WCHARSET(デフォルト:'UTF-8')を介して Adabas OP コマンドで指定された文字セットを暗黙的に使用します文字セットに関する情報は、内部フォーマットバッファに含まれています。そのため、このグローバルフォーマットバッファ ID が使用されるすべての Adabas セッションの OP コマンドに同じ WCHARSET が指定されている場合には、そのようなフォーマットバッファにのみグローバルフォーマットバッファ ID を使用できます。それ以外の場合は、W フィールドが正しくない文字セットで処理される可能性があります。

グローバルフォーマットバッファ ID オプションは、アディション 5 フィールドの 1 バイト目に数字または大文字に指定することで有効になります(例 3 参照)。

アディション 5 内の EBCDIC 文字

また、Adabas はメインフレームで発行されたコマンドを処理できる必要があります。この場合、アディション 5 に EBCDIC 文字が含まれている可能性があります。バイナリデータも含まれている可能性があるので、アディション 5 の EBCDIC-ASCII 変換は実行されません。そのため、アディション 5 の最初のバイトの EBCDIC 小文字(16 進数 8x、9x)は個別のローカルフォーマットバッファ ID を示し、EBCDIC 大文字(16 進数 Cx、Dx)および EBCDIC 数字(16 進数 Fx)は個別のグローバルフォーマットバッファ ID を示し、EBCDIC 空白(16 進数 40)は個別のフォーマットバッファ ID がないことを示します。

アディション 5 の最初のバイトに他のものを指定した場合の Adabas の動作は未定義になります。

コマンド ID とフォーマットバッファ ID の使用例

例 1:コマンド ID とフォーマットバッファ ID に同一の値を使用

Additions 5: The first byte of the Additions 5 field is blank or binary zero

結果:コマンド ID はフォーマットバッファ ID として使用されます。

例 2:個別のローカルフォーマットバッファ ID の使用

Additions 5: The first byte of the Additions 5 field is set to 'a'

結果:アディション 5 フィールドの 5 から 8 バイトが、フォーマットバッファ ID(X'FE' または X'FF' ではじまる ID であってはならない)として使用されます。

例 3:グローバルフォーマットバッファ ID の使用

Additions 5: The first byte of the Additions 5 field is set to 'A'

結果:アディション 5 フィールド(8 バイト)がグローバルフォーマットバッファ ID(複数ユーザーが同時に使用できる)として使用されます。

例 4:メインフレームでのグローバルフォーマットバッファ ID の使用

Additions 5: The first byte of the Additions 5 field is set to hex D1

結果:Hex D1 = EBCDIC ‘J’ -> アディション 5 フィールド(8 バイト)がグローバルフォーマットバッファ ID(複数ユーザーが同時に使用できる)として使用されます。

読み込み、検索および更新コマンドで使用するフォーマットバッファ ID

読み込みコマンド(L1~L6、L9)および更新コマンド(A1、N1/N2)では、読み込むまたは更新するフィールドを指定するフォーマットバッファが必要です。S1/S2/S4 検索コマンドにフォーマットバッファを指定して、最初の結果レコードを読み込むこともできます。このフォーマットバッファは、Adabas によって解釈され、内部フォーマットバッファに変換されます。同じフォーマットバッファを使用する一連のコマンドで、解釈や変換が繰り返されないように、同じフォーマットバッファ ID を使用できます。読み込みコマンドまたは更新コマンドにフォーマットバッファ ID を指定すると、Adabas によって、これが内部フォーマットバッファプールにあるかどうかがチェックされます。このフォーマットバッファ ID が存在すると、そのフォーマットバッファ ID に対応する内部フォーマットバッファが使用されるので、フォーマットバッファを解釈する必要がなくなります。したがって、同じフォーマットバッファで一連のレコードを読み込んだり、更新したりするときにフォーマットバッファ ID を使用すれば、読み込みコマンドや更新コマンドの処理時間をかなり削減することができます。同一フィールドを読んで更新する場合(例えば、L5 の後に A1 がある場合)、両コマンドに対して同じフォーマットバッファ ID を使用することをお勧めします(読み込みや更新用の同一フォーマットバッファ使用上の制限については「A1 コマンド」および「N1/N2 コマンド」を参照)。

内部フォーマットバッファプールがいっぱいになり、プールに存在しないフォーマットバッファ ID のコマンドを受け取ると、Adabas は、使用頻度の一番少ないエントリをこの新しいフォーマットバッファ ID で置き換えます。その後、削除したコマンド ID を使うコマンドを受け取ると、プール内の最少使用頻度のエントリをこのコマンド ID に置き換えます。このときは、フォーマットバッファが新たに翻訳され、内部フォーマットバッファに変換される必要があります。そのため、同じフォーマットバッファ ID を使用する一連の読み込みコマンドまたは更新コマンドの間は、フォーマットバッファを変更しないようにする必要があります。

注意:
常に、フォーマットバッファ ID とフォーマットバッファの正しいペアを指定してください。

  • 例えば、新しいフォーマットバッファを使用するときに、新しいコマンド ID を指定し忘れると、古いコマンド ID に関連付けられたフォーマットバッファに指定されているフィールドが読み込まれる可能性があります。これにより、レコードバッファに誤った結果が生じる可能性があります。

  • 同じフォーマットバッファ ID を持つ後続のコマンドに正しいフォーマットバッファを指定しないと、しばらくの間はプログラムが正しく動作するかもしれませんが、突然、対応する内部フォーマットバッファがフォーマットバッファプールで上書きされることがあります。その後、新しいフォーマットバッファの変換が必要になりますが、コマンドに正しいフォーマットバッファが指定されていない場合は変換が失敗するか、無効になります。

ISN リスト処理

このセクションでは、Adabas 一時ワークスペースから ISN を取得する手順について説明します。L1/L4 コマンドのGET NEXT オプションを使用して、ISN リスト中の ISN と関連するレコードを読む場合は、Adabas が自動的に行うので、この手順を使用する必要はありません。

ISN リストの格納

Adabas は次のいずれかの場合に ISN を Adabas 一時ワークスペースに格納します。

  • Sx コマンドが発行され、空白/ゼロ以外のコマンド ID が指定され、しかも SAVE ISN LISTオプション が指定されています。この場合、ISN 結果リスト全体が格納されます。

  • Sx コマンドが発行され、空白/ゼロ以外のコマンド ID が指定され、SAVE ISN LIST オプションが指定されず、しかも、実行結果の ISN リストは ISN バッファの許容量を超えます。この場合、あふれた ISN のみが格納されます。

コマンド ID フィールドに空白かバイナリのゼロを指定して Sx コマンドを発行した場合、Adabas は ISN を Adabas 一時ワークスペースに格納しません。

ISN リストの読み込み

最初の Sx コマンドで指定したコマンド ID と同じ値のコマンド ID を指定して Sx コマンドを発行することにより、ユーザーが Adabas 一時ワークスペースに格納されている ISN を読み込むことができます。アクティブなコマンド ID 値を指定して Sx コマンドを発行すると、Adabas は既存の ISN リストの ISN をユーザーが要求しているものとみなします。Adabas は指定のコマンド ID で識別される ISN リストを捜し出し、次の ISN グループを ISN バッファに入れます。ISN バッファに入るだけの ISN が返されます。

ISN リスト作成に使用する Sx コマンドで SAVE ISN LIST オプションが指定されていた場合、Adabas は ISN 下限フィールドに指定された ISN を使って返すべき次の ISN グループを判断します。次のグループは、ISN 下限フィールド内に指定された ISN の次に大きい ISN で始まります。ISN 下限フィールドにバイナリのゼロを指定した場合、リスト内の先頭 ISN で始まるものが、次のグループになります。リスト中のいずれの ISN よりも大きい値を指定すると、レスポンスコード 3 が返されます。ISN バッファを使用しない、このような S1 コールは、現在の ISN リスト内の再位置づけに使用できます。

ISN リストを S2/S9 コマンドを使って作成した場合は、指定 ISN が ISN リスト中に存在しなければなりません。存在しない場合はレスポンスコード 25 が返されます。このように SAVE ISN LIST オプションを使うと、ユーザーは ISN リスト内を前や後にスキップすることができます。これは、画面を前や後にスクロールしなければならないプログラムに対して有効です。

ISN リストを作成するときに、Sx コマンドに SAVE ISN LIST オプションを指定しなかった場合、Adabas はリスト作成時の順番で ISN を返し、ユーザーの ISN バッファへの各グループの挿入が完了すると、Adabas は一時ワークスペースからこれらのグループを削除します。リストの識別に使用されたコマンド ID も、ISN の最後のグループがユーザーに返されたときに解放されます。この場合、ISN 下限フィールドは使用されません。

コントロールブロック内の ISN 数フィールドを使って、リスト中の全 ISN を読み終える時点を判断することができます。Adabas はこのフィールドに、最初の Sx コマンドの結果として、検索条件を満足するレコードの総数を返します。また、Adabas 一時ワークスペースから ISN を取得するために使用した後続の Sx コマンドの結果として、Adabas は ISN バッファに挿入した ISN の数を返します。

存在しなくなった ISN の処理

検索処理で見つかっていた ISN が、ISN の処理時に存在しなくなることがあります。その理由は次のとおりです。

  • 検索結果に ISN が含まれた後に ISN が削除された。

  • 検索処理は以前に生成された ISN リストを処理し、その ISN リスト内の ISN は、検索処理が開始される前に削除された。

Adabas は、検索結果に含まれている ISN が現在も存在しているかどうかをチェックしません。例外は、フォーマットバッファも指定されている最初の Sx コマンドです。この場合、Adabas は結果の ISN リストの最初の ISN を読み込みます。それが存在しなくなった場合は、結果の ISN リストから ISN が削除されます。フォーマットバッファを使用する後続の Sx コマンドでは、処理される ISN リスト内の最初の ISN が存在しない場合、レスポンスコード 113 が返されます。これは、最後の ISN が返された後にコマンド ID が削除されることが理由です。ISN リストのすべての ISN を取得しなかった場合、ユーザーは別の後続の Sx コマンドが実行されると想定しますが、実際には新しい最初の Sx コマンドが実行されます。

GET NEXT オプションを指定した L1 コマンドを使用して ISN リストを処理した場合、存在しなくなった ISN はスキップされます。そのため、読み込まれた ISN の数が最初の Sx コマンドで返された ISN 数より少ないにもかかわらず、エンドオブリスト条件(レスポンスコード 3)が返されることがあります。

ISN リスト処理の例

例 1:SAVE ISN LIST オプションを使用した最初の Sx コール

COMMAND = Sx
COMMAND ID = SX01
COMMAND OPTION 1 = H
ISN LOWER LIMIT = 0
ISN BUFFER LENGTH = 20
CALL ADABAS ...

実行結果の ISN 数 = 7

実行結果の ISN リスト:
(ISN はすべて格納されます)8 12 14 15 24 31 33

実行結果の ISN バッファ:8 12 14 15 24

後続の Sx コール

COMMAND = Sx
COMMAND ID = SX01
ISN LOWER LIMIT = 24
ISN BUFFER LENGTH = 20
CALL ADABAS ...

実行結果の ISN 数 = 2

実行結果の ISN バッファ:31 33 14 15 24

後続の Sx コール

COMMAND = Sx
COMMAND ID = SX01
ISN LOWER LIMIT = 0
ISN BUFFER LENGTH = 20
CALL ADABAS ...

実行結果の ISN 数 = 5

実行結果の ISN バッファ:8 12 14 15 24

例 2:ISN オーバーフロー処理あり

最初の Sx コール:SAVE ISN LIST オプションを使用しません。

COMMAND = Sx
COMMAND ID = SX02
COMMAND OPTION 1 = blank
ISN LOWER LIMIT = 0
ISN BUFFER LENGTH = 20
CALL ADABAS ...

実行結果の ISN 数 = 7

実行結果の ISN リスト:(ISN 31 と 33 のみ格納されます)
8 12 14 15 24 31 33

実行結果の ISN バッファ:8 12 14 15 24

後続の Sx コール

COMMAND = Sx
COMMAND ID = SX02
ISN LOWER LIMIT  (not used)
ISN BUFFER LENGTH = 20
CALL ADABAS ...

実行結果の ISN 数 = 2

実行結果の ISN バッファ:(ISN 31 と 33 が Adabas 一時ワークスペースから削除され、コマンド ID SX02 が解放されます)。
31 33 14 15 24

2 番目のコールで最後の ISN が返された後に SX02 が解放されたので、コマンド ID が SX02 である後続の SX コールは、新しい SX コールとして処理されます。

例 3:ISN オーバーフロー処理なし

空白または 0 のコマンド ID 指定で最初の Sx コール

COMMAND = Sx
COMMAND ID = blanks or binary zeros
COMMAND OPTION 1 = blank
ISN LOWER LIMIT = 0
ISN BUFFER LENGTH = 20
CALL ADABAS ...

実行結果の ISN 数 = 7

実行結果の ISN リスト:
(ISN は格納されません)8 12 14 15 24 31 33

実行結果の ISN バッファ:8 12 14 15 24

後続の Sx コールでコマンド ID が空白かバイナリのゼロ、ISN 下限が 0 の場合、最初のコール時と同じ検索コマンドが再実行され、同じ結果が得られます。

コマンド ID が空白またはバイナリのゼロで、ISN 下限 =24 の後続のコールでは、Sx コマンドが再実行されて、ISN 数 =2 で ISN バッファには 31 と 33 の ISN が入ります。

例 4:GET-NEXT オプションを使用した ISN リストの読み込み

最初の Sx コマンド

COMMAND = Sx               
COMMAND ID = SX01          
COMMAND OPTION 1 = blank   
ISN LOWER LIMIT = 0        
ISN BUFFER LENGTH = 4      
FORMAT BUFFER = <not empty>
CALL ADABAS ...

実行結果の ISN 数 = 3

実行結果の ISN = 44

実行結果の ISN リスト:
44 321 344(321 と 344 のみ格納されます)

実行結果の ISN バッファ:44

結果のレコードバッファ:ISN 44 のフィールド値

後続の L1/L4 コール

COMMAND = L1 or L4         
COMMAND ID = SX04          
COMMAND OPTION 2 = N       
FORMAT BUFFER = <unchanged>
CALL ADABAS ...

結果のレスポンスコード = 0

実行結果の ISN = 321

ISN 321 は、Adabas 一時ワークスペースから削除されます。

結果のレコードバッファ:ISN 321 のフィールド値

後続の L1/L4 コール

COMMAND = L1 or L4         
COMMAND ID = SX04          
COMMAND OPTION 2 = N       
FORMAT BUFFER = <unchanged>
CALL ADABAS ...

結果のレスポンスコード = 0

実行結果の ISN = 344

ISN 344 が Adabas 一時ワークスペースから削除され、残りの ISN リストが空になります

結果のレコードバッファ:ISN 344 のフィールド値

後続の L1/L4 コール

COMMAND = L1 or L4         
COMMAND ID = SX04          
COMMAND OPTION 2 = N       
FORMAT BUFFER = <unchanged>
CALL ADABAS ... 

結果のレスポンスコード = 3 (ISN リストの最後)

コマンド ID SY04 が解放されます。

マルチフェッチ機能の使用

マルチフェッチ機能は、1 回のコールで複数のレコードを取得する際に使用します。この機能を使用すると、コミュニケーションのオーバーヘッドを大幅に削減することができます。

検索

コマンド L1/L4、L2/L5、L3/L6、および L9 のいずれかのコマンドオプション 1 フィールドに M を指定すれば、マルチフェッチ機能を発行できますが、このコマンドに RETURN オプションを指定する必要がある場合には、M ではなく O を指定します。

ACBX インターフェイスを使用する場合は、マルチフェッチバッファもユーザープログラム内で定義する必要があります。

ACB インターフェイスを使用する場合は、ISN バッファもユーザープログラム内で定義する必要があります。

レコードバッファに返されるレコードの内容を示すデータのストレージとして、対応するバッファが使用されます。最初の 4 バイトには、コールの結果として返されるレコードの数が格納されます。レコードバッファの各レコードは、ISN/マルチフェッチバッファの 16 バイトのエントリとして表現されます。

バイト 説明
1-4 レコードの長さ
5-8 Adabas レスポンスコード
9-12 レコードの ISN(L9 コマンドの場合は、ディスクリプタがピリオディックグループの中にあればオカレンスカウントを表します)
13~16(L9) ISN 数
13~16(L3/L6) ディスクリプタがピリオディックグループの中にあれば、ピリオディックグループのインデックス

コマンドブロックに ISN 下限フィールドを指定すると、返すレコードの数を制限することができます。このフィールドをゼロに設定した場合、返されるレコードの最大数は、レコードバッファや ISN/マルチフェッチバッファのサイズによって決定されます。

別のユーザーにより ISN がホールド状態になった時点、またはホールドキューが上限に達した時点で、それ以上、レコードがレコードバッファに返されなくなります。最初のレコードが別のユーザーにホールドされ、コマンドオプション 1 フィールドが M になっている場合、実質的には待機状態になっていることを表します。2 番目以降のレコードが別のユーザーにホールドされた場合には、その時点で、ホールドされる前のレコードがユーザーに返されます。コマンドオプション 1 フィールドが O になっていて、レコードが別のユーザーにホールドされた場合、レスポンスコード 145 が返されます。レスポンスコードの出力先は、最初のレコードの場合にはコントロールブロック、2 番目以降のレコードの場合には ISN/マルチフェッチバッファになります。

レコードの処理中にエラーが検出されると、ISN/マルチフェッチバッファの対応する構造にレスポンスコードが返されます。

コントロールブロックに返される ISN は、最初に返されたレコードの ISN です。

コントロールブロックに返される ISN と ISN 数は、最後に返されたレコードの ISN と ISN 数です。

ISN/マルチフェッチバッファ長が 20 バイト未満の場合、またはレコードバッファが小さすぎて 1 件もレコードを処理できない場合は、コントロールブロックにレスポンスコード 53 が返されます。

最初のレコードの処理中にエラーが検出されると、レスポンスコードがコントロールブロックのレスポンスコードフィールドに返されます。2 番目以降のレコードの処理中にエラーが検出されると、処理済みのレコードが返され、ユーザー定義の ISN/マルチフェッチバッファ内の対応する構造に、エラーが検出されたレコードのレスポンスコードが格納されます。

ホールド状態になったときの処理

別のユーザーにホールドされて ISN がホールド状態になった場合、またはホールドキューが上限に達した場合に、それ以降の処理がどうなるかは、指定したオプションが M なのか O なのかによって異なります。

M オプションを指定した場合、ホールド状態になるまでに L1/L4 コマンドが処理したレコードが返されますが、レスポンスコードは返されません。ホールド状態になるまでに 1 件もレコードを処理していない場合、Adabas は、次のレコードを処理できるようになるまで待機します。

O オプションを指定した場合、ホールド状態になった時点で、レコードバッファにレコードが返されなくなります。レコードバッファが空の場合には、レスポンスコード 145 がコントロールブロックに返されます。レコードバッファが空でない場合、コントロールブロックにはレスポンスコード 0 が返されますが、ISN/マルチフェッチバッファ(読み込まれなかったレコードに該当するエントリ)にはレスポンスコード 145 が返されます。

トランザクション制御

ET/BT コマンドのコマンドオプション 1 フィールドに M を指定すると、マルチフェッチ機能が起動されます。この指定で、ユーザーがISNバッファに指定したISNのリストがホールド状態から解放されます。最初の 4 バイトには、ホールド状態が解除される ISN の数が格納されます。ISN バッファでは、それぞれの ISN 情報が 8 バイトのエントリとして次のように示されます。

バイト 説明
1-4 ファイル番号
5-8 レコードの ISN

レコードが 1 件もホールド状態から解除されていない場合は、ISN バッファの最初の 4 バイトにゼロが設定されます。この場合、TT タイムリミットは再スタートしません。

指定したファイル番号と ISN の組み合わせが、該当ユーザーに対してホールド状態になっていなければ、Adabas レスポンスコード 144 が返されます。

このレスポンスコードは、ISN バッファの処理が全部終了してから返されます。

ISN バッファ長が 4 + (ISN 数 × 8) よりも短い場合は、マルチフェッチ機能は無視され、標準のコールとして処理されます。このとき、返される Adabas レスポンスコードは 53 です。

注意:
トランザクション制御には、ACBX インターフェイスもマルチフェッチ機能を使用するためのマルチフェッチバッファではなく、ISN バッファを使用します。

ACB と ACBX の機能

ACB インターフェイスで使用可能な Adabas 機能は、ACBX インターフェイスで使用可能な機能のサブセットです。ただし、MC コマンドは ACB インターフェイスを通じてのみ使用できます。

すべての ACB コールは、Adabas インターフェイスルーチン(adalnkx など)によって ACBX コールに変換され、結果は変換し直されて ACB インターフェイスに戻されます。次の規則が適用されます。

  • ACB と ACBX の両方に含まれるすべてのフィールドが ACBX にコピーされます。ACBX インターフェイスでは、一部のフィールドが大きいサイズで定義されています。つまり、ACB フィールドには収まらないが、対応する ACBX フィールドには収まる値を指定する場合は、ACBX インターフェイスを使用する必要があります。Adabas バージョン 6.2 では、このような大きいサイズはまだ使用されていません。

  • ACBX インターフェイスで必要な ABD は、Adabas バッファ長から生成されます。コマンドで 64 KB 以上のバッファが必要な場合は、ACBX インターフェイスを使用する必要があります。

  • 前のセクションで説明したように、ACBX インターフェイスがマルチフェッチバッファを使用する場合、ACB インターフェイスで ISN バッファが使用されることがあります。このような場合、ACB コールの ISN バッファの ABD は、マルチフェッチバッファの ABD として生成されます。

  • ACBX にのみ含まれるフィールドは、デフォルト値に設定されます。これらのフィールドに他の値を指定する場合は、ACBX インターフェイスを使用する必要がありますが、Adabas バージョン 6.2 には ACBX 専用フィールドからの入力を使用するコマンドはありません。

  • ACB と ACBX の両方に含まれるフィールドに属するフィールドの結果値は、ACB にコピーされます。Adabas バージョン 6.1 では、ACBX でフィールドが ACB でのサイズよりも大きいサイズで定義されている場合、これらのフィールドが ACB フィールドに収まらない値を持つことはできません。

  • ACBX 専用フィールドに返された情報は、ACB コールで失われます。Adabas バージョン 6.2 では、実行されたコマンドの一部の診断情報のみが ACBX 専用フィールドに返されます。

ACB コールと ACBx コールの関係に関するこの知識があれば、ACB インターフェイスと ACBX インターフェイスでどのようにコマンドが実行されるかに関する個別の説明は不要です。

システム生成フィールド

ファイルにシステム生成フィールドが含まれている場合は、格納および更新コマンドの動作のみが変更されます。読み込みおよび検索コマンドの動作は変更されません。

システム生成フィールドの値は、Adabas によって自動的に生成されます。格納および更新コマンドのレコードバッファにシステム生成フィールドの値が含まれているかどうかは関係ありません。レコードバッファ内のシステム生成フィールドのフィールド値は、通常、無視されます。ただし、以下で説明しているように、楽観的ロック用の最終更新タイムスタンプフィールドを使用する場合は例外です。

システム生成フィールドがオプション CR ありで定義されている場合、値は格納コマンド中にのみ生成され、更新されることはありません。

システム生成フィールドがオプション CR なしで定義されている場合、値は格納コマンド中に生成され、更新コマンド中に更新されます。フィールドがマルチプルバリューフィールドの場合、新しい最初の値が挿入され、古いフィールドが 1 エレメントだけ右にシフトされます。MU インデックスのあるフィールド値がファイルパラメータ SYFMAX より大きくなった場合、これらのフィールドは削除されます。

楽観的ロック用の最終更新タイムスタンプの使用

A1 コマンドにコマンドオプション 2 = 'T'(タイムスタンプのチェック)を指定すると、楽観的ロック用の最終更新タイムスタンプシステム生成フィールドを使用できます。

  • 更新するレコードを読み取るとき、レコードをまったくロックしないか、オプション 'C' でロックします。レコードをまったくロックしない場合は、コミットされていない更新が表示される(ダーティリード)という短所があります。オプション 'C' でロックした場合は、コミットされていない更新は表示されませんが、読み込みコマンドの終了後にロックが維持されません。読み込みコマンドは、最終更新タイムスタンプシステム生成フィールド(オプション SY = TIME が指定されていて、オプション CR が指定されていないフィールド)を読み込みます。

  • 更新は、コマンドオプション 'T' を指定した A1 コマンドによって実行され、フォーマットおよびレコードバッファに最終更新タイムスタンプフィールドを含んでいる必要があります。読み込みコマンド以降にフィールド値が変更されていてはいけません。

  • 最終更新タイムスタンプが MU フィールドに格納されている場合、インデックス 1 のフィールド値をフォーマットバッファに指定する必要があります。

  • オプション 'T' が指定されていて、かつ最終更新タイムスタンプシステム生成フィールドがフォーマットバッファに含まれていない場合は、レスポンスコード 44、サブコード 13 が返されます。

  • レコードバッファで指定されたフィールド値が、データベースレコードの現在の値と同じかどうかがチェックされます。

    • データベース内の値が同じ値で、オプション SY=TIME が指定されたフィールドの精度で現在時刻がまだ同じ場合、コマンドはレスポンスコード 22、サブコード 42 で失敗します

    • データベース内の値が同じ値で、オプション SY=TIME が指定されたフィールドの精度で現在時刻が変更された場合、レコードはホールド状態になります。レコードが別のユーザーによってホールドされている場合は、RETURN オプションの使用法によって異なる動作になります。

      • RETURN オプション(オプション 'R' または 'U')が指定されている場合は、レスポンスコード 145 が返されます。

      • それ以外の場合、コマンドはレコードが再び使用可能になるまで待機します。その後、チェックが繰り返されます。

    • その間にシステム生成値が変更された場合は、レスポンスコード 48、サブコード 34 が返されます。オプション 'L' または 'U' を指定した場合、変更されたレコードはレコードバッファに読み込まれます。

注意:
オプション SY=TIME が指定されたシステム生成フィールドが高精度タイムスタンプではない場合、このファイルに対するすべての更新がオプション 'T' で実行されるという条件で、更新が失われないことが保証されます。迷った場合は、この種の更新は高精度タイムスタンプでのみ使用してください。

読み込み整合性

L1、L2、L3、または S1 コマンドでレコードを読み込むと、ダーティリードになります。つまり、コミットされていない更新も表示されます。Adabas では、コミット済みレコードのみを表示するための、レコードの共有ロックを提供しています。各自の要件に応じて、異なるタイミングでレコードを共有ホールド状態にすることができます。

  • C オプションでは、レコードがすでにロックされているのでない限り、現在の読み込み処理終了後は、レコードの共有ホールド状態が維持されません。

  • Q オプションでは、読み込みループの次のレコードが読み込まれるまで、レコードが共有ホールド状態に維持されます。これを使用して、同じレコードに対して複数の整合性のある読み込み処理を実行できます。

  • S オプションでは、現在のトランザクションがコミットまたはロールバックされるまで、レコードの共有ホールド状態が維持されます。

  • RI コマンドでは、レコードが共有ホールド状態から削除される前に、レコードを共有ホールド状態から解放できます。

注意:
C、Q、または S オプションを使用するには、コマンドを L4、L5、L6、または S4 に変更する必要があります。

複数の読み込みコマンドを使用してレコードのさまざまな部分を読み込む場合(LOB フィールドを断片的に読み込み場合など)、読み込み処理間でレコードが更新されないようにすることを強くお勧めします。この目的のために、次のことが可能です。

  • レコードの最初の読み込みコマンドを実行するときに、コマンドオプション 3 = Q、S、または空白を使用して、レコードを共有または排他ホールド状態にする。

  • 各読み込みコマンドで、高精度のシステム生成最終更新タイムスタンプを読み込んで、読み込みコマンド間で変更されていないことを確認する。このソリューションの利点は、他のユーザーがレコードを排他的ホールド状態にしたときにもレコードを読み込むことができることです。ただし、まだダーティリードとなっている(コミットされていない更新が表示される)ことに注意する必要があります。

  • アプリケーションが読み込みの整合性を保証する。例えば、ユーザーがすでにロックしているレコードを、別のユーザーがロックした後にのみ別のユーザーによるレコード更新が許可される場合は、レコードをロックせずに読み込むことができます。この種類の整合性維持は、ファイルを更新するすべてのプログラムがこれらのルールを守ることが確実な場合にのみ使用してください。

ラージオブジェクト(LOB)サポート用の Adabas コマンドインターフェイスの機能

特に LOB サポート用として、Adabas コマンドインターフェイスに次の機能が導入されました。

ACBX インターフェイスでの大きなバッファ

古い ACB インターフェイスでは、レコードバッファのサイズは 64 KB に制限されていましたが、これは LOB サポートには小さすぎます。最大 2 GB のレコードバッファサイズを許容する新しい ACBX インターフェイスでは、この制限がなくなりました。

ACBX インターフェイスでの複数のフォーマット/レコードバッファペア

1 つの Adabas コールで LOB フィールドおよび他のフィールドにアクセスする場合、LOB 値は多くの場合可変長なので、このスペースを特別なエリアに割り当てることが必要になります。他のフィールドは固定長なので、事前定義されたエリアに置かれます。ACBX インターフェイスでは、これら両方のエリアを同じ Adabas コールの異なるレコードバッファとして指定できます。

可変長で読み込むときの LOB フィールドの 4 バイト長インジケータ

LOB フィールド(フィールドオプション LB が指定されたフィールド)の可変長を示すためにフォーマットバッファで長さ 0 を指定すると、より大きな長さ値をサポートするために 4 バイトの長さインジケータがレコードバッファで使用されます。

フォーマット/レコードバッファの長さインジケータ

LOB 値を読み込む場合、LOB 値の長さが事前にわからないことがよくあります。長さインジケータを使用すると、LOB 値のエリアを割り当てる前に LOB 値の長さを取得できます。

フォーマットバッファでアスタリスク(*)を使った長さ表記

長さとしてアスタリスク(*)を指定すると、可変長で値が読み込まれます。長さとして 0 を指定する場合との違いは次のとおりです。

  • 値は、前に長さのない値です。読み込みコマンドに推奨され、LOB フィールドに長さインジケータも指定する挿入/更新コマンドでは必須です。

  • レコードバッファに収まらない値を読み込んだ場合でも、レコードバッファオーバーフロー(Adabas レスポンスコード 53)は返されません。* 長さで長さインジケータと LOB 値を読み込んだ場合、LOB 値がレコードバッファに収まらない場合でも LOB 値の長さを取得でき、十分なサイズのレコードバッファを再割り当てして LOB 値を再読み込みすることができます。

フォーマットバッファでセグメント表記を使用した LOB の一部へのアクセス

使用可能なメモリに制限がある場合、または LOB 値内で既知の位置にある LOB の一部のみへのアクセスが必要な場合には、大きな LOB 値にアクセスするときに、LOB 値に断片的にアクセスできます。フォーマットバッファでセグメント表記を使用してこれを行うことができます。

注意:
フォーマットバッファエントリの詳細については、前述の「Adabas の呼び出し」の「フォーマットバッファとレコードバッファ」セクションを参照してください。