A Discrete-Event Network Simulator
API
time-probe-example.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 University of Washington
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  */
17 
18 //
19 // This example is designed to show the main features of an ns3::TimeProbe.
20 // A test object is used to emit values through a trace source. The
21 // example shows three ways to use a ns3::TimeProbe to hook the output
22 // of this trace source (in addition to hooking the raw trace source).
23 //
24 // It produces two types of output. By default, it will generate a
25 // gnuplot of interarrival times. If the '--verbose=1' argument is passed,
26 // it will also generate debugging output of the form (for example):
27 //
28 // Emitting at 96.5378 seconds
29 // context: raw trace source old 0.293343 new 0.00760254
30 // context: probe1 old 0.293343 new 0.00760254
31 // context: probe2 old 0.293343 new 0.00760254
32 // context: probe3 old 0.293343 new 0.00760254
33 //
34 // The stopTime defaults to 100 seconds but can be changed by an argument.
35 //
36 
37 #include "ns3/core-module.h"
38 #include "ns3/gnuplot-helper.h"
39 #include "ns3/time-probe.h"
40 
41 #include <string>
42 
43 using namespace ns3;
44 
45 NS_LOG_COMPONENT_DEFINE("TimeProbeExample");
46 
52 class Emitter : public Object
53 {
54  public:
59  static TypeId GetTypeId();
61 
62  private:
63  void DoInitialize() override;
65  void Emit();
66 
70 };
71 
73 
74 TypeId
76 {
77  static TypeId tid = TypeId("ns3::Emitter")
78  .SetParent<Object>()
79  .SetGroupName("Stats")
80  .AddConstructor<Emitter>()
81  .AddTraceSource("Interval",
82  "Trace source",
84  "ns3::TracedValueCallback::Time");
85  return tid;
86 }
87 
89  : m_interval(Seconds(0)),
90  m_last(Seconds(0))
91 {
92  m_var = CreateObject<ExponentialRandomVariable>();
93 }
94 
95 void
97 {
98  Simulator::Schedule(Seconds(m_var->GetValue()), &Emitter::Emit, this);
99 }
100 
101 void
103 {
104  NS_LOG_DEBUG("Emitting at " << Simulator::Now().As(Time::S));
107  TimeProbe::SetValueByPath("/Names/probe3", m_interval);
108  Simulator::Schedule(Seconds(m_var->GetValue()), &Emitter::Emit, this);
109 }
110 
111 // This is a function to test hooking a raw function to the trace source
112 void
113 NotifyViaTraceSource(std::string context, Time oldVal, Time newVal)
114 {
116  GlobalValue::GetValueByName("verbose", verbose);
117  if (verbose.Get())
118  {
119  std::cout << "context: " << context << " old " << oldVal.As(Time::S) << " new "
120  << newVal.As(Time::S) << std::endl;
121  }
122 }
123 
124 // This is a function to test hooking it to the probe output
125 void
126 NotifyViaProbe(std::string context, double oldVal, double newVal)
127 {
129  GlobalValue::GetValueByName("verbose", verbose);
130  if (verbose.Get())
131  {
132  std::cout << "context: " << context << " old " << oldVal << " new " << newVal << std::endl;
133  }
134 }
135 
136 static ns3::GlobalValue g_verbose("verbose",
137  "Whether to enable verbose output",
138  ns3::BooleanValue(false),
140 
141 int
142 main(int argc, char* argv[])
143 {
144  double stopTime = 100.0;
145  bool verbose = false;
146 
147  CommandLine cmd(__FILE__);
148  cmd.AddValue("stopTime", "Time (seconds) to terminate simulation", stopTime);
149  cmd.AddValue("verbose", "Whether to enable verbose output", verbose);
150  cmd.Parse(argc, argv);
151  bool connected;
152 
153  // Set a global value, so that the callbacks can access it
154  if (verbose)
155  {
156  GlobalValue::Bind("verbose", BooleanValue(true));
157  LogComponentEnable("TimeProbeExample", LOG_LEVEL_ALL);
158  }
159 
160  Ptr<Emitter> emitter = CreateObject<Emitter>();
161  Names::Add("/Names/Emitter", emitter);
162 
163  //
164  // The below shows typical functionality without a probe
165  // (connect a sink function to a trace source)
166  //
167  connected =
168  emitter->TraceConnect("Interval", "raw trace source", MakeCallback(&NotifyViaTraceSource));
169  NS_ASSERT_MSG(connected, "Trace source not connected");
170 
171  //
172  // Next, we'll show several use cases of using a Probe to access and
173  // filter the values of the underlying trace source
174  //
175 
176  //
177  // Probe1 will be hooked directly to the Emitter trace source object
178  //
179 
180  // probe1 will be hooked to the Emitter trace source
181  Ptr<TimeProbe> probe1 = CreateObject<TimeProbe>();
182  // the probe's name can serve as its context in the tracing
183  probe1->SetName("probe1");
184 
185  // Connect the probe to the emitter's Interval
186  connected = probe1->ConnectByObject("Interval", emitter);
187  NS_ASSERT_MSG(connected, "Trace source not connected to probe1");
188 
189  // The probe itself should generate output. The context that we provide
190  // to this probe (in this case, the probe name) will help to disambiguate
191  // the source of the trace
192  connected = probe1->TraceConnect("Output", probe1->GetName(), MakeCallback(&NotifyViaProbe));
193  NS_ASSERT_MSG(connected, "Trace source not connected to probe1 Output");
194 
195  //
196  // Probe2 will be hooked to the Emitter trace source object by
197  // accessing it by path name in the Config database
198  //
199 
200  // Create another similar probe; this will hook up via a Config path
201  Ptr<TimeProbe> probe2 = CreateObject<TimeProbe>();
202  probe2->SetName("probe2");
203 
204  // Note, no return value is checked here
205  probe2->ConnectByPath("/Names/Emitter/Interval");
206 
207  // The probe itself should generate output. The context that we provide
208  // to this probe (in this case, the probe name) will help to disambiguate
209  // the source of the trace
210  connected = probe2->TraceConnect("Output", "probe2", MakeCallback(&NotifyViaProbe));
211  NS_ASSERT_MSG(connected, "Trace source not connected to probe2 Output");
212 
213  //
214  // Probe3 will be called by the emitter directly through the
215  // static method SetValueByPath().
216  //
217  Ptr<TimeProbe> probe3 = CreateObject<TimeProbe>();
218  probe3->SetName("probe3");
219 
220  // By adding to the config database, we can access it later
221  Names::Add("/Names/probe3", probe3);
222 
223  // The probe itself should generate output. The context that we provide
224  // to this probe (in this case, the probe name) will help to disambiguate
225  // the source of the trace
226  connected = probe3->TraceConnect("Output", "probe3", MakeCallback(&NotifyViaProbe));
227  NS_ASSERT_MSG(connected, "Trace source not connected to probe3 Output");
228 
229  // Plot the interval values
230  GnuplotHelper plotHelper;
231  plotHelper.ConfigurePlot("time-probe-example",
232  "Emitter interarrivals vs. Time",
233  "Simulation time (Seconds)",
234  "Interarrival time (Seconds)",
235  "png");
236 
237  // Helper creates a TimeProbe and hooks it to the /Names/Emitter/Interval
238  // source. Helper also takes the Output of the TimeProbe and plots it
239  // as a dataset labeled 'Emitter Interarrival Time'
240  plotHelper.PlotProbe("ns3::TimeProbe",
241  "/Names/Emitter/Interval",
242  "Output",
243  "Emitter Interarrival Time",
244  GnuplotAggregator::KEY_INSIDE);
245 
246  // The Emitter object is not associated with an ns-3 node, so
247  // it won't get started automatically, so we need to do this ourselves
248  Simulator::Schedule(Seconds(0.0), &Emitter::Initialize, emitter);
249 
250  Simulator::Stop(Seconds(stopTime));
251  Simulator::Run();
252  Simulator::Destroy();
253 
254  return 0;
255 }
This is our test object, an object that increments counters at various times and emits one of them as...
void DoInitialize() override
Initialize() implementation.
static TypeId GetTypeId()
Register this type.
void Emit()
Generate data.
static TypeId GetTypeId()
Register this type.
Time m_last
Current interarrival time.
TracedValue< Time > m_interval
Interarrival time between events.
Ptr< ExponentialRandomVariable > m_var
Random number generator.
Parse command-line arguments.
Definition: command-line.h:232
double GetValue(double mean, double bound)
Get the next random value drawn from the distribution.
Hold a so-called 'global value'.
Definition: global-value.h:76
Helper class used to make gnuplot plots.
void ConfigurePlot(const std::string &outputFileNameWithoutExtension, const std::string &title, const std::string &xLegend, const std::string &yLegend, const std::string &terminalType="png")
void PlotProbe(const std::string &typeId, const std::string &path, const std::string &probeTraceSource, const std::string &title, GnuplotAggregator::KeyLocation keyLocation=GnuplotAggregator::KEY_INSIDE)
A base class which provides memory management and object aggregation.
Definition: object.h:89
void Initialize()
Invoke DoInitialize on all Objects aggregated to this one.
Definition: object.cc:186
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Time stopTime
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:302
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
@ LOG_LEVEL_ALL
Print everything.
Definition: log.h:116
cmd
Definition: second.py:40
bool verbose
static ns3::GlobalValue g_verbose("verbose", "Whether to enable verbose output", ns3::BooleanValue(false), ns3::MakeBooleanChecker())
void NotifyViaProbe(std::string context, double oldVal, double newVal)
void NotifyViaTraceSource(std::string context, Time oldVal, Time newVal)