ここでは、次の内容について説明します。
この付録では、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)が呼び出されていることに注意してください。これが行われないと、ワークステーション以外のクライアントでは、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をインクルードします)。関数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コマンドが出力するものです。
ワークステーションのconfigurationファイルでは、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