Borland(R) Enterprise Server VisiBroker(R) デベロッパーズガイド

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

7.5.2 ServantLocator

POAのアクティブオブジェクトマップがきわめて大きくなりメモリを消費するような状況はよくあります。メモリ消費量を減らすために,サーバントとオブジェクトの対応をアクティブオブジェクトマップに格納しないという意味のRequestProcessingPolicy::USE_SERVANT_MANAGERとServantRetentionPolicy::NON_RETAIN(C++)設定,またはRequestProcessingPolicy.USE_SERVANT_MANAGERとServantRetentionPolicy.NON_RETAIN(Java)設定でPOAを作成できます。対応が格納されないので,ServantLocatorサーバントマネージャをリクエストごとに起動できます。

サーバントロケータを使用したリクエストの処理中には,次のようなイベントが発生します。

  1. クライアントリクエストを受信します(クライアントリクエストにはPOA名およびオブジェクトIDが含まれます)。
  2. ServantRetentionPolicy::NON_RETAIN(C++),またはServantRetentionPolicy.NON_RETAIN(Java)を使用しているので,POAはアクティブオブジェクトマップのオブジェクトIDを探しません。
  3. POAはサーバントマネージャのpreinvokeを呼び出します。preinvokeはオブジェクトID,オブジェクトを活性化しているPOAなどのパラメタを渡します。
  4. サーバントロケータは適切なサーバントを探します。
  5. サーバントに対するオペレーションが実行され,クライアントに応答が返されます。
  6. POAはサーバントマネージャのpostinvokeを呼び出します。

preinvokeメソッドとpostinvokeメソッドはユーザが指定するコードです。

コードサンプル7-17 サーバントロケータタイプのサーバントマネージャを示すサーバコードサンプル(C++)
 
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;
}

コードサンプル7-18 サーバントロケータタイプのサーバントマネージャを示すサーバコードサンプル(Java)
 
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();
        }
     }
}
 

このサンプルのサーバントマネージャは,次のとおりです。

コードサンプル7-19 サーバントロケータのサンプルのサーバントマネージャ(C++)
 
// 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;
   }
};

コードサンプル7-20 サーバントロケータのサンプルのサーバントマネージャ(Java)
 
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");
   }
}