この付録では、TxRPCを使用した
rpcsimpと呼ばれる単一クライアント、単一サーバーで構成するアプリケーションについて解説します。この対話型アプリケーションのソース・ファイルは、Oracle Tuxedo ATMIソフトウェアとともに配布されていますが、RTK製品には含まれません。
このアプリケーション例を実行する前に、Oracle Tuxedoソフトウェアをインストールし、この付録で参照するファイルやコマンドが使用できるようにしておきます。
rpcsimpは、TxRPCを利用した非常に基本的なOracle Tuxedo ATMIアプリケーションです。このアプリケーションは、1つのクライアントと1つのサーバーで構成します。クライアントはリモート・プロシージャ・コール(オペレーション)
to_upper()と
to_lower()を呼び出します。これらのプロシージャ・コールは、いずれもサーバー内に実装されるものです。オペレーション
to_upper()は、文字列を小文字から大文字へ変換してクライアントに返します。一方
to_lower()は、文字列を大文字から小文字へ変換してクライアントに返します。各プロシージャ・コールが復帰すると、クライアントは文字列出力をユーザーの画面に表示します。
次に本プログラム例を構成、実行する手順を解説します。
rpcsimp用のディレクトリを作成し、そのディレクトリに移動します。
mkdir rpcsimpdir
cd rpcsimpdir
注意:
|
このようにしておくと、作業開始時にあった rpcsimp関連のファイルと、作業中に作成した新たなファイルを容易に把握できます。標準シェル( /bin/sh)またはKornシェルを使用してください。Cシェル( csh)は使わないでください。
|
TUXDIR=<
pathname of the Oracle Tuxedo System root directory>
TUXCONFIG=<
pathname of your present working directory>/TUXCONFIG
PATH=$PATH:$TUXDIR/bin
# SVR4, Unixware
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TUXDIR/lib
# HPUX
SHLIB_PATH=$LD_LIBRARY_PATH:$TUXDIR/lib
# RS6000
LIBPATH=$LD_LIBRARY_PATH:$TUXDIR/lib
export TUXDIR TUXCONFIG PATH LD_LIBRARY_PATH SHLIB_PATH LIBPATH
注意:
|
TUXDIRと PATHは、Oracle Tuxedo ATMIのディレクトリ構造内のファイルにアクセスし、Oracle Tuxedo ATMIコマンドを実行するのに必要です。構成ファイルがロードできるようにするには、 TUXCONFIGを設定する必要があります。共有オブジェクトを使用する場合、 LD_LIBRARY_PATH環境変数も設定します。
|
rpcsimp用のファイルをアプリケーション・ディレクトリにコピーします。
cp $TUXDIR/apps/rpcsimp/* .
一部のファイルを編集してから、実行形式ファイルを作成することがあるので、本ソフトウェアで提供されたオリジナルのファイルではなく、コピーしたファイルを用いて作業することをお薦めします。
$ ls
client.c
rpcsimp.mk
server.c
simp.idl
ubbconfig
wclient.def
wsimpdll.def
$
アプリケーションを構成するファイルは次のセクションで説明します。
[uuid(C996A680-9FC2-110F-9AEF-930269370000), version(1.0) ]
interface changecase
{
/* change a string to upper case */
void to_upper([in, out, string] char *str);
/* change a string to lower case */
void to_lower([in, out, string] char *str);
}
このファイルは2つのオペレーション(
to_upperと
to_lower)を持った単一インタフェース(
changecase version 1.0)を定義します。各オペレーションは、NULL (文字)で終わる文字列を入出力パラメータとして使用します。ACFフィルは提供されないので、状態変数は使用されず、クライアント・プログラムは例外処理を行う必要があります。各オペレーションには戻り値が生成されないことを示すためにvoidで宣言します。
simp.idlはスタブ関数の生成に使用されます(次を参照)。
クライアント・ソース・コード - client.c
#include <stdio.h>
#include "simp.h"
#include "atmi.h"
main(argc, argv)
int argc;
char **argv;
{
idl_char str[100];
unsigned char error_text[100];
int status;
if (argc > 1) {/* use command line argument if it exists */
(void) strncpy(str, argv[1], 100);
str[99] = '\0';
}
else
(void) strcpy(str, "Hello, world");
TRY
to_upper(str);
(void) fprintf(stdout, "to_upper returns: %s\n", str);
to_lower(str);
(void) fprintf(stdout, "to_lower returns: %s\n", str);
/* control flow continues after ENDTRY */
CATCH_ALL
exc_report(THIS_CATCH); /* print to stderr */
(void) tpterm();
exit(1);
ENDTRY
(void) tpterm();
exit(0);
}
ヘッダー・ファイル
simp.hは、
simp.idlを元にIDLコンパイラによって生成され、2つのオペレーション用の関数プロトタイプを持っています。
simp.hヘッダーには、RPCランタイム関数(本例には示されていません)用と例外処理用のヘッダー・ファイルも含まれます。関数
tpterm(3c)
が呼び出されるので、ヘッダー・ファイルatmi.hがインクルードされます。コマンド行に引数を指定すると、その引数は大文字や小文字への変換に使用されます(デフォルトでは"
hello world"になります)。例外処理はエラーの捕捉に使用されます。たとえば、サーバーが利用できない、メモリーを割り当てられない、通信できないなどの場合に例外が生成されます。
TRYブロックは、2つのリモート・プロシージャをカプセル化します。エラーが発生した場合、実行の制御は
CATCH_ALLブロックに移り、例外(
THIS_CATCH)を文字列に変換し、この文字列を
exc_reportを使用して標準エラー出力に表示して、終了します。アプリケーションを正しく終了するには、アプリケーションの実行が正常に行われた場合も、異常が発生した場合もともに、
tidl(1)が呼び出されていることに注意してください。これが行われないと、ワークステーション以外のクライアントでは、
userlog(3c)に警告が出力され、リソースが関連付けられたままになります。ワークステーション・クライアントでは、接続がタイムアウトするまでリソースが関連付けられたままになります。
#include <stdio.h>
#include <ctype.h>
#include "tx.h"
#include "simp.h"
int
tpsvrinit(argc, argv)
int argc;
char **argv;
{
if (tx_open() != TX_OK) {
(void) userlog("tx_open failed");
return(-1);
}
(void) userlog("tpsvrinit() succeeds.");
return(1);
}
void
to_upper(str)
idl_char *str;
{
idl_char *p;
for (p=str; *p != '\0'; p++)
*p = toupper((int)*p);
return;
}
void
to_lower(str)
idl_char *str;
{
idl_char *p;
for (p=str; *p != '\0'; p++)
*p = tolower((int)*p);
return;
}
client.cの場合と同様、このファイルでも
simp.hをインクルードします。
さらに、関数
tx_open(3c)
を呼び出すので、このファイルはtx.hもインクルードします(リソース・マネージャにアクセスしない場合でもtx.hをインクルードします)。関数
tpsvrinit(3c)は、ブート時に必ず関数
tx_open()が1度呼び出されるようにするために用意されています。障害が起こると、
-1が返され、サーバーのブートは失敗します。これは自動的に行われるので、この機能を提供する必要はありません。
これら2つのオペレーション関数は、アプリケーション作業、つまり今回の例では大文字や小文字への変換を行うために用意されています。
CC=cc
CFLAGS=
TIDL=$(TUXDIR)/bin/tidl
LIBTRPC=-ltrpc
all: client server
# Tuxedo client
client: simp.h simp_cstub.o
CC=$(CC) CFLAGS=$(CFLAGS) $(TUXDIR)/bin/buildclient \
-oclient -fclient.c -fsimp_cstub.o -f$(LIBTRPC)
# Tuxedo server
server: simp.h simp_sstub.o
CC=$(CC) CFLAGS=$(CFLAGS) $(TUXDIR)/bin/buildserver \
-oserver -s changecasev1_0 -fserver.c -fsimp_sstub.o \
-f$(LIBTRPC)
simp_cstub.o simp_sstub.o simp.h: simp.idl
$(TIDL) -cc_cmd "$(CC) $(CFLAGS) -c" simp.idl
#
# THIS PART OF THE FILE DEALING WITH THE DCE GATEWAY IS OMMITTED
#
# Cleanup
clean::
rm -f *.o server $(ALL2) ULOG.* TUXCONFIG
rm -f stderr stdout *stub.c *.h simpdce.idl gwinit.c
clobber: clean
makefileにより、クライアントやサーバーの実行プログラムが構築されます。
クライアントはヘッダー・ファイル
simp.hとクライアント・スタブ・オブジェクト・ファイルに依存して構築されます。
buildclientを実行すると、ソース・ファイルとして
client.cを、リンクするファイルとしてクライアント・スタブ・オブジェクト・ファイルを使用し、
-ltrpc RPCランタイム・ライブラリがリンクされ、実行形式のファイルが作成、出力されます。
サーバーは、ヘッダー・ファイル
simp.hとサーバー・スタブ・オブジェクト・ファイルに依存して構築されます。
buildserverを実行すると、ソース・ファイルとして
server.cを、リンクするファイルとしてサーバー・スタブ・オブジェクト・ファイルを使用し、
-ltrpcにより、RPCランタイム・ライブラリがリンクされ、実行形式のファイルが作成、出力されます。
クライアントやサーバーのスタブ・オブジェクト・ファイルと、ヘッダー・ファイル
simp.hは、いずれもIDL入力ファイルで
tidlコンパイラを実行することで作成されます。
cleanターゲットは、アプリケーションの構築中および実行中に作成されたファイルをすべて削除します。
ASCII構成ファイルの例を次に示します。ユーザーが使用している構成に応じて、マシン名、
TUXCONFIG、
TUXDIR、
APPDIRを設定する必要があります。
*RESOURCES
IPCKEY 187345
MODEL SHM
MASTER SITE1
PERM 0660
*MACHINES
<
UNAME> LMID=SITE1
TUXCONFIG="<
TUXCONFIG>"
TUXDIR="<
TUXDIR>"
APPDIR="<
APPDIR>"
# MAXWSCLIENTS=10
*GROUPS
GROUP1 LMID=SITE1 GRPNO=1
*SERVERS
server SRVGRP=GROUP1 SRVID=1
#WSL SRVGRP=GROUP1 SRVID=2 RESTART=Y GRACE=0
# CLOPT="-A -- -n <
address> -x 10 -m 1 -M 10 -d <
device>"
#
# Tuxedo-to-DCE Gateway
#simpgw SRVGRP=GROUP1 SRVID=2
*SERVICES
*ROUTING
ASCII構成ファイル
ubbconfigを編集して、位置に依存した情報(例:ユーザー独自のディレクトリ・パス名とマシン名)を指定します。置き換えるテキストは山かっこで囲みます。
TUXDIR、
TUXCONFIG、
APPDIR、および実行するマシン名は、フル・パス名に置き換えます。必要な値を次に要約します。
Oracle Tuxedoソフトウェアのルート・ディレクトリのフル・パス名です。前述のように設定します。
バイナリ構成ファイルのフル・パス名です。前述のように設定します。
アプリケーションを実行するディレクトリのフル・パス名です。
アプリケーションを実行するマシンの名前です。この名前は、UNIXの
uname -nコマンドが出力するものです。
ワークステーションのconfigurationファイルでは、
MAXWSCLIENTSおよび
WSL行のコメントを解除し、<
address>をワークステーション・リスナーに対して設定します。(詳細は、
WSL(5)を参照してください。)
次のコマンドを実行してクライアントとサーバー・プログラムを構築します。
make -f rpcsimp.mk TUXDIR=$TUXDIR
次のコマンドを実行してバイナリの
TUXCONFIG構成ファイルをロードします。
次のコマンドを実行してアプリケーションをブートします。
1.
|
必要に応じて大文字に変換した後で小文字に変換する文字列を指定して、ネイティブ・クライアント・プログラムを実行します。
|
$ client HeLlO
to_upper returns: HELLO
to_lower returns: hello
$
2.
|
ワークステーション上で実行する場合には、環境変数 WSNADDRをWSLプログラム用に指定したアドレスと一致するように設定します。Windowsクライアントは、次のコマンドで実行できます。
|
注意:
|
動的リンク・ライブラリは、別に開発されたアプリケーション(例:ビジュアル・ビルダー)で使用することもできます。
|
tmadmin(1)を使うと、RPCサーバーをモニターできます。次の例では、
psrと
pscを使って
サーバー・プログラムの情報を表示します。簡潔モード("+"で表示)では、RPCサービス名の長さは切りつめられることに注意してください。一方、冗長モードを使用すると、フル・ネームを表示できます。
リストA-6
tmadmin psrおよびpscの出力
$ tmadmin
> psr
a.out Name Queue Name Grp Name ID RqDone Load Done Current Service
---------- ---------- -------- -- ------ --------- ---------------
BBL 587345 SITE1 0 0 0 ( IDLE )
server 00001.00001 GROUP1 1 2 100 ( IDLE )
> psc
Service Name Routine Name a.out Name Grp Name ID Machine # Done Status
------------ ------------ ---------- -------- -- ------- ------ ------
ADJUNCTBB ADJUNCTBB BBL SITE1 0 SITE1 0 AVAIL
ADJUNCTADMIN ADJUNCTADMIN BBL SITE1 0 SITE1 0 AVAIL
changecasev+ changecasev+ server GROUP1 1 SITE1 2 AVAIL
> verbose
Verbose now on.
> psc -g GROUP1
Service Name: changecasev1_0
Service Type: USER
Routine Name: changecasev1_0
a.out Name: /home/sdf/trpc/rpcsimp/server
Queue Name: 00001.00001
Process ID: 8602, Machine ID: SITE1
Group ID: GROUP1, Server ID: 1
Current Load: 50
Current Priority: 50
Current Trantime: 30
Requests Done: 2
Current status: AVAILABLE
> quit
次のコマンドを実行して、アプリケーションを停止します。
次のコマンドを入力して、作成したファイルを削除します。