#include "orbsvcs/Log_Macros.h" #include "orbsvcs/Log_Macros.h" #include "orbsvcs/Notify/MonitorControl/MonitorManager.h" #if defined (TAO_HAS_MONITOR_FRAMEWORK) && (TAO_HAS_MONITOR_FRAMEWORK == 1) #include "orbsvcs/Notify/MonitorControl/NotificationServiceMonitor_i.h" #include "orbsvcs/Naming/Naming_Client.h" #include "tao/ORB.h" #include "tao/IORTable/IORTable.h" #include "ace/Service_Config.h" #include "ace/Get_Opt.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL TAO_MonitorManager::TAO_MonitorManager () : run_ (false) , initialized_ (false) { } int TAO_MonitorManager::init (int argc, ACE_TCHAR* argv[]) { ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->task_.mutex_, -1); this->task_.argv_.add (ACE_TEXT("fake_process_name")); ACE_Get_Opt opts (argc, argv, ACE_TEXT ("o:"), 0, 0, ACE_Get_Opt::PERMUTE_ARGS, 1); static const ACE_TCHAR* orbarg = ACE_TEXT ("ORBArg"); static const ACE_TCHAR* nonamesvc = ACE_TEXT ("NoNameSvc"); opts.long_option (orbarg, ACE_Get_Opt::ARG_REQUIRED); opts.long_option (nonamesvc, ACE_Get_Opt::NO_ARG); int c; while ((c = opts ()) != -1) switch (c) { case 'o': this->task_.ior_output_ = opts.opt_arg (); if (TAO_debug_level > 7) { ORBSVCS_DEBUG((LM_INFO, ACE_TEXT("(%P|%t) TAO_MonitorManager: Setting IOR output file to: %s"), this->task_.ior_output_.c_str ())); } break; case 0: if (ACE_OS::strcmp (opts.long_option (), orbarg) == 0) { ACE_TCHAR * orbArgs = opts.opt_arg (); if (TAO_debug_level > 7) { ORBSVCS_DEBUG((LM_INFO, ACE_TEXT("(%P|%t) TAO_MonitorManager: Setting Orb arguments to: %s"), orbArgs)); } this->task_.argv_.add (orbArgs); } else if (ACE_OS::strcmp (opts.long_option (), nonamesvc) == 0) { if (TAO_debug_level > 7) { ORBSVCS_DEBUG((LM_INFO, ACE_TEXT("(%P|%t) TAO_MonitorManager: Not using naming service"))); } this->task_.use_name_svc_ = false; } break; case ':': ORBSVCS_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) TAO_MonitorManager: %s requires an argument\n"), opts.last_option ()), -1); } // Force the ARGV_T to copy the elements added by the add() method this->task_.argv_.argv (); // Rember that Monitor has been configured this->initialized_ = true; return 0; } int TAO_MonitorManager::fini () { if (!CORBA::is_nil (this->task_.orb_.in ())) { ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->task_.mutex_, -1); if (!CORBA::is_nil (this->task_.orb_.in ())) { this->task_.orb_->shutdown (true); } } this->task_.wait (); return 0; } int TAO_MonitorManager::run () { bool activate = false; { ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->task_.mutex_, -1); // Work around for bug 3108. Need to create MC ORB in main thread // so any libs are loaded in the parent thread. // Initialize the ORB int argc = task_.argv_.argc (); task_.orb_ = CORBA::ORB_init (argc, task_.argv_.argv (), task_.mc_orb_name_.c_str ()); if (!this->run_ && this->initialized_) { this->run_ = true; activate = true; } } int status = 0; if (activate) { status = this->task_.activate (); if (status == 0) { // cj: Wait till the child thread has initialized completely // It still leaves a tiny race window open, but hopefully not much. // The race condition R1 is in ORBTask::svc(). this->task_.startup_barrier_.wait (); } } return status; } int TAO_MonitorManager::resume () { return this->run (); } void TAO_MonitorManager::shutdown () { TAO_MonitorManager* monitor = ACE_Dynamic_Service::instance ( TAO_NOTIFY_MONITOR_CONTROL_MANAGER); if (monitor != 0) { monitor->fini (); } } TAO_MonitorManager::ORBTask::ORBTask () : use_name_svc_ (true) , startup_barrier_ (2) // synch the parent with the single child thread , mc_orb_name_ (ACE_TEXT("TAO_MonitorAndControl")) { } int TAO_MonitorManager::ORBTask::svc () { try { if (CORBA::is_nil (this->orb_.in ())) { ORBSVCS_ERROR_RETURN ((LM_ERROR, "(%P|%t) TAO_MonitorManager: Unable to " "initialize the ORB\n"), 1); } PortableServer::POA_var poa; { ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->mutex_, -1); CORBA::Object_var obj = this->orb_->resolve_initial_references ("RootPOA"); poa = PortableServer::POA::_narrow (obj.in ()); if (CORBA::is_nil (poa.in ())) { ORBSVCS_ERROR_RETURN ((LM_ERROR, "(%P|%t) TAO_MonitorManager: Unable to " "resolve the RootPOA\n"), 1); } PortableServer::POAManager_var poa_manager = poa->the_POAManager (); poa_manager->activate (); // Activate the object NotificationServiceMonitor_i* servant; ACE_NEW_RETURN (servant, NotificationServiceMonitor_i (this->orb_.in ()), 1); PortableServer::ServantBase_var owner_transfer(servant); PortableServer::ObjectId_var id = poa->activate_object (servant); // Register the object with the IORTable obj = poa->id_to_reference (id.in ()); CosNotification::NotificationServiceMonitorControl_var monitor = CosNotification::NotificationServiceMonitorControl::_narrow (obj.in ()); CORBA::String_var ior = this->orb_->object_to_string (monitor.in ()); obj = this->orb_->resolve_initial_references ("IORTable"); IORTable::Table_var iortable = IORTable::Table::_narrow (obj.in ()); if (CORBA::is_nil (iortable.in ())) { ORBSVCS_ERROR_RETURN ((LM_ERROR, "(%P|%t) TAO_MonitorManager: Unable to " "resolve the IORTable\n"), 1); } iortable->bind(ACE_TEXT_ALWAYS_CHAR(mc_orb_name_.c_str()), ior.in ()); if (this->use_name_svc_) { TAO_Naming_Client nc; nc.init (this->orb_.in ()); CosNaming::Name name (1); name.length (1); name[0].id = CORBA::string_dup (ACE_TEXT_ALWAYS_CHAR(mc_orb_name_.c_str())); nc->rebind (name, monitor.in ()); } if (this->ior_output_.length () > 0) { FILE* fp = ACE_OS::fopen (this->ior_output_.c_str (), "w"); if (fp == 0) { ORBSVCS_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) TAO_MonitorManager: " ACE_TEXT ("Unable to write to %s\n")), this->ior_output_.c_str ()), 1); } else { ACE_OS::fprintf (fp, "%s", ior.in ()); ACE_OS::fclose (fp); } } } // R1: race condition (partially fixed): // TAO_MonitorManager::fini() is called directly after // TAO_MonitorManager::run(), the shutdown call on the ORB could // happen but the ORB::run() loop won't exit. startup_barrier_.wait (); this->orb_->run (); ACE_GUARD_RETURN (TAO_SYNCH_MUTEX, guard, this->mutex_, -1); // Destroy the POA and ORB if (!CORBA::is_nil (poa.in ())) { poa->destroy (true, true); } this->orb_->destroy (); // Set to nil to avoid double shutdown in TAO_MonitorManager::fini() this->orb_ = CORBA::ORB::_nil (); } catch (const CORBA::Exception& ex) { if (!CORBA::is_nil (this->orb_.in ())) { try { this->orb_->shutdown (); } catch (...) { } this->orb_ = CORBA::ORB::_nil (); } ex._tao_print_exception ("Caught in " "TAO_MonitorManager::ORBTask::svc"); } catch (...) { if (!CORBA::is_nil (this->orb_.in ())) { try { this->orb_->shutdown (); } catch (...) { } this->orb_ = CORBA::ORB::_nil (); } ORBSVCS_ERROR ((LM_ERROR, "Unexpected exception type caught " "in TAO_MonitorManager::ORBTask::svc")); } return 0; } TAO_END_VERSIONED_NAMESPACE_DECL typedef TAO_MonitorManager TAO_MonitorAndControl; ACE_STATIC_SVC_DEFINE (TAO_MonitorAndControl, ACE_TEXT (TAO_NOTIFY_MONITOR_CONTROL_MANAGER), ACE_Service_Type::SERVICE_OBJECT, &ACE_SVC_NAME (TAO_MonitorAndControl), ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, 0) ACE_FACTORY_DEFINE (TAO_Notify_MC, TAO_MonitorAndControl) #endif /* TAO_HAS_MONITOR_FRAMEWORK==1 */