グローバルトランザクション運用を行うためには、CORBAのクライアントアプリケーションの処理に加えて、CosTransactions::Current::commitメソッドなどのCurrentインタフェースを呼び出して、データベース連携サービスにトランザクション処理を依頼します。
これらの処理を考慮したクライアントアプリケーションの構成について以下に示します。
■初期化処理部
クライアントアプリケーションをCORBAサービスに登録、およびトランザクションサービスの初期化を行います。
■アプリケーション固有部
アプリケーション固有の処理部です。トランザクションの開始から終了までの流れを記述します。
■トランザクション用ライブラリ
データベース連携サービスが提供するクライアントアプリケーション用ライブラリです。
クライアントアプリケーションの基本形を以下に示します。
: static CORBA::ORB_ptr orb; static CosTransactions::Current_ptr Current; static CosNaming::NamingContext_ptr obj; static CosNaming::NamingContext_ptr naming_obj; : /* 初期化処理 */ orb = CORBA::ORB_init(argc, argv, FJ_OM_ORBid, *env); : naming_obj = NamingContext_obj->resolve(*name, *env); … (1) : /* トランザクション依頼処理 */ obj = orb->resolve_initial_references (CORBA_ORB_ObjectId_TransactionCurrent, *env); … (2) Current = CosTransactions::Current::narrow(obj); Current->begin(*env); … (3) : srvobj->ope1(para, *env … (4) : if (env->exception()) … (5) Current->rollback(*env); else Current->commit(CORBA_TRUE, *env);
ネーミングサービスからサーバアプリケーションのオブジェクトリファレンスを獲得します。
Currentインタフェースのオブジェクトリファレンスを獲得します。
CosTransactions::Current::beginメソッドでトランザクションの開始を宣言します。
サーバアプリケーションを呼び出します。
サーバアプリケーションの復帰状態を確認して、トランザクションの状態を決定します。トランザクションを正常終了する場合は、CosTransactions::Current::commitメソッドでトランザクションをコミットします。トランザクションを異常終了する場合は、CosTransactions::Current::rollbackメソッドでトランザクションをロールバックします。
クライアントアプリケーションからサーバアプリケーションを呼び出す形態を以下に示します。
■同期型
同期型呼出しは、クライアントアプリケーションからサーバアプリケーションを呼び出し、そのサーバアプリケーションの処理終了を待ち合わせる呼出し形態です。同期型の呼出し形態について、以下に示します。
同期型には、以下の2つのインタフェースがあります。詳細については、“リファレンスマニュアル(API編)”を参照してください。
静的起動インタフェース
サーバアプリケーションのメソッド名を指定して呼び出します。
動的起動インタフェース
RequestインタフェースのCORBA::Request::invoke()メソッドでサーバアプリケーションを呼び出します。
動的起動インタフェースにおいて、遅延同期送信を行う場合の注意事項を以下に示します。
遅延同期送信の呼出し元は、その呼出しの復帰が完了するまでデータベースの操作を禁止します。
遅延同期送信の呼出し先は、データベースを使用する場合には、複数の呼出しが同じデータベースをアクセスできません。
遅延同期送信で呼び出されたアプリケーションから、同時に同一のデータベースを操作することはできません。
遅延同期送信で呼び出されたアプリケーションから、異なるデータベースを操作することができます。
同期型を使用する場合のクライアントアプリケーションの処理論理を以下に示します。
サーバアプリケーションAのメソッド1を呼び出します。クライアントアプリケーションは、サーバアプリケーションAのメソッドが終了するまで待ち合わせます。
クライアントアプリケーションは、サーバアプリケーションAのメソッド1の処理が終了した時点で制御が戻ります。
サーバアプリケーションBのメソッド2を呼び出します。クライアントアプリケーションは、サーバアプリケーションBのメソッドが終了するまで待ち合わせます。
クライアントアプリケーションは、サーバアプリケーションBのメソッド2の処理が終了した時点で制御が戻ります。
■非同期型
非同期型呼出しは、クライアントアプリケーションからサーバアプリケーションを呼び出し、サーバアプリケーションのメソッドの終了を待たずにクライアントアプリケーションに制御が戻ります。クライアントアプリケーションは任意のタイミングでサーバアプリケーションのメソッドの終了結果を問い合わせる呼出し形態です。
非同期型の呼出し形態を以下に示します。
RequestインタフェースのCORBA::Request::send_deferred()メソッドを使用します。詳細については、“リファレンスマニュアル(API編)”を参照してください。
非同期型を使用する場合のクライアントアプリケーションの処理論理を以下に示します。
サーバアプリケーションAのメソッド1を非同期型で呼び出します。
サーバアプリケーションBのメソッド2を非同期型で呼び出します。
メソッド1の処理終了を問い合わせます。
メソッド2の処理終了を問い合わせます。
静的起動インタフェースでサーバアプリケーションを呼び出す場合の、クライアントアプリケーションの記述例について説明します。
■初期化
初期化処理として、ORBのオブジェクトリファレンスを取得します。オブジェクトリファレンスを取得するには、初期化メソッドを呼び出します。
記述例を以下に示します。
main(argc, argv ) int argc; char *argv[]; { CORBA::ORB_ptr orb; // ORBのオブジェクトリファレンス CORBA::Environment_ptr env; // 例外情報 int current_argc = argc; env = new CORBA::Environment; // 例外情報 orb = CORBA::ORB_init(current_argc, argv, FJ_OM_ORBid, *env);
■ネーミングサービスのオブジェクトリファレンスの獲得
実行するオブジェクトをネーミングサービスから検索するために、ネーミングサービスのオブジェクトリファレンスを取得します。ネーミングサービスのオブジェクトリファレンスには、CORBAインタフェースのオブジェクトリファレンスの取り出しメソッドを使用します。
処理の記述例を以下に示します。
// NamingServiceのオブジェクトリファレンスを獲得 CORBA::Object_ptr obj = orb->resolve_initial_references( CORBA_ORB_ObjectId_NameService, *env ); // NamingContextクラスへの変換 CosNaming::NamingContext_ptr NamingContext_obj = CosNaming::NamingContext::_narrow( obj );
■サーバアプリケーションのオブジェクトリファレンスの獲得
ネーミングサービスから、実行したいサーバアプリケーションの情報を検索します。サーバアプリケーションの情報を取り出すには、実行するサーバアプリケーションのオブジェクト名をパラメタとしてメソッドを起動し、オブジェクトリファレンス情報が格納されているネーミングコンテキストを取得します。
処理の記述例を以下に示します。
CosNaming::Name_ptr name; // CosNaming::Nameのインスタンス CosNaming::NameComponent_var *name_component; // オブジェクト名格納域 CORBA::Object_ptr obj; // サーバアプリケーションのオブジェクトリファレンス // CosNaming::NameComponent_var領域の獲得 name_component = CosNaming::Name::allocbuf(1); // オブジェクト名 name_component[0]->id = (const CORBA::Char *)"ODdemo::calculator"; // オブジェクトのタイプ name_component[0]->kind = (const CORBA::Char *)""; // CosNaming::Name領域の獲得 name = CosNaming::Name(1,1,name_component,CORBA_TRUE ); // サーバアプリケーションのオブジェクトリファレンスを獲得 obj = NamingContext_obj-> resolve( *name, *env ); // ODdemo::calculatorクラスへの変換 ODdemo::calculator_ptr ap = ODdemo::calculator::_narrow( obj);
トランザクションを開始するために、Currentインタフェースのオブジェクトリファレンスを取得し、CosTransactions::Current::beginメソッドを呼び出します。
処理の記述例を以下に示します。
CosTransactions::Current_ptr Current; /* トランザクション開始オブジェクトリファレンス */ /* トランザクション開始インタフェースのオブジェクトリファレンスを獲得 */ obj = orb->resolve_initial_refarences( CORBA_ORB_ObjectId_TransactionCurrent, *env); Current = CosTransactions::Current::_narrow(obj); /* トランザクション開始メソッドの呼出し */ Current->begin(*env);
メソッド名は、IDLで指定したモジュール名、インタフェース名、およびオペレーション名をコロン2つ(::)でつなげた形式で指定します。この例では、ODdemo、calculator、およびcalculateが該当します。なお、メソッドを呼出し時に、ネーミングサービスから取得したサーバアプリケーションのオブジェクトリファレンスおよびサーバプログラムで例外が発生した場合、例外情報を獲得するためにCORBA::Environment構造体を指定します。
処理の記述例を以下に示します。
ODdemo::calculator::result res; // 復帰値 CORBA::Long a, b; // パラメタ a = 10; b = 5; // メソッドの呼出し res = ap->calculate( a, b, *env );
サーバアプリケーションのメソッド呼出しの結果を復帰状態から判断し、トランザクションの状態を決定します。トランザクションを正常終了する場合は、CosTransactions::Current::commitメソッドを呼び出し、トランザクションをコミットします。トランザクションを異常終了する場合は、CosTransactions::Current::rollbackメソッドを呼び出し、トランザクションをロールバックします。
処理の記述例を以下に示します。
/* サーバアプリケーションのメソッド呼出しの復帰状態を確認 */ if(env->exception()) Current->rollback(*env); else Current->commit(CORBA_TRUE, *env);
動的起動インタフェースでサーバアプリケーションを呼び出す場合の、クライアントアプリケーションの記述例について説明します。
■初期化
初期化処理として、ORBのオブジェクトリファレンスを取得します。オブジェクトリファレンスを取得するには、初期化メソッドを呼び出します。
記述例を以下に示します。
main(argc, argv ) int argc; char *argv[]; { CORBA::ORB_ptr orb; // ORBのオブジェクトリファレンス CORBA::Environment_ptr env; // 例外情報 int current_argc = argc; env = new CORBA::Environment; // 例外情報 orb = CORBA::ORB_init(current_argc, argv, FJ_OM_ORBid, *env); : }
■ネーミングサービスのオブジェクトリファレンスの獲得
実行するオブジェクトをネーミングサービスから検索するために、ネーミングサービスのオブジェクトリファレンスを取得します。ネーミングサービスのオブジェクトリファレンスには、CORBAインタフェースのオブジェクトリファレンスの取り出しメソッドを使用します。
処理の記述例を以下に示します。
// NamingServiceのオブジェクトリファレンスを獲得 CORBA::Object_ptr obj = orb->resolve_initial_references( CORBA_ORB_ObjectId_NameService, *env ); // NamingContextクラスへの変換 CosNaming::NamingContext_ptr NamingContext_obj = CosNaming::NamingContext::_narrow( obj ); CORBA::release(obj);
■インタフェースリポジトリのサーバアプリケーション情報の獲得
インタフェースリポジトリには、IDLで定義されたモジュール名、インタフェース名、オペレーション名、およびパラメタが階層構造で格納されています。インタフェースリポジトリからサーバアプリケーションの情報を獲得する方法について、以下に示します。
インタフェースリポジトリからサーバアプリケーションの情報を取得するためには、InterfaceDefオブジェクトのオブジェクトリファレンスが必要です。InterfaceDefオブジェクトのオブジェクトリファレンスを求めるには、オブジェクト名をパラメタとして、ネーミングサービスからサーバアプリケーションのオブジェクトリファレンスを求めたあと、CORBA_Object::get::interface()メソッドにより、InterfaceDefオブジェクトリファレンスを取得します。
処理の記述例を以下に示します。
CORBA::Object_ptr obj; // オブジェクトリファレンス格納域 CosNaming::Name_ptr name; // CosNaming::Nameのインスタンス CosNaming::NameComponent_var *name_component; // オブジェクト名格納域 // CosNaming::NameComponent_var領域の獲得 name_component = CosNaming::Name::allocbuf(1); name_component[0]->id = (const CORBA::Char *)"ODdemo::calculator"; // オブジェクト名 name_component[0]->kind = (const CORBA::Char *)""; // オブジェクトのタイプ name = new CosNaming::Name(1,1,name_component,CORBA_TRUE ); // CosNaming::Name領域の獲得 // サーバアプリケーションのオブジェクトリファレンスを獲得 obj = NamingContext_obj-> resolve( *name, *env ); // InterfaceDefオブジェクトリファレンス取得 CORBA::InterfaceDef_ptr intf = obj->_get_interface( *env );
サーバアプリケーションのメソッド名をパラメタとして、CORBA::InterfaceDef::lookup_name()メソッドを使用することにより、インタフェースリポジトリから指定されたメソッドを検索します。結果として、指定したメソッド情報が格納されたOperationDefオブジェクトのオブジェクトリファレンスが通知されます。
// メソッドのOperationDefオブジェクトリファレンス取得 CORBA::ContainedSeq_ptr intf_opr = intf->lookup_name( "calculate", // メソッド名 -1, CORBA::dk_Operation, // Operation情報の取得 CORBA_FALSE, *env ); // OperationDefクラスへの変換 CORBA::OperationDef_ptr OperationDef_obj = CORBA::OperationDef::_narrow((*intf_opr)[0]);
OperationDefオブジェクトリファレンスをパラメタとして、CORBA::OperationDef::describe()メソッドにより、サーバアプリケーションがもっているメソッドのパラメタの情報(パラメタの名前、個数、パラメタの型など)をインタフェースリポジトリから検索します。
// 指定されたメソッドのパラメタ情報を検索 CORBA::Contained::Description *description = OperationDef_obj->describe( *env );
トランザクションを開始するために、Currentインタフェースのオブジェクトリファレンスを取得し、CosTransactions::Current::beginメソッドを呼び出します。
処理の記述例を以下に示します。
CosTransactions::Current_ptr Current; /* トランザクション開始オブジェクトリファレンス */ /* トランザクション開始インタフェースのオブジェクトリファレンスを獲得 */ obj = orb->resolve_initial_refarences( CORBA_ORB_ObjectId_TransactionCurrent, *env); Current = CosTransactions::Current::_narrow(obj); /* トランザクション開始メソッドの呼出し */ Current->begin(*env);
サーバアプリケーションに渡すパラメタを格納するための領域を保持するリストオブジェクトを生成するために、CORBA::ORB::create_list()メソッドに、何個のパラメタを格納するかを指定します。これにより、NVListオブジェクトリファレンスが通知されます。処理の記述例を以下に示します。
// Contained_Description構造体からパラメタ情報構造体の抽出 CORBA::Any tmp_any = *description->value; CORBA::OperationDescription *opr_description = (CORBA::OperationDescription *)tmp_any.value(); // パラメタ情報の抽出 CORBA::ParDescriptionSeq *params = opr_description->parameters; CORBA::NVList *arg_list; // NVList orb->create_list( params->length(), arg_list, *env ); // リストオブジェクトの生成
CORBA_NVListオブジェクトリファレンス、サーバアプリケーションのパラメタの名前、型、値、および長さをパラメタとしてCORBA::NVList::add_value()メソッドにより、サーバアプリケーションに渡すパラメタをリストオブジェクトに設定します。
処理の記述例を以下に示します。
CORBA::Any p1, p2; CORBA::Long x = 10, y = 20; p1 <<= x; p2 <<= y; // パラメタの設定 arg_list->add_value( ((*params)[0])->name, // パラメタ名 p1, // パラメタの型および値 CORBA::ARG_IN, // パラメタのタイプ(in,out, inout) *env ); // パラメタの設定 arg_list->add_value( ((*params)[1])->name, // パラメタ名 p2, // パラメタの型および値 CORBA::ARG_IN, // パラメタのタイプ(in,out, inout) *env );
CORBA::Object::create_request()メソッドにより、リクエストオブジェクトを作成します。リクエストとは、メソッド名にパラメタを加えたものです。リクエストオブジェクトに対して、サーバオブジェクトのオブジェクトリファレンス、NVListオブジェクトリファレンス、後述するNamedValueと呼ぶサーバの処理結果を格納する領域を指定することによりリクエストオブジェクトのオブジェクトリファレンスが通知されます。
処理の記述例を以下に示します。
CORBA::NVList_ptr arg_tmp; // 復帰パラメタ用リストオブジェクトの生成 orb->create_list(1, arg_tmp, *env); ODdemo::calculator::result *res = NULL; CORBA::Any any_tmp( _tc_ODdemo_calculator_result, res, CORBA_FALSE ); // 結果用受取り用変数(CORBA::NamedValue型変数) CORBA::NamedValue_ptr result = arg_tmp->add_value( NULL, // resultの設定 any_tmp, (CORBA::Flags)0, *env); CORBA::Request_ptr request; // リクエストオブジェクトの生成 obj->_create_request( CORBA_OBJECT_NIL, // context "calculate", // メソッド名 arg_list, // 入力パラメタ result, // 復帰値 request, // 出力パラメタの格納域 CORBA::OUT_LIST_MEMORY, *env );
NamedValueは、サーバの処理結果を格納するための領域です。
システムで定義する定義例を以下に示します。
module CORBA { struct NamedValue { identifier name; // パラメタの名前 any argument; // パラメタの値 long len; // パラメタの長さ Flags arg_modes; // パラメタの引き渡し方法(in,out,inout) }; };
class CORBA { class NamedValue { public: const char *name(CORBA::Environment &) const; // パラメタの名前 Any *value(CORBA::Environment &) const; // パラメタの値 Flags flags(CORBA::Environment &) const; // パラメタの引き渡し方法(in,out,inout) }; };
サーバアプリケーションに対してリクエストを送信します。リクエストの方法として、以下の方法があります。
同期送信
非同期送信
それぞれについて、以下に示します。
リクエストオブジェクトのオブジェクトリファレンスをパラメタとして、CORBA::Request::invoke()メソッドにより、サーバアプリケーションを呼び出します。処理の記述例を以下に示します。
request->invoke( *env );
リクエストオブジェクトのオブジェクトリファレンスをパラメタとして、CORBA::Request::send_deferred()メソッドにより、サーバアプリケーションを呼び出します。サーバアプリケーションの処理結果は、CORBA::Request:get_response()メソッドにより受け取ります。
処理の記述例を以下に示します。
request->send_deferred( *env ); // 処理の要求 request->get_response( *env ); // 処理結果の受取り
CORBA::Request::get_response()サーバアプリケーションからリクエストが完了していないことが判明した場合、再度CORBA::Request::get_response()メソッドを呼び出します。
リクエストオブジェクトのオブジェクトリファレンスをパラメタとして、CORBA::release()関数により、リクエストオブジェクトを削除します。また、同様にNVListオブジェクトのオブジェクトリファレンスをパラメタとしてCORBA::release()関数により、NVListオブジェクト削除をします。
処理の記述例を以下に示します。
CORBA::release( request ); // リクエストオブジェクトの削除 CORBA::release( arg_list); // NVListオブジェクトの削除
■トランザクションの完了
サーバアプリケーションのメソッド呼出しの結果を復帰状態から判断し、トランザクションの状態を決定します。トランザクションを正常終了する場合は、CosTransactions::Current::commitメソッドを呼び出し、トランザクションをコミットします。トランザクションを異常終了する場合は、CosTransactions::Current::rollbackメソッドを呼び出し、トランザクションをロールバックします。
処理の記述例を以下に示します。
/* サーバアプリケーションのメソッド呼出しの復帰状態を確認 */ if(env->exception()) Current->rollback(*env); else Current->commit(CORBA_TRUE, *env);