ヘッダーをスキップ
TxRPCを使用したOracle Tuxedoアプリケーションのプログラミング
  目次へ移動
目次

前
 
次
 

A アプリケーション例

このトピックには次の項が含まれます:

この付録の内容

この付録では、TxRPCを使用したrpcsimpと呼ばれる単一クライアント、単一サーバーで構成するアプリケーションについて解説します。この対話型アプリケーションのソース・ファイルは、Oracle Tuxedo ATMIソフトウェアとともに配布されていますが、RTK製品には含まれません。

前提条件

このアプリケーション例を実行する前に、Oracle Tuxedoソフトウェアをインストールし、この付録で参照するファイルやコマンドが使用できるようにしておきます。

rpcsimpアプリケーションの構築

rpcsimpは、TxRPCを利用した非常に基本的なOracle Tuxedo ATMIアプリケーションです。このアプリケーションは、1つのクライアントと1つのサーバーで構成します。クライアントはリモート・プロシージャ・コール(オペレーション) to_upper()to_lower()を呼び出します。これらのプロシージャ・コールは、いずれもサーバー内に実装されるものです。オペレーションto_upper()は、文字列を小文字から大文字へ変換してクライアントに返します。一方to_lower()は、文字列を大文字から小文字へ変換してクライアントに返します。各プロシージャ・コールが復帰すると、クライアントは文字列出力をユーザーの画面に表示します。

次に本プログラム例を構成、実行する手順を解説します。

ステップ1:アプリケーション・ディレクトリの作成

rpcsimp用のディレクトリを作成し、そのディレクトリに移動します。

mkdir rpcsimpdir
cd rpcsimpdir

注:

このようにしておくと、作業開始時にあったrpcsimp関連のファイルと、作業中に作成した新たなファイルを容易に把握できます。標準シェル(/bin/sh)またはKornシェルを使用してください。Cシェル(csh)は使わないでください。

ステップ2:環境変数の設定

必要な環境変数を設定し、エクスポートします。

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

注:

TUXDIRPATHは、Oracle Tuxedo ATMIのディレクトリ構造内のファイルにアクセスし、Oracle Tuxedo ATMIコマンドを実行するのに必要です。構成ファイルがロードできるようにするには、TUXCONFIGを設定する必要があります。共有オブジェクトを使用する場合、LD_LIBRARY_PATH環境変数も設定します。

ステップ3:ファイルのコピー

rpcsimp用のファイルをアプリケーション・ディレクトリにコピーします。

cp $TUXDIR/apps/rpcsimp/* .

一部のファイルを編集してから、実行形式ファイルを作成することがあるので、本ソフトウェアで提供されたオリジナルのファイルではなく、コピーしたファイルを用いて作業することをお薦めします。

ステップ4:ファイルの一覧表示

ファイルを一覧表示します。

$ ls
client.c
rpcsimp.mk
server.c
simp.idl
ubbconfig
wclient.def
wsimpdll.def
$

注:

この一覧には、「DCEゲートウェイ・アプリケーション」で説明するDCEゲートウェイ例で使用するファイルは含まれていません。

アプリケーションを構成するファイルは次のセクションで説明します。

IDL入力ファイル - simp.idl

サンプル・コード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_upperto_lower)を持った単一インタフェース(changecase version 1.0)を定義します。各オペレーションは、NULL (文字)で終わる文字列を入出力パラメータとして使用します。ACFフィルは提供されないので、状態変数は使用されず、クライアント・プログラムは例外処理を行う必要があります。各オペレーションには戻り値が生成されないことを示すためにvoidで宣言します。simp.idlはスタブ関数の生成に使用されます(次を参照)。

クライアント・ソース・コード - client.c

サンプル・コード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)に警告が出力され、リソースが関連付けられたままになります。ワークステーション・クライアントでは、接続がタイムアウトするまでリソースが関連付けられたままになります。

サーバー・ソース・コード - server.c

サンプル・コード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つのオペレーション関数は、アプリケーション作業、つまり今回の例では大文字や小文字への変換を行うために用意されています。

Makefile - rpcsimp.mk

サンプル・コード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ターゲットは、アプリケーションの構築中および実行中に作成されたファイルをすべて削除します。

構成ファイル - ubbconfig

ASCII構成ファイルの例を次に示します。ユーザーが使用している構成に応じて、マシン名、TUXCONFIGTUXDIRAPPDIRを設定する必要があります。

サンプル・コード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

MAXWSCLIENTSWSL行は、ワークステーション構成の場合にコメントを解除します。ワークステーション・リスナー用のリテラルnetaddrは、『Oracle Tuxedoファイル形式、データ記述、MIBおよびシステム・プロセス・リファレンス』のWSL(5)の説明に従って設定してください。

ステップ5: 構成の変更

ASCII構成ファイルubbconfigを編集して、位置に依存した情報(例:ユーザー独自のディレクトリ・パス名とマシン名)を指定します。置き換えるテキストは山かっこで囲みます。TUXDIRTUXCONFIGAPPDIR、および実行するマシン名は、フル・パス名に置き換えます。必要な値を次に要約します。

TUXDIR

Oracle Tuxedoソフトウェアのルート・ディレクトリのフル・パス名です。前述のように設定します。

TUXCONFIG

バイナリ構成ファイルのフル・パス名です。前述のように設定します。

APPDIR

アプリケーションを実行するディレクトリのフル・パス名です。

UNAME

アプリケーションを実行するマシンの名前です。この名前は、UNIXのuname -nコマンドが出力するものです。

ワークステーションのconfigurationファイルでは、MAXWSCLIENTSおよびWSL行のコメントを解除し、<address>をワークステーション・リスナーに対して設定します。(詳細は、WSL(5)を参照してください。)

ステップ6:アプリケーションの構築

次のコマンドを実行してクライアントとサーバー・プログラムを構築します。

make -f rpcsimp.mk TUXDIR=$TUXDIR

ステップ7: 構成ファイルのロード

次のコマンドを実行してバイナリのTUXCONFIG構成ファイルをロードします。

tmloadcf -y ubbconfig

ステップ8: 構成のブート

次のコマンドを実行してアプリケーションをブートします。

tmboot -y

ステップ9:クライアントの実行

  1. 必要に応じて大文字に変換した後で小文字に変換する文字列を指定して、ネイティブ・クライアント・プログラムを実行します。

    $ client HeLlO
    to_upper returns: HELLO
    to_lower returns: hello
    $
    
  2. ワークステーション上で実行する場合には、環境変数WSNADDRをWSLプログラム用に指定したアドレスと一致するように設定します。Windowsクライアントは、次のコマンドで実行できます。

    >win wclient
    

    注:

    動的リンク・ライブラリは、別に開発されたアプリケーション(例:ビジュアル・ビルダー)で使用することもできます。

ステップ10: RPCサーバーのモニター

tmadmin(1)を使うと、RPCサーバーをモニターできます。次の例では、psrpscを使ってサーバー・プログラムの情報を表示します。簡潔モード("+"で表示)では、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

ステップ11: 構成の停止

次のコマンドを実行して、アプリケーションを停止します。

tmshutdown -y

ステップ12:作成ファイルのクリーンアップ

次のコマンドを入力して、作成したファイルを削除します。

make -f rpcsimp.mk clean