add TimeProbe class to data collection framework

This commit is contained in:
Tom Henderson
2014-10-15 07:06:11 -07:00
parent 5b64122a3e
commit 203c408a67
12 changed files with 498 additions and 0 deletions

View File

@@ -57,6 +57,11 @@ us a note on ns-developers mailing list.</p>
<li> It is now possible to print the Neighbor Cache (ARP and NDISC) by using
the RoutingProtocolHelper
</li>
<li> A TimeProbe class has been added to the data collection framework in
the stats module, enabling TracedValues emitting values of type
ns3::Time to be handled by the framework.
</li>
</ul>
<h2>Changes to existing API:</h2>

View File

@@ -25,6 +25,8 @@ New user-visible features
the RoutingProtocolHelper
- The PrintRoutingTable... and PrintNeighborCache... are now static funtions
i.e., it's not anymore needed to instantiate an helper just to use them.
- A new TimeProbe class has been added to hook the data collection framework
to traced values emitting Time objects
Bugs fixed
----------

View File

@@ -359,6 +359,8 @@ The following traced values are supported with Probes as of this writing:
+------------------+-------------------+------------------------------------+
| bool | BooleanProbe | stats/model/uinteger-16-probe.h |
+------------------+-------------------+------------------------------------+
| ns3::Time | TimeProbe | stats/model/time-probe.h |
+------------------+-------------------+------------------------------------+
The following TraceSource types are supported by Probes as of this writing:

View File

@@ -605,6 +605,7 @@ to the GnuplotHelper and to the FileHelper:
- Uinteger8Probe
- Uinteger16Probe
- Uinteger32Probe
- TimeProbe
- PacketProbe
- ApplicationPacketProbe
- Ipv4PacketProbe

View File

@@ -18,6 +18,7 @@ Currently, only these Probes have been implemented in DCF:
- Uinteger8Probe
- Uinteger16Probe
- Uinteger32Probe
- TimeProbe
- PacketProbe
- ApplicationPacketProbe
- Ipv4PacketProbe

View File

@@ -0,0 +1,247 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014 University of Washington
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//
// This example is designed to show the main features of an ns3::TimeProbe.
// A test object is used to emit values through a trace source. The
// example shows three ways to use a ns3::TimeProbe to hook the output
// of this trace source (in addition to hooking the raw trace source).
//
// It produces two types of output. By default, it will generate a
// gnuplot of interarrival times. If the '--verbose=1' argument is passed,
// it will also generate debugging output of the form (for example):
//
// Emitting at 96.5378 seconds
// context: raw trace source old 0.293343 new 0.00760254
// context: probe1 old 0.293343 new 0.00760254
// context: probe2 old 0.293343 new 0.00760254
// context: probe3 old 0.293343 new 0.00760254
//
// The stopTime defaults to 100 seconds but can be changed by an argument.
//
#include <string>
#include "ns3/core-module.h"
#include "ns3/time-probe.h"
#include "ns3/gnuplot-helper.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("TimeProbeExample");
//
// This is our test object, an object that emits values according to
// a Poisson arrival process. It emits a traced Time value as a
// trace source; this takes the value of interarrival time
//
class Emitter : public Object
{
public:
static TypeId GetTypeId (void);
Emitter ();
private:
void DoInitialize (void);
// void Emit (void);
void Emit (void);
TracedValue<Time> m_interval;
Time m_last;
Ptr<ExponentialRandomVariable> m_var;
};
NS_OBJECT_ENSURE_REGISTERED (Emitter);
TypeId
Emitter::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::Emitter")
.AddConstructor<Emitter> ()
.SetParent<Object> ()
.AddTraceSource ("Interval",
"Trace source",
MakeTraceSourceAccessor (&Emitter::m_interval))
;
return tid;
}
Emitter::Emitter (void)
: m_interval (Seconds (0)),
m_last (Seconds (0))
{
m_var = CreateObject<ExponentialRandomVariable> ();
}
void
Emitter::DoInitialize (void)
{
Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Emit, this);
}
void
Emitter::Emit (void)
{
NS_LOG_DEBUG ("Emitting at " << Simulator::Now ().GetSeconds () << " seconds");
m_interval = Simulator::Now () - m_last;
m_last = Simulator::Now ();
TimeProbe::SetValueByPath ("/Names/probe3", m_interval);
Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Emit, this);
}
// This is a function to test hooking a raw function to the trace source
void
NotifyViaTraceSource (std::string context, Time oldVal, Time newVal)
{
BooleanValue verbose;
GlobalValue::GetValueByName ("verbose", verbose);
if (verbose.Get ())
{
std::cout << "context: " << context << " old " << oldVal.GetSeconds () << " new " << newVal.GetSeconds () << std::endl;
}
}
// This is a function to test hooking it to the probe output
void
NotifyViaProbe (std::string context, double oldVal, double newVal)
{
BooleanValue verbose;
GlobalValue::GetValueByName ("verbose", verbose);
if (verbose.Get ())
{
std::cout << "context: " << context << " old " << oldVal << " new " << newVal << std::endl;
}
}
static ns3::GlobalValue g_verbose ("verbose",
"Whether to enable verbose output",
ns3::BooleanValue (false),
ns3::MakeBooleanChecker ());
int main (int argc, char *argv[])
{
double stopTime = 100.0;
bool verbose = false;
CommandLine cmd;
cmd.AddValue ("stopTime", "Time (seconds) to terminate simulation", stopTime);
cmd.AddValue ("verbose", "Whether to enable verbose output", verbose);
cmd.Parse (argc, argv);
bool connected;
// Set a global value, so that the callbacks can access it
if (verbose)
{
GlobalValue::Bind ("verbose", BooleanValue (true));
LogComponentEnable ("TimeProbeExample", LOG_LEVEL_ALL);
}
Ptr<Emitter> emitter = CreateObject<Emitter> ();
Names::Add ("/Names/Emitter", emitter);
//
// The below shows typical functionality without a probe
// (connect a sink function to a trace source)
//
connected = emitter->TraceConnect ("Interval", "raw trace source", MakeCallback (&NotifyViaTraceSource));
NS_ASSERT_MSG (connected, "Trace source not connected");
//
// Next, we'll show several use cases of using a Probe to access and
// filter the values of the underlying trace source
//
//
// Probe1 will be hooked directly to the Emitter trace source object
//
// probe1 will be hooked to the Emitter trace source
Ptr<TimeProbe> probe1 = CreateObject<TimeProbe> ();
// the probe's name can serve as its context in the tracing
probe1->SetName ("probe1");
// Connect the probe to the emitter's Interval
connected = probe1->ConnectByObject ("Interval", emitter);
NS_ASSERT_MSG (connected, "Trace source not connected to probe1");
// The probe itself should generate output. The context that we provide
// to this probe (in this case, the probe name) will help to disambiguate
// the source of the trace
connected = probe1->TraceConnect ("Output", probe1->GetName (), MakeCallback (&NotifyViaProbe));
NS_ASSERT_MSG (connected, "Trace source not connected to probe1 Output");
//
// Probe2 will be hooked to the Emitter trace source object by
// accessing it by path name in the Config database
//
// Create another similar probe; this will hook up via a Config path
Ptr<TimeProbe> probe2 = CreateObject<TimeProbe> ();
probe2->SetName ("probe2");
// Note, no return value is checked here
probe2->ConnectByPath ("/Names/Emitter/Interval");
// The probe itself should generate output. The context that we provide
// to this probe (in this case, the probe name) will help to disambiguate
// the source of the trace
connected = probe2->TraceConnect ("Output", "probe2", MakeCallback (&NotifyViaProbe));
NS_ASSERT_MSG (connected, "Trace source not connected to probe2 Output");
//
// Probe3 will be called by the emitter directly through the
// static method SetValueByPath().
//
Ptr<TimeProbe> probe3 = CreateObject<TimeProbe> ();
probe3->SetName ("probe3");
// By adding to the config database, we can access it later
Names::Add ("/Names/probe3", probe3);
// The probe itself should generate output. The context that we provide
// to this probe (in this case, the probe name) will help to disambiguate
// the source of the trace
connected = probe3->TraceConnect ("Output", "probe3", MakeCallback (&NotifyViaProbe));
NS_ASSERT_MSG (connected, "Trace source not connected to probe3 Output");
// Plot the interval values
GnuplotHelper plotHelper;
plotHelper.ConfigurePlot ("time-probe-example",
"Emitter interarrivals vs. Time",
"Simulation time (Seconds)",
"Interarrival time (Seconds)",
"png");
// Helper creates a TimeProbe and hooks it to the /Names/Emitter/Interval
// source. Helper also takes the Output of the TimeProbe and plots it
// as a dataset labeled 'Emitter Interarrival Time'
plotHelper.PlotProbe ("ns3::TimeProbe",
"/Names/Emitter/Interval",
"Output",
"Emitter Interarrival Time",
GnuplotAggregator::KEY_INSIDE);
// The Emitter object is not associated with an ns-3 node, so
// it won't get started automatically, so we need to do this ourselves
Simulator::Schedule (Seconds (0.0), &Emitter::Initialize, emitter);
Simulator::Stop (Seconds (stopTime));
Simulator::Run ();
Simulator::Destroy ();
return 0;
}

View File

@@ -10,6 +10,9 @@ def build(bld):
program = bld.create_ns3_program('double-probe-example', ['network', 'stats'])
program.source = 'double-probe-example.cc'
program = bld.create_ns3_program('time-probe-example', ['stats'])
program.source = 'time-probe-example.cc'
program = bld.create_ns3_program('gnuplot-aggregator-example', ['network', 'stats'])
program.source = 'gnuplot-aggregator-example.cc'

View File

@@ -543,6 +543,13 @@ FileHelper::ConnectProbeToAggregator (const std::string &typeId,
MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
m_timeSeriesAdaptorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::TimeProbe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
MakeCallback (&TimeSeriesAdaptor::TraceSinkDouble,
m_timeSeriesAdaptorMap[probeContext]));
}
else
{
NS_FATAL_ERROR ("Unknown probe type " << m_probeMap[probeName].second << "; need to add support in the helper for this");

View File

@@ -403,6 +403,13 @@ GnuplotHelper::ConnectProbeToAggregator (const std::string &typeId,
MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
m_timeSeriesAdaptorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::TimeProbe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
MakeCallback (&TimeSeriesAdaptor::TraceSinkDouble,
m_timeSeriesAdaptorMap[probeContext]));
}
else
{
NS_FATAL_ERROR ("Unknown probe type " << m_probeMap[probeName].second << "; need to add support in the helper for this");

View File

@@ -0,0 +1,111 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
* Tiago G. Rodrigues (tgr002@bucknell.edu)
*
* Modified by: Mitch Watrous (watrous@u.washington.edu)
*
*/
#include "ns3/time-probe.h"
#include "ns3/object.h"
#include "ns3/log.h"
#include "ns3/names.h"
#include "ns3/config.h"
#include "ns3/trace-source-accessor.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("TimeProbe");
NS_OBJECT_ENSURE_REGISTERED (TimeProbe);
TypeId
TimeProbe::GetTypeId ()
{
static TypeId tid = TypeId ("ns3::TimeProbe")
.SetParent<Probe> ()
.AddConstructor<TimeProbe> ()
.AddTraceSource ("Output",
"The double valued (units of seconds) probe output",
MakeTraceSourceAccessor (&TimeProbe::m_output))
;
return tid;
}
TimeProbe::TimeProbe ()
{
NS_LOG_FUNCTION (this);
m_output = 0;
}
TimeProbe::~TimeProbe ()
{
NS_LOG_FUNCTION (this);
}
double
TimeProbe::GetValue (void) const
{
NS_LOG_FUNCTION (this);
return m_output;
}
void
TimeProbe::SetValue (Time newVal)
{
NS_LOG_FUNCTION (this << newVal.GetSeconds ());
m_output = newVal.GetSeconds ();
}
void
TimeProbe::SetValueByPath (std::string path, Time newVal)
{
NS_LOG_FUNCTION (path << newVal.GetSeconds ());
Ptr<TimeProbe> probe = Names::Find<TimeProbe> (path);
NS_ASSERT_MSG (probe, "Error: Can't find probe for path " << path);
probe->SetValue (newVal);
}
bool
TimeProbe::ConnectByObject (std::string traceSource, Ptr<Object> obj)
{
NS_LOG_FUNCTION (this << traceSource << obj);
NS_LOG_DEBUG ("Name of trace source (if any) in names database: " << Names::FindPath (obj));
bool connected = obj->TraceConnectWithoutContext (traceSource, MakeCallback (&ns3::TimeProbe::TraceSink, this));
return connected;
}
void
TimeProbe::ConnectByPath (std::string path)
{
NS_LOG_FUNCTION (this << path);
NS_LOG_DEBUG ("Name of trace source to search for in config database: " << path);
Config::ConnectWithoutContext (path, MakeCallback (&ns3::TimeProbe::TraceSink, this));
}
void
TimeProbe::TraceSink (Time oldData, Time newData)
{
NS_LOG_FUNCTION (this << oldData.GetSeconds () << newData.GetSeconds ());
if (IsEnabled ())
{
m_output = newData.GetSeconds ();
}
}
} // namespace ns3

View File

@@ -0,0 +1,110 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2011 Bucknell University
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
* Tiago G. Rodrigues (tgr002@bucknell.edu)
*
* Modified by: Mitch Watrous (watrous@u.washington.edu)
*/
#ifndef TIME_PROBE_H
#define TIME_PROBE_H
#include "ns3/probe.h"
#include "ns3/object.h"
#include "ns3/callback.h"
#include "ns3/boolean.h"
#include "ns3/traced-value.h"
#include "ns3/simulator.h"
#include "ns3/nstime.h"
namespace ns3 {
/**
* \ingroup probes
*
* This class is designed to probe an underlying ns3 TraceSource exporting
* an ns3::Time. This probe exports a trace source "Output" of type
* double, in units of seconds. The Output trace source emits a value when
* either the trace source emits a new value, or when SetValue () is called.
*
* The current value of the probe can be polled with the GetValue ()
* method.
*/
class TimeProbe : public Probe
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId ();
TimeProbe ();
virtual ~TimeProbe ();
/**
* \return the most recent value (units of seconds)
*/
double GetValue (void) const;
/**
* \param value set the traced Time to a new value
*/
void SetValue (Time value);
/**
* \brief Set a probe value by its name in the Config system
*
* \param path Config path to access the probe
* \param value set the traced Time to a new value
*/
static void SetValueByPath (std::string path, Time value);
/**
* \brief connect to a trace source attribute provided by a given object
*
* \param traceSource the name of the attribute TraceSource to connect to
* \param obj ns3::Object to connect to
* \return true if the trace source was successfully connected
*/
virtual bool ConnectByObject (std::string traceSource, Ptr<Object> obj);
/**
* \brief connect to a trace source provided by a config path
*
* \param path Config path to bind to
*
* Note, if an invalid path is provided, the probe will not be connected
* to anything.
*/
virtual void ConnectByPath (std::string path);
private:
/**
* \brief Method to connect to an underlying ns3::TraceSource of type Time
*
* \param oldData previous value of the Time
* \param newData new value of the Time
*/
void TraceSink (Time oldData, Time newData);
TracedValue<double> m_output; //!< Output trace source.
};
} // namespace ns3
#endif // TIME_PROBE_H

View File

@@ -25,6 +25,7 @@ def build(bld):
'model/probe.cc',
'model/boolean-probe.cc',
'model/double-probe.cc',
'model/time-probe.cc',
'model/uinteger-8-probe.cc',
'model/uinteger-16-probe.cc',
'model/uinteger-32-probe.cc',
@@ -58,6 +59,7 @@ def build(bld):
'model/probe.h',
'model/boolean-probe.h',
'model/double-probe.h',
'model/time-probe.h',
'model/uinteger-8-probe.h',
'model/uinteger-16-probe.h',
'model/uinteger-32-probe.h',