Interstage Application Server アプリケーション作成ガイド (CORBAサービス編)
目次 索引 前ページ次ページ

第5章 アプリケーションの開発(C++言語)> 5.3 サーバアプリケーションのプログラミング(Portable Object Adapter:POA)> 5.3.7 サーバアプリケーションのプログラミング例

5.3.7.4 Servant Locator使用例 (ユーザインスタンス管理方式)

(1)IDL定義

  module ODsample{
      interface    intf{
          readonly  attribute  long  value; 
          void add( in  long  a ); 
          void sub( in  long  b ); 
      }; 
      interface Factory{
          intf   create( in  string  userid ); 
          void   destroy( in  intf  obj ); 
      }; 
  };

(2)ネーミングサービスの登録

  OD_or_adm -c IDL:ODsample/Factory:1.0 -a Imple_POAsample4 -n ODsample::POAsample4

(3)アプリケーション構成概要図

(4)クライアントアプリケーション

  #include <iostream.h>
  #include <stdlib.h>

  #include "orb_cplus.h"
  #include "CosNaming_cplus.h"
  #include "simple.h"

  static  CORBA::Object_var             obj; 
  static  CORBA::Environment            env; 
  static  CORBA::ORB_var                orb; 
  static  CosNaming::NamingContext_var  cos_naming; 
  static  CosNaming::Name               name; 

  int main( int argc, char* argv[] ) 
  {
      try {
          // ORBの生成と初期化
          orb = CORBA::ORB_init( argc, argv, FJ_OM_ORBid, env ); 

          // ネーミングサービスのオブジェクトリファレンスの取得
          obj = orb->resolve_initial_references(
                        CORBA_ORB_ObjectId_NameService, env ); 
          cos_naming = CosNaming::NamingContext::_narrow( obj ); 

          // ネーミングサービスのresolveメソッドを発行し、
          // サーバアプリケーションのオブジェクトリファレンスの獲得
          name.length( 1 ); 
          name[0]->id   = ( const CORBA::Char* )"ODsample::POAsample4"; 
          name[0]->kind = ( const CORBA::Char* )""; 

          obj = cos_naming->resolve( name, env ); 

          // サーバアプリケーションのインタフェースクラスの獲得
          ODsample::Factory* target = ODsample::Factory::_narrow( obj ); 

          char userid[1024]; 
          printf( "USERID -> " ); 
          userid[0] = 0; 
          scanf( "%s", userid ); 
          if( strlen( userid ) < 1 ){
              return 255; 
          }

          // FactoryでインタフェースアプリのIORを作成する
          ODsample::intf* obj2 = target->create( userid, env ); 

          CORBA::Long  a = 10; 
          CORBA::Long  b = 5; 

          // サーバアプリケーションのメソッド呼出し
          CORBA::Long ret = obj2->value( env ); 
          printf( "value = %d\n", ret ); 

          obj2->add( a, env ); 
          printf( "add( %d )\n", a ); 

          ret = obj2->value( env ); 
          printf( "value = %d\n", ret ); 

          obj2->sub( b, env ); 
          printf( "sub( %d )\n", b ); 

          ret = obj2->value( env ); 
          printf( "value = %d\n", ret ); 

          target->destroy( obj2, env ); 

          CORBA::release( target ); 
          CORBA::release( obj2 ); 

      } catch( CORBA::SystemException&  se ) {
          cout << "exception-id: " << se.id() << endl; 
          exit(1); 
      } catch( CORBA::Exception&  e ) {
          cout << "exception-id: " << e.id() << endl; 
          exit(1); 
      }
      return 0; 
  }

(5)サーバアプリケーション

  #include <iostream.h>
  #include <stdlib.h>

  #include "orb_cplus.h"
  #include "poa.h"
  #include "CosNaming_cplus.h"

  #include "simple.h"

  static CORBA::ORB_var                   orb; 
  static CORBA::Object_var                obj; 
  static CORBA::Environment               env; 

  static PortableServer::POA_var          rootPOA; 
  static PortableServer::POA_var          factory_poa; 
  static PortableServer::POA_var          childPOA; 
  static CORBA::PolicyList                policies( 4 ); 
  static CORBA::PolicyList                inf_policies( 4 ); 
  static PortableServer::POAManager_var   poa_manager; 

  static CORBA::Long                      val = 10; 

  // ユーザアプリケーション:メイン処理クラス
  int main( int argc, char*argv[] ) 
  {
      int current_argc = argc; 
      try{
          // ORBの生成と初期化
          orb         = CORBA::ORB_init( current_argc, argv, FJ_OM_ORBid, env ); 

          // RootPOAのオブジェクトリファレンスの取得
          obj         = orb->resolve_initial_references( "RootPOA", env ); 
          // RootPOAのPOAオブジェクト獲得
          rootPOA     = PortableServer::POA::_narrow( obj ); 

          // Factoryインタフェース用のPOA作成
          // ポリシリスト作成
          policies.length( 4 ); 
          policies[0] = rootPOA->create_servant_retention_policy(
                                 PortableServer::NON_RETAIN, env ); 
          policies[1] = rootPOA->create_request_processing_policy(
                                 PortableServer::USE_DEFAULT_SERVANT, env ); 
          policies[2] = rootPOA->create_id_assignment_policy(
                                 PortableServer::SYSTEM_ID, env ); 
          policies[3] = rootPOA->create_id_uniqueness_policy(
                                 PortableServer::MULTIPLE_ID, env ); 

          factory_poa = rootPOA->create_POA( "IDL:ODsample/Factory:1.0", 
                          PortableServer::POAManager::_nil(), policies ,env); 

          // インタフェース用のPOA作成
          // ポリシリスト作成
          inf_policies.length( 4 ); 
          inf_policies[0] = rootPOA->create_servant_retention_policy(
                                 PortableServer::NON_RETAIN, env ); 
          inf_policies[1] = rootPOA->create_request_processing_policy(
                                 PortableServer::USE_SERVANT_MANAGER, env ); 
          inf_policies[2] = rootPOA->create_id_assignment_policy(
                                 PortableServer::USER_ID, env ); 
          inf_policies[3] = rootPOA->create_id_uniqueness_policy(
                                 PortableServer::UNIQUE_ID, env ); 

          childPOA = rootPOA->create_POA( "childPOA", 
                          PortableServer::POAManager::_nil(), inf_policies ,env); 

          // FactoryServantの生成
          ODsample_Factory_impl* svt = new ODsample_Factory_impl(); 
          // Factoryインタフェース用POAのDefault Servantに設定
          factory_poa->set_servant( svt, env ); 

          // ServantLocatorの生成
          PortableServer::ServantLocator* svtloc = new UserServantLocator(); 
          // インタフェース用POAにServantManagerとして登録
          childPOA->set_servant_manager( svtloc, env ); 

          // POAマネージャの獲得
          poa_manager = rootPOA->the_POAManager( env ); 

          // POAマネージャのactivate
          poa_manager->activate( env ); 

          orb->run( env ); 
      } catch( CORBA::Exception& e ) {
          cout << "exception-id: " << e.id() << endl; 
          exit(1); 
      }
      return 0; 
  }

  // 管理テーブル
  class ServantList
  {
  public: 
      ServantList() {
          _next = NULL; 
          _svr = NULL; 
          _oid = NULL; 
      }; 
      ~ServantList() {
          if( _svr != NULL ) {
              _svr->servant_delete();
          }
          if( _oid != NULL ) {
              delete _oid; 
          }
      }; 
      PortableServer::ObjectId* getObjectId() {
          return _oid; 
      }; 
      ServantList* getNext() {
          return _next; 
      }; 
      // 管理テーブルから検索
      PortableServer::ServantBase* getServant( const PortableServer::ObjectId* oid ) {
          if( _svr == NULL ) {
              if( _next == NULL ) {
                  return NULL; 
              }
              return _next->getServant( oid ); 
          }
          if( equal( oid ) ) {
              return _svr; 
          }
          if( _next ) {
              return _next->getServant( oid ); 
          }
          return NULL; 
      }; 
      long equal( const PortableServer::ObjectId* oid ) {
          if( _oid == NULL ) {
              return 0; 
          }
          if( oid->length() == oid->length() ) {
              long len = oid->length(); 
              long i; 
              for( i = 0 ; i < len ; i++ ) {
                  if( oid->operator[](i) != _oid->operator[](i) ) {
                      return 0; 
                  }
              }
              return 1; 
          }
          return 0; 
      }; 
      // 管理テーブルから削除
      void remove( PortableServer::ObjectId* oid ) {
          if( _next != NULL ) {
              if( _next->equal( oid ) ) {
                  ServantList* del = _next; 
                  _next = _next->getNext(); 
                   delete del; 
              }
          }
      }; 
      // 管理テーブルへ追加
      void put( const PortableServer::ObjectId* oid, PortableServer::ServantBase* svr ) {
          if( _next != NULL ) {
              _next->put( oid, svr ); 
          } else {
              _next = new ServantList(); 
              _next->_svr = svr; 
              _next->_oid = new PortableServer::ObjectId( *oid ); 
          }
      }; 
  private : 
      PortableServer::ObjectId*      _oid; 
      PortableServer::ServantBase*   _svr; 
      ServantList*                   _next; 
  }; 

  // 管理テーブルのインスタンス
  ServantList servant_list; 

  // ODsample_Factory_impl::create:メソッドの実装
  ODsample::intf_ptr ODsample_Factory_impl::create(
            const CORBA::Char* str, 
            CORBA::Environment& env) 
            throw( CORBA::Exception ){
      try{
          long len = strlen( str );
          CORBA::Octet* buf = PortableServer::ObjectId::allocbuf( len ); 
          memcpy( buf, str, len ); 
          PortableServer::ObjectId_var userid = new PortableServer::ObjectId(
                              len, len, buf, CORBA_TRUE ); 

          // オブジェクトリファレンスの生成
          CORBA::Object_var _tmpObj = childPOA->create_reference_with_id( *userid, 
                                   "IDL:ODsample/intf:1.0",env ); 
          ODsample::intf_ptr ior = ODsample::intf::_narrow( _tmpObj ); 
          return ior; 
      } catch(CORBA::Exception& e ) {
          cout << "exception-id: " << e.id() << endl; 
          throw e; 
      }
  }; 

  // ODsample_Factory_impl::destroy:メソッドの実装
  void ODsample_Factory_impl::destroy(
            ODsample::intf_ptr obj, 
            CORBA::Environment& env) 
            throw( CORBA::Exception ){
      try{
          // オブジェクトリファレンスからオブジェクトIDを求める
          PortableServer::ObjectId_var  oid = childPOA->reference_to_id( obj, env ); 

          // Servantを管理テーブルから削除
          servant_list.remove( oid ); 
      } catch( CORBA::Exception&  e ) {
          cout << "exception-id: " << e.id() << endl; 
          throw e; 
      }
  }; 

  // ServantLocator:Servant生成クラス(ServantLocatorを継承)
  class UserServantLocator: public PortableServer::ServantLocator
  {
  public: 
      UserServantLocator() {};
      ~UserServantLocator() {};

      PortableServer::Servant preinvoke(
                const PortableServer::ObjectId&          oid, 
                PortableServer::POA_ptr                  adapter, 
                const CORBA::Identifier                  operation, 
                PortableServer::ServantLocator::Cookie&  cookie, 
                CORBA::Environment& = CORBA::Environment() ) 
                throw( CORBA::Exception ) 
      {
          // Servantを検索する。みつからなければnewで生成する。
          PortableServer::Servant svt = servant_list.getServant( &oid ); 
          if( svt == NULL ) {
              svt = new ODsample_intf_impl(); 
              servant_list.put( &oid, svt ); 
          }
          // Cookieの作成
          cookie = ( CORBA::ULong )svt; 
          return svt; 
      }; 
      void  postinvoke(
            const PortableServer::ObjectId&         oid, 
            PortableServer::POA_ptr                 adapter, 
            const CORBA::Identifier                 operation, 
            PortableServer::ServantLocator::Cookie  cookie, 
            PortableServer::Servant                 the_servant, 
            CORBA::Environment& = CORBA::Environment() ) 
            throw( CORBA::Exception ) 
      {
      }; 
  }; 

  // ODsample_intf_implクラスのメソッド実装
  void ODsample_intf_impl::add(
            CORBA::Long a, 
            CORBA::Environment& env ) 
            throw( CORBA::Exception ) 
  {
      cout << "ODsample::intf::add()" << endl; 
      cout << "  value : " << val << endl; 
      cout << "  a     : " << a << endl; 
      val = val + a; 
      cout << "  result: " << val << endl; 
  }; 
  void ODsample_intf_impl::sub(
            CORBA::Long b, 
            CORBA::Environment& env ) 
            throw( CORBA::Exception ) 
  {
      cout << "ODsample::intf::sub()" << endl; 
      cout << "  value : " << val << endl; 
      cout << "  b     : " << b << endl; 
      val = val - b; 
      cout << "  result: " << val << endl; 
  }; 
  CORBA::Long ODsample_intf_impl::value(
            CORBA::Environment& env ) 
            throw( CORBA::Exception ) 
  {
      return val; 
  };

(6)例外情報の獲得

 サーバアプリケーションで例外を獲得する方法の詳細については、“サーバアプリケーションの例外処理”を参照してください。


目次 索引 前ページ次ページ

All Rights Reserved, Copyright(C) 富士通株式会社 2005