CORBA Programming with TAO - 8.Event Service(事件服务)

CORBA Programming with TAO - 8.Event Service(事件服务)

摘要:

事件服务(Event Service)通过在通信的双方甚至是多方间引入一个第三方――Event Channel,一定程度上解除ClientServer之间的耦合关系,在通信的过程中,任意一方只需与Event Channel打交道,而无需确切知道对方的存在,从而使得二者由一对一的关系变成多对多的关系。

一、简介

CORBA除了前面讲过的基本的Naming Service(命名服务)外,还定义了许多其它服务,Event Service就是其中的一个。标准的CORBA通信模式中,ClientServer之间的通信是直接的,ClientServer发出调用请求,Server进行处理并返回结果,这种处理方式下,二者之间是完全耦合在一起的一对一的关系。而Event Service则通过在二者之间引入一个第三方--Event Channel,可在一定程度上解除ClientServer之间的耦合关系,在通信的过程中,任意一方只需与Event Channel打交道,而无需确切知道对方的存在,从而使得二者由一对一的关系变成多对多的关系。

CORBAEvent Service定义了两种通信模式,推模式(Push Model)与拉模式(Pull Model)。在推模式下,PushSupplierEvent Channel发送消息,由Event ChannelCusumer转发消息;在拉模式下,PullConsumerEvent Channel请求消息,由Event ChannelSupplier转发该请求。但是,并不是说PushSupplier只能与PushConsumer通信,PullSupplier只能与PullConsumer通信,由于Event Channel提供的代理同时也扮演着Supplier/Consumer的角色,因此,在实际应用中,我们可以混合使用两种模式,后面的实例将演示PullSupplierPushConsumer通过Event Channel连接的例子,这种情况下,代理一方面不断地主动从Supplier处请求消息(默认时间间隔1秒),另一方面,又主动将收到的消息向Consumer发送。

二、编译

Naming Service一样,Event Service也是TAO的一个独立的Service,其源代码可以在$TAO/orbsvcs/CosEvent_Service下找到,但是前面介绍的CIAO_TAO.mwc产生的工程文件仅包含了TAO的少数几个Service,因此,要编译Event Service需要通过在$TAO_ROOT目录下运行:

mwc.pl -type vc8 TAO.mwc

以产生包含所有TAO实现的Service的工程文件。在执行上述命令前,最好将TAO.mwc的内容改为:

 

// TAO.mwc,v 1.2 2003/08/22 15:23:48 dhinton Exp

 

workspace {

  exclude {

    CIAO

    examples

    performance-tests

    tests

    orbsvcs/tests

    orbsvcs/performance-tests

    orbsvcs/examples

  }

}

 

否则,过多的测试工程将使得上述命令需要很长的时间才能执行完毕。

三、实例

下面举一个PullSupplier的例子,PullSupplier必须从POA_CosEventComm::PullSupplier派生,并实现该接口定义的三个基本方法:

CORBA::Any *pull();

CORBA::Any *try_pull(CORBA::Boolean &has_event);

void disconnect_pull_supplier ();

PullSupplier周期性会收到来自ProxyPullConsumerpull请求,要求从PullSupplier取得消息。下面是该实例的相关代码:

 

// Notes: just for demo, no exception handle

#include <orbsvcs/CosEventCommS.h>

#include <orbsvcs/CosEventChannelAdminC.h>

#include <orbsvcs/CosNamingC.h>

 

#include <process.h>

#include <stdio.h>

 

#include <iostream>

using namespace std;

 

class Supplier_i : virtual public POA_CosEventComm::PullSupplier {

public:

      Supplier_i () : l(0) {};

      // each PullSupplier must implement the following three methods.

      CORBA::Any *pull();

      CORBA::Any *try_pull(CORBA::Boolean &has_event);

      void disconnect_pull_supplier ();

     

private:

      CORBA::ULong l;

};

 

void Supplier_i::disconnect_pull_supplier () {

      cout << "Pull Supplier: disconnected by channel." << endl;

}

 

CORBA::Any* Supplier_i::pull() {

      cout << "Pull Supplier: pull() called. Data : ";

      CORBA::Any *any = new CORBA::Any();

      *any <<= l++;

      cout << l-1 << endl;

 

      return (any);

}

 

CORBA::Any *

Supplier_i::try_pull(CORBA::Boolean &has_event)

{

      cout << "Pull Supplier: try_pull() called. Data : ";

      CORBA::Any *any = new CORBA::Any();

      *any <<= l++;

      cout << l-1 << endl;

      has_event = 1;

 

      return (any);

}

 

int

main(int argc, char **argv)

{

      const char* channelName = "CosEventService";

      CORBA::Object_var obj;

 

      // Start orb.

      CORBA::ORB_ptr orb = CORBA::ORB_init(argc,argv);

     

      // find RootPOA

      obj=orb->resolve_initial_references("RootPOA");

      PortableServer::POA_var rootPoa = PortableServer::POA::_narrow(obj);

     

      // find and activate POAManager

      PortableServer::POAManager_var pman =rootPoa->the_POAManager();

      pman->activate();

     

      // find NameService

      obj = orb->resolve_initial_references("NameService");

      CosNaming::NamingContextExt_var ncRef = CosNaming::NamingContextExt::_narrow(obj);

 

      cout << "Find NameService" << endl;

     

      // search for EventChannel though NameService

      CosNaming::Name_var name = ncRef->to_name(channelName);

      obj = ncRef->resolve(name);

      CosEventChannelAdmin::EventChannel_var channel =

            CosEventChannelAdmin::EventChannel::_narrow(obj);

 

      cout << "Find EventChannel" << endl;

     

      // find SupplierAdmin on this channel

      CosEventChannelAdmin::SupplierAdmin_var supplier_admin;

      supplier_admin = channel->for_suppliers ();

 

      cout << "Find SupplierAdmin" << endl;

 

      // find ProxyPullConsumer under this SupplierAdmin

      CosEventChannelAdmin::ProxyPullConsumer_var proxy_consumer;  

      proxy_consumer = supplier_admin->obtain_pull_consumer ();

 

      // create PullSupplier

      Supplier_i* supplier = new Supplier_i ();

      CosEventComm::PullSupplier_var supplierRef = supplier->_this();

     

      // Connect PullSupplier with ProxyPullConsumer

      proxy_consumer->connect_pull_supplier(supplierRef.in());

      cout << "Connect Pull Supplier." << endl;

     

      orb->run();

     

      // cut off connection with ProxyPullConsumer

      proxy_consumer->disconnect_pull_consumer();

 

      cout << "Disconnect ProxyPullConsumer." << endl;

 

      // Destroy the POA, waiting until the destruction terminates

      rootPoa->destroy (1, 1);

      orb->destroy ();

 

      return 0;

}

 

从上面的代码可以看出,PullSupplier的基本调用序列为:

1、初始化ORB、查找rootPOA并激活POA Manager、查找Name Service并通过Name Service与事件通道取得联系;(这一步与前面讲的Name Service的例子并无差异)

2、在找到对应的事件通道后,PullSupplier通过channel->for_suppliers()找到对应的SupplierAdmin,进而通过SupplierAdmin找到ProxyPullConsumer,这样我们就可以向该代理注册我们的PullSupplier了。

3、最后,我们可以通过调用disconnect_pull_consumer()方法断开与ProxyPullConsumer的连接。

 

本文附带的源码包还包括了PullConsumerPushSupplierPushConsumer等三个例子,基本流程与上面类似,大家可以自行进行比较,以充分掌握各模式对调用序列的影响。

 

实际上,除了上面将事件数据写入Any类型进行传输外,CORBA规范还定义了一套强类型API,以用于用户自定义类型的传输,%TAO_ROOT%/orbsvcs/examples/CosEC/TypedSimple是一个强类型EventChannel的例子。

四、运行

由于上述实例需要同时使用Naming_ServiceEvent_Service,因此,需要在启动程序前先启动这两个服务:

%TAO_ROOT%/orbsvcs/Naming_Service/Naming_Service -m 1

%TAO_ROOT%/orbsvcs/CosEvent_Service/CosEvent_Service

然后即可启动客户程序:

pushcons

pushsupp

五、小结

Event ServiceSupplierConsumer提供了一种基本的借助第三方进行通信的机制,从而一定程度上解除了二者之间的耦合关系,但由于Event Service没有提供Filter机制,所有事件在整个事件通道内进行广播,使得Consumer无法订阅自己感兴趣的事件,同时,对QoS的等方面的支持也十分有限,因此,对于我们的实际应用,Event Service往往只能被应用于十分简单的松散耦合的多方通信。

CORBA规范定义的Notification Service从很大程度对Event Service进行了扩展,避免了Event Service存在的一些问题,感兴趣的朋友可以访问:

http://www.cs.wustl.edu/~schmidt/ACE_wrappers/TAO/docs/notification/reliability.html

来获得在TAO中使用Notification Service的相关信息。

 

附:本文示例源代码

参考:

1.      Alex Tingle, Paul Nader. omniEvents. http://omnievents.sourceforge.net/doc/index.html

2.      IONA Technologies. OrbixEvents Programmer's Guide. http://www.iona.com/support/docs/manuals/orbix/33/html/orbixevents33_pguide/index.html

3.      OMG. Event Service, v1.2. http://www.omg.org/cgi-bin/apps/doc?formal/04-10-02.pdf

4.      Carlos O'Ryan. TAO's COS Event Service. http://www.cs.wustl.edu/~schmidt/ACE_wrappers/TAO/docs/tutorials/Quoter/Event_Service/index.html

5.      Chris Gill, Tim Harrison, and Carlos O'Ryan. Using the Real-Time Event Service. http://www.cs.wustl.edu/~schmidt/events_tutorial.html

你可能感兴趣的:(exception,server,manager,filter,service,iostream)