#include "ace/Monitor_Base.h" #if defined (ACE_HAS_MONITOR_FRAMEWORK) && (ACE_HAS_MONITOR_FRAMEWORK == 1) #include "ace/ACE.h" #include "ace/Monitor_Admin_Manager.h" #include "ace/Monitor_Control_Action.h" #include "ace/Monitor_Point_Registry.h" #include "ace/Guard_T.h" #include "ace/Dynamic_Service.h" #include "ace/OS_NS_sys_time.h" #if !defined (__ACE_INLINE__) #include "ace/Monitor_Base.inl" #endif /* __ACE_INLINE__ */ ACE_BEGIN_VERSIONED_NAMESPACE_DECL namespace ACE { namespace Monitor_Control { Monitor_Base::Monitor_Base (const char* name, Monitor_Control_Types::Information_Type type) : ACE_Refcountable_T (1) , data_ (type) , name_ (name) { } Monitor_Base::~Monitor_Base () { ACE_GUARD (ACE_SYNCH_MUTEX, guard, this->mutex_); if (this->data_.type_ == Monitor_Control_Types::MC_LIST) { for (size_t i = 0UL; i < this->data_.index_; ++i) { #if defined (ACE_HAS_ALLOC_HOOKS) ACE_Allocator::instance()->free(this->data_.list_[i]); #else delete [] this->data_.list_[i]; #endif /* ACE_HAS_ALLOC_HOOKS */ } } } void Monitor_Base::update () { /// Overridden in derived classes. } void Monitor_Base::receive (double data) { if (this->data_.type_ == Monitor_Control_Types::MC_LIST) { ACELIB_ERROR ((LM_ERROR, ACE_TEXT ("receive: can't store numeric value - ") ACE_TEXT ("%s is a string type monitor\n"), this->name_.c_str ())); return; } ACE_GUARD (ACE_SYNCH_MUTEX, guard, this->mutex_); this->data_.timestamp_ = ACE_OS::gettimeofday (); this->data_.value_ = data; if (this->data_.type_ != Monitor_Control_Types::MC_COUNTER) { this->data_.sum_ += data; this->data_.sum_of_squares_ += (data * data); ++this->data_.index_; } if (this->data_.type_ == Monitor_Control_Types::MC_COUNTER) { ++this->data_.last_; this->data_.maximum_ = this->data_.last_; } else { this->data_.last_ = data; if (!this->data_.minimum_set_) { this->data_.minimum_set_ = true; this->data_.minimum_ = data; } else if (this->data_.minimum_ > data) { this->data_.minimum_ = data; } if (this->data_.maximum_ < data) { this->data_.maximum_ = data; } } } void Monitor_Base::receive (size_t data) { this->receive (static_cast (data)); } void Monitor_Base::receive (const Monitor_Control_Types::NameList& data) { if (this->data_.type_ != Monitor_Control_Types::MC_LIST) { ACELIB_ERROR ((LM_ERROR, ACE_TEXT ("receive: can't store string values - ") ACE_TEXT ("%s is a numeric type monitor\n"), this->name_.c_str ())); return; } ACE_GUARD (ACE_SYNCH_MUTEX, guard, this->mutex_); for (size_t i = 0UL; i < this->data_.index_; ++i) { ACE::strdelete (this->data_.list_[i]); } this->data_.index_ = data.size (); this->data_.list_.max_size (this->data_.index_); for (size_t i = 0UL; i < this->data_.index_; ++i) { this->data_.list_[i] = ACE::strnew (data[i].c_str ()); } } long Monitor_Base::add_constraint (const char* expression, Control_Action* action) { /// Thread-safe and guaranteed to be unique. long id = Monitor_Point_Registry::instance ()->constraint_id (); CONSTRAINTS::value_type entry; entry.first = id; entry.second.expr = expression; entry.second.control_action = action; /// This is thread-safe on its own so we don't have /// to guard it here. action->add_ref (); { ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->mutex_, -1); /// Since we know external key is unique, /// we don't check for failure. (void) this->constraints_.insert (entry); } return id; } Control_Action* Monitor_Base::remove_constraint (const long constraint_id) { Control_Action* retval = 0; { ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->mutex_, 0); CONSTRAINT_ITERATOR i = this->constraints_.find (constraint_id); if (i != this->constraints_.end ()) { retval = i->second.control_action; (void) this->constraints_.erase (constraint_id); } } return retval; } void Monitor_Base::retrieve (Monitor_Control_Types::Data& data) const { ACE_GUARD (ACE_SYNCH_MUTEX, guard, this->mutex_); data = this->data_; } void Monitor_Base::clear () { ACE_GUARD (ACE_SYNCH_MUTEX, guard, this->mutex_); this->clear_i (); } void Monitor_Base::retrieve_and_clear (Monitor_Control_Types::Data& data) { ACE_GUARD (ACE_SYNCH_MUTEX, guard, this->mutex_); data = this->data_; this->clear_i (); } void Monitor_Base::add_to_registry (const ACE_Time_Value& time) { MC_ADMINMANAGER *mgr = ACE_Dynamic_Service::instance ("MC_ADMINMANAGER"); if (!mgr->admin ().monitor_point (this, time)) { ACELIB_ERROR ((LM_ERROR, "monitor point %s registration failed\n", this->name ())); } } void Monitor_Base::remove_from_registry () { if (!Monitor_Point_Registry::instance ()->remove (this->name ())) { // (JP) There is a problem with this failing on a single ACE_Message_Queue // monitor per process. I think it is the message queue associated // with the default reactor, maybe because at that low level, ACE // is using malloc with placement, then free, which may bypass the // normal destructors. In any case, it happens only at shutdown // and there seems to be no memory leak. // ACELIB_ERROR ((LM_ERROR, // "monitor point %s unregistration failed\n", // this->name ())); } } double Monitor_Base::average () const { if (this->data_.type_ == Monitor_Control_Types::MC_COUNTER || this->data_.type_ == Monitor_Control_Types::MC_GROUP || this->data_.type_ == Monitor_Control_Types::MC_LIST) { ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("average: %s is wrong monitor type\n"), this->name_.c_str ()), 0); } ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->mutex_, 0.0); return (this->data_.index_== 0UL ? 0.0 : this->data_.sum_ / this->data_.index_); } double Monitor_Base::sum_of_squares () const { if (this->data_.type_ == Monitor_Control_Types::MC_COUNTER || this->data_.type_ == Monitor_Control_Types::MC_GROUP || this->data_.type_ == Monitor_Control_Types::MC_LIST) { ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("sum_of_squares: %s ") ACE_TEXT ("is wrong monitor type\n"), this->name_.c_str ()), 0); } ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->mutex_, 0.0); return this->data_.sum_of_squares_; } size_t Monitor_Base::count () const { if (this->data_.type_ == Monitor_Control_Types::MC_GROUP) { ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("count: %s is a monitor group\n"), this->name_.c_str ()), 0UL); } ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->mutex_, 0UL); return (this->data_.type_ == Monitor_Control_Types::MC_COUNTER ? static_cast (this->data_.last_) : this->data_.index_); } double Monitor_Base::minimum_sample () const { if (this->data_.type_ == Monitor_Control_Types::MC_GROUP || this->data_.type_ == Monitor_Control_Types::MC_LIST) { ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("minimum_sample: %s ") ACE_TEXT ("is wrong monitor type\n"), this->name_.c_str ()), 0); } ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->mutex_, 0.0); return this->data_.minimum_; } double Monitor_Base::maximum_sample () const { if (this->data_.type_ == Monitor_Control_Types::MC_GROUP || this->data_.type_ == Monitor_Control_Types::MC_LIST) { ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("maximum_sample: %s ") ACE_TEXT ("is wrong monitor type\n"), this->name_.c_str ()), 0); } ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->mutex_, 0.0); return this->data_.maximum_; } double Monitor_Base::last_sample () const { if (this->data_.type_ == Monitor_Control_Types::MC_GROUP || this->data_.type_ == Monitor_Control_Types::MC_LIST) { ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("last_sample: %s ") ACE_TEXT ("is wrong monitor type\n"), this->name_.c_str ()), 0); } ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->mutex_, 0.0); return this->data_.last_; } Monitor_Control_Types::NameList Monitor_Base::get_list () const { Monitor_Control_Types::NameList retval; if (this->data_.type_ != Monitor_Control_Types::MC_LIST) { ACELIB_ERROR ((LM_ERROR, ACE_TEXT ("get_list: %s is not a ") ACE_TEXT ("list monitor type\n"), this->name_.c_str ())); return retval; } ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, this->mutex_, retval); for (size_t i = 0UL; i < this->data_.index_; ++i) { retval.push_back (this->data_.list_[i]); } return retval; } void Monitor_Base::clear_i () { if (this->data_.type_ == Monitor_Control_Types::MC_LIST) { for (size_t i = 0UL; i < this->data_.index_; ++i) { ACE::strdelete (this->data_.list_[i]); } this->data_.list_.max_size (0UL); } this->data_.value_ = 0.0; this->data_.timestamp_ = ACE_Time_Value::zero; this->data_.index_ = 0UL; this->data_.minimum_set_ = false; this->data_.minimum_ = 0.0; this->data_.maximum_ = 0.0; this->data_.sum_ = 0.0; this->data_.sum_of_squares_ = 0.0; this->data_.last_ = 0.0; } } } ACE_END_VERSIONED_NAMESPACE_DECL #endif /* ACE_HAS_MONITOR_FRAMEWORK==1 */