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

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

5.3.7.8 Active Object Map(AOM)使用例(Factory-1方式+クライアントとのコネクション切断時のインスタンス解放)

(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 username );
          void   destroy( in  intf  obj ); 
      };
  };

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

  OD_or_adm -c IDL:ODsample/Factory:1.0 -a Imple_POAsample5 -n ODsample::POAsample5

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

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

  #include <iostream.h>
  #include <stdlib.h>
  #include "orb_cplus.h"
  #include "CosNaming_cplus.h"
  #include "simple.h"
  #include <string.h>

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

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

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

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

        // Factoryのオブジェクトリファレンスの獲得
        ODsample::Factory_ptr factory = ODsample::Factory::_narrow( obj );
        CORBA::release( obj );

        // ユーザIDの入力
        char _username[128];
        cout << "input your name  => ";
        cin >> _username;

        // Factoryでインタフェース用オブジェクトリファレンス作成
        ODsample::intf_ptr target = factory->create( _username );

        // サーバアプリケーションのメソッド呼出し
        cout << "value = " << target->value() << endl;
        cout << "add => ";
        CORBA::Long a;
        cin >> a;

        target->add( a );

        cout << "value = " << target->value() << endl;
        cout << "sub => ";
        CORBA::Long b;
        cin >> b;

        target->sub( b );

        cout << "value = " << target->value() << endl;

        CORBA::release( factory );
        CORBA::release( target );

    } 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 "simple.h"
  #include "poa.h"
  #include "CosNaming_cplus.h"

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

  static PortableServer::POA_var          rootPOA;
  static PortableServer::POA_var          factoryPOA;
  static CORBA::PolicyList                factory_policies;
  static PortableServer::POAManager_var   poa_manager;

  // ユーザアプリケーション:メイン処理クラス
  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作成
        // ポリシリスト作成
        factory_policies.length( 4 );
        factory_policies[0] = rootPOA->create_servant_retention_policy(
                                 PortableServer::NON_RETAIN, env );
        factory_policies[1] = rootPOA->create_request_processing_policy(
                                 PortableServer::USE_DEFAULT_SERVANT, env );
        factory_policies[2] = rootPOA->create_id_assignment_policy(
                                 PortableServer::SYSTEM_ID, env );
        factory_policies[3] = rootPOA->create_id_uniqueness_policy(
                                 PortableServer::MULTIPLE_ID, env );

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

        // FactoryServantの生成
        PortableServer::Servant  svt = _ct_ODsample_Factory( rootPOA );

        // Factoryインタフェース用POAをDefault Servantに設定
        factoryPOA->set_servant( svt, env );

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

        // インスタンス解放処理の登録
        PortableServer::POAdiconnect::setDisconnect(new instrelease());

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

        orb->run( env );

    } 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;
  }

  // FactoryServant:Factoryメソッド実装クラス
  class FactoryServant
  {
  public :
    // コンストラクタ
    FactoryServant(
        PortableServer::POA_ptr  poa )
    {
        _poa = poa;
    }

    ~FactoryServant()
    {
        CORBA::release( _poa );
    }

    ODsample::intf_ptr create(
        const CORBA::Char *username,
        CORBA::Environment&  env )
        throw( CORBA::Exception )
    {
        if( !_poa ) return NULL;
        ODsample::intf_ptr _ior = NULL;
        try{
            if( servant_list == NULL ){
                servant_list = new ServantList();
            }

            // Servantの検索
            PortableServer::ServantBase *_svt = servant_list->get( username );

            // みつからない場合、Servantを作成(guestは毎回作成)
            if( !_svt ){
                _svt = _ct_ODsample_intf( username );
                servant_list->put( username, _svt );
                if( 100 < servant_list->length()){
                  PortableServer::POAdisconnect::setDisconnect(new ALLinstrelease());
                }
            }

            // Servantからオブジェクトリファレンスの生成
            // IMPLICIT_ACTIVATIONポリシを指定しているので、AOMへ自動登録される
            CORBA::Object_ptr _obj = _poa->servant_to_reference( _svt, env );
            _ior = ODsample::intf::_narrow( _obj );

            CORBA::release( _obj );
        } catch( CORBA::Exception &e ) {
            cout << "exception-id: " << e.id() << endl;
            throw e;
        }
        return _ior;
    };


    void destroy(
        ODsample::intf_ptr obj,
        CORBA::Environment& env )
        throw( CORBA::Exception )
    {
        if( !_poa ) return;
        try{
            // オブジェクトリファレンスからオブジェクトIDを求める
            PortableServer::ObjectId_var _oid = _poa->reference_to_id( obj, env );

            // オブジェクトIDからServantを求める
            PortableServer::Servant _svt = _poa->id_to_servant( *_oid, env );

            // Servantをdeactiveにする
            _poa->deactivate_object( *_oid, env );

            // Servantの削除
            _svt->servant_delete();
        } catch( CORBA::Exception& e ) {
            cout << "exception-id: " << e.id() << endl;
            throw e;
        }
    };
  private :
    FactoryServant() {}
    PortableServer::POA_ptr    _poa;
  };

  // FactoryServantをtieオブジェクトに関連付けるためのメソッド(delegate方式の場合)
  POA_ODsample_Factory*  _ct_ODsample_Factory(
    PortableServer::POA_ptr poa )
  {
    FactoryServant*  impl = new FactoryServant( poa );
    POA_ODsample_Factory_tie< FactoryServant >*  tie
        = new POA_ODsample_Factory_tie< FactoryServant >( impl );
    return tie;
  }

  // Servant:メソッド実装クラス(スケルトンを継承)
  class UserServant
  {
  public :
    UserServant(
        const CORBA::Char *username )
    {
        _username = new char[ strlen(username) + 1 ];
        strcpy( _username, username );
        _val = 10;
    }
    ~UserServant()
    {
        if( _username )
            delete [] _username;
    }

    void add(
        CORBA::Long a,
        CORBA::Environment& env)
        throw( CORBA::Exception )
    {
        cout << "ODsample::intf::add()" << endl;
        cout << "  val : " << _val << endl;
        cout << "  a     : " << a << endl;
        _val = _val + a;
        cout << "  result: " << _val << endl;
    }

    void sub(
        CORBA::Long b,
        CORBA::Environment& env)
        throw( CORBA::Exception )
    {
        cout << "ODsample::intf::sub()" << endl;
        cout << "  val : " << _val << endl;
        cout << "  b     : " << b << endl;
        _val = _val - b;
        cout << "  result: " << _val << endl;
    }

    CORBA::Long value(
        CORBA::Environment& env)
        throw( CORBA::Exception )
    {
        return _val;
    }

    const char *name()
    {
        return _username;
    }

  private :
    UserServant() {}
    char *_username;
    long _val;
  };

  // UserServantをtieオブジェクトに関連付けるためのメソッド(delegate方式の場合)
  POA_ODsample_intf *_ct_ODsample_intf(
      const CORBA::Char *username )
  {
      UserServant*  impl = new UserServant( username );
      POA_ODsample_intf_tie< UserServant >*  tie
          = new POA_ODsample_intf_tie< UserServant >( impl );
      return tie;
  }

  // 条件付きインスタンス解放クラス(POAdisconnectを継承)
  class instrelease : public virtual PortableServer::POAdisconnect
  {
  public :
    instrelease() {}
    ~instrelease() {}

    CORBA::Boolean release_instance(
        PortableServer::POA_ptr poa,
        PortableServer::ServantBase *svt,
        PortableServer::ObjectId&  oid,
        CORBA::Environment&  env  )
    {
        cout << "instrelease::release_instance called..." << endl;
        POA_ODsample_intf_tie< UserServant >*  _tie
                        = dynamic_cast< POA_ODsample_intf_tie< UserServant >* >( svt );
        UserServant*  _svt = _tie->_tied_object();
        cout << "    servant->name : " << _svt->name() << endl;
        if( !strcmp( _svt->name(), "guest" )){
            ServantList::remove( servant_list, "guest" );
            return true;
        }
        return false;
    }
  };

  // 無条件インスタンス解放クラス(POAdisconnectを継承)
  class ALLinstrelease : public virtual PortableServer::POAdisconnect
  {
  public :
    ALLinstrelease() {}
    ~ALLinstrelease() {}

    CORBA::Boolean release_instance(
        PortableServer::POA_ptr poa,
        PortableServer::ServantBase *svt,
        PortableServer::ObjectId&  oid,
        CORBA::Environment&  env  )
    {
        cout << "ALLinstrelease::release_instance called..." << endl;
        POA_ODsample_intf_tie< UserServant >*  _tie
                        = dynamic_cast< POA_ODsample_intf_tie< UserServant >* >( svt );
        UserServant*  _svt = _tie->_tied_object();
        cout << "    servant->name : " << _svt->name() << endl;
        ServantList::remove( servant_list, _svt->name());
        return true;
    }
  };

  // Servant管理テーブル
  class ServantList
  {
  public:
    ServantList()
    {
        _svt = NULL;
        _username = NULL;
        _next = NULL;
    };
    ServantList(
        const CORBA::Char *username,
        PortableServer::ServantBase *svt )
    {
        _username = new char[ strlen(username) + 1];
        strcpy( _username, username );
        _svt = svt;
        _next = NULL;
    };
    ~ServantList()
    {
        if( _username )
            delete [] _username;
        if( _next )
            delete _next;
    };

    PortableServer::ServantBase *get(
        const CORBA::Char *username )
    {
        if( !username || !_username )
            return NULL;
        if( !strcmp( username, _username )){
            return _svt;
        }
        if( _next )
            return _next->get(username);
        return NULL;
    }

    void put(
        const CORBA::Char *username,
        PortableServer::ServantBase *svt )
    {
        if( _next != NULL ){
            _next->put( username, svt );
        }
        else{
            if( _svt == NULL ){
                _svt = svt;
                _username = new char[ strlen(username) + 1];
                strcpy( _username, username );
            }
            else{
                _next = new ServantList( username, svt );
            }
        }
    }

    static void remove(
        ServantList *&list,
        const CORBA::Char *username )
    {
        ServantList *_back = NULL;
        for( ServantList *_list = list; _list; _list = _list->_next ){
            if( !strcmp( _list->_username, username )){
                if( _back ){
                    _back->_next = _list->_next;
                }
                else{
                    list = _list->_next;
                }
                _list->_next = NULL;
                delete _list;
                break;
            }
            _back = _list;
        }
        return;
    }

    int length()
    {
        ServantList *_p = _next;
        int _count = 1;
        while( _p ){
            _p = _p->_next;
            ++_count;
        }
        return _count;
    }

  private :
    PortableServer::ServantBase *_svt;
    char *_username;
    ServantList *_next;
  };

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

(6)例外情報の獲得

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


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

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