ここでは,サービス活性化のodbのサンプルについて説明します。サンプルはBorland Enterprise Server VisiBrokerをインストールしたディレクトリのexamples/vbe/boa/odbに入っています。このディレクトリには,表29-1のファイルも含まれます。
表29-1 サービス活性化用odbのサンプルファイル
ファイル名 | 説明 |
---|---|
odb.idl | DBインタフェースとDBObjectインタフェースのIDL |
Server.C(C++) Server.java(Java) | サービスアクティベータを使用してオブジェクトを生成し,オブジェクトのIORを返し,オブジェクトを非活性化します。 |
Creator.C(C++) Creator.java(Java) | 100個のオブジェクトを生成するためにDBインタフェースを呼び出し,結果として生じた文字列化オブジェクトリファレンスをファイル(objref.out)に格納します。 |
Client.C(C++) Client.java(Java) | オブジェクトの文字列化オブジェクトリファレンスをファイルから読み出して,それらに対する呼び出しを行い,サーバ内のアクティベータにオブジェクトを生成させます。 |
Makefile | makeまたはnmake(Windowsの場合)がodbサブディレクトリ内で呼び出された時に,次に示すクライアントプログラムとサーバプログラムを生成します。
|
odbのサンプルは,一つのサービスから任意の数のオブジェクトがどのように作成できるかを示します。サービス単体は,IORの一部として格納された各オブジェクトのリファレンスデータとともに,各オブジェクトではなくBOAに登録されます。これによって,オブジェクトキーをオブジェクトリファレンスの一部として格納できるので,OODB(オブジェクト指向データベース)統合を簡易化できます。未生成のオブジェクトをクライアントが呼び出す場合,BOAはユーザが定義したActivatorを呼び出します。すると,アプリケーションは適切なオブジェクトをパーシステント記憶領域からロードできます。
このサンプルでは,「DBService」という名前のサービスに対してオブジェクトを活性化し,非活性化する責任のあるActivatorが生成されます。このActivatorが生成するオブジェクトのリファレンスには,VisiBroker ORBがDBServiceサービスのActivatorを再検索し,Activatorが要求に応じてこれらのオブジェクトを再生成するために十分な情報が含まれています。
DBServiceサービスはDBObjectインタフェースをインプリメントするオブジェクトに対して責任があります。インタフェース(odb.idlに含まれる)はこれらのオブジェクトの手動生成をできるようにするために提供されます。
odb.idlインタフェースはDBObject odbインタフェースをインプリメントするオブジェクトの手動生成をできるようにします。
interface DBObject {
string get_name();
};
typedef sequence<DBObject> DBObjectSequence;
interface DB {
DBObject create_object(in string name);
};
DBObjectインタフェースはDBインタフェースが生成したオブジェクトを表し,サービスオブジェクトとして取り扱えます。
DBObjectSequenceはDBObjectのシーケンスです。サーバはこのシーケンスを使って,現在活性化しているオブジェクトを把握します。
DBインタフェースはcreate_objectオペレーションを使って一つ以上のDBObjectを生成します。DBインタフェースが生成したオブジェクト群は,サービスとして一つにまとめることができます。
idl2cppコンパイラは,boa/odb/odb.idlからスケルトンクラス_sk_DBObject用に2種類のコンストラクタを生成します。最初のコンストラクタは手動実体化オブジェクトで使用します。二つ目のコンストラクタはオブジェクトをサービスの一部にします。コードサンプル29-5に示すように,DBObjectのインプリメンテーションは,手動実体化オブジェクトで一般に使用されるobject_nameコンストラクタではなく,サービスコンストラクタを使用してベースの_sk_DBObjectメソッドを構築します。この種のコンストラクタを起動して,DBObjectはそれ自身をDBServiceというサービスの一部として構築します。
class DBObjectImpl: public _sk_DBObject {
private:
CORBA::String_var_name;
public:
DBObjectImpl(const char *nm,
const CORBA::ReferenceData& data)
: _sk_DBObject("DBService", data), _name(nm) {}
. . .
}
通常,オブジェクトをインプリメントしているC++またはJavaクラスをサーバが実体化し,次にBOA::obj_is_ready(C++),BOA::impl_is_ready(C++)またはobj_is_ready(Java),impl_is_ready(Java)の順で呼び出すと,オブジェクトが活性化されます。オブジェクトの活性化を遅延させるには,BOAがオブジェクト活性化中に呼び出すactivateメソッドの制御を得る必要があります。この制御を得るには,extension::Activator(C++)またはcom.inprise.vbroker.extension.Activator(Java)から新たなクラスを派生させ,activateメソッドを変更し,変更したactivateメソッドを使ってオブジェクト固有のC++クラスまたはJavaクラスを実体化します。
odbのサンプルでは,DBActivatorクラスがextension::Activator(C++)またはcom.inprise.vbroker.extension.Activator(Java)から派生し,activateメソッドとdeactivateメソッドを変更します。DBObjectはactivateメソッド内に構築されます。
class DBActivator: public extension::Activator {
virtual CORBA::Object_ptr activate(
CORBA::ImplementationDef_ptr impl);
virtual void deactivate(CORBA::Object_ptr,
CORBA::ImplementationDef_ptr impl );
public:
DBActivator(CORBA::BOA_ptr boa) : _boa(boa) {}
private:
CORBA::BOA_ptr _boa;
};
// Server.java
class DBActivator implements Activator {
private static int _count;
private com.inprise.vbroker.CORBA.BOA _boa;
public DBActivator(com.inprise.vbroker.CORBA.BOA boa) {
_boa = boa;
}
public org.omg.CORBA.Object activate(
com.inprise.vbroker.extension.ImplementationDef impl) {
System.out.printIn("Activator called " + ++_count + " times");
byte[ ] ref_data = ((ActivationImplDef) impl).id();
DBObjectImpl obj = new DBObjectImpl(new String(ref_data));
_boa.obj_is_ready(obj);
return obj;
}
public void deactivate(org.omg.CORBA.Object obj, ImplementationDef impl) {
// nothing to do here...
}
}
コードサンプル29-8に示すように,DBActivatorクラスはそのCORBA::ReferenceDataパラメタに基づいてオブジェクトを生成します(C++)。コードサンプル29-9では,DBActivatorクラスがReferenceDataパラメタに基づいてオブジェクトを生成する方法を示します(Java)。BOAはActivatorの責任の下でオブジェクトを求めるクライアントリクエストを受信すると,そのActivatorに対してactivateメソッドを起動します。このメソッドを呼び出す時,BOAはActivatorにImplementationDefパラメタを引き渡すことによって,活性化されたオブジェクトインプリメンテーションを一意に識別します。このパラメタから,インプリメンテーションはリクエストされたオブジェクトの一意の識別子であるCORBA::ReferenceData(C++)またはReferenceData(Java)を取得できます。
CORBA::Object_ptr DBActivator::activate(
CORBA::ImplementationDef_ptr impl) {
extension::ActivationImplDef* actImplDef =
extension::ActivationImplDef::_downcast(impl);
CORBA::ReferenceData_var id(actImplDef->id());
cout << "Activate called for object=[" << (char*) id->data()
<< "]" << endl;
DBObjectImpl *obj = new DBObjectImpl((char *)id->data(), id);
_impls.length(_impls.length() +1);
_impls[_impls.length()-1] = DBObject::_duplicate(obj);
_boa->obj_is_ready(obj);
return obj;
}
public org.omg.CORBA.Object activate(ImplementationDef impl) {
System.out.println("Activator called " + ++_count + " times");
byte[ ] ref_data = ((ActivationImplDef) impl) .id();
DBObjectImpl obj = new DBObjectImpl(new String(ref_data));
_boa.obj_is_ready(obj);
return obj;
}
コードサンプル29-10に示すように,DBActivatorサービスアクティベータは,メインサーバプログラムのBOA::impl_is_ready呼び出しを使って生成され,BOAに登録されます(C++)。コードサンプル29-11は,メインサーバプログラムのimpl_is_ready呼び出しによってDBActivatorサービスアクティベータを作成し,登録するJavaの例を示します。
DBActivatorサービスアクティベータは,DBServiceサービスに属するすべてのオブジェクトに対して責任を持ちます。DBServiceサービスのオブジェクトを求めるリクエストはすべてDBActivatorサービスアクティベータを通じて指示されます。このサービスアクティベータによって活性化されたオブジェクトはすべてそれらがDBServiceサービスに属していることをVisiBroker ORBに通知するリファレンスを持っています。
int main(int argc, char **argv) {
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
CORBA::BOA_ptr boa = orb->BOA_init(argc, argv);
MyDB db("Database Manager");
boa->obj_is_ready(&db);
DBObjectImplReaper reaper;
reaper.start();
cout << "Server is ready to receive requests" << endl;
boa->impl_is_ready("DBService", new DBActivator(boa));
return(0);
}
public static void main(String[ ] args) {
org.omg.CORBA.ORB orb = ORB.init(args, null);
com.inprise.vbroker.CORBA.BOA boa
= ((com.inprise.vbroker.orb.ORB )orb).BOA_init();
DB db = new DBImpl("Database Manager");
boa.obj_is_ready(db);
boa.impl_is_ready("DBService", new DBActivator(boa));
}
BOA::impl_is_ready(C++)またはimpl_is_ready(Java)の呼び出しは,通常のBOA::impl_is_ready(C++)またはimpl_is_ready(Java)の呼び出しの変形であり,次のように引数を二つ持つことに注意してください。
オブジェクトが構築されるたびに,BOA::obj_is_readyをDBActivator::activate内で明示的に呼び出す必要があります。サーバプログラムにはBOA::obj_is_readyに対して二つの呼び出しがあります。第一の呼び出しはサーバがサービスオブジェクトを生成し,生成元プログラムにIORを返した時に発生します。
DBObject_ptr create_object(const char *name) {
char ref_data[100];
memset(ref_data,'¥0',100);
sprintf(ref_data, "%s", name);
CORBA::ReferenceData id(100, 100, (CORBA::Octet *)ref_data);
DBObjectImpl *obj = new DBObjectImpl(name, id);
_boa()->obj_is_ready(obj);
_impls.length(_impls.length() + 1);
_impls[_impls.length()-1] = DBObject::_duplicate(obj);
return obj;
}
BOA::obj_is_readyへの第二の呼び出しは,DBActivator::activate内にあり,これは明示的に呼び出す必要があります。コンテキスト内でのこの第二の呼び出しについては,コードサンプル29-8を参照してください。
オブジェクトが構築されるたびに,obj_is_readyをactivate()メソッド内で明示的に呼び出す必要があります。サーバプログラムにはobj_is_readyに対して二つの呼び出しがあります。第一の呼び出しはサーバがサービスオブジェクトを生成し,生成元プログラムにIORを返した時に発生します。
public DBObject create_object(String name) {
System.out.println("Creating: " + name);
DBObject dbObject = new DBObjectImpl(name);
_boa().obj_is_ready(dbObject, "DBService", name.getBytes());
return dbObject;
}
obj_is_readyへの第二の呼び出しは,activate内にあり,これは明示的に呼び出す必要があります。コンテキスト内でのこの第二呼び出しについては,コードサンプル29-9を参照してください。