FML を使用した Tuxedo アプリケーションのプログラミング

     前  次    新しいウィンドウで目次を開く     
ここから内容の開始

FML および VIEWS の機能

ここでは、以下の内容について説明します。

 


レコードをフィールドに分割する: データ構造体とフィールド化バッファ

データ レコードは、分割できない完全なエンティティでない限り、フィールドに分割できる状態でなければなりません。データ レコードを分割できないと、レコード内の情報を使用したり、変更できません。ATMI 環境では、次のどちらかを使用してレコードを分割できます。

構造体を使用してレコードをフィールドに分割する

レコードを分割する一般的な方法の 1 つは、構造体を使用して連続したストレージをフィールドに分割することです。フィールドには ID が指定されます。各フィールド内のデータの種類は、データ型の宣言によって示されます。

たとえば、C 言語プログラム内のデータ項目が、従業員の ID、名前、住所、および性別の場合は、次の構造体を使用してプログラムを設定できます。

struct S {
long empid;
char name[20];
char addr[40];
char gender;
};

ここでは、empid (従業員の ID) というフィールドが long 型の整数で宣言されています。name (名前) は 20 文字の文字配列で宣言され、addr (住所) は 40 文字の文字配列で宣言されます。gender (性別) は、単一文字 (mf など) で宣言されます。

C プログラム内で、変数 p が struct S 型の構造体を指す場合は、p->empidp->namep->addr、および p->gender という参照を使用してフィールドを指定できます。

同じデータ構造の COBOL COPY ファイルは、以下のようになります (第 01 行はアプリケーション側で提供されます)。

05 EMPID                           PIC S9(9) USAGE IS COMP-5.
05 NAME PIC X(20).
05 ADDR PIC X(40).
05 GENDER PIC X(01).
05 FILLER PIC X(03).

COBOL のプログラムで、第 01 行に MYREC という名前を付けた場合は、EMPID IN MYRECNAME IN MYRECADDR IN MYREC、および GENDER IN MYREC を使用して各フィールドにアクセスできます。

このデータ表現法は広く使用されており、通常は適用できますが、次の 2 つの潜在的な問題があります。

フィールド化バッファを使用してレコードをフィールドに分割する

レコードをフィールドに分割する別の方法は、フィールド化バッファを使用することです。

フィールド化バッファは、レコードのフィールドに対して連想アクセスを提供するデータ構造体です。つまり、フィールド名は、フィールドのデータ型のほか、ストレージの位置を含む識別子と関連付けられています。

フィールド化バッファの主な利点は、データの独立性です。つまり、バッファに対してフィールドを追加または削除したり、フィールド長を変更しても、フィールドを参照するプログラムを再コンパイルする必要はありません。データの独立性を実現するため、フィールドは以下のように使用されます。

ATMI 環境では、協調動作するプロセス間で送信されるデータを表現する標準的な方法として、フィールド化バッファを使用できます。

 


FML でのフィールド化バッファの実装方法

フィールド化バッファの作成、更新、アクセス、入力、出力、および操作は、フィールド操作言語 (FML) によって行います。FML には以下の特徴があります。

FML は、C プログラムから呼び出すことができる関数およびマクロのライブラリとして実装されています。FML には、以下の関数が用意されています。

上記のうち、最後のセットが FML VIEWS ソフトウェアを構成する関数のセットです。VIEWS は、FML フィールド化バッファとアプリケーション プログラムの構造体 (C 言語または COBOL 言語) との間でデータを交換する関数のセットです。プログラムは、別のプロセスからフィールド化バッファを受け取ると、次の動作として以下のいずれかを実行します。

バッファのデータに対して、時間のかかる操作を行う必要がある場合は、フィールド化バッファのデータを構造体に転送し、通常の C または COBOL 文を使用してそのデータを処理すると、プログラムのパフォーマンスを向上させることができます。次に、再び VIEWS 関数を使用してデータをフィールド化バッファに戻すと、そのバッファを別のプロセスに送信できます。

VIEWS を使用する前に、受信するフィールド化バッファのデータ形式がプログラム側で認識できるようにプログラムを設定しておかなければなりません。この設定には、システム キャッシュに保存されている VIEW 記述のセットを使用します。

VIEW 記述は、ソース VIEW ファイル内に作成および格納されます。VIEW 記述により、フィールド化バッファ内のフィールドが C 構造体または COBOL レコード内のメンバにマッピングされます。ソース VIEW 記述がコンパイルされると、その記述は、フィールド化バッファと C 構造体、またはフィールド化バッファと COBOL レコードの間で転送されるデータをマッピングするために使用できます。

主要なファイルに VIEW 記述をキャッシングしておくと、プログラムのデータ独立性を強化できます。つまり、VIEWS 記述を変更し、再コンパイルするだけで、VIEWS を使用するアプリケーション プログラム全体のデータ形式に変更を加えることができます。

 


FML の機能

ここでは、以下の内容について説明します。

 


フィールド化バッファとは

フィールド化バッファとは、レコードのフィールドに対して連想アクセスを行うデータ構造です。

FML フィールド化バッファ内の各フィールドには、フィールドのデータ型に関する情報とユニークな ID 番号を組み合わせた short 型の整数がラベル付けされています。このラベルは、フィールド識別子 (fldid) と呼ばれます。可変長項目の場合は、fldid の後にデータ長を指定します。

フィールド化バッファは、fldid、データ、の順で組み合わせるか、または、可変長項目の場合は fldid、フィールド値長、データ、の順で組み合わせて表現します。次の図を参照してください。

図 2-1 フィールド化バッファ

フィールド化バッファ

FML 関数を使用するたびに #include を使用して組み込まれるヘッダ ファイル (fml.h または fml32.h) では、typedef により、フィールド識別子は FLDID (FML32 では FLDID32)、フィールド値長は FLDLEN (FML32 では FLDLEN32)、フィールド オカレンス数は FLDOCC (FML32 では FLDOCC32) と定義されます。

 


サポートされているフィールド型

サポートされているフィールド型は、short 型、long 型、float 型、double 型、char 型、string 型、carray 型 (文字配列)、mbstring 型 (マルチバイト文字配列 - Tuxedo リリース 8.1 またはそれ以降で使用可能)、ptr 型 (バッファを指すポインタ)、FML32 型 (埋め込み型の FML32 バッファ)、および VIEW32 型 (埋め込み型の VIEW32 バッファ) です。mbstringptrFML32、および VIEW32 型は、FML32 インタフェースでのみサポートされています。これらの型は、次のコード リストに示すように、fml.h (または fml32.h) 内の #define 文で定義されています。

コード リスト 2-1 fml.h および fml32.h における FML フィールド型の定義
#define FLD_SHORT       0       /* short int */
#define FLD_LONG 1 /* long int */
#define FLD_CHAR 2 /* character */
#define FLD_FLOAT 3 /* 単精度 float */
#define FLD_DOUBLE 4 /* 倍精度 float */
#define FLD_STRING 5 /* string - null で終わる */
#define FLD_CARRAY 6 /* character 配列 */
#define FLD_PTR 9 /* バッファに対するポインタ */
#define FLD_FML32 10 /* 埋め込み型の FML32 バッファ */
#define FLD_VIEW32 11 /* 埋め込み型の VIEW32 バッファ */
#define FLD_MBSTRING 12 /* マルチバイトの character 配列 */

FLD_STRINGFLD_CARRAY、および FLD_MBSTRING はいずれも配列ですが、次の点が異なります。

フィールドを追加または変更する関数には、FLDLEN 引数を指定します。この引数は、FLD_CARRAY または FLD_MBSTRING フィールドを処理する場合は必須です。文字列または文字配列のサイズは、FML では最大 65,535 文字、FML32 では最大 2 ギガバイトに制限されています。

unsigned 型のデータ型は、フィールド化バッファに格納しないでください。このデータ型を使用すると、フィールド化バッファからデータを検索するたびに、FML の変換関数を使用して、unsigned short 型データをすべて long 型データに変換するか、またはそれらのデータを正しい unsigned 型にキャストしなければなりません。

ほとんどの FML 関数では、型のチェックは行われません。通常、フィールド化バッファで更新または検索された値は、ネイティブな型と一致すると見なされます。たとえば、バッファ フィールドが FLD_LONG として定義されていると、必ず、long 型の値のアドレスを渡す必要があります。FML 変換関数は、データをフィールド化バッファに格納する (または、データをフィールド化バッファから検索する) ほか、ユーザ指定の型からネイティブ フィールド型 (または、ネイティブ フィールド型からユーザ指定の型) にデータを変換します。

FLD_PTR フィールド型を使用すると、FML32 バッファ内のアプリケーション データへのポインタを埋め込むことができます。アプリケーション側では、データ バッファへのポインタの追加、変更、アクセス、および削除が可能です。FLD_PTR フィールドが指すバッファは、tpalloc(3c) を呼び出して割り当てます。FLD_PTR フィールド型は、FML32 でのみサポートされています。

FLD_FML32 フィールド型は、レコード全体を単一フィールドとして FML32 バッファに格納できます。同様に、FLD_VIEW32 フィールド型は、C 構造体全体を FML32 バッファ内に単一フィールドとして格納できます。FLD_FML32 および FLD_VIEW32 フィールド型は、FML32 でのみサポートされています。

VIEWS の int 型

VIEWS は、大半の FML 関数でサポートされているデータ型のほか、ソース VIEW 記述内で int 型を間接的にサポートします。VIEW 記述がコンパイルされると、VIEW のコンパイラは、マシンの種類に応じて、すべての int 型を short 型か long 型に自動的に変換します。詳細については、「VIEWS の機能」を参照してください。

VIEWS の dec_t 型

VIEWS では、ソース VIEW 記述内で dec_t パック 10 進数型もサポートされています。このデータ型は、VIEW の構造体から COBOL のプログラムへの転送に便利です。dec_t 型を使用する C プログラムでは、『Oracle Tuxedo C リファレンス』の「decimal(3c)」リファレンス ページで説明されている関数を使用してフィールドの初期化およびアクセスを行う必要があります。COBOL プログラムでは、パック 10 進数 (COMP-3) の定義を使用してこのフィールドに直接アクセスできます。FML では dec_t フィールドがサポートされていないため、このフィールドは、VIEW から FML に変換するときに、フィールド化バッファ内の対応する FML フィールドのデータ型 (string 型など) に自動的に変換されます。

 


フィールド名から識別子へのマッピング

Oracle Tuxedo システムでは、フィールドは通常、フィールド識別子 (fldid) の整数によって参照されます。フィールド識別子の詳細については、「フィールド名とフィールド識別子を定義する」を参照してください。このため、変更の可能性があるフィールド名を使用しないで、プログラム内でフィールドを参照できます。

識別子をフィールド名に割り当てる (マッピングする) には、次のいずれかの方法を使用します。

通常のアプリケーション プログラムでは、上記の方法のどちらか、または両方を使用して、フィールド識別子をフィールド名にマッピングできます。

FML でフィールド化レコード内のデータにアクセスするには、FML でフィールド名と識別子のマッピング情報にアクセスできなければなりません。FML は、以下の方法のいずれかを使用してこのマッピング情報を取得します。

フィールド名と識別子のマッピングは、COBOL では使用できません。

実行時: フィールド テーブル ファイル

フィールド テーブル ファイルにより、FML プログラムの実行時、フィールド名と識別子のマッピング情報が使用可能になります。ただし、フィールド名と識別子のマッピング テーブル ファイルの場所は、2 つの環境変数を用いて、プログラマが直接設定します。

環境変数 FLDTBLDIR には、フィールド テーブルの検索用ディレクトリのリストを指定し、FIELDTBLS 環境変数には、それらのテーブル ディレクトリから検索すべきファイルのリストを指定します。対応する FML32 の環境変数は、FLDTBLDIR32 および FIELDTBLS32 です。

アプリケーション プログラム内では、FML 関数である Fldid() により、フィールド名からフィールド識別子への変換が実行時に行われます。フィールド識別子をフィールド名に変換する処理は、Fname() によって行われます (Fldid(3fml) および Fname(3fml) を参照してください。FML32 については Fldid32 および Fname32 を参照してください)。これらの 2 つの関数のうち、最初に呼び出された関数によってメモリ内の領域がフィールド テーブル用に動的に割り当てられ、フィールド テーブルがプロセスのアドレス領域にロードされます。フィールド テーブルが不要になると、領域を回復できます。詳細については、「フィールド テーブルをロードする」を参照してください。

アプリケーション内でフィールド名と識別子のマッピングの変更が予測される場合は、この方法を使用します。詳細については、「フィールドの定義と使用」を参照してください。

コンパイル時: ヘッダ ファイル

mkfldhdr() (または mkfldhdr32()) を使用すると、フィールド テーブル ファイルからヘッダ ファイルを作成できます。これらのヘッダ ファイルは、C プログラムの #include に組み込まれており、フィールド名とフィールド識別子のマッピングを行います。mkfldhdr、mkfldhdr32(1) の詳細については、『Tuxedo コマンド リファレンス』を参照してください。

C プリプロセッサは、コンパイル時にフィールド ヘッダ ファイルを使用して、すべてのフィールド名の参照をフィールド識別子に変換します。したがって、前の節で説明したように、フィールド テーブル ファイルを使用して Fldid() 関数や Fname() 関数を呼び出す必要はありません。

プログラムで必要なフィールド名が常にわかる場合は、フィールド テーブルのヘッダ ファイルを #include でプログラムに組み込むと、データ領域を節約できます。データ領域を節約すると、プログラムではすばやく目的のタスクを実行できます。

ただし、この方法はコンパイル時にマッピングを解決するため、アプリケーション内でフィールド名とフィールド識別子のマッピングに変更が生じる可能性がある場合は使用しないでください。詳細については、「フィールドの定義と使用」を参照してください。

 


フィールド化バッファのインデックス

フィールド化バッファに多数のフィールドが含まれる場合、内部インデックスを使用すると、FML でのアクセスが促進されます。通常、ユーザはこのインデックスの存在を意識することはありません。

ただし、フィールド化バッファのインデックスは、メモリおよびディスク領域を消費します。したがって、フィールド化バッファをディスクに格納したり、プロセス間またはコンピュータ間で転送する場合は、まず、このインデックスを削除すると、ディスク領域や転送時間を節約できます。

インデックスを削除するには、Funindex() 関数を使用します。フィールド化バッファがディスクから読み取られるか、または、送信プロセスによって受け取られると、Findex() 関数を使用して再びインデックスを明示的に作成できます。

ただし、この方法を使用してもメモリは節約できません。Funindex() 関数を使用しても、フィールド化バッファのインデックス用に使用されるインコア メモリは回復できません。

詳細については、『Oracle Tuxedo FML リファレンス』の「Funindex、Funindex32(3fml)」または「Findex、Findex32(3fml)」を参照してください。

 


複数のオカレンスを持つフィールド化バッファのフィールド

フィールド化バッファ内のフィールドは、複数回出現する場合があります。FML 関数の多くが、検索または変更の対象にするフィールド オカレンスを指定する引数を取ります。フィールドが複数回出現する場合、オカレンスは、最初のオカレンスを 0 として、順次番号付けされます。オカレンスのセットは論理的なシーケンスを構成しますが、オカレンス番号に関連するオーバーヘッドは発生しません (つまり、オカレンス番号はフィールド化バッファに格納されません)。

フィールドのオカレンスを追加すると、そのオカレンスは、オカレンスのセットの最後に追加され、最も大きい番号の次の番号が指定されたオカレンスとして参照されます。最も大きい番号が指定されたオカレンス以外のオカレンスを削除すると、削除されたオカレンスより大きい番号のオカレンスには、1 つ低い番号が指定されます。たとえば、オカレンス 6 はオカレンス 5 になり、オカレンス 5 はオカレンス 4 になります。

 


論理式とフィールド化バッファ

アプリケーション プログラムが次に行うアクションは、ユーザ端末やデータベース レコードなど、別のソースから受け取ったフィールド化バッファの 1 つまたは複数のフィールドの値によって決まります。FML には、フィールド化バッファや VIEW に関する論理式を作成して、指定したバッファや VIEW が論理式の条件に合致するかどうかを判定するための関数がいくつか用意されています。

作成された論理式は、評価ツリーにコンパイルされます。評価ツリーは、フィールド化バッファまたは VIEW が指定された論理式の条件を満たすかどうかの判定に使用されます。

たとえば、プログラムがフィールド化バッファ (バッファ A) にデータ レコードを読み込み、そのバッファに論理式を適用するとします。バッファ A が論理式で指定された条件を満たす場合は、FML 関数が使用され、別のバッファ (バッファ B) をバッファ A からのデータで更新します。

 


VIEWS の機能

VIEWS は、プログラムがフィールド化バッファを受け取った後またはフィールド化バッファを別のプログラムに送る前に、バッファのデータに対して大量の処理を行う場合に特に便利です。

このような場合、VIEWS 関数を使用してフィールド化バッファのデータをバッファから C 構造体に転送し、その後でデータを処理すると、処理効率を高めることができます。フィールドをバッファ内で処理する場合、FML 関数より C 関数の方が処理時間が短いためです。C 構造体でデータの処理を終了したら、そのデータをフィールド化バッファに戻し、さらに別のプログラムに転送できます。

VIEWS には、以下の特徴があります。

ソース VIEW ファイルは、1 つまたは複数のソース VIEW 記述を含む一般的なテキスト ファイルです。ソース VIEW ファイルは、VIEW コンパイラである viewc または viewc32 への入力として使用され、ソース VIEW 記述をコンパイルし、オブジェクト VIEW ファイルに格納します。VIEW コンパイラの詳細については、『Tuxedo コマンド リファレンス』の「viewc、viewc32(1)」を参照してください。

VIEW コンパイラは、オブジェクト VIEW ファイル用の C ヘッダ ファイルも生成します。これらのヘッダ ファイルは、アプリケーション プログラム内に組み込まれると、オブジェクト VIEW 記述で指定された構造体を定義できます。

VIEW コンパイラは、必要に応じてオブジェクト VIEW ファイルに対する COBOL COPY ファイルも生成します。これらの COPY ファイルは、COPY プログラムに組み込み、オブジェクト VIEW 記述で指定するレコード形式を定義できます。

NULL 値は構造体の空のメンバを表すのに使用し、viewfile の構造体の各メンバに対して指定できます。メンバに NULL 値を指定しないと、省略時の NULL 値が使用されます。

ただし、構造体からフィールド化バッファへの転送時には、NULL 値を含む構造体メンバは転送されません。

また、C または COBOL 構造体のメンバとフィールド化バッファ内のフィールドの間にマッピングが存在していても、それらの間でのデータ転送を禁止することができます。これは、ソース VIEW ファイルで指定します。

FML VIEWS 関数として、Fvstof()Fvftos()Fvnull()Fvopt()Fvselinit()Fvsinit() があります。COBOL では、VIEWS 機能によって FVSTOF および FVFTOS の 2 つの手順が提供されています。どちらの VIEW 関数を呼び出しても、指定されたオブジェクト VIEW ファイルが検索され、そのファイルが見つかると、VIEW ファイルのキャッシュに自動的にロードされます。つまり、環境変数 VIEWFILES で指定された各ファイルが順番に検索され (「FML および VIEWS の環境設定」を参照)、指定された名前が付いた最初のオブジェクト VIEW ファイルがロードされます。同じ名前を持つ以降のオブジェクト VIEW ファイルは無視されます。FML VIEWS 関数の詳細については、『Oracle Tuxedo FML リファレンス』を参照してください。

VIEWS では、構造体の配列、ポインタ、ユニオン、typedef はサポートされていません。

複数のオカレンスを持つ VIEWS のフィールド

VIEWS は、フィールド化バッファと C 構造体、またはフィールド化バッファと COBOL レコードの間で交換されるフィールドを扱うため、バッファ内で複数回発生するフィールドも処理する必要があります。

構造体内にフィールドの複数のオカレンスを格納するため、メンバは、C 言語または COBOL の OCCURS 句により配列として宣言されます。フィールドの 1 オカレンスに対して 1 つの配列の要素が使用されます。配列のサイズは、バッファ内のフィールド オカレンスの最大数を反映します。

フィールド化バッファから C 構造体または COBOL レコードへのデータ転送時に、受信側の配列に存在する要素の数がフィールド化バッファ内のオカレンスの数より多い場合、余分な要素には、デフォルト値またはユーザ指定の NULL 値が割り当てられます。バッファ内のオカレンスの数が配列内の要素の数より多い場合は、バッファ内の余分なオカレンスは無視されます。

C 構造体または COBOL レコードからフィールド化バッファにデータを転送する場合、デフォルト値またはユーザ指定の NULL 値に等しい値を含む配列メンバは無視されます。

 


FML 関数のエラー処理

FML 関数は、エラーを検出すると、以下の値のいずれか 1 つを返します。

FML 関数の呼び出しに対するすべての戻り値はこれらの条件と照合され、その結果、エラーが検出されます。

エラーの場合はすべて、外部整数 Ferrorfml.h で定義されたエラー番号に設定されます。FML32 では、Ferror32fml32.h で定義されたエラー番号に設定されます。

F_error() 関数 (または F_error32() 関数) は、標準エラー出力上にメッセージを出力します。この関数は、パラメータを 1 つ (文字列) とり、コロンと空白文字を追加してその引数文字列を出力します。次に、エラー メッセージとその後に続く改行文字を出力します。表示されるエラー メッセージは、エラー発生時に設定された Ferror 内の現在のエラー番号に対して定義されているメッセージです。

大抵の場合、F_error() 関数 (または F_error32() 関数) の引数文字列には、エラーを引き起こしたプログラムの名前が含まれます。詳細については、『Oracle Tuxedo FML リファレンス』の「F_error、F_error32(3fml)」を参照してください。

エラー メッセージのテキストをメッセージ カタログから取り出すため、Fstrerror、Fstrerror32(3fml) を使用できます。これらの関数は、userlog(3c)F_error()、または F_error32() の引数として使用できるポインタを返します。

FML の関数のエラー コードについては、『Oracle Tuxedo FML リファレンス』の各関数のエントリを参照してください。


  ページの先頭       前  次