Orocos Real-Time Toolkit  2.9.0
TaskContextServer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Wed Jan 18 14:09:49 CET 2006 TaskContextServer.cxx
3 
4  TaskContextServer.cxx - description
5  -------------------
6  begin : Wed January 18 2006
7  copyright : (C) 2006 Peter Soetens
8  email : peter.soetens@fmtc.be
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 
40 #include "TaskContextServer.hpp"
41 #include "TaskContextProxy.hpp"
42 #include "corba.h"
43 #ifdef CORBA_IS_TAO
44 #include "TaskContextS.h"
45 #include <orbsvcs/CosNamingC.h>
46 // ACE Specific, for printing exceptions.
47 #include <ace/SString.h>
48 #include "tao/TimeBaseC.h"
49 #include "tao/Messaging/Messaging.h"
50 #include "tao/Messaging/Messaging_RT_PolicyC.h"
51 #else
52 #include <omniORB4/Naming.hh>
53 #endif
54 #include "TaskContextC.h"
55 #include "TaskContextI.h"
56 #include "DataFlowI.h"
57 #include "POAUtility.h"
58 #include <iostream>
59 #include <fstream>
60 
61 #include "../../os/threads.hpp"
62 #include "../../Activity.hpp"
63 
64 namespace RTT
65 {namespace corba
66 {
67  using namespace std;
68 
69  std::map<TaskContext*, TaskContextServer*> TaskContextServer::servers;
70 
71  base::ActivityInterface* TaskContextServer::orbrunner = 0;
72 
73  bool TaskContextServer::is_shutdown = false;
74 
75  std::map<TaskContext*, std::string> TaskContextServer::iors;
76 
78  {
79  Logger::In in("~TaskContextServer()");
80  servers.erase(mtaskcontext);
81 
82  // Remove taskcontext ior reference
83  iors.erase(mtaskcontext);
84 
85  PortableServer::ObjectId_var oid = mpoa->servant_to_id(mtask_i.in());
86  mpoa->deactivate_object(oid);
87 
88  if (muse_naming) {
89  try {
90  CORBA::Object_var rootObj = orb->resolve_initial_references("NameService");
91  CosNaming::NamingContext_var rootNC = CosNaming::NamingContext::_narrow(rootObj.in());
92 
93  if (CORBA::is_nil( rootNC.in() ) ) {
94  log(Warning) << "CTaskContext '"<< mregistered_name << "' could not find CORBA Naming Service."<<endlog();
95  } else {
96  // Nameserver found...
97  CosNaming::Name name;
98  name.length(2);
99  name[0].id = CORBA::string_dup("TaskContexts");
100  name[1].id = CORBA::string_dup( mregistered_name.c_str() );
101  try {
102  rootNC->unbind(name);
103  log(Info) << "Successfully removed CTaskContext '"<< mregistered_name <<"' from CORBA Naming Service."<<endlog();
104  }
105  catch( CosNaming::NamingContext::NotFound ) {
106  log(Info) << "CTaskContext '"<< mregistered_name << "' task was already unbound."<<endlog();
107  }
108  catch( ... ) {
109  log(Warning) << "CTaskContext '"<< mregistered_name << "' unbinding failed."<<endlog();
110  }
111  }
112  } catch (...) {
113  log(Warning) << "CTaskContext '"<< mregistered_name << "' unbinding failed from CORBA Naming Service."<<endlog();
114  }
115  }
116  }
117 
118 
119  void TaskContextServer::initTaskContextServer(bool require_name_service)
120  {
121  Logger::In in("TaskContextServer()");
122  servers[mtaskcontext] = this;
123  try {
124  // Each server has its own POA.
125  // The server's objects have their own poa as well.
126  CORBA::Object_var poa_object =
127  orb->resolve_initial_references ("RootPOA");
128  mpoa = PortableServer::POA::_narrow(poa_object);
129  PortableServer::POAManager_var poa_manager =
130  mpoa->the_POAManager ();
131 
132  //poa = POAUtility::create_basic_POA( poa, poa_manager, taskc->getName().c_str(), 0, 1);
133  // poa_manager->activate ();
134 
135  // TODO : Use a better suited POA than create_basic_POA, use the 'session' or so type
136  // But watch out: we need implicit activation, our you will get exceptions upon ->_this()
137  // The POA for the Server's objects:
138  // PortableServer::POA_var objpoa = POAUtility::create_basic_POA(poa,
139  // poa_manager,
140  // std::string(taskc->getName() + "OBJPOA").c_str(),
141  // 0, 0); // Not persistent, allow implicit.
142 
143  // The servant : TODO : cleanup servant in destructor !
145  mtask_i = serv = new RTT_corba_CTaskContext_i( mtaskcontext, mpoa );
146  mtask = serv->activate_this();
147 
148  // Store reference to iors
149  CORBA::String_var ior = orb->object_to_string( mtask.in() );
150  iors[mtaskcontext] = std::string( ior.in() );
151 
152  if ( muse_naming ) {
153  CORBA::Object_var rootObj;
154  CosNaming::NamingContext_var rootNC;
155  try {
156  rootObj = orb->resolve_initial_references("NameService");
157  rootNC = CosNaming::NamingContext::_narrow(rootObj);
158  } catch (...) {}
159 
160  if (CORBA::is_nil( rootNC ) ) {
161  std::string err("CTaskContext '" + mregistered_name + "' could not find CORBA Naming Service.");
162  if (require_name_service) {
163  log(Error) << err << endlog();
164  servers.erase(mtaskcontext);
165  throw IllegalServer(err);
166  }
167  else
168  {
169  log(Warning) << err << endlog();
170 #ifndef ORO_NO_EMIT_CORBA_IOR
171  log() <<"Writing IOR to 'std::cerr' and file '" << mregistered_name <<".ior'"<<endlog();
172 
173  // this part only publishes the IOR to a file.
174  CORBA::String_var ior = orb->object_to_string( mtask.in() );
175  std::cerr << ior.in() <<std::endl;
176  {
177  // write to a file as well.
178  std::string iorname( mregistered_name );
179  iorname += ".ior";
180  std::ofstream file_ior( iorname.c_str() );
181  file_ior << ior.in() <<std::endl;
182  }
183 #endif
184  return;
185  }
186  }
187  log(Info) << "CTaskContext '"<< mregistered_name << "' found CORBA Naming Service."<<endlog();
188  // Nameserver found...
189  CosNaming::Name name;
190  name.length(1);
191  name[0].id = CORBA::string_dup("TaskContexts");
192  CosNaming::NamingContext_var controlNC;
193  try {
194  controlNC = rootNC->bind_new_context(name);
195  }
196  catch( CosNaming::NamingContext::AlreadyBound&) {
197  log(Debug) << "NamingContext 'TaskContexts' already bound to CORBA Naming Service."<<endlog();
198  // NOP.
199  }
200 
201  name.length(2);
202  name[1].id = CORBA::string_dup( mregistered_name.c_str() );
203  try {
204  rootNC->bind(name, mtask );
205  log(Info) << "Successfully added CTaskContext '"<< mregistered_name <<"' to CORBA Naming Service."<<endlog();
206  }
207  catch( CosNaming::NamingContext::AlreadyBound&) {
208  log(Warning) << "CTaskContext '"<< mregistered_name << "' already bound to CORBA Naming Service."<<endlog();
209  log() <<"Trying to rebind...";
210  try {
211  rootNC->rebind(name, mtask);
212  } catch( ... ) {
213  log() << " failed!"<<endlog();
214  return;
215  }
216  log() << " done. New CTaskContext bound to Naming Service."<<endlog();
217  }
218  } // use_naming
219  else {
220  log(Info) <<"CTaskContext '"<< mregistered_name << "' is not using the CORBA Naming Service."<<endlog();
221 #ifndef ORO_NO_EMIT_CORBA_IOR
222  log() <<"Writing IOR to 'std::cerr' and file '" << mregistered_name <<".ior'"<<endlog();
223 
224  // this part only publishes the IOR to a file.
225  CORBA::String_var ior = orb->object_to_string( mtask.in() );
226  std::cerr << ior.in() <<std::endl;
227  {
228  // write to a file as well.
229  std::string iorname( mregistered_name );
230  iorname += ".ior";
231  std::ofstream file_ior( iorname.c_str() );
232  file_ior << ior.in() <<std::endl;
233  }
234 #endif
235  return;
236  }
237  }
238  catch (CORBA::Exception &e) {
239  log(Error) << "CORBA exception raised!" << endlog();
240  log() << CORBA_EXCEPTION_INFO(e) << endlog();
241  }
242 
243  }
244 
245  TaskContextServer::TaskContextServer(TaskContext* taskc, const string& alias, bool use_naming, bool require_name_service)
246  : mtaskcontext(taskc), muse_naming(use_naming), mregistered_name(alias)
247  {
248  this->initTaskContextServer(require_name_service);
249  }
250 
251 
252  TaskContextServer::TaskContextServer(TaskContext* taskc, bool use_naming, bool require_name_service)
253  : mtaskcontext(taskc), muse_naming(use_naming), mregistered_name(taskc->getName())
254  {
255  this->initTaskContextServer(require_name_service);
256  }
257 
259  if ( !CORBA::is_nil(orb) && !is_shutdown) {
260  log(Info) << "Cleaning up TaskContextServers..."<<endlog();
261  while ( !servers.empty() ){
262  delete servers.begin()->second;
263  // note: destructor will self-erase from map !
264  }
266  log() << "Cleanup done."<<endlog();
267  }
268  }
269 
271  if ( !CORBA::is_nil(orb) ) {
272  ServerMap::iterator it = servers.find(c);
273  if ( it != servers.end() ){
274  log(Info) << "Cleaning up TaskContextServer for "<< c->getName()<<endlog();
276  delete it->second; // destructor will do the rest.
277  // note: destructor will self-erase from map !
278  }
279  }
280  }
281 
282  void TaskContextServer::ShutdownOrb(bool wait_for_completion)
283  {
284  Logger::In in("ShutdownOrb");
285  DoShutdownOrb(wait_for_completion);
286  }
287 
288  void TaskContextServer::DoShutdownOrb(bool wait_for_completion)
289  {
290  if (is_shutdown) {
291  log(Info) << "Orb already down..."<<endlog();
292  return;
293  }
294  if ( CORBA::is_nil(orb) ) {
295  log(Error) << "Orb Shutdown...failed! Orb is nil." << endlog();
296  return;
297  }
298 
299  try {
300  CleanupServers(); // can't do this after an orb->shutdown().
301  log(Info) << "Orb Shutdown...";
302  is_shutdown = true;
303  if (wait_for_completion)
304  log(Info)<<"waiting..."<<endlog();
305  orb->shutdown( wait_for_completion );
306  log(Info) << "done." << endlog();
307  }
308  catch (CORBA::Exception &e) {
309  log(Error) << "Orb Shutdown...failed! CORBA exception raised." << endlog();
310  log() << CORBA_EXCEPTION_INFO(e) << endlog();
311  return;
312  }
313  }
314 
315 
317  {
318  if ( CORBA::is_nil(orb) ) {
319  log(Error) << "RunOrb...failed! Orb is nil." << endlog();
320  return;
321  }
322  try {
323  log(Info) <<"Entering orb->run()."<<endlog();
324  orb->run();
325  log(Info) <<"Breaking out of orb->run()."<<endlog();
326  }
327  catch (CORBA::Exception &e) {
328  log(Error) << "Orb Run : CORBA exception raised!" << endlog();
329  log() << CORBA_EXCEPTION_INFO(e) << endlog();
330  }
331  }
332 
336  class OrbRunner
337  : public Activity
338  {
339  public:
340  OrbRunner(int scheduler, int priority, unsigned cpu_affinity)
341  : Activity(scheduler, priority, cpu_affinity)
342  {}
343  void loop()
344  {
345  Logger::In in("OrbRunner");
347  }
348 
349  bool breakLoop()
350  {
351  return true;
352  }
353 
354  void finalize()
355  {
356  Logger::In in("OrbRunner");
357  log(Info) <<"Safely stopped."<<endlog();
358  }
359  };
360 
362  void TaskContextServer::ThreadOrb(int scheduler, int priority, unsigned cpu_affinity)
363  {
364  Logger::In in("ThreadOrb");
365  if ( CORBA::is_nil(orb) ) {
366  log(Error) << "ThreadOrb...failed! Orb is nil." << endlog();
367  return;
368  }
369  if (orbrunner != 0) {
370  log(Error) <<"Orb already running in a thread."<<endlog();
371  } else {
372  log(Info) <<"Starting Orb in a thread."<<endlog();
373  orbrunner = new OrbRunner(scheduler, priority, cpu_affinity);
374  orbrunner->start();
375  }
376  }
377 
379  {
380  Logger::In in("DestroyOrb");
381  if ( CORBA::is_nil(orb) ) {
382  log(Error) << "DestroyOrb...failed! Orb is nil." << endlog();
383  return;
384  }
385 
386  if (orbrunner) {
387  orbrunner->stop();
388  delete orbrunner;
389  orbrunner = 0;
390  }
391 
392  try {
393  // Destroy the POA, waiting until the destruction terminates
394  //poa->destroy (1, 1);
395  CleanupServers();
396  orb->destroy();
397  rootPOA = 0;
398  orb = 0;
399  log(Info) <<"Orb destroyed."<<endlog();
400  }
401  catch (CORBA::Exception &e) {
402  log(Error) << "Orb Destroy : CORBA exception raised!" << endlog();
403  log() << CORBA_EXCEPTION_INFO(e) << endlog();
404  }
405 
406  }
407 
408  TaskContextServer* TaskContextServer::Create(TaskContext* tc, bool use_naming, bool require_name_service){
409  return TaskContextServer::Create(tc, tc->getName(), use_naming, require_name_service);
410  }
411 
412  TaskContextServer* TaskContextServer::Create(TaskContext* tc, const std::string& alias, bool use_naming, bool require_name_service) {
413  if ( CORBA::is_nil(orb) )
414  return 0;
415 
416  if ( servers.count(tc) ) {
417  log(Debug) << "Returning existing TaskContextServer for "<< alias <<endlog();
418  return servers.find(tc)->second;
419  }
420 
421  // create new:
422  log(Info) << "Creating new TaskContextServer for "<< alias <<endlog();
423  try {
424  TaskContextServer* cts = new TaskContextServer(tc, alias, use_naming, require_name_service);
425  return cts;
426  }
427  catch( IllegalServer& is ) {
428  cerr << is.what() << endl;
429  }
430  return 0;
431  }
432 
433  CTaskContext_ptr TaskContextServer::CreateServer(TaskContext* tc, bool use_naming, bool require_name_service) {
434  return TaskContextServer::CreateServer(tc, tc->getName(), use_naming, require_name_service);
435  }
436 
437  CTaskContext_ptr TaskContextServer::CreateServer(TaskContext* tc, const std::string& alias, bool use_naming, bool require_name_service) {
438  if ( CORBA::is_nil(orb) )
439  return CTaskContext::_nil();
440 
441  if ( servers.count(tc) ) {
442  log(Debug) << "Returning existing TaskContextServer for "<< alias <<endlog();
443  return CTaskContext::_duplicate( servers.find(tc)->second->server() );
444  }
445 
446  for (TaskContextProxy::PMap::iterator it = TaskContextProxy::proxies.begin(); it != TaskContextProxy::proxies.end(); ++it)
447  if ( (it->first) == tc ) {
448  log(Debug) << "Returning server of Proxy for "<< alias <<endlog();
449  return CTaskContext::_duplicate(it->second);
450  }
451 
452  // create new:
453  log(Info) << "Creating new TaskContextServer for "<< alias <<endlog();
454  try {
455  TaskContextServer* cts = new TaskContextServer(tc, alias, use_naming, require_name_service);
456  return CTaskContext::_duplicate( cts->server() );
457  }
458  catch( IllegalServer& is ) {
459  cerr << is.what() << endl;
460  }
461  return CTaskContext::_nil();
462  }
463 
464 
465  CTaskContext_ptr TaskContextServer::server() const
466  {
467  // we're not a factory function, so we don't _duplicate.
468  return mtask.in();
469  }
470 
472  {
473  IorMap::const_iterator it = iors.find(tc);
474  if (it != iors.end())
475  return it->second;
476 
477  return std::string("");
478  }
479 
480 }}
This class manages the creation of TaskContext Corba Servers and a Corba Object Request Broker (Orb) ...
Service::shared_ptr provides()
Returns this Service.
~TaskContextServer()
When a TaskContextServer is destroyed, the object reference is removed from the Naming Service and th...
STL namespace.
virtual RTT::corba::CTaskContext_ptr activate_this()
Definition: TaskContextI.h:108
#define CORBA_EXCEPTION_INFO(x)
Definition: corba.h:68
static CTaskContext_ptr CreateServer(TaskContext *tc, bool use_naming=true, bool require_name_service=false)
Factory method: create a CORBA server for an existing TaskContext.
static std::string getIOR(TaskContext *tc)
Get the IOR of a given TaskContext.
TaskContextServer(TaskContext *taskcontext, bool use_naming, bool require_name_service)
Private constructor which creates a new servant.
basic_ostreams & endl(basic_ostreams &s)
Flush and newline.
Definition: rtstreams.cpp:110
void initTaskContextServer(bool require_name_service)
OrbRunner(int scheduler, int priority, unsigned cpu_affinity)
Thrown if a server does not exist or has the wrong type.
static void CleanupServer(TaskContext *tc)
Deletes a TaskContext server for a given taskcontext.
const char * what() const
static base::ActivityInterface * orbrunner
static PortableServer::POA_var rootPOA
The root POA of this process.
static TaskContextServer * Create(TaskContext *tc, bool use_naming=true, bool require_name_service=false)
Factory method: create a CORBA server for an existing TaskContext.
static void ThreadOrb()
This is an overloaded member function, provided for convenience. It differs from the above function o...
An Activity executes a RunnableInterface object in a (periodic) thread.
Definition: Activity.hpp:70
Class which runs an orb in an Orocos thread.
corba::CTaskContext_var mtask
static void deregisterServant(DataFlowInterface *obj)
Definition: DataFlowI.cpp:87
Notify the Logger in which &#39;module&#39; the message occured.
Definition: Logger.hpp:159
static void CleanupServers()
Destroys all TaskContextServer objects.
The TaskContext is the C++ representation of an Orocos component.
Definition: TaskContext.hpp:93
virtual bool start()=0
Start the activity.
#define ORO_SCHED_RT
Definition: fosi.h:49
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:52
static void ShutdownOrb(bool wait_for_completion=true)
Invoke this method once to shutdown the Orb which is running the task servers in RunOrb().
static void RunOrb()
Invoke this method to run the orb and accept client requests.
static void DestroyOrb()
Invoke this method once to cleanup the orb.
static void DoShutdownOrb(bool wait_for_completion=true)
Internal shutdown function, used by both thread and ShutdownOrb.
CTaskContext_ptr server() const
Get the Corba Object of this TaskContext.
static CORBA::ORB_var orb
The orb of this process.
virtual const std::string & getName() const
Returns the name of this TaskContext.
virtual bool stop()=0
Stop the activity This will stop the activity by removing it from the &#39;run-queue&#39; of a thread or call...