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

CORBA Programming with TAO - 8.Event Service(事件服务)
摘要:
事件服务(Event Service)通过在通信的双方甚至是多方间引入一个第三方――Event Channel,一定程度上解除Client和Server之间的耦合关系,在通信的过程中,任意一方只需与Event Channel打交道,而无需确切知道对方的存在,从而使得二者由一对一的关系变成多对多的关系。
一、简介
CORBA除了前面讲过的基本的Naming Service(命名服务)外,还定义了许多其它服务,Event Service就是其中的一个。标准的CORBA通信模式中,Client与Server之间的通信是直接的,Client向Server发出调用请求,Server进行处理并返回结果,这种处理方式下,二者之间是完全耦合在一起的一对一的关系。而Event Service则通过在二者之间引入一个第三方--Event Channel,可在一定程度上解除Client和Server之间的耦合关系,在通信的过程中,任意一方只需与Event Channel打交道,而无需确切知道对方的存在,从而使得二者由一对一的关系变成多对多的关系。
CORBA的Event Service定义了两种通信模式,推模式(Push Model)与拉模式(Pull Model)。在推模式下,PushSupplier向Event Channel发送消息,由Event Channel向Cusumer转发消息;在拉模式下,PullConsumer向Event Channel请求消息,由Event Channel向Supplier转发该请求。但是,并不是说PushSupplier只能与PushConsumer通信,PullSupplier只能与PullConsumer通信,由于Event Channel提供的代理同时也扮演着Supplier/Consumer的角色,因此,在实际应用中,我们可以混合使用两种模式,后面的实例将演示PullSupplier与PushConsumer通过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周期性会收到来自ProxyPullConsumer的pull请求,要求从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的连接。
 
本文附带的源码包还包括了PullConsumer、PushSupplier、PushConsumer等三个例子,基本流程与上面类似,大家可以自行进行比较,以充分掌握各模式对调用序列的影响。
 
实际上,除了上面将事件数据写入Any类型进行传输外,CORBA规范还定义了一套强类型API,以用于用户自定义类型的传输,%TAO_ROOT%/orbsvcs/examples/CosEC/TypedSimple是一个强类型EventChannel的例子。
四、运行
由于上述实例需要同时使用Naming_Service、Event_Service,因此,需要在启动程序前先启动这两个服务:
%TAO_ROOT%/orbsvcs/Naming_Service/Naming_Service -m 1
%TAO_ROOT%/orbsvcs/CosEvent_Service/CosEvent_Service
然后即可启动客户程序:
pushcons
pushsupp
五、小结
Event Service为Supplier与Consumer提供了一种基本的借助第三方进行通信的机制,从而一定程度上解除了二者之间的耦合关系,但由于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,service,filter,iostream)