Orb.cc

Go to the documentation of this file.
00001 //                            Package   : omniEvents
00002 // Orb.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 "Orb.h"
00025 
00026 #ifdef HAVE_IOSTREAM
00027 #  include <iostream>
00028 #else
00029 #  include <iostream.h>
00030 #endif
00031 
00032 #include <stdlib.h>
00033 #include <assert.h>
00034 
00035 #include "Callback.h"
00036 
00037 namespace OmniEvents {
00038 
00039 Orb Orb::_inst;
00040 
00041 
00042 Orb::~Orb()
00043 {
00044   omni_mutex_lock l(_deferredRequestsLock);
00045   list<RequestCallback_t>::iterator curr, next=_deferredRequests.begin();
00046   while(next!=_deferredRequests.end())
00047   {
00048     curr=next++;
00049     CORBA::release(curr->first);
00050     _deferredRequests.erase(curr);
00051   }
00052 }
00053 
00054 
00055 void Orb::resolveInitialReferences()
00056 {
00057   assert(!CORBA::is_nil(_orb));
00058 
00059   const char* action=""; // Use this variable to help report errors.
00060   try
00061   {
00062     CORBA::Object_var obj;
00063 
00064     action="resolve initial reference 'RootPOA'";
00065     obj=_orb->resolve_initial_references("RootPOA");
00066     _RootPOA=PortableServer::POA::_narrow(obj);
00067     if(CORBA::is_nil(_RootPOA))
00068         throw CORBA::OBJECT_NOT_EXIST();
00069 
00070     action="resolve initial reference 'omniINSPOA'";
00071     obj=_orb->resolve_initial_references("omniINSPOA");
00072     _omniINSPOA=PortableServer::POA::_narrow(obj);
00073     if(CORBA::is_nil(_omniINSPOA))
00074         throw CORBA::OBJECT_NOT_EXIST();
00075 
00076     // The naming service is optional.
00077     try
00078     {
00079       action="resolve initial reference 'NameService'";
00080       obj=_orb->resolve_initial_references("NameService");
00081       _NameService=CosNaming::NamingContext::_narrow(obj);
00082     }
00083     catch(CORBA::Exception& ex)
00084     {
00085       DB(1,"Warning - failed to "<<action<<
00086          IFELSE_OMNIORB4(". Exception: "<<ex._name(),"."))
00087     }
00088   
00089 #ifdef HAVE_OMNIORB4
00090     action="resolve initial reference 'POACurrent'";
00091     obj=_orb->resolve_initial_references("POACurrent");
00092     _POACurrent=PortableServer::Current::_narrow(obj);
00093     if(CORBA::is_nil(_POACurrent))
00094         throw CORBA::OBJECT_NOT_EXIST();
00095 #endif
00096 
00097     return;
00098   }
00099   catch(CORBA::ORB::InvalidName& ex) // resolve_initial_references
00100   {
00101     DB(0,"Failed to "<<action<<". InvalidName")
00102   }
00103   catch(CORBA::TRANSIENT& ex) // _narrow()
00104   {
00105     DB(0,"Failed to "<<action<<". TRANSIENT")
00106   }
00107   catch(CORBA::OBJECT_NOT_EXIST& ex) // _narrow()
00108   {
00109     DB(0,"Failed to "<<action<<". OBJECT_NOT_EXIST")
00110   }
00111   catch(CORBA::SystemException& ex)
00112   {
00113     DB(0,"Failed to "<<action<<"."
00114       IF_OMNIORB4(" "<<ex._name()<<" ("<<NP_MINORSTRING(ex)<<")") )
00115   }
00116   catch(CORBA::Exception& ex)
00117   {
00118     DB(0,"Failed to "<<action<<"." IF_OMNIORB4(" "<<ex._name()) )
00119   }
00120   exit(1);
00121 }
00122 
00123 
00124 void Orb::run()
00125 {
00126   while(!_shutdownRequested)
00127   {
00128     omni_thread::sleep(5);
00129     omni_mutex_lock l(_deferredRequestsLock);
00130     DB(20,"Polling "<<_deferredRequests.size()<<" deferred requests.")
00131     list<RequestCallback_t>::iterator curr, next=_deferredRequests.begin();
00132     while(next!=_deferredRequests.end())
00133     {
00134       curr=next++;
00135       if(curr->first->poll_response())
00136       {
00137         CORBA::Environment_ptr env=curr->first->env();// No need to release env.
00138         if(!CORBA::is_nil(env) && env->exception())
00139         {
00140           CORBA::Exception* ex =env->exception(); // No need to free exception.
00141           DB(10,"Deferred call to "<<curr->first->operation()
00142             <<"() got exception" IF_OMNIORB4(<<": "<<ex->_name()))
00143         }
00144         else if(curr->second && curr->second->isValid())
00145         {
00146           DB(15,"Deferred call to "<<curr->first->operation()<<"() returned.")
00147           if(curr->second->isValid()) // BUG - possible race here
00148              curr->second->callback(curr->first);
00149         }
00150         else
00151         {
00152           DB(15,"Orphan call to "<<curr->first->operation()<<"() returned.")
00153         }
00154         CORBA::release(curr->first);
00155         _deferredRequests.erase(curr);
00156       }
00157     }
00158   }
00159   
00160   // Clean up all outstanding requests.
00161   omni_mutex_lock l(_deferredRequestsLock);
00162   while(!_deferredRequests.empty())
00163   {
00164     CORBA::release(_deferredRequests.front().first);
00165     _deferredRequests.pop_front();
00166   }
00167 }
00168 
00169 
00170 void Orb::deferredRequest(CORBA::Request_ptr req, Callback* callback)
00171 {
00172   omni_mutex_lock l(_deferredRequestsLock);
00173   if(_shutdownRequested)
00174       CORBA::release(req);
00175   else if(callback)
00176       _deferredRequests.push_front(RequestCallback_t(req,callback));
00177   else
00178       _deferredRequests.push_back(RequestCallback_t(req,NULL));
00179 }
00180 
00181 
00182 void Orb::cancelCallback(const Callback* callback)
00183 {
00184   omni_mutex_lock l(_deferredRequestsLock);
00185   list<RequestCallback_t>::iterator i=_deferredRequests.begin();
00186   // All the callback are at the front, so we can stop when i->second==NULL.
00187   while(i!=_deferredRequests.end() && i->second)
00188   {
00189     if(i->second==callback)
00190        i->second=NULL;
00191     ++i;
00192   }
00193 }
00194 
00195 
00196 void Orb::reportObjectFailure(
00197   const char*       here,
00198   CORBA::Object_ptr obj,
00199   CORBA::Exception* ex
00200 )
00201 {
00202   assert(!CORBA::is_nil(obj));
00203 #ifdef HAVE_OMNIORB4
00204   {
00205     // Hack! The '!' signals object failure.
00206     // See DaemonImpl::log() in daemon_unix.cc.
00207     omniORB::logger log("omniEvents! Object failure: ");
00208     omniIOR* ior =obj->_PR_getobj()->_getIOR();
00209     // Log Repository ID.
00210     log<<ior->repositoryID();
00211     // Log Object ID. (Limitation: only display the first TAG_INTERNET_IOP)
00212     for(CORBA::ULong i=0; i<ior->iopProfiles().length(); i++)
00213     {
00214       if (ior->iopProfiles()[i].tag == IOP::TAG_INTERNET_IOP)
00215       {
00216         IIOP::ProfileBody pBody;
00217         IIOP::unmarshalProfile(ior->iopProfiles()[i],pBody);
00218         log<<" \"";
00219         for(CORBA::ULong j=0; j<pBody.object_key.length(); ++j)
00220         {
00221           char c=(char)pBody.object_key[j];
00222           log<<( (c>=' '&&c<='~')? c: '.' ); // Log object key as text
00223         }
00224         log<<"\" at "<<(const char*)pBody.address.host<<":"<<pBody.address.port;
00225         break; // ONLY DISPLAY FIRST!
00226       }
00227     }
00228     // Log exception.
00229     if(!ex)
00230     {
00231       log<<" threw unknown exception\n";
00232     }
00233     else
00234     {
00235       log<<" threw "<<ex->_name();
00236       CORBA::SystemException* sysex =CORBA::SystemException::_downcast(ex);
00237       if(sysex)
00238           log<<" ("<<NP_MINORSTRING(*sysex)<<")";
00239       log<<"\n";
00240     }
00241   }
00242 #endif
00243   {
00244     omniORB::logger log("omniEvents! Object failure detail: ");
00245     CORBA::String_var sior( Orb::inst()._orb->object_to_string(obj) );
00246     log<<sior<<" at "<<here<<"\n";
00247   }
00248 }
00249 
00250 
00251 //
00252 // Callback
00253 //
00254 
00255 const long Callback::_goodMagic =0xCa11ab1e;
00256 
00257 Callback::~Callback()
00258 {
00259   _magic=0;
00260   // This call can be blocked waiting for a mutex. In the meantime, Orb::run()
00261   // might come along and try to call callback(). If that happens.. BANG!
00262   // This object's virtual call table has already been destroyed, so
00263   // any attempt to call a virtual function will cause a core dump.
00264 
00265   // To prevent this, here we set _magic=0 BEFORE calling cancelCallback(),
00266   // and in Orb::run() we check the value of _magic (by calling isValid())
00267   // BEFORE we try to call callback().
00268   Orb::inst().cancelCallback(this);
00269 }
00270 
00271 
00272 }; // end namespace OmniEvents

Generated on Mon Jan 9 03:52:13 2006 for OmniEvents by  doxygen 1.4.6