From 65bf27f326a3b16fe8c513f304f4c50563ea2516 Mon Sep 17 00:00:00 2001 From: storri Date: Mon, 24 Mar 2003 15:18:06 +0000 Subject: Adding Metrics to TAO orbsvcs --- TAO/orbsvcs/orbsvcs/Makefile | 7 +- TAO/orbsvcs/orbsvcs/Makefile.Metrics | 111 ++ TAO/orbsvcs/orbsvcs/Metrics.idl | 331 +++++ .../orbsvcs/Metrics/Metrics_FrameManager.cpp | 14 + TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.h | 34 + TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.i | 9 + .../orbsvcs/Metrics/Metrics_FrameManager_T.cpp | 14 + .../orbsvcs/Metrics/Metrics_FrameManager_T.h | 276 ++++ .../orbsvcs/Metrics/Metrics_FrameManager_T.i | 821 +++++++++++ TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.cpp | 29 + TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.h | 51 + TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.i | 10 + .../orbsvcs/Metrics/Metrics_LocalCache_T.cpp | 490 ++++++ TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.h | 329 +++++ TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.i | 1556 ++++++++++++++++++++ TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.cpp | 892 +++++++++++ TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.h | 217 +++ .../orbsvcs/Metrics/Metrics_UpcallMonitor.cpp | 20 + .../orbsvcs/Metrics/Metrics_UpcallMonitor.h | 262 ++++ .../orbsvcs/Metrics/Metrics_UpcallMonitor.i | 371 +++++ .../orbsvcs/Metrics/Metrics_UpcallMonitor_T.cpp | 25 + .../orbsvcs/Metrics/Metrics_UpcallMonitor_T.h | 157 ++ .../orbsvcs/Metrics/Metrics_UpcallMonitor_T.i | 256 ++++ TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.cpp | 526 +++++++ TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.h | 126 ++ TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.i | 33 + TAO/orbsvcs/orbsvcs/Metrics/metrics_export.h | 50 + 27 files changed, 7016 insertions(+), 1 deletion(-) create mode 100644 TAO/orbsvcs/orbsvcs/Makefile.Metrics create mode 100644 TAO/orbsvcs/orbsvcs/Metrics.idl create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.cpp create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.h create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.i create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.cpp create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.h create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.i create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.cpp create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.h create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.i create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.cpp create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.h create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.i create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.cpp create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.h create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.cpp create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.h create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.i create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.cpp create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.h create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.i create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.cpp create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.h create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.i create mode 100644 TAO/orbsvcs/orbsvcs/Metrics/metrics_export.h diff --git a/TAO/orbsvcs/orbsvcs/Makefile b/TAO/orbsvcs/orbsvcs/Makefile index 5593637121d..c3e48c86d57 100644 --- a/TAO/orbsvcs/orbsvcs/Makefile +++ b/TAO/orbsvcs/orbsvcs/Makefile @@ -94,6 +94,9 @@ ifndef TAO_ORBSVCS TAO_ORBSVCS += Notify + ifeq ($(metrics),1) + TAO_ORBSVCS += Metrics + endif # metrics endif # TAO_ORBSVCS # The order in this list is important as some libraries depend on @@ -227,7 +230,9 @@ endif ifneq (,$(findstring IFRService, $(TAO_ORBSVCS))) MKLIST += Makefile.IFRService endif - +ifneq (,$(findstring Metrics, $(TAO_ORBSVCS))) + MKLIST += Makefile.Metrics +endif #---------------------------------------------------------------------------- # Local rules #---------------------------------------------------------------------------- diff --git a/TAO/orbsvcs/orbsvcs/Makefile.Metrics b/TAO/orbsvcs/orbsvcs/Makefile.Metrics new file mode 100644 index 00000000000..2ad9259af7a --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Makefile.Metrics @@ -0,0 +1,111 @@ +#---------------------------------------------------------------------------- +# GNU Makefile +#---------------------------------------------------------------------------- +MAKEFILE = Makefile.Metrics +DEPENDENCY_FILE = .depend.Makefile.Metrics +LIB_UNCHECKED = libTAO_Metrics.a +SHLIB_UNCHECKED = libTAO_Metrics.$(SOEXT) + +ifndef TAO_ROOT + TAO_ROOT = $(ACE_ROOT)/TAO +endif + +IDL_FILES = Metrics +IDL_SRC = $(foreach ext, C.cpp S.cpp, $(foreach file, $(IDL_FILES), $(file)$(ext))) + + + +Metrics = \ + MetricsC \ + MetricsS \ + Metrics/Metrics_FrameManager \ + Metrics/Metrics_LocalCache \ + Metrics/Metrics_Logger \ + Metrics/Metrics_UpcallMonitor \ + Metrics/Metrics_Utils + +ifndef ORBSVCS_COMPONENTS + ORBSVCS_COMPONENTS = \ + Metrics +endif # ORBSVCS_COMPONENTS + +ifneq (,$(findstring Metrics, $(ORBSVCS_COMPONENTS))) + FILES += $(Metrics) +endif # Metrics + +VPATH = .:Metrics + +ifeq (,$(TAO_ORBSVCS)) +LIB = $(LIB_UNCHECKED) +SHLIB = $(SHLIB_UNCHECKED) +else + ifeq (Metrics, $(findstring Metrics, $(TAO_ORBSVCS))) + LIB = $(LIB_UNCHECKED) + SHLIB = $(SHLIB_UNCHECKED) + endif +endif + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(TAO_ROOT)/rules.tao.GNU +LSRC = $(addsuffix .cpp, $(FILES)) +ifeq (,$(TAO_ORBSVCS)) +BUILD += ORBSVCS_COMPONENTS +else + ifeq (Metrics, $(findstring Metrics, $(TAO_ORBSVCS))) + BUILD += ORBSVCS_COMPONENTS + endif +endif +ACELIB = -lACE + +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU +include $(TAO_ROOT)/taoconfig.mk + +CPPFLAGS += -I../../orbsvcs -I../.. -I../../tao -I../../.. +ifeq ($(shared_libs),1) +ifneq ($(SHLIB),) +CPPFLAGS += -DTAO_METRICS_BUILD_DLL +endif +endif +ifeq ($(static_libs),1) +ifneq ($(LIB),) +CPPFLAGS += -DTAO_AS_STATIC_LIBS -DACE_AS_STATIC_LIBS +endif +endif + + +LDFLAGS += -L../../orbsvcs/orbsvcs -L../../tao -L../../../ace +TAO_IDLFLAGS += -Wb,pre_include=ace/pre.h -Wb,post_include=ace/post.h -Wb,export_macro=TAO_Metrics_Export -Wb,export_include=Metrics/metrics_export.h -I../.. -I$(TAO_ROOT)/orbsvcs -Ge 1 -Sc + +ACE_SHLIBS = -lTAO_PortableServer -lTAO $(ACELIB) + +#---------------------------------------------------------------------------- +# Local targets +#---------------------------------------------------------------------------- + +.PHONY: ORBSVCS_COMPONENTS +ORBSVCS_COMPONENTS: + @sh ../../../bin/ace_components --orbsvcs --append '$(ORBSVCS_COMPONENTS)' + +compclean: + @sh $(ACE_ROOT)/bin/ace_components --orbsvcs --remove + +ADDITIONAL_IDL_TARGETS = + +# IDL File Directory: . + +idl_stubs: $(ADDITIONAL_IDL_TARGETS) + +all: idl_stubs + +.PRECIOUS: $(foreach ext, $(IDL_EXT), $(foreach file, $(IDL_FILES), $(file)$(ext))) + +realclean: clean compclean + -$(RM) $(foreach ext, $(IDL_EXT), $(foreach file, $(IDL_FILES), $(file)$(ext))) + diff --git a/TAO/orbsvcs/orbsvcs/Metrics.idl b/TAO/orbsvcs/orbsvcs/Metrics.idl new file mode 100644 index 00000000000..00e87c7f87a --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics.idl @@ -0,0 +1,331 @@ +// $Id$ + +#ifndef METRICS_IDL +#define METRICS_IDL + +#include "TimeBase.idl" +#include "RtecScheduler.idl" +#pragma prefix "" + +module Metrics +{ + // Types + + enum TIMEPROBE_EVENT_TYPE + { + WORK_START, + WORK_STOP, + WORK_SUSPEND, + WORK_RESUME + }; + + typedef TIMEPROBE_EVENT_TYPE TIMEPROBE_EVENT_TYPE_t; + + typedef TimeBase::TimeT Time; // time type + typedef sequence Handle_Set_t; // handle sequence + + struct QoSParameter_t + // = TITLE + // Describes the monitored QoS for an "RT_Operation". + // + // = DESCRIPTION + // The deadline success and failure counts for an operation. + { + RtecScheduler::handle_t handle; + // The handle of the operation for which the information is stored + + string entry_point; + // The name of the operation for which the information is stored + + unsigned long deadlines_made; + // The number of deadlines successfully met. + + unsigned long deadlines_missed; + // The number of deadlines missed. + + unsigned long operations_cancelled; + // The number of operations cancelled. + + short is_hrt; + // Indicates whether or not the operation is hard real-time. + }; + + typedef sequence QoSParameter_Set; + + + struct QoSData + // = TITLE + // Describes the monitored QoS for the visualization browser. + // + // = DESCRIPTION + // Aggregate success, failure, and cancellation counts the operations. + { + long hrt_deadlines_made; + // The number of hard real-time deadlines successfully met. + + long hrt_deadlines_missed; + // The number of hard real-time deadlines missed. + + long hrt_operations_cancelled; + // The number of hard real-time operations that were cancelled. + + long srt_deadlines_made; + // The number of soft real-time deadlines successfully met. + + long srt_deadlines_missed; + // The number of soft real-time deadlines missed. + + long srt_operations_cancelled; + // The number of soft real-time operations that were cancelled. + }; + + struct UtilData + // = TITLE + // Describes the monitored QoS for the visualization browser. + // + // = DESCRIPTION + // Aggregate success, failure, and cancellation counts the operations. + { + double hrt_op_utilization; + // The percentage of the time spent in hard real-time operations. + + double srt_op_utilization; + // The percentage of the time spent in soft real-time operations. + + double queue_utilization; + // The percentage of the time spent managing queues. + }; + + struct ProbeIdentity_t + // = TITLE + // Describes the identity of a timeprobe. + // + // = DESCRIPTION + // The name and identifier for a timeprobe. + { + unsigned long probe_id; + // The unique identifier for the timeprobe. + + string probe_name; + // The name of the timeprobe. + }; + + typedef sequence ProbeIdentity_Set; + + struct TimeprobeParameter_t + // = TITLE + // Describes the monitored data for a timeprobe. + // + // = DESCRIPTION + // The duration of an interval for a timeprobe. + { + unsigned long probe_id; + // The name of the timeprobe that collected the data. + + short is_operation; + // Indicates whether or not the data are for an operation. + + short is_hrt; + // Indicates whether or not an operation is hard real-time. + + short is_full_interval; + // Indicates whether or not the time reported is for the entire + // interval measured by the time probe. + + short cross_thread_probe; + // Indicates whether or not the time reported is for the entire + // interval measured by the time probe. + + Time start_event_time; + // The start of the event for sorting purposes. + + Time stop_event_time; + // The start of the event for sorting purposes. + + Time interval; + // The elapsed time within the timeprobe. + }; + + typedef sequence TimeprobeParameter_Set; + + + // Exceptions + + exception SYNCHRONIZATION {}; + // A synchronization error occurred in a method. + + exception INTERNAL {}; + // An error occurred in an internal data structure. + + exception INTERNAL_0 {}; + exception INTERNAL_1 {}; + exception INTERNAL_2 {}; + exception INTERNAL_3 {}; + exception INTERNAL_4 {}; + exception INTERNAL_5 {}; + exception INTERNAL_6 {}; + exception INTERNAL_7 {}; + exception INTERNAL_8 {}; + // These are to track down an infrequently reproducible + // error, and should be removed eventually. + + exception NIL_LOGGER {}; + // An operation was passed a nil logger pointer. + + // Interfaces + + interface QoSLogger + // = TITLE + // This interface provides access to a QoS logger. + // + // = DESCRIPTION + // This interface allows clients log monitored QoS information. + { + oneway void send_banner (in string banner); + // Sends a banner to the logger, which is recorded in the + // output log and communicated to the visualization browser. + + oneway void log_aggregate_QoS (in Metrics::QoSParameter_Set qos_set, + in Time interval); + // Reports the aggregate QoS information for all operations + // to the passed QoS logger. + + oneway void set_identities (in Metrics::ProbeIdentity_Set identity_set); + // Binds the names of various timeprobes to their identifiers so + // that ids alone can be used (for efficiency) in passing data. + + oneway void set_identity (in Metrics::ProbeIdentity_t identity); + // Binds the names of various timeprobes to their identifiers so + // that ids alone can be used (for efficiency) in passing data. + + oneway void log_timeprobe_data (in Metrics::TimeprobeParameter_Set data_set, + in Time interval); + // Reports timeprobe data collected since last run. + }; + + + interface QoSMonitor + // = TITLE + // This interface provides access to a QoS data monitor. + // + // = DESCRIPTION + // This interface allows objects to store and query monitored + // QoS information. + { + void report_made_deadline (in RtecScheduler::handle_t handle) + raises (INTERNAL_0); + // Report a successful upcall. + + void report_missed_deadline (in RtecScheduler::handle_t handle) + raises (INTERNAL_1); + // Report an unsuccessful upcall. + + void reset_statistics (in RtecScheduler::handle_t handle) + raises (INTERNAL_7, INTERNAL_8); + // Resets the aggregate QoS information for the given + // operation handle. + + void get_aggregate_QoS (in RtecScheduler::handle_t handle, + out Metrics::QoSParameter_t qos) + raises (INTERNAL_2, INTERNAL_3); + // Retrieves the aggregate QoS information for the given + // operation handle. + + void get_aggregate_QoS_set (in Metrics::Handle_Set_t handle_set, + out Metrics::QoSParameter_Set qos_set) + raises (INTERNAL_4, INTERNAL_5); + // Retrieves the aggregate QoS information for all operations + // in the passed handle set. + }; + + + interface ReportingQoSMonitor : QoSMonitor + // = TITLE + // This interface provides access to a QoS data monitor. + // + // = DESCRIPTION + // This interface allows objects to report monitored + // QoS information to a QoS logger. + { + void report_aggregate_QoS (in Metrics::QoSLogger logger, + in Metrics::Time interval) + raises (NIL_LOGGER, INTERNAL_6); + // Reports the aggregate QoS information for all operations + // to the passed QoS logger. + }; + + interface FrameManager + // = TITLE + // This interface provides access to a QoS data monitor. + // + // = DESCRIPTION + // This interface allows objects to query or report monitored + // QoS information that was collected by QoS monitoring adapters. + { + short register_period (in RtecScheduler::Period_t p) + raises (INTERNAL, SYNCHRONIZATION); + // Binds the period to the internal frame map, with a new frame data + // structure. Returns 0 if a new entry is bound successfully, + // returns 1 if an attempt is made to bind an existing entry, and + // returns -1 if failures occur. + + short update_all_frames_with_time (in Time tv) + raises (SYNCHRONIZATION); + // Updates time frames, based on the passed time value. + + short update_all_frames () + raises (SYNCHRONIZATION); + // Updates time frames, based on the current time as of the call. + + short update_frame_with_time (in RtecScheduler::Period_t p, in Time tv) + raises (INTERNAL, SYNCHRONIZATION); + // Updates the passed period's time frame, based on the passed time + // value. + + short update_frame (in RtecScheduler::Period_t p) + raises (INTERNAL, SYNCHRONIZATION); + // Updates the passed period's time frame, based on the current time + // as of the call. + + short reset_all_frames_with_time (in Time tv) + raises (SYNCHRONIZATION); + // Resets time frames, based on the passed time value. + + short reset_all_frames () + raises (SYNCHRONIZATION); + // Resets time frames, based on the current time as of the call. + + short reset_frame_with_time (in RtecScheduler::Period_t p, in Time tv) + raises (INTERNAL, SYNCHRONIZATION); + // Resets the passed period's start-of-frame, based on the passed time + // value. + + short reset_frame (in RtecScheduler::Period_t p) + raises (INTERNAL, SYNCHRONIZATION); + // Resets the passed period's start-of-frame, based on the current time + // as of the call. + + short get_start_time (in RtecScheduler::Period_t p, out Time start) + raises (INTERNAL, SYNCHRONIZATION); + // Gets the start time for the period's current frame. + + short get_end_time (in RtecScheduler::Period_t p, out Time end) + raises (INTERNAL, SYNCHRONIZATION); + // Gets the end time for the period's current frame. + + short get_frame_id (in RtecScheduler::Period_t p, out unsigned long id) + raises (INTERNAL, SYNCHRONIZATION); + // Gets the locally unique identifier for the period's current frame. + + short get_frame_data (in RtecScheduler::Period_t p, out Time start, + out Time end, out unsigned long id) + raises (INTERNAL, SYNCHRONIZATION); + // Gets the start time, end time, and id for the period's current frame. + }; + +}; + +#endif /* METRICS_IDL */ + + + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.cpp b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.cpp new file mode 100644 index 00000000000..3a04aca99f0 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.cpp @@ -0,0 +1,14 @@ +// $Id$ + +#ifndef METRICS_FRAME_MANAGER_CPP +#define METRICS_FRAME_MANAGER_CPP + +#include "Metrics_FrameManager.h" + +#if !defined (__ACE_INLINE__) +#include "Metrics_FrameManager.i" +#endif /* __ACE_INLINE__ */ + + +#endif /* METRICS_FRAME_MANAGER_CPP */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.h b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.h new file mode 100644 index 00000000000..f1ad017f20d --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.h @@ -0,0 +1,34 @@ +// $Id$ + +#ifndef METRICS_FRAME_MANAGER_H +#define METRICS_FRAME_MANAGER_H + +#include "ace/OS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Hash_Map_Manager.h" +#include "ace/Singleton.h" + +#include "orbsvcs/Time_Utilities.h" +#include "orbsvcs/RtecSchedulerC.h" + +#include "Metrics_Utils.h" + +#if defined (__ACE_INLINE__) +#include "Metrics_FrameManager.i" +#endif /* __ACE_INLINE__ */ + +#include "Metrics_FrameManager_T.h" + +typedef TAO_Metrics_FrameManager +TAO_METRICS_FRAME_MGR_TYPE; + +typedef ACE_Singleton +TAO_METRICS_FRAME_MGR_SINGLETON; + + +#endif /* METRICS_FRAME_MANAGER_H */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.i b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.i new file mode 100644 index 00000000000..bb47ba99272 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.i @@ -0,0 +1,9 @@ +// $Id$ + +#ifndef METRICS_FRAME_MANAGER_I +#define METRICS_FRAME_MANAGER_I + + + +#endif /* METRICS_FRAME_MANAGER_I */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.cpp b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.cpp new file mode 100644 index 00000000000..64bf39f09f8 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.cpp @@ -0,0 +1,14 @@ +// $Id$ + +#ifndef METRICS_FRAME_MANAGER_T_CPP +#define METRICS_FRAME_MANAGER_T_CPP + +#include "Metrics_FrameManager_T.h" + +#if !defined (__ACE_INLINE__) +#include "Metrics_FrameManager_T.i" +#endif /* __ACE_INLINE__ */ + + +#endif /* METRICS_FRAME_MANAGER_T_CPP */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.h b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.h new file mode 100644 index 00000000000..b44a0c3299f --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.h @@ -0,0 +1,276 @@ +// $Id$ + +#ifndef METRICS_FRAME_MANAGER_T_H +#define METRICS_FRAME_MANAGER_T_H + +#include "ace/OS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Hash_Map_Manager.h" + +#include "orbsvcs/Time_Utilities.h" +#include "orbsvcs/RtecSchedulerC.h" +#include "orbsvcs/MetricsS.h" + +#include "orbsvcs/Metrics/Metrics_FrameManager.h" + + +template +struct TAO_Metrics_Frame_Manager_Data +{ + // = TITLE + // Defines a class for time frame management data. + // + // = DESCRIPTION + // This class makes use of the class to + // store period and endpoint data for a given time frame. + +public: + + TAO_Metrics_Frame_Manager_Data (RtecScheduler::Period_t p) + : frame_id_ (0), period_ (0, p / 10) {} + // Constructor. Note that p is in hundreds of nanoseconds so we + // divide by ten to get microseconds. The start_ and end_ data + // members are set equal to ACE_Time_Value::zero by their own + // default constructors. + + CORBA::ULong frame_id_; + // Stores the number of previous frames for that period. May roll + // over, but is intended to provide a locally (for a large range of + // locality) unique frame identifier. + + ACE_Time_Value period_; + // Relative time to the next frame, from the start of this one. + + ACE_Time_Value start_; + // Absolute time of the start of the frame and end of the last. + + ACE_Time_Value end_; + // Absolute time to the end of the frame and start of the next. + + ACE_LOCK lock_; + // Lock for synchronizing access to the data instance. +}; + + +template +class TAO_Metrics_FrameManager : public POA_Metrics::FrameManager + +{ + // = TITLE + // Defines a class that implements a local metrics cache. + // + // = DESCRIPTION + // This class makes use of the class to + // implement a cache for local use. +public: + + typedef TAO_Metrics_FrameManager TAO_METRICS_FRAME_MANAGER_TYPE; + typedef TAO_Metrics_Frame_Manager_Data TAO_METRICS_FRAME_MANAGER_DATA_TYPE; + + typedef ACE_Hash_Map_Manager_Ex, + ACE_Equal_To, + ACE_Null_Mutex> METRICS_FRAME_DATA_MAP; + // Type of map used for O(1) lookup of monitored data for operations. + + typedef ACE_Hash_Map_Entry + METRICS_FRAME_DATA_MAP_ENTRY; + // Type of entry in monitor map. + + typedef ACE_Hash_Map_Iterator_Ex, + ACE_Equal_To, + ACE_Null_Mutex> + METRICS_FRAME_DATA_MAP_ITERATOR; + // Type of iterator for monitor map. + + TAO_Metrics_FrameManager (); + // Constructor. + + ~TAO_Metrics_FrameManager (); + // Destructor. + + CORBA::Short register_period (RtecScheduler::Period_t p, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)); + // Binds the period to the internal frame map, with a new frame data + // structure. Returns 0 if a new entry is bound successfully, + // returns 1 if an attempt is made to bind an existing entry, and + // returns -1 if failures occur. + + CORBA::Short update_all_frames (const ACE_Time_Value& tv); + // Updates time frames, based on the passed time value. + + CORBA::Short update_all_frames_with_time (Metrics::Time mt, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::SYNCHRONIZATION)); + // Updates time frames, based on the passed time value. + + CORBA::Short update_all_frames (CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::SYNCHRONIZATION)); + // Updates time frames, based on the current time as of the call. + + CORBA::Short update_frame (RtecScheduler::Period_t p, const ACE_Time_Value& tv); + // Updates the passed period's time frame, based on the passed time + // value. + + CORBA::Short update_frame_with_time (RtecScheduler::Period_t p, + Metrics::Time mt, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)); + // Updates the passed period's time frame, based on the passed time + // value. + + CORBA::Short update_frame (RtecScheduler::Period_t p, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)); + // Updates the passed period's time frame, based on the current time + // as of the call. + + CORBA::Short reset_all_frames (const ACE_Time_Value& tv); + // Resets time frames, based on the passed time value. + + CORBA::Short reset_all_frames_with_time (Metrics::Time mt, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::SYNCHRONIZATION)); + // Resets time frames, based on the passed time value. + + CORBA::Short reset_all_frames (CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::SYNCHRONIZATION)); + // Resets time frames, based on the current time as of the call. + + CORBA::Short reset_frame (RtecScheduler::Period_t p, const ACE_Time_Value& tv); + // Resets the passed period's start-of-frame, based on the passed time + // value. + + CORBA::Short reset_frame_with_time (RtecScheduler::Period_t p, + Metrics::Time mt, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)); + // Resets the passed period's start-of-frame, based on the passed time + // value. + + CORBA::Short reset_frame (RtecScheduler::Period_t p, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)); + // Resets the passed period's start-of-frame, based on the current time + // as of the call. + + CORBA::Short get_start_time (RtecScheduler::Period_t p, ACE_Time_Value &start); + // Gets the start time for the period's current frame. + + CORBA::Short get_start_time (RtecScheduler::Period_t p, + Metrics::Time &start, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)); + // Gets the start time for the period's current frame. + + CORBA::Short get_end_time (RtecScheduler::Period_t p, ACE_Time_Value &end); + // Gets the end time for the period's current frame. + + CORBA::Short get_end_time (RtecScheduler::Period_t p, + Metrics::Time &end, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)); + // Gets the end time for the period's current frame. + + CORBA::Short get_frame_id (RtecScheduler::Period_t p, + CORBA::ULong &id, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)); + // Gets the locally unique identifier for the period's current frame. + + CORBA::Short get_frame_data (RtecScheduler::Period_t p, ACE_Time_Value &start, + ACE_Time_Value &end, CORBA::ULong &id); + // Gets the start time, end time, and id period's current frame. + + CORBA::Short get_frame_data (RtecScheduler::Period_t p, + Metrics::Time &start, + Metrics::Time &end, + CORBA::ULong &id, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)); + // Gets the start time, end time, and id period's current frame. + +protected: + + CORBA::Short update_data (TAO_Metrics_Frame_Manager_Data & data, + const ACE_Time_Value& tv); + // Updates the passed frame data structure's start and end times, + // based on the passed time value. This is a protected internal + // method, and should only be called with locks already held. + + + CORBA::Short reset_data (TAO_Metrics_Frame_Manager_Data & data, + const ACE_Time_Value& tv); + // Resets the passed frame data structure's start and end times, to + // the passed time value and one period later, respectively. This + // is a protected internal method, and should only be called with + // locks already held. + + METRICS_FRAME_DATA_MAP frame_data_map_; + // Maps periods to frame data. + + // Count of the number of registered periods. + u_long period_count_; + + ACE_LOCK lock_; + // Lock for synchronizing access to the map. +}; + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "Metrics_FrameManager_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Metrics_FrameManager_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#if defined (__ACE_INLINE__) +#include "Metrics_FrameManager_T.i" +#endif /* __ACE_INLINE__ */ + +#endif /* METRICS_FRAME_MANAGER_T_H */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.i b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.i new file mode 100644 index 00000000000..a14671b359e --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.i @@ -0,0 +1,821 @@ +// $Id$ + +#ifndef METRICS_FRAME_MANAGER_T_I +#define METRICS_FRAME_MANAGER_T_I + + +//////////////////////////////////// +// Class TAO_Metrics_FrameManager // +//////////////////////////////////// + + +// Default constructor. + +template +ACE_INLINE +TAO_Metrics_FrameManager:: +TAO_Metrics_FrameManager () + : period_count_ (0) +{ + // Ensure that the high res timer global scale factor + // is set before any of its static methods are used + ACE_High_Res_Timer::global_scale_factor (); +} + +// Destructor. Note: this is *not* thread safe. If we're destroying +// the frame manager then there had better not be any threads in the +// manager anyway. If a use case requires thread safety at +// destruction, then some kind of external reader-writer locking and +// barrier synchronization scheme will be needed to make this work +// efficiently. + +template +ACE_INLINE +TAO_Metrics_FrameManager:: +~TAO_Metrics_FrameManager () +{ + // Iterate through and delete the data structures in the map + METRICS_FRAME_DATA_MAP_ITERATOR iter (frame_data_map_); + while (iter.done () == 0) + { + delete (*iter).int_id_; + ++iter; + } +} + + +// Binds the period to the internal frame map, with a new frame data +// structure. Returns 0 if a new entry is bound successfully, returns +// 1 if an attempt is made to bind an existing entry, and returns -1 +// if failures occur. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +register_period (RtecScheduler::Period_t p, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)) +{ + // Treat a zero period as a special case: no need to register, but + // no harm if someone tries. + if (p == 0) + { + return 0; + } + + // Synchronize read/write access to the map while the new period's + // frame is being installed. + ACE_Write_Guard mon (this->lock_); + if (mon.locked () == 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + int result = 0; + TAO_Metrics_Frame_Manager_Data * data = 0; + if (frame_data_map_.find (p) != 0) + { + ACE_NEW_RETURN (data, TAO_Metrics_Frame_Manager_Data (p), -1); + result = frame_data_map_.trybind (p, data); + if (result == 0) + { + // All is well: count the new period. + ++period_count_; + } + else + { + delete data; + + // We failed to bind: throw an exception. + ACE_THROW_RETURN (Metrics::INTERNAL (), -1); + } + } + + return result; +} + +// Updates time frames, based on the passed time value. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +update_all_frames (const ACE_Time_Value& tv) +{ + // Synchronize read/write access to the map while the new frames are + // being computed. + ACE_Write_Guard mon (this->lock_); + if (mon.locked () == 0) + { + return -1; + } + + METRICS_FRAME_DATA_MAP_ITERATOR iter (frame_data_map_); + while (iter.done () == 0) + { + update_data (*((*iter).int_id_), tv); + ++iter; + } + return 0; +} + + +// Updates time frames, based on the passed time value. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +update_all_frames_with_time (Metrics::Time mt, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::SYNCHRONIZATION)) +{ + // Reentrant method that calls locked method. + ACE_Time_Value tv; + ORBSVCS_Time::TimeT_to_Time_Value(tv, mt); + if (this->update_all_frames (tv) < 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + return 0; +} + +// Updates time frames, based on the current time as of the call. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +update_all_frames (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::SYNCHRONIZATION)) +{ + // Synchronize read/write access to the map while the new frames are + // being computed. + ACE_Write_Guard mon (this->lock_); + if (mon.locked () == 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + METRICS_FRAME_DATA_MAP_ITERATOR iter (frame_data_map_); + + // Grab the common time stamp as late as possible, i.e., after all + // locks are held. + ACE_Time_Value tv; + ACE_hrtime_t hrtime_now = ACE_OS::gethrtime (); + ACE_High_Res_Timer::hrtime_to_tv (tv, hrtime_now); + + while (iter.done () == 0) + { + update_data (*((*iter).int_id_), tv); + ++iter; + } + return 0; +} + + +// Updates the passed period's time frame, based on the passed time +// value. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +update_frame (RtecScheduler::Period_t p, const ACE_Time_Value& tv) +{ + // Treat a zero period as a special case. + if (p == 0) + { + return 0; + } + + TAO_Metrics_Frame_Manager_Data * data; + + // Synchronize write access to the map during pointer lookup only + ACE_Read_Guard mon (this->lock_); + if (mon.locked () == 0) + { + return -1; + } + + if (frame_data_map_.find (p, data) == 0 && data != 0) + { + mon.release (); + + // Synchronize read/write access to the specific data structure + // instance during update + ACE_Write_Guard data_mon (data->lock_); + if (data_mon.locked () == 0) + { + return -1; + } + return update_data (*data, tv); + } + + return -2; +} + +// Updates the passed period's time frame, based on the passed time +// value. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +update_frame_with_time (RtecScheduler::Period_t p, Metrics::Time mt, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)) +{ + // Treat a zero period as a special case. + if (p == 0) + { + return 0; + } + + // Reentrant method that calls locked method. + ACE_Time_Value tv; + ORBSVCS_Time::TimeT_to_Time_Value(tv, mt); + switch (this->update_frame (p, tv)) + { + case -1: ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + case -2: ACE_THROW_RETURN (Metrics::INTERNAL (), -1); + default: return 0; + } +} + + +// Updates the passed period's time frame, based on the current time +// as of the call. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +update_frame (RtecScheduler::Period_t p, CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)) +{ + // Treat a zero period as a special case. + if (p == 0) + { + return 0; + } + + TAO_Metrics_Frame_Manager_Data * data; + + // Synchronize write access to the map during pointer lookup only + ACE_Read_Guard mon (this->lock_); + if (mon.locked () == 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + if (frame_data_map_.find (p, data) == 0 && data != 0) + { + mon.release (); + + // Synchronize read/write access to the specific data structure instance during + // update + ACE_Write_Guard data_mon (data->lock_); + if (data_mon.locked () == 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + // Grab the time stamp as late as possible, i.e., after all locks + // are held. + ACE_Time_Value tv; + ACE_hrtime_t hrtime_now = ACE_OS::gethrtime (); + ACE_High_Res_Timer::hrtime_to_tv (tv, hrtime_now); + + return update_data (*data, tv); + } + + ACE_THROW_RETURN (Metrics::INTERNAL (), -1); +} + + +// Resets time frames, based on the passed time value. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +reset_all_frames (const ACE_Time_Value& tv) +{ + // Synchronize read/write access to the map during the reset + ACE_Write_Guard mon (this->lock_); + if (mon.locked () == 0) + { + return -1; + } + + METRICS_FRAME_DATA_MAP_ITERATOR iter (frame_data_map_); + while (iter.done () == 0) + { + reset_data (*((*iter).int_id_), tv); + ++iter; + } + return 0; +} + + +// Resets time frames, based on the passed time value. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +reset_all_frames_with_time (Metrics::Time mt, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::SYNCHRONIZATION)) +{ + // Reentrant method that calls locked method. + ACE_Time_Value tv; + ORBSVCS_Time::TimeT_to_Time_Value(tv, mt); + if (this->reset_all_frames (tv) < 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + return 0; +} + +// Resets time frames, based on the current time as of the call. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +reset_all_frames (CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::SYNCHRONIZATION)) +{ + // Synchronize read/write access to the map during the reset + ACE_Write_Guard mon (this->lock_); + if (mon.locked () == 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + METRICS_FRAME_DATA_MAP_ITERATOR iter (frame_data_map_); + + // Grab the time stamp as late as possible, i.e., after all locks + // are held. + ACE_Time_Value tv; + ACE_hrtime_t hrtime_now = ACE_OS::gethrtime (); + ACE_High_Res_Timer::hrtime_to_tv (tv, hrtime_now); + + while (iter.done () == 0) + { + reset_data (* ((*iter).int_id_), tv); + ++iter; + } + return 0; +} + + +// Resets the passed period's start-of-frame, based on the passed time +// value. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +reset_frame (RtecScheduler::Period_t p, const ACE_Time_Value& tv) +{ + // Treat a zero period as a special case. + if (p == 0) + { + return 0; + } + + TAO_Metrics_Frame_Manager_Data * data; + + // Synchronize write access to the map during lookup only + ACE_Read_Guard mon (this->lock_); + if (mon.locked () == 0) + { + return -1; + } + + if (frame_data_map_.find (p, data) == 0 && data != 0) + { + mon.release (); + + // Synchronize read/write access to the individual data + // structure instance during reset + ACE_Write_Guard data_mon (data->lock_); + if (data_mon.locked () == 0) + { + return -1; + } + + return reset_data (*data, tv); + } + + return -2; +} + +// Resets the passed period's start-of-frame, based on the passed time +// value. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +reset_frame_with_time (RtecScheduler::Period_t p, Metrics::Time mt, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)) +{ + // Treat a zero period as a special case. + if (p == 0) + { + return 0; + } + + // Reentrant method that calls locked method. + ACE_Time_Value tv; + ORBSVCS_Time::TimeT_to_Time_Value(tv, mt); + switch (this->reset_frame (p, tv)) + { + case -1: ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + case -2: ACE_THROW_RETURN (Metrics::INTERNAL (), -1); + default: return 0; + } +} + + +// Resets the passed period's start-of-frame, based on the current +// time as of the call. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +reset_frame (RtecScheduler::Period_t p, CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)) +{ + // Treat a zero period as a special case. + if (p == 0) + { + return 0; + } + + TAO_Metrics_Frame_Manager_Data * data; + + // Synchronize write access to the map during lookup only + ACE_Read_Guard mon (this->lock_); + if (mon.locked () == 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + if (frame_data_map_.find (p, data) == 0 && data != 0) + { + mon.release (); + + // Synchronize read/write access to the individual data + // structure instance during reset + ACE_Write_Guard data_mon (data->lock_); + if (data_mon.locked () == 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + // Grab the time stamp as late as possible, i.e., after all locks + // are held. + ACE_Time_Value tv; + ACE_hrtime_t hrtime_now = ACE_OS::gethrtime (); + ACE_High_Res_Timer::hrtime_to_tv (tv, hrtime_now); + + if (data == 0) + { + ACE_THROW_RETURN (Metrics::INTERNAL (), -1); + } + + return reset_data (*data, tv); + } + + ACE_THROW_RETURN (Metrics::INTERNAL (), -1); +} + + +// Gets the start time for the period's current frame. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +get_start_time (RtecScheduler::Period_t p, ACE_Time_Value &start) +{ + // Treat a zero period as a special case. + if (p == 0) + { + start = ACE_Time_Value::zero; + return 0; + } + + TAO_Metrics_Frame_Manager_Data * data; + + // Synchronize write access to the map during lookup only + ACE_Read_Guard mon (this->lock_); + if (mon.locked () == 0) + { + return -1; + } + + if (frame_data_map_.find (p, data) == 0 && data != 0) + { + mon.release (); + + // Synchronize write access to the individual data structure instance + ACE_Read_Guard data_mon (data->lock_); + if (data_mon.locked () == 0) + { + return -1; + } + + start.set (data->start_.sec (), data->start_.usec ()); + return 0; + } + + return -2; +} + +// Gets the start time for the period's current frame. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +get_start_time (RtecScheduler::Period_t p, Metrics::Time &start, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)) +{ + // Treat a zero period as a special case. + if (p == 0) + { + start = 0; + return 0; + } + + // Reentrant method that calls locked method. + ACE_Time_Value tv; + switch (this->get_start_time (p, tv)) + { + case -1: ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + case -2: ACE_THROW_RETURN (Metrics::INTERNAL (), -1); + default: ORBSVCS_Time::Time_Value_to_TimeT (start, tv); + return 0; + } +} + + +// Gets the end time for the period's current frame. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +get_end_time (RtecScheduler::Period_t p, ACE_Time_Value &end) +{ + // Treat a zero period as a special case. + if (p == 0) + { + end = ACE_Time_Value::zero; + return 0; + } + + TAO_Metrics_Frame_Manager_Data * data = 0; + + // Synchronize write access to the map during lookup only + ACE_Read_Guard mon (this->lock_); + if (mon.locked () == 0) + { + return -1; + } + + if (frame_data_map_.find (p, data) == 0 && data != 0) + { + mon.release (); + + // Synchronize write access to the individual data structure instance + ACE_Read_Guard data_mon (data->lock_); + if (data_mon.locked () == 0) + { + return -1; + } + + end.set (data->end_.sec (), data->end_.usec ()); + return 0; + } + + return -2; +} + + +// Gets the end time for the period's current frame. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +get_end_time (RtecScheduler::Period_t p, Metrics::Time &end, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)) +{ + // Treat a zero period as a special case. + if (p == 0) + { + end = 0; + return 0; + } + + // Reentrant method that calls locked method. + ACE_Time_Value tv; + switch (this->get_end_time (p, tv)) + { + case -1: ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + case -2: ACE_THROW_RETURN (Metrics::INTERNAL (), -1); + default: ORBSVCS_Time::Time_Value_to_TimeT (end, tv); + return 0; + } +} + +// Gets the locally unique identifier for the period's current frame. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +get_frame_id (RtecScheduler::Period_t p, + CORBA::ULong &id, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)) +{ + // Treat a zero period as a special case. + if (p == 0) + { + id = 0; + return 0; + } + + TAO_Metrics_Frame_Manager_Data * data; + + // Synchronize write access to the map during lookup only + ACE_Read_Guard mon (this->lock_); + if (mon.locked () == 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + if (frame_data_map_.find (p, data) == 0 && data != 0) + { + mon.release (); + + // Synchronize write access to the individual data structure instance + ACE_Read_Guard data_mon (data->lock_); + if (data_mon.locked () == 0) + { + ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + } + + id = data->frame_id_; + return 0; + } + + ACE_THROW_RETURN (Metrics::INTERNAL (), -1); +} + + +// Gets the start time, end time, and id period's current frame. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +get_frame_data (RtecScheduler::Period_t p, ACE_Time_Value &start, + ACE_Time_Value &end, CORBA::ULong &id) +{ + // Treat a zero period as a special case. + if (p == 0) + { + start = ACE_Time_Value::zero; + end = ACE_Time_Value::zero; + id = 0; + return 0; + } + + TAO_Metrics_Frame_Manager_Data * data; + + // Synchronize write access to the map during lookup only + ACE_Read_Guard mon (this->lock_); + if (mon.locked () == 0) + { + return -1; + } + + if (frame_data_map_.find (p, data) == 0 && data != 0) + { + mon.release (); + + // Synchronize write access to the individual data structure instance + ACE_Read_Guard data_mon (data->lock_); + if (data_mon.locked () == 0) + { + return -1; + } + + start.set (data->start_.sec (), data->start_.usec ()); + end.set (data->end_.sec (), data->end_.usec ()); + id = data->frame_id_; + return 0; + } + + return -2; +} + + + +// Gets the start time, end time, and id period's current frame. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +get_frame_data (RtecScheduler::Period_t p, Metrics::Time &start, + Metrics::Time &end, CORBA::ULong &id, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL, + Metrics::SYNCHRONIZATION)) +{ + // Treat a zero period as a special case. + if (p == 0) + { + start = 0; + end = 0; + id = 0; + return 0; + } + + // Reentrant method that calls locked method. + ACE_Time_Value start_tv, end_tv; + switch (this->get_frame_data (p, start_tv, end_tv, id)) + { + case -1: ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1); + case -2: ACE_THROW_RETURN (Metrics::INTERNAL (), -1); + default: ORBSVCS_Time::Time_Value_to_TimeT (start, start_tv); + ORBSVCS_Time::Time_Value_to_TimeT (end, end_tv); + return 0; + } +} + + +// Updates the passed frame data structure's start and end times, +// based on the passed time value. This is a protected internal +// method, and should only be called with locks already held. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +update_data (TAO_Metrics_Frame_Manager_Data & data, const ACE_Time_Value& tv) +{ + if (data.end_ == ACE_Time_Value::zero) + { + return reset_data (data, tv); + } + + // Advance to the frame that encloses the passed time value. + while (data.end_ < tv) + { + data.end_ += data.period_; + ++data.frame_id_; + } + + data.start_.set (data.end_.sec (), data.end_.usec ()); + data.start_ -= data.period_; + return 0; +} + + +// Resets the passed frame data structure's start and end times, to +// the passed time value and one period later, respectively. This is +// a protected internal method, and should only be called with locks +// already held. + +template +ACE_INLINE CORBA::Short +TAO_Metrics_FrameManager:: +reset_data (TAO_Metrics_Frame_Manager_Data & data, const ACE_Time_Value& tv) +{ + data.start_.set (tv.sec (), tv.usec ()); + data.end_.set (tv.sec () + data.period_.sec (), + tv.usec () + data.period_.usec ()); + return 0; +} + + +#endif /* METRICS_FRAME_MANAGER_T_I */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.cpp b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.cpp new file mode 100644 index 00000000000..e89c29d4dae --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.cpp @@ -0,0 +1,29 @@ +// $Id$ + +#ifndef METRICS_LOCAL_CACHE_CPP +#define METRICS_LOCAL_CACHE_CPP + +#include "Metrics_LocalCache.h" + +#if !defined (__ACE_INLINE__) +#include "Metrics_LocalCache.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Hash_Map_Entry::TAO_Metrics_Cache_Data *>; +template class ACE_Hash_Map_Entry::TAO_Metrics_Cache_Data_Base *>; +template class ACE_Hash_Map_Manager_Ex::TAO_Metrics_Cache_Data *, ACE_Hash, ACE_Equal_To, ACE_Null_Mutex>; +template class ACE_Hash_Map_Manager_Ex::TAO_Metrics_Cache_Data_Base *, ACE_Hash, ACE_Equal_To, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex::TAO_Metrics_Cache_Data_Base *, ACE_Hash, ACE_Equal_To, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex::TAO_Metrics_Cache_Data *, ACE_Hash, ACE_Equal_To, ACE_Null_Mutex>; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Hash_Map_Entry::TAO_Metrics_Cache_Data *> +#pragma instantiate ACE_Hash_Map_Entry::TAO_Metrics_Cache_Data_Base *> +#pragma instantiate ACE_Hash_Map_Manager_Ex::TAO_Metrics_Cache_Data *, ACE_Hash, ACE_Equal_To, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Manager_Ex::TAO_Metrics_Cache_Data_Base *, ACE_Hash, ACE_Equal_To, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex::TAO_Metrics_Cache_Data_Base *, ACE_Hash, ACE_Equal_To, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex::TAO_Metrics_Cache_Data *, ACE_Hash, ACE_Equal_To, ACE_Null_Mutex> +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + +#endif /* METRICS_LOCAL_CACHE_CPP */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.h b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.h new file mode 100644 index 00000000000..15523e6ffdc --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.h @@ -0,0 +1,51 @@ +// $Id$ + +#ifndef METRICS_LOCAL_CACHE_H +#define METRICS_LOCAL_CACHE_H + + +#include "ace/OS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Hash_Map_Manager.h" +#include "ace/Metrics_Cache.h" +#include "ace/Metrics_Cache_T.h" +#include "ace/Singleton.h" + +#include "orbsvcs/Time_Utilities.h" +#include "orbsvcs/Scheduler_Factory.h" +#include "orbsvcs/MetricsC.h" + +#include "Metrics_Utils.h" + +#if defined (__ACE_INLINE__) +#include "Metrics_LocalCache.i" +#endif /* __ACE_INLINE__ */ + +#include "Metrics_LocalCache_T.h" + +typedef TAO_Metrics_LocalCache +TAO_METRICS_CACHE_TYPE; + +typedef ACE_Singleton +TAO_METRICS_CACHE_SINGLETON_TYPE; + +typedef TAO_Metrics_ReportingLocalCache +TAO_METRICS_REPORTING_CACHE_TYPE; + +typedef ACE_Singleton +TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE; + +#if defined (TAO_USES_REPORTING_METRICS) +typedef TAO_METRICS_REPORTING_CACHE_TYPE TAO_METRICS_CACHE; +typedef TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE TAO_METRICS_CACHE_SINGLETON; +#else +typedef TAO_METRICS_CACHE_TYPE TAO_METRICS_CACHE; +typedef TAO_METRICS_CACHE_SINGLETON_TYPE TAO_METRICS_CACHE_SINGLETON; +#endif + +#endif /* METRICS_LOCAL_CACHE_H */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.i b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.i new file mode 100644 index 00000000000..a9ccf1b5acd --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.i @@ -0,0 +1,10 @@ +// $Id$ + +#ifndef METRICS_LOCAL_CACHE_I +#define METRICS_LOCAL_CACHE_I + +#endif /* METRICS_LOCAL_CACHE_I */ + + + + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.cpp b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.cpp new file mode 100644 index 00000000000..d0ea2bd6f03 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.cpp @@ -0,0 +1,490 @@ +// $Id$ + +#ifndef METRICS_LOCAL_CACHE_T_CPP +#define METRICS_LOCAL_CACHE_T_CPP + +#include "Metrics_LocalCache_T.h" + +#if defined VXWORKS +#include +#endif + +////////////////////////////////////// +// Class TAO_Metrics_LocalTimeprobe // +////////////////////////////////////// + +// Default constructor. + +template +TAO_Metrics_LocalTimeprobe:: +TAO_Metrics_LocalTimeprobe (u_int id, + const char *name, + u_long size, + ALLOCATOR * alloc) + : ACE_Metrics_Timeprobe (alloc, id, name, size), + is_operation_ (0), + is_hrt_ (0), + data_set_ (0) +{ +} + +template +void +TAO_Metrics_LocalTimeprobe::report_intervals (int report_full_interval_times) +{ + u_long data_set_length = 0; + + // Modified by BRM. This should also work for ACE_Based_Pointer since the conversion + // operator should fire. + // Metrics::TimeprobeParameter_Set * data_set = data_set_.addr (); + Metrics::TimeprobeParameter_Set * data_set = data_set_; + + ACE_Time_Value full_start_time (ACE_Time_Value::zero); + ACE_Time_Value full_stop_time (ACE_Time_Value::zero); + + if (!data_set) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalTimeprobe::report_intervals:" + " no data set installed")); +#endif + return; + } + else + { + data_set_length = data_set->length (); + } + + if (this->current_size_ == 0 && this->report_buffer_full_ == 0) + return; + + u_long valid_intervals = 0; + int good_interval; + + // Note the case of current_size_ and report_buffer_full_ both being + // 0 was checked above, which simplifies this code. + // This logic make no sense to me. What are you going for here, Chris? + // If the buffer fills, then report_buffer_full == 1, and current size == 0. + // We always needs i to start at 0, though????? + // u_long i; + // i = (report_buffer_full_ == 0) ? 1 : this->current_size_; + u_long start_evt_ndx = 0; + u_long full_interval_start_evt_ndx = 0; + u_long full_interval_start_ndx_set = 0; + u_long stop_evt_ndx = 0; + short any_cross_thread_event = 0; + short is_cross_thread_event = 0; + do + { + // Begin a new interval at each successive start event. + if (is_event (this->timeprobes ()[start_evt_ndx], + ACE_Metrics_Timeprobe::WORK_START)) + { + // If we see the start event, then reset the cross thread indicator + is_cross_thread_event = 0; + + if (!full_interval_start_ndx_set) + { + full_interval_start_ndx_set = 1; + full_interval_start_evt_ndx = start_evt_ndx; + } + + // Accumulates elapsed time in the measured interval, taking + // into account paired suspend and resume markers. + ACE_Time_Value elapsed_time (ACE_Time_Value::zero); + + // Stores current start time: either from a start or resume event. + ACE_Time_Value start_time (this->timeprobes ()[start_evt_ndx].time_); + + // Check if this start time is less than the full interval for worse + // case time. + if (full_start_time == ACE_Time_Value::zero || + this->timeprobes ()[start_evt_ndx].time_ < full_start_time) + { + full_start_time.set (this->timeprobes ()[start_evt_ndx].time_.sec (), + this->timeprobes ()[start_evt_ndx].time_.usec ()); + } + if (full_stop_time == ACE_Time_Value::zero || + this->timeprobes ()[start_evt_ndx].time_ > full_stop_time) + { + full_stop_time.set (this->timeprobes ()[start_evt_ndx].time_.sec (), + this->timeprobes ()[start_evt_ndx].time_.usec ()); + } + + good_interval = 1; + + // Increment past the start event and start looking for the stop event + u_long stop_or_suspend_evt_ndx = (start_evt_ndx + 1) % this ->max_size_; // Modulus increment: loops around at the end. + do + { + // If the index is at the end, skip and exit the loop. + if (stop_or_suspend_evt_ndx == this->current_size_) + { + break; + } + + // This needs to be rethought... Events that occur across threads are a real thing. + // So for now, the behavior is to just indicate the events that are cross thread +// if (this->timeprobes ()[start_evt_ndx].thread_ != this->timeprobes ()[stop_or_suspend_evt_ndx].thread_) +// { +// stop_or_suspend_evt_ndx = (stop_or_suspend_evt_ndx + 1) % this ->max_size_; // Modulus increment: loops around at the end. +// continue; +// } + + // Check for the stop event + if (is_event (this->timeprobes ()[stop_or_suspend_evt_ndx], + ACE_Metrics_Timeprobe::WORK_STOP)) + { + ++valid_intervals; + + if (this->timeprobes ()[start_evt_ndx].thread_ != this->timeprobes ()[stop_or_suspend_evt_ndx].thread_) + { + // If any probe is cross, thread then the interval is cross thread. + any_cross_thread_event = 1; + + is_cross_thread_event = 1; + } + + // done this way for efficiency: no temporaries constructed + elapsed_time += this->timeprobes ()[stop_or_suspend_evt_ndx].time_; + elapsed_time -= start_time; + + // This doesn't make sense. Full start time better be the result of + // a start event. +// if (full_start_time == ACE_Time_Value::zero || +// this->timeprobes ()[j].time_ < full_start_time) +// { +// full_start_time.set (this->timeprobes()[j].time_.sec (), +// this->timeprobes()[j].time_.usec()); +// } + + if (full_stop_time == ACE_Time_Value::zero || + this->timeprobes ()[stop_or_suspend_evt_ndx].time_ > full_stop_time) + { + full_stop_time.set (this->timeprobes()[stop_or_suspend_evt_ndx].time_.sec (), + this->timeprobes()[stop_or_suspend_evt_ndx].time_.usec()); + } + + stop_evt_ndx = stop_or_suspend_evt_ndx; + // Increase the length of the data set and record + // the interval info. + ++data_set_length; + data_set->length (data_set_length); + (*(data_set))[data_set_length-1].is_full_interval = 0; + (*(data_set))[data_set_length-1].probe_id = this->id_; + (*(data_set))[data_set_length-1].is_operation = this->is_operation_; + (*(data_set))[data_set_length-1].is_hrt = this->is_hrt_; + (*(data_set))[data_set_length-1].cross_thread_probe = is_cross_thread_event; + ORBSVCS_Time::Time_Value_to_TimeT + ((*(data_set)) [data_set_length-1].start_event_time, + this->timeprobes ()[start_evt_ndx].time_); + ORBSVCS_Time::Time_Value_to_TimeT + ((*(data_set)) [data_set_length-1].stop_event_time, + this->timeprobes ()[stop_or_suspend_evt_ndx].time_); + ORBSVCS_Time::Time_Value_to_TimeT + ((*(data_set)) [data_set_length-1].interval, + elapsed_time); +#if defined (METRICS_CACHE_DEBUG_OUTPUT_ENABLED) + ACE_OS::printf (" %9lu\n", + (u_long) + ACE_U64_TO_U32((*(data_set)) + [data_set_length-1].interval + / 10)); +#endif + break; + } + + // If it wasn't a stop event, check for a suspend event +#if defined (ACE_HAS_METRICS_BASE_POINTERS) + else if (this->timeprobes ()[stop_or_suspend_evt_ndx].event_ == (u_long) + ACE_Metrics_Timeprobe::WORK_SUSPEND) +#else + else if (this->timeprobes ()[stop_or_suspend_evt_ndx].event_.event_number_ == (u_long) + ACE_Metrics_Timeprobe::WORK_SUSPEND) +#endif + { + u_long resume_evt_ndx = (stop_or_suspend_evt_ndx + 1) % this ->max_size_; // Modulus increment: loops around at the end. + do + { + // Skip until we reach the next event in the same thread, or if the + // index is at the end, skip and exit the loop. +// if (this->timeprobes ()[j].thread_ != this->timeprobes ()[k].thread_ +// || k == this->current_size_) +// { +// continue; +// } + + // If we saw a suspend event, the next event has to be a resume event + if (is_event (this->timeprobes ()[resume_evt_ndx], + ACE_Metrics_Timeprobe::WORK_RESUME)) + { + // Store the elapsed time between the last + // start and the suspend event. + elapsed_time += + this->timeprobes ()[stop_or_suspend_evt_ndx].time_ - start_time; + + // Update the start time to be that of the + // resume event. + start_time = this->timeprobes ()[resume_evt_ndx].time_; + + // This code doesn't make sense here. It always has to hit the stop to + // adjust the stop time. Anything else is a partial and invalid. +// if (full_start_time == ACE_Time_Value::zero || +// this->timeprobes ()[resume_evt_ndx].time_ < full_start_time) +// { +// full_start_time. +// set (this->timeprobes()[resume_evt_ndx].time_.sec (), +// this->timeprobes()[resume_evt_ndx].time_.usec ()); +// } +// if (full_stop_time == ACE_Time_Value::zero || +// this->timeprobes ()[resume_evt_ndx].time_ > full_stop_time) +// { +// full_stop_time. +// set (this->timeprobes()[resume_evt_ndx].time_.sec (), +// this->timeprobes()[resume_evt_ndx].time_.usec ()); +// } + + + // Keep looking for the end of the interval + // after the resume event. + stop_or_suspend_evt_ndx = resume_evt_ndx; + break; + } + else if (is_event (this->timeprobes ()[resume_evt_ndx], + ACE_Metrics_Timeprobe::WORK_START) || + is_event (this->timeprobes ()[resume_evt_ndx], + ACE_Metrics_Timeprobe::WORK_STOP) || + is_event (this->timeprobes ()[resume_evt_ndx], + ACE_Metrics_Timeprobe::WORK_SUSPEND)) + { + // Something went wrong during the current interval: + // just ignore the previous start time stamp. + good_interval = 0; + break; + } + + resume_evt_ndx = (resume_evt_ndx + 1) % this ->max_size_; // Modulus increment: loops around at the end. + + } while (resume_evt_ndx != this->current_size_); + } + + // If we got a start event, make sure that we don't see another start or resume + // until we see a stop or suspend event + else if (is_event (this->timeprobes ()[stop_or_suspend_evt_ndx], + ACE_Metrics_Timeprobe::WORK_START) || + is_event (this->timeprobes ()[stop_or_suspend_evt_ndx], + ACE_Metrics_Timeprobe::WORK_RESUME)) + { + // Something went wrong during the current interval: + // just ignore the previous start time stamp. + break; + } + + stop_or_suspend_evt_ndx = (stop_or_suspend_evt_ndx + 1) % this ->max_size_; // Modulus increment: loops around at the end. + + } while (stop_or_suspend_evt_ndx != this->current_size_ && good_interval); + + // If we found the stop of + start_evt_ndx = stop_or_suspend_evt_ndx; + } + + start_evt_ndx = (start_evt_ndx + 1) % this ->max_size_; // Modulus increment: loops around at the end. + + } while (start_evt_ndx < this->current_size_); + + + if (report_full_interval_times) + { + // Increase the length of the data set and record the full interval. + ++data_set_length; + data_set->length (data_set_length); + (*(data_set))[data_set_length-1].is_full_interval = 1; + (*(data_set))[data_set_length-1].probe_id = this->id_; + (*(data_set))[data_set_length-1].is_operation = this->is_operation_; + (*(data_set))[data_set_length-1].is_hrt = this->is_hrt_; + (*(data_set))[data_set_length-1].cross_thread_probe = any_cross_thread_event; + ORBSVCS_Time::Time_Value_to_TimeT + ((*(data_set)) [data_set_length-1].start_event_time, + this->timeprobes ()[start_evt_ndx].time_); + ORBSVCS_Time::Time_Value_to_TimeT + ((*(data_set)) [data_set_length-1].stop_event_time, + this->timeprobes ()[stop_evt_ndx].time_); + ORBSVCS_Time::Time_Value_to_TimeT( + (*(data_set))[data_set_length-1].interval, + full_stop_time - full_start_time); + } +} + + +// Flush the TAO metrics local timeprobe into shared memory. + +template +void +TAO_Metrics_LocalTimeprobe::flush_TAO_Metrics_LocalTimeprobe () +{ +// TBD - 1) replace VXWORKS with a nicer ACE/TAO #define +// 2) provide a general capability to apply an arbitrary +// functor to the whole data structure framework (e.g., flush). + +#if defined VXWORKS + // TBD - implement this +#endif +} + + +////////////////////////////////// +// Class TAO_Metrics_LocalCache // +////////////////////////////////// + + +template +void +TAO_Metrics_LocalCache::reset_statistics () +{ + // Call the base class reset method first. + this->reset_base_statistics (); + + // Iterate over consumer side base map, + // resetting probes. + METRICS_BASE_MONITOR_MAP_ITERATOR + base_iter (this->base_monitor_maps_ [this->consumer_index_]); + + for (TAO_Metrics_Cache_Data_Base * data_base = 0; + base_iter.done () == 0; + ++base_iter) + { + // Modified by BRM. This should also work for ACE_Based_Pointer since the conversion + // operator should fire. +// data_base = (*base_iter).int_id_.addr (); + data_base = (*base_iter).int_id_; + // Modified by BRM. This should also work for ACE_Based_Pointer since the conversion + // operator should fire. +// if (data_base.addr ()) + if (data_base) + { + data_base->probe.reset (); + } + } + + + // Iterate over consumer side monitor map, + // resetting counts and probes. + METRICS_MONITOR_MAP_ITERATOR data_iter (this-> + monitor_maps_ [this-> + consumer_index_]); + for (TAO_Metrics_Cache_Data * data = 0; + data_iter.done () == 0; + ++data_iter) + { + // Modified by BRM. This should also work for ACE_Based_Pointer since the conversion + // operator should fire. +// data = (*data_iter).int_id_.addr (); + data = (*data_iter).int_id_; + if (data) + { + data->probe.reset (); + data->missed_deadlines = 0; + data->made_deadlines = 0; + data->cancellations = 0; + } + } +} + + +// Flush the TAO local metrics cache into shared memory. + +template +void +TAO_Metrics_LocalCache:: +flush_TAO_Metrics_LocalCache () +{ +#if defined VXWORKS + + // TBD - fix this: is it complete? + + // TBD - add base metrics map flush + + // TBD - do probes need their own flush method? + + // flush the class + // cacheFlush ( + // DATA_CACHE, + // this, + // sizeof (TAO_Metrics_LocalCache)); + + // flush the monitor data map hash table + // cacheFlush (DATA_CACHE, + // &monitor_maps_ [this->consumer_index_], + // sizeof (METRICS_MONITOR_MAP)); + + // flush the nodes in the monitor data map hash table + // and the data stored in the nodes. + // METRICS_MONITOR_MAP_ITERATOR data_iter (this-> + // monitor_maps_ [this-> + // consumer_index_]); + // for (; + // data_iter.done () == 0; + // ++data_iter) + // { + // METRICS_MONITOR_MAP_ENTRY *entry; + // data_iter.next (entry); + // if (entry) + // { + // cacheFlush (DATA_CACHE, + // entry, + // sizeof (METRICS_MONITOR_MAP_ENTRY)); + // if (entry->int_id_.addr ()) + // { + // cacheFlush (DATA_CACHE, + // entry->int_id_.addr (), + // sizeof (TAO_Metrics_Cache_Data)); + // } + // } + // } + + // flush the base class probe counts + // cacheFlush (DATA_CACHE, + // this-> + // enqueue_count_ [this->consumer_index_].addr (), + // this->probe_set_size_ * sizeof (u_long)); + + // cacheFlush (DATA_CACHE, + // this-> + // dequeue_count_ [this->consumer_index_].addr (), + // this->probe_set_size_ * sizeof (u_long)); + + // flush the base class probe pointer arrays + // cacheFlush ( + // DATA_CACHE, + // this->enqueue_probes_ [this->consumer_index_], + // this-> + // probe_set_size_ + // * sizeof (ACE_Metrics_Timeprobe *)); + // cacheFlush ( + // DATA_CACHE, + // this->dequeue_probes_ [this->consumer_index_], + // this->probe_set_size_ + // * sizeof (ACE_Metrics_Timeprobe *)); + + // flush the base class probes + // for (u_int i = 0; i < this->probe_set_size_; ++i) + // { + // cacheFlush ( + // DATA_CACHE, + // this->enqueue_probes_ [this->consumer_index_][i], + // sizeof (ACE_Metrics_Timeprobe)); + // cacheFlush ( + // DATA_CACHE, + // this->dequeue_probes_ [this->consumer_index_][i], + // sizeof (ACE_Metrics_Timeprobe)); + // } +#endif +} + +#if !defined (__ACE_INLINE__) +#include "Metrics_LocalCache_T.i" +#endif /* __ACE_INLINE__ */ + +#endif /* METRICS_LOCAL_CACHE_T_CPP */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.h b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.h new file mode 100644 index 00000000000..ea4aa97b4d7 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.h @@ -0,0 +1,329 @@ +// $Id$ + +#ifndef METRICS_LOCAL_CACHE_T_H +#define METRICS_LOCAL_CACHE_T_H + +#include "ace/OS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Hash_Map_Manager.h" +#include "ace/Metrics_Cache.h" +#include "ace/Metrics_Cache_T.h" + +#include "orbsvcs/Time_Utilities.h" +#include "orbsvcs/Scheduler_Factory.h" +#include "orbsvcs/MetricsC.h" + +#include "orbsvcs/Metrics/Metrics_Utils.h" + +#if defined (ACE_HAS_METRICS_BASE_POINTERS) + typedef ACE_Based_Pointer ACE_METRICS_STRING_TYPE; + typedef ACE_Based_Pointer ACE_METRICS_PARAMETER_SET_TYPE; +#else + typedef char * ACE_METRICS_STRING_TYPE; + typedef Metrics::TimeprobeParameter_Set * ACE_METRICS_PARAMETER_SET_TYPE; +#endif + +//DCL:Commented out to remove Linux compile error +//#include "orbsvcs/Metrics/Metrics_LocalCache.h" + +template +class TAO_Metrics_LocalTimeprobe + : public ACE_Metrics_Timeprobe +{ + // = TITLE + // Defines a class that implements a local timeprobe. + // + // = DESCRIPTION + // This class makes use of the class to + // implement a timeprobe for use in a local metrics cache. +public: + + typedef TAO_Metrics_LocalTimeprobe TAO_METRICS_TIMEPROBE_TYPE; + + TAO_Metrics_LocalTimeprobe (u_int id = 0, + const char *name = 0, + u_long size + = METRICS_DEFAULT_TIMEPROBE_TABLE_SIZE, + ALLOCATOR * alloc = 0); + // Default constructor. + + void report_intervals (int report_full_interval_times = 0); + // Reports valid intervals between start and stop events. + + void install_data_set (Metrics::TimeprobeParameter_Set *data_set = 0); + // Installs or unistalls the data set into which probe will report. + + void mark_as_operation (void) {this->is_operation_ = 1;} + // Marks the probe as being for an operation. + + void set_hrt (int hrt) {this->is_hrt_ = hrt;} + // Marks the probe as being SRT/HRT. + + ACE_Time_Value last_recorded_timestamp (void); + // Returns the last timestamp that was recorded in the probe. + // If no stamps are recorded, returns zero. + + void flush_TAO_Metrics_LocalTimeprobe (); + // Flush the TAO metrics local timeprobe into shared memory. + +protected: + + int is_operation_; + // Indicates whether or not the probe is for an operation. + + int is_hrt_; + // Indicates whether or not the probe is Hard Real-Time. + + ACE_METRICS_PARAMETER_SET_TYPE data_set_; + // Points to a probe metrics data set. +}; + +template +class TAO_Metrics_LocalCache + : public ACE_Metrics_Cache +{ + // = TITLE + // Defines a class that implements a local metrics cache. + // + // = DESCRIPTION + // This class makes use of the class to + // implement a cache for local use. +public: + + typedef ACE_Metrics_Timeprobe + ACE_METRICS_TIMEPROBE_TYPE; + +#if defined (ACE_HAS_METRICS_BASE_POINTERS) + typedef ACE_Based_Pointer + ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE; +#else + typedef ACE_METRICS_TIMEPROBE_TYPE * ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE; +#endif + + typedef TAO_Metrics_LocalTimeprobe TAO_METRICS_TIMEPROBE_TYPE; + + typedef TAO_Metrics_LocalCache TAO_METRICS_CACHE_TYPE; + + struct TAO_Metrics_Cache_Data_Base + { + ACE_METRICS_STRING_TYPE probe_name; + TAO_Metrics_LocalTimeprobe probe; + }; + + struct TAO_Metrics_Cache_Data : public TAO_Metrics_Cache_Data_Base + { + int is_hrt; + u_long missed_deadlines; + u_long made_deadlines; + u_long cancellations; + }; + +#if defined (ACE_HAS_METRICS_BASE_POINTERS) + typedef ACE_Based_Pointer ACE_METRICS_CACHE_DATA_BASE_TYPE; + typedef ACE_Based_Pointer ACE_METRICS_CACHE_DATA_TYPE; +#else + typedef TAO_Metrics_Cache_Data_Base* ACE_METRICS_CACHE_DATA_BASE_TYPE; + typedef TAO_Metrics_Cache_Data* ACE_METRICS_CACHE_DATA_TYPE; +#endif + + typedef ACE_Hash_Map_Manager_Ex, + ACE_Equal_To, + ACE_Null_Mutex> METRICS_BASE_MONITOR_MAP; + // Type of map used for O(1) lookup of monitored data for operations. + + typedef ACE_Hash_Map_Entry + METRICS_BASE_MONITOR_MAP_ENTRY; + // Type of entry in monitor map. + + typedef ACE_Hash_Map_Iterator_Ex, + ACE_Equal_To, + ACE_Null_Mutex> + METRICS_BASE_MONITOR_MAP_ITERATOR; + // Type of iterator for monitor map. + + typedef ACE_Hash_Map_Manager_Ex, + ACE_Equal_To, + ACE_Null_Mutex> METRICS_MONITOR_MAP; + // Type of map used for O(1) lookup of monitored data for operations. + + typedef ACE_Hash_Map_Entry + METRICS_MONITOR_MAP_ENTRY; + // Type of entry in monitor map. + + typedef ACE_Hash_Map_Iterator_Ex, + ACE_Equal_To, + ACE_Null_Mutex> + METRICS_MONITOR_MAP_ITERATOR; + // Type of iterator for monitor map. + + TAO_Metrics_LocalCache (u_long table_size + = METRICS_DEFAULT_TIMEPROBE_TABLE_SIZE, + u_long number_of_probes + = METRICS_DEFAULT_TIMEPROBE_COUNT, + ALLOCATOR * alloc = 0); + // Constructor. + + ~TAO_Metrics_LocalCache () {this->fini ();} + // Destructor. + + void reset_statistics (); + // Reset the collection of metrics data. + + int init (u_long number_of_probes); + // Factory method for constructing probes. + + void fini (); + // Method for destroying probes. + + void register_upcall_adapter (RtecScheduler::handle_t handle, + const char *name, + int is_hrt, + unsigned short incr_upcall_id = 1); + // Registers an upcall adapter, allocates monitoring data structures + // for it in hash maps if not already present. + + RtecScheduler::handle_t register_base_metrics (const char *name, + TAO_Metrics_Utils::Base_Metrics_Type bmt, + unsigned short incr_base_id = 1); + // Registers a base metrics probe, allocates monitoring data structures + // for it in hash maps, returns a handle to the metrics segment. + + void report_upcall_start (RtecScheduler::handle_t handle); + // Inline: Records start time of an upcall. + + int report_upcall_stop (RtecScheduler::handle_t handle, + const ACE_Time_Value & deadline); + // Inline: Records end time of an upcall, returns 0 if the deadline + // was made, 1 if the deadline was missed, or -1 if an error occurred. + // If the passed deadline is equal to ACE_Time_Value::zero, by definition + // the deadline is made, and the method returns 0. + + void report_upcall_cancellation (RtecScheduler::handle_t handle); + // Inline: Reports a cancelled upcall. + + void report_base_metrics_start (RtecScheduler::handle_t handle); + // Inline: Records start time of a base metrics segment. + + void report_base_metrics_stop (RtecScheduler::handle_t handle); + // Inline: Records stop time of a base metrics segment. + + void report_base_metrics_suspend (RtecScheduler::handle_t handle); + // Inline: Records start time of a base metrics segment. + + void report_base_metrics_resume (RtecScheduler::handle_t handle); + // Inline: Records stop time of a base metrics segment. + + void flush_TAO_Metrics_LocalCache (); + // Flush the TAO metrics local cache into shared memory. + +protected: + void increment_base_handle(TAO_Metrics_Utils::Base_Metrics_Type bmt); + // Used to increment the probe id counter for a particular metrics type + + void increment_upcall_handle(); + // Used to increment the probe id counter for a upcall probe type + + METRICS_BASE_MONITOR_MAP base_monitor_maps_ [2]; + // These map base metrics ids to base monitor data. + + METRICS_MONITOR_MAP monitor_maps_ [2]; + // These map operation handles to upcall monitor data. + + // Count of the number of registered sched probes. + u_long sched_count_; + + // Count of the number of registered quo probes. + u_long quo_count_; + + // Count of the number of registered tns probes. + u_long tns_count_; + + // Count of the number of registered teec probes. + u_long teec_count_; + + // Count of the number of registered rtarm probes. + u_long rtarm_count_; + + // Count of the number of registered upcall adapters. + u_long upcall_adapter_count_; + + // Holds the next base metrics probe handle to assign + RtecScheduler::handle_t next_base_metrics_handle_; + +}; + + + +template +class TAO_Metrics_ReportingLocalCache + : public TAO_Metrics_LocalCache +{ + // = TITLE + // Defines a class that adds metrics logger reporting to a local cache. + // + // = DESCRIPTION + // This class makes use of the as its + // a cache for local use, and adds reporting to the logger. +public: + + TAO_Metrics_ReportingLocalCache (u_long table_size + = METRICS_DEFAULT_TIMEPROBE_TABLE_SIZE, + u_long number_of_probes + = METRICS_DEFAULT_TIMEPROBE_COUNT, + ALLOCATOR * alloc = 0); + // Constructor. + + ~TAO_Metrics_ReportingLocalCache () {this->fini ();} + // Destructor. + + void output_statistics (Metrics::QoSLogger_ptr logger); + // Output the statistics to the remote logger servant. + + void register_upcall_adapter (RtecScheduler::handle_t handle, + const char *name, + int is_hrt, + Metrics::QoSLogger_ptr logger); + // Registers an upcall adapter, allocates monitoring data structures + // for it in hash maps if not already present. + + RtecScheduler::handle_t register_base_metrics (const char *name, + TAO_Metrics_Utils::Base_Metrics_Type bmt, + Metrics::QoSLogger_ptr logger); + // Registers a base metrics probe, allocates monitoring data structures + // for it in hash maps, returns a handle to the metrics segment. + + int register_probes (Metrics::QoSLogger_ptr logger); + // Registers probes with the logger. + + void flush_TAO_Metrics_ReportingLocalCache (); + // Flush the TAO metrics local cache into shared memory. +}; + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "Metrics_LocalCache_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Metrics_LocalCache_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#if defined (__ACE_INLINE__) +#include "Metrics_LocalCache_T.i" +#endif /* __ACE_INLINE__ */ + +#endif /* METRICS_LOCAL_CACHE_T_H */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.i b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.i new file mode 100644 index 00000000000..f35c960698d --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.i @@ -0,0 +1,1556 @@ +// $Id$ + +#ifndef METRICS_LOCAL_CACHE_T_I +#define METRICS_LOCAL_CACHE_T_I + +////////////////////////////////////// +// class TAO_Metrics_LocalTimeprobe // +////////////////////////////////////// + +// Installs or unistalls the data set into which probe will report. + +template +ACE_INLINE void +TAO_Metrics_LocalTimeprobe:: +install_data_set (Metrics::TimeprobeParameter_Set *data_set) +{ + data_set_ = data_set; +} + + +// Returns the last timestamp that was recorded in the probe. +// If no stamps are recorded, returns zero. + +template +ACE_INLINE ACE_Time_Value +TAO_Metrics_LocalTimeprobe::last_recorded_timestamp (void) +{ + return (this->current_size_ > 0) + ? this->timeprobes ()[this->current_size_ - 1].time_ + : ((report_buffer_full_ == 0) + ? ACE_Time_Value::zero + : this->timeprobes ()[this->max_size_ - 1].time_); +} + +////////////////////////////////// +// Class TAO_Metrics_LocalCache // +////////////////////////////////// + + +// Default constructor. +template +ACE_INLINE +TAO_Metrics_LocalCache:: +TAO_Metrics_LocalCache (u_long table_size, + u_long number_of_probes, + ALLOCATOR * alloc) + : ACE_Metrics_Cache (table_size, number_of_probes, alloc), + sched_count_ (0), + quo_count_ (0), + tns_count_ (0), + teec_count_ (0), + rtarm_count_ (0), + upcall_adapter_count_ (0), + next_base_metrics_handle_ (1) +{ + // Ensure that the high res timer global scale factor + // is set before any of its static methods are used + ACE_High_Res_Timer::global_scale_factor (); + + // Allocate the probe arrays, based on passed count + if (init (number_of_probes) != 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "Metrics_Metrics::Metrics_Metrics init failed")); +#endif + } +} + +// Factory method for constructing probes. +template +ACE_INLINE int +TAO_Metrics_LocalCache::init (u_long number_of_probes) +{ + if (number_of_probes == 0 + || number_of_probes >= TAO_Metrics_Utils::METRICS_DEQUEUE_PROBE_ID_BASE) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::init " + "number_of_probes out of range")); +#endif + return -1; + } + + // Allocate the probe arrays, based on passed count + + u_long *count_temp = 0; + ACE_NEW_MALLOC_ARRAY_RETURN (count_temp, + (u_long *) this->allocator ()-> + malloc (sizeof (u_long) + * number_of_probes), + u_long, + number_of_probes, + -1); + enqueue_count_ [0] = count_temp; + + ACE_NEW_MALLOC_ARRAY_RETURN (count_temp, + (u_long *) this->allocator ()-> + malloc (sizeof (u_long) + * number_of_probes), + u_long, + number_of_probes, + -1); + enqueue_count_ [1] = count_temp; + + ACE_NEW_MALLOC_ARRAY_RETURN (count_temp, + (u_long *) this->allocator ()-> + malloc (sizeof (u_long) + * number_of_probes), + u_long, + number_of_probes, + -1); + dequeue_count_ [0] = count_temp; + + ACE_NEW_MALLOC_ARRAY_RETURN (count_temp, + (u_long *) this->allocator ()-> + malloc (sizeof (u_long) + * number_of_probes), + u_long, + number_of_probes, + -1); + dequeue_count_ [1] = count_temp; + + ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE * probes_temp; + + ACE_NEW_MALLOC_ARRAY_RETURN (probes_temp, + (ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE*) + this->allocator ()-> + malloc (sizeof(ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE) + * number_of_probes), + ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE, + number_of_probes, + -1); + enqueue_probes_ [0] = probes_temp; + + ACE_NEW_MALLOC_ARRAY_RETURN (probes_temp, + (ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE*) + this->allocator ()-> + malloc (sizeof(ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE) + * number_of_probes), + ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE, + number_of_probes, + -1); + enqueue_probes_ [1] = probes_temp; + + ACE_NEW_MALLOC_ARRAY_RETURN (probes_temp, + (ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE*) + this->allocator ()-> + malloc (sizeof(ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE) + * number_of_probes), + ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE, + number_of_probes, + -1); + dequeue_probes_ [0] = probes_temp; + + ACE_NEW_MALLOC_ARRAY_RETURN (probes_temp, + (ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE*) + this->allocator ()-> + malloc (sizeof(ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE) + * number_of_probes), + ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE, + number_of_probes, + -1); + dequeue_probes_ [1] = probes_temp; + + u_int i; + for (i = 0; i < number_of_probes; ++i) + { + TAO_METRICS_TIMEPROBE_TYPE *timeprobe_temp; + ACE_NEW_MALLOC_RETURN (timeprobe_temp, + (TAO_METRICS_TIMEPROBE_TYPE *) this-> + allocator ()-> + malloc (sizeof (TAO_METRICS_TIMEPROBE_TYPE)), + TAO_METRICS_TIMEPROBE_TYPE, + -1); + // Modified by BRM. Not sure what the equivalent for ACE_Based_Pointers is. + // enqueue_probes_ [0].addr () [i] = timeprobe_temp; + enqueue_probes_ [0][i] = timeprobe_temp; + + ACE_NEW_MALLOC_RETURN (timeprobe_temp, + (TAO_METRICS_TIMEPROBE_TYPE *) this-> + allocator ()-> + malloc (sizeof (TAO_METRICS_TIMEPROBE_TYPE)), + TAO_METRICS_TIMEPROBE_TYPE, + -1); + // Modified by BRM. Not sure what the equivalent for ACE_Based_Pointers is. + // enqueue_probes_ [1].addr () [i] = timeprobe_temp; + enqueue_probes_ [1][i] = timeprobe_temp; + + ACE_NEW_MALLOC_RETURN (timeprobe_temp, + (TAO_METRICS_TIMEPROBE_TYPE *) this-> + allocator ()-> + malloc (sizeof (TAO_METRICS_TIMEPROBE_TYPE)), + TAO_METRICS_TIMEPROBE_TYPE, + -1); + // Modified by BRM. Not sure what the equivalent for ACE_Based_Pointers is. + // dequeue_probes_ [0].addr () [i] = timeprobe_temp; + dequeue_probes_ [0][i] = timeprobe_temp; + + ACE_NEW_MALLOC_RETURN (timeprobe_temp, + (TAO_METRICS_TIMEPROBE_TYPE *) this-> + allocator ()-> + malloc (sizeof (TAO_METRICS_TIMEPROBE_TYPE)), + TAO_METRICS_TIMEPROBE_TYPE, + -1); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // dequeue_probes_ [1].addr () [i] = timeprobe_temp; + dequeue_probes_ [1][i] = timeprobe_temp; + } + + ACE_METRICS_STRING_TYPE * names_temp; + u_int j = 0; + names_temp = + (ACE_METRICS_STRING_TYPE*) this->allocator ()-> + malloc (sizeof (ACE_METRICS_STRING_TYPE) * number_of_probes); + if (names_temp == 0) + { + errno = ENOMEM; + return -1; + } + else + { + // Explicit constructor invocation using array placement + // new, to work around broken placement array new on MSVC++ + for (j = 0; j < number_of_probes; ++j) + { + new (names_temp + j) ACE_METRICS_STRING_TYPE; + } + } + enqueue_names_ = names_temp; + + names_temp = + (ACE_METRICS_STRING_TYPE*) this->allocator ()-> + malloc (sizeof (ACE_METRICS_STRING_TYPE) * number_of_probes); + if (names_temp == 0) + { + errno = ENOMEM; + return -1; + } + else + { + // Explicit constructor invocation using array placement + // new, to work around broken placement array new on MSVC++ + for (u_int j = 0; j < number_of_probes; ++j) + { + new (names_temp + j) ACE_METRICS_STRING_TYPE; + } + } + dequeue_names_ = names_temp; + + // Allocate a single block for names, into which both + // enqueue and dequeue names arrays will point. + char *temp; + ACE_NEW_MALLOC_ARRAY_RETURN (temp, + (char *) this->allocator ()-> + malloc (TAO_Metrics_Utils::METRICS_BUFSIZE + * 2 * number_of_probes), + char, + TAO_Metrics_Utils::METRICS_BUFSIZE + * 2 * number_of_probes, + -1); + + // Iterate to initialize the arrays + for (i = 0; i < number_of_probes; ++i) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // enqueue_names_.addr () [i] = + enqueue_names_[i] = temp + i * TAO_Metrics_Utils::METRICS_BUFSIZE; + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // dequeue_names_.addr () [i] = + dequeue_names_[i] = temp + (i + number_of_probes) * TAO_Metrics_Utils::METRICS_BUFSIZE; + + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->enqueue_count_ [0].addr () [i] = 0; + this->enqueue_count_ [0][i] = 0; + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->enqueue_count_ [1].addr () [i] = 0; + this->enqueue_count_ [1] [i] = 0; + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // ACE_OS::memset (this->enqueue_names_.addr () [i].addr (), + ACE_OS::memset (this->enqueue_names_ [i], + 0, TAO_Metrics_Utils::METRICS_BUFSIZE); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // ACE_OS::sprintf (this->enqueue_names_.addr () [i].addr (), + ACE_OS::sprintf (this->enqueue_names_ [i], + "enqueue_%d", i); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->enqueue_probes_ [0].addr () [i].addr ()-> + this->enqueue_probes_ [0] [i]-> + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_name (this->enqueue_names_.addr () [i].addr ()); + probe_name (this->enqueue_names_ [i]); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->enqueue_probes_ [1].addr () [i].addr ()-> + this->enqueue_probes_ [1] [i]-> + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_name (this->enqueue_names_.addr () [i].addr ()); + probe_name (this->enqueue_names_ [i]); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->enqueue_probes_ [0].addr () [i].addr ()-> + this->enqueue_probes_ [0] [i]-> + probe_id (TAO_Metrics_Utils::METRICS_ENQUEUE_PROBE_ID_BASE + i); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->enqueue_probes_ [1].addr () [i].addr ()-> + this->enqueue_probes_ [1] [i]-> + probe_id (TAO_Metrics_Utils::METRICS_ENQUEUE_PROBE_ID_BASE + i); + + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->enqueue_probes_ [0].addr () [i].addr ()-> + this->enqueue_probes_ [0] [i]-> + increase_size (this->table_size_); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->enqueue_probes_ [1].addr () [i].addr ()-> + this->enqueue_probes_ [1] [i]-> + increase_size (this->table_size_); + + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->dequeue_count_ [0].addr() [i] = 0; + this->dequeue_count_ [0][i] = 0; + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->dequeue_count_ [1].addr () [i] = 0; + this->dequeue_count_ [1] [i] = 0; + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // ACE_OS::memset (this->dequeue_names_.addr () [i].addr (), + ACE_OS::memset (this->dequeue_names_ [i], + 0, TAO_Metrics_Utils::METRICS_BUFSIZE); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // ACE_OS::sprintf (this->dequeue_names_.addr () [i].addr (), + ACE_OS::sprintf (this->dequeue_names_ [i], + "dequeue_%d", i); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->dequeue_probes_ [0].addr () [i].addr ()-> + this->dequeue_probes_ [0] [i]-> + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_name (this->dequeue_names_.addr () [i].addr ()); + probe_name (this->dequeue_names_ [i]); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->dequeue_probes_ [1].addr () [i].addr ()-> + this->dequeue_probes_ [1] [i]-> + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_name (this->dequeue_names_.addr () [i].addr ()); + probe_name (this->dequeue_names_ [i]); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->dequeue_probes_ [0].addr () [i].addr ()-> + this->dequeue_probes_ [0] [i]-> + probe_id (TAO_Metrics_Utils::METRICS_DEQUEUE_PROBE_ID_BASE + i); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->dequeue_probes_ [1].addr () [i].addr ()-> + this->dequeue_probes_ [1] [i]-> + probe_id (TAO_Metrics_Utils::METRICS_DEQUEUE_PROBE_ID_BASE + i); + + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->dequeue_probes_ [0].addr () [i].addr ()-> + this->dequeue_probes_ [0] [i]-> + increase_size (this->table_size_); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->dequeue_probes_ [1].addr () [i].addr ()-> + this->dequeue_probes_ [1] [i]-> + increase_size (this->table_size_); + } + + // If we got here we're pretty much OK. + this->probe_set_size_ = number_of_probes; + + return 0; +} + + +// Method for destroying probes. +template +ACE_INLINE void +TAO_Metrics_LocalCache::fini () +{ + if (this->probe_set_size_ > 0) + { + // Destroy the monolithic block of storage allocated to hold all names. + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (enqueue_names_.addr () [0].addr ()) + if (enqueue_names_ [0]) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (enqueue_names_.addr () [0].addr ()); + this->allocator ()->free (enqueue_names_ [0]); + } + } + + // Destroy storage allocated to hold counts. + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (enqueue_count_ [0].addr ()) + if (enqueue_count_ [0]) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (enqueue_count_ [0].addr ()); + this->allocator ()->free (enqueue_count_ [0]); + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (enqueue_count_ [1].addr ()) + if (enqueue_count_ [1]) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (enqueue_count_ [1].addr ()); + this->allocator ()->free (enqueue_count_ [1]); + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (dequeue_count_ [0].addr()) + if (dequeue_count_ [0]) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (dequeue_count_ [0].addr()); + this->allocator ()->free (dequeue_count_ [0]); + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (dequeue_count_ [1].addr()) + if (dequeue_count_ [1]) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (dequeue_count_ [1].addr()); + this->allocator ()->free (dequeue_count_ [1]); + } + + // Destroy the actual probes + TAO_METRICS_TIMEPROBE_TYPE *probe_ptr; + for (u_int i = 0; i < this->probe_set_size_; ++i) + { + //DCL:Change to static_cast for now to remove Linux compile error + //probe_ptr = ACE_dynamic_cast (TAO_METRICS_TIMEPROBE_TYPE *, + // enqueue_probes_ [0].addr () [i].addr ()); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_ptr = static_cast(enqueue_probes_ [0].addr () [i].addr ()); + probe_ptr = static_cast(enqueue_probes_ [0] [i]); + ACE_DES_FREE (probe_ptr, + this->allocator ()->free, + TAO_METRICS_TIMEPROBE_TYPE); + //probe_ptr = ACE_dynamic_cast (TAO_METRICS_TIMEPROBE_TYPE *, + // enqueue_probes_ [1].addr () [i].addr ()); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_ptr = static_cast(enqueue_probes_ [1].addr () [i].addr ()); + probe_ptr = static_cast(enqueue_probes_ [1] [i]); + ACE_DES_FREE (probe_ptr, + this->allocator ()->free, + TAO_METRICS_TIMEPROBE_TYPE); + //probe_ptr = ACE_dynamic_cast (TAO_METRICS_TIMEPROBE_TYPE *, + // dequeue_probes_ [0].addr () [i].addr ()); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_ptr = static_cast (dequeue_probes_ [0].addr () [i].addr ()); + probe_ptr = static_cast (dequeue_probes_ [0] [i]); + ACE_DES_FREE (probe_ptr, + this->allocator ()->free, + TAO_METRICS_TIMEPROBE_TYPE); + //probe_ptr = ACE_dynamic_cast (TAO_METRICS_TIMEPROBE_TYPE *, + // dequeue_probes_ [1].addr () [i].addr ()); + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_ptr = static_cast (dequeue_probes_ [1].addr () [i].addr ()); + probe_ptr = static_cast (dequeue_probes_ [1] [i]); + ACE_DES_FREE (probe_ptr, + this->allocator ()->free, + TAO_METRICS_TIMEPROBE_TYPE); + } + + // Destroy storage allocated to hold probe pointers. + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (enqueue_probes_ [0].addr ()) + if (enqueue_probes_ [0]) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (enqueue_probes_ [0].addr ()); + this->allocator ()->free (enqueue_probes_ [0]); + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (enqueue_probes_ [1].addr ()) + if (enqueue_probes_ [1]) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (enqueue_probes_ [1].addr ()); + this->allocator ()->free (enqueue_probes_ [1]); + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (dequeue_probes_ [0].addr ()) + if (dequeue_probes_ [0]) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (dequeue_probes_ [0].addr ()); + this->allocator ()->free (dequeue_probes_ [0]); + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (dequeue_probes_ [1].addr ()) + if (dequeue_probes_ [1]) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (dequeue_probes_ [1].addr ()); + this->allocator ()->free (dequeue_probes_ [1]); + } + + // Destroy storage for string pointers + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (enqueue_names_.addr ()) + if (enqueue_names_) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (enqueue_names_.addr ()); + this->allocator ()->free (enqueue_names_); + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (dequeue_names_.addr ()) + if (dequeue_names_) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (dequeue_names_.addr ()); + this->allocator ()->free (dequeue_names_); + } + + TAO_Metrics_Cache_Data_Base * base_data = 0; + + for (METRICS_BASE_MONITOR_MAP_ITERATOR base_iter_0 (this-> + base_monitor_maps_ [0]); + base_iter_0.done () == 0; + ++base_iter_0) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // base_data = (*base_iter_0).int_id_.addr (); + base_data = (*base_iter_0).int_id_; + if (base_data) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (base_data->probe_name.addr ()) + if (base_data->probe_name) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (base_data->probe_name.addr ()); + this->allocator ()->free (base_data->probe_name); + } + + ACE_DES_FREE (base_data, + this->allocator ()->free, + TAO_Metrics_Cache_Data_Base); + } + } + + for (METRICS_BASE_MONITOR_MAP_ITERATOR + base_iter_1 (this->base_monitor_maps_ [1]); + base_iter_1.done () == 0; + ++base_iter_1) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // base_data = (*base_iter_1).int_id_.addr (); + base_data = (*base_iter_1).int_id_; + if (base_data) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (base_data->probe_name.addr ()) + if (base_data->probe_name) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (base_data->probe_name.addr ()); + this->allocator ()->free (base_data->probe_name); + } + + ACE_DES_FREE (base_data, + this->allocator ()->free, + TAO_Metrics_Cache_Data_Base); + } + } + + TAO_Metrics_Cache_Data * data = 0; + + for (METRICS_MONITOR_MAP_ITERATOR data_iter_0 (this->monitor_maps_ [0]); + data_iter_0.done () == 0; + ++data_iter_0) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // data = (*data_iter_0).int_id_.addr (); + data = (*data_iter_0).int_id_; + if (data) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (data->probe_name.addr ()) + if (data->probe_name) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (data->probe_name.addr ()); + this->allocator ()->free (data->probe_name); + } + + ACE_DES_FREE (data, + this->allocator ()->free, + TAO_Metrics_Cache_Data); + } + } + + for (METRICS_MONITOR_MAP_ITERATOR data_iter_1 (this->monitor_maps_ [1]); + data_iter_1.done () == 0; + ++data_iter_1) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // data = (*data_iter_1).int_id_.addr (); + data = (*data_iter_1).int_id_; + if (data) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (data->probe_name.addr ()) + if (data->probe_name) + { + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // this->allocator ()->free (data->probe_name.addr ()); + this->allocator ()->free (data->probe_name); + } + + ACE_DES_FREE (data, + this->allocator ()->free, + TAO_Metrics_Cache_Data); + } + } +} + +// Registers an upcall adapter, allocates monitoring data structures +// for it in hash maps if not already present. + +template +ACE_INLINE void +TAO_Metrics_LocalCache:: +register_upcall_adapter (RtecScheduler::handle_t handle, + const char *name, + int is_hrt, + unsigned short incr_upcall_id) +{ + ACE_METRICS_CACHE_DATA_TYPE data = 0; + TAO_Metrics_Cache_Data * data_temp; + for (u_int i = 0; i < 2; ++i) + { + // Look for an existing data structure entry in each hash map. + if (monitor_maps_ [i].find (handle, data) != 0 + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // || (data_temp = data.addr ()) == 0) + || (data_temp = data) == 0) + { + // Create and bind if not there + ACE_NEW_MALLOC (data_temp, + (TAO_Metrics_Cache_Data *) this->allocator ()-> + malloc (sizeof (TAO_Metrics_Cache_Data)), + TAO_Metrics_Cache_Data); + data = data_temp; + + char * probe_name_temp; + ACE_NEW_MALLOC_ARRAY (probe_name_temp, + (char *) this->allocator ()-> + malloc (TAO_Metrics_Utils::METRICS_BUFSIZE), + char, + TAO_Metrics_Utils::METRICS_BUFSIZE); + data_temp->probe_name = probe_name_temp; + + ACE_OS::memset (data_temp-> + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_name.addr (), 0, TAO_Metrics_Utils::METRICS_BUFSIZE); + probe_name, 0, TAO_Metrics_Utils::METRICS_BUFSIZE); + + ACE_OS::strncpy (data_temp-> + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_name.addr (), name, TAO_Metrics_Utils::METRICS_BUFSIZE-1); + probe_name, name, TAO_Metrics_Utils::METRICS_BUFSIZE-1); + data_temp->probe.probe_name (data_temp-> + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_name.addr ()); + probe_name); + + data_temp->probe.mark_as_operation (); + data_temp->probe.set_hrt (is_hrt); + + data_temp->is_hrt = is_hrt; + + data_temp->probe.probe_id (this->upcall_adapter_count_ + + TAO_Metrics_Utils::METRICS_UPCALL_MONITOR_ADAPTER_ID_BASE); + + data_temp->missed_deadlines = 0; + data_temp->made_deadlines = 0; + data_temp->cancellations = 0; + + if (monitor_maps_ [i].rebind (handle, data) < 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::register_upcall_adapter" + " bind failed.\n")); +#endif + return; + } + + } + } + + if (incr_upcall_id) + { + this->increment_upcall_handle(); + } +} + + + +// Registers a base metrics probe, allocates monitoring data structures +// for it in hash maps, returns a handle to it. +template +ACE_INLINE RtecScheduler::handle_t +TAO_Metrics_LocalCache:: +register_base_metrics (const char *name, + TAO_Metrics_Utils::Base_Metrics_Type bmt, + unsigned short incr_base_id) +{ + ACE_METRICS_CACHE_DATA_BASE_TYPE base_data = 0; + TAO_Metrics_Cache_Data_Base * base_data_temp = 0; + RtecScheduler::handle_t handle = + this->next_base_metrics_handle_++; + + for (u_int i = 0; i < 2; ++i) + { + // Look for an existing data structure entry in each hash map. + if (base_monitor_maps_ [i].find (handle, base_data) != 0 + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // || (base_data_temp = base_data.addr ()) == 0) + || (base_data_temp = base_data) == 0) + { + // Create and bind if not there + ACE_NEW_MALLOC_RETURN (base_data_temp, + (TAO_Metrics_Cache_Data_Base *) + this->allocator ()->malloc + (sizeof (TAO_Metrics_Cache_Data_Base)), + TAO_Metrics_Cache_Data_Base, + RtecScheduler::handle_t (-1)); + base_data = base_data_temp; + + char * probe_name_temp; + ACE_NEW_MALLOC_ARRAY_RETURN (probe_name_temp, + (char *) this->allocator ()->malloc + (TAO_Metrics_Utils::METRICS_BUFSIZE), + char, + TAO_Metrics_Utils::METRICS_BUFSIZE, + RtecScheduler::handle_t (-1)); + base_data_temp->probe_name = probe_name_temp; + + ACE_OS::memset (base_data_temp-> + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_name.addr (), 0, TAO_Metrics_Utils::METRICS_BUFSIZE); + probe_name, 0, TAO_Metrics_Utils::METRICS_BUFSIZE); + ACE_OS::strncpy (base_data_temp-> + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_name.addr (), name, TAO_Metrics_Utils::METRICS_BUFSIZE-1); + probe_name, name, TAO_Metrics_Utils::METRICS_BUFSIZE-1); + base_data_temp->probe.probe_name (base_data_temp-> + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // probe_name.addr ()); + probe_name); + + switch (bmt) + { + case TAO_Metrics_Utils::SCHED: + base_data_temp-> + probe.probe_id (this->sched_count_ + + TAO_Metrics_Utils::METRICS_SCHED_PROBE_ID_BASE); + break; + case TAO_Metrics_Utils::QUO: + base_data_temp-> + probe.probe_id (this->quo_count_ + + TAO_Metrics_Utils::METRICS_QUO_PROBE_ID_BASE); + break; + case TAO_Metrics_Utils::TNS: + base_data_temp-> + probe.probe_id (this->tns_count_ + + TAO_Metrics_Utils::METRICS_TNS_PROBE_ID_BASE); + break; + case TAO_Metrics_Utils::TEEC: + base_data_temp-> + probe.probe_id (this->teec_count_ + + TAO_Metrics_Utils::METRICS_TEEC_PROBE_ID_BASE); + break; + case TAO_Metrics_Utils::RTARM: // treat RTARM as the default case + default: + base_data_temp-> + probe.probe_id (this->rtarm_count_ + + TAO_Metrics_Utils::METRICS_RTARM_PROBE_ID_BASE); + break; + } + + if (base_monitor_maps_ [i].rebind (handle, base_data) < 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::register_base_metrics" + " bind failed.\n")); +#endif + } + + } + } + + if (incr_base_id == 1) + { + increment_base_handle(bmt); + } + return handle; +} + + +// Inline: Records start time of an upcall. + +template +ACE_INLINE void +TAO_Metrics_LocalCache::report_upcall_start (RtecScheduler::handle_t handle) +{ + ACE_METRICS_CACHE_DATA_TYPE data = 0; + TAO_Metrics_Cache_Data * data_tmp = 0; + if (monitor_maps_ [supplier_index_].find (handle, data) < 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_start:\n" + "Could not find data for handle %d.\n", + handle)); +#endif + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // else if ((data_tmp = data.addr ()) == 0) + else if ((data_tmp = data) == 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_start:\n" + "Data pointer bound for handle %d is 0.\n", + handle)); +#endif + } + else + { + if (! this->interval_initialized_) + { + this->interval_initialized_ = 1; + ACE_hrtime_t hrtime_now = ACE_OS::gethrtime (); + ACE_High_Res_Timer::hrtime_to_tv (this->interval_start_, + hrtime_now); + this->interval_end_.set (this->interval_start_.sec (), + this->interval_start_.usec ()); + } + + // Take timeprobe stamp + data_tmp->probe.timeprobe (ACE_Metrics_Timeprobe:: + WORK_START); + } +} + + +// Inline: Records end time of an upcall, returns 0 if the deadline +// was made, 1 if the deadline was missed, or -1 if an error occurred. + +template +ACE_INLINE int +TAO_Metrics_LocalCache:: +report_upcall_stop (RtecScheduler::handle_t handle, + const ACE_Time_Value & deadline) +{ + // Capture current time value. + ACE_Time_Value current_time; + ACE_hrtime_t hrtime_now = ACE_OS::gethrtime (); + ACE_High_Res_Timer::hrtime_to_tv (current_time, hrtime_now); + + ACE_METRICS_CACHE_DATA_TYPE data = 0; + TAO_Metrics_Cache_Data * data_tmp = 0; + if (monitor_maps_ [supplier_index_].find (handle, data) < 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_stop:\n" + "Could not find data for handle %d.\n", + handle)); +#endif + return -1; + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // else if ((data_tmp = data.addr ()) == 0) + else if ((data_tmp = data) == 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_stop:\n" + "Data pointer bound for handle %d is 0.\n", + handle)); +#endif + return -1; + } + else + { + // Take timeprobe stamp + data_tmp->probe.timeprobe (ACE_Metrics_Timeprobe:: + WORK_STOP); + + this->interval_end_ = + data_tmp->probe.last_recorded_timestamp (); + + // Check time value, record whether we made or missed deadline. + if (current_time <= deadline || deadline == ACE_Time_Value::zero) + { + ++data_tmp->made_deadlines; + return 0; + } + else + { + ++data_tmp->missed_deadlines; +#if defined (METRICS_CACHE_DEBUG_OUTPUT_ENABLED) + ACE_DEBUG((LM_DEBUG, + "Missed Deadline: deadline = %u:%u, " + "current time = %u:%u\n", + deadline.sec (), + deadline.usec (), + current_time.sec (), + current_time.usec ())); +#endif + return 1; + } + } +} + +// Inline: Records cancelled upcall. + +template +ACE_INLINE void +TAO_Metrics_LocalCache:: +report_upcall_cancellation (RtecScheduler::handle_t handle) +{ + ACE_METRICS_CACHE_DATA_TYPE data = 0; + TAO_Metrics_Cache_Data * data_tmp = 0; + if (monitor_maps_ [supplier_index_].find (handle, data) < 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_cancellation:\n" + "Could not find data for handle %d.\n", + handle)); +#endif + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // else if ((data_tmp = data.addr ()) == 0) + else if ((data_tmp = data) == 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_cancellation:\n" + "Data pointer bound for handle %d is 0.\n", + handle)); +#endif + } + else + { + // Increment the cancellation count for that operation. + ++data_tmp->cancellations; + + // Update the metrics interval endpoint(s). + if (this->interval_initialized_) + { + ACE_hrtime_t hrtime_now = ACE_OS::gethrtime (); + ACE_High_Res_Timer::hrtime_to_tv (this->interval_end_, + hrtime_now); + } + else + { + this->interval_initialized_ = 1; + ACE_hrtime_t hrtime_now = ACE_OS::gethrtime (); + ACE_High_Res_Timer::hrtime_to_tv (this->interval_start_, + hrtime_now); + this->interval_end_.set (this->interval_start_.sec (), + this->interval_start_.usec ()); + } + } +} + + +// Inline: Records start time of a base metrics segment. + +template +ACE_INLINE void +TAO_Metrics_LocalCache::report_base_metrics_start (RtecScheduler::handle_t handle) +{ + ACE_METRICS_CACHE_DATA_BASE_TYPE base_data = 0; + TAO_Metrics_Cache_Data_Base * base_data_tmp = 0; + if (base_monitor_maps_ [supplier_index_].find (handle, base_data) < 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_start:\n" + "Could not find data for handle %d.\n", + handle)); +#endif + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // else if ((base_data_tmp = base_data.addr ()) == 0) + else if ((base_data_tmp = base_data) == 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_start:\n" + "Data pointer bound for handle %d is 0.\n", + handle)); +#endif + } + else + { + if (! this->interval_initialized_) + { + this->interval_initialized_ = 1; + ACE_hrtime_t hrtime_now = ACE_OS::gethrtime (); + ACE_High_Res_Timer::hrtime_to_tv (this->interval_start_, + hrtime_now); + this->interval_end_.set (this->interval_start_.sec (), + this->interval_start_.usec ()); + } + + // Take timeprobe stamp + base_data_tmp->probe.timeprobe (ACE_Metrics_Timeprobe:: + WORK_START); + } +} + + +// Inline: Records stop time of a base metrics segment. + +template +ACE_INLINE void +TAO_Metrics_LocalCache:: +report_base_metrics_stop (RtecScheduler::handle_t handle) +{ + ACE_METRICS_CACHE_DATA_BASE_TYPE base_data = 0; + TAO_Metrics_Cache_Data_Base * base_data_tmp = 0; + if (base_monitor_maps_ [supplier_index_].find (handle, base_data) < 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_stop:\n" + "Could not find data for handle %d.\n", + handle)); +#endif + return; + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // else if ((base_data_tmp = base_data.addr ()) == 0) + else if ((base_data_tmp = base_data) == 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_stop:\n" + "Data pointer bound for handle %d is 0.\n", + handle)); +#endif + return; + } + else + { + // Take timeprobe stamp + base_data_tmp->probe.timeprobe (ACE_Metrics_Timeprobe:: + WORK_STOP); + + this->interval_end_ = + base_data_tmp->probe.last_recorded_timestamp (); + } +} + +// Inline: Records suspend time of a base metrics segment. + +template +ACE_INLINE void +TAO_Metrics_LocalCache:: +report_base_metrics_suspend (RtecScheduler::handle_t handle) +{ + ACE_METRICS_CACHE_DATA_BASE_TYPE base_data = 0; + TAO_Metrics_Cache_Data_Base * base_data_tmp = 0; + if (base_monitor_maps_ [supplier_index_].find (handle, base_data) < 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_suspend:\n" + "Could not find data for handle %d.\n", + handle)); +#endif + return; + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // else if ((base_data_tmp = base_data.addr ()) == 0) + else if ((base_data_tmp = base_data) == 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_suspend:\n" + "Data pointer bound for handle %d is 0.\n", + handle)); +#endif + return; + } + else + { + // Take timeprobe stamp + base_data_tmp->probe.timeprobe (ACE_Metrics_Timeprobe:: + WORK_SUSPEND); + + this->interval_end_ = + base_data_tmp->probe.last_recorded_timestamp (); + } +} + + +// Inline: Records resume time of a base metrics segment. + +template +ACE_INLINE void +TAO_Metrics_LocalCache:: +report_base_metrics_resume (RtecScheduler::handle_t handle) +{ + ACE_METRICS_CACHE_DATA_BASE_TYPE base_data = 0; + TAO_Metrics_Cache_Data_Base * base_data_tmp = 0; + if (base_monitor_maps_ [supplier_index_].find (handle, base_data) < 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_resume:\n" + "Could not find data for handle %d.\n", + handle)); +#endif + return; + } + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // else if ((base_data_tmp = base_data.addr ()) == 0) + else if ((base_data_tmp = base_data) == 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::report_upcall_resume:\n" + "Data pointer bound for handle %d is 0.\n", + handle)); +#endif + return; + } + else + { + // Take timeprobe stamp + base_data_tmp->probe.timeprobe (ACE_Metrics_Timeprobe:: + WORK_RESUME); + + this->interval_end_ = + base_data_tmp->probe.last_recorded_timestamp (); + } +} + +template +void +TAO_Metrics_LocalCache:: +increment_base_handle(TAO_Metrics_Utils::Base_Metrics_Type bmt) +{ + switch (bmt) + { + case TAO_Metrics_Utils::SCHED: + ++this->sched_count_; + break; + case TAO_Metrics_Utils::QUO: + ++this->quo_count_; + break; + case TAO_Metrics_Utils::TNS: + ++this->tns_count_; + break; + case TAO_Metrics_Utils::TEEC: + ++this->teec_count_; + break; + case TAO_Metrics_Utils::RTARM: // treat RTARM as the default case + default: + ++this->rtarm_count_; + break; + } +} + +template +void +TAO_Metrics_LocalCache:: +increment_upcall_handle() +{ + ++this->upcall_adapter_count_; +} + +/////////////////////////////////////////// +// Class TAO_Metrics_ReportingLocalCache // +/////////////////////////////////////////// + + +// Default constructor. + +template +ACE_INLINE +TAO_Metrics_ReportingLocalCache:: +TAO_Metrics_ReportingLocalCache (u_long table_size, + u_long number_of_probes, + ALLOCATOR * alloc) + : TAO_Metrics_LocalCache (table_size, number_of_probes, alloc) +{ +} + + +// Registers probes with the logger. + +template +ACE_INLINE int +TAO_Metrics_ReportingLocalCache::register_probes (Metrics::QoSLogger_ptr logger) +{ + ACE_TRY_NEW_ENV + { + if (CORBA::is_nil (logger)) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::register_probes:\n" + "passed logger pointer was nil.\n")); +#endif + return -1; + } + + // Sequence to register probe names and ids with the logger. + Metrics::ProbeIdentity_Set probe_identities (this->probe_set_size_ * 2); + probe_identities.length (this->probe_set_size_ * 2); + + for (u_int i = 0; i < this->probe_set_size_; ++i) + { + // Batch up the enqueue ids and enqueue names so we + // can register them with the logger. + probe_identities [i].probe_id = + i + TAO_Metrics_Utils::METRICS_ENQUEUE_PROBE_ID_BASE; + probe_identities [i].probe_name = + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // (const char *) this->enqueue_names_.addr () [i].addr (); + (const char *) this->enqueue_names_ [i]; + probe_identities [i + this->probe_set_size_].probe_id = + i + TAO_Metrics_Utils::METRICS_DEQUEUE_PROBE_ID_BASE; + probe_identities [i + this->probe_set_size_].probe_name = + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // (const char *) this->dequeue_names_.addr () [i].addr (); + (const char *) this->dequeue_names_ [i]; + } + + logger->set_identities (probe_identities, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "TAO_Metrics_LocalCache::register_probes exception"); +#endif + return -1; + } + ACE_ENDTRY; + + return 0; +} + + +template +ACE_INLINE void +TAO_Metrics_ReportingLocalCache::output_statistics (Metrics::QoSLogger_ptr logger) +{ + if (metrics_enabled_) + { + if (CORBA::is_nil (logger)) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::output_statistics:\n" + "passed logger pointer was nil.\n")); +#endif + return; + } + + Metrics::TimeprobeParameter_Set data_set; + Metrics::QoSParameter_Set qos_set; + + // For each probe on the metrics consumer side, install data set, + // call probe's report_intervals method, and then uninstall data + // set. + + for (u_int j = 0; j < this->probe_set_size_; ++j) + { + { + // The cast is needed to convert the base class pointer + // (which we got from the (outer) based pointer addr () call) to a + // derived class pointer. + TAO_METRICS_TIMEPROBE_TYPE *probe_ptr = + ACE_dynamic_cast (TAO_METRICS_TIMEPROBE_TYPE *, + this-> + enqueue_probes_ +// Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers +// [this->consumer_index_].addr () [j].addr ()); + [this->consumer_index_] [j]); + if (probe_ptr) + { + probe_ptr->install_data_set (& data_set); + probe_ptr->report_intervals (); + probe_ptr->install_data_set (0); + probe_ptr->install_data_set (& data_set); + probe_ptr->report_intervals (); + probe_ptr->install_data_set (0); + } +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + else + { + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::output_statistics: " + "pointer static cast or down cast failed")); + } +#endif + } + } + + // Iterate over registered base metrics data and harvest those probes. + TAO_Metrics_Cache_Data_Base * base_data = 0; + METRICS_BASE_MONITOR_MAP_ITERATOR + base_iter (this->base_monitor_maps_ [this->consumer_index_]); + for (; + base_iter.done () == 0; + ++base_iter) + { +// Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers +// base_data = (*base_iter).int_id_.addr (); + base_data = (*base_iter).int_id_; + if (base_data) + { + base_data->probe.install_data_set (& data_set); + base_data->probe.report_intervals (); + base_data->probe.install_data_set (0); + } + } + + + // Iterate over registered upcall data and harvest those probes, and + // the aggregate QoS data too. + TAO_Metrics_Cache_Data * data = 0; + METRICS_MONITOR_MAP_ITERATOR + data_iter (this->monitor_maps_ [this->consumer_index_]); + for (u_long qos_length = 1; + data_iter.done () == 0; + ++data_iter, ++qos_length) + { +// Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers +// data = (*data_iter).int_id_.addr (); + data = (*data_iter).int_id_; + if (data) + { + data->probe.install_data_set (& data_set); + data->probe.report_intervals (); + data->probe.install_data_set (0); + + qos_set.length (qos_length); + qos_set [qos_length - 1].entry_point +// Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers +// = (const char *) data->probe_name.addr (); + = (const char *) data->probe_name; + qos_set [qos_length - 1].deadlines_made = data->made_deadlines; + qos_set [qos_length - 1].deadlines_missed = data->missed_deadlines; + qos_set [qos_length - 1].operations_cancelled = data->cancellations; + qos_set [qos_length - 1].is_hrt = data->is_hrt; + } + } + + // Then, give harvested data sets to the remote logger. + + Metrics::Time interval; + ACE_Time_Value interval_tv ((this->interval_initialized_) + ? (this->interval_end_ - this->interval_start_) + : ACE_Time_Value::zero); + ORBSVCS_Time::Time_Value_to_TimeT (interval, interval_tv); + + ACE_TRY_NEW_ENV + { + logger->log_timeprobe_data (data_set, interval, ACE_TRY_ENV); + ACE_TRY_CHECK; + + logger->log_aggregate_QoS (qos_set, interval, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "TAO_Metrics_LocalCache::output_statistics:" + " logger call failed\n"); +#endif + } + ACE_ENDTRY; + + // Finally, reset the metrics data on the consumer side, for the + // next round of logging. TBD - consider whether or not we should + // do this here, or make resetting an independent action. + this->reset_statistics (); + this->reset_base_statistics (); + } +} + + +// Registers an upcall adapter, allocates monitoring data structures +// for it in hash maps if not already present. + +template +ACE_INLINE void +TAO_Metrics_ReportingLocalCache:: +register_upcall_adapter (RtecScheduler::handle_t handle, + const char *name, + int is_hrt, + Metrics::QoSLogger_ptr logger) +{ + // Call the base class method: the wierd syntax is needed because + // MSVC++ was choking on the direct invocation using the this pointer. + TAO_Metrics_LocalCache *base_ptr = this; + const unsigned short incr_upcall_id = 0; + base_ptr->register_upcall_adapter (handle, name, is_hrt, incr_upcall_id); + + // Look for an existing data structure entry in the 0th hash map. + ACE_METRICS_CACHE_DATA_TYPE data = 0; + if (monitor_maps_ [0].find (handle, data) != 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::register_upcall_adapter" + " bind failed.\n")); +#endif + return; + } + + // Register upcall monitor adapter's name and id with the logger: + // allows registrations of the same adapter under different ids. + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (! CORBA::is_nil (logger) && data.addr () != 0) + if (! CORBA::is_nil (logger) && data != 0) + { + Metrics::ProbeIdentity_t probe_identity; + probe_identity.probe_id = this->upcall_adapter_count_ + + TAO_Metrics_Utils::METRICS_UPCALL_MONITOR_ADAPTER_ID_BASE; + probe_identity.probe_name = + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // (const char *) data.addr ()->probe_name.addr (); + (const char *) data->probe_name; + + // Increment the probe id now that we're finished using it. + this->increment_upcall_handle(); + + ACE_TRY_NEW_ENV + { + logger->set_identity (probe_identity, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "TAO_Metrics_LocalCache::" + "register_upcall_adapter:" + " logger call failed\n"); +#endif + } + ACE_ENDTRY; + } +} + +// Registers a base metrics probe, allocates monitoring data structures +// for it in hash maps, returns a handle to it. +template +ACE_INLINE RtecScheduler::handle_t +TAO_Metrics_ReportingLocalCache:: +register_base_metrics (const char *name, + TAO_Metrics_Utils::Base_Metrics_Type bmt, + Metrics::QoSLogger_ptr logger) +{ + // Call the base class method and grab the handle it returns; + TAO_Metrics_LocalCache *base_ptr = this; + const unsigned short incr_probe_id = 0; + RtecScheduler::handle_t handle = base_ptr->register_base_metrics (name, bmt, incr_probe_id); + + // If there was an error, just return. + if (handle == 0) + { + return handle; + } + + // Look for an existing data structure entry in each hash map. + ACE_METRICS_CACHE_DATA_BASE_TYPE base_data = 0; + if (base_monitor_maps_ [0].find (handle, base_data) != 0) + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::register_upcall_adapter" + " bind failed.\n")); +#endif + return 0; + } + + // Register base metrics segment name and id with the logger. + + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // if (! CORBA::is_nil (logger) && base_data.addr () != 0) + if (! CORBA::is_nil (logger) && base_data != 0) + { + Metrics::ProbeIdentity_t probe_identity; + + switch (bmt) + { + case TAO_Metrics_Utils::SCHED: + probe_identity.probe_id = this->sched_count_ + + TAO_Metrics_Utils::METRICS_SCHED_PROBE_ID_BASE; + break; + case TAO_Metrics_Utils::QUO: + probe_identity.probe_id = this->quo_count_ + + TAO_Metrics_Utils::METRICS_QUO_PROBE_ID_BASE; + break; + case TAO_Metrics_Utils::TNS: + probe_identity.probe_id = this->tns_count_ + + TAO_Metrics_Utils::METRICS_TNS_PROBE_ID_BASE; + break; + case TAO_Metrics_Utils::TEEC: + probe_identity.probe_id = this->teec_count_ + + TAO_Metrics_Utils::METRICS_TEEC_PROBE_ID_BASE; + break; + case TAO_Metrics_Utils::RTARM: // treat RTARM as the default case + default: + probe_identity.probe_id = this->rtarm_count_ + + TAO_Metrics_Utils::METRICS_RTARM_PROBE_ID_BASE; + break; + } + + // Now increment the handle. + increment_base_handle(bmt); + + probe_identity.probe_name = + // Modified by BRM. Not sure what the equivalent is for ACE_Based_Pointers + // (const char *) base_data.addr ()->probe_name.addr (); + (const char *) base_data->probe_name; + + ACE_TRY_NEW_ENV + { + logger->set_identity (probe_identity, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { +#if defined (METRICS_CACHE_ERROR_OUTPUT_ENABLED) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "TAO_Metrics_LocalCache::" + "register_base_metrics:" + " logger call failed\n"); +#endif + } + ACE_ENDTRY; + } + + return handle; +} + + +#endif /* METRICS_LOCAL_CACHE_T_I */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.cpp b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.cpp new file mode 100644 index 00000000000..b4c4ca3b4cb --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.cpp @@ -0,0 +1,892 @@ +// $Id$ + +#include "Metrics_Logger.h" +#include "ace/Auto_Ptr.h" + +ACE_RCSID(Metrics_Logger, Metrics_Logger, "$Id$") + +const int OPEN_CLOSE_BANNER_CYCLE = 4; + + +////////////////////////////// +// class TAO_Metrics_Logger // +////////////////////////////// + +// Default constructor. + +TAO_Metrics_Logger::TAO_Metrics_Logger (int generate_events, + int generate_log, + int generate_export_file, + const char *log_filename) + : generate_events_ (generate_events), +#ifdef VXWORKS + generate_log_ (1), + log_filename_ ("logger.txt"), +#else + generate_log_ (generate_log), + log_filename_ (log_filename), +#endif + generate_totals_(0), + generate_export_file_(generate_export_file), + log_started_ (0), + log_file_ (stdout), + export_file_(stdout), + saveFileCnt_(0) +{ +#ifdef VXWORKS + taskPrioritySet( taskIdSelf(), 145 ); +#endif + +#if defined (METRICS_LOGGER_SENDS_EVENTS) + if (this->generate_events_) + { + // Connect the underlying DOVE event supplier. + if (this->dove_supplier_.connect () < 0) + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, "failed to connect DOVE event supplier\n")); +#endif + this->generate_events_ = 0; + } + } +#endif /* METRICS_LOGGER_SENDS_EVENTS */ + + if (generate_log_) + { + if (log_filename_) + { + log_file_ = ACE_OS::fopen (log_filename_, "w+"); + if (log_file_ == NULL) + { + generate_log_ = 0; +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "Logger failed to open log file %s\n", + log_filename_)); +#endif + return; + } + + if (generate_export_file_) + { + export_file_ = ACE_OS::fopen ("remote_logger_export.excel", "w+"); + if (export_file_ == NULL) + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, "Logger failed to open log file %s\n", log_filename_)); +#endif + return; + } + } + log_started_ = 1; + } + + // Write a start of logging session message. + time_t current_time = ACE_OS::time (); + ACE_OS::fprintf (log_file_, + "\n\nTAO_Metrics Metrics Logging Session: %s\n\n", + ACE_OS::ctime (& current_time)); + + ACE_OS::fprintf (export_file_, + "\n\nTAO_Metrics Metrics Logging Session: %s\n\n", + ACE_OS::ctime (& current_time)); + if (log_filename_) + { + ACE_OS::fflush (log_file_); + ACE_OS::fflush (export_file_); +// ACE_OS::fclose (log_file_); + } + } +} + + +// Destructor. + +TAO_Metrics_Logger::~TAO_Metrics_Logger () +{ + if (generate_log_) + { + if (log_filename_) + { +// log_file_ = ACE_OS::fopen (log_filename_, "a+"); + } + + ACE_OS::fprintf (log_file_, "\n\n"); + + ACE_OS::fflush (log_file_); + + ACE_OS::fprintf (export_file_, "\n\n"); + ACE_OS::fflush (export_file_); + + if (log_filename_) + { +// ACE_OS::fclose (log_file_); + } + } + +#if defined (METRICS_LOGGER_SENDS_EVENTS) + if (this->generate_events_) + { + this->dove_supplier_.disconnect (); + } +#endif /* METRICS_LOGGER_SENDS_EVENTS */ +} + + +// Active object loop for processing logged data. + +int +TAO_Metrics_Logger::svc (void) +{ + ACE_Message_Block *mb; + + // Loop forever. + while (1) + if (this->getq (mb) < 0) + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "(%P|%t) getq failed in TAO_Metrics_Logger::svc")); +#endif + return -1; + } + else if (! mb) + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "(%P|%t) null message block pointer in TAO_Metrics_Logger::svc")); +#endif + return -1; + } + else if (! mb->rd_ptr ()) + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "(%P|%t) null message block pointer in TAO_Metrics_Logger::svc")); +#endif + return -1; + } + else + { + // Process message. + + TAO_Metrics_Logger_Data *data = (TAO_Metrics_Logger_Data *) mb->rd_ptr (); + switch (data->data_type_) + { + case TAO_Metrics_Logger_Data::QOS_TYPE: + this->process_aggregate_QoS (*data->qos_params_, data->interval_); + delete data; + delete mb; + break; + + case TAO_Metrics_Logger_Data::TIMEPROBE_TYPE: + this->process_timeprobe_data (*data->timeprobe_params_, data->interval_); + delete data; + delete mb; + break; + + case TAO_Metrics_Logger_Data::BANNER_TYPE: + this->process_banner (data->banner_); + delete data; + delete mb; + break; + + default: +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "(%P|%t) unrecognized data type in TAO_Metrics_Logger::svc")); +#endif + return -1; + } + } + +// Modified by BAP. Remove unreachable code. +// return 0; +} + + +// Sends a banner to be written to the log file and to the visualization browser. + +void +TAO_Metrics_Logger::send_banner (const char *banner, + CORBA::Environment &ACE_TRY_ENV) +{ + //Added to remove Linux warning (Boeing Extension) + ACE_UNUSED_ARG(ACE_TRY_ENV); + + // Package up the data and put it on the task queue. + + TAO_Metrics_Logger_Data *data; + ACE_NEW (data, + TAO_Metrics_Logger_Data (TAO_Metrics_Logger_Data::BANNER_TYPE)); + ACE_NEW (data->banner_, char [ACE_OS::strlen (banner) + 1]); + ACE_OS::strcpy (data->banner_, banner); + + ACE_Message_Block *mb; + ACE_NEW (mb, + ACE_Message_Block ((char *) data, + sizeof (TAO_Metrics_Logger_Data))); + + if (this->putq (mb) < 0) + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_Logger::send_banner putq failed")); +#endif + } +} + +void +TAO_Metrics_Logger::process_banner (const char *banner) +{ + if (this->generate_log_) + { + if (log_filename_) + { +// log_file_ = ACE_OS::fopen (log_filename_, "a+"); + } + + ACE_OS::fprintf (log_file_, + "%s\n", banner); + ACE_OS::fprintf (export_file_, + "%s\n", banner); + if (log_filename_) + { + ACE_OS::fflush (log_file_); + ACE_OS::fflush (export_file_); + + // Close and then reopen the file. We can't afford to open & close all of the time. + if (( saveFileCnt_++ % OPEN_CLOSE_BANNER_CYCLE) == 0 ) + { + ACE_OS::fclose (log_file_); + log_file_ = ACE_OS::fopen (log_filename_, "a+"); + + ACE_OS::fclose (export_file_); + export_file_ = ACE_OS::fopen ("remote_logger_export.excel", "a+"); + } + } + } +} + + +// Reports the aggregate QoS information for all operations +// to the passed QoS logger. + +void +TAO_Metrics_Logger::log_aggregate_QoS (const Metrics::QoSParameter_Set & qos_params, + Metrics::Time interval, + CORBA::Environment &ACE_TRY_ENV) +{ +// This is a temporary patch to eliminate this data from the log. It was done to bypass a long rebuild +// that would have been required otherwise. Remove this patch later. Brian Mendel + //Added to remove Linux warning (Boeing Extension) + ACE_UNUSED_ARG(ACE_TRY_ENV); + + // Package up the data and put it on the task queue. +#if 0 + TAO_Metrics_Logger_Data *data; + ACE_NEW (data, + TAO_Metrics_Logger_Data (TAO_Metrics_Logger_Data::QOS_TYPE, + interval)); + ACE_NEW (data->qos_params_, + Metrics::QoSParameter_Set (qos_params)); + + ACE_Message_Block *mb; + ACE_NEW (mb, + ACE_Message_Block ((char *) data, + sizeof (TAO_Metrics_Logger_Data))); + + if (this->putq (mb) < 0) + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_Logger::log_aggregate_QoS putq failed")); +#endif + } +#endif +} + + +// Processes the aggregate QoS information for all operations +// to the passed QoS logger. + +void +TAO_Metrics_Logger::process_aggregate_QoS (const Metrics::QoSParameter_Set & qos_params, + Metrics::Time interval) +{ + //Added to remove Linux warning (Boeing Extension) + ACE_UNUSED_ARG(interval); + + if (this->generate_log_) + { + if (log_filename_) + { +// log_file_ = ACE_OS::fopen (log_filename_, "a+"); + } + + ACE_OS::fprintf (log_file_, + "\nName missed made cancelled\n"); + + ACE_OS::fprintf (export_file_, + "\n\n Name \t missed \t made \t cancelled\n"); + } + +#if defined (METRICS_LOGGER_SENDS_EVENTS) + if (this->generate_events_) + { + this->qos_data_.hrt_deadlines_missed = 0; + this->qos_data_.hrt_deadlines_made = 0; + this->qos_data_.hrt_operations_cancelled = 0; + this->qos_data_.srt_deadlines_missed = 0; + this->qos_data_.srt_deadlines_made = 0; + this->qos_data_.srt_operations_cancelled = 0; + } +#endif /* METRICS_LOGGER_SENDS_EVENTS */ + + for (u_long i = 0; i < qos_params.length (); ++i) + { +#if defined (METRICS_LOGGER_SENDS_EVENTS) + if (this->generate_events_) + { + if (qos_params [i].is_hrt) + { + this->qos_data_.hrt_deadlines_missed += + qos_params [i].deadlines_missed; + this->qos_data_.hrt_deadlines_made += + qos_params [i].deadlines_made; + this->qos_data_.hrt_operations_cancelled += + qos_params [i].operations_cancelled; + } + else + { + this->qos_data_.srt_deadlines_missed += + qos_params [i].deadlines_missed; + this->qos_data_.srt_deadlines_made += + qos_params [i].deadlines_made; + this->qos_data_.srt_operations_cancelled += + qos_params [i].operations_cancelled; + } + } +#endif /* METRICS_LOGGER_SENDS_EVENTS */ + + if (this->generate_log_) + { + ACE_OS::fprintf (log_file_, + "%-50s %8lu %8lu %8lu\n", + (const char *)qos_params [i].entry_point, + qos_params [i].deadlines_missed, + qos_params [i].deadlines_made, + qos_params [i].operations_cancelled); + ACE_OS::fprintf (export_file_, + " %s \t %lu \t %lu \t %lu\n", + (const char *)qos_params [i].entry_point, + qos_params [i].deadlines_missed, + qos_params [i].deadlines_made, + qos_params [i].operations_cancelled); + } + } + +#if defined (METRICS_LOGGER_SENDS_EVENTS) + if (this->generate_events_) + { + // Push an event to the visualization browser. + CORBA::Any any; + + ACE_TRY_NEW_ENV + { + any.replace (Metrics::_tc_QoSData, &qos_data_, 0, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "TAO_Metrics_Logger::process_aggregate_QoS"); +#endif + return; + } + ACE_ENDTRY; + + this->dove_supplier_.notify (any); + } +#endif /* METRICS_LOGGER_SENDS_EVENTS */ + + if (this->generate_log_) + { + if (log_filename_) + { + ACE_OS::fflush (log_file_); +// ACE_OS::fclose (log_file_); + } + } +} + + +// Binds the names of various timeprobes to their identifiers so +// that ids alone can be used (for efficiency) in passing data. + +void +TAO_Metrics_Logger::set_identities (const Metrics::ProbeIdentity_Set & + probe_identities, + CORBA::Environment &ACE_TRY_ENV) +{ + for (u_long i = 0; i < probe_identities.length (); ++i) + { + this->set_identity (probe_identities [i], ACE_TRY_ENV); + ACE_CHECK; + } +} + +void +TAO_Metrics_Logger::set_identity (const Metrics::ProbeIdentity_t & probe_identity, + CORBA::Environment &ACE_TRY_ENV) +{ + // Look up the existing name that is bound, creating one if there is + // not one there already. + CORBA::String_var *name = 0; + if (probe_name_map_.find (probe_identity.probe_id, name) != 0 + || name == 0) + { + ACE_NEW_THROW_EX (name, + CORBA::String_var (probe_identity.probe_name), + CORBA::NO_MEMORY ()); + ACE_CHECK; + + // What is this used for? BRM + auto_ptr name_ptr (name); + + if (probe_name_map_.rebind (probe_identity.probe_id, name) < 0) + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, "TAO_Metrics_Logger::set_identity bind failed.\n")); +#endif + return; + } + + // DEBUG + const char * name_cstr = name->in (); + ACE_DEBUG ((LM_DEBUG, + "Logger registered name [%s] with id [%u]\n", + name_cstr, probe_identity.probe_id)); + + name_ptr.release (); + } + else + { + // DEBUG + const char * old_name_cstr = name->in (); + + // Unconditionally set the name to the new name. + *name = probe_identity.probe_name; + + // DEBUG + const char * new_name_cstr = name->in (); + ACE_DEBUG ((LM_DEBUG, + "Logger CHANGED name from [%s] to [%s] for id [%u]\n", + old_name_cstr, new_name_cstr, probe_identity.probe_id)); + } +} + + +// Reports timeprobe data collected since last run. + +void +TAO_Metrics_Logger::log_timeprobe_data (const Metrics::TimeprobeParameter_Set & + timeprobe_params, + Metrics::Time interval, + CORBA::Environment &ACE_TRY_ENV) +{ + //Added to remove Linux warning (Boeing Extension) + ACE_UNUSED_ARG(ACE_TRY_ENV); + + // Package up the data and put it on the task queue. + + TAO_Metrics_Logger_Data *data; + ACE_NEW (data, + TAO_Metrics_Logger_Data (TAO_Metrics_Logger_Data::TIMEPROBE_TYPE, + interval)); + ACE_NEW (data->timeprobe_params_, + Metrics::TimeprobeParameter_Set (timeprobe_params)); + + ACE_Message_Block *mb; + ACE_NEW (mb, + ACE_Message_Block ((char *) data, + sizeof (TAO_Metrics_Logger_Data))); + + if (this->putq (mb) < 0) + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_Logger::log_timeprobe_data putq failed")); +#endif + } +} + + +// Processes timeprobe data collected since last run. +void +TAO_Metrics_Logger::process_timeprobe_data (const Metrics::TimeprobeParameter_Set & timeprobe_params, + Metrics::Time interval) +{ + if (this->generate_log_) + { + if (log_filename_) + { + // log_file_ = ACE_OS::fopen (log_filename_, "a+"); + } + + ACE_OS::fprintf (log_file_, + "\n\n\n" + "Interval (usec): %9lu \n\n" + "Probe elapsed_time(usec) Start Time (usecs) Stop Time (usec)\n\n", + // Modified by BAP. This really should be corrected since we are truncating the interval here. + // We can get away with it here for now since the intervals are small enough to not roll over. + (u_long) ACE_U64_TO_U32(interval)/10 ); + + ACE_OS::fprintf (export_file_, + "\n\n\n" + "Interval (usec): \t %9lu \t \n\n" + "Probe \t elapsed_time(usec) \tStart Time (usecs) \t Stop Time (usec)\n\n", + // Modified by BAP. This really should be corrected since we are truncating the interval here. + // We can get away with it here for now since the intervals are small enough to not roll over. + (u_long) ACE_U64_TO_U32(interval)/10 ); + } + +#if defined (METRICS_LOGGER_SENDS_EVENTS) + Metrics::Time queue_time = 0; + Metrics::Time hrt_op_time = 0; + Metrics::Time srt_op_time = 0; +#endif /* METRICS_LOGGER_SENDS_EVENTS */ + + for (u_long i = 0; i < timeprobe_params.length (); ++i) + { +#if defined (METRICS_LOGGER_SENDS_EVENTS) + if (! timeprobe_params [i].is_full_interval) + { + if (timeprobe_params [i].is_operation) + { + if (timeprobe_params [i].is_hrt) + { + hrt_op_time += timeprobe_params [i].interval; + } + else + { + srt_op_time += timeprobe_params [i].interval; + } + } + else + { + queue_time += timeprobe_params [i].interval; + } + } +#endif /* METRICS_LOGGER_SENDS_EVENTS */ + + if (this->generate_log_) + { + // Look up the name of the probe in the hash map. + // If successful, use the name, and if not just use the probe id. + CORBA::String_var *probe_name = 0; + ASYS_TCHAR format_spec[255]; + ASYS_TCHAR export_spec[255]; + + if (probe_name_map_.find (timeprobe_params [i].probe_id, probe_name) == 0 + && probe_name != 0) + { + if (timeprobe_params [i].cross_thread_probe && + timeprobe_params [i].is_full_interval) + { + if (generate_totals_) + { +#if defined (ACE_LACKS_LONGLONG_T) + // This needs to be fixed for platforms that do not have 64 bit support. This will result + // in overruns as currently written + ACE_OS::fprintf (log_file_, + " %-40s (total) %20lu %20lu %20lu *** Cross Thread Event ***\n", + (const char *) *probe_name, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].interval)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].start_event_time)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].stop_event_time)/10); + ACE_OS::fprintf (export_file_, + " %s (total) \t %lu \t %lu \t %lu \t ***Cross Thread Event***\n", + (const char *) *probe_name, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].interval)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].start_event_time)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].stop_event_time)/10); +#else + // Build up the format specifiers since the specifier or not portable + ACE_OS::strcpy(format_spec, " %-40s (total) "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " *** Cross Thread Event ***\n"); + + ACE_OS::strcpy(export_spec, " %-40s (total) \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t*** Cross Thread Event ***\n"); + + ACE_OS::fprintf (log_file_, + format_spec, + (const char *) *probe_name, + timeprobe_params [i].interval / 10, + timeprobe_params [i].start_event_time / 10, + timeprobe_params [i].stop_event_time / 10); + ACE_OS::fprintf (export_file_, + export_spec, + (const char *) *probe_name, + timeprobe_params [i].interval / 10, + timeprobe_params [i].start_event_time / 10, + timeprobe_params [i].stop_event_time / 10); +#endif + } + } + else + { +#if defined (ACE_LACKS_LONGLONG_T) + // This needs to be fixed for platforms that do not have 64 bit support. This will result + // in overruns as currently written + ACE_OS::fprintf (log_file_, + " %-40s %20lu %20lu %20lu *** Cross Thread Event ***\n", + (const char *) *probe_name, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].interval)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].start_event_time)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].stop_event_time)/10); + ACE_OS::fprintf (export_file_, + " %s \t %lu \t %lu \t %lu \t ***Cross Thread Event***\n", + (const char *) *probe_name, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].interval)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].start_event_time)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].stop_event_time)/10); +#else + // Build up the format specifiers since the specifier or not portable + ACE_OS::strcpy(format_spec, " %-40s "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " *** Cross Thread Event ***\n"); + + ACE_OS::strcpy(export_spec, " %-40s \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t *** Cross Thread Event ***\n"); + + ACE_OS::fprintf (log_file_, + format_spec, + (const char *) *probe_name, + timeprobe_params [i].interval / 10, + timeprobe_params [i].start_event_time / 10, + timeprobe_params [i].stop_event_time / 10); + ACE_OS::fprintf (export_file_, + export_spec, + (const char *) *probe_name, + timeprobe_params [i].interval / 10, + timeprobe_params [i].start_event_time / 10, + timeprobe_params [i].stop_event_time / 10); +#endif + } + + } + else + { + if (timeprobe_params [i].cross_thread_probe && + timeprobe_params [i].is_full_interval) + { + if (generate_totals_) +#if defined (ACE_LACKS_LONGLONG_T) + ACE_OS::fprintf (log_file_, + " [id (total): %8lu] %9lu %9lu %9lu *** Cross Thread Event ***\n", + timeprobe_params [i].probe_id, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].interval)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].start_event_time)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].stop_event_time)/10); + ACE_OS::fprintf (export_file_, + " [id (total): %lu] \t %lu \t %lu \t %lu \t ***Cross Thread Event***\n", + timeprobe_params [i].probe_id, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].interval)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].start_event_time)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].stop_event_time)/10); +#else + // Build up the format specifiers since the specifier or not portable + ACE_OS::strcpy(format_spec, " [id (total): %8lu] "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " *** Cross Thread Event ***\n"); + + ACE_OS::strcpy(export_spec, " [id (total): %8lu] \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t*** Cross Thread Event ***\n"); + + if (probe_name == 0) + { + ACE_DEBUG((LM_DEBUG, "Found a probe with id: %d with no name\n", timeprobe_params [i].probe_id)); + } + else + { + ACE_OS::fprintf (log_file_, + format_spec, + (const char *) *probe_name, + timeprobe_params [i].interval / 10, + timeprobe_params [i].start_event_time / 10, + timeprobe_params [i].stop_event_time / 10); + ACE_OS::fprintf (export_file_, + export_spec, + (const char *) *probe_name, + timeprobe_params [i].interval / 10, + timeprobe_params [i].start_event_time / 10, + timeprobe_params [i].stop_event_time / 10); + } +#endif + } + else +#if defined (ACE_LACKS_LONGLONG_T) + ACE_OS::fprintf (log_file_, + " [id: %14lu] %9lu %9lu %9lu \n", + timeprobe_params [i].probe_id, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].interval)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].start_event_time)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].stop_event_time)/10); + ACE_OS::fprintf (export_file_, + " [id: %lu] \t %lu \t %lu \t %lu\n", + timeprobe_params [i].probe_id, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].interval)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].start_event_time)/10, + (u_long) ACE_U64_TO_U32(timeprobe_params [i].stop_event_time)/10); +#else + // Build up the format specifiers since the specifier or not portable + ACE_OS::strcpy(format_spec, " [id: %14lu] "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " "); + ACE_OS::strcat(format_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(format_spec, " *** Cross Thread Event ***\n"); + + ACE_OS::strcpy(export_spec, " [id: %lu] \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " \t "); + ACE_OS::strcat(export_spec, ACE_UINT64_FORMAT_SPECIFIER); + ACE_OS::strcat(export_spec, " *** Cross Thread Event ***\n"); + + if (probe_name == 0) + { + ACE_DEBUG((LM_DEBUG, "Found a probe with id: %d with no name\n", timeprobe_params [i].probe_id)); + } + else + { + ACE_OS::fprintf (log_file_, + format_spec, + (const char *) *probe_name, + timeprobe_params [i].interval / 10, + timeprobe_params [i].start_event_time / 10, + timeprobe_params [i].stop_event_time / 10); + ACE_OS::fprintf (export_file_, + export_spec, + (const char *) *probe_name, + timeprobe_params [i].interval / 10, + timeprobe_params [i].start_event_time / 10, + timeprobe_params [i].stop_event_time / 10); + } +#endif + + } + } // End if (this->generate_log_) + } + +#if defined (METRICS_LOGGER_SENDS_EVENTS) + if (this->generate_events_) + { + CORBA::Any any; + + util_data_.hrt_op_utilization = + ACE_static_cast ( + CORBA::Double, + ACE_UINT64_DBLCAST_ADAPTER (hrt_op_time)) + / ACE_static_cast ( + CORBA::Double, + ACE_UINT64_DBLCAST_ADAPTER (interval)); + + util_data_.srt_op_utilization = + ACE_static_cast ( + CORBA::Double, + ACE_UINT64_DBLCAST_ADAPTER (srt_op_time)) + / ACE_static_cast ( + CORBA::Double, + ACE_UINT64_DBLCAST_ADAPTER (interval)); + + util_data_.queue_utilization = + ACE_static_cast ( + CORBA::Double, + ACE_UINT64_DBLCAST_ADAPTER (queue_time)) + / ACE_static_cast ( + CORBA::Double, + ACE_UINT64_DBLCAST_ADAPTER (interval)); + + ACE_TRY_NEW_ENV + { + any.replace (Metrics::_tc_UtilData, &util_data_, 0, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { +#if defined (METRICS_LOGGER_ERROR_OUTPUT_ENABLED) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "TAO_Metrics_Logger::process_aggregate_QoS"); +#endif + return; + } + ACE_ENDTRY; + + this->dove_supplier_.notify (any); + } +#endif /* METRICS_LOGGER_SENDS_EVENTS */ + + if (this->generate_log_) + { + if (log_filename_) + { + ACE_OS::fflush (log_file_); + ACE_OS::fflush (export_file_); +// ACE_OS::fclose (log_file_); + } + } +} + + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +// Already instantiated in Transport_Mux_Strategy ... otherwise VxWorks gets dual +// definition link error +//template class ACE_Equal_To; +// The below template already instantiated in ../ace/Funchtor.h +// template class ACE_Hash; +template class ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Base_Ex, ACE_Equal_To, ACE_Null_Mutex>; +template class ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex>; +template class ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex>; +template class ACE_Hash_Map_Entry; +#elif defined(ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Equal_To +//#pragma instantiate ACE_Hash +#pragma instantiate ACE_Hash_Map_Manager_Ex, ACE_Equal_To, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex, ACE_Equal_To, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex, ACE_Equal_To, ACE_Null_Mutex> +#pragma instantiate ACE_Hash_Map_Entry +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.h b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.h new file mode 100644 index 00000000000..1d63dbbdeaf --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.h @@ -0,0 +1,217 @@ +// $Id$ + +#ifndef METRICS_LOGGER_H +#define METRICS_LOGGER_H + +#if ! defined (VXWORKS) + +// Comment out both of these to disable output +# define METRICS_LOGGER_ERROR_OUTPUT_ENABLED +# define METRICS_LOGGER_DEBUG_OUTPUT_ENABLED + +#endif /* ! VXWORKS */ + +// Comment this out to disable event passing +#define TAO_METRICS_LOGGER_SENDS_EVENTS + +#include "ace/OS.h" +#include "ace/Task.h" +#include "ace/Singleton.h" + +#include "tao/TAO.h" + +#include "orbsvcs/Time_Utilities.h" +#include "orbsvcs/MetricsS.h" +#include "orbsvcs/RtecEventCommS.h" + +#include "Metrics_Utils.h" + +#if defined (METRICS_LOGGER_SENDS_EVENTS) +#include "MetricsC.h" +#include "DOVE_Supplier.h" +#endif /* METRICS_LOGGER_SENDS_EVENTS */ + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class TAO_ORBSVCS_Export TAO_Metrics_Logger_Data +{ + // = TITLE + // Defines a class for logger data. + // + // = DESCRIPTION + // This class is used to transfer metrics data to the logger class. +public: + + enum LOGGER_DATA_TYPE {QOS_TYPE, TIMEPROBE_TYPE, BANNER_TYPE}; + + TAO_Metrics_Logger_Data (LOGGER_DATA_TYPE data_type, + Metrics::Time interval = ORBSVCS_Time::zero ()) + : data_type_ (data_type), + interval_ (interval), + qos_params_ (0), + timeprobe_params_ (0), + banner_ (0) + { + } + // Constructor. + + ~TAO_Metrics_Logger_Data () + { + delete qos_params_; + delete timeprobe_params_; + delete banner_; + } + // Destructor. + + LOGGER_DATA_TYPE data_type_; + // Identifies type of data. + + Metrics::Time interval_; + // Time interval over which data were collected. + + Metrics::QoSParameter_Set * qos_params_; + // Points to a QoS parameter data set. + + Metrics::TimeprobeParameter_Set * timeprobe_params_; + // Points to a timeprobe data set. + + char * banner_; + // Banner for entry in the log and/or visualization stream. +}; + + + +class TAO_ORBSVCS_Export TAO_Metrics_Logger + : public ACE_Task, public POA_Metrics::QoSLogger + // = TITLE + // This class implements a Metrics QoS logger. + // + // = DESCRIPTION + // This class allows clients to log monitored QoS. +{ +public: + + typedef ACE_Hash_Map_Manager_Ex, + ACE_Equal_To, + ACE_Null_Mutex> PROBE_NAME_MAP; + // Type of map used for O(1) lookup of probe names. + + typedef ACE_Hash_Map_Entry PROBE_NAME_MAP_ENTRY; + // Type of map used for O(1) lookup of RT_Infos by their handles. + + TAO_Metrics_Logger (int generate_events = 0, int generate_log = 0, int generate_export_file = 1, const char *log_filename = 0); + // Default constructor. + + virtual ~TAO_Metrics_Logger (); + // Destructor. + + virtual int svc (void); + // Active object loop for processing logged data. + + void send_banner (const char *banner, + CORBA::Environment &ACE_TRY_ENV = + CORBA::Environment::default_environment ()); + // Sends a banner to be written to the log file and to the visualization browser. + + void process_banner (const char *banner); + // Writes banner to the log file and/or to the visualization browser. + + void log_aggregate_QoS (const Metrics::QoSParameter_Set & qos_params, + Metrics::Time interval, + CORBA::Environment &ACE_TRY_ENV = + CORBA::Environment::default_environment ()); + // Reports the aggregate QoS information for all operations + // to the passed QoS logger. + + void process_aggregate_QoS (const Metrics::QoSParameter_Set & qos_params, + Metrics::Time interval); + // Processes the aggregate QoS information for all operations + // to the passed QoS logger. + + void set_identities (const Metrics::ProbeIdentity_Set & probe_identities, + CORBA::Environment &ACE_TRY_ENV = + CORBA::Environment::default_environment ()); + // Binds the names of various timeprobes to their identifiers so + // that ids alone can be used (for efficiency) in passing data. + + void set_identity (const Metrics::ProbeIdentity_t & probe_identity, + CORBA::Environment &ACE_TRY_ENV = + CORBA::Environment::default_environment ()); + // Binds the names of various timeprobes to their identifiers so + // that ids alone can be used (for efficiency) in passing data. + + void log_timeprobe_data (const Metrics::TimeprobeParameter_Set & timeprobe_params, + Metrics::Time interval, + CORBA::Environment &ACE_TRY_ENV = + CORBA::Environment::default_environment ()); + // Reports timeprobe data collected since last run. + + void process_timeprobe_data (const Metrics::TimeprobeParameter_Set & timeprobe_params, + Metrics::Time interval); + // Processes timeprobe data collected since last run. + +protected: + + int generate_events_; + // Indicates whether or not to generate events for displays. + + int generate_log_; + // Indicates whether or not to generate a text log. + + int generate_totals_; + // Indicates whether information of totals are logged. + + int generate_export_file_; + // Indicates whether information of totals are logged. + + //DCL:Move code here to remove Linux compiler warning + const char *log_filename_; + // Name of the text log file (if any) + + int log_started_; + // Indicates whether or not the log has been started already. + + FILE *log_file_; + // Handle to the text log file (if any). + + FILE *export_file_; + // Handle to the excel export log file (if any). + + PROBE_NAME_MAP probe_name_map_; + // Maps probe ids to their names. + +#if defined (METRICS_LOGGER_SENDS_EVENTS) + DOVE_Supplier dove_supplier_; + // DOVE Event supplier. + + Metrics::QoSData qos_data_; + // QoS data structure. + + Metrics::UtilData util_data_; + // Utilization data structure. + +#endif /* METRICS_LOGGER_SENDS_EVENTS */ + + // Only write the file once every OPEN_CLOSE_BANNER_CYCLE banner + // changes + int saveFileCnt_; +}; + +typedef ACE_Singleton +TAO_METRICS_LOGGER_REF_SINGLETON; + +typedef ACE_Singleton +TAO_METRICS_LOGGER_SINGLETON; + + +#endif /* METRICS_LOGGER_H */ + + + + + + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.cpp b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.cpp new file mode 100644 index 00000000000..90b873deef9 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.cpp @@ -0,0 +1,20 @@ +// $Id$ + +#ifndef METRICS_UPCALL_MONITOR_CPP +#define METRICS_UPCALL_MONITOR_CPP + +#include "Metrics_UpcallMonitor.h" + +#if !defined (__ACE_INLINE__) +#include "Metrics_UpcallMonitor.i" +#endif /* __ACE_INLINE__ */ + +// Added by joeh to fix undefined symbols for VxWorks load +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class TAO_Metrics_LocalCache; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate TAO_Metrics_LocalCache +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + +#endif /* METRICS_UPCALL_MONITOR_CPP */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.h b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.h new file mode 100644 index 00000000000..538d3d3a3da --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.h @@ -0,0 +1,262 @@ +// $Id$ + +#ifndef METRICS_UPCALL_MONITOR_H +#define METRICS_UPCALL_MONITOR_H + +#if ! defined (VXWORKS) + +// Comment out both of these to disable output +# define METRICS_MONITOR_ERROR_OUTPUT_ENABLED +# define METRICS_MONITOR_DEBUG_OUTPUT_ENABLED + +#endif /* ! VXWORKS */ + +#include "ace/Singleton.h" +#include "ace/Hash_Map_Manager.h" + +#include "orbsvcs/RtecEventCommS.h" +#include "orbsvcs/Time_Utilities.h" +#include "orbsvcs/MetricsS.h" + +#include "Metrics_LocalCache.h" +#include "Metrics_FrameManager.h" +#include "Metrics_Utils.h" + +class TAO_ORBSVCS_Export TAO_Metrics_UpcallMonitor + : public POA_Metrics::QoSMonitor +{ + // = TITLE + // This class implements a Metrics QoS monitor. + // + // = DESCRIPTION + // This class allows clients to monitor QoS, collected + // by the rest of the metrics framework. +public: + + typedef ACE_Hash_Map_Manager_Ex, + ACE_Equal_To, + ACE_SYNCH_MUTEX> MONITOR_MAP; + // Type of map used for O(1) lookup of missed/made deadline counts + // by operation handles. + + typedef ACE_Hash_Map_Entry + MONITOR_MAP_ENTRY; + // Type of map used for O(1) lookup of RT_Infos by their handles. + + typedef ACE_Hash_Map_Iterator_Ex, + ACE_Equal_To, + ACE_SYNCH_MUTEX> MONITOR_MAP_ITERATOR; + // Type of map used for O(1) lookup of missed/made deadline counts + // by operation handles. + + + TAO_Metrics_UpcallMonitor (); + // Default constructor. + + ~TAO_Metrics_UpcallMonitor (); + // Destructor. + + virtual void + report_made_deadline (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_0)); + // Reports a successful upcall. + + virtual void + report_missed_deadline (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_1)); + // Reports an unsuccessful upcall. + + virtual void + get_aggregate_QoS (RtecScheduler::handle_t handle, + Metrics::QoSParameter_t_out qos, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_2, + Metrics::INTERNAL_3)); + // Get the aggregate QoS statistics collected for the passed handle. + + virtual void get_aggregate_QoS_set ( + const Metrics::Handle_Set_t & handle_set, + Metrics::QoSParameter_Set_out qos_set, + CORBA::Environment &ACE_TRY_ENV = + TAO_default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_4, + Metrics::INTERNAL_5)); + // Get the aggregate QoS statistics collected for each handle in the + // passed set. + + virtual void + reset_statistics (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_7, + Metrics::INTERNAL_8)); + // Resets the aggregate QoS information for the given operation. + + MONITOR_MAP &missed_map (); + // Accessor for map of operation handle to a count of deadlines missed. + + MONITOR_MAP &made_map (); + // Accessor for map of operation handle to a count of deadlines made. + +private: + + // = Implementation members. + + MONITOR_MAP missed_map_; + // Maps operation handle to a count of deadlines missed. + + MONITOR_MAP made_map_; + // Maps operation handle to a count of deadlines made. + +}; + + +class TAO_ORBSVCS_Export TAO_Metrics_ReportingUpcallMonitor + : public POA_Metrics::ReportingQoSMonitor +{ + // = TITLE + // This class implements a reporting extension for a Metrics QoS monitor. + // + // = DESCRIPTION + // This class uses delegation to avoid the ugly consequences of + // multiple inheritance from a common IDL base class along two + // inheritance paths. +public: + + typedef ACE_Hash_Map_Manager_Ex, + ACE_Equal_To, + ACE_SYNCH_MUTEX> MONITOR_MAP; + // Type of map used for O(1) lookup of missed/made deadline counts + // by operation handles. + + typedef ACE_Hash_Map_Entry + MONITOR_MAP_ENTRY; + // Type of map used for O(1) lookup of RT_Infos by their handles. + + typedef ACE_Hash_Map_Iterator_Ex, + ACE_Equal_To, + ACE_SYNCH_MUTEX> MONITOR_MAP_ITERATOR; + // Type of map used for O(1) lookup of missed/made deadline counts + // by operation handles. + + + TAO_Metrics_ReportingUpcallMonitor (); + // Default constructor. + + ~TAO_Metrics_ReportingUpcallMonitor (); + // Destructor. + + virtual void + report_made_deadline (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_0)); + // Reports a successful upcall. + + virtual void + report_missed_deadline (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_1)); + // Reports an unsuccessful upcall. + + virtual void + get_aggregate_QoS (RtecScheduler::handle_t handle, + Metrics::QoSParameter_t_out qos, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_2, + Metrics::INTERNAL_3)); + // Get the aggregate QoS statistics collected for the passed handle. + + virtual void get_aggregate_QoS_set ( + const Metrics::Handle_Set_t & handle_set, + Metrics::QoSParameter_Set_out qos_set, + CORBA::Environment &ACE_TRY_ENV = + TAO_default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_4, + Metrics::INTERNAL_5)); + // Get the aggregate QoS statistics collected for each handle in the + // passed set. + + virtual void report_aggregate_QoS ( + Metrics::QoSLogger_ptr logger, + Metrics::Time interval, + CORBA::Environment &ACE_TRY_ENV = + TAO_default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::NIL_LOGGER, + Metrics::INTERNAL_6)); + // Report the aggregate QoS statistics to the logger. + + virtual void + reset_statistics (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV + = CORBA::Environment::default_environment ()) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_7, + Metrics::INTERNAL_8)); + // Resets the aggregate QoS information for the given operation. + +private: + + TAO_Metrics_UpcallMonitor monitor_; + // The monitor we're wrapping. +}; + + +#if defined (__ACE_INLINE__) +#include "Metrics_UpcallMonitor.i" +#endif /* __ACE_INLINE__ */ + +#include "orbsvcs/Metrics/Metrics_UpcallMonitor_T.h" + +typedef TAO_Metrics_UpcallMonitorAdapter +TAO_METRICS_MONITOR_ADAPTER_TYPE; + +typedef TAO_Metrics_ReportingUpcallMonitorAdapter +TAO_METRICS_REPORTING_MONITOR_ADAPTER_TYPE; + +typedef ACE_Singleton +TAO_METRICS_MONITOR_SINGLETON_TYPE; + +typedef ACE_Singleton +TAO_METRICS_REPORTING_MONITOR_SINGLETON_TYPE; + +#if defined (TAO_USES_REPORTING_METRICS) +typedef TAO_METRICS_REPORTING_MONITOR_ADAPTER_TYPE TAO_METRICS_MONITOR_ADAPTER; +typedef TAO_METRICS_REPORTING_MONITOR_SINGLETON_TYPE TAO_METRICS_MONITOR_SINGLETON; +#else +typedef TAO_METRICS_MONITOR_ADAPTER_TYPE TAO_METRICS_MONITOR_ADAPTER; +typedef TAO_METRICS_MONITOR_SINGLETON_TYPE TAO_METRICS_MONITOR_SINGLETON; +#endif + + +#endif /* METRICS_UPCALL_MONITOR_H */ + + + + + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.i b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.i new file mode 100644 index 00000000000..77cb2d37708 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.i @@ -0,0 +1,371 @@ +// $Id$ + +// @METRICS@ + +#ifndef METRICS_UPCALL_MONITOR_I +#define METRICS_UPCALL_MONITOR_I + +//# if defined (METRICS_USES_OP_CANCELLATION) +//# undef METRICS_USES_OP_CANCELLATION +//# endif /* METRICS_USES_OP_CANCELLATION */ + +# if ! defined (METRICS_USES_OP_CANCELLATION) +# define METRICS_USES_OP_CANCELLATION +# endif /* ! METRICS_USES_OP_CANCELLATION */ + + +///////////////////////////////////// +// Class TAO_Metrics_UpcallMonitor // +///////////////////////////////////// + +// Default constructor. + +ACE_INLINE +TAO_Metrics_UpcallMonitor::TAO_Metrics_UpcallMonitor () +{ +} + +// Destructor. + +ACE_INLINE +TAO_Metrics_UpcallMonitor::~TAO_Metrics_UpcallMonitor () +{ +} + +// Reports a successful upcall. + +ACE_INLINE void +TAO_Metrics_UpcallMonitor:: +report_made_deadline (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_0)) +{ + CORBA::ULong count = 0; + MONITOR_MAP_ENTRY *entry; + + if (made_map_.trybind (handle, count, entry) < 0) + { + ACE_DEBUG ((LM_DEBUG, + "Failed trybind for handle %u in made map\n", handle)); + ACE_THROW (Metrics::INTERNAL_0 ()); + } + + ++entry->int_id_; +} + +// Reports an unsuccessful upcall. + +ACE_INLINE void +TAO_Metrics_UpcallMonitor:: +report_missed_deadline (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_1)) +{ + CORBA::ULong count = 0; + MONITOR_MAP_ENTRY *entry; + + if (missed_map_.trybind (handle, count, entry) < 0) + { + ACE_DEBUG ((LM_DEBUG, + "Failed trybind for handle %u in missed map\n", handle)); + ACE_THROW (Metrics::INTERNAL_1 ()); + } + + ++entry->int_id_; +} + + +// Get the aggregate QoS statistics collected so far by the monitor. + +ACE_INLINE void +TAO_Metrics_UpcallMonitor::get_aggregate_QoS (RtecScheduler::handle_t handle, + Metrics::QoSParameter_t_out qos, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_2, + Metrics::INTERNAL_3)) +{ + CORBA::ULong made_count = 0; + CORBA::ULong missed_count = 0; + MONITOR_MAP_ENTRY *made_entry; + MONITOR_MAP_ENTRY *missed_entry; + + if (made_map_.trybind (handle, made_count, made_entry) < 0) + { + ACE_DEBUG ((LM_DEBUG, "TAO_Metrics_UpcallMonitor::get_aggregate_QoS: " + "Failed trybind for handle %u in made map\n", handle)); + ACE_THROW (Metrics::INTERNAL_2 ()); + } + + if (missed_map_.trybind (handle, missed_count, missed_entry) < 0) + { + ACE_DEBUG ((LM_DEBUG, "TAO_Metrics_UpcallMonitor::get_aggregate_QoS: " + "Failed trybind for handle %u in missed map\n", handle)); + ACE_THROW (Metrics::INTERNAL_3 ()); + } + + ACE_NEW_THROW_EX (qos, + Metrics::QoSParameter_t, + CORBA::NO_MEMORY ()); + + qos->handle = handle; + qos->deadlines_made = made_entry->int_id_; + qos->deadlines_missed = missed_entry->int_id_; + qos->operations_cancelled = 0; + qos->is_hrt = 0; +} + + +// Get the aggregate QoS statistics collected for each handle in the +// passed set. + +ACE_INLINE void +TAO_Metrics_UpcallMonitor::get_aggregate_QoS_set ( + const Metrics::Handle_Set_t & handle_set, + Metrics::QoSParameter_Set_out qos_set, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_4, + Metrics::INTERNAL_5)) +{ + CORBA::ULong made_count = 0; + CORBA::ULong missed_count = 0; + MONITOR_MAP_ENTRY *made_entry = 0; + MONITOR_MAP_ENTRY *missed_entry = 0; + + ACE_NEW_THROW_EX (qos_set, + Metrics::QoSParameter_Set (handle_set.length ()), + CORBA::NO_MEMORY ()); + qos_set->length (handle_set.length ()); + + + for (u_int i = 0; i < handle_set.length (); ++i) + { + made_count = 0; + missed_count = 0; + made_entry = 0; + missed_entry = 0; + + if (made_map_.trybind (handle_set [i], made_count, made_entry) < 0) + { + ACE_DEBUG ((LM_DEBUG, + "TAO_Metrics_UpcallMonitor::get_aggregate_QoS_set: " + "Failed trybind for handle_set [%d] = %u in made map\n", + i, handle_set [i])); + ACE_THROW (Metrics::INTERNAL_4 ()); + } + + if (missed_map_.trybind (handle_set [i], missed_count, missed_entry) < 0) + { + ACE_DEBUG ((LM_DEBUG, + "TAO_Metrics_UpcallMonitor::get_aggregate_QoS_set: " + "Failed trybind for handle_set[%d]=%u in missed map\n", + i, handle_set [i])); + ACE_THROW (Metrics::INTERNAL_5 ()); + } + + qos_set [i].handle = handle_set [i]; + qos_set [i].deadlines_made = made_entry->int_id_; + qos_set [i].deadlines_missed = missed_entry->int_id_; + qos_set [i].operations_cancelled = 0; + qos_set [i].is_hrt = 0; + } +} + + + +// Resets the aggregate QoS information for the given operation. + +ACE_INLINE void +TAO_Metrics_UpcallMonitor::reset_statistics (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_7, + Metrics::INTERNAL_8)) +{ + CORBA::ULong count = 0; + + if (made_map_.rebind (handle, count) < 0) + { + ACE_THROW (Metrics::INTERNAL_7 ()); + } + + if (missed_map_.rebind (handle, count) < 0) + { + ACE_THROW (Metrics::INTERNAL_8 ()); + } +} + + +// Accessor for map of operation handle to a count of deadlines missed. + +ACE_INLINE +TAO_Metrics_UpcallMonitor::MONITOR_MAP & +TAO_Metrics_UpcallMonitor::missed_map () +{ + return this->missed_map_; +} + +// Accessor for map of operation handle to a count of deadlines made. + +ACE_INLINE +TAO_Metrics_UpcallMonitor::MONITOR_MAP & +TAO_Metrics_UpcallMonitor::made_map () +{ + return this->made_map_; +} + +////////////////////////////////////////////// +// Class TAO_Metrics_ReportingUpcallMonitor // +////////////////////////////////////////////// + +// Default constructor. + +ACE_INLINE +TAO_Metrics_ReportingUpcallMonitor::TAO_Metrics_ReportingUpcallMonitor () +{ +} + +// Destructor. + +ACE_INLINE +TAO_Metrics_ReportingUpcallMonitor::~TAO_Metrics_ReportingUpcallMonitor () +{ +} + +// Reports a successful upcall. + +ACE_INLINE void +TAO_Metrics_ReportingUpcallMonitor:: +report_made_deadline (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_0)) +{ + monitor_.report_made_deadline (handle, ACE_TRY_ENV); +} + +// Reports an unsuccessful upcall. + +ACE_INLINE void +TAO_Metrics_ReportingUpcallMonitor:: +report_missed_deadline (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_1)) +{ + monitor_.report_missed_deadline (handle, ACE_TRY_ENV); +} + + +// Get the aggregate QoS statistics collected so far by the monitor. + +ACE_INLINE void +TAO_Metrics_ReportingUpcallMonitor::get_aggregate_QoS (RtecScheduler::handle_t handle, + Metrics::QoSParameter_t_out qos, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_2, + Metrics::INTERNAL_3)) +{ + monitor_.get_aggregate_QoS (handle, qos, ACE_TRY_ENV); +} + + +// Get the aggregate QoS statistics collected for each handle in the +// passed set. + +ACE_INLINE void +TAO_Metrics_ReportingUpcallMonitor::get_aggregate_QoS_set ( + const Metrics::Handle_Set_t & handle_set, + Metrics::QoSParameter_Set_out qos_set, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_4, + Metrics::INTERNAL_5)) +{ + monitor_.get_aggregate_QoS_set (handle_set, qos_set, ACE_TRY_ENV); +} + + + +// Resets the aggregate QoS information for the given operation. + +ACE_INLINE void +TAO_Metrics_ReportingUpcallMonitor::reset_statistics (RtecScheduler::handle_t handle, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::INTERNAL_7, + Metrics::INTERNAL_8)) +{ + monitor_.reset_statistics (handle, ACE_TRY_ENV); +} + + +// Reports the aggregate QoS statistics to the logger. + +ACE_INLINE void +TAO_Metrics_ReportingUpcallMonitor::report_aggregate_QoS ( + Metrics::QoSLogger_ptr logger, + Metrics::Time interval, + CORBA::Environment &ACE_TRY_ENV) + ACE_THROW_SPEC ((CORBA::SystemException, + Metrics::NIL_LOGGER, + Metrics::INTERNAL_6)) +{ + if (CORBA::is_nil (logger)) + { + ACE_THROW (Metrics::NIL_LOGGER ()); + } + + Metrics::QoSParameter_Set qos_set; + u_int set_length = 1; + + // First, look at made map handles + MONITOR_MAP_ITERATOR iter (monitor_.made_map ()); + for (; iter.done () == 0; ++iter, ++set_length) + { + CORBA::ULong missed_count; + if (monitor_.missed_map ().find ((*iter).ext_id_, missed_count) < 0) + { + missed_count = 0; + } + + qos_set.length (set_length); + + qos_set [set_length - 1].entry_point = (const char *) "MONITOR MADE_MAP_OP"; + qos_set [set_length - 1].handle = (*iter).ext_id_; + qos_set [set_length - 1].deadlines_made = (*iter).int_id_; + qos_set [set_length - 1].deadlines_missed = missed_count; + qos_set [set_length - 1].operations_cancelled = 0; + qos_set [set_length - 1].is_hrt = 0; + } + + // Then, find missed map handles with no made map entry. + MONITOR_MAP_ITERATOR missed_iter (monitor_.missed_map ()); + for (; missed_iter.done () == 0; ++missed_iter) + { + CORBA::ULong made_count; + if (monitor_.made_map ().find ((*missed_iter).ext_id_, made_count) < 0) + { + qos_set.length (set_length); + + qos_set [set_length - 1].entry_point = (const char *) "MONITOR MISS_MAP_OP"; + qos_set [set_length - 1].handle = (*missed_iter).ext_id_; + qos_set [set_length - 1].deadlines_made = 0; + qos_set [set_length - 1].deadlines_missed = (*missed_iter).int_id_; + qos_set [set_length - 1].operations_cancelled = 0; + qos_set [set_length - 1].is_hrt = 0; + + ++set_length; + } + } + + logger->log_aggregate_QoS (qos_set, interval); +} + +#endif /* METRICS_UPCALL_MONITOR_I */ + + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.cpp b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.cpp new file mode 100644 index 00000000000..7065e9bea6d --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.cpp @@ -0,0 +1,25 @@ +// $Id$ + +#ifndef METRICS_UPCALL_MONITOR_T_CPP +#define METRICS_UPCALL_MONITOR_T_CPP + +#include "Metrics_UpcallMonitor_T.h" + +#if !defined (__ACE_INLINE__) +#include "Metrics_UpcallMonitor_T.i" +#endif /* __ACE_INLINE__ */ + +// Virtual destructor: destroy actual consumer if we own it. + +template +TAO_Metrics_UpcallMonitorAdapter:: +~TAO_Metrics_UpcallMonitorAdapter () +{ + if (adapter_owns_consumer_) + { + delete (& consumer_); + } +} + +#endif /* METRICS_UPCALL_MONITOR_T_CPP */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.h b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.h new file mode 100644 index 00000000000..10bccb4f8e1 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.h @@ -0,0 +1,157 @@ +// $Id$ + +#ifndef METRICS_UPCALL_MONITOR_T_H +#define METRICS_UPCALL_MONITOR_T_H + +#if ! defined (VXWORKS) + +// Comment out both of these to disable output +# define METRICS_MONITOR_ERROR_OUTPUT_ENABLED +# define METRICS_MONITOR_DEBUG_OUTPUT_ENABLED + +#endif /* ! VXWORKS */ + +#include "Metrics_LocalCache.h" +#include "Metrics_FrameManager.h" + +#include "ace/Hash_Map_Manager.h" + +#include "orbsvcs/RtecEventCommS.h" +#include "orbsvcs/Time_Utilities.h" +#include "orbsvcs/MetricsS.h" + +#include "orbsvcs/Metrics/Metrics_UpcallMonitor.h" + +template +class TAO_Metrics_UpcallMonitorAdapter + : public RtecEventComm::PushConsumer +{ + // = TITLE + // This class implements an adapter for monitoring QoS received by + // an event push consumer. + // + // = DESCRIPTION + // This class wraps the consumer event push upcall with time + // probe and monitor reporting calls. +public: + + TAO_Metrics_UpcallMonitorAdapter ( + POA_Metrics::QoSMonitor & monitor, + TAO_Metrics_LocalCache & cache, + TAO_Metrics_FrameManager & frame_manager, + POA_RtecEventComm::PushConsumer & consumer, + TAO_String_Manager entry_point, + RtecScheduler::handle_t handle, + RtecScheduler::Period_t period, + RtecScheduler::Time wcet, + RtecScheduler::Criticality_t criticality, + int adapter_owns_consumer = 1, + int cache_register = 1); + // Constructor that takes a reference to the various metrics + // objects, the actual push consumer we're monitoring, QoS info + // about the consumer, and an int that indicates whether (non-zero) + // or not (zero) we need to destroy the consumer in our destructor. + + virtual ~TAO_Metrics_UpcallMonitorAdapter (); + // Virtual destructor: destroys actual consumer if it owns it. + + RtecScheduler::Period_t get_period (); + // Get the current period for the adapter. + + void set_period (RtecScheduler::Period_t period); + // Set the current period for the adapter. + + void push (const RtecEventComm::EventSet & data, + CORBA::Environment &ACE_TRY_ENV = + CORBA::Environment::default_environment ()); + // Do a monitored push to the actual PushConsumer for which we're a proxy + + void disconnect_push_consumer (CORBA::Environment &ACE_TRY_ENV = + CORBA::Environment::default_environment ()); + // Delegates to the actual PushConsumer for which we're a proxy + +protected: + + // = Implementation members. + + POA_Metrics::QoSMonitor & monitor_; + // A reference to the monitor to which we report. + + TAO_Metrics_LocalCache & cache_; + // A reference to the metrics data cache to which we report. + + TAO_Metrics_FrameManager & frame_manager_; + // A reference to the frame manager we use. + + POA_RtecEventComm::PushConsumer & consumer_; + // A reference to the actual PushConsumer for which we're a proxy + + RtecScheduler::handle_t handle_; + // Handle of the operation we're wrapping. + + RtecScheduler::Period_t period_; + // Current period for the adapter. + + ACE_Time_Value execution_time_; + // Current execution time for the adapter. + + int is_critical_; + // Whether or not the adapter is critical. + + int adapter_owns_consumer_; + // indicates whether (non-zero) or not (zero) we need + // to destroy the consumer in our destructor. + +}; + +template +class TAO_Metrics_ReportingUpcallMonitorAdapter + : public TAO_Metrics_UpcallMonitorAdapter +{ + // = TITLE + // This class implements an adapter for monitoring QoS received by + // an event push consumer. + // + // = DESCRIPTION + // This class wraps the consumer event push upcall with time + // probe and monitor reporting calls. +public: + + TAO_Metrics_ReportingUpcallMonitorAdapter ( + POA_Metrics::QoSMonitor & monitor, + TAO_Metrics_ReportingLocalCache & cache, + TAO_Metrics_FrameManager & frame_manager, + POA_RtecEventComm::PushConsumer & consumer, + TAO_String_Manager entry_point, + RtecScheduler::handle_t handle, + RtecScheduler::Period_t period, + RtecScheduler::Time wcet, + RtecScheduler::Criticality_t criticality, + int adapter_owns_consumer = 1, + Metrics::QoSLogger_ptr logger = 0); + // Constructor that takes a reference to a logger object and + // info needed to construct or base class. + +protected: + + // = Implementation members. + + Metrics::QoSLogger_ptr logger_; + // A (possibly null) CORBA pointer to a logging object + +}; + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "Metrics_UpcallMonitor_T.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("Metrics_UpcallMonitor_T.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#if defined (__ACE_INLINE__) +#include "Metrics_UpcallMonitor_T.i" +#endif /* __ACE_INLINE__ */ + +#endif /* METRICS_UPCALL_MONITOR_T_H */ + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.i b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.i new file mode 100644 index 00000000000..bad8d27cea7 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.i @@ -0,0 +1,256 @@ +// $Id$ + +// @METRICS@ + +#ifndef METRICS_UPCALL_MONITOR_T_I +#define METRICS_UPCALL_MONITOR_T_I + +//# if defined (METRICS_USES_OP_CANCELLATION) +//# undef METRICS_USES_OP_CANCELLATION +//# endif /* METRICS_USES_OP_CANCELLATION */ + +# if ! defined (METRICS_USES_OP_CANCELLATION) +# define METRICS_USES_OP_CANCELLATION +# endif /* ! METRICS_USES_OP_CANCELLATION */ + + +//////////////////////////////////////////// +// class TAO_Metrics_UpcallMonitorAdapter // +//////////////////////////////////////////// + + +// Constructor that takes a reference to the actual push consumer +// we're monitoring and an int that indicates whether (non-zero) or +// not (zero) we need to destroy the consumer in our destructor. + +template +ACE_INLINE +TAO_Metrics_UpcallMonitorAdapter:: +TAO_Metrics_UpcallMonitorAdapter ( + POA_Metrics::QoSMonitor & monitor, + TAO_Metrics_LocalCache &cache, + TAO_Metrics_FrameManager &frame_manager, + POA_RtecEventComm::PushConsumer & consumer, + TAO_String_Manager entry_point, + RtecScheduler::handle_t handle, + RtecScheduler::Period_t period, + RtecScheduler::Time wcet, + RtecScheduler::Criticality_t criticality, + int adapter_owns_consumer, + int cache_register) + : monitor_ (monitor), + cache_ (cache), + frame_manager_ (frame_manager), + consumer_ (consumer), + handle_ (handle), + period_ (period), + adapter_owns_consumer_ (adapter_owns_consumer) +{ +//DCL:Added to remove Linux compile warning + ACE_UNUSED_ARG(entry_point); + + // Ensure that the high res timer global scale factor + // is set before any of its static methods are used + ACE_High_Res_Timer::global_scale_factor (); + + // Store the RT_Info execution time. + ORBSVCS_Time::TimeT_to_Time_Value(this->execution_time_, + wcet); + this->is_critical_ = + (criticality == RtecScheduler::HIGH_CRITICALITY + || criticality == RtecScheduler::VERY_HIGH_CRITICALITY) + ? 1 : 0; + + // Use the type-preserving argument rather than the base class + // reference which is fine everywhere but here. + if (cache_register) + { + if (cache.metrics_enabled()) + cache.register_upcall_adapter (this->handle_, + entry_point, + this->is_critical_); + } +} + + +// Get the current priod for the adapter. + +template +ACE_INLINE RtecScheduler::Period_t +TAO_Metrics_UpcallMonitorAdapter:: +get_period () +{ + return this->period_; +} + + +// Set the current priod for the adapter. + +template +ACE_INLINE void +TAO_Metrics_UpcallMonitorAdapter:: +set_period (RtecScheduler::Period_t period) +{ + this->period_ = period; +} + + +// Do a monitored push to the actual PushConsumer for which we're a proxy +template +ACE_INLINE void +TAO_Metrics_UpcallMonitorAdapter:: +push (const RtecEventComm::EventSet & data, + CORBA::Environment &ACE_TRY_ENV) +{ + // Save stamped deadline. + ACE_Time_Value deadline_tv; + + // If we get an error, just set the deadline to zero, and possibly + // complain. + if (this->frame_manager_.get_end_time (this->period_, deadline_tv) < 0) + { + deadline_tv = ACE_Time_Value::zero; +# if defined (METRICS_MONITOR_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_UpcallMonitorAdapter::push" + " get_end_time failed .\n")); +# endif /* METRICS_MONITOR_ERROR_OUTPUT_ENABLED */ + } + +# if defined (METRICS_USES_OP_CANCELLATION) + + // Take current time stamp and add expected execution to get + // projected completion. Done this way for efficiency, to minimize + // temporaries and their copies and constructor and destructor calls. + ACE_Time_Value projected_tv; + ACE_hrtime_t hrtime_now = ACE_OS::gethrtime (); + ACE_High_Res_Timer::hrtime_to_tv (projected_tv, + hrtime_now); + projected_tv += this->execution_time_; + + // Operation cancellation: uses WCET to determine whether or not + // deadline will be met. A critical operation (is_critical_) is + // dispatched unconditionally. A zero deadline indicates an + // operation is not deadline-bound and thus is not subject to + // cancellation. + if (this->is_critical_ + || deadline_tv >= projected_tv + || deadline_tv == ACE_Time_Value::zero) + { +# endif /* METRICS_USES_OP_CANCELLATION */ + + // Record the start of the upcall in the cache. +#if 0 + if ( this->handle_ != TAO_Metrics_Utils::timeoutEvent ()) +#endif /* 0 */ + if (cache_.metrics_enabled()) + cache_.report_upcall_start (this->handle_); + + // Push to the actual consumer. + consumer_.push (data, ACE_TRY_ENV); + + // Record the end of the upcall in the cache, and report whether + // the deadline was made or missed to the monitor. + +#if 0 + if ( this->handle_ != TAO_Metrics_Utils::timeoutEvent ()) + { +#else /* 1 */ + if (1) + { +#endif /* 0 */ + if (cache_.metrics_enabled()) + { + int result = cache_.report_upcall_stop (this->handle_, deadline_tv); + if (result == 0) + { + monitor_.report_made_deadline (this->handle_, ACE_TRY_ENV); + ACE_CHECK; + } + else if (result == 1) + { + monitor_.report_missed_deadline (this->handle_, ACE_TRY_ENV); + ACE_CHECK; + } +# if defined (METRICS_MONITOR_ERROR_OUTPUT_ENABLED) + else + { + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_UpcallMonitorAdapter::push" + " upcall stop reporting failed .\n")); + } + +# endif /* METRICS_MONITOR_ERROR_OUTPUT_ENABLED */ + } + } +# if defined (METRICS_USES_OP_CANCELLATION) + } + else + { +# if defined (METRICS_MONITOR_DEBUG_OUTPUT_ENABLED) + ACE_DEBUG ((LM_INFO, + "SRT Operation cancelled .\n")); +# endif /* METRICS_MONITOR_DEBUG_OUTPUT_ENABLED */ + + if (cache_.metrics_enabled()) + { + // The operation push was cancelled: report the cancellation to + // the cache and the missed deadline to the monitor. + cache_.report_upcall_cancellation (this->handle_); + monitor_.report_missed_deadline (this->handle_, ACE_TRY_ENV); + ACE_CHECK; + } + } + +# endif /* METRICS_USES_OP_CANCELLATION */ +} + +// Delegates to the actual PushConsumer for which we're a proxy. + +template +ACE_INLINE void +TAO_Metrics_UpcallMonitorAdapter:: +disconnect_push_consumer (CORBA::Environment &ACE_TRY_ENV) +{ + consumer_.disconnect_push_consumer (ACE_TRY_ENV); +} + + +template +ACE_INLINE +TAO_Metrics_ReportingUpcallMonitorAdapter:: +TAO_Metrics_ReportingUpcallMonitorAdapter ( + POA_Metrics::QoSMonitor & monitor, + TAO_Metrics_ReportingLocalCache &cache, + TAO_Metrics_FrameManager &frame_manager, + POA_RtecEventComm::PushConsumer & consumer, + TAO_String_Manager entry_point, + RtecScheduler::handle_t handle, + RtecScheduler::Period_t period, + RtecScheduler::Time wcet, + RtecScheduler::Criticality_t criticality, + int adapter_owns_consumer, + Metrics::QoSLogger_ptr logger) + : TAO_Metrics_UpcallMonitorAdapter + (monitor, + cache, + frame_manager, + consumer, + entry_point, + handle, + period, + wcet, + criticality, + adapter_owns_consumer, + 0 /* don't register */), + logger_ (logger) +{ + // Use the type-preserving argument rather than the base class + // reference which is fine everywhere but here. + cache.register_upcall_adapter (this->handle_, + entry_point, + this->is_critical_, + this->logger_); +} + +#endif /* METRICS_UPCALL_MONITOR_T_I */ diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.cpp b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.cpp new file mode 100644 index 00000000000..80c696ed074 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.cpp @@ -0,0 +1,526 @@ +// $Id$ + +#ifndef METRICS_UTILS_CPP +#define METRICS_UTILS_CPP + +#include "Metrics_Utils.h" + +///////////////////////////// +// Class TAO_Metrics_Utils // +///////////////////////////// + +// Static constants + +const u_int WSOA_Metrics_Handles::WSOA_METRICS_MAX_TILING_FACTOR = 64; + +const u_int TAO_Metrics_Utils::METRICS_BUFSIZE = 64; + +const u_int TAO_Metrics_Utils::METRICS_ENQUEUE_PROBE_ID_BASE = 0; +const u_int TAO_Metrics_Utils::METRICS_DEQUEUE_PROBE_ID_BASE = 1000; +const u_int TAO_Metrics_Utils::METRICS_SCHED_PROBE_ID_BASE = 2000; +const u_int TAO_Metrics_Utils::METRICS_QUO_PROBE_ID_BASE = 3000; +const u_int TAO_Metrics_Utils::METRICS_RTARM_PROBE_ID_BASE = 4000; +const u_int TAO_Metrics_Utils::METRICS_TNS_PROBE_ID_BASE = 5000; +const u_int TAO_Metrics_Utils::METRICS_TEEC_PROBE_ID_BASE = 6000; +const u_int TAO_Metrics_Utils::METRICS_UPCALL_MONITOR_ADAPTER_ID_BASE = 7000; + +// Static variable + +RtecScheduler::handle_t TAO_Metrics_Utils::timeoutEvent_ = 72; + + + +// Static method to set the mission state in the logger. + +void +TAO_Metrics_Utils::set_mission_state (int i, Metrics::QoSLogger_ptr logger) +{ + if (CORBA::is_nil (logger)) + { +#if defined (METRICS_UTILS_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_Utils::set_mission_state:\n" + "Logger IOR reference is nil.\n")); +#endif + return; + } + + char banner [TAO_Metrics_Utils::METRICS_BUFSIZE]; + ACE_OS::memset (banner, 0, TAO_Metrics_Utils::METRICS_BUFSIZE); + ACE_OS::sprintf (banner, "\n\n*** Mission State %d ***\n\n", i); + + ACE_TRY_NEW_ENV + { + logger->send_banner (banner, ACE_TRY_ENV); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { +#if defined (METRICS_UTILS_ERROR_OUTPUT_ENABLED) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "TAO_Metrics_LocalCache::set_mission_state:" + " logger call failed\n"); +#endif + } + ACE_ENDTRY; +} + +// Sets the logger reference. + +Metrics::QoSLogger_var +TAO_Metrics_Utils::get_logger (const char * logger_ior_str, + CORBA::ORB_ptr orb) +{ + Metrics::QoSLogger_var logger; + if (logger_ior_str && orb) + { + ACE_TRY_NEW_ENV + { + CORBA::Object_var obj = + orb->string_to_object (logger_ior_str); + ACE_TRY_CHECK; + + if (CORBA::is_nil (obj.in ())) + { +#if defined (METRICS_UTILS_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_Utils::get_logger:\n" + "Logger IOR string produced a " + "nil reference:\n[%s]", + logger_ior_str)); +#endif + return logger; + } + else + { + logger = Metrics::QoSLogger::_narrow (obj.in ()); + ACE_TRY_CHECK; + + if (CORBA::is_nil (logger.in ())) + { +#if defined (METRICS_UTILS_ERROR_OUTPUT_ENABLED) + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::set_logger:\n" + "Could not narrow IOR to logger:\n[%s]", + logger_ior_str)); +#endif + return logger; + } + } + } + ACE_CATCHANY + { +#if defined (METRICS_UTILS_ERROR_OUTPUT_ENABLED) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "TAO_Metrics_LocalCache::set_logger exception"); +#endif + return logger; + } + ACE_ENDTRY; + } +#if defined (METRICS_UTILS_ERROR_OUTPUT_ENABLED) + else + { + ACE_ERROR ((LM_ERROR, + "TAO_Metrics_LocalCache::set_logger:\n" + "must pass a non-zero orb and ior pointer\n")); + } +#endif + return logger; +} + + +//////////////////////////////// +// class WSOA_Metrics_Handles // +//////////////////////////////// + +// Default constructor - registers all WSOA METRICS INSTRUMENTATION handles. + +WSOA_Metrics_Handles::WSOA_Metrics_Handles () + : tiles_requested_ (0) + , compute_metrics_handle_(0) + , RTARM_triggered_adaptation_metrics_handle_(0) + , RTARM_region_transition_metrics_handle_(0) + , QuO_contract_eval_metrics_handle_(0) + , tile_request_delegate_metrics_handle_(0) + , image_received_metrics_handle_(0) + , image_processed_metrics_handle_(0) + , image_quiescent_metrics_handle_(0) + , tile_received_first_metrics_handle_(0) + , tile_processed_first_metrics_handle_(0) + , tile_queuing_first_metrics_handle_(0) + , tile_decompression_first_metrics_handle_(0) + , tile_ipm_first_metrics_handle_(0) + , zlib_compression_handle_(0) + , zlib_decompression_handle_(0) +{ +#ifdef TAO_USES_REPORTING_METRICS + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "TAO_compute_scheduling", + TAO_Metrics_Utils::SCHED, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->compute_metrics_handle_); + + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "RTARM_triggered_adaptation", + TAO_Metrics_Utils::RTARM, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->RTARM_triggered_adaptation_metrics_handle_); + + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "RTARM_region_transition", + TAO_Metrics_Utils::RTARM, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->RTARM_region_transition_metrics_handle_); + + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "QuO_contract_eval", + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->QuO_contract_eval_metrics_handle_); + + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_request_delegate", + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->tile_request_delegate_metrics_handle_); + + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "image_received", + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->image_received_metrics_handle_); + + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "image_processed", + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->image_processed_metrics_handle_); + + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "image_quiescent", + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->image_quiescent_metrics_handle_); + + char registration_name[64]; + u_int i; + + // Store the first tile received handle, and make room for the others. + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_received_0", + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->tile_received_first_metrics_handle_); + + RtecScheduler::handle_t temp_metrics_handle = 0; + for (i = 1; i <= WSOA_METRICS_MAX_TILING_FACTOR; ++i) + { + ::sprintf (registration_name, "tile_received_%d", i); + + // We just throw the handles away rather than storing them, + // as they're always calculated by offset from the first. + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + temp_metrics_handle); + } + + // Store the first tile processed handle, and make room for the others. + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_processed_0", + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->tile_processed_first_metrics_handle_); + + for (i = 1; i <= WSOA_METRICS_MAX_TILING_FACTOR; ++i) + { + ::sprintf (registration_name, "tile_processed_%d", i); + + // We just throw the handles away rather than storing them, + // as they're always calculated by offset from the first. + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + temp_metrics_handle); + } + + // Store the first tile processed handle, and make room for the others. + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_queuing_0", + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->tile_queuing_first_metrics_handle_); + + for (i = 1; i <= WSOA_METRICS_MAX_TILING_FACTOR; ++i) + { + ::sprintf (registration_name, "tile_queuing_%d", i); + + // We just throw the handles away rather than storing them, + // as they're always calculated by offset from the first. + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + temp_metrics_handle); + } + + // Store the first tile processed handle, and make room for the others. + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_decompression_0", + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->tile_decompression_first_metrics_handle_); + + for (i = 1; i <= WSOA_METRICS_MAX_TILING_FACTOR; ++i) + { + ::sprintf (registration_name, "tile_decompression_%d", i); + + // We just throw the handles away rather than storing them, + // as they're always calculated by offset from the first. + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + temp_metrics_handle); + } + + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_ipm_0", + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->tile_ipm_first_metrics_handle_); + + for (i = 1; i <= WSOA_METRICS_MAX_TILING_FACTOR; ++i) + { + ::sprintf (registration_name, "tile_ipm_%d", i); + + // We just throw the handles away rather than storing them, + // as they're always calculated by offset from the first. + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + temp_metrics_handle); + } + + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "zlib Compression", + TAO_Metrics_Utils::SCHED, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->zlib_compression_handle_); + + REGISTER_METRICS_REPORTING_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "zlib Compression", + TAO_Metrics_Utils::SCHED, + *TAO_METRICS_LOGGER_REF_SINGLETON::instance(), + this->zlib_decompression_handle_); +#else /* ! TAO_USES_REPORTING_METRICS */ + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "TAO_compute_scheduling", + TAO_Metrics_Utils::SCHED, + this->compute_metrics_handle_); + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "RTARM_triggered_adaptation", + TAO_Metrics_Utils::RTARM, + this->RTARM_triggered_adaptation_metrics_handle_); + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "RTARM_region_transition", + TAO_Metrics_Utils::RTARM, + this->RTARM_region_transition_metrics_handle_); + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "QuO_contract_eval", + TAO_Metrics_Utils::QUO, + this->QuO_contract_eval_metrics_handle_); + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_request_delegate", + TAO_Metrics_Utils::QUO, + this->tile_request_delegate_metrics_handle_); + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "image_received", + TAO_Metrics_Utils::QUO, + this->image_received_metrics_handle_); + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "image_processed", + TAO_Metrics_Utils::QUO, + this->image_processed_metrics_handle_); + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "image_quiescent", + TAO_Metrics_Utils::QUO, + this->image_quiescent_metrics_handle_); + + char registration_name[64]; + u_int i; + + // Store the first tile received handle, and make room for the others. + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_received_0", + TAO_Metrics_Utils::QUO, + this->tile_received_first_metrics_handle_); + + RtecScheduler::handle_t temp_metrics_handle; + for (i = 1; i <= WSOA_METRICS_MAX_TILING_FACTOR; ++i) + { + ::sprintf (registration_name, "tile_received_%d", i); + + // We just throw the handles away rather than storing them, + // as they're always calculated by offset from the first. + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + temp_metrics_handle); + } + + // Store the first tile processed handle, and make room for the others. + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_processed_0", + TAO_Metrics_Utils::QUO, + this->tile_processed_first_metrics_handle_); + + for (i = 1; i <= WSOA_METRICS_MAX_TILING_FACTOR; ++i) + { + ::sprintf (registration_name, "tile_processed_%d", i); + + // We just throw the handles away rather than storing them, + // as they're always calculated by offset from the first. + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + temp_metrics_handle); + } + + // Store the first tile processed handle, and make room for the others. + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_queuing_0", + TAO_Metrics_Utils::QUO, + this->tile_queuing_first_metrics_handle_); + + for (i = 1; i <= WSOA_METRICS_MAX_TILING_FACTOR; ++i) + { + ::sprintf (registration_name, "tile_queuing_%d", i); + + // We just throw the handles away rather than storing them, + // as they're always calculated by offset from the first. + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + temp_metrics_handle); + } + + // Store the first tile processed handle, and make room for the others. + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_decompression_0", + TAO_Metrics_Utils::QUO, + this->tile_decompression_first_metrics_handle_); + + for (i = 1; i <= WSOA_METRICS_MAX_TILING_FACTOR; ++i) + { + ::sprintf (registration_name, "tile_decompression_%d", i); + + // We just throw the handles away rather than storing them, + // as they're always calculated by offset from the first. + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + temp_metrics_handle); + } + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "tile_ipm_0", + TAO_Metrics_Utils::QUO, + this->tile_ipm_first_metrics_handle_); + + for (i = 1; i <= WSOA_METRICS_MAX_TILING_FACTOR; ++i) + { + ::sprintf (registration_name, "tile_ipm_%d", i); + + // We just throw the handles away rather than storing them, + // as they're always calculated by offset from the first. + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + temp_metrics_handle); + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + registration_name, + TAO_Metrics_Utils::QUO, + tile_decompression_handle); + } + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "zlib Compression", + TAO_Metrics_Utils::SCHED, + this->zlib_compression_handle_); + + REGISTER_METRICS_PROBE_RETURN(TAO_METRICS_REPORTING_CACHE_SINGLETON_TYPE::instance(), + base_metrics, + "zlib Compression", + TAO_Metrics_Utils::SCHED, + this->zlib_decompression_handle_); +#endif /* TAO_USES_REPORTING_METRICS */ +} + + + +#if !defined (__ACE_INLINE__) +#include "Metrics_Utils.i" +#endif /* __ACE_INLINE__ */ + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ + +#endif /* METRICS_UTILS_CPP */ + + diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.h b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.h new file mode 100644 index 00000000000..04963cbbecd --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.h @@ -0,0 +1,126 @@ +// $Id$ + +#ifndef METRICS_UTILS_H +#define METRICS_UTILS_H + +#if ! defined (VXWORKS) + +// Comment out both of these to disable output +# define METRICS_UTILS_ERROR_OUTPUT_ENABLED +# define METRICS_UTILS_DEBUG_OUTPUT_ENABLED + +#endif /* ! VXWORKS */ + +#include "ace/OS.h" +#include "orbsvcs/RtecSchedulerC.h" +#include "orbsvcs/MetricsC.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class TAO_ORBSVCS_Export TAO_Metrics_Utils +{ + // = TITLE + // Defines a class for various metrics utility functions. + // + // = DESCRIPTION + // This class provides static methods for various general + // purpose tasks for managing and using the metrics framework. + +public: + + // Type declarations + + enum Base_Metrics_Type {SCHED, QUO, RTARM, TNS, TEEC}; + + static const u_int METRICS_BUFSIZE; + // Constant size for local buffers. + + static const u_int METRICS_ENQUEUE_PROBE_ID_BASE; + static const u_int METRICS_DEQUEUE_PROBE_ID_BASE; + static const u_int METRICS_SCHED_PROBE_ID_BASE; + static const u_int METRICS_QUO_PROBE_ID_BASE; + static const u_int METRICS_TNS_PROBE_ID_BASE; + static const u_int METRICS_TEEC_PROBE_ID_BASE; + static const u_int METRICS_RTARM_PROBE_ID_BASE; + static const u_int METRICS_UPCALL_MONITOR_ADAPTER_ID_BASE; + // Constants for offsets into ranges of probe ids. + + static void set_mission_state (int i, Metrics::QoSLogger_ptr logger); + // Sets the mission state in the logger referenced by the passed pointer. + + static void set_mission_state (int i, const char * logger_ior_str); + // Sets the mission state in the logger referenced by the passed ior string. + + static Metrics::QoSLogger_var get_logger (const char * logger_ior_str, + CORBA::ORB_ptr orb_); + // Gets a pointer to a logger from the passed logger ior string, + // using the passed ORB. + + static RtecScheduler::handle_t timeoutEvent (void); + // Accessor for static timeout event handle. This handle is ignored + // by the QoS monitor, since by definition it will be dispatched + // after the end-of-frame. + + static void timeoutEvent (RtecScheduler::handle_t handle); + // Mutator for static timeout event handle. This handle is ignored + // by the QoS monitor, since by definition it will be dispatched + // after the end-of-frame. + +private: + + static RtecScheduler::handle_t timeoutEvent_; +}; + + +struct TAO_ORBSVCS_Export WSOA_Metrics_Handles +{ + // = TITLE + // Defines a helper class for WSOA METRICS INSTRUMENTATION. + // + // = DESCRIPTION + // This class provides a single point of initialization (registration) + // and storage for the handles used in WSOA metrics collection. It is necessary + // to define this class at this level to cross-cut multiple layers of the + // architecture and provide consistent points of instrumentation across layers. + +public: + + WSOA_Metrics_Handles (); + // Default constructor - registers all handles. + + // number of tile handles to reserve in each category. + static const u_int WSOA_METRICS_MAX_TILING_FACTOR; + + // global attribute to decide when image is downloaded. + u_long tiles_requested_; + + // Globally accessible handles for METRICS INSTRUMENTATION + RtecScheduler::handle_t compute_metrics_handle_; + RtecScheduler::handle_t RTARM_triggered_adaptation_metrics_handle_; + RtecScheduler::handle_t RTARM_region_transition_metrics_handle_; + RtecScheduler::handle_t QuO_contract_eval_metrics_handle_; + RtecScheduler::handle_t tile_request_delegate_metrics_handle_; + RtecScheduler::handle_t image_received_metrics_handle_; + RtecScheduler::handle_t image_processed_metrics_handle_; + RtecScheduler::handle_t image_quiescent_metrics_handle_; + RtecScheduler::handle_t tile_received_first_metrics_handle_; + RtecScheduler::handle_t tile_queuing_first_metrics_handle_; + RtecScheduler::handle_t tile_decompression_first_metrics_handle_; + RtecScheduler::handle_t tile_ipm_first_metrics_handle_; + RtecScheduler::handle_t tile_processed_first_metrics_handle_; + + RtecScheduler::handle_t zlib_compression_handle_; + RtecScheduler::handle_t zlib_decompression_handle_; +}; + +typedef ACE_Singleton +WSOA_METRICS_HANDLES_SINGLETON; + + +#if defined (__ACE_INLINE__) +#include "Metrics_Utils.i" +#endif /* __ACE_INLINE__ */ + +#endif /* METRICS_UTILS_H */ diff --git a/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.i b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.i new file mode 100644 index 00000000000..e66bd0c7d62 --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.i @@ -0,0 +1,33 @@ +// $Id$ + +#ifndef METRICS_UTILS_I +#define METRICS_UTILS_I + +///////////////////////////// +// Class TAO_Metrics_Utils // +///////////////////////////// + +// Accessor for static timeout event handle. This handle is ignored +// by the QoS monitor, since by definition it will be dispatched +// after the end-of-frame. + +ACE_INLINE +RtecScheduler::handle_t +TAO_Metrics_Utils::timeoutEvent (void) +{ + return TAO_Metrics_Utils::timeoutEvent_; +} + + +// Mutator for static timeout event handle. This handle is ignored +// by the QoS monitor, since by definition it will be dispatched +// after the end-of-frame. + +ACE_INLINE +void +TAO_Metrics_Utils::timeoutEvent (RtecScheduler::handle_t handle) +{ + TAO_Metrics_Utils::timeoutEvent_ = handle; +} + +#endif /* METRICS_UTILS_I */ diff --git a/TAO/orbsvcs/orbsvcs/Metrics/metrics_export.h b/TAO/orbsvcs/orbsvcs/Metrics/metrics_export.h new file mode 100644 index 00000000000..06e7155f7bf --- /dev/null +++ b/TAO/orbsvcs/orbsvcs/Metrics/metrics_export.h @@ -0,0 +1,50 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl Metrics +// ------------------------------ +#ifndef METRICS_EXPORT_H +#define METRICS_EXPORT_H + +#include "ace/config-all.h" + +#if !defined (METRICS_HAS_DLL) +# define METRICS_HAS_DLL 1 +#endif /* ! METRICS_HAS_DLL */ + +#if defined (METRICS_HAS_DLL) && (METRICS_HAS_DLL == 1) +# if defined (METRICS_BUILD_DLL) +# define Metrics_Export ACE_Proper_Export_Flag +# define METRICS_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define METRICS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* METRICS_BUILD_DLL */ +# define Metrics_Export ACE_Proper_Import_Flag +# define METRICS_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define METRICS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* METRICS_BUILD_DLL */ +#else /* METRICS_HAS_DLL == 1 */ +# define Metrics_Export +# define METRICS_SINGLETON_DECLARATION(T) +# define METRICS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* METRICS_HAS_DLL == 1 */ + +// Set METRICS_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (METRICS_NTRACE) +# if (ACE_NTRACE == 1) +# define METRICS_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define METRICS_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !METRICS_NTRACE */ + +#if (METRICS_NTRACE == 1) +# define METRICS_TRACE(X) +#else /* (METRICS_NTRACE == 1) */ +# define METRICS_TRACE(X) ACE_TRACE_IMPL(X) +#endif /* (METRICS_NTRACE == 1) */ + +#endif /* METRICS_EXPORT_H */ + +// End of auto generated file. -- cgit v1.2.1