diff options
Diffstat (limited to 'ACE/TAO/orbsvcs/Fault_Detector/FT_FaultDetectorFactory_i.cpp')
-rw-r--r-- | ACE/TAO/orbsvcs/Fault_Detector/FT_FaultDetectorFactory_i.cpp | 666 |
1 files changed, 666 insertions, 0 deletions
diff --git a/ACE/TAO/orbsvcs/Fault_Detector/FT_FaultDetectorFactory_i.cpp b/ACE/TAO/orbsvcs/Fault_Detector/FT_FaultDetectorFactory_i.cpp new file mode 100644 index 00000000000..46b0d49d480 --- /dev/null +++ b/ACE/TAO/orbsvcs/Fault_Detector/FT_FaultDetectorFactory_i.cpp @@ -0,0 +1,666 @@ +/* -*- C++ -*- */ +//============================================================================= +/** + * @file FT_FaultDetectorFactory_i.cpp + * + * $Id$ + * + * This file is part of Fault Tolerant CORBA. + * + * @author Dale Wilson <wilson_d@ociweb.com> + */ +//============================================================================= +#include "FT_FaultDetectorFactory_i.h" +#include "Fault_Detector_i.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_unistd.h" +#include "ace/Auto_Ptr.h" +#include "orbsvcs/CosNamingC.h" +#include "orbsvcs/PortableGroup/PG_Property_Set.h" + +// Use this macro at the beginning of CORBA methods +// to aid in debugging. +#define METHOD_ENTRY(name) \ + ACE_DEBUG (( LM_DEBUG, \ + "Enter %s\n", #name \ + )) + +// Use this macro to return from CORBA methods +// to aid in debugging. Note that you can specify +// the return value after the macro, for example: +// METHOD_RETURN(Plugh::plover) xyzzy; is equivalent +// to return xyzzy; +// METHOD_RETURN(Plugh::troll); is equivalent to +// return; +// WARNING: THIS GENERATES TWO STATEMENTS!!! THE FOLLOWING +// will not do what you want it to: +// if (cave_is_closing) METHOD_RETURN(Plugh::pirate) aarrggh; +// Moral: Always use braces. +#define METHOD_RETURN(name) \ + ACE_DEBUG (( LM_DEBUG, \ + "Leave %s\n", #name \ + )); \ + return /* value goes here */ + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +////////////////////////////////////////////////////// +// FT_FaultDetectorFactory_i Construction/destruction + +TAO::FT_FaultDetectorFactory_i::FT_FaultDetectorFactory_i () + : orb_ (0) + , poa_ (0) + , objectId_ (0) + , ior_output_file_ (0) + , ns_name_ (0) + , naming_context_ (0) + , this_name_ (1) + , quit_on_idle_ (0) + , domain_ (CORBA::string_dup("default_domain")) + , location_ (1) + , notifier_ (0) + , rm_register_ (1) + , replication_manager_ (0) + , registered_ (0) + , factory_registry_ (0) + , identity_ ("") + , empty_slots_ (0) + , quit_requested_ (0) + +{ + this->location_.length(1); + this->location_[0].id = CORBA::string_dup("default_location"); +} + +TAO::FT_FaultDetectorFactory_i::~FT_FaultDetectorFactory_i () +{ + //scope the guard + { + InternalGuard guard (this->internals_); + + // be sure all detectors are gone + // before this object disappears + shutdown_i (); + } + fini (); + this->threadManager_.close (); +} + +//////////////////////////////////////////// +// FT_FaultDetectorFactory_i private methods + +void TAO::FT_FaultDetectorFactory_i::shutdown_i() +{ + // assume mutex is locked + for (size_t nDetector = 0; nDetector < this->detectors_.size(); ++nDetector) + { + Fault_Detector_i * detector = this->detectors_[nDetector]; + if (detector != 0) + { + detector->request_quit(); + } + } +} + +int TAO::FT_FaultDetectorFactory_i::write_ior() +{ + int result = -1; + FILE* out = ACE_OS::fopen (this->ior_output_file_, "w"); + if (out) + { + ACE_OS::fprintf (out, "%s", this->ior_.in ()); + ACE_OS::fclose (out); + result = 0; + } + else + { + ACE_ERROR ((LM_ERROR, + "Open failed for %s\n", ior_output_file_ + )); + } + return result; +} + +////////////////////////////////////////////////////// +// FT_FaultDetectorFactory_i public, non-CORBA methods + +int TAO::FT_FaultDetectorFactory_i::parse_args (int argc, ACE_TCHAR * argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("d:l:o:qr")); + int c; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'd': + { + this->domain_ = CORBA::string_dup (ACE_TEXT_ALWAYS_CHAR(get_opts.opt_arg ())); + break; + } + case 'l': + { + this->location_.length(1); + this->location_[0].id = CORBA::string_dup(ACE_TEXT_ALWAYS_CHAR(get_opts.opt_arg ())); + break; + } + case 'o': + { + this->ior_output_file_ = get_opts.opt_arg (); + break; + } + case 'r': + { + this->rm_register_ = ! this->rm_register_; + break; + } + case 'q': + { + this->quit_on_idle_ = 1; + break; + } + + case '?': + // fall thru + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s" + " -d <FT Domain>" + " -l <FT Location>" + " -o <iorfile>" + " -r <disable registering with replication manager>" + " -q{uit on idle}" + "\n", + argv [0]), + -1); + break; + } + } + // Indicates sucessful parsing of the command line + return 0; +} + +const char * TAO::FT_FaultDetectorFactory_i::identity () const +{ + return this->identity_.c_str(); +} + +int TAO::FT_FaultDetectorFactory_i::idle (int & result) +{ + ACE_UNUSED_ARG (result); + int quit = this->quit_requested_; + if (quit == 0 && this->detectors_.size() == this->empty_slots_) + { + // don't quitOnIdle until something has happened + if (this->quit_on_idle_ && this->empty_slots_ != 0) + { + ACE_ERROR (( LM_INFO, + "FaultDetectorFactory exits due to quit on idle option.\n" + )); + quit = 1; + } + } + + return quit; +} + + +int TAO::FT_FaultDetectorFactory_i::init (CORBA::ORB_ptr orb) +{ + int result = 0; + this->orb_ = CORBA::ORB::_duplicate (orb); + + // Use the ROOT POA for now + CORBA::Object_var poa_object = + this->orb_->resolve_initial_references (TAO_OBJID_ROOTPOA); + + if (CORBA::is_nil (poa_object.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT (" (%P|%t) Unable to initialize the POA.\n")), + -1); + + // Get the POA object. + this->poa_ = + PortableServer::POA::_narrow (poa_object.in ()); + + + if (CORBA::is_nil(this->poa_.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT (" (%P|%t) Unable to narrow the POA.\n")), + -1); + } + + PortableServer::POAManager_var poa_manager = + this->poa_->the_POAManager (); + + poa_manager->activate (); + + // Register with the POA. + + this->objectId_ = this->poa_->activate_object (this); + + // find my IOR + + CORBA::Object_var this_obj = + this->poa_->id_to_reference (objectId_.in ()); + + this->ior_ = this->orb_->object_to_string (this_obj.in ()); + + this->identity_ = "FaultDetectorFactory"; + + /////////////////////////////// + // Register with ReplicationManager + if (this->rm_register_) + { + try + { + CORBA::Object_var rm_obj = orb->resolve_initial_references("ReplicationManager"); + this->replication_manager_ = ::FT::ReplicationManager::_narrow(rm_obj.in()); + if (!CORBA::is_nil (replication_manager_.in ())) + { + // capture the default notifier + this->notifier_ = this->replication_manager_->get_fault_notifier (); + + // register with ReplicationManager::RegistrationFactory + PortableGroup::Criteria criteria(0); + this->factory_registry_ = this->replication_manager_->get_factory_registry (criteria); + + if (! CORBA::is_nil(factory_registry_.in ())) + { + PortableGroup::FactoryInfo info; + info.the_factory = ::PortableGroup::GenericFactory::_narrow(this_obj.in ()); + info.the_location = this->location_; + info.the_criteria.length(1); + info.the_criteria[0].nam.length(1); + info.the_criteria[0].nam[0].id = CORBA::string_dup(PortableGroup::role_criterion); + info.the_criteria[0].val <<= CORBA::string_dup(FT::FAULT_DETECTOR_ROLE_NAME); + + ACE_DEBUG ((LM_DEBUG, + "FaultDetector registering with ReplicationManager.\n" + )); + this->factory_registry_->register_factory( + FT::FAULT_DETECTOR_ROLE_NAME, + FT::FAULT_DETECTOR_ROLE_NAME, + info); + + ACE_DEBUG ((LM_DEBUG, + "FaultDetector Registration complete.\n" + )); + this->registered_ = 1; + } + else + { + ACE_ERROR ((LM_ERROR,"FaultNotifier: ReplicationManager doesn't have RegistrationFactory.\n" )); + } + } + else + { + ACE_ERROR ((LM_ERROR,"FaultNotifier: Can't resolve ReplicationManager, It will not be registered.\n" )); + } + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ( + "ReplicaFactory: Exception resolving ReplicationManager. Factory will not be registered.\n"); + } + } + else + { + ACE_DEBUG ((LM_DEBUG, + "FaultNotifier: ReplicationManager registration disabled.\n" + )); + } + + if (this->ior_output_file_ != 0) + { + this->identity_ = "file:"; + this->identity_ += ACE_TEXT_ALWAYS_CHAR(this->ior_output_file_); + write_ior(); + } + + if (this->ns_name_ != 0) + { + this->identity_ = "name:"; + this->identity_ += this->ns_name_; + + CORBA::Object_var naming_obj = + this->orb_->resolve_initial_references ("NameService"); + + if (CORBA::is_nil(naming_obj.in ())){ + ACE_ERROR_RETURN ((LM_ERROR, + "%T %n (%P|%t) Unable to find the Naming Service\n"), + 1); + } + + this->naming_context_ = + ::CosNaming::NamingContext::_narrow (naming_obj.in ()); + + this->this_name_.length (1); + this->this_name_[0].id = CORBA::string_dup (this->ns_name_); + + this->naming_context_->rebind (this->this_name_, this_obj.in() //CORBA::Object::_duplicate(this_obj) + ); + } + + return result; +} + +int TAO::FT_FaultDetectorFactory_i::fini (void) +{ + if (this->ior_output_file_ != 0) + { + ACE_OS::unlink (this->ior_output_file_); + this->ior_output_file_ = 0; + } + if (this->ns_name_ != 0) + { + this->naming_context_->unbind (this_name_); + this->ns_name_ = 0; + } + + if (this->registered_) + { + this->factory_registry_->unregister_factory( + FT::FAULT_DETECTOR_ROLE_NAME, + this->location_); + this->registered_ = 0; + } + return 0; +} + + +CORBA::ULong TAO::FT_FaultDetectorFactory_i::allocate_id() +{ + CORBA::ULong id = this->detectors_.size(); + if (this->empty_slots_ != 0) + { + for(CORBA::ULong pos = 0; pos < id; ++pos) + { + if (this->detectors_[pos] == 0) + { + id = pos; + } + } + } + else + { + this->detectors_.push_back(0); + this->empty_slots_ += 1; + } + return id; +} + +void TAO::FT_FaultDetectorFactory_i::remove_detector(CORBA::ULong id, TAO::Fault_Detector_i * detector) +{ + InternalGuard guard (this->internals_); + if (id < this->detectors_.size()) + { + if(this->detectors_[id] == detector) + { + delete this->detectors_[id]; + this->detectors_[id] = 0; + this->empty_slots_ += 1; + if (this->empty_slots_ == this->detectors_.size()) + { + ACE_ERROR (( LM_INFO, + "FaultDetectorFactory is idle.\n" + )); + } + } + else + { + ACE_ERROR (( LM_ERROR, + "Remove detector %d mismatch.\n", + static_cast<int> (id) + )); + } + } + else + { + ACE_ERROR (( LM_ERROR, + "Attempt to remove invalid detector %d. Limit %d.\n", + static_cast<int> (id), + static_cast<int> (this->detectors_.size()) + )); + } +} + +////////////////////////////////////////// +// FT_FaultDetectorFactory_i CORBA methods + +void TAO::FT_FaultDetectorFactory_i::change_properties ( + const PortableGroup::Properties & property_set + ) +{ + METHOD_ENTRY(TAO::FT_FaultDetectorFactory_i::change_properties); + + // TimeT is expressed in 10E-7 seconds (== 100 nSec == 0.1 uSec) + static const long timeT_per_uSec = 10L; + static const long uSec_per_sec = 1000000L; + + ::TAO::PG_Property_Set decoder(property_set); + + TimeBase::TimeT value = 0; + if( TAO::find (decoder, FT::FT_FAULT_MONITORING_INTERVAL, value) ) + { + // note: these should be unsigned long, but + // ACE_Time_Value wants longs. + long uSec = static_cast<long> ((value / timeT_per_uSec) % uSec_per_sec); + long sec = static_cast<long> ((value / timeT_per_uSec) / uSec_per_sec); + ACE_Time_Value atv(sec, uSec); + TAO::Fault_Detector_i::set_time_for_all_detectors(atv); + } + else + { + ACE_ERROR ((LM_ERROR, + "Throwing Invalid Property: %s\n", + FT::FT_FAULT_MONITORING_INTERVAL + )); + ::PortableGroup::InvalidProperty ex; + ex.nam.length(1); + ex.nam[0].id = CORBA::string_dup(FT::FT_FAULT_MONITORING_INTERVAL); + throw ::PortableGroup::InvalidProperty (ex); + } + METHOD_RETURN(TAO::FT_FaultDetectorFactory_i::change_properties); +} + +void TAO::FT_FaultDetectorFactory_i::shutdown (void) +{ + METHOD_ENTRY(TAO::FT_FaultDetectorFactory_i::shutdown); + InternalGuard guard (this->internals_); + shutdown_i (); + this->quit_requested_ = 1; + METHOD_RETURN(TAO::FT_FaultDetectorFactory_i::shutdown); +} + +CORBA::Object_ptr TAO::FT_FaultDetectorFactory_i::create_object ( + const char * type_id, + const PortableGroup::Criteria & the_criteria, + PortableGroup::GenericFactory::FactoryCreationId_out factory_creation_id + ) +{ + METHOD_ENTRY(TAO::FT_FaultDetectorFactory_i::create_object); + + ACE_UNUSED_ARG (type_id); //@@ use it + InternalGuard guard (this->internals_); + + ::TAO::PG_Property_Set decoder (the_criteria); + + // boolean, becomes true if a required parameter is missing + int missingParameter = 0; + const char * missingParameterName = 0; + + FT::FaultNotifier_ptr notifier; + if (! ::TAO::find (decoder, ::FT::FT_NOTIFIER, notifier) ) + { + if (! CORBA::is_nil (this->notifier_.in ())) + { + notifier = FT::FaultNotifier::_duplicate (this->notifier_.in ()); + } + else + { + ACE_ERROR ((LM_ERROR, + "FaultDetectorFactory::create_object: Missing parameter %s\n", + ::FT::FT_NOTIFIER + )); + missingParameter = 1; + missingParameterName = ::FT::FT_NOTIFIER; + } + } + + FT::PullMonitorable_ptr monitorable; + if (! ::TAO::find (decoder, ::FT::FT_MONITORABLE, monitorable) ) + { + ACE_ERROR ((LM_ERROR, + "FaultDetectorFactory::create_object: Missing parameter %s\n", + ::FT::FT_MONITORABLE + )); + missingParameter = 1; + missingParameterName = ::FT::FT_MONITORABLE; + } + + FT::FTDomainId domain_id = 0; + // note the cast in the next line makes ANY >>= work. + const char * domain_id_string = 0; + if (::TAO::find (decoder, ::FT::FT_DOMAIN_ID, domain_id_string) ) + { + // NOTE the assumption that we can assign a char * to a domain id + domain_id = const_cast<char *> (domain_id_string); + } + else + { + domain_id = this->domain_; + +// ACE_ERROR ((LM_ERROR, +// "FaultDetectorFactory::create_object: Missing parameter %s\n", +// ::FT::FT_DOMAIN_ID +// )); +// missingParameter = 1; +// missingParameterName = ::FT::FT_DOMAIN_ID; + } + + PortableGroup::Location * object_location = 0; + if (! ::TAO::find (decoder, ::FT::FT_LOCATION, object_location) ) + { + object_location = & this->location_; + +// ACE_ERROR ((LM_ERROR, +// "FaultDetectorFactory::create_object: Missing parameter %s\n", +// ::FT::FT_LOCATION +// )); +// missingParameter = 1; +// missingParameterName = ::FT::FT_LOCATION; + } + + PortableGroup::TypeId object_type = 0; + const char * object_type_string; + if (::TAO::find (decoder, ::FT::FT_TYPE_ID, object_type_string)) + { + object_type = const_cast<char *> (object_type_string); + } + else + { + object_type = const_cast<char *> ("unknown"); + // Not required: missingParameter = 1; + ACE_DEBUG ((LM_DEBUG, "Object type not given.\n")); + } + + FT::ObjectGroupId group_id = 0; + if (! ::TAO::find (decoder, ::FT::FT_GROUP_ID, group_id) ) + { + // Not required: missingParameter = 1; + } + + if (missingParameter) + { + ACE_ERROR ((LM_ERROR, + "Throwing 'InvalidCriteria' due to missing %s\n", + missingParameterName + )); + throw PortableGroup::InvalidCriteria(); + } + + CORBA::ULong detectorId = allocate_id(); + + // NOTE: ACE_NEW is incompatable with auto_ptr + // so create a bare pointer first. + TAO::Fault_Detector_i * pFD = 0; + + ACE_NEW_NORETURN(pFD, TAO::Fault_Detector_i( + *this, + detectorId, + notifier, + monitorable, + domain_id, + *object_location, + object_type, + group_id)); + if (pFD == 0) + { + ACE_ERROR ((LM_ERROR, + "New FaultDetector_i returned NULL. Throwing ObjectNotCreated.\n" + )); + throw PortableGroup::ObjectNotCreated(); + } + auto_ptr<TAO::Fault_Detector_i> detector(pFD); + + ACE_NEW_NORETURN ( factory_creation_id, + PortableGroup::GenericFactory::FactoryCreationId); + if (factory_creation_id.ptr() == 0) + { + ACE_ERROR ((LM_ERROR, + "New factory_creation_id returned NULL. Throwing ObjectNotCreated.\n" + )); + + throw PortableGroup::ObjectNotCreated(); + } + (*factory_creation_id) <<= detectorId; + + (*detector).start(this->threadManager_); + + this->detectors_[detectorId] = detector.release(); + this->empty_slots_ -= 1; + + // since FaultDetector is not a CORBA object (it does not implement + // an interface.) we always return NIL; + METHOD_RETURN(TAO::FT_FaultDetectorFactory_i::create_object) + CORBA::Object::_nil(); +} + +void TAO::FT_FaultDetectorFactory_i::delete_object ( + const PortableGroup::GenericFactory::FactoryCreationId & factory_creation_id + ) +{ + METHOD_ENTRY(TAO::FT_FaultDetectorFactory_i::delete_object); + + InternalGuard guard (this->internals_); + + CORBA::ULong detectorId; + factory_creation_id >>= detectorId; + if (detectorId < this->detectors_.size()) + { + if(this->detectors_[detectorId] != 0) + { + this->detectors_[detectorId]->request_quit(); + } + else + { + throw ::PortableGroup::ObjectNotFound(); + } + } + else + { + throw ::PortableGroup::ObjectNotFound(); + } + METHOD_RETURN(TAO::FT_FaultDetectorFactory_i::delete_object); +} + +CORBA::Boolean TAO::FT_FaultDetectorFactory_i::is_alive (void) +{ + METHOD_RETURN(TAO::FT_FaultDetectorFactory_i::is_alive) + 1; +} + +TAO_END_VERSIONED_NAMESPACE_DECL |