あるプロセスから別のプロセスにメッセージを送信する場合、メッセージ・データ用のバッファを割り当てておく必要があります。Oracle Tuxedoシステムのクライアントは、型付きバッファを使用してサーバーにメッセージを送ります。型付きバッファとは、カテゴリ(タイプ)と、サブカテゴリ(サブタイプ)が定義されたメモリー領域です。型付きバッファは、Oracle Tuxedoシステムでサポートされる分散プログラミング環境の基本要素の1つです。
なぜ「型付き」レコードを使用するのでしょうか。分散環境では、アプリケーションが異機種システムにインストールされ、異なるプロトコルを使用して複数のネットワーク間で通信が行われます。バッファ・タイプが異なると、初期化、メッセージの送受信、およびデータのエンコード/デコードにそれぞれ別のルーチンが必要になります。各バッファに特定のタイプが割り当てられていると、プログラマが介在しなくても、そのタイプに対応するルーチンを自動的に呼び出すことができます。
表2-1は、Oracle Tuxedoシステムでサポートされる型付きバッファと、そのバッファが次の条件を満たしているかどうかを示しています。
ルーティング関数が必要な場合は、アプリケーション・プログラマが用意します。
Oracle Tuxedoシステム固有の自己記述型バッファ・タイプ。このバッファでは、各データ・フィールドに対応する識別子、オカレンス番号、場合によっては長さを示す値が格納されています。データ操作はすべて、ネイティブなC言語の文ではなくFML関数を使用して行われます。このため、処理に多少のオーバーヘッドが生じてでも、FMLバッファを通じて、データの独立性と動作の柔軟性が確保されるようになっています。
FMLバッファの詳細は、「FML型バッファ」を参照してください。
|
|||||
FML32バッファの詳細は、「FML型バッファ」を参照してください。
|
|||||
アプリケーションで定義されるC構造体。VIEW型には、個々のデータ構造体を示すサブタイプが必要です。VIEW記述ファイル (データ構造体のフィールドとタイプが定義されたファイル)は、VIEW型バッファに定義されたデータ構造体を使用するクライアント・プロセスとサーバー・プロセスがアクセスできなければなりません。異なるタイプのマシン間でバッファがやり取りされる場合は、エンコード/デコードが自動的に行われます。
VIEWバッファの詳細は、「VIEW型バッファ」を参照してください。
|
|||||
VIEW32バッファの詳細は、「VIEW型バッファ」を参照してください。
|
|||||
XML文書のルーティングは、要素の内容、または要素タイプと属性値に基づいて行われます。使用されている文字エンコードはXMLパーサーによって判別されます(Oracle Tuxedo 9.xでは、XMLパーサーとしてApache Xerces C++バージョン2.5パーサーが使用可能)。エンコードがOracle Tuxedoの構成ファイル(UBBCONFIG(5)とDMCONFIG(5))で使用されているネイティブな文字セット(US-ASCIIまたはEBCDIC)と異なる場合、要素と属性名はUS-ASCIIまたはEBCDICに変換されます。
XMLバッファおよびXerces C++パーサーの詳細は、「XML型バッファとApache Xerces C++パーサー」を参照してください。
|
|||||
Oracle Tuxedo 8.1で使用可能になったマルチバイト文字の文字配列。MBSTRINGバッファの詳細は、「MBSTRING型バッファ」を参照してください。
|
すべてのバッファ・タイプは、$TUXDIR/lib
ディレクトリのtmtypesw.c
ファイルに定義されています。クライアント・プログラムとサーバー・プログラムで認識されるバッファ・タイプは、tmtypesw.c
に定義されているものだけです。tmtypesw.c
ファイルを編集して、バッファ・タイプを追加したり削除できます。また、UBBCONFIG
のBUFTYPE
パラメータを使用して、特定のサービスで処理できるタイプとサブタイプを制限できます。
tmtypesw.c
ファイルは、共有オブジェクトや動的リンク・ライブラリのビルドに使用されます。このオブジェクトは、Oracle Tuxedo管理サーバー、およびアプリケーション・クライアントとアプリケーション・サーバーによって動的にロードされます。
初期状態では、バッファはクライアント・プロセスに関連付けられていません。クライアント・プロセスでメッセージを送信する場合、サポートされているタイプのバッファを割り当てて、メッセージを格納できるようにします。型付きバッファを割り当てるには、次に示すようにtpacall (3c)関数を使用します。
char*
tpalloc(char *type
, char *
subtype
, long
size
)
表2-2は、tpalloc()
関数の引数を示しています。
Oracle Tuxedoシステムにより、
CARRAY 、X_OCTET 、およびXML を除くすべての型付きバッファに、自動的にデフォルトのバッファ・サイズが割り当てられます。自動的にバッファ・サイズが割り当てられないバッファ型には、バッファの終わりを識別できるようにサイズを指定する必要があります。
|
リスト2-1で示すように、VIEW
、VIEW32
、X_C_TYPE
およびX_COMMON
型バッファにはsubtype
引数が必要です。
struct aud *audv; /* pointer to aud view structure */
. . .
audv = (struct aud *) tpalloc("VIEW", "aud", sizeof(struct aud));
. . .
リスト2-2は、FML型バッファの割当て方法を示しています。subtype
引数にNULL値が指定されていることに注目してください。
FBFR *fbfr; /* pointer to an FML buffer structure */
. . .
fbfr = (FBFR *)tpalloc("FML", NULL, Fneeded(f, v))
. . .
リスト2-3は、CARRAY
型バッファの割当て方法を示しています(このバッファ型では、size
値を指定する必要があります)。
char *cptr;
long casize;
. . .
casize = 1024;
cptr = tpalloc("CARRAY", NULL, casize);
. . .
処理が正常に終了すると、tpalloc()
関数はchar
型のポインタを返します。STRING
とCARRAY
以外のタイプでは、ポインタを適切なC構造体またはFMLポインタにキャストする必要があります。
tpalloc()
関数は、エラーを検出するとNULLポインタを返します。次は、エラー条件の例です。
全エラー・コードとその説明については、『Oracle Tuxedo ATMI C関数リファレンス』の「tpalloc(3c)」を参照してください。
リスト2-4は、STRING
型バッファの割当て方法を示しています。この例では、tpalloc()
のsize
引数の値として、関連するデフォルト・サイズが使用されています。
char *cptr;
. . .
cptr = tpalloc("STRING", NULL, 0);
. . .
バッファを割り当てると、そこにデータを格納できるようになります。
リスト2-5では、3つのメンバー(フィールド)を持つVIEW
型バッファaud
を作成しています。3つのメンバーは、コマンドラインがある場合は、そこから取得される支店識別子のb_id
、照会された残高を戻すbalance
、およびユーザーのステータス行にメッセージを戻すermsg
です。audit
を使用して特定の支店の残高が照会されると、b_id
メンバーの値には照会の送信先の支店識別子、balance
メンバーにはゼロ、ermsg
メンバーにはNULL文字列がそれぞれ設定されます。
...
audv = (struct aud *)tpalloc("VIEW", "aud", sizeof(struct aud));
/* Prepare aud structure */
audv->b_id = q_branchid;
audv->balance = 0.0;
(void)strcpy(audv->ermsg, "");
...
audit
を使用して銀行全体の残高が照会されると、BAL
サーバーが呼び出されてサイトごとの残高合計が取得されます。個々のサイトで照会を行うには、代表支店識別子を指定します。代表支店IDは、配列sitelist[]
に格納されます。したがって、aud
構造体は、リスト2-6のように設定されます。
...
/* Prepare aud structure */
audv->b_id = sitelist[i];/* routing done on this field */
audv->balance = 0.0;
(void)strcpy(audv->ermsg, "");
...
STRING
バッファにデータを格納するプロセスについては、「バッファのサイズ変更」のコード・リストを参照してください。
tpalloc()で割り当てられたバッファのサイズを変更するには、次のようにtprealloc (3c)関数を使用します。
char*
tprealloc(char *ptr, long size)
表2-3は、tprealloc()
関数の引数を示しています。
サイズを変更するバッファを指すポインタ。このポインタは、
tpalloc() の呼出しで設定されます。それ以外の方法で設定されている場合、呼出しは失敗し、tperrno(5)がTPEINVAL に設定されて、無効な引数がこの関数に渡されたことが示されます。
|
|
tprealloc()
が返すポインタは、元のバッファと同じタイプのバッファを指します。バッファの場所が変わっている場合があるので、返されたポインタを使用してサイズが変更されたバッファを参照します。
バッファのサイズを増やすためにtprealloc()
関数を呼び出すと、バッファに新しい領域が割り当てられます。バッファのサイズを減らすためにtprealloc()
関数を呼び出すと、実際にバッファのサイズが変更されるのでなく、指定されたサイズを超える領域が使用不能になります。型付きバッファの内容には影響しません。未使用領域を解放するには、必要なサイズを持つ別のバッファにデータをコピーし、未使用領域を持つバッファを解放します。
tprealloc()
関数は、エラーが発生するとNULLポインタを返し、tperrno
に適切な値を設定します。エラー・コードについては、『Oracle Tuxedo ATMI C関数リファレンス』の「tpalloc (3c)」を参照してください。
警告: | tprealloc() 関数がNULLポインタを返した場合、内容が変更されて有効ではなくなったバッファが渡された可能性があります。 |
リスト2-7は、STRING
バッファの領域を再度割り当てる方法を示しています。
#include <stdio.h>
#include “atmi.h”
char instr[100]; /* string to capture stdin input strings */
long s1len, s2len; /* string 1 and string 2 lengths */
char *s1ptr, *s2ptr; /* string 1 and string 2 pointers */
main()
{
(void)gets(instr); /* get line from stdin */
s1len = (long)strlen(instr)+1; /* determine its length */
join application
if ((s1ptr = tpalloc(“STRING”, NULL, s1len)) == NULL) {
fprintf(stderr, “tpalloc failed for echo of: %s\n”, instr);
leave application
exit(1);
}
(void)strcpy(s1ptr, instr);
make communication call with buffer pointed to by s1ptr
(void)gets(instr); /* get another line from stdin */
s2len = (long)strlen(instr)+1; /* determine its length */
if ((s2ptr = tprealloc(s1ptr, s2len)) == NULL) {
fprintf(stderr, “tprealloc failed for echo of: %s\n”, instr);
free s1ptr's buffer
leave application
exit(1);
}
(void)strcpy(s2ptr, instr);
make communication call with buffer pointed to by s2ptr
. . .
}
リスト2-8は前述の例を拡張したもので、発生する可能性があるすべてのエラー・コードを確認する方法を示しています。
. . .
if ((s2ptr=tprealloc(s1ptr, s2len)) == NULL)
switch(tperrno) {
case TPEINVAL:
fprintf(stderr, "given invalid arguments\n");
fprintf(stderr, "will do tpalloc instead\n");
tpfree(s1ptr);
if ((s2ptr=tpalloc("STRING", NULL, s2len)) == NULL) {
fprintf(stderr, "tpalloc failed for echo of: %s\n", instr);
leave application
exit(1);
}
break;
case TPEPROTO:
fprintf(stderr, "tried to tprealloc before tpinit;\n");
fprintf(stderr, "program error; contact product support\n");
leave application
exit(1);
case TPESYSTEM:
fprintf(stderr,
"BEA Tuxedo error occurred; consult today's userlog file\n");
leave application
exit(1);
case TPEOS:
fprintf(stderr, "Operating System error %d occurred\n",Uunixerr);
leave application
exit(1);
default:
fprintf(stderr,
"Error from tpalloc: %s\n", tpstrerror(tperrno));
break;
}
tptypes (3c)関数は、バッファのタイプとサブタイプ(指定されている場合)を返します。次はtptypes()
関数のシグネチャです。
long
tptypes(char *ptr, char *type, char *subtype)
表2-4は、tptypes()
関数の引数を示しています。
データ・バッファを指すポインタ。このポインタは、tpalloc()または
tprealloc() の呼出しで設定されます。NULLは指定できません。また、文字型にキャストする必要があります。この2つの条件が満たされていない場合、tptypes()関数は引数が無効であることを示すエラーを返します。
|
|
処理が正常に終了した場合、tptypes()
関数は長精度型(long)でバッファの長さを返します。
エラーが発生した場合、tptypes()
は-1
を戻し、tperrno(5)に対応するエラー・コードを設定します。エラー・コードのリストについては、『Oracle Tuxedo ATMI C関数リファレンス』のC言語アプリケーション・トランザクション・モニター・インタフェースの紹介に関する項およびtpalloc(3c)に関する項を参照してください。
リスト2-9に示すように、処理の正常終了時にtptypes()
から戻されたサイズ値を使用して、デフォルトのバッファ・サイズがデータを格納するのに十分な大きさかどうかを確認できます。
. . .
iptr = (FBFR *)tpalloc("FML", NULL, 0);
ilen = tptypes(iptr, NULL, NULL);
. . .
if (ilen < mydatasize)
iptr=tprealloc(iptr, mydatasize);
tpfree (3c)関数は、tpalloc()で割り当てられたバッファ、またはtprealloc()で再度割り当てられたバッファを解放します。次はtpfree()
関数のシグネチャです。
void
tpfree(char *ptr)
tpfree()
関数の引数は、リスト2-5に示すptr
だけです。
データ・バッファを指すポインタ。このポインタは、tpalloc()またはtprealloc()の呼出しで設定されます。NULLは指定できません。また、文字型にキャストする必要があります。この2つの条件が満たされていない場合、この関数は何も解放しないか、エラー条件を通知しないで制御を戻します。
|
tpfree()
を使用してFML32
バッファを解放するとき、ルーチンは埋め込まれたバッファをすべて再帰的に解放して、メモリー・リークの発生を防ぎます。埋め込みバッファが解放されないようにするには、対応するポインタにNULLを指定してからtpfree()
ルーチンを発行します。ptrがNULLの場合、何も処理は行われません。
リスト2-10は、tpfree()
関数を使用してバッファを解放する方法を示しています。
struct aud *audv; /* pointer to aud view structure */
. . .
audv = (struct aud *)tpalloc("VIEW", "aud", sizeof(struct aud));
. . .
tpfree((char *)audv);
VIEW
型バッファには2種類あります。1つはFML VIEW
で、FML
バッファから生成されるC構造体です。もう1つは、単なる非依存型のC構造体です。
FML
バッファをC構造体に変換して再び元に戻す(FML VIEW
型バッファを使用する)のは、FML
型バッファでの処理にはオーバーヘッドが生じるからです。つまりFML型バッファには、データの独立性と操作の利便性がある一方で、FML
関数を呼び出すためのオーバーヘッドが発生します。C構造体は、柔軟性の点では劣りますが、バッファ・データの時間がかかる処理に適しています。大量のデータを操作する場合、フィールド化バッファのデータをC構造体に転送し、通常のC関数を使用してそのデータを処理し、格納やメッセージ転送を行うためにそのデータをFML型バッファに戻すと、パフォーマンスを向上させることができます。
FML
型バッファとFML
ファイルの変換の詳細は、『Oracle Tuxedo ATMI FML関数リファレンス』を参照してください。
#include
文に指定します。アプリケーションでVIEW型バッファを使用するには、表2-6の環境変数を設定します。
VIEW
型バッファを使用するには、VIEW記述ファイルにC言語のレコードを定義する必要があります。VIEW記述ファイルには、各エントリのVIEW、およびC構造体のマッピングとFML
変換パターンを記述したVIEWが定義されています。VIEWの名前は、C言語の構造体の名前に対応します。
$ /* VIEW構造体*/
VIEW viewname
type cname fbname count flag size null
表2-7は、VIEW記述ファイルに指定する必要がある各C構造体のフィールドを示しています。
|
|||
FML からVIEW 、またはVIEW からFML への変換関数を使用する場合、対応するFML 名をこのフィールドに指定する必要があります。このフィールド名は、FML フィールド表ファイルにも必要です。FML に依存しないVIEW には必要ありません。
|
|||
|
|||
数値型の場合、デフォルトのNULL値は0 (
dec_t の場合は0.0)になります。文字型の場合、デフォルトのNULL値は\0 になります。STRING 型、CARRAY 型、およびMBSTRING 型の場合、デフォルトのNULL値は “ "になります。
エスケープ文字として使用されている定数も、NULL値の指定に使用できます。VIEWコンパイラで認識されるエスケープ定数は、
\ddd (d は8進数)、\0 、\n 、\t 、\v 、\r 、\f 、\\ 、\' 、および\" です。
|
行頭に#または$文字を付けてコメント行を挿入できます。行頭に$が挿入されたコード行は、.h
ファイルに出力されます。
リスト2-11は、FML
バッファに基づくVIEW記述サンプル・ファイルの一部です。この場合は、fbname
フィールドを指定する必要があり、この値は対応するフィールド表ファイルの値と一致している必要があります。CARRAY1
フィールドのオカレンス・カウントが2
に設定されていること、C
フラグが設定されて追加のカウント要素の作成が定義されていることに注目してください。また、L
フラグが設定され、アプリケーションがCARRAY1
フィールドを格納するときの文字数を示す長さ要素が定義されています。
$ /* View structure */
$ /* View structure */
VIEW empname
#TYPE CNAME FBNAME COUNT FLAG SIZE NULL
string fname EMP_FNAME 1 - 25 -
char minit EMP_MINIT 1 - - -
string lname EMP_LNAME 1 - 25 -
END
$
VIEW MYVIEW
#type cname fbname count flag size null
float float1 FLOAT1 1 - - 0.0
double double1 DOUBLE1 1 - - 0.0
long long1 LONG1 1 - - 0
short short1 SHORT1 1 - - 0
int int1 INT1 1 - - 0
dec_t dec1 DEC1 1 - 9,16 0
char char1 CHAR1 1 - - '\0'
string string1 STRING1 1 - 20 '\0'
carray carray1 CARRAY1 2 CL 20 '\0'
bool bool1 BOOL1 1 - - 0
signedchar signedchar1 SIGNEDCHAR1 1 - - 0
unsignedchar unsignedchar1 UNSIGNEDCHAR1 1 - - 0
wchar_t wchar_t1 WCHAR_T1 1 - - 0
unsignedint unsignedint1 UNSIGNEDINT1 1 - - 0
unsignedlong unsignedlong1 UNSIGNEDLONG1 1 - - 0
longlong longlong1 LONGLONG1 1 - - 0
unsignedlonglong unsignedlonglong1 UNSIGNEDLONGLONG1 1 - - 0
longdouble longdouble1 LONGDOUBLE1 1 - - 0
struct empname ename 1 - - 0
END
リスト2-12は、同じVIEW記述ファイルで非依存型VIEW
のものを示しています。
$ /* View structure */
VIEW empname
#TYPE CNAME FBNAME COUNT FLAG SIZE NULL
string fname - 1 - 25 -
char minit - 1 - - -
string lname - 1 - 25 -
END
$
VIEW MYVIEW
#type cname fbname count flag size null
float float1 - 1 - - 0.0
double double1 - 1 - - 0.0
long long1 - 1 - - 0
short short1 - 1 - - 0
int int1 - 1 - - 0
dec_t dec1 - 1 - 9,16 0
char char1 - 1 - - '\0'
string string1 - 1 - 20 '\0'
carray carray1 - 2 CL 20 '\0'
bool bool1 - 1 - - 0
signedchar signedchar1 - 1 - - 0
unsignedchar unsignedchar1 - 1 - - 0
wchar_t wchar_t1 - 1 - - 0
unsignedint unsignedint1 - 1 - - 0
unsignedlong unsignedlong1 - 1 - - 0
longlong longlong1 - 1 - - 0
unsignedlonglong unsignedlonglong1 - 1 - - 0
longdouble longdouble1 - 1 - - 0
struct empname ename 1 - - 0
END
この形式はFML
依存型VIEWと同じです。ただし、fbname
フィールドとnull
フィールドには意味がなく、viewcコンパイラで無視されます。これらのフィールドには、プレースホルダーとしてダッシュ(-)などの値を挿入する必要があります。
VIEW
型バッファをコンパイルするには、引数としてVIEW記述ファイルの名前を指定してviewc
コマンドを実行します。非依存型VIEW
を指定するには、-n
オプションを使用します。生成される出力ファイルを書き込むディレクトリを指定することもできます(オプション)。デフォルトでは、出力ファイルはカレント・ディレクトリに書き込まれます。
たとえば、FML
依存型VIEW
をコンパイルするには、次のようにコンパイラを実行します。
viewc myview.v
注意: | VIEW32 型バッファをコンパイルするには、viewc32 コマンドを実行します。 |
非依存型VIEW
の場合、コマンドラインで次のように-n
オプションを指定します。
viewc -n myview.v
リスト2-13は、viewc
によって作成されるヘッダー・ファイルの例を示しています。
/* View structure */
struct empname {
char fname[25]; /* null="\0" */
char minit; /* null='\0' */
char lname[25]; /* null="\0" */
};
struct MYVIEW {
float float1; /* null=0.000000 */
double double1; /* null=0.000000 */
long long1; /* null=0 */
short short1; /* null=0 */
long int1; /* null=0 */
dec_t dec1; /* null=0.0 */
char char1; /* null='\0' */
char string1[20]; /* null="\0" */
unsigned long L_carray1[2]; /* length array of carray1 */
long C_carray1; /* count of carray1 */
char carray1[2][20]; /* null="\0" */
char bool1; /* null= */
signed char signedchar1; /* null="" */
unsigned char unsignedchar1; /* null="" */
wchar_t wchar_t1; /* null= */
unsigned int unsignedint1; /* null= */
unsigned long unsignedlong1; /* null=0 */
long long longlong1; /* null= */
unsigned long long unsignedlonglong1; /* null= */
long double longdouble1; /* null= */
struct empname ename; /* null= */
};
FML依存型とFML非依存型VIEWにも、同じヘッダー・ファイルが生成されます。
クライアント・プログラムまたはサービス・サブルーチンでVIEW
型バッファを使用するには、アプリケーションの#include
文にヘッダー・ファイルを指定する必要があります。
FML
ヘッダー・ファイルを作成して、アプリケーションの#include
文に指定します。 FML
関数は、フィールド化バッファからC構造体への変換、またその逆の変換など、型付きバッファを操作する場合に使用します。これらの関数を使用すると、データ構造やデータの格納状態がわからなくても、データ値にアクセスしたり更新できます。FML
関数の詳細は、『Oracle Tuxedo ATMI FML関数リファレンス』を参照してください。
アプリケーション・プログラムでFML型バッファを使用するには、表2-8の環境変数を設定します。
FML
型バッファやFML
依存型VIEW
を使用する場合は、常にフィールド表ファイルが必要です。フィールド表ファイルは、FML
型バッファのフィールドの論理名をそのフィールドをユニークに識別する文字列にマッピングします。
$ /* FML structure */
*basevalue
name number type flags comments
表2-9は、FML
フィールド表ファイルに指定する必要があるFML
フィールドを示しています。
すべてのフィールドは省略可能です。また、複数個使用できます。
リスト2-14は、FML依存型VIEWの例で使用されるフィールド表ファイルを示しています。
# name number type flags comments
EMP_FNAME 101 string - -
EMP_MINIT 102 char - -
EMP_LNAME 103 string - -
#
FLOAT1 110 float - -
DOUBLE1 111 double - -
LONG1 112 long - -
SHORT1 113 short - -
INT1 114 long - -
DEC1 115 string - -
CHAR1 116 char - -
STRING1 117 string - -
CARRAY1 118 carray - -
BOOL1 119 char - -
SIGNEDCHAR1 120 char - -
UNSIGNEDCHAR1 121 char - -
WCHAR_T1 122 long - -
UNSIGNEDINT1 123 long - -
UNSIGNEDLONG1 124 long - -
LONGLONG1 125 long - -
UNSIGNEDLONGLONG1 126 long - -
LONGDOUBLE1 127 double - -
ename 128 fml32 - -
クライアント・プログラムやサービス・サブルーチンでFML
型バッファを使用するには、FML
ヘッダー・ファイルを作成して、アプリケーションの#include
文にそのヘッダー・ファイルを指定する必要があります。
フィールド表ファイルからFML
ヘッダー・ファイルを作成するには、mkfldhdr(1)
コマンドを使用します。たとえば、myview.flds.h
というファイルを作成するには、次のコマンドを入力します。
mkfldhdr myview.flds
FML32
型バッファの場合は、mkfldhdr32
コマンドを使用します。
リスト2-15は、mkfldhdr
コマンドによって作成されるmyview.flds.h
ヘッダー・ファイルを示しています。
/* fname fldid */
/* ----- ----- */
#define EMP_FNAME ((FLDID32)167772261) /* number: 101 type: string */
#define EMP_MINIT ((FLDID32)67108966) /* number: 102 type: char */
#define EMP_LNAME ((FLDID32)167772263) /* number: 103 type: string */
#define FLOAT1 ((FLDID32)100663406) /* number: 110 type: float */
#define DOUBLE1 ((FLDID32)134217839) /* number: 111 type: double */
#define LONG1 ((FLDID32)33554544) /* number: 112 type: long */
#define SHORT1 ((FLDID32)113) /* number: 113 type: short */
#define INT1 ((FLDID32)33554546) /* number: 114 type: long */
#define DEC1 ((FLDID32)167772275) /* number: 115 type: string */
#define CHAR1 ((FLDID32)67108980) /* number: 116 type: char */
#define STRING1 ((FLDID32)167772277) /* number: 117 type: string */
#define CARRAY1 ((FLDID32)201326710) /* number: 118 type: carray */
#define BOOL1 ((FLDID32)67108983) /* number: 119 type: char */
#define SIGNEDCHAR1 ((FLDID32)67108984) /* number: 120 type: char */
#define UNSIGNEDCHAR1 ((FLDID32)67108985) /* number: 121 type: char */
#define WCHAR_T1 ((FLDID32)33554554) /* number: 122 type: long */
#define UNSIGNEDINT1 ((FLDID32)33554555) /* number: 123 type: long */
#define UNSIGNEDLONG1 ((FLDID32)33554556) /* number: 124 type: long */
#define LONGLONG1 ((FLDID32)33554557) /* number: 125 type: long */
#define UNSIGNEDLONGLONG1 ((FLDID32)33554558) /* number: 126 type: long */
#define LONGDOUBLE1 ((FLDID32)134217855) /* number: 127 type: double */
#define ename ((FLDID32)335544448) /* number: 128 type: fml32 */
アプリケーションの#include
文に新しいヘッダー・ファイルを指定します。ヘッダー・ファイルがインクルードされると、シンボリック名でフィールドを参照できるようになります。
XMLがデータ標準として受け入れられるに伴い、アプリケーションでXML型付きバッファを使用するOracle Tuxedoユーザーが増加しています。この動きを後押しするため、Oracle TuxedoソフトウェアではApache Xerces C++バージョン2.5パーサーが統合されました。
XMLバッファを使用すると、Oracle TuxedoアプリケーションでXMLを使用して、アプリケーション内やアプリケーション間でデータを交換できるようになります。Oracle Tuxedoアプリケーションでは、単純XML型バッファの送受信や、それらのバッファを適切なサーバーにルーティングできます。解析など、XMLドキュメントのすべての処理ロジックはアプリケーション側にあります。
XML
型バッファのプログラミング・モデルは、CARRAY
型バッファのモデルと類似しています。tpalloc()関数を使用して、バッファの長さを指定する必要があります。最大4 GBのXML文書がサポートされます。
イベント処理で行われるフォーマット処理とフィルタ処理は、STRING型バッファが使用されている場合はサポートされますが、XML型バッファではサポートされません。そのため、XML型バッファのバッファ・タイプ・スイッチ内の_tmfilter
関数と_tmformat
関数のポインタは、NULLに設定されます。
Oracle TuxedoシステムのXMLパーサーは、次の操作を行います。
XML型バッファでは、データ依存型ルーティングがサポートされています。XML文書のルーティングは、要素の内容、または要素タイプと属性値に基づいて行われます。使用される文字エンコードはXMLパーサーによって判別されます。エンコードがOracle Tuxedoの構成ファイル(UBBCONFIG
とDMCONFIG
)で使用されているネイティブな文字セット(US-ASCIIまたはEBCDIC)と異なる場合、要素と属性名はUS-ASCIIまたはEBCDICに変換されます。
XMLドキュメントには、ルーティング用に構成する属性を含めなければなりません。属性がルーティング基準として構成されていてもXMLドキュメントに含まれていない場合、ルーティング処理は失敗します。
要素の内容と属性値は、ルーティング・フィールド値の構文とセマンティクスに従っていることが必要です。また、ルーティング・フィールド値のタイプも指定しなければなりません。XMLでサポートされるのは文字データだけです。範囲フィールドが数値の場合、そのフィールドの内容や値はルーティング処理時に数値に変換されます。
Xerces-C++ 2.5.0パーサーは、移植可能なC++サブセットで記述され、XML文書を解析、生成、操作、および検証するための共有ライブラリを備えています。これは、XML 1.0勧告および関連する規格に準拠します: DOM 1.0、DOM 2.0、SAX 1.0、SAX 2.0、ネームスペースおよびW3CのXMLスキーマ勧告バージョン1.0。
Xerces-C++ 1.7パーサーは、検証が必要なときに文書型定義(DTD)とXMLスキーマ・ファイルをキャッシュせず、DTDで使用される外部エンティティ・ファイルもキャッシュしません。Oracle Tuxedo 8.1では、Webで繰り返し取得される外部DTD、スキーマ、およびエンティティ・ファイルをキャッシュするオプションを追加することによってXerces-C++ 1.7パーサーのパフォーマンスが向上ました。この変更の継続的なサポートは、Tuxedo 9.xおよびXerces C++ 2.5.0で使用可能です。
Xerces-C++パーサーのキャッシュ機能を有効または無効にする方法は次の2通りです。
注意: | これらの4つのメソッドは、Apache Xerces-C++パーサーに加えられたOracle Tuxedoの拡張機能です。次の2つのXercesオブジェクトと組み合せて排他的に使用されます。 |
Oracle Tuxedo配布キットには、様々なプラットフォーム上で200種類を超えるエンコード文字セット(エンコード形式)をサポートするC/C++ライブラリ、International Components for Unicode (ICU) 3.0ライブラリが付属しています。Xerces-C++ 2.5.0パーサーは、ICU 3.0ライブラリと共に構築されます。
Xerces-C++パーサーATMI関数を使用するためのサンプル・アプリケーションは、Oracle Tuxedoユーザー・ドキュメントに記載されています。このサンプルには、Xerces-C++パーサーのラッパーを記述して、Cで記述されたTuxedoクライアントおよびサーバーからXerces-C++ ATMI関数を呼び出せるようにするための方法が示されています。
XercesパーサーでXMLスキーマを使用するためのサンプル・アプリケーションは、Oracle Tuxedoのドキュメントに記載されています。『Oracle Tuxedo ATMIアプリケーション開発のためのチュートリアル』の「xmlfmlapp(完全なC XML/FML32変換アプリケーション)のチュートリアル」を参照してください。
getURLEntityCacheDir(3c)、setURLEntityCacheDir(3c)、getURLEntityCaching(3c)、setURLEntityCaching(3c)、Xerces APIパーサーのオンライン・ドキュメント
入力/出力形式として、XMLデータは、現在のアプリケーション開発で幅広く使用されています。一方、ほとんどのTuxedoカスタマは、望ましいデータ・トランスポートとしてTuxedo FML/FML32バッファを使用する既存の定義済サービスに多額の投資を行っています。
Oracle Tuxedoは、XMLとFML/FML32バッファ間のデータ変換が可能な機能を追加して、この問題に対処します。この変換は、次のいずれかの方法で開始できます。
プログラマ用に、XMLデータとFML/FML32バッファ間のオンデマンド変換では、手動変換用に新しいATMI関数が4つ用意されています。詳細は、「オンデマンド変換の使い方」を参照してください。
アプリケーション開発者用に、XMLとFML/FML32バッファ間の自動変換では、UBBCONFIG
構成ファイルのSERVICES
セクションに新しいBUFTYPECONV
パラメータが用意されています。自動変換では、サーバーの起動時に変換が開始されます。詳細については、「自動変換の使い方」を参照してください。
変換に使用されるメソッドに関係なく、FML/FML32フィールド型は、特定の方法でXMLにマッピングされます。変換マッピングの詳細は、「XMLとFML/FML32フィールド型のマッピング」を参照してください。
注意: | XMLとFML/FML32間の変換では、サイズが大きくなる可能性があるサード・パーティ・ライブラリ(libticudata.soなど)を使用します。 |
注意: | 共有ライブラリのサイズが大きくなると、そのライブラリに直接または間接的に依存する、Tuxedoアプリケーションで実行中のプロセスが多くのメモリーを消費し、その結果、パフォーマンスが低下する可能性があります。 |
注意: | XMLとFML/FML32間の変換機能は、Tuxedoシステム・プロセスでは使用しないでください。 |
注意: | Xercesパーサーを使用したXMLとFML/FML32バッファ間の変換の制限に関するその他の既知の問題については、「変換の制限事項」を参照してください。 |
オンデマンド変換では、XMLデータからFML/FML32バッファまたはFML/FML32バッファからXMLデータへの変換を手動で実行できます。
次の4つのATMI関数では、オンデマンド変換を実行できます。
これらの関数と引数の詳細な説明については、『Oracle Tuxedo ATMI C関数リファレンス』を参照してください。
XMLデータとFML/FML32バッファ間のオンデマンド変換を実行するには、次の手順に従います。
ATMI関数を使用してXMLとFML/FML32バッファ間の変換を開始する場合は、次のいずれかの方法でパーサー検証が決定されます。
ATMI関数とそのXercesパーサーのflag引数の詳細な説明については、『Oracle Tuxedo ATMI C関数リファレンス』を参照してください。
自動変換では、最初の形式も最後の形式もXMLになります。つまり、XMLバッファがFML/FML32バッファに入力、変換、および処理され、最後にXMLに再変換されます。
XMLとFML/FML32バッファ間の変換を開始するには、UBBCONFIG
ファイルのSERVICES
セクションのBUFTYPECONV
パラメータを指定する必要があります。このパラメータは、XML2FML
またはXML2FML32
のどちらかの値のオプションのみを受け付けます。
このパラメータを使用してサーバーを起動した場合、クライアントtpcall()
、tpacall()
、tpconnect()
、またはtpsend()
によって入力バッファがXMLバッファからFML/FML32バッファに変換されてからサービスに送られます。tpreturn()
またはtpsend()
が呼び出されると、FML/FML32バッファがXMLバッファに変換されてから返されます。
BUFTYPECONV
パラメータを使用しているサービスでは、クライアントまたはその他のサービスは、既存のサービスがFML/FML32バッファを処理する方法を変更することなく、XMLバッファを送受信できます。
注意: | BUFTYPECONV パラメータを使用する場合は、以下の項目に注意してください。 |
BUFTYPECONV
パラメータを使用している場合、出力されたすべてのFML/FML32バッファはXMLに変換されます。BUFTYPECONV
パラメータを使用して新しいサービス名を作成すると、XMLを出力し、FML/FML32バッファに対する元のサービス名を保持することができます。BUFTYPECONV
で指定されている場合でも変換されません。サーバー
として機能する場合のみです。つまり、クライアントまたは他のサービスが、BUFTYPECONV
パラメータを使用してサービスにリクエストを行う場合です。 BUFTYPECONV
パラメータを使用しているサービスがクライアントとして動作している場合、変換は実行されません。たとえば、別のサービスに対してtpcall()
を使用しているBUFTYPECONV
パラメータが指定されたサービスなどが挙げられます。/Q
メッセージング・モードでは、TMQFORWARD
はサービスの呼出しにtpcall()
を使用します。呼び出されたサービスがBUFTYPECONV
パラメータを使用している場合、自動変換が実行されます。 自動変換の際に、入力XMLルート要素名を保存することはできないため、出力XMLルート・タグは、デフォルト・ルート・タグ<FML Type="FML">
または<FML Type="FML32">
を使用します。
XMLデータとFML/FML32バッファ間の自動変換を実行するには、次の手順に従います。
Xercesパーサーは、デフォルトの属性設定を使用して、自動変換時のXML検証を制御します。ただし、Tuxedoでは14個の固有のXerces DOMParserクラス属性をサポートしており、これらを使用することで自動変換を多少柔軟にカスタマイズできます。
自動変換メソッドを使用している場合、パーサー検証は以下のいずれかの方法で決定されます。
TPXPARSFILE
環境変数で検証オプションを指定する TPXPARSFILE
環境変数は、変更したいXercesDOMParserクラス属性設定を含むテキスト・ファイルへの完全修飾パスを示します。
テキスト・ファイルの各属性は、次の形式で別の行に記述されます。
<parser attribute>=<setting>
<parser attribute>
には、次の表の14個のパーサー属性の一部または全部を指定できます((D)はデフォルト設定を示します)。
注意: | これらの属性の詳細は、Xercesパーサー2.5.0のドキュメントを参照してください。 |
リスト2-16は、TPXPARSFILE
環境変数のサンプル入力プレーン・テキスト・ファイルです。
CacheGrammarFromParse=True
DoNameSpaces=True
DoSchema=True
ExternalSchemaLocation= http://www.xml.org/sch.xsd
ExitOnFirstFatalError=c:\xml\example.xsd
IncludeIgnorableWhiteSpace=True
LoadGrammar=
NoNamespaceSchemaLocation=
StandardUriConformant=True
UseCachedGrammarInParse=True
UseScanner=WF
ValidationConstraintFatal=True
ValidationScheme=Val_Auto
ValidationSchemaFullChecking=True
XML形式とFML/FML32フィールド間の関係では、XML要素名はFML/FML32フィールド名と同じですが、XML値は対応するフィールド型をもとに解釈されます。
開始および終了タグは、フィールドの名前を使用します。属性は、必要に応じてFLD_FML32、FLD_MBSTRING
とFLD_VIEW32
で提供されます。フィールド名と属性の大文字と小文字は区別されます。
フィールド値は文字列として読み取られ、以下のフィールド型に変換されます。
<FIELDNAME Attribute="Attribute Value"> FIELDVALUE </FIELDNAME>
FML/FML32フィールド型は、次のようにXMLバッファ型にマッピングされます。
XMLへの変換時に、 FML32への変換時に、 |
||||
FLD_FML32 フィールド名は、FMLフィールド名に基づいて開始および終了タグでサポートされます。このXMLドキュメントには、バッファに含まれるフィールドごとに<fieldname>value</fieldname> の複数の説明が含まれます。
|
||||
FLD_MBSTRING フィールド変換は、Encoding属性、およびFML32フィールドを記述するためのフィールド・データを使用します。この変換は、Fmbpack32 を使用した場合と同じです。次の条件に注意してください。
|
Tuxedoで提供されているXerces 2.5.0パーサーを使用したXMLデータとFML/FML32バッファ間の変換には、次の制限事項があります。
<FML Type="FML">
または<FML Type="FML32">
が使用されます。
中国語、日本語、韓国語、およびその他のアジア太平洋言語で必要とされるマルチバイト・エンコード文字セットをサポートするために、Oracle Tuxedoには、マルチバイト文字のユーザー・データをトランスポートするためのMBSTRING型付きバッファが用意されています。中国語、日本語、韓国語、およびその他のアジア太平洋言語では、文字を表現するために複数バイトを使用するエンコード文字セットが使用されます。
MBSTRING型付きバッファおよびマルチバイト文字エンコード機能を使用すると、Oracle Tuxedoシステムは、プロセス間でMBSTRINGバッファ(またはFML32バッファのFLD_MBSTRING
フィールド)が転送されるときに、ユーザー・データを別のエンコード表現に変換できます。図2-1は、エンコード変換がどのように行われるかを例示しています。
上図の例に示すように、MBSTRING型付きバッファは、ユーザー・データのコード・セット文字エンコード(または単にエンコード)を識別する情報を保持できます。この例では、クライアントのリクエストのMBSTRINGバッファは、Shift-JIS (SJIS)エンコードで表される日本語ユーザー・データを保持し、サーバーの応答のMBSTRINGバッファは、Extended UNIX Code (EUC)エンコードで表される日本語ユーザー・データを保持しています。マルチバイト文字エンコード機能では、環境変数TPMBENC
とTPMBACONV
を読み込んで、ソースのエンコード、ターゲットのエンコード、および自動エンコード変換の状態(有効または無効)を判別します。
エンコードの変換機能により、基底のTuxedoシステム・ソフトウェアでは、着信メッセージのエンコード表現を、受信プロセスが実行されているマシンでサポートされているエンコード表現に変換できます。この変換は文字コード・セット間の変換でも言語の翻訳でもなく、同じ言語の異なる文字エンコード間の変換です。
次の2つのフローチャートでは、MBSTRINGバッファの割り当て、送信、受信、および変換時に環境変数およびATMIがどのように使用されるかを示します。
sendlen
がゼロに設定されている場合、MBSTRING
を自己記述型にすることができます。一部のTuxedoバッファでは、ユーザーがバッファの長さを指定していない場合、バッファが長さを自己決定できます。この自己記述型の動作は、アプリケーションが、Tuxedo関数呼出し(tpcall()
など)のsendlen
引数をゼロに設定したときにトリガーされます。
_mbspresend()
を追加するには、Tuxedoバッファをカスタマイズするユーザーがアプリケーションを再ビルドする必要があります。
TPMBENC
で指定する安全または危険なエンコード名という考えは、これらのエンコードのマルチバイト文字データにNULLが埋め込まれているかどうかで決まります。_mbspresend()
関数はstrlen()
を使用してデータの長さを決めるので、NULLが埋め込まれていると、データの長さが不適切になり、誤ったデータ・バイト数が送られてしまいます。
sendlen0_unsafe_tpmbenc
のデフォルト・リストには、NULLが埋め込まれている可能性がある(便宜上、大文字および小文字の)マルチバイトUnicodeエンコード名があります。アプリケーション管理またはパフォーマンスを考慮すると、このリストを変更する必要があります。
MBSTRING
自己記述処理ですべてのエンコード名が安全なものとみなされます。MBSTRING
自己記述処理ですべてのエンコード名が危険なものとみなされます(tperrno
はTPEINVAL
になります)。_mbsinit()
で)一度読み取られ、Tuxedoの内部にリストが格納されます。mbsinit()
の実行中に、格納されているリストとTPMBENC
名が比較され、バッファが安全または危険に設定されます。_mbspresend()
が呼び出され(sendlen
引数がゼロに設定されている状態)、バッファが安全とマークされると、データの長さはTuxedoの内部で設定されます。Oracle Tuxedoのマルチバイト文字サポートには、以下の制限が存在します。
MBSTRING
とFLD_MBSTRING
をサポートするTuxedo APIに相当するCOBOL APIは存在しません。 Oracle Tuxedo 8.1以降のソフトウェア配布キットには、多くのエンコード文字セットとエンコードをサポートするエンコード変換ライブラリであるlibiconv
が付属しています。マルチバイト文字エンコードの機能では、このライブラリの文字変換関数を使用して、サポートされている任意の文字エンコードから別の文字エンコードにUnicode変換を通じて変換できます。
マルチバイト文字エンコードの詳細は、次のドキュメントを参照してください。
Oracle Tuxedoシステムで提供されるバッファ・タイプでは、アプリケーションのニーズが満たされない場合があります。たとえば、アプリケーションがフラットではないデータ構造体、つまりSQLデータベースの問合せのための解析ツリーなど、ほかのデータ構造体へのポインタを持つデータ構造を扱う場合があります。アプリケーション固有の要件に対応するために、Oracle Tuxedoシステムではカスタム・バッファがサポートされています。
バッファをカスタマイズするには、表2-10の特性を理解しておく必要があります。
表 2-11は、各バッファ・タイプに指定する必要があるルーチンを示しています。特定のルーチンが必要ない場合は、NULLポインタを指定します。必要に応じて、Oracle Tuxedoシステムでデフォルトの処理が行われます。
領域の割当てと解放、メッセージの送受信など、バッファを操作するコードを記述するのはアプリケーション・プログラマです。デフォルトのバッファ・タイプではアプリケーションのニーズを満たすことができない場合、ほかのバッファ・タイプを定義し、新しいルーチンを記述してバッファ・タイプ・スイッチに組み込むことができます。
静的ライブラリが使用されるアプリケーションで、カスタム・バッファ・タイプ・スイッチを使う場合は、カスタム・サーバーをビルドして、新しいタイプ・スイッチにリンクする必要があります。詳細は、buildwsh
(1)、TMQUEUE
(5)、TMQFORWARD
(5)を参照してください。
ここでは、前述の手順に従って、共有オブジェクトまたはDLL環境で新しいバッファ・タイプを定義します。最初に、Oracle Tuxedoシステム・ソフトウェアに提供されているバッファ・スイッチを参照してみます。リスト2-17は、システムに提供されているスイッチです。
#include <stdio.h>
#include <tmtypes.h>
/*
* Initialization of the buffer type switch.
*/
struct tmtype_sw_t tm_typesw[] = {
{
"CARRAY", /* type */
"*", /* subtype */
0 /* dfltsize */
NULL, /* initbuf */
NULL, /* reinitbuf */
NULL, /* uninitbuf */
NULL, /* presend */
NULL, /* postsend */
NULL, /* postrecv */
NULL, /* encdec */
NULL, /* route */
NULL, /* filter */
NULL, /* format */
NULL, /* presend2 */
NULL /* multibyte code-set encoding conversion */
},
{
"STRING", /* type */
"*", /* subtype */
512, /* dfltsize */
NULL, /* initbuf */
NULL, /* reinitbuf */
NULL, /* uninitbuf */
_strpresend, /* presend */
NULL, /* postsend */
NULL, /* postrecv */
_strencdec, /* encdec */
NULL, /* route */
_sfilter, /* filter */
_sformat, /* format */
NULL, /* presend2 */
NULL /* multibyte code-set encoding conversion */
},
{
"FML", /* type */
"*", /* subtype */
1024, /* dfltsize */
_finit, /* initbuf */
_freinit, /* reinitbuf */
_funinit, /* uninitbuf */
_fpresend, /* presend */
_fpostsend, /* postsend */
_fpostrecv, /* postrecv */
_fencdec, /* encdec */
_froute, /* route */
_ffilter, /* filter */
_fformat, /* format */
NULL, /* presend2 */
NULL /* multibyte code-set encoding conversion */
},
{
"VIEW", /* type */
"*", /* subtype */
1024, /* dfltsize */
_vinit, /* initbuf */
_vreinit, /* reinitbuf */
NULL, /* uninitbuf */
_vpresend, /* presend */
NULL, /* postsend */
NULL, /* postrecv */
_vencdec, /* encdec */
_vroute, /* route */
_vfilter, /* filter */
_vformat, /* format */
NULL, /* presend2 */
NULL /* multibyte code-set encoding conversion */
},
{
/* XATMI - identical to CARRAY */
"X_OCTET", /* type */
"*", /* subtype */
0 /* dfltsize */
},
{ /* XATMI - identical to VIEW */
{'X','_','C','_','T','Y','P','E'}, /* type */
"*", /* subtype */
1024, /* dfltsize */
_vinit, /* initbuf */
_vreinit, /* reinitbuf */
NULL, /* uninitbuf */
_vpresend, /* presend */
NULL, /* postsend */
NULL, /* postrecv */
_vencdec, /* encdec */
_vroute, /* route */
_vfilter, /* filter */
_vformat, /* format */
NULL, /* presend2 */
NULL /* multibyte code-set encoding conversion */
},
{
/* XATMI - identical to VIEW */
{'X','_','C','O','M','M','O','N'}, /* type */
"*", /* subtype */
1024, /* dfltsize */
_vinit, /* initbuf */
_vreinit, /* reinitbuf */
NULL, /* uninitbuf */
_vpresend, /* presend */
NULL, /* postsend */
NULL, /* postrecv */
_vencdec, /* encdec */
_vroute, /* route */
_vfilter, /* filter */
_vformat, /* format */
NULL, /* presend2 */
NULL /* multibyte code-set encoding conversion */
},
{
"FML32", /* type */
"*", /* subtype */
1024, /* dfltsize */
_finit32, /* initbuf */
_freinit32, /* reinitbuf */
_funinit32, /* uninitbuf */
_fpresend32, /* presend */
_fpostsend32, /* postsend */
_fpostrecv32, /* postrecv */
_fencdec32, /* encdec */
_froute32, /* route */
_ffilter32, /* filter */
_fformat32, /* format */
_fpresend232, /* presend2 */
_fmbconv32 /* multibyte code-set encoding conversion */
},
{
"VIEW32", /* type */
"*", /* subtype */
1024, /* dfltsize */
_vinit32, /* initbuf */
_vreinit32, /* reinitbuf */
NULL, /* uninitbuf */
_vpresend32, /* presend */
NULL, /* postsend */
NULL, /* postrecv */
_vencdec32, /* encdec */
_vroute32, /* route */
_vfilter32, /* filter */
_vformat32, /* format */
NULL, /* presend2 */
_vmbconv32, /* multibyte code-set encoding conversion */
},
{
"XML", /* type */
"*", /* subtype */
0, /* dfltsize */
NULL, /* initbuf */
NULL, /* reinitbuf */
NULL, /* uninitbuf */
NULL, /* presend */
NULL, /* postsend */
NULL, /* postrecv */
NULL, /* encdec */
_xroute, /* route */
NULL, /* filter */
NULL, /* format */
NULL, /* presend2 */
NULL /* multibyte code-set encoding conversion */
},
{
"MBSTRING", /* type */
"*", /* subtype */
0, /* dfltsize */
_mbsinit, /* initbuf */
NULL, /* reinitbuf */
NULL, /* uninitbuf */
_mbspresend, /* presend */
NULL, /* postsend */
NULL, /* postrecv */
NULL, /* encdec */
NULL, /* route */
NULL, /* filter */
NULL, /* format */
NULL, /* presend2 */
_mbsconv /* multibyte code-set encoding conversion */
},
{
""
}
};
struct tmtype_sw_t _TM_FAR *
_TMDLLENTRY
_tmtypeswaddr(void)
{
return(tm_typesw);
}
この例をよく理解できるように、リスト2-18に示すバッファ・タイプ構造体の宣言を参照してください。
/*
* The following definitions are in $TUXDIR/include/tmtypes.h
*/
#define TMTYPELEN ED_TYPELEN
#define TMSTYPELEN ED_STYPELEN
struct tmtype_sw_t {
char type[TMTYPELEN]; /* type of buffer */
char subtype[TMSTYPELEN]; /* subtype of buffer */
long dfltsize; /* default size of buffer */
/* buffer initialization function pointer */
int (_TMDLLENTRY *initbuf) _((char _TM_FAR *, long));
/* buffer reinitialization function pointer */
int (_TMDLLENTRY *reinitbuf) _((char _TM_FAR *, long));
/* buffer un-initialization function pointer */
int (_TMDLLENTRY *uninitbuf) _((char _TM_FAR *, long));
/* pre-send buffer manipulation func pointer */
long (_TMDLLENTRY *presend) _((char _TM_FAR *, long, long));
/* post-send buffer manipulation func pointer */
void (_TMDLLENTRY *postsend) _((char _TM_FAR *, long, long));
/* post-receive buffer manipulation func pointer*/
long (_TMDLLENTRY *postrecv) _((char _TM_FAR *, long, long));
/* XDR encode/decode function pointer */
long (_TMDLLENTRY *encdec) _((int, char _TM_FAR *, long, char _TM_FAR *, long));
/* routing function pointer */
int (_TMDLLENTRY *route) _((char _TM_FAR *, char _TM_FAR *, char _TM_FAR *,
long, char _TM_FAR *));
/* buffer filtering function pointer */
int (_TMDLLENTRY *filter) _((char _TM_FAR *, long, char _TM_FAR *, long));
/* buffer formatting function pointer */
int (_TMDLLENTRY *format) _((char _TM_FAR *, long, char _TM_FAR *,
char _TM_FAR *, long));
/* process buffer before sending, possibly generating copy */
long (_TMDLLENTRY *presend2) _((char _TM_FAR *, long,
long, char _TM_FAR *, long, long _TM_FAR *));
/* Multibyte code-set encoding conversion function pointer*/
long (_TMDLLENTRY *mbconv) _((char _TM_FAR *, long,
char _TM_FAR *, char _TM_FAR *, long, long _TM_FAR *));
/* this space reserved for future expansion */
void (_TMDLLENTRY *reserved[8]) _((void));
};
/*
* application types switch pointer
* always use this pointer when accessing the table
*/
extern struct tmtype_sw_t *tm_typeswp;
前述のデフォルト・バッファ・タイプ・スイッチの例は、バッファ・タイプ・スイッチの初期化を示しています。9つのデフォルト・バッファ・タイプの後に、サブタイプの名前を指定するフィールドがあります。VIEW
(X_C_TYPE
とX_COMMON
)型を除き、サブタイプはNULLです。VIEW
のサブタイプは``*''として指定されています。これは、デフォルトのVIEW
型のサブタイプに制約がないことを示します。つまり、VIEW
型のすべてのサブタイプは同じ方法で処理されます。
次のフィールドには、バッファのデフォルト(最小)サイズが指定されています。CARRAY
(X_OCTET
)型の場合、このフィールドに0が指定されています。これは、CARRAY
型バッファを使用するルーチンでは、CARRAY
型に必要な領域をtpalloc()
で割り当てなければならないことを示します。
それ以外のバッファ・タイプの場合、tpalloc()
が呼び出されて、dfltsize
フィールドに指定されている領域がOracle Tuxedoシステムによって割り当てられます。ただし、tpalloc()
のサイズを示す引数にこれより大きな値が設定されていない場合にかぎります。
バッファ・タイプ・スイッチのエントリで、残りの8つのフィールドには、スイッチ要素ルーチンの名前が指定されています。これらのルーチンの詳細は、『Oracle Tuxedo C関数リファレンス』のbuffer(3c)
を参照してください。ルーチン名からそのルーチンの処理内容がわかります。たとえば、FML
型の_fpresend
は、送信前にバッファを操作するルーチンを指すポインタです。送信前処理が必要ない場合は、NULLポインタを指定します。NULLは、特に処理が必要ないことを示し、その結果デフォルトの処理が行われます。詳細は、buffer(3c)
を参照してください。
スイッチの最後にNULLエントリがあることに注目してください。変更時には、配列の終わりに必ずNULLエントリを置いてください。
アプリケーションで新しいバッファ・タイプを定義するのは、特別な処理を行うためです。たとえば、アプリケーションで、次のプロセスにバッファを送信する前に、データ圧縮を何度か行うとします。このようなアプリケーションでは、送信前処理ルーチンを記述します。リスト2-19は、送信前処理ルーチンの宣言を示しています。
long
presend(ptr, dlen, mdlen)
char *ptr;
long dlen, mdlen;
送信前処理ルーチンで行うデータ圧縮は、アプリケーションのシステム・プログラマが行います。
ルーチンの処理が正常に終了した場合、同じバッファ内にある圧縮後の送信データの長さが返されます。処理が失敗した場合は、-1
が返されます。
プログラマが記述した送信前処理ルーチンには、Cコンパイラが使用できる任意の識別子を付けることができます。たとえば、_mypresend
という名前を付けます。
_mypresend
圧縮ルーチンを使用する場合、受信側にはそのデータの圧縮を解除する_mypostrecv
ルーチンが必要です。『Oracle Tuxedo Cリファレンス』のbuffer
(3c)に示すテンプレートを使用してください。
新しいスイッチ要素ルーチンを記述し、そのコンパイルに成功したら、そのバッファ・タイプ・スイッチに新しいバッファ・タイプを追加する必要があります。その場合、$TUXDIR/lib/tmtypesw.c
(デフォルトのバッファ・タイプ・スイッチのソース・コード)をコピーします。コピーしたファイル名に、mytypesw.c
など、拡張子として.c
を付けます。コピーしたファイルに新しいタイプを追加します。タイプ名は8文字以内で指定します。サブタイプには、NULL(""
)または16文字以内の文字列を指定できます。新しいスイッチ要素ルーチンの名前は、extern
宣言も含めて適切な場所に入力します。リスト2-20は、その例を示しています。
#include <stdio.h>
#include <tmtypes.h>
/* Customized the buffer type switch */
static struct tmtype_sw_t tm_typesw[] = {
{
"SOUND", /* type */
“", /* subtype */
50000, /* dfltsize */
snd_init, /* initbuf */
snd_init, /* reinitbuf */
NULL, /* uninitbuf */
snd_cmprs, /* presend */
snd_uncmprs, /* postsend */
snd_uncmprs /* postrecv */
},
{
"FML", /* type */
"", /* subtype */
1024, /* dfltsize */
_finit, /* initbuf */
_freinit, /* reinitbuf */
_funinit, /* uninitbuf */
_fpresend, /* presend */
_fpostsend, /* postsend */
_fpostrecv, /* postrecv */
_fencdec, /* encdec */
_froute, /* route */
_ffilter, /* filter */
_fformat /* format */
},
{
""
}
};
この例では、SOUND
という新しいタイプを追加しています。また、VIEW
、X_OCTET
、X_COMMON
、およびX_C_TYPE
のエントリを削除して、デフォルト・スイッチで不要なエントリを削除できることを示しています。配列の最後にNULLがあることに注目してください。
新しいバッファ・タイプを定義する別の方法は、既存のタイプを再定義することです。バッファ・タイプMYTYPE
に定義したデータ圧縮が文字列に対して実行されたとします。その場合、STRING
型の2つの_dfltblen
のかわりに、新しいスイッチ要素ルーチン_mypresend
と_mypostrecv
を使用できます。
インストールを簡単に行うには、バッファ・タイプ・スイッチを共有オブジェクトに格納します。
注意: | 一部のプラットフォームでは、「共有オブジェクト」ではなく「共有ライブラリ」という言葉が使用されています。Windows 2003プラットフォームでは、「共有オブジェクト」ではなく「動的リンク・ライブラリ」と呼ばれています。この3つの用語が示す機能は同じなので、ここでは「共有オブジェクト」を使用します。 |
ここでは、アプリケーション内のすべてのOracle Tuxedoプロセスに、変更後のバッファ・タイプ・スイッチを認識させる方法について説明します。これらのプロセスには、Oracle Tuxedoシステムで提供されるサーバーとユーティリティのほかに、アプリケーション・サーバーおよびアプリケーション・クライアントも含まれています。
$TUXDIR/lib/tmtypesw.c
をコピーして変更します。関数を追加する場合は、それらの関数をtmtypesw.c
に記述するか、別のCソース・ファイルに記述します。tmtypesw.c
をコンパイルします。libbuft.so.71
をカレント・ディレクトリから別のディレクトリにコピーします。コピー先のディレクトリとしては、アプリケーションがlibbuft.so.71を認識でき、Oracle Tuxedoシステムで提供されるデフォルトの共有オブジェクトより先にlibbuft.so.71が処理されるディレクトリを選択します。$APPDIR
または$TUXDIR/lib
ディレクトリ、または$TUXDIR/bin
(Windows 2003プラットフォームの場合)のいずれかを使用することをお薦めします。オペレーティング・システムの規則に従うために、プラットフォームが異なる場合は、バッファ・タイプ・スイッチ共有オブジェクトには異なる名前が使用されます。
共有オブジェクト・ライブラリのビルド方法については、お使いのプラットフォームのソフトウェア開発ドキュメントを参照してください。
別の方法として、すべてのクライアント・プロセスとサーバー・プロセスで新しいバッファ・タイプ・スイッチを静的にリンクすることもできます。ただし、この方法ではエラーが発生しやすくなり、効率も共有オブジェクト・ライブラリをビルドするより劣ります。
「新しいtm_typeswのコンパイルとリンク」で説明したように、Windowsプラットフォーム上でtmtypesw.c
を変更した場合、リスト2-21に示すコマンドを使用して、変更後のバッファ・タイプ・スイッチをアプリケーションから使用できるようにします。
CL -AL -I..\e\|sysinclu -I..\e\|include -Aw -G2swx -Zp -D_TM_WIN
-D_TMDLL -Od -c TMTYPESW.C
LINK /CO /ALIGN:16 TMTYPESW.OBJ, WBUFT.DLL, NUL, WTUXWS /SE:250 /NOD
/NOE LIBW LDLLCEW, WBUFT.DEF
RC /30 /T /K WBUFT.DLL
構成ファイルのMACHINES
セクションにあるTYPE
パラメータは、データ表現と使用するコンパイラが同じであるマシンをグループ化して、TYPE
が異なるマシン間でやり取りされるメッセージのデータが変換されるようにします。デフォルトのバッファ・タイプの場合、異なるマシン間でのデータ変換はユーザー、管理者、プログラマに対して透過的です。
アプリケーションで新しいバッファ・タイプを定義して、データ表現スキームが異なるマシン間でメッセージを交換する場合、新しいエンコード/デコード・ルーチンを記述して、バッファ・タイプ・スイッチに組み込む必要があります。独自のデータ変換ルーチンを記述する場合は、次のガイドラインに従ってください。
「buffer(3c)」
に示してある_tmencdecルーチンのセマンティクスを使用します。つまり、同じ引数を使用し、処理が成功した場合や失敗した場合に_tmencdecと同じ値が返されるようにルーチンをコーディングします。
新しいバッファ・タイプを定義する場合は、「独自のバッファ・タイプの定義」の手順に従って、新しいバッファ・タイプを使用するサービスを提供するサーバーをビルドします。 エンコード/デコード・ルーチンが呼び出されるのは、データをやり取りする2つのマシンのTYPE
が異なることがOracle Tuxedoシステムによって検出された場合だけです。