OmniEvents
Orb.cc
Go to the documentation of this file.
1 // Package : omniEvents
2 // Orb.cc Created : 2003/12/04
3 // Author : Alex Tingle
4 //
5 // Copyright (C) 2003-2005 Alex Tingle.
6 //
7 // This file is part of the omniEvents application.
8 //
9 // omniEvents is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // omniEvents is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 
24 #include "Orb.h"
25 
26 #ifdef HAVE_IOSTREAM
27 # include <iostream>
28 #else
29 # include <iostream.h>
30 #endif
31 
32 #include <stdlib.h>
33 #include <assert.h>
34 
35 #include "Callback.h"
36 
37 namespace OmniEvents {
38 
39 Orb Orb::_inst;
40 
41 
43 {
44  omni_mutex_lock l(_deferredRequestsLock);
45  list<RequestCallback_t>::iterator curr, next=_deferredRequests.begin();
46  while(next!=_deferredRequests.end())
47  {
48  curr=next++;
49  CORBA::release(curr->first);
50  _deferredRequests.erase(curr);
51  }
52 }
53 
54 
56 {
57  assert(!CORBA::is_nil(_orb));
58 
59  const char* action=""; // Use this variable to help report errors.
60  try
61  {
62  CORBA::Object_var obj;
63 
64  action="resolve initial reference 'RootPOA'";
65  obj=_orb->resolve_initial_references("RootPOA");
66  _RootPOA=PortableServer::POA::_narrow(obj);
67  if(CORBA::is_nil(_RootPOA))
68  throw CORBA::OBJECT_NOT_EXIST();
69 
70  action="resolve initial reference 'omniINSPOA'";
71  obj=_orb->resolve_initial_references("omniINSPOA");
72  _omniINSPOA=PortableServer::POA::_narrow(obj);
73  if(CORBA::is_nil(_omniINSPOA))
74  throw CORBA::OBJECT_NOT_EXIST();
75 
76  // The naming service is optional.
77  try
78  {
79  action="resolve initial reference 'NameService'";
80  obj=_orb->resolve_initial_references("NameService");
81  _NameService=CosNaming::NamingContext::_narrow(obj);
82  }
83  catch(CORBA::Exception& ex)
84  {
85  DB(1,"Warning - failed to "<<action<<
86  IFELSE_OMNIORB4(". Exception: "<<ex._name(),"."))
87  }
88 
89 #ifdef HAVE_OMNIORB4
90  action="resolve initial reference 'POACurrent'";
91  obj=_orb->resolve_initial_references("POACurrent");
92  _POACurrent=PortableServer::Current::_narrow(obj);
93  if(CORBA::is_nil(_POACurrent))
94  throw CORBA::OBJECT_NOT_EXIST();
95 #endif
96 
97  return;
98  }
99  catch(CORBA::ORB::InvalidName& ex) // resolve_initial_references
100  {
101  DB(0,"Failed to "<<action<<". InvalidName")
102  }
103  catch(CORBA::TRANSIENT& ex) // _narrow()
104  {
105  DB(0,"Failed to "<<action<<". TRANSIENT")
106  }
107  catch(CORBA::OBJECT_NOT_EXIST& ex) // _narrow()
108  {
109  DB(0,"Failed to "<<action<<". OBJECT_NOT_EXIST")
110  }
111  catch(CORBA::SystemException& ex)
112  {
113  DB(0,"Failed to "<<action<<"."
114  IF_OMNIORB4(" "<<ex._name()<<" ("<<NP_MINORSTRING(ex)<<")") )
115  }
116  catch(CORBA::Exception& ex)
117  {
118  DB(0,"Failed to "<<action<<"." IF_OMNIORB4(" "<<ex._name()) )
119  }
120  exit(1);
121 }
122 
123 
124 void Orb::run()
125 {
126  while(!_shutdownRequested)
127  {
128  omni_thread::sleep(5);
129 
130  list<Callback*> usedCallbacks;
131  {
132  omni_mutex_lock l(_deferredRequestsLock);
133  DB(20,"Polling "<<_deferredRequests.size()<<" deferred requests.")
134  list<RequestCallback_t>::iterator curr, next=_deferredRequests.begin();
135  while(next!=_deferredRequests.end())
136  {
137  curr=next++;
138  if(curr->first->poll_response())
139  {
140  CORBA::Environment_ptr env=curr->first->env();// No need to release.
141  if(!CORBA::is_nil(env) && env->exception())
142  {
143  CORBA::Exception* ex =env->exception(); // No need to free exception
144  DB(10,"Deferred call to "<<curr->first->operation()
145  <<"() got exception" IF_OMNIORB4(<<": "<<ex->_name()))
146  }
147  else if(curr->second)
148  {
149  DB(15,"Deferred call to "<<curr->first->operation()<<"() returned.")
150  curr->second->callback(curr->first);
151  }
152  else
153  {
154  DB(15,"Orphan call to "<<curr->first->operation()<<"() returned.")
155  }
156  CORBA::release(curr->first);
157  if(curr->second)
158  usedCallbacks.push_back( curr->second );
159  _deferredRequests.erase(curr);
160  }
161  } // end loop while()
162  }
163  // _deferredRequestsLock is now unlocked: clear away used callbacks.
164  // (Cannot do this while _deferredRequestsLock is held, because of the
165  // following deadlock:
166  // _remove_ref() -> ~Proxy() -> Orb::deferredRequest()
167  while(!usedCallbacks.empty())
168  {
169  usedCallbacks.front()->_remove_ref();
170  usedCallbacks.pop_front();
171  }
172  } // end loop while(!_shutdownRequested)
173 
174  // Clean up all outstanding requests.
175  omni_mutex_lock l(_deferredRequestsLock);
176  while(!_deferredRequests.empty())
177  {
178  _deferredRequests.front().first->get_response();
179  CORBA::release(_deferredRequests.front().first);
180  if(_deferredRequests.front().second)
181  _deferredRequests.front().second->_remove_ref();
182  _deferredRequests.pop_front();
183  }
184 }
185 
186 
187 void Orb::deferredRequest(CORBA::Request_ptr req, Callback* callback)
188 {
190  callback=NULL;
191  // If _shutdownRequested and Orb::run() has already terminated, then
192  // the request (req) will never be collected or released. This is sad, and it
193  // makes omniORB complain - but at least it works:
194  // Attempting to get_response() here can cause deadlock. Just releasing the
195  // Request causes a SEGV when the call returns.
196 
197  if(callback)
198  callback->_add_ref();
199  omni_mutex_lock l(_deferredRequestsLock);
200  _deferredRequests.push_back(RequestCallback_t(req,callback));
201 }
202 
203 
205  const char* here,
206  CORBA::Object_ptr obj,
207  CORBA::Exception* ex
208 )
209 {
210  assert(!CORBA::is_nil(obj));
211 #ifdef HAVE_OMNIORB4
212  {
213  // Hack! The '!' signals object failure.
214  // See DaemonImpl::log() in daemon_unix.cc.
215  omniORB::logger log("omniEvents! Object failure: ");
216  omniIOR* ior =obj->_PR_getobj()->_getIOR();
217  // Log Repository ID.
218  log<<ior->repositoryID();
219  // Log Object ID. (Limitation: only display the first TAG_INTERNET_IOP)
220  for(CORBA::ULong i=0; i<ior->iopProfiles().length(); i++)
221  {
222  if (ior->iopProfiles()[i].tag == IOP::TAG_INTERNET_IOP)
223  {
224  IIOP::ProfileBody pBody;
225  IIOP::unmarshalProfile(ior->iopProfiles()[i],pBody);
226  log<<" \"";
227  for(CORBA::ULong j=0; j<pBody.object_key.length(); ++j)
228  {
229  char c=(char)pBody.object_key[j];
230  log<<( (c>=' '&&c<='~')? c: '.' ); // Log object key as text
231  }
232  log<<"\" at "<<(const char*)pBody.address.host<<":"<<pBody.address.port;
233  break; // ONLY DISPLAY FIRST!
234  }
235  }
236  // Log exception.
237  if(!ex)
238  {
239  log<<" threw unknown exception\n";
240  }
241  else
242  {
243  log<<" threw "<<ex->_name();
244  CORBA::SystemException* sysex =CORBA::SystemException::_downcast(ex);
245  if(sysex)
246  log<<" ("<<NP_MINORSTRING(*sysex)<<")";
247  log<<"\n";
248  }
249  }
250 #endif
251  {
252  omniORB::logger log("omniEvents! Object failure detail: ");
253  CORBA::String_var sior( Orb::inst()._orb->object_to_string(obj) );
254  log<<sior<<" at "<<here<<"\n";
255  }
256 }
257 
258 
259 }; // end namespace OmniEvents
#define IFELSE_OMNIORB4(omniORB4_code, default_code)
Definition: Orb.h:45
#define DB(l, x)
Definition: Orb.h:49
#define IF_OMNIORB4(omniORB4_code)
Definition: Orb.h:46
#define NP_MINORSTRING(systemException)
Definition: Orb.h:52
Interface for classes that wish to receive callbacks from deferred requests.
Definition: Callback.h:46
PortableServer::POA_var _RootPOA
Definition: Orb.h:89
pair< CORBA::Request_ptr, Callback * > RequestCallback_t
Definition: Orb.h:73
~Orb()
Destructor needs to be public to keep MS VC++6 happy.
Definition: Orb.cc:42
list< RequestCallback_t > _deferredRequests
Definition: Orb.h:74
CORBA::ORB_var _orb
Definition: Orb.h:88
static Orb _inst
Definition: Orb.h:72
bool _shutdownRequested
Definition: Orb.h:76
CosNaming::NamingContext_var _NameService
Definition: Orb.h:91
void deferredRequest(CORBA::Request_ptr req, Callback *callback=NULL)
Adopts the request and then stores it in _deferredRequests.
Definition: Orb.cc:187
void reportObjectFailure(const char *here, CORBA::Object_ptr obj, CORBA::Exception *ex)
Called by omniEvents when an object has failed (fatal exception).
Definition: Orb.cc:204
static Orb & inst()
Definition: Orb.h:81
void resolveInitialReferences()
_orb must already have been initialized before this method is called.
Definition: Orb.cc:55
omni_mutex _deferredRequestsLock
Definition: Orb.h:75
void run()
Parks the main thread, but also picks up (and ignores) responses from orphan requests.
Definition: Orb.cc:124
PortableServer::POA_var _omniINSPOA
Definition: Orb.h:90