summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstorri <storri@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-03-24 15:18:06 +0000
committerstorri <storri@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-03-24 15:18:06 +0000
commit65bf27f326a3b16fe8c513f304f4c50563ea2516 (patch)
tree5a69083a8f10d9cca483a6c3604087af8790de20
parent398d7f80677b8459d3044d1d2a018b75086e5a44 (diff)
downloadATCD-65bf27f326a3b16fe8c513f304f4c50563ea2516.tar.gz
Adding Metrics to TAO orbsvcs
-rw-r--r--TAO/orbsvcs/orbsvcs/Makefile7
-rw-r--r--TAO/orbsvcs/orbsvcs/Makefile.Metrics111
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics.idl331
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.cpp14
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.h34
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager.i9
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.cpp14
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.h276
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_FrameManager_T.i821
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.cpp29
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.h51
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache.i10
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.cpp490
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.h329
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_LocalCache_T.i1556
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.cpp892
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_Logger.h217
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.cpp20
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.h262
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor.i371
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.cpp25
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.h157
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_UpcallMonitor_T.i256
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.cpp526
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.h126
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/Metrics_Utils.i33
-rw-r--r--TAO/orbsvcs/orbsvcs/Metrics/metrics_export.h50
27 files changed, 7016 insertions, 1 deletions
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<RtecScheduler::handle_t> 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_t> 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_t> 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_t> 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<ACE_SYNCH_MUTEX>
+TAO_METRICS_FRAME_MGR_TYPE;
+
+typedef ACE_Singleton<TAO_METRICS_FRAME_MGR_TYPE, ACE_SYNCH_MUTEX>
+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 <class ACE_LOCK>
+struct TAO_Metrics_Frame_Manager_Data
+{
+ // = TITLE
+ // Defines a class for time frame management data.
+ //
+ // = DESCRIPTION
+ // This class makes use of the <ACE_Time_Value> 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 ACE_LOCK>
+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 <ACE_Metrics_Cache> class to
+ // implement a cache for local use.
+public:
+
+ typedef TAO_Metrics_FrameManager<ACE_LOCK> TAO_METRICS_FRAME_MANAGER_TYPE;
+ typedef TAO_Metrics_Frame_Manager_Data<ACE_LOCK> TAO_METRICS_FRAME_MANAGER_DATA_TYPE;
+
+ typedef ACE_Hash_Map_Manager_Ex<RtecScheduler::Period_t,
+ TAO_METRICS_FRAME_MANAGER_DATA_TYPE *,
+ ACE_Hash<RtecScheduler::Period_t>,
+ ACE_Equal_To<RtecScheduler::Period_t>,
+ 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<RtecScheduler::Period_t,
+ TAO_METRICS_FRAME_MANAGER_DATA_TYPE *>
+ METRICS_FRAME_DATA_MAP_ENTRY;
+ // Type of entry in monitor map.
+
+ typedef ACE_Hash_Map_Iterator_Ex<RtecScheduler::Period_t,
+ TAO_METRICS_FRAME_MANAGER_DATA_TYPE *,
+ ACE_Hash<RtecScheduler::Period_t>,
+ ACE_Equal_To<RtecScheduler::Period_t>,
+ 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<ACE_LOCK> & 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<ACE_LOCK> & 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 <class ACE_LOCK>
+ACE_INLINE
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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 <class ACE_LOCK>
+ACE_INLINE
+TAO_Metrics_FrameManager<ACE_LOCK>::
+~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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> mon (this->lock_);
+ if (mon.locked () == 0)
+ {
+ ACE_THROW_RETURN (Metrics::SYNCHRONIZATION (), -1);
+ }
+
+ int result = 0;
+ TAO_Metrics_Frame_Manager_Data<ACE_LOCK> * data = 0;
+ if (frame_data_map_.find (p) != 0)
+ {
+ ACE_NEW_RETURN (data, TAO_Metrics_Frame_Manager_Data<ACE_LOCK> (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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> * data;
+
+ // Synchronize write access to the map during pointer lookup only
+ ACE_Read_Guard<ACE_LOCK> 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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> * data;
+
+ // Synchronize write access to the map during pointer lookup only
+ ACE_Read_Guard<ACE_LOCK> 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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+reset_all_frames (const ACE_Time_Value& tv)
+{
+ // Synchronize read/write access to the map during the reset
+ ACE_Write_Guard<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> * data;
+
+ // Synchronize write access to the map during lookup only
+ ACE_Read_Guard<ACE_LOCK> 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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> * data;
+
+ // Synchronize write access to the map during lookup only
+ ACE_Read_Guard<ACE_LOCK> 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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> * data;
+
+ // Synchronize write access to the map during lookup only
+ ACE_Read_Guard<ACE_LOCK> 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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> * data = 0;
+
+ // Synchronize write access to the map during lookup only
+ ACE_Read_Guard<ACE_LOCK> 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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> * data;
+
+ // Synchronize write access to the map during lookup only
+ ACE_Read_Guard<ACE_LOCK> 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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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<ACE_LOCK> * data;
+
+ // Synchronize write access to the map during lookup only
+ ACE_Read_Guard<ACE_LOCK> 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<ACE_LOCK> 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+update_data (TAO_Metrics_Frame_Manager_Data<ACE_LOCK> & 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 <class ACE_LOCK>
+ACE_INLINE CORBA::Short
+TAO_Metrics_FrameManager<ACE_LOCK>::
+reset_data (TAO_Metrics_Frame_Manager_Data<ACE_LOCK> & 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<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data *>;
+template class ACE_Hash_Map_Entry<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data_Base *>;
+template class ACE_Hash_Map_Manager_Ex<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data *, ACE_Hash<int>, ACE_Equal_To<int>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Manager_Ex<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data_Base *, ACE_Hash<int>, ACE_Equal_To<int>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator_Base_Ex<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data_Base *, ACE_Hash<int>, ACE_Equal_To<int>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator_Base_Ex<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data *, ACE_Hash<int>, ACE_Equal_To<int>, ACE_Null_Mutex>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Hash_Map_Entry<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data *>
+#pragma instantiate ACE_Hash_Map_Entry<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data_Base *>
+#pragma instantiate ACE_Hash_Map_Manager_Ex<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data *, ACE_Hash<int>, ACE_Equal_To<int>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Manager_Ex<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data_Base *, ACE_Hash<int>, ACE_Equal_To<int>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data_Base *, ACE_Hash<int>, ACE_Equal_To<int>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<int, TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>::TAO_Metrics_Cache_Data *, ACE_Hash<int>, ACE_Equal_To<int>, 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<ACE_SYNCH_MUTEX, ACE_New_Allocator>
+TAO_METRICS_CACHE_TYPE;
+
+typedef ACE_Singleton<TAO_METRICS_CACHE_TYPE, ACE_SYNCH_MUTEX>
+TAO_METRICS_CACHE_SINGLETON_TYPE;
+
+typedef TAO_Metrics_ReportingLocalCache<ACE_SYNCH_MUTEX, ACE_New_Allocator>
+TAO_METRICS_REPORTING_CACHE_TYPE;
+
+typedef ACE_Singleton<TAO_METRICS_REPORTING_CACHE_TYPE, ACE_SYNCH_MUTEX>
+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 <cacheLib.h>
+#endif
+
+//////////////////////////////////////
+// Class TAO_Metrics_LocalTimeprobe //
+//////////////////////////////////////
+
+// Default constructor.
+
+template <class ACE_LOCK, class ALLOCATOR>
+TAO_Metrics_LocalTimeprobe<ACE_LOCK, ALLOCATOR>::
+TAO_Metrics_LocalTimeprobe (u_int id,
+ const char *name,
+ u_long size,
+ ALLOCATOR * alloc)
+ : ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> (alloc, id, name, size),
+ is_operation_ (0),
+ is_hrt_ (0),
+ data_set_ (0)
+{
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+void
+TAO_Metrics_LocalTimeprobe<ACE_LOCK, ALLOCATOR>::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<ACE_LOCK, ALLOCATOR>::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<ACE_LOCK, ALLOCATOR>::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<ACE_LOCK, ALLOCATOR>::WORK_SUSPEND)
+#else
+ else if (this->timeprobes ()[stop_or_suspend_evt_ndx].event_.event_number_ == (u_long)
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::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<ACE_LOCK, ALLOCATOR>::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<ACE_LOCK, ALLOCATOR>::WORK_START) ||
+ is_event (this->timeprobes ()[resume_evt_ndx],
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::WORK_STOP) ||
+ is_event (this->timeprobes ()[resume_evt_ndx],
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::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<ACE_LOCK, ALLOCATOR>::WORK_START) ||
+ is_event (this->timeprobes ()[stop_or_suspend_evt_ndx],
+ ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>::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 <class ACE_LOCK, class ALLOCATOR>
+void
+TAO_Metrics_LocalTimeprobe<ACE_LOCK, ALLOCATOR>::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 <class ACE_LOCK, class ALLOCATOR>
+void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::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 <class ACE_LOCK, class ALLOCATOR>
+void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+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<ACE_LOCK, ALLOCATOR>));
+
+ // 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<ACE_LOCK,ALLOCATOR> *));
+ // cacheFlush (
+ // DATA_CACHE,
+ // this->dequeue_probes_ [this->consumer_index_],
+ // this->probe_set_size_
+ // * sizeof (ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR> *));
+
+ // 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<ACE_LOCK, ALLOCATOR>));
+ // cacheFlush (
+ // DATA_CACHE,
+ // this->dequeue_probes_ [this->consumer_index_][i],
+ // sizeof (ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>));
+ // }
+#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<char> ACE_METRICS_STRING_TYPE;
+ typedef ACE_Based_Pointer<Metrics::TimeprobeParameter_Set> 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 ACE_LOCK, class ALLOCATOR>
+class TAO_Metrics_LocalTimeprobe
+ : public ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>
+{
+ // = TITLE
+ // Defines a class that implements a local timeprobe.
+ //
+ // = DESCRIPTION
+ // This class makes use of the <ACE_Metrics_Timeprobe> class to
+ // implement a timeprobe for use in a local metrics cache.
+public:
+
+ typedef TAO_Metrics_LocalTimeprobe<ACE_LOCK, ALLOCATOR> 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 ACE_LOCK, class ALLOCATOR>
+class TAO_Metrics_LocalCache
+ : public ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR>
+{
+ // = TITLE
+ // Defines a class that implements a local metrics cache.
+ //
+ // = DESCRIPTION
+ // This class makes use of the <ACE_Metrics_Cache> class to
+ // implement a cache for local use.
+public:
+
+ typedef ACE_Metrics_Timeprobe<ACE_LOCK, ALLOCATOR>
+ ACE_METRICS_TIMEPROBE_TYPE;
+
+#if defined (ACE_HAS_METRICS_BASE_POINTERS)
+ typedef ACE_Based_Pointer<ACE_METRICS_TIMEPROBE_TYPE>
+ ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE;
+#else
+ typedef ACE_METRICS_TIMEPROBE_TYPE * ACE_METRICS_TIMEPROBE_BASED_PTR_TYPE;
+#endif
+
+ typedef TAO_Metrics_LocalTimeprobe<ACE_LOCK, ALLOCATOR> TAO_METRICS_TIMEPROBE_TYPE;
+
+ typedef TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR> TAO_METRICS_CACHE_TYPE;
+
+ struct TAO_Metrics_Cache_Data_Base
+ {
+ ACE_METRICS_STRING_TYPE probe_name;
+ TAO_Metrics_LocalTimeprobe<ACE_LOCK, ALLOCATOR> 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<TAO_Metrics_Cache_Data_Base> ACE_METRICS_CACHE_DATA_BASE_TYPE;
+ typedef ACE_Based_Pointer<TAO_Metrics_Cache_Data> 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<RtecScheduler::handle_t,
+ ACE_METRICS_CACHE_DATA_BASE_TYPE,
+ ACE_Hash<RtecScheduler::handle_t>,
+ ACE_Equal_To<RtecScheduler::handle_t>,
+ 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<RtecScheduler::handle_t,
+ ACE_METRICS_CACHE_DATA_BASE_TYPE >
+ METRICS_BASE_MONITOR_MAP_ENTRY;
+ // Type of entry in monitor map.
+
+ typedef ACE_Hash_Map_Iterator_Ex<RtecScheduler::handle_t,
+ ACE_METRICS_CACHE_DATA_BASE_TYPE,
+ ACE_Hash<RtecScheduler::handle_t>,
+ ACE_Equal_To<RtecScheduler::handle_t>,
+ ACE_Null_Mutex>
+ METRICS_BASE_MONITOR_MAP_ITERATOR;
+ // Type of iterator for monitor map.
+
+ typedef ACE_Hash_Map_Manager_Ex<RtecScheduler::handle_t,
+ ACE_METRICS_CACHE_DATA_TYPE,
+ ACE_Hash<RtecScheduler::handle_t>,
+ ACE_Equal_To<RtecScheduler::handle_t>,
+ ACE_Null_Mutex> METRICS_MONITOR_MAP;
+ // Type of map used for O(1) lookup of monitored data for operations.
+
+ typedef ACE_Hash_Map_Entry<RtecScheduler::handle_t,
+ ACE_METRICS_CACHE_DATA_TYPE >
+ METRICS_MONITOR_MAP_ENTRY;
+ // Type of entry in monitor map.
+
+ typedef ACE_Hash_Map_Iterator_Ex<RtecScheduler::handle_t,
+ ACE_METRICS_CACHE_DATA_TYPE,
+ ACE_Hash<RtecScheduler::handle_t>,
+ ACE_Equal_To<RtecScheduler::handle_t>,
+ 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 ACE_LOCK, class ALLOCATOR>
+class TAO_Metrics_ReportingLocalCache
+ : public TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>
+{
+ // = TITLE
+ // Defines a class that adds metrics logger reporting to a local cache.
+ //
+ // = DESCRIPTION
+ // This class makes use of the <TAO_Metrics_LocalCache> 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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_LocalTimeprobe<ACE_LOCK, ALLOCATOR>::
+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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE ACE_Time_Value
+TAO_Metrics_LocalTimeprobe<ACE_LOCK, ALLOCATOR>::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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+TAO_Metrics_LocalCache (u_long table_size,
+ u_long number_of_probes,
+ ALLOCATOR * alloc)
+ : ACE_Metrics_Cache<ACE_LOCK, ALLOCATOR> (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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE int
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::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<TAO_METRICS_TIMEPROBE_TYPE *>(enqueue_probes_ [0].addr () [i].addr ());
+ probe_ptr = static_cast<TAO_METRICS_TIMEPROBE_TYPE *>(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<TAO_METRICS_TIMEPROBE_TYPE *>(enqueue_probes_ [1].addr () [i].addr ());
+ probe_ptr = static_cast<TAO_METRICS_TIMEPROBE_TYPE *>(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 <TAO_METRICS_TIMEPROBE_TYPE *>(dequeue_probes_ [0].addr () [i].addr ());
+ probe_ptr = static_cast <TAO_METRICS_TIMEPROBE_TYPE *>(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 <TAO_METRICS_TIMEPROBE_TYPE *>(dequeue_probes_ [1].addr () [i].addr ());
+ probe_ptr = static_cast <TAO_METRICS_TIMEPROBE_TYPE *>(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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE RtecScheduler::handle_t
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::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<ACE_LOCK, ALLOCATOR>::
+ 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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE int
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+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<ACE_LOCK, ALLOCATOR>::
+ 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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::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<ACE_LOCK, ALLOCATOR>::
+ WORK_START);
+ }
+}
+
+
+// Inline: Records stop time of a base metrics segment.
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+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<ACE_LOCK, ALLOCATOR>::
+ WORK_STOP);
+
+ this->interval_end_ =
+ base_data_tmp->probe.last_recorded_timestamp ();
+ }
+}
+
+// Inline: Records suspend time of a base metrics segment.
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+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<ACE_LOCK, ALLOCATOR>::
+ WORK_SUSPEND);
+
+ this->interval_end_ =
+ base_data_tmp->probe.last_recorded_timestamp ();
+ }
+}
+
+
+// Inline: Records resume time of a base metrics segment.
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+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<ACE_LOCK, ALLOCATOR>::
+ WORK_RESUME);
+
+ this->interval_end_ =
+ base_data_tmp->probe.last_recorded_timestamp ();
+ }
+}
+
+template <class ACE_LOCK, class ALLOCATOR>
+void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+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 <class ACE_LOCK, class ALLOCATOR>
+void
+TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR>::
+increment_upcall_handle()
+{
+ ++this->upcall_adapter_count_;
+}
+
+///////////////////////////////////////////
+// Class TAO_Metrics_ReportingLocalCache //
+///////////////////////////////////////////
+
+
+// Default constructor.
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE
+TAO_Metrics_ReportingLocalCache<ACE_LOCK, ALLOCATOR>::
+TAO_Metrics_ReportingLocalCache (u_long table_size,
+ u_long number_of_probes,
+ ALLOCATOR * alloc)
+ : TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR> (table_size, number_of_probes, alloc)
+{
+}
+
+
+// Registers probes with the logger.
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE int
+TAO_Metrics_ReportingLocalCache<ACE_LOCK, ALLOCATOR>::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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_ReportingLocalCache<ACE_LOCK, ALLOCATOR>::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<ACE_LOCK, ALLOCATOR>::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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_ReportingLocalCache<ACE_LOCK, ALLOCATOR>::
+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<ACE_LOCK, ALLOCATOR> *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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE RtecScheduler::handle_t
+TAO_Metrics_ReportingLocalCache<ACE_LOCK, ALLOCATOR>::
+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<ACE_LOCK, ALLOCATOR> *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<CORBA::String_var> 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<CORBA::ULong>;
+// The below template already instantiated in ../ace/Funchtor.h
+// template class ACE_Hash<CORBA::ULong>;
+template class ACE_Hash_Map_Manager_Ex<CORBA::ULong, CORBA::String_var *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator_Base_Ex<CORBA::ULong, CORBA::String_var *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Iterator_Ex<CORBA::ULong, CORBA::String_var *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Reverse_Iterator_Ex<CORBA::ULong, CORBA::String_var *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>;
+template class ACE_Hash_Map_Entry<CORBA::ULong, CORBA::String_var *>;
+#elif defined(ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Equal_To<CORBA::ULong>
+//#pragma instantiate ACE_Hash<CORBA::ULong>
+#pragma instantiate ACE_Hash_Map_Manager_Ex<CORBA::ULong, CORBA::String_var *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<CORBA::ULong, CORBA::String_var *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Iterator_Ex<CORBA::ULong, CORBA::String_var *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<CORBA::ULong, CORBA::String_var *, ACE_Hash<CORBA::ULong>, ACE_Equal_To<CORBA::ULong>, ACE_Null_Mutex>
+#pragma instantiate ACE_Hash_Map_Entry<CORBA::ULong, CORBA::String_var *>
+#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<ACE_MT_SYNCH>, 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<CORBA::ULong,
+ CORBA::String_var *,
+ ACE_Hash<CORBA::ULong>,
+ ACE_Equal_To<CORBA::ULong>,
+ ACE_Null_Mutex> PROBE_NAME_MAP;
+ // Type of map used for O(1) lookup of probe names.
+
+ typedef ACE_Hash_Map_Entry<CORBA::ULong, CORBA::String_var> 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<Metrics::QoSLogger_var, ACE_SYNCH_MUTEX>
+TAO_METRICS_LOGGER_REF_SINGLETON;
+
+typedef ACE_Singleton<TAO_Metrics_Logger, ACE_SYNCH_MUTEX>
+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<ACE_Thread_Mutex, ACE_New_Allocator>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate TAO_Metrics_LocalCache<ACE_Thread_Mutex, ACE_New_Allocator>
+#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<RtecScheduler::handle_t,
+ CORBA::ULong,
+ ACE_Hash<RtecScheduler::handle_t>,
+ ACE_Equal_To<RtecScheduler::handle_t>,
+ 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<RtecScheduler::handle_t, CORBA::ULong>
+ MONITOR_MAP_ENTRY;
+ // Type of map used for O(1) lookup of RT_Infos by their handles.
+
+ typedef ACE_Hash_Map_Iterator_Ex<RtecScheduler::handle_t,
+ CORBA::ULong,
+ ACE_Hash<RtecScheduler::handle_t>,
+ ACE_Equal_To<RtecScheduler::handle_t>,
+ 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<RtecScheduler::handle_t,
+ CORBA::ULong,
+ ACE_Hash<RtecScheduler::handle_t>,
+ ACE_Equal_To<RtecScheduler::handle_t>,
+ 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<RtecScheduler::handle_t, CORBA::ULong>
+ MONITOR_MAP_ENTRY;
+ // Type of map used for O(1) lookup of RT_Infos by their handles.
+
+ typedef ACE_Hash_Map_Iterator_Ex<RtecScheduler::handle_t,
+ CORBA::ULong,
+ ACE_Hash<RtecScheduler::handle_t>,
+ ACE_Equal_To<RtecScheduler::handle_t>,
+ 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<ACE_SYNCH_MUTEX, ACE_New_Allocator>
+TAO_METRICS_MONITOR_ADAPTER_TYPE;
+
+typedef TAO_Metrics_ReportingUpcallMonitorAdapter<ACE_SYNCH_MUTEX, ACE_New_Allocator>
+TAO_METRICS_REPORTING_MONITOR_ADAPTER_TYPE;
+
+typedef ACE_Singleton<TAO_Metrics_UpcallMonitor, ACE_SYNCH_MUTEX>
+TAO_METRICS_MONITOR_SINGLETON_TYPE;
+
+typedef ACE_Singleton<TAO_Metrics_ReportingUpcallMonitor, ACE_SYNCH_MUTEX>
+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 <class ACE_LOCK, class ALLOCATOR>
+TAO_Metrics_UpcallMonitorAdapter<ACE_LOCK, ALLOCATOR>::
+~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 ACE_LOCK, class ALLOCATOR>
+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<ACE_LOCK, ALLOCATOR> & cache,
+ TAO_Metrics_FrameManager<ACE_LOCK> & 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<ACE_LOCK, ALLOCATOR> & cache_;
+ // A reference to the metrics data cache to which we report.
+
+ TAO_Metrics_FrameManager<ACE_LOCK> & 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 ACE_LOCK, class ALLOCATOR>
+class TAO_Metrics_ReportingUpcallMonitorAdapter
+ : public TAO_Metrics_UpcallMonitorAdapter <ACE_LOCK, ALLOCATOR>
+{
+ // = 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<ACE_LOCK, ALLOCATOR> & cache,
+ TAO_Metrics_FrameManager<ACE_LOCK> & 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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE
+TAO_Metrics_UpcallMonitorAdapter<ACE_LOCK, ALLOCATOR>::
+TAO_Metrics_UpcallMonitorAdapter (
+ POA_Metrics::QoSMonitor & monitor,
+ TAO_Metrics_LocalCache<ACE_LOCK, ALLOCATOR> &cache,
+ TAO_Metrics_FrameManager<ACE_LOCK> &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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE RtecScheduler::Period_t
+TAO_Metrics_UpcallMonitorAdapter<ACE_LOCK, ALLOCATOR>::
+get_period ()
+{
+ return this->period_;
+}
+
+
+// Set the current priod for the adapter.
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_UpcallMonitorAdapter<ACE_LOCK, ALLOCATOR>::
+set_period (RtecScheduler::Period_t period)
+{
+ this->period_ = period;
+}
+
+
+// Do a monitored push to the actual PushConsumer for which we're a proxy
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_UpcallMonitorAdapter<ACE_LOCK, ALLOCATOR>::
+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 <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE void
+TAO_Metrics_UpcallMonitorAdapter<ACE_LOCK, ALLOCATOR>::
+disconnect_push_consumer (CORBA::Environment &ACE_TRY_ENV)
+{
+ consumer_.disconnect_push_consumer (ACE_TRY_ENV);
+}
+
+
+template <class ACE_LOCK, class ALLOCATOR>
+ACE_INLINE
+TAO_Metrics_ReportingUpcallMonitorAdapter<ACE_LOCK, ALLOCATOR>::
+TAO_Metrics_ReportingUpcallMonitorAdapter (
+ POA_Metrics::QoSMonitor & monitor,
+ TAO_Metrics_ReportingLocalCache<ACE_LOCK, ALLOCATOR> &cache,
+ TAO_Metrics_FrameManager<ACE_LOCK> &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<ACE_LOCK, ALLOCATOR>
+ (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<WSOA_Metrics_Handles, ACE_Thread_Mutex>;
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+#pragma instantiate ACE_Singleton<WSOA_Metrics_Handles, ACE_Thread_Mutex>
+#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, ACE_SYNCH_MUTEX>
+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.