diff options
Diffstat (limited to 'TAO/orbsvcs/FT_ReplicationManager/FT_FaultConsumer.cpp')
-rw-r--r-- | TAO/orbsvcs/FT_ReplicationManager/FT_FaultConsumer.cpp | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/TAO/orbsvcs/FT_ReplicationManager/FT_FaultConsumer.cpp b/TAO/orbsvcs/FT_ReplicationManager/FT_FaultConsumer.cpp new file mode 100644 index 00000000000..b9aec6de436 --- /dev/null +++ b/TAO/orbsvcs/FT_ReplicationManager/FT_FaultConsumer.cpp @@ -0,0 +1,286 @@ +/* -*- C++ -*- */ +//============================================================================= +/** + * @file FT_FaultConsumer.cpp + * + * $Id$ + * + * This file is part of TAO's implementation of Fault Tolerant CORBA. + * This file provides the implementation of the TAO::FT_FaultConsumer + * class. The TAO::FT_FaultConsumer connects to the FaultNotifier to + * receive fault reports. It interacts with the ReplicationManager + * to process fault reports (e.g., to set a new primary on an object + * group or to create a new member of an object group). + * + * @author Steve Totten <totten_s@ociweb.com> + */ +//============================================================================= + +#include "FT_FaultConsumer.h" +#include "orbsvcs/FT_ReplicationManagerC.h" +#include "orbsvcs/FT_ReplicationManager/FT_FaultAnalyzer.h" +#include "tao/debug.h" + +ACE_RCSID (FT_FaultConsumer, + FT_FaultConsumer, + "$Id$") + + +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +/// Default constructor. +TAO::FT_FaultConsumer::FT_FaultConsumer () + : poa_ (PortableServer::POA::_nil ()) + , fault_notifier_ (FT::FaultNotifier::_nil ()) + , fault_analyzer_ (0) + , consumer_id_ (0) + , consumer_ref_ (CosNotifyComm::StructuredPushConsumer::_nil ()) + , notifications_ (0) +{ +} + +/// Destructor. +TAO::FT_FaultConsumer::~FT_FaultConsumer () +{ +} + +/** +* Connect to the FT::FaultNotifier. +* Note: We make the following assumptions about what the +* application will do: +* - Create an instance of this consumer class. +* - Obtain the object reference of the FaultNotifier to which this +* consumer should connect. +* - Call this init() method, passing it the POA with which we +* have been activated, the FaultNotifier, and ReplicationManager +* object references. +*/ +int TAO::FT_FaultConsumer::init ( + PortableServer::POA_ptr poa, + FT::FaultNotifier_ptr fault_notifier, + TAO::FT_FaultAnalyzer * fault_analyzer) +{ + + if (TAO_debug_level > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ( + "Enter TAO::FT_FaultConsumer::init.\n") + )); + } + + ACE_ASSERT (!CORBA::is_nil (poa)); + ACE_ASSERT (!CORBA::is_nil (fault_notifier)); + ACE_ASSERT (fault_analyzer != 0); + + // Duplicate the object references passed in. + this->poa_ = + PortableServer::POA::_duplicate (poa); + this->fault_notifier_ = + FT::FaultNotifier::_duplicate (fault_notifier); + + // We have no ownership responsibilities for the Fault Analyzer. + this->fault_analyzer_ = fault_analyzer; + + //@@ Should this init() method activate the consumer in the POA, or + // should the application do that? + // I don't think this object can activate itself because it doesn't + // know the policies on the POA. So, we assume the application has + // already activated us. + //@@ For now, let's try just activating it in the POA. + + // Activate this consumer in the POA. + this->object_id_ = this->poa_->activate_object (this); + CORBA::Object_var obj = + this->poa_->id_to_reference (this->object_id_.in()); + + // Narrow it to CosNotifyComm::StructuredPushConsumer. + this->consumer_ref_ = CosNotifyComm::StructuredPushConsumer::_narrow ( + obj.in()); + + // Subscribe to the FaultNotifier. + CosNotifyFilter::Filter_var filter = CosNotifyFilter::Filter::_nil (); + this->consumer_id_ = fault_notifier_->connect_structured_fault_consumer ( + this->consumer_ref_.in(), filter.in ()); + + if (TAO_debug_level > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ( + "Leave TAO::FT_FaultConsumer::init.\n") + )); + } + + // Success. + return 0; +} + +/** +* Clean house for process shut down. +* - Disconnect from FT::FaultNotifier. +* - Deactivate from the POA. +*/ +int TAO::FT_FaultConsumer::fini (void) +{ + + if (TAO_debug_level > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Enter TAO::FT_FaultConsumer::fini.\n") + )); + } + + // Disconnect from the FaultNotifier. + // Swallow any exception. + try + { + if (!CORBA::is_nil (this->fault_notifier_.in())) + { + + if (TAO_debug_level > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ( + "TAO::FT_FaultConsumer::fini: " + "Disconnecting consumer from FaultNotifier.\n") + )); + } + + this->fault_notifier_->disconnect_consumer ( + this->consumer_id_); + + if (TAO_debug_level > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ( + "TAO::FT_FaultConsumer::fini: " + "Deactivating from POA.\n") + )); + } + + // Deactivate ourself from the POA. + this->poa_->deactivate_object ( + this->object_id_.in()); + } + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ( + ACE_TEXT ( + "TAO::FT_FaultConsumer::fini: ""Error disconnecting from notifier (ignored).\n")); + } + + if (TAO_debug_level > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ( + "TAO::FT_FaultConsumer::fini: " + "Setting our object reference to nil.\n") + )); + } + + this->consumer_ref_ = CosNotifyComm::StructuredPushConsumer::_nil (); + + if (TAO_debug_level > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Leave TAO::FT_FaultConsumer::fini.\n") + )); + } + + // Success. + return 0; +} + +CosNotifyComm::StructuredPushConsumer_ptr +TAO::FT_FaultConsumer::consumer_ref () +{ + return CosNotifyComm::StructuredPushConsumer::_duplicate ( + this->consumer_ref_.in ()); +} + +size_t TAO::FT_FaultConsumer::notifications () const +{ + return this->notifications_; +} + + +/////////////////// +// CORBA operations + +// Receive and process an incoming fault event from the Fault Notifier. +// First, we validate the event to make sure it is something we can +// handle. Then, we analyze it. If it is not an event we can handle, +// we simply log the error and drop the event. +void TAO::FT_FaultConsumer::push_structured_event ( + const CosNotification::StructuredEvent &event + ) +{ + // Debugging support. + this->notifications_ += 1; + if (TAO_debug_level > 1) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ( + "TAO::FT_FaultConsumer::push_structured_event: " + "Received Fault notification(%d):\n"), + static_cast<unsigned int> (this->notifications_) + )); + } + + int result = 0; + + // Make sure it is an event type we can handle. + if (result == 0) + { + result = this->fault_analyzer_->validate_event_type (event); + if (result != 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ( + "TAO::FT_FaultConsumer::push_structured_event: " + "Received invalid fault event type.\n") + )); + } + } + + // Analyze the event. + if (result == 0) + { + result = this->fault_analyzer_->analyze_fault_event (event); + if (result != 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ( + "TAO::FT_FaultConsumer::push_structured_event: " + "Could not analyze fault event.\n") + )); + } + } + + return; +} + +void TAO::FT_FaultConsumer::offer_change ( + const CosNotification::EventTypeSeq & added, + const CosNotification::EventTypeSeq & removed + ) +{ + ACE_UNUSED_ARG (added); + ACE_UNUSED_ARG (removed); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("TAO::FT_FaultConsumer::offer_change() call ignored.\n") + )); +} + +void TAO::FT_FaultConsumer::disconnect_structured_push_consumer ( + ) +{ + //TODO: For now, we are just ignoring the disconnect callback. + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT("TAO::FT_FaultConsumer::disconnect_structured_push_consumer() " + "call ignored.\n") + )); +} + +TAO_END_VERSIONED_NAMESPACE_DECL |