add TimeProbe class to data collection framework
This commit is contained in:
@@ -605,6 +605,7 @@ to the GnuplotHelper and to the FileHelper:
|
||||
- Uinteger8Probe
|
||||
- Uinteger16Probe
|
||||
- Uinteger32Probe
|
||||
- TimeProbe
|
||||
- PacketProbe
|
||||
- ApplicationPacketProbe
|
||||
- Ipv4PacketProbe
|
||||
|
||||
@@ -18,6 +18,7 @@ Currently, only these Probes have been implemented in DCF:
|
||||
- Uinteger8Probe
|
||||
- Uinteger16Probe
|
||||
- Uinteger32Probe
|
||||
- TimeProbe
|
||||
- PacketProbe
|
||||
- ApplicationPacketProbe
|
||||
- Ipv4PacketProbe
|
||||
|
||||
247
src/stats/examples/time-probe-example.cc
Normal file
247
src/stats/examples/time-probe-example.cc
Normal 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;
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
111
src/stats/model/time-probe.cc
Normal file
111
src/stats/model/time-probe.cc
Normal 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
|
||||
110
src/stats/model/time-probe.h
Normal file
110
src/stats/model/time-probe.h
Normal 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
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user