ここでは、次の内容について説明します。
この付録では、TxRPCを使用したrpcsimp
と呼ばれる単一クライアント、単一サーバーで構成するアプリケーションについて解説します。 この対話型アプリケーションのソース・ファイルは、Oracle Tuxedoソフトウェアと共に配布されていますが、RTK製品には含まれません。
このアプリケーション例を実行する前に、Oracle Tuxedoソフトウェアをインストールし、この付録で参照するファイルやコマンドが使用できるようにしておきます。
rpcsimp
は、TxRPCを利用した非常に基本的なOracle Tuxedoアプリケーションです。 このアプリケーションは、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のディレクトリ構造内のファイルにアクセスし、Oracle Tuxedoコマンドを実行するのに必要です。 構成ファイルがロードできるようにするには、TUXCONFIG を設定する必要があります。 共有オブジェクトを使用する場合、LD_LIBRARY_PATH 環境変数も設定します。 |
rpcsimp
用のファイルをアプリケーション・ディレクトリにコピーします。
cp $TUXDIR/apps/rpcsimp/* .
一部のファイルを編集してから、実行形式ファイルを作成することがあるので、本ソフトウェアで提供されたオリジナルのファイルではなく、コピーしたファイルを用いて作業することをお薦めします。
ファイルを一覧表示します。
$ ls client.c rpcsimp.mk server.c simp.idl ubbconfig wclient.def wsimpdll.def $
アプリケーションを構成するファイルは次のセクションで説明します。
サンプル・コードA-1 simp.idl
[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
はスタブ関数の生成に使用されます(以下を参照)。
サンプル・コードA-2 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)
が呼び出されていることに注意してください。 tpterm(3c)を呼び出さないと、ワークステーション以外のクライアントでは、userlog(3c)
に警告が出力され、リソースが関連付けられたままになります。ワークステーション・クライアントでは、接続がタイムアウトするまでリソースが関連付けられたままになります。
サンプル・コードA-3 server.c
#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をインクルードします。これはX/OPEN TxRPC仕様で定められているとおりです)。 関数tpsvrinit(3c)
は、ブート時に必ず関数tx_open()
が1度呼び出されるようにするために用意されています。 障害が起こると、-1
が返され、サーバーのブートは失敗します。 これは自動的に行われるので、この機能を提供する必要はありません。
これら2つのオペレーション関数は、アプリケーション作業、つまり今回の例では大文字や小文字への変換を行うために用意されています。
サンプル・コードA-4 rpcsimp.mk
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
により、クライアントやサーバーの実行プログラムが構築されます。
「DCEゲートウェイ・アプリケーション」で説明する、DCEゲートウェイの処理に関するmakefile
の部分はリストでは省略されています。
クライアントはヘッダー・ファイルsimp.h
とクライアント・スタブ・オブジェクト・ファイルに依存して構築されます。buildclient
を実行すると、ソース・ファイルとしてclient.c
を、リンクするファイルとしてクライアント・スタブ・オブジェクト・ファイルを使用し、-ltrpc
RPCランタイム・ライブラリがリンクされ、実行形式のファイルが作成、出力されます。
サーバーは、ヘッダー・ファイルsimp.h
とサーバー・スタブ・オブジェクト・ファイルに依存して構築されます。buildserver
を実行すると、ソース・ファイルとしてserver.c
を、リンクするファイルとしてサーバー・スタブ・オブジェクト・ファイルを使用し、-ltrpc
により、RPCランタイム・ライブラリがリンクされ、実行形式のファイルが作成、出力されます。
クライアントやサーバーのスタブ・オブジェクト・ファイルと、ヘッダー・ファイルsimp.h
は、いずれもIDL入力ファイルでtidl
コンパイラを実行することで作成されます。
clean
ターゲットは、アプリケーションの構築中および実行中に作成されたファイルをすべて削除します。
ASCII構成ファイルの例を次に示します。 ユーザーが使用している構成に応じて、マシン名、TUXCONFIG
、TUXDIR
、APPDIR
を設定する必要があります。
サンプル・コードA-5 ubbconfig
*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
MAXWSCLIENTS
とWSL
行は、ワークステーション構成の場合にコメントを解除します。 ワークステーション・リスナー用のリテラルnetaddr
は、『Oracle Tuxedoのファイル形式とデータ記述方法』のWSL(5)
の説明に従って設定してください。
ASCII構成ファイルubbconfig
を編集して、位置に依存した情報(例:ユーザー独自のディレクトリ・パス名とマシン名)を指定します。 置き換えるテキストは山かっこで囲みます。 TUXDIR
、TUXCONFIG
、APPDIR
、および実行するマシン名は、フル・パス名に置き換えます。 必要な値を以下に要約します。
TUXDIR
Oracle Tuxedoソフトウェアのルート・ディレクトリのフル・パス名です。上記のように設定します。
TUXCONFIG
バイナリ構成ファイルのフル・パス名です。上記のように設定します。
APPDIR
アプリケーションを実行するディレクトリのフル・パス名です。
UNAME
アプリケーションを実行するマシンの名前です。この名前は、UNIXのuname -n
コマンドが出力するものです。
ワークステーションの構成ファイルでは、MAXWSCLIENTS
とWSL
行のコメントを解除し、<address
>をワークステーション・リスナーに対して設定します(詳細は、WSL
(5)を参照)。
必要に応じて大文字に変換した後で小文字に変換する文字列を指定して、ネイティブ・クライアント・プログラムを実行します。
$ client HeLlO to_upper returns: HELLO to_lower returns: hello $
ワークステーション上で実行する場合には、環境変数WSNADDR
をWSLプログラム用に指定したアドレスと一致するように設定します。 Windowsクライアントは、次のコマンドで実行できます。
>win wclient
注意: 動的リンク・ライブラリは、別に開発されたアプリケーション(例:ビジュアル・ビルダー)で使用することもできます。 |
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