Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

ProxyPullConsumer.cc

Go to the documentation of this file.
00001 //                            Package   : omniEvents
00002 // ProxyPullConsumer.cc       Created   : 2003/12/04
00003 //                            Author    : Alex Tingle
00004 //
00005 //    Copyright (C) 2003 Alex Tingle.
00006 //
00007 //    This file is part of the omniEvents application.
00008 //
00009 //    omniEvents is free software; you can redistribute it and/or
00010 //    modify it under the terms of the GNU Lesser General Public
00011 //    License as published by the Free Software Foundation; either
00012 //    version 2.1 of the License, or (at your option) any later version.
00013 //
00014 //    omniEvents is distributed in the hope that it will be useful,
00015 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 //    Lesser General Public License for more details.
00018 //
00019 //    You should have received a copy of the GNU Lesser General Public
00020 //    License along with this library; if not, write to the Free Software
00021 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 
00024 #include "ProxyPullConsumer.h"
00025 #include "Orb.h"
00026 #include "omniEventsLog.h"
00027 
00028 #define DB(l,x) ((omniORB::traceLevel >= l) && (cerr << x << endl))
00029 
00030 namespace OmniEvents {
00031 
00032 //
00033 //  ProxyPullConsumerManager
00034 //
00035 
00036 PortableServer::Servant
00037 ProxyPullConsumerManager::incarnate(
00038   const PortableServer::ObjectId& oid,
00039   PortableServer::POA_ptr         poa
00040 )
00041 {
00042   // ?? Check that OID is valid here.
00043   ProxyPullConsumer_i* result =new ProxyPullConsumer_i(_managedPoa,_queue);
00044   _servants.insert(result);
00045   return result;
00046 }
00047 
00048 ProxyPullConsumerManager::ProxyPullConsumerManager(
00049   PortableServer::POA_ptr parentPoa,
00050   list<CORBA::Any*>&      q
00051 )
00052 : ProxyManager(parentPoa,"ProxyPullConsumer"),
00053   _queue(q)
00054 {
00055   // pass
00056 }
00057 
00058 CosEventChannelAdmin::ProxyPullConsumer_ptr
00059 ProxyPullConsumerManager::createObject()
00060 {  
00061   return createNarrowedReference<CosEventChannelAdmin::ProxyPullConsumer>(
00062            _managedPoa,
00063            CosEventChannelAdmin::_tc_ProxyPullConsumer->id()
00064          );
00065 }
00066 
00067 
00068 
00069 void ProxyPullConsumerManager::trigger()
00070 {
00071   // Trigger each servant in turn.
00072   for(set<Proxy*>::iterator i =_servants.begin(); i!=_servants.end(); ++i)
00073   {
00074     ProxyPullConsumer_i* proxy=static_cast<ProxyPullConsumer_i*>(*i);
00075     proxy->trigger();
00076   }
00077 }
00078 
00079 
00080 //
00081 //  ProxyPullConsumer_i
00082 //
00083 
00084 // CORBA interface methods
00085 
00086 void ProxyPullConsumer_i::connect_pull_supplier(
00087   CosEventComm::PullSupplier_ptr pullSupplier
00088 )
00089 {
00090   try
00091   {
00092     if(CORBA::is_nil(pullSupplier))
00093         throw CORBA::BAD_PARAM();
00094     if(!CORBA::is_nil(_target) || !CORBA::is_nil(_req))
00095         throw CosEventChannelAdmin::AlreadyConnected();
00096     _target=CosEventComm::PullSupplier::_duplicate(pullSupplier);
00097 
00098     omniEventsLog::persist();
00099   }
00100   catch(...) // ?? AlreadyConnected -> deactivate. DOS attack!!
00101   {
00102     _target=CosEventComm::PullSupplier::_nil();
00103     deactivateObject(); //??  <<===== Get rid of this.
00104     throw;
00105   }
00106 }
00107 
00108 void ProxyPullConsumer_i::disconnect_pull_consumer()
00109 {
00110   DB(5,"ProxyPullConsumer_i::disconnect_pull_consumer()");
00111   deactivateObject();
00112   if(CORBA::is_nil(_target))
00113   {
00114     throw CORBA::BAD_INV_ORDER(
00115       omni::BAD_INV_ORDER_RequestUsedMoreThanOnce,
00116       CORBA::COMPLETED_YES
00117     );
00118   }
00119   else
00120   {
00121     CORBA::Request_var req=_target->_request("disconnect_pull_supplier");
00122     req->send_deferred();
00123     Orb::inst().orphanRequest(req._retn());
00124     _target=CosEventComm::PullSupplier::_nil();
00125   }
00126 }
00127 
00128 //
00129 
00130 ProxyPullConsumer_i::ProxyPullConsumer_i(
00131   PortableServer::POA_ptr poa,
00132   list<CORBA::Any*>&      q
00133 )
00134 : Proxy(poa),
00135   _target(CosEventComm::PullSupplier::_nil()),
00136   _queue(q)
00137 {
00138   _exceptionCount[Pull]=0;
00139   _exceptionCount[TryPull]=0;
00140 }
00141 
00142 void ProxyPullConsumer_i::trigger()
00143 {
00144   // PSEUDOCODE:
00145   // If an exception has arrived, increment the exception count for that
00146   //   operation (pull or try_pull), and switch to the other operation.
00147   // If both operations' exception counts are >1, then deactivate this object.
00148   // If a method has returned, then desice whether we have an event (hasEvent).
00149   //   If so, the read the event and push it onto the queue.
00150   // If there is no request in progress, send a new request to the current
00151   //   operation (pull or try_pull).
00152 
00153   // Prefer 'pull' method calls.
00154   CORBA::String_var opname ="pull";
00155 
00156   if(!CORBA::is_nil(_req) && _req->poll_response()) 
00157   {
00158     opname=CORBA::string_dup(_req->operation());
00159 
00160     CORBA::Environment_var env=_req->env();
00161     if(!CORBA::is_nil(env) && env->exception()) 
00162     {
00163       CORBA::Exception* ex =env->exception(); // No need to free exception.
00164       DB(1,"ProxyPullConsumer got exception: "<<ex->_name()<<", op:"<<opname);
00165       _req=CORBA::Request::_nil();
00166       if(0==strcmp("pull",opname))
00167       {
00168         ++(_exceptionCount[Pull]);
00169         opname="try_pull"; // Try something else next time.
00170       }
00171       else if(0==strcmp("try_pull",opname))
00172       {
00173         ++(_exceptionCount[TryPull]);
00174         opname="pull"; // Try something else next time.
00175       }
00176       else
00177           DB(1,"Ignoring unrecognised response. operation:"<<opname);
00178       if(_exceptionCount[Pull]>=2 && _exceptionCount[TryPull]>=2)
00179       {
00180         _target=CosEventComm::PullSupplier::_nil(); // disconnected
00181         deactivateObject();
00182         return;
00183       }
00184     }
00185     else  
00186     {
00187       // Do we have an event?
00188       bool hasEvent=false;
00189       if(0==strcmp("pull",opname))
00190       {
00191         _exceptionCount[Pull]=0;
00192         hasEvent=true;
00193       }
00194       else if(0==strcmp("try_pull",opname))
00195       {
00196         _exceptionCount[TryPull]=0;
00197         CORBA::NVList_var args=_req->arguments();
00198         if(args->count()==1)
00199         {
00200           CORBA::NamedValue_var hasEventArg=args->item(0);
00201           if(0==strcmp(hasEventArg->name(),"has_event"))
00202           {
00203             CORBA::Any* a =hasEventArg->value();
00204             CORBA::Boolean b;
00205             CORBA::Any::to_boolean tb(b); //MS VC++6 is on drugs!
00206             hasEvent=(((*a)>>=tb) && b);
00207           }
00208         }
00209       }
00210       // Pick up an event, if we have one.
00211       if(hasEvent)
00212       {
00213         CORBA::Any* event =new CORBA::Any();
00214         _req->return_value() >>= (*event);
00215         _queue.push_back(event);
00216       }
00217     }
00218     _req=CORBA::Request::_nil();
00219   }
00221   if(CORBA::is_nil(_req) && !CORBA::is_nil(_target))
00222   {
00223     _req=_target->_request(opname);
00224     _req->set_return_type(CORBA::_tc_any);
00225     if(0==strcmp("try_pull",opname))
00226         _req->add_out_arg("has_event")<<=CORBA::Any::from_boolean(1);
00227     _req->send_deferred();
00228   }
00229 }
00230 
00231 void ProxyPullConsumer_i::reincarnate(const OEP_prxy& prxy)
00232 {
00233   CosEventComm::PullSupplier_var pullSupplier =
00234     string_to_<CosEventComm::PullSupplier>(prxy.getIor());
00235   // Do not activate until we know that we have read a valid target.
00236   activateObjectWithId(prxy.getKey());
00237   connect_pull_supplier(pullSupplier.in());
00238 }
00239 
00240 void ProxyPullConsumer_i::output(ostream& os)
00241 {
00242   Output out =basicOutput(os,"pxyPullConsumer",3,this,_target.in());
00243 }
00244 
00245 }; // end namespace OmniEvents

Generated on Fri Dec 12 10:53:02 2003 for OmniEvents by doxygen1.2.15