分散トランザクション処理機能 OpenTP1 プログラム作成リファレンス C言語編

[目次][索引][前へ][次へ]

7.4.1 XATMIインタフェースの例

<この項の構成>
(1) リクエスト/レスポンス型サービスの通信の例
(2) 会話型サービスの通信の例

(1) リクエスト/レスポンス型サービスの通信の例

(a) 処理の概要

ここで示す例題の処理概要を,次に説明します。

[説明]宿泊施設の空き状況を調べるサービスと,飛行機の空き状況を調べるサービスを,SUPから呼びます。前者は非同期に,後者は同期的に応答を受信します。

(b) UAPの構成

例題のUAPの構成を次の図に示します。

図7-4 同期的に応答を受信するリクエスト/レスポンス型サービスの通信形態

[図データ]

(c) 通信に使う型付きバッファ

通信に使う型付きバッファの構造体を次に示します。

struct hotel {                   struct plane {
    DCLONG date;                     DCLONG date;
    char place[128];                 char dest[128];
    char hname[128];                 DCLONG departure;
    DCLONG status;                   DCLONG status;
 }                                }
(d) SUPの例
  10  /* SUPのXATMIインタフェース定義の例(rrsup.defファイル)*/
  20  called_servers = { "rrspp.def" };
  10  /* SUPの例(rrsup.cファイル)*/
  20  #include <stdio.h>
  30  #include <dcrpc.h>
  40  #include <xatmi.h>
  50  #include <dcadm.h>
  60  /*
  70   * XATMIスタブヘッダファイル
  80   */
  90  #include "rrsup_stbx.h"
 100  main()
 110  {
 120  /*
 130   * 変数の定義
 140   */
 150    struct hotel *hptr; 
 160    struct plane *pptr;
 170    struct  errmsg *werrmsg ;
 180    long  hlen, plen ;
 190    int  cd ;
 200    int rc;
 210  /*
 220   * RPC-OPEN(UAPの開始)
 230   */
 240      rc = dc_rpc_open(DCNOFLAGS);
 250      if(rc != DC_OK){
 260          printf("dc_rpc_openに失敗しました。\
 270                  ERROR CODE = %d \n", rc);
 280          goto PROG_END;
 290      }
 300  /*
 310   * ADM-COMPLETE(ユーザサーバの開始処理完了の報告)
 320   */
 330      rc = dc_adm_complete(DCNOFLAGS);
 340      if(rc != DC_OK){
 350          printf("dc_adm_completeに失敗しました。\
 360                  ERROR CODE = %d \n",  rc);
 370          goto PROG_END;
 380      }
 390  /*
 400   * TPALLOC(型付きバッファの確保)
 410   */
 420    /* 宿泊施設空き状況検索サービス用 */
 430      hptr = (struct hotel *)tpalloc("X_COMMON", "hotel", 0);
 440      if(hptr == NULL){
 450          printf("tpallocに失敗しました。\
 460                  ERROR CODE = %d \n", tperrno);
 470          goto PROG_END;
 480      }
 490    /* 飛行機空き状況検索サービス用 */
 500      pptr = (struct plane *)tpalloc("X_COMMON", "plane", 0);
 510      if(pptr == NULL){
 520          printf("tpallocに失敗しました。\
 530                  ERROR CODE = %d \n", tperrno);
 540          goto PROG_END;
 550      }
 560  /*
 570   * データの設定
 580   */
 590    hptr->date = 940415 ;
 600    strcpy(hptr->place, "SAPPORO") ;
 610    strcpy(hptr->hname, "PRINCE") ;
 620    hptr->status = 0 ;
 630    pptr->date = 940415 ;
 640    strcpy(pptr->dest, "CHITOSE") ;
 650    pptr->departure = 1540 ;
 660    pptr->status = 0 ;
 670  /*
 680   * TPACALL(サービスリクエストを送信する)
 690   */
 700      cd = tpacall("SVHOTEL", (char *) hptr, 0, 0);
 710      if(cd == -1){
 720         printf("宿泊施設空状況検索サービスの呼び出しに失敗しました。\
 730                 ERROR CODE = %d \n", tperrno);
 740         goto PROG_END;
 750      }
 760      printf("宿泊施設空状況検索サービスの呼び出しに成功しました。\n");
 770  /*
 780   * TPCALL(サービスリクエストを送信して,応答を待つ)
 790   */
 800      rc = tpcall("SVPLANE", (char *) pptr, 0, (char **) &pptr, &plen, 0);
 810      if(rc != 0){
 820          if(tperrno == TPESVCFAIL){
 830             werrmsg = (struct errmsg *) pptr ;
 840             printf("%s ERROR CODE = %d USER CODE = %d\n",
 850                     werrmsg->errmessage, tperrno, tpurcode);
 860             goto PROG_END ;
 870          }else{
 880             printf("飛行機空き状況検索サービスの呼び出しに失敗しました。 \
 890                     ERROR CODE = %d", tperrno);
 900             goto PROG_END;
 910          }
 920      }
 930      printf("飛行機空き状況検索サービスの呼び出しの応答受信に成功しました。\n");
 940      if(pptr->status == 1){
 950          printf("飛行機空き状況 : 満席です。 \n");
 960      } else {
 970          printf("飛行機空き状況 : 空席があります。 \n");
 980      }
 990  /*
1000   * TPGETRPLY(応答を受信する)
1010   */
1020      rc = tpgetrply(&cd, (char **) &hptr, &hlen, 0);
1030      if(rc != 0){
1040          if(tperrno == TPESVCFAIL){
1050             werrmsg = (struct errmsg *) hptr ;
1060             printf("%s ERROR CODE = %d USER CODE = %d\n",
1070                     werrmsg->errmessage, tperrno, tpurcode);
1080             goto PROG_END ;
1090          }else{
1100             printf("宿泊施設空状況検索サービスに失敗しました。 \
1110                     ERROR CODE = %d", tperrno);
1120             goto PROG_END;
1130          }
1140      }
1150      printf("宿泊施設空状況検索サービスの応答受信に成功しました。\n");
1160      if(hptr->status == 1){
1170          printf("宿泊施設空き状況 : 満室です。 \n");
1180      } else {
1190          printf("宿泊施設空き状況 : 空室があります。 \n");
1200      }
1210  /*
1220   * 型付きバッファの解放
1230   */
1240      tpfree((char *) hptr);
1250      tpfree((char *) pptr);
1260  /*
1270   * RPC-CLOSE(UAPの終了)
1280   */
1290      PROG_END:
1300      dc_rpc_close(DCNOFLAGS);
1310      printf("またのご利用をお待ちしています。\n");
1320      exit(0);
1330  }
  10  #ユーザサービス定義の例(rrsupファイル)
  20  set  module              = "rrsup"
  30  set  receive_from        = none
  40  set  trn_expiration_time = 180
  50  set  trn_expiration_time_suspend = Y
(e) SPPの例
  10  /* XATMIインタフェース定義の例(rrspp.defファイル)*/
  20  X_COMMON hotel {
  30      long   date;
  40      char   place[128];
  50      char   hname[128];
  60      long   status;
  70  };
  80  X_COMMON plane {
  90      long   date;
 100      char   dest[128];
 110      long   departure;
 120      long   status;
 130  };
 140  X_COMMON errmsg {
 150      char   errmessage[128];
 160  };
 170  service shotel(X_COMMON hotel) ;
 180  service splane(X_COMMON plane) ;
  10  /* SPPのメイン関数例(rrspp.cファイル)*/
  20  #include <stdio.h>
  30  #include <dcrpc.h>
  40  #include <xatmi.h>
  50  #include <dcadm.h>
  60  /*
  70   * XATMIスタブヘッダファイル
  80   */
  90  #include "rrspp_stbx.h"
 100  main()
 110  {
 120  /*
 130   * 変数の定義
 140   */
 150     int rc;
 160  /*
 170   * RPC-OPEN(UAPの開始)
 180   */
 190      rc = dc_rpc_open(DCNOFLAGS);
 200      if(rc != DC_OK){
 210          printf("dc_rpc_openに失敗しました。\
 220                  ERROR CODE = %d \n", rc);
 230          goto PROG_END;
 240      }
 250  /*
 260   * RPC-MAINLOOP(SPPのサービス開始)
 270   */
 280      rc = dc_rpc_mainloop(DCNOFLAGS);
 290      if(rc != DC_OK){
 300          printf("dc_rpc_mainloopに失敗しました。\
 310                  ERROR CODE = %d \n", rc);
 320      }
 330  /*
 340   * RPC-CLOSE(UAPの終了)
 350   */
 360  PROG_END:
 370      dc_rpc_close(DCNOFLAGS);
 380      exit(0);
 390  }
  10  /* SPPのサービス関数例(rrsvc.cファイル)*/
  20  #include <stdio.h>
  30  #include <dcrpc.h>
  40  #include <xatmi.h>
  50  #include <dcadm.h>
  60  /*
  70   * XATMIスタブヘッダファイル
  80   */
  90  #include "rrspp_stbx.h"
 100  void shotel(svcinfo)
 110  TPSVCINFO *svcinfo;
 120  {
 130  /*
 140   * 変数の定義
 150   */
 160      struct hotel *hptr;
 170    
 180      hptr = (struct hotel *) svcinfo->data;
 190      /* このサービスは空き状況を検索して,満室ならば status = 1 ,
 200       * 空室があれば status = 0,エラーが起こったときは,メッセージを返します。
 210       * ここでは,検索した結果,満室だったとします。*/
 220      hptr->status = 1 ;
 230      tpreturn(TPSUCCESS, 0, hptr, 0, 0);
 240      return ; /* OpenTP1の場合はtpreturn後にreturnの発行が必要です。 */
 250  }
 260  void splane(svcinfo)
 270  TPSVCINFO *svcinfo;
 280  {
 290      struct plane *pptr;
 300      pptr = (struct plane *) svcinfo->data;
 310      /* このサービスは空き状況を検索して,満席ならば status = 1, 
 320       * 空席があれば status = 0 ,エラーが起こったときは,メッセージを返します。
 330       * ここでは,検索した結果,満席だったとします。*/
 340      pptr->status = 1 ;
 350      tpreturn(TPSUCCESS, 0, pptr, 0, 0);
 360      return ;
 370  }
  10  #ユーザサービス定義の例(rrsppファイル)
  20  set    service_group      = "rrspp_svg"
  30  set    module             = "rrspp"
  40  set    service            = "SVHOTEL=shotel","SVPLANE=splane"
  50  set    trn_expiration_time = 180
  60  set    trn_expiration_time_suspend = Y
  70  set    server_type = "xatmi"

(2) 会話型サービスの通信の例

(a) 処理の概要

ここで示す例題の処理概要を,次に説明します。

[説明]acctreq構造体の構造を持つ型付きバッファでサービス関数を起動します。acctreqのメンバは口座番号の上限と下限を示します。サービス関数では,この範囲にある口座データをacctdat構造体の構造を持つ型付きバッファに設定して,会話のオリジネータに送信します。

(b) UAPの構成

例題のUAPの構成を次の図に示します。

図7-5 会話型サービスの通信形態

[図データ]

(c) 通信に使う型付きバッファ

通信に使う型付きバッファの構造体を次に示します。

(d) SUPの例
  10  /* SUPのXATMIインタフェース定義の例(convsup.defファイル)*/
  20  called_servers = { "convspp.def" };
  10  /* SUPのコーディング例(convsup.cファイル)*/
  20  #include <stdio.h>
  30  #include <dcrpc.h>
  40  #include <xatmi.h>
  50  #include <tx.h>
  60  #include <dcadm.h>
  70  /*
  80   * XATMIスタブヘッダファイル
  90   */
 100  #include "convsup_stbx.h"
 110  main()
 120  {
 130  /*
 140   * 変数の定義
 150   */
 160      struct   acctreq  *rptr; 
 170      struct   acctdata *dptr; 
 180      long     wlen;
 190      int      cd;
 200      int      rc;
 210      long     revent; 
 220      long     size = 0 ;
 230  /*
 240   * RPC-OPEN(UAPの開始)
 250   */
 260      rc = dc_rpc_open(DCNOFLAGS);
 270      if(rc != DC_OK){
 280          printf("dc_rpc_openに失敗しました。ERROR CODE = %d \n", rc);
 290          goto PROG_END;
 300      }
 310  /*
 320   * ADM-COMPLETE(ユーザサーバの開始処理完了の報告)
 330   */
 340      rc = dc_adm_complete(DCNOFLAGS);
 350      if(rc != DC_OK){
 360          printf("dc_adm_completeに失敗しました。ERROR CODE = %d \n", rc);
 370          goto PROG_END;
 380      }
 390  /*
 400   * TPALLOC(型付きバッファの確保)
 410   */
 420    /*サーチする口座番号の上限,下限の設定用*/  
 430      rptr = (struct acctreq *)tpalloc(X_COMMON, "acctreq", 0);
 440  
 450      if(rptr == NULL){
 460          printf("tpallocに失敗しました。ERROR CODE = %d \n", tperrno);
 470          goto PROG_END;
 480      }
 490    /*サーチ結果の口座データ用*/  
 500      dptr = (struct acctdata *)tpalloc(X_COMMON, "acctdata", 0) ;
 510      if(dptr == NULL){
 520          printf("tpallocに失敗しました。ERROR CODE = %d \n", tperrno);
 530          goto PROG_END;
 540      }
 550  /*
 560   * データの設定
 570   * サーチする範囲を指定
 580   */
 590      rptr->lower_no = 10000000L;
 600      rptr->upper_no = 20000000L;
 610   /* トランザクション開始  */
 620      tx_begin() ;
 630  /*
 640   * TPCONNECT(会話サービスの呼び出し)
 650   * INQUIRYを呼ぶ。
 660   */
 670      cd = tpconnect("INQUIRY", (char *) rptr, 0, TPRECVONLY);
 680      if(cd == -1){
 690          printf("tpconnectに失敗しました。ERROR CODE = %d \n", tperrno);
 700          goto PROG_END;
 710      }
 720  /*
 730   * エラーが起こるまで(イベントの発生も含む),
 740   * TPRECV(メッセージを受信)
 750   */
 760      while(rc != -1){
 770          rc = tprecv(cd, (char **) &dptr, &wlen, 0, &revent);
 780          /*
 790           *エラーが起こっていなければ,
 800           *受信した口座情報を出力する。
 810           */
 820          if(rc != -1) {
 830              printf("サービスから口座情報を受信しました。\n");
 840              printf("口座番号 = %d \n", dptr->acct_no);
 850              printf("名前 = %s \n", dptr->name);
 860              printf("預金 = %d \n", dptr->amount);
 870          }
 880      }
 890  /*
 900   * サービスの結果の出力
 910   */
 920      if(tperrno == TPEEVENT){
 930          if(revent == TPEV_SVCSUCC){
 940          /* サービスは成功した。*/
 950              printf("サービスは成功しました。\n");
 960              /* トランザクションのコミット */
 970              tx_commit() ;
 980          }else{
 990              printf("何らかのイベントが発生しています。revent = %d\n", 
1000              revent);
1010              /* トランザクションのロールバック*/
1020              tx_rollback() ;
1030          }
1040    }
1050  /*
1060   * 型付きバッファの解放
1070   */
1080      tpfree((char *) rptr);
1090      tpfree((char *) dptr);
1100  /*
1110   * RPC-CLOSE(UAPの終了)
1120   */
1130      PROG_END:
1140      dc_rpc_close(DCNOFLAGS);
1150      exit(0);
1160  }
  10  #ユーザサービス定義の例(convsupファイル)
  20  set module              = "convsup"         #実行形式ファイル名
  30  set watch_time          = 180               #最大応答待ち時間
  40  set receive_from        = none              #受信方法
  50  set trn_expiration_time = 180
  60                              #トランザクションブランチ限界経過時間
  70  set trn_expiration_time_suspend = Y         #必ず Y を指定
(e) SPPの例
  10  /* SPPのXATMIインタフェース定義の例(convspp.defファイル)*/
  20  X_COMMON acctreq {
  30      long   upper_no;
  40      long   lower_no;
  50  };
  60  X_COMMON acctdata {
  70      long   acct_no;
  80      char   name[128];
  90      short  amount;
 100  };
 110  service inquiry(X_COMMON acctreq) ;
  10  /* SPPのメイン関数例(convspp.cファイル)*/
  20  #include <stdio.h>
  30  #include <dcrpc.h>
  40  #include <xatmi.h>
  50  #include <dcadm.h>
  60  /*
  70   * XATMIスタブヘッダファイル
  80   */
  90  #include "convspp_stbx.h"
 100  main()
 110  {
 120  /*
 130   * 変数の定義
 140   */
 150      int rc;
 160  /*
 170   * RPC-OPEN(UAPの開始)
 180   */
 190      rc = dc_rpc_open(DCNOFLAGS);
 200      if(rc != DC_OK){
 210          printf("dc_rpc_openに失敗しました。ERROR CODE = %d \n", rc);
 220          goto PROG_END;
 230      }
 240    
 250  /*
 260   * RPC-MAINLOOP(SPPのサービス開始)
 270   */
 280      rc = dc_rpc_mainloop(DCNOFLAGS);
 290      if(rc != DC_OK){
 300          printf("dc_rpc_mainloopに失敗しました。ERROR CODE = %d \n",rc);
 310      }
 320  /*
 330   * RPC-CLOSE(UAPの終了)
 340   */
 350      PROG_END:
 360      dc_rpc_close(DCNOFLAGS);
 370      exit(0);
 380  }
  10  /* SPPのサービス関数例(convsvc.cファイル)*/
  20  #include <stdio.h>
  30  #include <dcrpc.h>
  40  #include <xatmi.h>
  50  #include <dcadm.h>
  60  /*
  70   * XATMIスタブヘッダファイル
  80   */
  90  #include "convspp_stbx.h"
 100  /*
 110   * DEPOSITSVC  サービス関数
 120   * tpconnect()によって口座番号の上限,下限を受取り
 130   * その範囲にある口座の情報を送信する。
 140   */
 150  void inquiry(svcinfo)
 160  TPSVCINFO *svcinfo;
 170  {
 180  /*
 190   * 変数の定義
 200   */
 210      struct   acctreq  *rptr;
 220      struct   acctdata *dptr;
 230      char     type[9];
 240      char     subtype[17];
 250      long     revent, rval;
 260      int      size;
 270  /*
 280   * サービス要求が受け付けられた
 290   */
 300      rptr = (struct acctreq *) svcinfo->data;
 310  /*
 320   * オリジネータに返すデータのtypedバッファの確保
 330   */
 340      dptr = (struct acctdata *)tpalloc("X_COMMON", "acctdata", 0);
 350      if(dptr == NULL){
 360          printf("tpallocでエラーが起こりました。tperrno = %d \n",
 370                 tperrno);
 380          abort();
 390      }
 400  /*
 410   * ユーザ処理
 420   * データファイルを検索して口座番号が範囲内の口座情報を返す。
 430   * ここでは2件見つかったこととしてデータを送信する。
 440   */
 450      
 460      dptr->acct_no = 10000001L;
 470      strcpy(dptr->name, "Hitachi Hanako");
 480      dptr->amount = 20000;
 490  /*
 500   * TPSEND(メッセージの送信)
 510   */
 520      tpsend(svcinfo->cd, (char *) dptr, 0, 0, &revent);
 530      if(tperrno != -1){
 540          rval = TPSUCCESS;
 550      }else{
 560          rval = TPFAIL;
 570          goto SVC_END;
 580      }
 590      dptr->acct_no = 10000002L;
 600      dptr->amount = 10000;
 610      strcpy(dptr->name, "Hitachi Tarou");
 620  /*
 630   * TPSEND(メッセージの送信)
 640   */
 650      tpsend(svcinfo->cd, (char *) dptr, 0, 0, &revent);
 660      if(tperrno != -1){
 670          rval = TPSUCCESS;
 680      }else{
 690          rval = TPFAIL;
 700          goto SVC_END;
 710      }
 720  SVC_END:
 730      tpreturn(rval, 0, NULL, 0, 0);
 740      return; /* OpenTP1の場合 tpreturn後にreturnが必要です。*/
 750  }
  10  # ユーザサービス定義の例(convsppファイル)
  20    set  service_group     = "convspp_svg"     #サービスグループ名
  30    set  module            = "convspp"         #実行形式ファイル名
  40    set  service  = "INQUIRY=inquiry"
  50                              #サービス名=エントリポイント名
  60    set  watch_time        = 180               #最大応答待ち時間
  70    set  trn_expiration_time = 240
  80                              #トランザクションブランチ限界経過時間
  90    set  trn_expiration_time_suspend = Y       #必ず Y を指定
 100    set  server_type = "xatmi"                 #サーバタイプ
 110    set  receive_from = "socket"               #受信方法