注意:
|
ここでは、CORBAサービスのオブジェクト・トランザクション・サービスに対するC++インタフェースの使い方について説明します。Oracle Tuxedo製品のCORBA環境で利用可能なすべてのトランザクション機能の説明、およびそれらのトランザクション機能を実装する手順については、Oracle Tuxedoオンライン・ドキュメントの 『CORBAトランザクションの使用』を参照してください。
|
Oracle Tuxedo CORBA JavaクライアントとOracle Tuxedo CORBA JavaクライアントORBはTuxedo 8.1で非推奨になり、サポートされなくなりました。Oracle Tuxedo CORBA JavaクライアントおよびOracle Tuxedo CORBA JavaクライアントORBのテキスト参照、関連するコード・サンプルはすべて、サード・パーティのJava ORBライブラリの実装/実行の支援と、プログラマによる参照のみに使用する必要があります。
サード・パーティのCORBA Java ORBのテクニカル・サポートは、各ベンダーによって提供されます。Oracle Tuxedoでは、サード・パーティのCORBA Java ORBに関する技術的なサポートまたはドキュメントは提供していません。
Oracle Tuxedo製品の最も基本的な機能の1つにトランザクション管理があります。トランザクションは、データベース・トランザクションが誤りなく完了し、高パフォーマンス・トランザクションのすべてのACIDプロパティ(原子性、一貫性、独立性、および持続性)が確保されるようにする手段です。Oracle Tuxedoシステムでは、データベースの更新が(様々なリソース・マネージャにまたがる場合でも)誤りなく実行されるようにする完全なインフラストラクチャによってトランザクションの整合性が保護されます。
Oracle Tuxedoシステムは、次のものを使用します。
•
|
CORBAサービスのオブジェクト・トランザクション・サービス(OTS)
|
Oracle Tuxedo製品のCORBA環境では、オブジェクト・トランザクション・サービスに対するC++インタフェースが提供されます。OTSには、TransactionCurrent環境オブジェクトを通じてアクセスします。TransactionCurrent環境オブジェクトの使用方法については、Oracle Tuxedoオンライン・ドキュメントの
『CORBAクライアント・アプリケーションの作成』を参照してください。
OTSでは、ビジネス・トランザクションについて以下のサポートが提供されます。
•
|
クライアント・アプリケーションによってトランザクションが開始されたときにグローバル・トランザクション識別子が作成されます。
|
•
|
トランザクションに関与し、トランザクションがコミットされるときにコーディネートする必要のあるオブジェクトがTPフレームワークと共同でトラッキングされます。
|
•
|
リソース・マネージャ(データベースが多い)がトランザクションのかわりにアクセスされたときにそのことがリソース・マネージャに通知されます。リソース・マネージャはトランザクションが終了するまでアクセスされたレコードをロックします。
|
•
|
トランザクションが完了したときに2フェーズ・コミットが調整され、トランザクションのすべての参加リソースで更新が同時にコミットされます。Open Group XAプロトコルを使用して、更新されるすべてのデータベースでコミットがコーディネートされます。この規格は、ほぼすべてのリレーショナル・データベースでサポートされています。
|
•
|
トランザクションが停止されるときにロールバック手続きが実行されます。
|
•
|
障害が発生したときにリカバリ手続きが実行されます。クラッシュ発生時にマシンでどのトランザクションがアクティブだったのかが判別され、続いて、トランザクションをロールバックすべきなのか、またはコミットすべきなのかが判断されます。
|
図5-1は、Oracle Tuxedo CORBAアプリケーションでトランザクションがどのように機能するのかを示しています。
基本的なトランザクションは、以下のように動作します。
1.
|
クライアント・アプリケーションが、Bootstrapオブジェクトを使用してOracle TuxedoドメインのTransactionCurrentオブジェクトのオブジェクト参照を取得します。
|
2.
|
クライアント・アプリケーションが、 Tobj::TransactionCurrent::begin()メソッドを使用してトランザクションを開始し、TPフレームワークを通じてCORBAインタフェースにリクエストを発行します。CORBAインタフェースのすべての操作は、トランザクションのスコープ内で実行されます。
|
•
|
それらのいずれかの操作の呼出しで(明示的にまたは通信障害の結果として)例外が生成された場合は、その例外を取得し、トランザクションをロールバックできます。
|
•
|
例外が発生しない場合、クライアント・アプリケーションでは Tobj::TransactionCurrent::commit()メソッドを使用して現在のトランザクションをコミットします。このメソッドは、トランザクションを終了して、操作の処理を開始します。トランザクションは、トランザクションのすべての参加リソースがコミットに同意した場合にのみコミットされます。
|
3.
|
Tobj::TransactionCurrent::commit()メソッドにより、トランザクションを完了するためにTPフレームワークからトランザクション・マネージャが呼び出されます。
|
4.
|
トランザクション・マネージャがデータベースを更新します。
|
注意:
|
Oracle Tuxedo CORBAでは、CORBA Interoperable Naming Service (INS)を利用してもセキュリティ・サービスの初期オブジェクト参照を取得できます。INSブートストラップ処理メカニズムについては、 『CORBAプログラミング・リファレンス』を参照してください。
|
Transactionsサンプル・アプリケーション
Transactionsサンプル・アプリケーションでは、コースの登録の操作がトランザクションのスコープ内で実行されます。Transactionsサンプル・アプリケーションで使用されるトランザクション・モデルは、会話型モデルと、単一クライアントの呼出しでデータベースの複数の個別操作が呼び出されるモデルを組み合せたものです。
Transactionsサンプル・アプリケーションは、以下のように機能します。
2.
|
リストの各コースについて、CORBAサーバー・アプリケーションが次のことをチェックします。
|
•
|
コースがすべての基準を満たす場合は、CORBAサーバー・アプリケーションによってそのコースで学生が登録されます。
|
•
|
コースがデータベースにない場合、またはそのコースで学生がすでに登録されている場合は、CORBAサーバー・アプリケーションによって、学生を登録できないコースのリストにそのコースが追加されます。すべての登録リクエストが処理された後、登録に失敗したコースのリストがCORBAサーバー・アプリケーションから返されます。CORBAクライアント・アプリケーションでは、トランザクションをコミットするか(登録リクエストが成功したコースで学生が登録される)、またはトランザクションをロールバックするか(どのコースにも学生は登録されない)を選択できます。
|
•
|
学生が履修できる単位の最大数を超えている場合は、 TooManyCreditsユーザー例外がCORBAサーバー・アプリケーションからCORBAクライアント・アプリケーションに返されます。CORBAクライアント・アプリケーションでは、リクエストが拒否されたことを説明する短いメッセージが表示されます。その後、CORBAクライアント・アプリケーションによってトランザクションがロールバックされます。
|
図5-2は、Transactionsサンプル・アプリケーションのしくみを示しています。
Transactionsサンプル・アプリケーションは、次の2とおりの方法でトランザクションをロールバックします。
•
|
致命的ではない場合。コースがデータベースに存在しないか、学生がすでに登録されているためにコースの登録が失敗する場合は、それらのコースの数がCORBAサーバー・アプリケーションからCORBAクライアント・アプリケーションに返されます。トランザクションをロールバックするかどうかの決断は、CORBAクライアント・アプリケーションのユーザーが行います。
|
•
|
致命的な場合。登録できる単位の最大数を超えているためにコースの登録が失敗する場合は、CORBAサーバー・アプリケーションによってCORBA例外が生成され、その例外がCORBAクライアント・アプリケーションに返されます。この場合も、トランザクションをロールバックするかどうかは、CORBAクライアント・アプリケーションに依存します。
|
ここでは、トランザクションが含まれるOracle Tuxedo CORBAアプリケーションの開発手順を説明します。
表5-1は、開発手順を示しています。
表5-1
トランザクションの含まれるOracle Tuxedo CORBAアプリケーションの開発手順
|
|
|
トランザクションに関与するCORBAインタフェースのOMG IDLコードを記述します。
|
|
実装構成ファイル(ICF)でCORBAインタフェースのトランザクション・ポリシーを定義します。
|
|
CORBAクライアント・アプリケーションを記述します。
|
|
CORBAサーバー・アプリケーションを記述します。
|
|
|
この開発手順では、Transactionsサンプル・アプリケーションを例に挙げて説明します。Transactionsサンプル・アプリケーションのソース・ファイルは、Oracle Tuxedoソフトウェアの
\samples\corba\universityディレクトリにあります。Transactionsサンプル・アプリケーションのビルドと実行については、Oracle Tuxedoオンライン・ドキュメントの
『CORBA Universityサンプル・アプリケーション・ガイド』を参照してください。
ほかのCORBAインタフェースの場合と同じように、トランザクションに関与するインタフェースをObject Management Group (OMG)インタフェース定義言語(IDL)で指定する必要があります。また、そのインタフェースを使用して発生する可能性のあるすべてのユーザー例外を指定することも必要です。
Transactionsサンプル・アプリケーションでは、
Registrarインタフェースと
register_for_courses()操作をOMG IDLで定義します。
register_for_courses()操作には、
NotRegisteredListというパラメータがあります。このパラメータは、登録の失敗したコースのリストをCORBAクライアント・アプリケーションに返します。
NotRegisteredListの値が空の場合、CORBAクライアント・アプリケーションはトランザクションをコミットします。また、
TooManyCreditsユーザー例外も定義する必要があります。
リスト5‑1は、Transactionsサンプル・アプリケーションのOMG IDLコードを示しています。
リスト5-1
Transactionsサンプル・アプリケーションのOMG IDLコード
#pragma prefix "beasys.com"
module UniversityT
{
typedef unsigned long CourseNumber;
typedef sequence<CourseNumber> CourseNumberList;
struct CourseSynopsis
{
CourseNumber course_number;
string title;
};
typedef sequence<CourseSynopsis> CourseSynopsisList;
interface CourseSynopsisEnumerator
{
//Returns a list of length 0 if there are no more entries
CourseSynopsisList get_next_n(
in unsigned long number_to_get, // 0 = return all
out unsigned long number_remaining
);
void destroy();
};
typedef unsigned short Days;
const Days MONDAY = 1;
const Days TUESDAY = 2;
const Days WEDNESDAY = 4;
const Days THURSDAY = 8;
const Days FRIDAY = 16;
//Classes restricted to same time block on all scheduled days,
//starting on the hour
struct ClassSchedule
{
Days class_days; // bitmask of days
unsigned short start_hour; // whole hours in military time
unsigned short duration; // minutes
};
struct CourseDetails
{
CourseNumber course_number;
double cost;
unsigned short number_of_credits;
ClassSchedule class_schedule;
unsigned short number_of_seats;
string title;
string professor;
string description;
};
typedef sequence<CourseDetails> CourseDetailsList;
typedef unsigned long StudentId;
struct StudentDetails
{
StudentId student_id;
string name;
CourseDetailsList registered_courses;
};
enum NotRegisteredReason
{
AlreadyRegistered,
NoSuchCourse
};
struct NotRegistered
{
CourseNumber course_number;
NotRegisteredReason not_registered_reason;
};
typedef sequence<NotRegistered> NotRegisteredList;
exception TooManyCredits
{
unsigned short maximum_credits;
};
//The Registrar interface is the main interface that allows
//students to access the database.
interface Registrar
{
CourseSynopsisList
get_courses_synopsis(
in string search_criteria,
in unsigned long number_to_get,
out unsigned long number_remaining,
out CourseSynopsisEnumerator rest);
CourseDetailsList get_courses_details(in CourseNumberList
courses);
StudentDetails get_student_details(in StudentId student);
NotRegisteredList register_for_courses(
in StudentId student,
in CourseNumberList courses
) raises (
TooManyCredits
);
// The RegistrarFactory interface finds Registrar interfaces.
interface RegistrarFactory
{
Registrar find_registrar(
);
};
ステップ2:インタフェースのトランザクション・ポリシーの定義
トランザクション・ポリシーは、インタフェースごとに使用されます。設計時に、Oracle Tuxedo CORBAアプリケーション内のどのインタフェースでトランザクションを処理するかを決定します。
次の表は、トランザクション・ポリシーのリストです。
|
|
|
インタフェースは常にトランザクションの一部である必要があります。インタフェースがトランザクションの一部ではない場合、トランザクションはTPフレームワークによって自動的に開始されます。
|
|
インタフェースはトランザクションに関与しません。ただし、トランザクションのスコープ内でこのインタフェースにリクエストを行うことはできます。このインタフェースの UBBCONFIGファイルで指定される AUTOTRANパラメータは無視されます。
|
|
インタフェースはトランザクションに関与しません。このインタフェース用に作成されるオブジェクトは、トランザクションに関与できません。Oracle Tuxedoシステムは、このポリシーが設定されているインタフェースがトランザクションに関与した場合に INVALID_TRANSACTION例外を生成します。
|
|
インタフェースはトランザクションに関与できます。リクエストがトランザクションに関係する場合、オブジェクトはトランザクションに関与できます。このトランザクション・ポリシーはデフォルトです。
注意:
|
リクエストのトランザクション・プロパティは、 autotranパラメータを使用しても定義できます。
|
|
開発段階では、トランザクション・ポリシーを割り当てることで、どのインタフェースがトランザクションで実行されるのかを定義します。
CORBAサーバー・アプリケーションでは、実装構成ファイル(ICF)でトランザクション・ポリシーを指定します。
genicfコマンドを実行すると、テンプレートのICFファイルが作成されます。
Transactionsサンプル・アプリケーションでは、
Registrarインタフェースのトランザクション・ポリシーが
alwaysに設定されます。
ステップ3: CORBAクライアント・アプリケーションの記述
CORBAクライアント・アプリケーションでは、次のタスクを実行するコードが必要です。
1.
|
BootstrapオブジェクトからTransactionCurrentオブジェクトまたはTransactionFactoryオブジェクトのリファレンスを取得します。
|
2.
|
TransactionCurrentオブジェクトの Tobj::TransactionCurrent::begin()操作を呼び出してトランザクションを開始します。
|
3.
|
オブジェクトの操作を呼び出します。Transactionsサンプル・アプリケーションでは、CORBAクライアント・アプリケーションが(コースのリストを渡して) Registrarオブジェクトの register_for_courses()操作を呼び出します。
|
リスト5‑2は、トランザクションの開発手順を説明するTransactionsサンプル・アプリケーションのCORBA C++クライアント・アプリケーションの一部分です。
リスト5-2
CORBA C++クライアント・アプリケーションのトランザクション・コード
CORBA::Object_var var_transaction_current_oref =
Bootstrap.resolve_initial_references("TransactionCurrent");
CosTransactions::Current_var var_transaction_current_ref=
CosTransactions::Current::_narrow(var_transaction_current_oref.in());
//Begin the transaction
var_transaction_current_ref->begin();
try {
// Perform the operation inside the transaction
pointer_Registar_ref->register_for_courses(student_id, course_number_list);
// ...
// If operation executes with no errors, commit the transaction:
CORBA::Boolean report_heuristics = CORBA_TRUE;
var_transaction_current_ref->commit(report_heuristics);
}
catch (...) {
// If the operation has problems executing, rollback the
// transaction. Then throw the original exception again.
// If the rollback fails, ignore the exception and throw the
// original exception again.
try {
var_transaction_current_ref->rollback();
}
catch (...) {
TP::userlog("rollback failed");
}
throw;
}
ステップ4: CORBAサーバー・アプリケーションの記述
CORBAサーバー・アプリケーションでトランザクションを使用する場合は、インタフェースの操作を実装するメソッドを記述する必要があります。Transactionsサンプル・アプリケーションでは、
register_for_courses()操作のメソッド実装を記述します。
Oracle Tuxedo CORBAアプリケーションでデータベースを使用する場合は、XAリソース・マネージャを開閉するコードがCORBAサーバー・アプリケーションで必要となります。それらの操作は、Serverオブジェクトの
Server::initialize()操作と
Server::release()操作に含められます。
リスト5‑3は、XAリソース・マネージャをオープンおよびクローズするTransactionsサンプル・アプリケーションのServerオブジェクトのコードの一部分です。
注意:
|
トランザクションを実装するC++サーバー・アプリケーションの完全な例については、Oracle Tuxedoオンライン・ドキュメントの 『CORBAトランザクションの使用』のTransactionsサンプル・アプリケーションを参照してください。
|
リスト5-3
Transactionsサンプル・アプリケーションのC++ Serverオブジェクト
CORBA::Boolean Server::initialize(int argc, char* argv[])
{
TRACE_METHOD("Server::initialize");
try {
open_database();
begin_transactional();
register_fact();
return CORBA_TRUE;
}
catch (CORBA::Exception& e) {
LOG("CORBA exception : " <<e);
}
catch (SamplesDBException& e) {
LOG("Can���t connect to database");
}
catch (...) {
LOG("Unexpected exception");
}
cleanup();
return CORBA_FALSE;
}
void Server::release()
{
TRACE_METHOD("Server::release");
cleanup();
}
static void cleanup()
{
unregister_factory();
end_transactional();
close_database();
}
// Utilities to manage transaction resource manager
CORBA::Boolean s_became_transactional = CORBA_FALSE;
static void begin_transactional()
{
TP::open_xa_rm();
s_became_transactional = CORBA_TRUE;
}
static void end_transactional()
{
if(!s_became_transactional){
// cleanup not necessary
return;
}
try {
TP::close_xa_rm ();
}
catch (CORBA::Exception& e) {
LOG("CORBA Exception : " << e);
}
catch (...) {
LOG("unexpected exception");
}
s_became_transactional = CORBA_FALSE;
}
トランザクション対応Oracle Tuxedo CORBAアプリケーションの構成ファイルには、次の情報を追加する必要があります。
•
|
SERVERSセクションで、CORBAサーバー・アプリケーションおよびデータベースを管理するアプリケーションのトランザクション・グループを指定します。
|
•
|
GROUPSセクションで、サーバー・グループを定義します。 GROUPSセクションの OPENINFOパラメータと CLOSEINFOパラメータで、データベースのXAリソース・マネージャを開閉するための情報を設定します。この情報は、データベースの製品ドキュメントから取得します。デフォルトの com.beasys.Tobj.Server.initialize()操作は、リソース・マネージャを自動的に開きます。
|
リスト5‑4は、Transactionsサンプル・アプリケーションの構成ファイルでこの情報が定義されている部分です。
リスト5-4
Transactionsサンプル・アプリケーションの構成ファイル
*RESOURCES
IPCKEY 55432
DOMAINID university
MASTER SITE1
MODEL SHM
LDBAL N
SECURITY APP_PW
*MACHINES
BLOTTO
LMID = SITE1
APPDIR = C:\TRANSACTION_SAMPLE
TUXCONFIG=C:\TRANSACTION_SAMPLE\tuxconfig
TLOGDEVICE=C:\APP_DIR\TLOG
TLOGNAME=TLOG
TUXDIR="C:\tuxdir"
MAXWSCLIENTS=10
*GROUPS
SYS_GRP
LMID = SITE1
GRPNO = 1
ORA_GRP
LMID = SITE1
GRPNO = 2
OPENINFO = "ORACLE_XA:Oracle_XA+SqlNet=ORCL+Acc=P
/scott/tiger+SesTm=100+LogDir=.+MaxCur=5"
OPENINFO = "ORACLE_XA:Oracle_XA+Acc=P/scott/tiger
+SesTm=100+LogDir=.+MaxCur=5"
CLOSEINFO = ""
TMSNAME = "TMS_ORA"
*SERVERS
DEFAULT:
RESTART = Y
MAXGEN = 5
TMSYSEVT
SRVGRP = SYS_GRP
SRVID = 1
TMFFNAME
SRVGRP = SYS_GRP
SRVID = 2
CLOPT = "-A -- -N -M"
TMFFNAME
SRVGRP = SYS_GRP
SRVID = 3
CLOPT = "-A -- -N"
TMFFNAME
SRVGRP = SYS_GRP
SRVID = 4
CLOPT = "-A -- -F"
TMIFRSVR
SRVGRP = SYS_GRP
SRVID = 5
UNIVT_SERVER
SRVGRP = ORA_GRP
SRVID = 1
RESTART = N
ISL
SRVGRP = SYS_GRP
SRVID = 6
CLOPT = -A -- -n //MACHINENAME:2500
トランザクション・ログおよび構成ファイルでのパラメータの定義については、Oracle Tuxedoオンライン・ドキュメントの
『Oracle Tuxedoアプリケーションの設定』を参照してください。