POAのアクティブオブジェクトマップがきわめて大きくなりメモリを消費するような状況はよくあります。メモリ消費量を減らすために,サーバントとオブジェクトの対応をアクティブオブジェクトマップに格納しないという意味のRequestProcessingPolicy::USE_SERVANT_MANAGERとServantRetentionPolicy::NON_RETAIN(C++)設定,またはRequestProcessingPolicy.USE_SERVANT_MANAGERとServantRetentionPolicy.NON_RETAIN(Java)設定でPOAを作成できます。対応が格納されないので,ServantLocatorサーバントマネージャをリクエストごとに起動できます。
サーバントロケータを使用したリクエストの処理中には,次のようなイベントが発生します。
int main(int argc, char* const* argv) {
try {
// Initialize the ORB.
CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
// And the Data source
DataStore::_create();
// get a reference to the rootPOA
CORBA::Object_var obj =
orb->resolve_initial_references("RootPOA");
PortableServer::POA_var rootPOA =
PortableServer::POA::_narrow(obj);
CORBA::PolicyList policies;
policies.length(3);
// Create a child POA with Persistence life span policy
// that uses servant manager with non-retain retention
// policy ( no Active Object Map ) causing the POA to use
// the servant locator.
policies[(CORBA::ULong)0] =
rootPOA->create_lifespan_policy
(PortableServer::PERSISTENT);
policies[(CORBA::ULong)1] =
rootPOA->create_servant_retention_policy
(PortableServer::NON_RETAIN);
policies[(CORBA::ULong)2] =
rootPOA->create_request_processing_policy
(PortableServer::USE_SERVANT_MANAGER);
PortableServer::POAManager_var rootManager =
rootPOA->the_POAManager();
PortableServer::POA_var myPOA =
rootPOA->create_POA("bank_servant_locator_poa",
rootManager, policies);
// Create the servant locator
AccountManagerLocator servant_locator_impl;
myPOA->set_servant_manager(&servant_locator_impl);
// Generate two references - one for checking and another
// for savings.Note that we are not creating any
// servants here and just manufacturing a reference which
// is not yet backed by a servant
PortableServer::ObjectId_var an_oid =
PortableServer::string_to_ObjectId
("CheckingAccountManager");
CORBA::Object_var cref = myPOA->create_reference_with_id
(an_oid.in(), "IDL:Bank/AccountManager:1.0");
an_oid = PortableServer::string_to_ObjectId
("SavingsAccountManager");
CORBA::Object_var sref = myPOA->create_reference_with_id
(an_oid.in(), "IDL:Bank/AccountManager:1.0");
// Activate the POA Manager
rootManager->activate();
// Write out Checking reference
CORBA::String_var string_ref =
orb->object_to_string(cref.in());
ofstream crefFile("cref.dat");
crefFile << string_ref << endl;
crefFile.close();
// Now write out the Savings reference
string_ref = orb->object_to_string(sref.in());
ofstream srefFile("sref.dat");
srefFile << string_ref << endl;
srefFile.close();
// Wait for incoming requests
cout << "Bank Manager is ready" << endl;
orb->run();
// Destroy the accounts database
DataStore::_destroy();
}
catch(const CORBA::Exception& e) {
cerr << e << endl;
}
return 1;
}
import org.omg.PortableServer.*;
public class Server {
public static void main(String[ ] args) {
try {
// Initialize the ORB.
org.omg.CORBA.ORB orb =
org.omg.CORBA.ORB.init(args,null);
// get a reference to the rootPOA
POA rootPOA = POAHelper.narrow(
orb.resolve_initial_references("RootPOA"));
// Create policies for our POA.
// We need persistence life span,
// use servant manager request processing
// policies and non retain retention policy.
// This non retain policy will let us use the
// servant locator instead of servant activator
org.omg.CORBA.Policy[ ] policies = {
rootPOA.create_lifespan_policy(
LifespanPolicyValue.PERSISTENT),
rootPOA.create_servant_retention_policy(
ServantRetentionPolicyValue.NON_RETAIN),
rootPOA.create_request_processing_policy(
RequestProcessingPolicyValue.
USE_SERVANT_MANAGER)
};
// Create myPOA with the right policies
POA myPOA = rootPOA.create_POA(
"bank_servant_locator_poa",
rootPOA.the_POAManager(),
policies );
// Create the servant locator servant
// and get its reference
ServantLocator sl =
new AccountManagerLocator()._this(orb);
// Set the servant locator on our POA
myPOA.set_servant_manager(sl);
org.omg.CORBA.Object ref ;
// Activate the POA manager
rootPOA.the_POAManager().activate();
// Generate the reference and write it out.
// One for each Checking and Savings
// account types .Note that we are not creating
// any servants here and just manufacturing a
// reference which is not yet backed by a servant.
try {
ref = myPOA.create_reference_with_id(
"CheckingAccountManager".getBytes(),
"IDL:Bank/AccountManager:1.0");
// Write out checking object ID
java.io.PrintWriter pw =
new java.io.PrintWriter(
new java.io.FileWriter("cref.dat"));
pw.println(orb.object_to_string(ref));
pw.close();
ref = myPOA.create_reference_with_id(
"SavingsAccountManager".getBytes(),
"IDL:Bank/AccountManager:1.0");
// Write out savings object ID
pw = new java.io.PrintWriter(
new java.io.FileWriter("sref.dat"));
System.gc();
pw.println(orb.object_to_string(ref));
pw.close();
} catch ( java.io.IOException e ){
System.out.println(
"Error writing the IOR to file");
return;
}
System.out.println("BankManager is ready.");
// Wait for incoming requests
orb.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}
このサンプルのサーバントマネージャは,次のとおりです。
// Servant Locator
class AccountManagerLocator :
public PortableServer::ServantLocator {
public:
AccountManagerLocator (){}
// preinvoke is very similar to ServantActivator 's
// incarnate method but gets called every time a
// request comes in unlike incarnate() which gets called
// every time the POA does not find a servant in the
// active object map
virtual PortableServer::Servant preinvoke
(const PortableServer::ObjectId& oid,
PortableServer::POA_ptr adapter,
const char* operation,
PortableServer::ServantLocator::
Cookie& the_cookie) {
CORBA::String_var s =
PortableServer::ObjectId_to_string (oid);
cout << "¥nAccountManagerLocator.preinvoke called
with ID = " << s << endl;
PortableServer::Servant servant;
if ( VISPortable::vstricmp( (char *)s,
"SavingsAccountManager" ) == 0 )
//Create CheckingAccountManager Servant
servant = new SavingsAccountManagerImpl;
else if ( VISPortable::vstricmp( (char *)s,
"CheckingAccountManager" ) == 0 )
// Create CheckingAccountManager Servant
servant = new CheckingAccountManagerImpl;
else
throw CORBA::OBJECT_NOT_EXIST();
// Note also that we do not spawn of a thread to
// explicitly deactivate an object unlike a servant
// activator , this is because the POA itself calls
// post invoke after the request is complete.In the
// case of a servant activator the POA calls
// etherealize() only if the object is deactivated
// by calling poa->de_activate object or the POA
// itself is destroyed.
//return the servant
return servant;
}
virtual void postinvoke (const PortableServer::ObjectId& oid,
PortableServer::POA_ptr adapter,
const char* operation,
PortableServer::ServantLocator::Cookie the_cookie,
PortableServer::Servant the_servant) {
CORBA::String_var s =
PortableServer::ObjectId_to_string (oid);
cout << "¥nAccountManagerLocator.postinvoke called
with ID = " << s << endl;
delete the_servant;
}
};
import org.omg.PortableServer.*;
import org.omg.PortableServer.
ServantLocatorPackage.CookieHolder;
public class AccountManagerLocator extends
ServantLocatorPOA {
public Servant preinvoke (byte[ ] oid,POA adapter,
java.lang.String operation,
CookieHolder the_cookie) throws ForwardRequest {
String accountType = new String(oid);
System.out.println(
"¥nAccountManagerLocator.
preinvoke called with ID = " +
accountType + "¥n");
if ( accountType.equalsIgnoreCase
("SavingsAccountManager"))
return new SavingsAccountManagerImpl();
return new CheckingAccountManagerImpl();
}
public void postinvoke (byte[ ] oid,
POA adapter,
java.lang.String operation,
java.lang.Object the_cookie,
Servant the_servant) {
System.out.println(
"¥nAccountManagerLocator.postinvoke called
with ID = " +
new String(oid) + "¥n");
}
}