#include "tao/ImR_Client/ImR_Client.h" #include "ace/Vector_T.h" #include "tao/debug.h" #include "tao/ORB_Core.h" #include "tao/Stub.h" #include "tao/Profile.h" #include "tao/PortableServer/Root_POA.h" #include "tao/PortableServer/Non_Servant_Upcall.h" #include "tao/ImR_Client/ServerObject_i.h" #include "tao/ImR_Client/ImplRepoC.h" #include "tao/IORManipulation/IORManip_Loader.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL namespace { char* find_delimiter (char* const ior, const char delimiter) { // Search for "corbaloc:" alone, without the protocol. This code // should be protocol neutral. const char corbaloc[] = "corbaloc:"; char *pos = ACE_OS::strstr (ior, corbaloc); pos = ACE_OS::strchr (pos + sizeof (corbaloc), ':'); pos = ACE_OS::strchr (pos + 1, delimiter); return pos; } CORBA::Object_ptr combine (TAO_ORB_Core& orb_core, const TAO_Profile& profile, const char* const key_str, const char* type_id) { CORBA::String_var profile_str = profile.to_string (); if (TAO_debug_level > 0) { TAOLIB_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO_ImR_Client (%P|%t) - IMR partial IOR <%C>\n"), profile_str.in ())); } char* const pos = find_delimiter (profile_str.inout (), profile.object_key_delimiter ()); if (pos) pos[1] = 0; // Crop the string. else { if (TAO_debug_level > 0) { TAOLIB_ERROR ((LM_ERROR, ACE_TEXT ("TAO_ImR_Client (%P|%t) - Could not parse ImR IOR, skipping ImRification\n"))); } return CORBA::Object::_nil(); } ACE_CString ior (profile_str.in ()); // Add the key. ior += key_str; if (TAO_debug_level > 0) { TAOLIB_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO_ImR_Client (%P|%t) - ImR-ified IOR <%C>\n"), ior.c_str ())); } CORBA::Object_ptr obj = orb_core.orb ()->string_to_object (ior.c_str ()); obj->_stubobj()->type_id = type_id; return obj; } class ImRifyProfiles { public: ImRifyProfiles (const TAO_MProfile& base_profiles, const TAO_Profile* const profile_in_use, TAO_ORB_Core& orb_core, const char* const key_str, const char* type_id) : base_profiles_ (base_profiles), profile_in_use_ (profile_in_use), orb_core_ (orb_core), key_str_ (key_str), type_id_ (type_id), objs_ (base_profiles.profile_count()), list_buffer_ (new CORBA::Object_ptr[base_profiles.profile_count()]), ior_list_ (base_profiles.profile_count (), base_profiles.profile_count (), list_buffer_, 0) { } ~ImRifyProfiles () { delete [] list_buffer_; } CORBA::Object_ptr combined_ior () { const CORBA::ULong pcount = base_profiles_.profile_count (); for (CORBA::ULong i = 0; i < pcount; ++i) { if (!combine_profile (i)) { return default_obj ("could not resolve IORManipulation"); } } CORBA::Object_var IORM = orb_core_.orb () ->resolve_initial_references (TAO_OBJID_IORMANIPULATION, 0); if (CORBA::is_nil (IORM.in ())) { return default_obj ("could not resolve IORManipulation"); } TAO_IOP::TAO_IOR_Manipulation_var iorm = TAO_IOP::TAO_IOR_Manipulation::_narrow (IORM.in ()); if (CORBA::is_nil (iorm.in ())) { return default_obj ("could not narrow IORManipulation"); } try { return iorm->merge_iors(ior_list_); } catch (const ::CORBA::Exception& ) { return default_obj ("could not ImRify object with all profiles"); } } private: bool combine_profile(const CORBA::ULong i) { try { // store the combined profile+key list_buffer_[i] = combine (orb_core_, *(base_profiles_.get_profile (i)), key_str_, type_id_); // manage the memory objs_[i] = list_buffer_[i]; return true; } catch (const ::CORBA::Exception& ) { return false; } } CORBA::Object_ptr default_obj(const char* desc) { const CORBA::ULong pcount = base_profiles_.profile_count (); const char* info = "because couldn't find ImR profile_in_use in profiles"; // identify the profile in use to see if we can default to // that profiles partial ImR-ification for (CORBA::ULong i = 0; i < pcount; ++i) { if (profile_in_use_ == base_profiles_.get_profile (i)) { // if there is no object then try one last time to combine // the profile if (CORBA::is_nil(objs_[i].in ()) && !combine_profile (i)) { info = "because couldn't ImR-ify profile_in_use"; break; } if (TAO_debug_level > 0) { TAOLIB_ERROR((LM_ERROR, ACE_TEXT("TAO_ImR_Client (%P|%t) - ERROR: %C. ") ACE_TEXT("Defaulting to ImR-ifying profile_in_use\n"), desc)); } return objs_[i]._retn (); } } if (TAO_debug_level > 0) { TAOLIB_ERROR((LM_ERROR, ACE_TEXT ("TAO_ImR_Client (%P|%t) - ERROR: %C, ") ACE_TEXT ("but cannot default to ImR-ifying profile_in_use %C\n"), desc, info)); } return CORBA::Object::_nil(); } const TAO_MProfile& base_profiles_; const TAO_Profile* const profile_in_use_; TAO_ORB_Core& orb_core_; const char* const key_str_; const char* const type_id_; ACE_Vector objs_; CORBA::Object_ptr* const list_buffer_; TAO_IOP::TAO_IOR_Manipulation::IORList ior_list_; }; } namespace TAO { namespace ImR_Client { ImR_Client_Adapter_Impl::ImR_Client_Adapter_Impl (void) : server_object_ (0) { } void ImR_Client_Adapter_Impl::imr_notify_startup (TAO_Root_POA* poa ) { CORBA::Object_var imr = poa->orb_core ().implrepo_service (); if (CORBA::is_nil (imr.in ())) { if (TAO_debug_level > 0) { TAOLIB_ERROR ((LM_ERROR, ACE_TEXT ("TAO_ImR_Client (%P|%t) - ERROR: No usable IMR initial reference ") ACE_TEXT ("available but use IMR has been specified.\n"))); } throw ::CORBA::TRANSIENT ( CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), CORBA::COMPLETED_NO); } if (TAO_debug_level > 0) { if (TAO_debug_level > 1) { CORBA::ORB_ptr orb = poa->orb_core ().orb (); CORBA::String_var ior = orb->object_to_string (imr.in ()); TAOLIB_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO_ImR_Client (%P|%t) - Notifying ImR of startup IMR IOR <%C>\n"), ior.in ())); } } ImplementationRepository::Administration_var imr_locator; { // ATTENTION: Trick locking here, see class header for details TAO::Portable_Server::Non_Servant_Upcall non_servant_upcall (*poa); ACE_UNUSED_ARG (non_servant_upcall); imr_locator = ImplementationRepository::Administration::_narrow (imr.in ()); } if (CORBA::is_nil (imr_locator.in ())) { if (TAO_debug_level > 0) { TAOLIB_ERROR ((LM_ERROR, ACE_TEXT ("TAO_ImR_Client (%P|%t) - ERROR: Narrowed IMR initial reference ") ACE_TEXT ("is nil but use IMR has been specified.\n"))); } throw ::CORBA::TRANSIENT ( CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), CORBA::COMPLETED_NO); } TAO_Root_POA *root_poa = poa->object_adapter ().root_poa (); ACE_NEW_THROW_EX (this->server_object_, ServerObject_i (poa->orb_core ().orb (), root_poa), CORBA::NO_MEMORY ()); PortableServer::ServantBase_var safe_servant (this->server_object_); ACE_UNUSED_ARG (safe_servant); // Since this method is called from the POA constructor, there // shouldn't be any waiting required. Therefore, // can be ignored. bool wait_occurred_restart_call_ignored = false; // Activate the servant in the root poa. PortableServer::ObjectId_var id = root_poa->activate_object_i (this->server_object_, poa->server_priority (), wait_occurred_restart_call_ignored); CORBA::Object_var obj = root_poa->id_to_reference_i (id.in (), false); ImplementationRepository::ServerObject_var svr = ImplementationRepository::ServerObject::_narrow (obj.in ()); if (!svr->_stubobj () || !svr->_stubobj ()->profile_in_use ()) { if (TAO_debug_level > 0) { TAOLIB_ERROR ((LM_ERROR, "TAO_ImR_Client (%P|%t) - Invalid ImR ServerObject, bailing out.\n")); } return; } CORBA::ORB_var orb = root_poa->_get_orb (); CORBA::String_var full_ior = orb->object_to_string (obj.in ()); TAO_Profile& profile = *(svr->_stubobj ()->profile_in_use ()); CORBA::String_var ior = profile.to_string(); if (TAO_debug_level > 0) { TAOLIB_DEBUG((LM_INFO, "TAO_ImR_Client (%P|%t) - full_ior <%C>\nior <%C>\n", full_ior.in(), ior.in())); } char* const pos = find_delimiter (ior.inout (), profile.object_key_delimiter ()); const ACE_CString partial_ior (ior.in (), (pos - ior.in ()) + 1); if (TAO_debug_level > 0) { CORBA::String_var poaname = poa->the_name (); TAOLIB_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO_ImR_Client (%P|%t) - Informing IMR that <%C> is running at <%C>\n"), poaname.in(), partial_ior.c_str ())); } try { // ATTENTION: Trick locking here, see class header for details TAO::Portable_Server::Non_Servant_Upcall non_servant_upcall (*poa); ACE_UNUSED_ARG (non_servant_upcall); ACE_CString const serverId = poa->orb_core ().server_id (); ACE_CString name; if (serverId.empty ()) { name = poa->name (); } else { name = serverId + ":" + poa->name (); } imr_locator->server_is_running (name.c_str (), partial_ior.c_str (), svr.in ()); } catch (const ::CORBA::SystemException&) { throw; } catch (const ::CORBA::Exception&) { throw ::CORBA::TRANSIENT ( CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), CORBA::COMPLETED_NO); } if (TAO_debug_level > 0) { TAOLIB_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO_ImR_Client (%P|%t) - Successfully notified ImR of Startup\n"))); } } void ImR_Client_Adapter_Impl::imr_notify_shutdown (TAO_Root_POA* poa ) { // Notify the Implementation Repository about shutting down. CORBA::Object_var imr = poa->orb_core ().implrepo_service (); // Check to see if there was an imr returned. // If none, return ourselves. if (CORBA::is_nil (imr.in ())) return; try { if (TAO_debug_level > 0) { CORBA::String_var poaname = poa->the_name (); TAOLIB_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO_ImR_Client (%P|%t) - Notifying IMR of Shutdown server: <%C>\n"), poaname.in ())); } // ATTENTION: Trick locking here, see class header for details TAO::Portable_Server::Non_Servant_Upcall non_servant_upcall (*poa); ACE_UNUSED_ARG (non_servant_upcall); // Get the IMR's administrative object and call shutting_down on it ImplementationRepository::Administration_var imr_locator = ImplementationRepository::Administration::_narrow (imr.in ()); imr_locator->server_is_shutting_down (poa->name ().c_str ()); } catch (const ::CORBA::COMM_FAILURE&) { // At the moment we call this during ORB shutdown and the ORB is // configured to drop replies during shutdown (it does by default in // the LF model) we get a COMM_FAILURE exception which we ignore if (TAO_debug_level > 0) { TAOLIB_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO_ImR_Client (%P|%t) - Ignoring COMM_FAILURE while unregistering") ACE_TEXT ("from ImR.\n"))); } } catch (const ::CORBA::TRANSIENT&) { // Similarly, there are cases where we could get a TRANSIENT. if (TAO_debug_level > 0) { TAOLIB_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO_ImR_Client (%P|%t) - Ignoring TRANSIENT while unregistering") ACE_TEXT ("from ImR.\n"))); } } catch (const ::CORBA::Exception& ex) { ex._tao_print_exception ( "ImR_Client_Adapter_Impl::imr_notify_shutdown()"); // Ignore exceptions } if (this->server_object_) { PortableServer::POA_var default_poa = this->server_object_->_default_POA (); TAO_Root_POA *root_poa = dynamic_cast (default_poa.in ()); if (!root_poa) { throw ::CORBA::OBJ_ADAPTER (); } PortableServer::ObjectId_var id = root_poa->servant_to_id_i (this->server_object_); root_poa->deactivate_object_i (id.in ()); this->server_object_ = 0; } } // ********************************************************************* // Initialization and registration of dynamic service object. int ImR_Client_Adapter_Impl::Initializer (void) { TAO_Root_POA::imr_client_adapter_name ( "Concrete_ImR_Client_Adapter"); return ACE_Service_Config::process_directive ( ace_svc_desc_ImR_Client_Adapter_Impl); } CORBA::Object_ptr ImR_Client_Adapter_Impl::imr_key_to_object(TAO_Root_POA* poa, const TAO::ObjectKey &key, const char* type_id) const { TAO_ORB_Core& orb_core = poa->orb_core (); // Check to see if we alter the IOR. CORBA::Object_var imr = orb_core.implrepo_service (); if (CORBA::is_nil (imr.in ()) || !imr->_stubobj () || !imr->_stubobj ()->profile_in_use ()) { if (TAO_debug_level > 1) { TAOLIB_DEBUG ((LM_DEBUG, ACE_TEXT ("TAO_ImR_Client (%P|%t) - Missing ImR IOR, will not use the ImR\n"))); } return CORBA::Object::_nil(); } const TAO_MProfile& base_profiles = imr->_stubobj ()->base_profiles (); CORBA::String_var key_str; TAO::ObjectKey::encode_sequence_to_string (key_str.inout (), key); // if there is only one profile, no need to use IORManipulation if (base_profiles.profile_count() == 1) { return combine(orb_core, *base_profiles.get_profile(0), key_str.in(), type_id); } // need to combine each profile in the ImR with the key and // then merge them all together into one ImR-ified ior ImRifyProfiles imrify (base_profiles, imr->_stubobj ()->profile_in_use (), orb_core, key_str, type_id); return imrify.combined_ior (); } } } ACE_STATIC_SVC_DEFINE ( ImR_Client_Adapter_Impl, ACE_TEXT ("Concrete_ImR_Client_Adapter"), ACE_SVC_OBJ_T, &ACE_SVC_NAME (ImR_Client_Adapter_Impl), ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ, 0) ACE_FACTORY_NAMESPACE_DEFINE ( TAO_IMR_Client, ImR_Client_Adapter_Impl, TAO::ImR_Client::ImR_Client_Adapter_Impl) TAO_END_VERSIONED_NAMESPACE_DECL