Index: CHANGES.html
===================================================================
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -54,9 +54,25 @@
Changes from ns-3.23 to ns-3.24
New API:
+ (stats) Five new collector types, a Collector base class, an EventDrivenCollector, a TimeSeriesCollector, a TimeAverageCollector, and a ScalingCollector, have been added.
+
+ (stats) The base class for DataCollectionObject now supports methods to configure start time, end time, and enabled time periods for DCF objects.
+
+ (stats) A new method GnuplotHelper::SetScalingFactor() has been added to support scaling of y-axis data in gnuplot plots.
+
Changes to existing API:
+ (stats) The GnuplotHelper class method PlotProbe() has been deprectated, replaced by a similar AddProbe() to enable multiple data series.
+
+ (stats) The FileHelper class method WriteProbe() has been deprectated, replaced by a similar AddProbe(), for API alignment with GnuplotHelper.
+
+ (stats) The setting of terminal type and key location in the GnuplotHelper class have been moved outside of the constructors (old constructor versions are now deprecated) and moved to separate class methods. Deprecated constructors will be removed in future ns-3 versions.
+
+ (stats) The TimeSeriesAdaptor class has been removed and functionally replaced by the EventDrivenCollector class. This is mainly an internal API change.
+
+ (stats) The TimeProbe class Output trace source data type has been changed to export a ns3::Time type rather than double type, to align with other Probes.
+
Changes to build system:
Index: doc/manual/Makefile
===================================================================
--- a/doc/manual/Makefile
+++ b/doc/manual/Makefile
@@ -47,7 +47,6 @@
${SRC}/stats/doc/probe.rst \
${SRC}/stats/doc/collector.rst \
${SRC}/stats/doc/aggregator.rst \
- ${SRC}/stats/doc/adaptor.rst \
${SRC}/stats/doc/scope-and-limitations.rst \
# list all manual figure files that need to be copied to
Index: doc/tutorial/source/data-collection.rst
===================================================================
--- a/doc/tutorial/source/data-collection.rst
+++ b/doc/tutorial/source/data-collection.rst
@@ -7,8 +7,8 @@
---------------
Our final tutorial chapter introduces some components that were added
-to |ns3| in version 3.18, and that are still under development. This
-tutorial section is also a work-in-progress.
+to |ns3| starting with version 3.18, and that are still under development.
+This tutorial section is also a work-in-progress.
Motivation
**********
@@ -122,22 +122,20 @@
+ GnuplotHelper plotHelper;
+
+ // Configure the plot. The first argument is the file name prefix
- + // for the output files generated. The second, third, and fourth
- + // arguments are, respectively, the plot title, x-axis, and y-axis labels
- + plotHelper.ConfigurePlot ("seventh-packet-byte-count",
- + "Packet Byte Count vs. Time",
- + "Time (Seconds)",
- + "Packet Byte Count");
- +
- + // Specify the probe type, trace source path (in configuration namespace), and
- + // probe output trace source ("OutputBytes") to plot. The fourth argument
- + // specifies the name of the data series label on the plot. The last
- + // argument formats the plot by specifying where the key should be placed.
- + plotHelper.PlotProbe (probeType,
- + tracePath,
- + "OutputBytes",
- + "Packet Byte Count",
- + GnuplotAggregator::KEY_BELOW);
+ + // for the output files generated. The second, third, and fourth
+ + // arguments are, respectively, the plot title, x-axis, and y-axis labels
+ + plotHelper.ConfigurePlot ("seventh-packet-byte-count",
+ + "Packet Byte Count vs. Time",
+ + "Time (Seconds)",
+ + "Packet Byte Count");
+ +
+ + // Specify the probe type, trace source path (in configuration namespace), and
+ + // probe output trace source ("OutputBytes") to plot. The fourth argument
+ + // specifies the name of the data series label on the plot.
+ + plotHelper.AddProbe (probeType,
+ + tracePath,
+ + "OutputBytes",
+ + "Packet Byte Count");
+
+ // Use FileHelper to write out the packet byte count over time
+ FileHelper fileHelper;
@@ -270,13 +268,11 @@
+ // Specify the probe type, trace source path (in configuration namespace), and
+ // probe output trace source ("OutputBytes") to plot. The fourth argument
- + // specifies the name of the data series label on the plot. The last
- + // argument formats the plot by specifying where the key should be placed.
- + plotHelper.PlotProbe (probeType,
- + tracePath,
- + "OutputBytes",
- + "Packet Byte Count",
- + GnuplotAggregator::KEY_BELOW);
+ + // specifies the name of the data series label on the plot.
+ + plotHelper.AddProbe (probeType,
+ + tracePath,
+ + "OutputBytes",
+ + "Packet Byte Count");
The first two arguments are the name of the probe type and the trace source path.
These two are probably the hardest to determine when you try to use
@@ -288,7 +284,8 @@
::
.AddTraceSource ("Tx", "Send IPv6 packet to outgoing interface.",
- MakeTraceSourceAccessor (&Ipv6L3Protocol::m_txTrace))
+ MakeTraceSourceAccessor (&Ipv6L3Protocol::m_txTrace),
+ "ns3::Ipv6L3Protocol::TxRxTracedCallback")
This says that ``Tx`` is a name for variable ``m_txTrace``, which has
a declaration of:
@@ -300,11 +297,32 @@
*/
TracedCallback, Ptr, uint32_t> m_txTrace;
+
+The last argument specifies that it is a TxRxTracedCallback; this
+documentation string allows the signature to be easily found using
+Doxygen. If we look at this signature in the same header file, we can
+see also:
+
+::
+
+ /**
+ * TracedCallback signature for packet transmission or reception events.
+ *
+ * \param [in] packet The packet.
+ * \param [in] ipv6
+ * \param [in] interface
+ */
+ typedef void (* TxRxTracedCallback)
+ (const Ptr packet, const Ptr ipv6,
+ const uint32_t interface);
+
+i.e. the same information about the arguments is present in this typedef.
+
It turns out that this specific trace source signature is supported
by a Probe class (what we need here) of class Ipv6PacketProbe.
See the files ``src/internet/model/ipv6-packet-probe.{h,cc}``.
-So, in the PlotProbe statement above, we see that the statement is
+So, in the AddProbe statement above, we see that the statement is
hooking the trace source (identified by path string) with a matching
|ns3| Probe type of ``Ipv6PacketProbe``. If we did not support
this probe type (matching trace source signature), we could have not
@@ -324,17 +342,20 @@
.SetGroupName ("Stats")
.AddConstructor ()
.AddTraceSource ( "Output",
- "The packet plus its IPv6 object and interface that serve as the output for this probe",
- MakeTraceSourceAccessor (&Ipv6PacketProbe::m_output))
+ "The packet plus its IPv6 object and interface "
+ "that serve as the output for this probe",
+ MakeTraceSourceAccessor (&Ipv6PacketProbe::m_output),
+ "ns3::Ipv6PacketProbe::TracedCallback")
.AddTraceSource ( "OutputBytes",
"The number of bytes in the packet",
- MakeTraceSourceAccessor (&Ipv6PacketProbe::m_outputBytes))
+ MakeTraceSourceAccessor (&Ipv6PacketProbe::m_outputBytes),
+ "ns3::Packet::PacketSizeTracedCallback")
;
return tid;
}
-The third argument of our PlotProbe statement specifies that we are
+The third argument of our AddProbe statement specifies that we are
interested in the number of bytes in this packet; specifically, the
"OutputBytes" trace source of Ipv6PacketProbe.
Finally, the last two arguments of the statement provide the plot
@@ -343,6 +364,31 @@
the plot key to be inserted below the plot. Other options include
NO_KEY, KEY_INSIDE, and KEY_ABOVE.
+Multiple data series can be added to a single plot.
+This can be done by repeatedly calling ``AddProbe()`` such as in the
+previous example (avoiding the use of wildcards):
+
+::
+
+ tracePath = "/NodeList/0/$ns3::Ipv4L3Protocol/Tx";
+ plotHelper.AddProbe (probeType,
+ tracePath,
+ "OutputBytes",
+ "Packet Byte Count for node 0");
+ tracePath = "/NodeList/1/$ns3::Ipv4L3Protocol/Tx";
+ plotHelper.AddProbe (probeType,
+ tracePath,
+ "OutputBytes",
+ "Packet Byte Count for node 1");
+
+Finally, by default, the helper uses a Collector type of
+``ns3::EventDrivenCollector`` which does not do any processing
+of the data generated asynchronously by the trace sources. Other
+Collector types are possible, such as a TimeSeriesCollector to
+generate periodic time-series, a TimeAverageCollector to generate
+rates (such as data rate from an interface, sampled every second),
+and the ability to scale the Y-axis data using a ScalingCollector.
+More details can be found in the |ns3| manual.
Supported Trace Types
*********************
Index: examples/tutorial/seventh.cc
===================================================================
--- a/examples/tutorial/seventh.cc
+++ b/examples/tutorial/seventh.cc
@@ -283,13 +283,11 @@
// Specify the probe type, trace source path (in configuration namespace), and
// probe output trace source ("OutputBytes") to plot. The fourth argument
- // specifies the name of the data series label on the plot. The last
- // argument formats the plot by specifying where the key should be placed.
- plotHelper.PlotProbe (probeType,
- tracePath,
- "OutputBytes",
- "Packet Byte Count",
- GnuplotAggregator::KEY_BELOW);
+ // specifies the name of the data series label on the plot.
+ plotHelper.AddProbe (probeType,
+ tracePath,
+ "OutputBytes",
+ "Packet Byte Count");
// Use FileHelper to write out the packet byte count over time
FileHelper fileHelper;
@@ -303,9 +301,9 @@
// Specify the probe type, trace source path (in configuration namespace), and
// probe output trace source ("OutputBytes") to write.
- fileHelper.WriteProbe (probeType,
- tracePath,
- "OutputBytes");
+ fileHelper.AddProbe (probeType,
+ tracePath,
+ "OutputBytes");
Simulator::Stop (Seconds (20));
Simulator::Run ();
Index: src/stats/doc/adaptor.rst
===================================================================
deleted file mode 100644
--- a/src/stats/doc/adaptor.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-.. include:: replace.txt
-
-.. heading hierarchy:
- ************* Section (#.#)
- ============= Subsection (#.#.#)
- ############# Paragraph (no number)
- ~~~~~~~~~~~~~ Sub-paragraph (no number)
-
-Adaptors
-********
-
-This section details the functionalities provided by the Adaptor
-class to an |ns3| simulation. This section is meant for users
-interested in developing simulations with the |ns3| tools and using
-the Data Collection Framework, of which the Adaptor class is a
-part, to generate data output with their simulation's results.
-
-Note: the term 'adaptor' may also be spelled 'adapter'; we chose
-the spelling aligned with the C++ standard.
-
-Adaptor Overview
-================
-
-An Adaptor is used to make connections between different types of DCF
-objects.
-
-To date, one Adaptor has been implemented:
-
-- TimeSeriesAdaptor
-
-Time Series Adaptor
-===================
-
-The TimeSeriesAdaptor lets Probes connect directly to Aggregators
-without needing any Collector in between.
-
-Both of the implemented DCF helpers utilize TimeSeriesAdaptors
-in order to take probed values of different types and output the
-current time plus the value with both converted to doubles.
-
-The role of the TimeSeriesAdaptor class is that of an adaptor, which
-takes raw-valued probe data of different types and outputs a tuple of
-two double values. The first is a timestamp, which may be set to
-different resolutions (e.g. Seconds, Milliseconds, etc.) in the future
-but which is presently hardcoded to Seconds.
-The second is the conversion of a non-double
-value to a double value (possibly with loss of precision).
-
Index: src/stats/doc/collector.rst
===================================================================
--- a/src/stats/doc/collector.rst
+++ b/src/stats/doc/collector.rst
@@ -9,10 +9,57 @@
Collectors
**********
-This section is a placeholder to detail the functionalities provided by
-the Collector
-class to an |ns3| simulation, and gives examples on how to code them
-in a program.
+As stated in the introduction, a *Collector* consumes the data generated
+by one or more Probe objects. It performs transformations on the data,
+such as normalization, reduction, and the computation of basic statistics.
+Collector objects do not produce data that is directly output by the ns-3
+run; instead, they output data downstream to another type of object,
+called *Aggregator*, which performs that function. Typically,
+Collectors output their data in the form of trace sources as well,
+allowing collectors to be chained in series.
-**Note:** As of ns-3.18, Collectors are still under development and
-not yet provided as part of the framework.
+There are four Collector types presently provided:
+
+* EventDrivenCollector
+* TimeSeriesCollector
+* TimeAverageCollector
+* ScalingCollector
+
+There is a Collector base class that exists to provide default
+implementations of various TraceSinks for popular |ns3| data types
+(e.g. Double, Boolean, Time), and to allow for generic collector containers
+that hold different types of collectors.
+
+The ``ns3::EventDrivenCollector`` is almost a pass-through object
+for data generated by probes; its main responsibility is for converting
+output data into C++ type ``double``, and for appending a timestamp
+(also of type ``double``). The data is provided in a trace source
+named ``Output`` with signature:
+
+::
+
+ // the output data trace source
+ TracedCallback m_output;
+
+In fact, this is a common pattern for trace sources from these collectors,
+converting current |ns3| Time to a double value (seconds) and converting
+the new value provided by the probe to a double valued quantity.
+
+The EventDrivenCollector provides output asynchronously, for each
+event generated by the attached probe. The ``ns3::TimeSeriesCollector``
+instead provides a time series of data, sampled every ``Period`` seconds
+(where Period is an |ns3| attribute). So while a probe may produce
+data many times per second, the time series collector outputs the most
+currently received value when its regular period is up.
+
+The ``ns3::TimeAverageCollector`` will also produce regular output according
+to a period (default 1 second), but will sum and average the values
+received by the probe across the measurement period. This is useful for
+plotting data rates (e.g. if a probe said that two 1000 byte packets
+were generated in the past second, the output of this collector would
+be 16,000 (bits/sec) in that reporting interval).
+
+Finally, the ``ns3::ScalingCollector`` will transform the input data
+that it receives by multiplying by a scaling factor, useful for
+converting the units on the output data. This collector is usually
+placed in series with another upstream Collector.
Index: src/stats/doc/data-collection-helpers.rst
===================================================================
--- a/src/stats/doc/data-collection-helpers.rst
+++ b/src/stats/doc/data-collection-helpers.rst
@@ -64,25 +64,38 @@
- A shell script to generate the gnuplot
There are two configuration statements that are needed to produce plots.
-The first statement configures the plot (filename, title, legends, and
-output type, where the output type defaults to PNG if unspecified):
+The first statement configures the plot (filename, title, and legends):
::
void ConfigurePlot (const std::string &outputFileNameWithoutExtension,
const std::string &title,
const std::string &xLegend,
- const std::string &yLegend,
- const std::string &terminalType = ".png");
+ const std::string &yLegend);
+
+This may be further customized by the following optional methods:
+
+::
+
+ void SetTerminalType (const std::string &terminalType);
+ void SetScalingFactor (double scalingFactor);
+
+The first method will change the from the default "png" output file extension.
+The second method will scale all data output from the collector; e.g.
+selecting a value of 0.001 will make the y-axis units on the plot in
+terms of thousands. The default scaling factor is 1. Note that this
+function must be called before adding probes to have effect on the
+next data series to be added; it will not cause a scaling factor to
+be applied to previously added probes.
The second statement hooks the trace source of interest:
::
- void PlotProbe (const std::string &typeId,
- const std::string &path,
- const std::string &probeTraceSource,
- const std::string &title);
+ void AddProbe (const std::string &typeId,
+ const std::string &path,
+ const std::string &probeTraceSource,
+ const std::string &title);
The arguments are as follows:
@@ -91,7 +104,7 @@
* probeTraceSource: Which output of the probe (itself a trace source) should be plotted
* title: The title to associate with the dataset(s) (in the gnuplot legend)
-A variant on the PlotProbe above is to specify a fifth optional argument
+A variant on the AddProbe above is to specify a fifth optional argument
that controls where in the plot the key (legend) is placed.
A fully worked example (from ``seventh.cc``) is shown below:
@@ -108,18 +121,15 @@
plotHelper.ConfigurePlot ("seventh-packet-byte-count",
"Packet Byte Count vs. Time",
"Time (Seconds)",
- "Packet Byte Count",
- "png");
+ "Packet Byte Count");
// Specify the probe type, trace source path (in configuration namespace), and
// probe output trace source ("OutputBytes") to plot. The fourth argument
- // specifies the name of the data series label on the plot. The last
- // argument formats the plot by specifying where the key should be placed.
- plotHelper.PlotProbe (probeType,
- tracePath,
- "OutputBytes",
- "Packet Byte Count",
- GnuplotAggregator::KEY_BELOW);
+ // specifies the name of the data series label on the plot.
+ plotHelper.AddProbe (probeType,
+ tracePath,
+ "OutputBytes",
+ "Packet Byte Count");
In this example, the ``probeType`` and ``tracePath`` are as follows (for IPv4):
@@ -179,8 +189,7 @@
void ConfigurePlot (const std::string &outputFileNameWithoutExtension,
const std::string &title,
const std::string &xLegend,
- const std::string &yLegend,
- const std::string &terminalType = ".png");
+ const std::string &yLegend);
It has the following arguments:
@@ -199,10 +208,6 @@
| yLegend | The legend for the y |
| | vertical axis. |
+--------------------------------+------------------------------+
- | terminalType | Terminal type setting string |
- | | for output. The default |
- | | terminal type is "png". |
- +--------------------------------+------------------------------+
The GnuplotHelper's ``ConfigurePlot()`` function configures plot
related parameters for this gnuplot helper so
@@ -220,24 +225,22 @@
plotHelper.ConfigurePlot ("seventh-packet-byte-count",
"Packet Byte Count vs. Time",
"Time (Seconds)",
- "Packet Byte Count",
- "png");
+ "Packet Byte Count");
-GnuplotHelper PlotProbe
-#######################
+GnuplotHelper AddProbe
+######################
-The GnuplotHelper's ``PlotProbe()`` function can be used
+The GnuplotHelper's ``AddProbe()`` function can be used
to plot values generated by probes.
It has the following prototype:
::
- void PlotProbe (const std::string &typeId,
+ void AddProbe (const std::string &typeId,
const std::string &path,
const std::string &probeTraceSource,
- const std::string &title,
- enum GnuplotAggregator::KeyLocation keyLocation = GnuplotAggregator::KEY_INSIDE);
+ const std::string &title);
It has the following arguments:
@@ -256,12 +259,8 @@
| title | The title to be associated |
| | to this dataset |
+------------------+------------------------------+
- | keyLocation | The location of the key in |
- | | the plot. The default |
- | | location is inside. |
- +------------------+------------------------------+
-The GnuplotHelper's ``PlotProbe()`` function
+The GnuplotHelper's ``AddProbe()`` function
plots a dataset generated by hooking the |ns3| trace source with a
probe created by the helper, and then plotting the values from the
probeTraceSource.
@@ -283,11 +282,10 @@
::
- plotHelper.PlotProbe ("ns3::Ipv4PacketProbe",
- "/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
- "OutputBytes",
- "Packet Byte Count",
- GnuplotAggregator::KEY_BELOW);
+ plotHelper.AddProbe ("ns3::Ipv4PacketProbe",
+ "/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
+ "OutputBytes",
+ "Packet Byte Count");
Other Examples
##############
@@ -329,16 +327,23 @@
plotHelper.ConfigurePlot ("gnuplot-helper-example",
"Emitter Counts vs. Time",
"Time (Seconds)",
- "Emitter Count",
- "png");
+ "Emitter Count");
// Plot the values generated by the probe. The path that we provide
// helps to disambiguate the source of the trace.
- plotHelper.PlotProbe ("ns3::Uinteger32Probe",
- "/Names/Emitter/Counter",
- "Output",
- "Emitter Count",
- GnuplotAggregator::KEY_INSIDE);
+ plotHelper.AddProbe ("ns3::Uinteger32Probe",
+ "/Names/Emitter/Counter",
+ "Output",
+ "Emitter Count");
+
+ plotHelper.SetCollectorType("ns3::EventDrivenCollector");
+
+Note also that there is a ``SetCollectorType`` method. This can
+be used to specify different collector types than the (default)
+``ns3::EventDrivenCollector``. The above statement just sets
+the collector type to the default (and is therefore unnecessary) but
+can be used to specify other collector types (such as a TimeSeriesCollector)
+and configure the collector attributes.
FileHelper
==========
@@ -416,7 +421,7 @@
wildcard match with the "*" replaced with "0". The second text file,
which is named "seventh-packet-byte-count-1.txt", corresponds to
the wildcard match with the "*" replaced with "1". Also, note that
-the function call to ``WriteProbe()`` will give an error message if
+the function call to ``AddProbe()`` will give an error message if
there are no matches for a path that contains wildcards.
::
@@ -432,9 +437,9 @@
fileHelper.Set2dFormat ("Time (Seconds) = %.3e\tPacket Byte Count = %.0f");
// Write the values generated by the probe.
- fileHelper.WriteProbe ("ns3::Ipv4PacketProbe",
- "/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
- "OutputBytes");
+ fileHelper.AddProbe ("ns3::Ipv4PacketProbe",
+ "/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
+ "OutputBytes");
FileHelper ConfigureFile
########################
@@ -477,19 +482,19 @@
fileHelper.ConfigureFile ("seventh-packet-byte-count",
FileAggregator::FORMATTED);
-FileHelper WriteProbe
+FileHelper AddProbe
#####################
-The FileHelper's ``WriteProbe()`` function can be used
+The FileHelper's ``AddProbe()`` function can be used
to write values generated by probes to text files.
It has the following prototype:
::
- void WriteProbe (const std::string &typeId,
- const std::string &path,
- const std::string &probeTraceSource);
+ void AddProbe (const std::string &typeId,
+ const std::string &path,
+ const std::string &probeTraceSource);
It has the following arguments:
@@ -506,7 +511,7 @@
| | access. |
+------------------+------------------------------+
-The FileHelper's ``WriteProbe()`` function
+The FileHelper's ``AddProbe()`` function
creates output text files generated by hooking the ns-3 trace source
with a probe created by the helper, and then writing the values from the
probeTraceSource. The output file names will have the text stored
@@ -530,9 +535,9 @@
::
- fileHelper.WriteProbe ("ns3::Ipv4PacketProbe",
- "/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
- "OutputBytes");
+ fileHelper.AddProbe ("ns3::Ipv4PacketProbe",
+ "/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
+ "OutputBytes");
Other Examples
##############
@@ -590,7 +595,7 @@
// Write the values generated by the probe. The path that we
// provide helps to disambiguate the source of the trace.
- fileHelper.WriteProbe ("ns3::Uinteger32Probe",
+ fileHelper.AddProbe ("ns3::Uinteger32Probe",
"/Names/Emitter/Counter",
"Output");
@@ -611,7 +616,7 @@
- Ipv4PacketProbe
These Probes, therefore, are the only TypeIds available to be used
-in ``PlotProbe()`` and ``WriteProbe()``.
+in `AddProbe()``.
In the next few sections, we cover each of the fundamental object
types (Probe, Collector, and Aggregator) in more detail, and show
Index: src/stats/doc/data-collection.rst
===================================================================
--- a/src/stats/doc/data-collection.rst
+++ b/src/stats/doc/data-collection.rst
@@ -31,6 +31,5 @@
probe.rst
collector.rst
aggregator.rst
- adaptor.rst
scope-and-limitations.rst
Index: src/stats/doc/scope-and-limitations.rst
===================================================================
--- a/src/stats/doc/scope-and-limitations.rst
+++ b/src/stats/doc/scope-and-limitations.rst
@@ -23,17 +23,11 @@
- ApplicationPacketProbe
- Ipv4PacketProbe
-Currently, no Collectors are available in the DCF, although a
-BasicStatsCollector is under development.
-
Currently, only these Aggregators have been implemented in DCF:
- GnuplotAggregator
- FileAggregator
-Currently, only this Adaptor has been implemented in DCF:
-
-Time-Series Adaptor.
Future Work
###########
@@ -43,9 +37,6 @@
Here are some things that still need to be done:
-- Hook up more trace sources in |ns3| code to get more values out of the simulator.
-- Implement more types of Probes than there currently are.
-- Implement more than just the single current 2-D Collector, BasicStatsCollector.
-- Implement more Aggregators.
-- Implement more than just Adaptors.
+- Add more trace sources in |ns3| code to get more values out of the simulator.
+- Implement more types of Probes, Collectors, and Aggregators to better cover the ns-3 API.
Index: src/stats/examples/event-driven-collector-example.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/examples/event-driven-collector-example.cc
@@ -0,0 +1,166 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+/*
+ * This example is designed to show the main features of an
+ * ns3::EventDrivenCollector. The example is modified from double-probe-example.cc.
+ * The ns3::EventDrivenCollector is the simplest collector. It collects
+ * a single volumn of double valued data and outputs the data downstream.
+ * The example below uses a ns3::EventDrivenCollector to collect data
+ * generated from an Emitter object and dumps the data to a txt file with
+ * a FileAggregator object.
+ */
+
+#include
+#include
+
+#include "ns3/core-module.h"
+#include "ns3/double-probe.h"
+#include "ns3/event-driven-collector.h"
+#include "ns3/stats-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("EventDrivenCollectorExample");
+
+
+// Declare a EventDrivenCollector as a global variable
+Ptr collector = CreateObject ();
+
+
+/*
+ * This is our test object, an object that increments counters at
+ * various times and emits one of them as a trace source.
+ */
+class Emitter : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ Emitter ();
+private:
+ void DoInitialize (void);
+ void Emit (void);
+ void Count (void);
+
+ TracedValue m_counter; // normally this would be integer type
+ Ptr m_var;
+
+};
+
+NS_OBJECT_ENSURE_REGISTERED (Emitter)
+;
+
+TypeId
+Emitter::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Emitter")
+ .AddConstructor ()
+ .SetParent ()
+ .AddTraceSource ("Counter",
+ "sample counter",
+ MakeTraceSourceAccessor (&Emitter::m_counter),
+ "ns3::TracedValue::DoubleCallback")
+ ;
+ return tid;
+}
+
+Emitter::Emitter (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_counter = 0;
+ m_var = CreateObject ();
+}
+
+void
+Emitter::DoInitialize (void)
+{
+ NS_LOG_FUNCTION (this);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Emit, this);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Count, this);
+}
+
+void
+Emitter::Emit (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG ("Emitting at " << Simulator::Now ().GetSeconds ());
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Emit, this);
+}
+
+void
+Emitter::Count (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG ("Counting at " << Simulator::Now ().GetSeconds ());
+ m_counter += 1.0;
+ DoubleProbe::SetValueByPath ("/Names/StaticallyAccessedProbe", m_counter);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Count, this);
+}
+
+
+int main (int argc, char *argv[])
+{
+ CommandLine cmd;
+ cmd.Parse (argc, argv);
+ bool connected;
+
+ Ptr emitter = CreateObject ();
+ Names::Add ("/Names/Emitter", emitter);
+
+ //
+ // testProbe will be called by the emitter directly through the
+ // static method SetValueByPath().
+ //
+ Ptr testProbe = CreateObject ();
+ testProbe->SetName ("StaticallyAccessedProbe");
+ // We must add it to the config database
+ Names::Add ("/Names/Probes", testProbe->GetName (), testProbe);
+
+ // hook the probe to the callback function
+ connected = testProbe->TraceConnectWithoutContext ("Output", MakeCallback (&EventDrivenCollector::TraceSinkDouble, collector));
+ NS_ASSERT (connected == true);
+
+ // enable the collector
+ collector->Enable ();
+
+ // Set up a FileAggregator
+ std::string outputFileName = "event-driven-collector-output.txt";
+ enum FileAggregator::FileType m_fileType = FileAggregator::SPACE_SEPARATED;
+
+ Ptr aggregator = CreateObject (outputFileName, m_fileType);
+
+ aggregator->SetHeading ("time value");
+ aggregator->Enable ();
+
+ // connect the collector with the aggregator
+ connected = collector->TraceConnect ("Output", "/Names/Probes/StaticallyAccessedProbe/Output", MakeCallback (&FileAggregator::Write2d, aggregator));
+ NS_ASSERT (connected == true);
+ NS_UNUSED (connected);
+
+ // 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 (100.0));
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return 0;
+}
Index: src/stats/examples/file-helper-example.cc
===================================================================
--- a/src/stats/examples/file-helper-example.cc
+++ b/src/stats/examples/file-helper-example.cc
@@ -126,9 +126,9 @@
// Write the values generated by the probe. The path that we
// provide helps to disambiguate the source of the trace.
- fileHelper.WriteProbe ("ns3::Uinteger32Probe",
- "/Names/Emitter/Counter",
- "Output");
+ fileHelper.AddProbe ("ns3::Uinteger32Probe",
+ "/Names/Emitter/Counter",
+ "Output");
// 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
Index: src/stats/examples/gnuplot-helper-example.cc
===================================================================
--- a/src/stats/examples/gnuplot-helper-example.cc
+++ b/src/stats/examples/gnuplot-helper-example.cc
@@ -122,17 +122,27 @@
plotHelper.ConfigurePlot ("gnuplot-helper-example",
"Emitter Count vs. Time",
"Time (Seconds)",
- "Emitter Count",
- "png");
+ "Emitter Count");
+
+ // Set collector type to EventDrivenCollector
+ plotHelper.SetCollectorType("ns3::EventDrivenCollector");
+ // Uncomment the code below to set up a TimeSeriesCollector with a
+ // data collection period of 3 seconds.
+ //
+ //plotHelper.SetCollectorType("ns3::TimeSeriesCollector");
+ //plotHelper.SetTimeSeriesCollectorPeriod(Seconds(3));
+
+ plotHelper.SetScalingFactor(10);
+
// Create a probe. Because the trace source we are interested in is
// of type uint32_t, we specify the type of probe to use by the first
// argument specifying its ns3 TypeId.
- plotHelper.PlotProbe ("ns3::Uinteger32Probe",
- "/Names/Emitter/Counter",
- "Output",
- "Emitter Count",
- GnuplotAggregator::KEY_INSIDE);
+ plotHelper.AddProbe("ns3::Uinteger32Probe",
+ "/Names/Emitter/Counter",
+ "Output",
+ "Emitter Count");
+
// 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
Index: src/stats/examples/scaling-collector-example.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/examples/scaling-collector-example.cc
@@ -0,0 +1,166 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+/*
+ * This example is designed to show the main features of an
+ * ns3::ScalingCollector. The example is modified from double-probe-example.cc.
+ * The ns3::ScalingCollector collects a single volumn of double valued data and
+ * multiplies the number with a scaling factor. It then outputs the data downstream.
+ * The example below uses a ns3::ScalingCollector to collect data
+ * generated from an Emitter object and dumps the data to a txt file with
+ * a FileAggregator object.
+ */
+
+#include
+#include
+
+#include "ns3/core-module.h"
+#include "ns3/double-probe.h"
+#include "ns3/scaling-collector.h"
+#include "ns3/stats-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("ScalingCollectorExample");
+
+/*
+ * This is our test object, an object that increments counters at
+ * various times and emits one of them as a trace source.
+ */
+class Emitter : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ Emitter ();
+private:
+ void DoInitialize (void);
+ void Emit (void);
+ void Count (void);
+
+ TracedValue m_counter; // normally this would be integer type
+ Ptr m_var;
+
+};
+
+NS_OBJECT_ENSURE_REGISTERED (Emitter)
+;
+
+TypeId
+Emitter::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Emitter")
+ .AddConstructor ()
+ .SetParent ()
+ .AddTraceSource ("Counter",
+ "sample counter",
+ MakeTraceSourceAccessor (&Emitter::m_counter),
+ "ns3::TracedValue::DoubleCallback")
+ ;
+ return tid;
+}
+
+Emitter::Emitter (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_counter = 0;
+ m_var = CreateObject ();
+}
+
+void
+Emitter::DoInitialize (void)
+{
+ NS_LOG_FUNCTION (this);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Emit, this);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Count, this);
+}
+
+void
+Emitter::Emit (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG ("Emitting at " << Simulator::Now ().GetSeconds ());
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Emit, this);
+}
+
+void
+Emitter::Count (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG ("Counting at " << Simulator::Now ().GetSeconds ());
+ m_counter += 1.0;
+ DoubleProbe::SetValueByPath ("/Names/StaticallyAccessedProbe", m_counter);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Count, this);
+}
+
+
+int main (int argc, char *argv[])
+{
+ CommandLine cmd;
+ cmd.Parse (argc, argv);
+ bool connected;
+
+ Ptr collector = CreateObject ();
+
+ Ptr emitter = CreateObject ();
+ Names::Add ("/Names/Emitter", emitter);
+
+ //
+ // testProbe will be called by the emitter directly through the
+ // static method SetValueByPath().
+ //
+ Ptr testProbe = CreateObject ();
+ testProbe->SetName ("StaticallyAccessedProbe");
+ // We must add it to the config database
+ Names::Add ("/Names/Probes", testProbe->GetName (), testProbe);
+
+ // Set the scaling factor of the ScalingCollector to 10
+ collector->SetAttribute ("ScalingFactor", DoubleValue (10));
+
+ // hook the probe to the callback function
+ connected = testProbe->TraceConnectWithoutContext ("Output", MakeCallback (&ScalingCollector::TraceSinkDouble, collector));
+ NS_ASSERT (connected == true);
+
+ // enable the collector
+ collector->Enable ();
+
+ // Set up a FileAggregator
+ std::string outputFileName = "scaling-collector-output.txt";
+ enum FileAggregator::FileType m_fileType = FileAggregator::SPACE_SEPARATED;
+
+ Ptr aggregator = CreateObject (outputFileName, m_fileType);
+
+ aggregator->SetHeading ("time value");
+ aggregator->Enable ();
+
+ // connect the collector with the aggregator
+ connected = collector->TraceConnect ("Output", "/Names/Probes/StaticallyAccessedProbe/Output", MakeCallback (&FileAggregator::Write2d, aggregator));
+ NS_ASSERT (connected == true);
+ NS_UNUSED (connected);
+
+ // 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 (100.0));
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return 0;
+}
Index: src/stats/examples/time-averaging-collector-example.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/examples/time-averaging-collector-example.cc
@@ -0,0 +1,172 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+/*
+ * This example is designed to show the main features of an
+ * ns3::TimeAveragingCollector.
+ * The example is modified from double-probe-example.cc.
+ *
+ * The ns3::TimeAveragingCollector is able to generate outputs downstream
+ * in every specified time interval. The output data are the averages of the
+ * data received by the collector during that time interval.
+ * The example below uses ns3::TimeAveragingCollector to collect
+ * data from an Emitter object and
+ * generates outputs to a txt file every 1 second.
+ */
+
+#include
+#include
+
+#include "ns3/core-module.h"
+#include "ns3/double-probe.h"
+#include "ns3/time-averaging-collector.h"
+#include "ns3/stats-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TimeAveragingCollectorExample");
+
+
+// Declare a TimeAveragingCollector as a global variable.
+// The collector will spit out outputs every one second.
+Ptr collector = CreateObject ();
+
+
+/*
+ * This is our test object, an object that increments counters at
+ * various times and emits one of them as a trace source.
+ */
+class Emitter : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ Emitter ();
+private:
+ void DoInitialize (void);
+ void Emit (void);
+ void Count (void);
+
+ TracedValue m_counter; // normally this would be integer type
+ Ptr m_var;
+
+};
+
+NS_OBJECT_ENSURE_REGISTERED (Emitter)
+;
+
+TypeId
+Emitter::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Emitter")
+ .AddConstructor ()
+ .SetParent ()
+ .AddTraceSource ("Counter",
+ "sample counter",
+ MakeTraceSourceAccessor (&Emitter::m_counter),
+ "ns3::TracedValue::DoubleCallback")
+ ;
+ return tid;
+}
+
+Emitter::Emitter (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_counter = 0;
+ m_var = CreateObject ();
+}
+
+void
+Emitter::DoInitialize (void)
+{
+ NS_LOG_FUNCTION (this);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Emit, this);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Count, this);
+}
+
+void
+Emitter::Emit (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG ("Emitting at " << Simulator::Now ().GetSeconds ());
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Emit, this);
+}
+
+void
+Emitter::Count (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG ("Counting at " << Simulator::Now ().GetSeconds ());
+ m_counter += 1.0;
+ DoubleProbe::SetValueByPath ("/Names/StaticallyAccessedProbe", m_counter);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Count, this);
+}
+
+
+int main (int argc, char *argv[])
+{
+ CommandLine cmd;
+ cmd.Parse (argc, argv);
+ bool connected;
+
+ Ptr emitter = CreateObject ();
+ Names::Add ("/Names/Emitter", emitter);
+
+ collector->SetPeriod (Seconds (3));
+
+ //
+ // testProbe will be called by the emitter directly through the
+ // static method SetValueByPath().
+ //
+ Ptr testProbe = CreateObject ();
+ testProbe->SetName ("StaticallyAccessedProbe");
+ // We must add it to the config database
+ Names::Add ("/Names/Probes", testProbe->GetName (), testProbe);
+
+ // hook the probe to the callback function
+ connected = testProbe->TraceConnectWithoutContext ("Output", MakeCallback (&TimeAveragingCollector::TraceSinkDouble, collector));
+ NS_ASSERT (connected == true);
+ NS_UNUSED (connected); // silence unused variable warnings
+
+ // enable the collector
+ collector->Enable ();
+
+ // Set up a FileAggregator
+ std::string outputFileName = "time-averaging-collector-output.txt";
+ enum FileAggregator::FileType m_fileType = FileAggregator::SPACE_SEPARATED;
+
+ Ptr aggregator = CreateObject (outputFileName, m_fileType);
+
+ aggregator->SetHeading ("time value");
+ aggregator->Enable ();
+
+ // connect the collector with the aggregator
+ connected = collector->TraceConnect ("Output", "/Names/Probes/StaticallyAccessedProbe/Output", MakeCallback (&FileAggregator::Write2d, aggregator));
+ NS_ASSERT (connected == true);
+
+ // 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 (100.0));
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return 0;
+}
Index: src/stats/examples/time-probe-example.cc
===================================================================
--- a/src/stats/examples/time-probe-example.cc
+++ b/src/stats/examples/time-probe-example.cc
@@ -18,7 +18,7 @@
//
// 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
+// 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).
//
@@ -47,7 +47,7 @@
//
// This is our test object, an object that emits values according to
-// a Poisson arrival process. It emits a traced Time value as a
+// 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
@@ -64,8 +64,8 @@
// void Emit (void);
void Emit (void);
- TracedValue m_interval;
- Time m_last;
+ TracedValue m_interval;
+ Time m_last;
Ptr m_var;
};
@@ -123,13 +123,13 @@
// This is a function to test hooking it to the probe output
void
-NotifyViaProbe (std::string context, double oldVal, double newVal)
+NotifyViaProbe (std::string context, Time oldVal, Time newVal)
{
BooleanValue verbose;
GlobalValue::GetValueByName ("verbose", verbose);
if (verbose.Get ())
{
- std::cout << "context: " << context << " old " << oldVal << " new " << newVal << std::endl;
+ std::cout << "context: " << context << " old " << oldVal.GetSeconds () << " new " << newVal.GetSeconds () << std::endl;
}
}
@@ -235,11 +235,10 @@
// 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);
+ plotHelper.AddProbe ("ns3::TimeProbe",
+ "/Names/Emitter/Interval",
+ "Output",
+ "Emitter Interarrival Time");
// 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
Index: src/stats/examples/time-series-collector-example.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/examples/time-series-collector-example.cc
@@ -0,0 +1,168 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+/*
+ * This example is designed to show the main features of an
+ * ns3::TimeSeriesCollector.
+ * The example is modified from double-probe-example.cc.
+ *
+ * The ns3::TimeSeriesCollector is able to generate outputs downstream
+ * in every specified time interval. The example below uses
+ * ns3::TimeSeriesCollector to collect data from an Emitter object and
+ * generates outputs to a txt file every 1 second.
+ */
+
+#include
+#include
+
+#include "ns3/core-module.h"
+#include "ns3/double-probe.h"
+#include "ns3/time-series-collector.h"
+#include "ns3/stats-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TimeSeriesCollectorExample");
+
+
+
+/*
+ * This is our test object, an object that increments counters at
+ * various times and emits one of them as a trace source.
+ */
+class Emitter : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ Emitter ();
+private:
+ void DoInitialize (void);
+ void Emit (void);
+ void Count (void);
+
+ TracedValue m_counter; // normally this would be integer type
+ Ptr m_var;
+
+};
+
+NS_OBJECT_ENSURE_REGISTERED (Emitter)
+;
+
+TypeId
+Emitter::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Emitter")
+ .AddConstructor ()
+ .SetParent ()
+ .AddTraceSource ("Counter",
+ "sample counter",
+ MakeTraceSourceAccessor (&Emitter::m_counter),
+ "ns3::TracedValue::DoubleCallback")
+ ;
+ return tid;
+}
+
+Emitter::Emitter (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_counter = 0;
+ m_var = CreateObject ();
+}
+
+void
+Emitter::DoInitialize (void)
+{
+ NS_LOG_FUNCTION (this);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Emit, this);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Count, this);
+}
+
+void
+Emitter::Emit (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG ("Emitting at " << Simulator::Now ().GetSeconds ());
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Emit, this);
+}
+
+void
+Emitter::Count (void)
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG ("Counting at " << Simulator::Now ().GetSeconds ());
+ m_counter += 1.0;
+ DoubleProbe::SetValueByPath ("/Names/StaticallyAccessedProbe", m_counter);
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Count, this);
+}
+
+
+int main (int argc, char *argv[])
+{
+ CommandLine cmd;
+ cmd.Parse (argc, argv);
+ bool connected;
+
+ Ptr emitter = CreateObject ();
+ Names::Add ("/Names/Emitter", emitter);
+
+ // The collector will emit outputs every one second.
+ Ptr collector = CreateObject ();
+ collector->SetPeriod (Seconds (1));
+
+ //
+ // testProbe will be called by the emitter directly through the
+ // static method SetValueByPath().
+ //
+ Ptr testProbe = CreateObject ();
+ testProbe->SetName ("StaticallyAccessedProbe");
+ // We must add it to the config database
+ Names::Add ("/Names/Probes", testProbe->GetName (), testProbe);
+
+ // hook the probe to the callback function
+ connected = testProbe->TraceConnectWithoutContext ("Output", MakeCallback (&TimeSeriesCollector::TraceSinkDouble, collector));
+ NS_ASSERT (connected == true);
+ NS_UNUSED (connected); // silence unused variable warnings
+
+ // enable the collector
+ collector->Enable ();
+
+ // Set up a FileAggregator
+ std::string outputFileName = "time-series-collector-output.txt";
+ enum FileAggregator::FileType m_fileType = FileAggregator::SPACE_SEPARATED;
+
+ Ptr aggregator = CreateObject (outputFileName, m_fileType);
+
+ aggregator->SetHeading ("time value");
+ aggregator->Enable ();
+
+ // connect the collector with the aggregator
+ connected = collector->TraceConnect ("Output", "/Names/Probes/StaticallyAccessedProbe/Output", MakeCallback (&FileAggregator::Write2d, aggregator));
+ NS_ASSERT (connected == true);
+
+ // 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 (100.0));
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return 0;
+}
Index: src/stats/examples/wscript
===================================================================
--- a/src/stats/examples/wscript
+++ b/src/stats/examples/wscript
@@ -25,4 +25,14 @@
program = bld.create_ns3_program('file-helper-example', ['network', 'stats'])
program.source = 'file-helper-example.cc'
+ program = bld.create_ns3_program('event-driven-collector-example', ['network', 'stats'])
+ program.source = 'event-driven-collector-example.cc'
+ program = bld.create_ns3_program('scaling-collector-example', ['network', 'stats'])
+ program.source = 'scaling-collector-example.cc'
+
+ program = bld.create_ns3_program('time-series-collector-example', ['network', 'stats'])
+ program.source = 'time-series-collector-example.cc'
+
+ program = bld.create_ns3_program('time-averaging-collector-example', ['network', 'stats'])
+ program.source = 'time-averaging-collector-example.cc'
Index: src/stats/helper/file-helper.cc
===================================================================
--- a/src/stats/helper/file-helper.cc
+++ b/src/stats/helper/file-helper.cc
@@ -26,6 +26,7 @@
#include "ns3/abort.h"
#include "ns3/log.h"
#include "ns3/config.h"
+#include "ns3/collector.h"
#include "ns3/get-wildcard-matches.h"
namespace ns3 {
@@ -40,6 +41,7 @@
m_hasHeadingBeenSet (false)
{
NS_LOG_FUNCTION (this);
+ m_collectorFactory.SetTypeId ("ns3::EventDrivenCollector");
// Note that this does not construct an aggregator. It will be
// constructed later when needed.
@@ -54,6 +56,7 @@
m_hasHeadingBeenSet (false)
{
NS_LOG_FUNCTION (this);
+ m_collectorFactory.SetTypeId ("ns3::EventDrivenCollector");
// Note that this does not construct an aggregator. It will be
// constructed later when needed.
@@ -87,11 +90,44 @@
}
void
+FileHelper::SetCollectorType (std::string collectorType,
+ std::string n0, const AttributeValue &v0,
+ std::string n1, const AttributeValue &v1,
+ std::string n2, const AttributeValue &v2,
+ std::string n3, const AttributeValue &v3,
+ std::string n4, const AttributeValue &v4,
+ std::string n5, const AttributeValue &v5,
+ std::string n6, const AttributeValue &v6,
+ std::string n7, const AttributeValue &v7)
+{
+ ObjectFactory factory;
+ factory.SetTypeId (collectorType);
+ factory.Set (n0, v0);
+ factory.Set (n1, v1);
+ factory.Set (n2, v2);
+ factory.Set (n3, v3);
+ factory.Set (n4, v4);
+ factory.Set (n5, v5);
+ factory.Set (n6, v6);
+ factory.Set (n7, v7);
+ m_collectorFactory = factory;
+}
+
+void
FileHelper::WriteProbe (const std::string &typeId,
const std::string &path,
const std::string &probeTraceSource)
{
NS_LOG_FUNCTION (this << typeId << path << probeTraceSource);
+ AddProbe (typeId, path, probeTraceSource);
+}
+
+void
+FileHelper::AddProbe (const std::string &typeId,
+ const std::string &path,
+ const std::string &probeTraceSource)
+{
+ NS_LOG_FUNCTION (this << typeId << path << probeTraceSource);
std::string pathWithoutLastToken;
std::string lastToken;
@@ -134,7 +170,7 @@
// the wildcard matches because the passed in path has none.
matchIdentifier = "0";
onlyOneAggregator = true;
- ConnectProbeToAggregator (typeId,
+ CreateDataCollectionChain (typeId,
matchIdentifier,
path,
probeTraceSource,
@@ -161,7 +197,7 @@
wildcardSeparator);
// Connect the probe to the aggregator for this match.
- ConnectProbeToAggregator (typeId,
+ CreateDataCollectionChain (typeId,
matchIdentifier,
matchedPath,
probeTraceSource,
@@ -177,7 +213,7 @@
}
void
-FileHelper::AddProbe (const std::string &typeId,
+FileHelper::AddProbeToMap (const std::string &typeId,
const std::string &probeName,
const std::string &path)
{
@@ -213,24 +249,21 @@
}
void
-FileHelper::AddTimeSeriesAdaptor (const std::string &adaptorName)
+FileHelper::AddCollector (const std::string &collectorName)
{
- NS_LOG_FUNCTION (this << adaptorName);
+ NS_LOG_FUNCTION (this << collectorName);
- // See if this time series adaptor had already been added.
- if (m_timeSeriesAdaptorMap.count (adaptorName) > 0)
+ Ptr collector = DynamicCast (m_collectorFactory.Create ());
+ collector->Enable ();
+ // See if this collector had already been added.
+
+ if (m_collectorMap.count (collectorName) > 0)
{
- NS_ABORT_MSG ("That time series adaptor has already been added");
+ NS_ABORT_MSG ("That Collector has already been added");
}
- // Create the time series adaptor.
- Ptr timeSeriesAdaptor = CreateObject ();
-
- // Enable logging of data for the time series adaptor.
- timeSeriesAdaptor->Enable ();
-
// Add this time series adaptor to the map so that it can be used.
- m_timeSeriesAdaptorMap[adaptorName] = timeSeriesAdaptor;
+ m_collectorMap[collectorName] = collector;
}
void
@@ -251,7 +284,7 @@
if (onlyOneAggregator)
{
// Get a pointer to the aggregator.
- Ptr singleAggregator = GetAggregatorSingle ();
+ Ptr singleAggregator = GetAggregator ();
m_aggregatorMap[aggregatorName] = singleAggregator;
return;
@@ -305,6 +338,12 @@
Ptr
FileHelper::GetAggregatorSingle ()
{
+ return GetAggregator ();
+}
+
+Ptr
+FileHelper::GetAggregator ()
+{
NS_LOG_FUNCTION (this);
// Do a lazy construction of the single aggregator if it hasn't
@@ -448,7 +487,7 @@
}
void
-FileHelper::ConnectProbeToAggregator (const std::string &typeId,
+FileHelper::CreateDataCollectionChain (const std::string &typeId,
const std::string &matchIdentifier,
const std::string &path,
const std::string &probeTraceSource,
@@ -472,102 +511,116 @@
// Add the probe to the map of probes, which will keep the probe in
// memory after this function ends.
- AddProbe (typeId, probeName, path);
+ AddProbeToMap (typeId, probeName, path);
// Because the callbacks to the probes' trace sources don't use the
// probe's context, a unique adaptor needs to be created for each
// probe context so that information is not lost.
- AddTimeSeriesAdaptor (probeContext);
+ AddCollector (probeContext);
- // Connect the probe to the adaptor.
- if (m_probeMap[probeName].second == "ns3::DoubleProbe")
- {
- m_probeMap[probeName].first->TraceConnectWithoutContext
- (probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkDouble,
- m_timeSeriesAdaptorMap[probeContext]));
- }
- else if (m_probeMap[probeName].second == "ns3::BooleanProbe")
- {
- m_probeMap[probeName].first->TraceConnectWithoutContext
- (probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkBoolean,
- m_timeSeriesAdaptorMap[probeContext]));
- }
- else if (m_probeMap[probeName].second == "ns3::PacketProbe")
- {
- m_probeMap[probeName].first->TraceConnectWithoutContext
- (probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
- m_timeSeriesAdaptorMap[probeContext]));
- }
- else if (m_probeMap[probeName].second == "ns3::ApplicationPacketProbe")
- {
- m_probeMap[probeName].first->TraceConnectWithoutContext
- (probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
- m_timeSeriesAdaptorMap[probeContext]));
- }
- else if (m_probeMap[probeName].second == "ns3::Ipv4PacketProbe")
- {
- m_probeMap[probeName].first->TraceConnectWithoutContext
- (probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
- m_timeSeriesAdaptorMap[probeContext]));
- }
- else if (m_probeMap[probeName].second == "ns3::Ipv6PacketProbe")
- {
- m_probeMap[probeName].first->TraceConnectWithoutContext
- (probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
- m_timeSeriesAdaptorMap[probeContext]));
- }
- else if (m_probeMap[probeName].second == "ns3::Uinteger8Probe")
- {
- m_probeMap[probeName].first->TraceConnectWithoutContext
- (probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger8,
- m_timeSeriesAdaptorMap[probeContext]));
- }
- else if (m_probeMap[probeName].second == "ns3::Uinteger16Probe")
- {
- m_probeMap[probeName].first->TraceConnectWithoutContext
- (probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger16,
- m_timeSeriesAdaptorMap[probeContext]));
- }
- else if (m_probeMap[probeName].second == "ns3::Uinteger32Probe")
- {
- m_probeMap[probeName].first->TraceConnectWithoutContext
- (probeTraceSource,
- 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");
- }
+ ConnectProbeToCollector (probeTraceSource, probeName, probeContext);
// Add the aggregator to the map of aggregators, which will keep the
// aggregator in memory after this function ends.
std::string outputFileName = outputFileNameWithoutExtension + ".txt";
AddAggregator (probeContext, outputFileName, onlyOneAggregator);
- // Connect the adaptor to the aggregator.
- std::string adaptorTraceSource = "Output";
- m_timeSeriesAdaptorMap[probeContext]->TraceConnect
- (adaptorTraceSource,
+ ConnectCollectorToAggregator (probeContext);
+}
+
+void
+FileHelper::ConnectCollectorToAggregator (const std::string probeContext)
+{
+ // Connect the collector to the aggregator.
+ std::string collectorTraceSource = "Output";
+ m_collectorMap[probeContext]->TraceConnect
+ (collectorTraceSource,
probeContext,
MakeCallback (&FileAggregator::Write2d,
m_aggregatorMap[probeContext]));
}
+void
+FileHelper::ConnectProbeToCollector (const std::string probeTraceSource,
+ const std::string probeName,
+ const std::string probeContext)
+{
+ // Connect the probe to the adaptor.
+ if (m_probeMap[probeName].second == "ns3::DoubleProbe")
+ {
+ m_probeMap[probeName].first->TraceConnectWithoutContext
+ (probeTraceSource,
+ MakeCallback (&Collector::TraceSinkDouble,
+ m_collectorMap[probeContext]));
+ }
+ else if (m_probeMap[probeName].second == "ns3::BooleanProbe")
+ {
+ m_probeMap[probeName].first->TraceConnectWithoutContext
+ (probeTraceSource,
+ MakeCallback (&Collector::TraceSinkBoolean,
+ m_collectorMap[probeContext]));
+ }
+ else if (m_probeMap[probeName].second == "ns3::PacketProbe")
+ {
+ m_probeMap[probeName].first->TraceConnectWithoutContext
+ (probeTraceSource,
+ MakeCallback (&Collector::TraceSinkUinteger32,
+ m_collectorMap[probeContext]));
+ }
+ else if (m_probeMap[probeName].second == "ns3::ApplicationPacketProbe")
+ {
+ m_probeMap[probeName].first->TraceConnectWithoutContext
+ (probeTraceSource,
+ MakeCallback (&Collector::TraceSinkUinteger32,
+ m_collectorMap[probeContext]));
+ }
+ else if (m_probeMap[probeName].second == "ns3::Ipv4PacketProbe")
+ {
+ m_probeMap[probeName].first->TraceConnectWithoutContext
+ (probeTraceSource,
+ MakeCallback (&Collector::TraceSinkUinteger32,
+ m_collectorMap[probeContext]));
+ }
+ else if (m_probeMap[probeName].second == "ns3::Ipv6PacketProbe")
+ {
+ m_probeMap[probeName].first->TraceConnectWithoutContext
+ (probeTraceSource,
+ MakeCallback (&Collector::TraceSinkUinteger32,
+ m_collectorMap[probeContext]));
+ }
+ else if (m_probeMap[probeName].second == "ns3::Uinteger8Probe")
+ {
+ m_probeMap[probeName].first->TraceConnectWithoutContext
+ (probeTraceSource,
+ MakeCallback (&Collector::TraceSinkUinteger8,
+ m_collectorMap[probeContext]));
+ }
+ else if (m_probeMap[probeName].second == "ns3::Uinteger16Probe")
+ {
+ m_probeMap[probeName].first->TraceConnectWithoutContext
+ (probeTraceSource,
+ MakeCallback (&Collector::TraceSinkUinteger16,
+ m_collectorMap[probeContext]));
+ }
+ else if (m_probeMap[probeName].second == "ns3::Uinteger32Probe")
+ {
+ m_probeMap[probeName].first->TraceConnectWithoutContext
+ (probeTraceSource,
+ MakeCallback (&Collector::TraceSinkUinteger32,
+ m_collectorMap[probeContext]));
+ }
+ else if (m_probeMap[probeName].second == "ns3::TimeProbe")
+ {
+ m_probeMap[probeName].first->TraceConnectWithoutContext
+ (probeTraceSource,
+ MakeCallback (&Collector::TraceSinkDouble,
+ m_collectorMap[probeContext]));
+ }
+ else
+ {
+ NS_FATAL_ERROR ("Unknown probe type " << m_probeMap[probeName].second << "; need to add support in the helper for this");
+ }
+}
+
} // namespace ns3
Index: src/stats/helper/file-helper.h
===================================================================
--- a/src/stats/helper/file-helper.h
+++ b/src/stats/helper/file-helper.h
@@ -26,8 +26,8 @@
#include "ns3/object-factory.h"
#include "ns3/ptr.h"
#include "ns3/probe.h"
+#include "ns3/collector.h"
#include "ns3/file-aggregator.h"
-#include "ns3/time-series-adaptor.h"
namespace ns3 {
@@ -40,13 +40,13 @@
public:
/**
* Constructs a file helper that will create a space separated file
- * named "file-helper.txt" unless it is later configured otherwise.
+ * named "file-helper.txt" unless it is later configured to a different name.
*/
FileHelper ();
/**
* \param outputFileNameWithoutExtension name of output file to
- * write with no extension
+ * write with no extension
* \param fileType type of file to write.
*
* Constructs a file helper that will create a file named
@@ -55,13 +55,13 @@
* specified by fileType. The default file type is space-separated.
*/
FileHelper (const std::string &outputFileNameWithoutExtension,
- enum FileAggregator::FileType fileType = FileAggregator::SPACE_SEPARATED);
+ enum FileAggregator::FileType fileType = FileAggregator::SPACE_SEPARATED) NS_DEPRECATED;
virtual ~FileHelper ();
/**
* \param outputFileNameWithoutExtension name of output file to
- * write with no extension
+ * write with no extension
* \param fileType type of file to write.
*
* Configures file related parameters for this file helper so that
@@ -74,6 +74,43 @@
enum FileAggregator::FileType fileType = FileAggregator::SPACE_SEPARATED);
/**
+ * \param fileType file type setting for output
+ */
+ void SetFileType (enum FileAggregator::FileType fileType);
+
+ /**
+ * Select the collector type and configure its attributes for any probes
+ * added thereafter (but not affecting probes added before).
+ * The default is "ns3::EventDrivenCollector".
+ * \param collectorType the ns-3 TypeId string of the collector type
+ * \param n0 the name of the attribute to set
+ * \param v0 the value of the attribute to set
+ * \param n1 the name of the attribute to set
+ * \param v1 the value of the attribute to set
+ * \param n2 the name of the attribute to set
+ * \param v2 the value of the attribute to set
+ * \param n3 the name of the attribute to set
+ * \param v3 the value of the attribute to set
+ * \param n4 the name of the attribute to set
+ * \param v4 the value of the attribute to set
+ * \param n5 the name of the attribute to set
+ * \param v5 the value of the attribute to set
+ * \param n6 the name of the attribute to set
+ * \param v6 the value of the attribute to set
+ * \param n7 the name of the attribute to set
+ * \param v7 the value of the attribute to set
+ */
+ void SetCollectorType (std::string collectorType,
+ std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+ std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+ std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+ std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+ std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+ std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+ std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+ std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+
+ /**
* \param typeId the type ID for the probe used when it is created.
* \param path Config path for underlying trace source to be probed
* \param probeTraceSource the probe trace source to access.
@@ -105,14 +142,41 @@
*/
void WriteProbe (const std::string &typeId,
const std::string &path,
- const std::string &probeTraceSource);
+ const std::string &probeTraceSource) NS_DEPRECATED;
/**
- * \param adaptorName the timeSeriesAdaptor's name.
+ * \param typeId the type ID for the probe used when it is created.
+ * \param path Config path for underlying trace source to be probed
+ * \param probeTraceSource the probe trace source to access.
*
- * \brief Adds a time series adaptor to be used to write the file.
+ * Creates output files generated by hooking the ns-3 trace source
+ * with a probe, and then writing the values from the
+ * probeTraceSource. The output file names will have the text stored
+ * in m_outputFileNameWithoutExtension plus ".txt", and will consist
+ * of the 'newValue' at each timestamp.
+ *
+ * This method will create one or more probes according to the TypeId
+ * provided, connect the probe(s) to the trace source specified by
+ * the config path, and hook the probeTraceSource(s) to the downstream
+ * aggregator.
+ *
+ * If the config path has more than one match in the system
+ * (e.g. there is a wildcard), then one output file for each match
+ * will be created. The output file names will contain the text in
+ * m_outputFileNameWithoutExtension plus the matched characters for
+ * each of the wildcards in the config path, separated by dashes,
+ * plus ".txt". For example, if the value in
+ * m_outputFileNameWithoutExtension is the string
+ * "packet-byte-count", and there are two wildcards in the path,
+ * then output file names like "packet-byte-count-0-0.txt" or
+ * "packet-byte-count-12-9.txt" will be possible as names for the
+ * files that will be created.
+ *
+ * A fatal error will result if an unknown probe type is used.
*/
- void AddTimeSeriesAdaptor (const std::string &adaptorName);
+ void AddProbe (const std::string &typeId,
+ const std::string &path,
+ const std::string &probeTraceSource);
/**
* \param aggregatorName the aggregator's name.
@@ -131,7 +195,7 @@
* \return Ptr to the probe
* \brief Gets the specified probe.
*/
- Ptr GetProbe (std::string probeName) const;
+ Ptr GetProbe (std::string probeName) const NS_DEPRECATED;
/**
* \return Ptr to a FileAggregator object
@@ -140,7 +204,7 @@
* This function is non-const because an aggregator may be lazily
* created by this method.
*/
- Ptr GetAggregatorSingle ();
+ Ptr GetAggregatorSingle () NS_DEPRECATED;
/**
* \param aggregatorName name for aggregator.
@@ -152,7 +216,7 @@
* created by this method.
*/
Ptr GetAggregatorMultiple (const std::string &aggregatorName,
- const std::string &outputFileName);
+ const std::string &outputFileName) NS_DEPRECATED;
/**
* \param heading the heading string.
@@ -253,9 +317,16 @@
*
* \brief Adds a probe to be used to write values to files.
*/
- void AddProbe (const std::string &typeId,
- const std::string &probeName,
- const std::string &path);
+ void AddProbeToMap (const std::string &typeId,
+ const std::string &probeName,
+ const std::string &path);
+
+ /**
+ * \param collectorName the name of the collector
+ *
+ * \brief Adds the collector to the FileHelper.
+ */
+ void AddCollector (const std::string &collectorName);
/**
* \param typeId the type ID for the probe used when it is created.
@@ -272,13 +343,40 @@
*
* A fatal error will result if an unknown probe type is used.
*/
- void ConnectProbeToAggregator (const std::string &typeId,
+ void CreateDataCollectionChain (const std::string &typeId,
const std::string &matchIdentifier,
const std::string &path,
const std::string &probeTraceSource,
const std::string &outputFileNameWithoutExtension,
bool onlyOneAggregator);
+ /**
+ * \param probeTraceSource the trace source of the probe
+ * \param probeName the name of the probe in the map
+ * \param probeContext the context of the probe in the collector map
+ *
+ * \brief Connects a probe to a Collector object
+ */
+ void ConnectProbeToCollector(const std::string probeTraceSource,
+ const std::string probeName,
+ const std::string probeContext);
+
+ /**
+ * \param probeContext the name of the collector in the map
+ *
+ * \brief connect a collector to an aggregator
+ */
+ void ConnectCollectorToAggregator(const std::string probeContext);
+
+ /**
+ * \return Ptr to a FileAggregator object
+ * \brief Gets the single aggregator that is always constructed.
+ *
+ * This function is non-const because an aggregator may be lazily
+ * created by this method.
+ */
+ Ptr GetAggregator ();
+
/// Used to create the probes and collectors as they are added.
ObjectFactory m_factory;
@@ -292,8 +390,8 @@
/// Maps probe names to probes.
std::map, std::string> > m_probeMap;
- /// Maps time series adaptor names to time series adaptors.
- std::map > m_timeSeriesAdaptorMap;
+ /// Maps Collector names to Collectors
+ std::map > m_collectorMap;
/// Number of file probes that have been created.
uint32_t m_fileProbeCount;
@@ -304,6 +402,9 @@
/// The name of the output file to created without its extension.
std::string m_outputFileNameWithoutExtension;
+ /// Factory object for instantiating collector
+ ObjectFactory m_collectorFactory;
+
/// Indicates if the heading line for the file has been set.
bool m_hasHeadingBeenSet;
Index: src/stats/helper/gnuplot-helper.cc
===================================================================
--- a/src/stats/helper/gnuplot-helper.cc
+++ b/src/stats/helper/gnuplot-helper.cc
@@ -1,6 +1,7 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2013 University of Washington
+ * Copyright (c) 2015 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
@@ -16,6 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mitch Watrous (watrous@u.washington.edu)
+ * Modified by: Li Li (ll024@bucknell.edu)
*/
#include
@@ -41,9 +43,11 @@
m_title ("Gnuplot Helper Plot"),
m_xLegend ("X Values"),
m_yLegend ("Y Values"),
- m_terminalType ("png")
+ m_terminalType ("png"),
+ m_scalingFactor (1)
{
NS_LOG_FUNCTION (this);
+ m_collectorFactory.SetTypeId ("ns3::EventDrivenCollector");
// Note that this does not construct an aggregator. It will be
// constructed later when needed.
@@ -60,9 +64,11 @@
m_title (title),
m_xLegend (xLegend),
m_yLegend (yLegend),
- m_terminalType (terminalType)
+ m_terminalType (terminalType),
+ m_scalingFactor (1)
{
NS_LOG_FUNCTION (this);
+ m_collectorFactory.SetTypeId ("ns3::EventDrivenCollector");
// Construct the aggregator.
ConstructAggregator ();
@@ -79,6 +85,7 @@
const std::string &xLegend,
const std::string &yLegend,
const std::string &terminalType)
+
{
NS_LOG_FUNCTION (this << outputFileNameWithoutExtension << title
<< xLegend << yLegend << terminalType);
@@ -101,6 +108,48 @@
ConstructAggregator ();
}
+void
+GnuplotHelper::SetTerminalType (const std::string &terminalType)
+{
+ m_terminalType = terminalType;
+}
+
+void
+GnuplotHelper::SetScalingFactor (double scalingFactor)
+{
+ m_scalingFactor = scalingFactor;
+}
+
+void
+GnuplotHelper::SetCollectorType (std::string collectorType,
+ std::string n0, const AttributeValue &v0,
+ std::string n1, const AttributeValue &v1,
+ std::string n2, const AttributeValue &v2,
+ std::string n3, const AttributeValue &v3,
+ std::string n4, const AttributeValue &v4,
+ std::string n5, const AttributeValue &v5,
+ std::string n6, const AttributeValue &v6,
+ std::string n7, const AttributeValue &v7)
+{
+ ObjectFactory factory;
+ factory.SetTypeId (collectorType);
+ factory.Set (n0, v0);
+ factory.Set (n1, v1);
+ factory.Set (n2, v2);
+ factory.Set (n3, v3);
+ factory.Set (n4, v4);
+ factory.Set (n5, v5);
+ factory.Set (n6, v6);
+ factory.Set (n7, v7);
+ m_collectorFactory = factory;
+}
+
+void
+GnuplotHelper::SetKeyLocation(enum GnuplotAggregator::KeyLocation keyLocation)
+{
+ m_keyLocation = keyLocation;
+}
+
void
GnuplotHelper::PlotProbe (const std::string &typeId,
const std::string &path,
@@ -110,17 +159,19 @@
{
NS_LOG_FUNCTION (this << typeId << path << probeTraceSource << title << keyLocation);
- // Get a pointer to the aggregator.
- Ptr aggregator = GetAggregator ();
+ if (!m_aggregator)
+ {
+ ConstructAggregator ();
+ }
// Add a subtitle to the title to show the trace source's path.
- aggregator->SetTitle ( m_title + " \\n\\nTrace Source Path: " + path);
+ m_aggregator->SetTitle ( m_title + " \\n\\nTrace Source Path: " + path);
// Set the default dataset plotting style for the values.
- aggregator->Set2dDatasetDefaultStyle (Gnuplot2dDataset::LINES_POINTS);
+ m_aggregator->Set2dDatasetDefaultStyle (Gnuplot2dDataset::LINES_POINTS);
// Set the location of the key in the plot.
- aggregator->SetKeyLocation (keyLocation);
+ m_aggregator->SetKeyLocation (keyLocation);
std::string pathWithoutLastToken;
std::string lastToken;
@@ -162,7 +213,7 @@
// is only one matching config path. There is no need to find
// the wildcard matches because the passed in path has none.
matchIdentifier = "0";
- ConnectProbeToAggregator (typeId,
+ CreateDataCollectionChain (typeId,
matchIdentifier,
path,
probeTraceSource,
@@ -187,7 +238,7 @@
wildcardSeparator);
// Connect the probe to the aggregator for this match.
- ConnectProbeToAggregator (typeId,
+ CreateDataCollectionChain (typeId,
matchIdentifier,
matchedPath,
probeTraceSource,
@@ -203,6 +254,110 @@
void
GnuplotHelper::AddProbe (const std::string &typeId,
+ const std::string &path,
+ const std::string &probeTraceSource,
+ const std::string &dataSeriesName)
+{
+ NS_LOG_FUNCTION (this << typeId << path << probeTraceSource <<
+ dataSeriesName);
+
+ if (!m_aggregator)
+ {
+ ConstructAggregator ();
+ }
+
+ // Add a subtitle to the title to show the trace source's path.
+ m_aggregator->SetTitle ( m_title + " \\n\\nTrace Source Path: " + path);
+
+ // Set the default dataset plotting style for the values.
+ m_aggregator->Set2dDatasetDefaultStyle (Gnuplot2dDataset::LINES_POINTS);
+
+ // Set the location of the key in the plot.
+ m_aggregator->SetKeyLocation (m_keyLocation);
+
+ std::string pathWithoutLastToken;
+ std::string lastToken;
+
+ // See if the path has any wildcards.
+ bool pathHasNoWildcards = path.find ("*") == std::string::npos;
+
+ // Remove the last token from the path; this should correspond to the
+ // trace source attribute.
+ size_t lastSlash = path.find_last_of ("/");
+ if (lastSlash == std::string::npos)
+ {
+ pathWithoutLastToken = path;
+ lastToken = "";
+ }
+ else
+ {
+ // Chop off up to last token.
+ pathWithoutLastToken = path.substr (0, lastSlash);
+
+ // Save the last token without the last slash.
+ lastToken = path.substr (lastSlash + 1, std::string::npos);
+ }
+
+ // See if there are any matches for the probe's path with the last
+ // token removed; this corresponds to the traced object itself.
+ NS_LOG_DEBUG ("Searching config database for trace source " << path);
+ Config::MatchContainer matches = Config::LookupMatches (pathWithoutLastToken);
+ uint32_t matchCount = matches.GetN ();
+ NS_LOG_DEBUG ("Found " << matchCount << " matches for trace source " << path);
+
+ // This is used to make the probe's context be unique.
+ std::string matchIdentifier;
+
+ // Hook one or more probes and the aggregator together.
+ if (matchCount == 1 && pathHasNoWildcards)
+ {
+ // Connect the probe to the aggregator only once because there
+ // is only one matching config path. There is no need to find
+ // the wildcard matches because the passed in path has none.
+ matchIdentifier = "0";
+ CreateDataCollectionChain (typeId,
+ matchIdentifier,
+ path,
+ probeTraceSource,
+ dataSeriesName);
+ //title);
+ }
+ else if (matchCount > 0)
+ {
+ // Handle all of the matches if there are more than one.
+ for (uint32_t i = 0; i < matchCount; i++)
+ {
+ // Set the match identifier.
+ std::ostringstream matchIdentifierStream;
+ matchIdentifierStream << i;
+ matchIdentifier = matchIdentifierStream.str ();
+
+ // Construct the matched path and get the matches for each
+ // of the wildcards.
+ std::string wildcardSeparator = " ";
+ std::string matchedPath = matches.GetMatchedPath (i) + lastToken;
+ std::string wildcardMatches = GetWildcardMatches (path,
+ matchedPath,
+ wildcardSeparator);
+
+ // Connect the probe to the aggregator for this match.
+ CreateDataCollectionChain (typeId,
+ matchIdentifier,
+ matchedPath,
+ probeTraceSource,
+ dataSeriesName + "-" + wildcardMatches);
+ }
+ }
+ else
+ {
+ // There is a problem if there are no matching config paths.
+ NS_FATAL_ERROR ("Lookup of " << path << " got no matches");
+ }
+
+}
+
+void
+GnuplotHelper::AddProbeToMap (const std::string &typeId,
const std::string &probeName,
const std::string &path)
{
@@ -237,25 +392,22 @@
m_probeMap[probeName] = std::make_pair (probe, typeId);
}
+
void
-GnuplotHelper::AddTimeSeriesAdaptor (const std::string &adaptorName)
+GnuplotHelper::AddCollector (const std::string &collectorName)
{
- NS_LOG_FUNCTION (this << adaptorName);
+ NS_LOG_FUNCTION (this << collectorName);
- // See if this time series adaptor had already been added.
- if (m_timeSeriesAdaptorMap.count (adaptorName) > 0)
+ Ptr collector = DynamicCast (m_collectorFactory.Create ());
+ collector->Enable ();
+ // See if this collector had already been added.
+
+ if (m_collectorMap.count (collectorName) > 0)
{
- NS_ABORT_MSG ("That time series adaptor has already been added");
+ NS_ABORT_MSG ("That Collector has already been added");
}
-
- // Create the time series adaptor.
- Ptr timeSeriesAdaptor = CreateObject ();
-
- // Enable logging of data for the time series adaptor.
- timeSeriesAdaptor->Enable ();
-
- // Add this time series adaptor to the map so that can be used.
- m_timeSeriesAdaptorMap[adaptorName] = timeSeriesAdaptor;
+ // Add this collector to the map so that it can be used.
+ m_collectorMap[collectorName] = collector;
}
Ptr
@@ -307,7 +459,7 @@
}
void
-GnuplotHelper::ConnectProbeToAggregator (const std::string &typeId,
+GnuplotHelper::CreateDataCollectionChain (const std::string &typeId,
const std::string &matchIdentifier,
const std::string &path,
const std::string &probeTraceSource,
@@ -316,7 +468,10 @@
NS_LOG_FUNCTION (this << typeId << matchIdentifier << path << probeTraceSource
<< title);
- Ptr aggregator = GetAggregator ();
+ if (!m_aggregator)
+ {
+ ConstructAggregator ();
+ }
// Increment the total number of plot probes that have been created.
m_plotProbeCount++;
@@ -332,98 +487,148 @@
// Add the probe to the map of probes, which will keep the probe in
// memory after this function ends.
- AddProbe (typeId, probeName, path);
+ AddProbeToMap (typeId, probeName, path);
- // Because the callbacks to the probes' trace sources don't use the
- // probe's context, a unique adaptor needs to be created for each
- // probe context so that information is not lost.
- AddTimeSeriesAdaptor (probeContext);
+ // Add an Collector corresponding to the probe (this will also create
+ // a ScalingCollector corresponding to this trace source)
+ AddCollector (probeContext);
- // Connect the probe to the adaptor.
+ ConnectProbeToCollector(probeTraceSource, probeName, probeContext);
+
+ if (m_scalingFactor != 1.00) {
+ AddScalingCollector (probeContext);
+ }
+
+
+ ConnectCollectorToAggregator(probeContext);
+ // Add the dataset to the plot.
+ m_aggregator->Add2dDataset (probeContext, title);
+}
+
+
+void
+GnuplotHelper::AddScalingCollector(const std::string &collectorName)
+{
+ // Create the ScalingCollector
+ Ptr scalingCollector = CreateObject ();
+
+ // Set the scaling factor of the ScalingFactor object
+ scalingCollector->SetAttribute ("ScalingFactor", DoubleValue (m_scalingFactor));
+
+ // Enable logging of data for the ScalingCollector
+ scalingCollector->Enable();
+
+ // Add this collector to the map so that it can be used.
+ m_scalingCollectorMap[collectorName] = scalingCollector;
+}
+
+void
+GnuplotHelper::ConnectProbeToCollector(const std::string probeTraceSource,
+ const std::string probeName,
+ const std::string probeContext)
+{
+ // Connect the probe to the collector.
if (m_probeMap[probeName].second == "ns3::DoubleProbe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkDouble,
- m_timeSeriesAdaptorMap[probeContext]));
+ MakeCallback (&Collector::TraceSinkDouble,
+ m_collectorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::BooleanProbe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkBoolean,
- m_timeSeriesAdaptorMap[probeContext]));
+ MakeCallback (&Collector::TraceSinkBoolean,
+ m_collectorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::PacketProbe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
- m_timeSeriesAdaptorMap[probeContext]));
+ MakeCallback (&Collector::TraceSinkUinteger32,
+ m_collectorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::ApplicationPacketProbe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
- m_timeSeriesAdaptorMap[probeContext]));
+ MakeCallback (&Collector::TraceSinkUinteger32,
+ m_collectorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::Ipv4PacketProbe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
- m_timeSeriesAdaptorMap[probeContext]));
+ MakeCallback (&Collector::TraceSinkUinteger32,
+ m_collectorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::Ipv6PacketProbe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
- m_timeSeriesAdaptorMap[probeContext]));
+ MakeCallback (&Collector::TraceSinkUinteger32,
+ m_collectorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::Uinteger8Probe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger8,
- m_timeSeriesAdaptorMap[probeContext]));
+ MakeCallback (&Collector::TraceSinkUinteger8,
+ m_collectorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::Uinteger16Probe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger16,
- m_timeSeriesAdaptorMap[probeContext]));
+ MakeCallback (&Collector::TraceSinkUinteger16,
+ m_collectorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::Uinteger32Probe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkUinteger32,
- m_timeSeriesAdaptorMap[probeContext]));
+ MakeCallback (&Collector::TraceSinkUinteger32,
+ m_collectorMap[probeContext]));
}
else if (m_probeMap[probeName].second == "ns3::TimeProbe")
{
m_probeMap[probeName].first->TraceConnectWithoutContext
(probeTraceSource,
- MakeCallback (&TimeSeriesAdaptor::TraceSinkDouble,
- m_timeSeriesAdaptorMap[probeContext]));
+ MakeCallback (&Collector::TraceSinkTime,
+ m_collectorMap[probeContext]));
}
else
{
NS_FATAL_ERROR ("Unknown probe type " << m_probeMap[probeName].second << "; need to add support in the helper for this");
}
- // Connect the adaptor to the aggregator.
- std::string adaptorTraceSource = "Output";
- m_timeSeriesAdaptorMap[probeContext]->TraceConnect
- (adaptorTraceSource,
- probeContext,
- MakeCallback (&GnuplotAggregator::Write2d, aggregator));
+}
- // Add the dataset to the plot.
- aggregator->Add2dDataset (probeContext, title);
+void
+GnuplotHelper::ConnectCollectorToAggregator(const std::string probeContext)
+{
+ if (m_scalingFactor != 1.00) {
+ // if there is a ScalingCollector object, then connect
+ // the collector to the ScalingCollector object and then
+ // the ScalingCollector object to the aggregator
+ m_collectorMap[probeContext]->TraceConnectWithoutContext
+ ("Output",
+ MakeCallback(&ScalingCollector::TraceSinkDouble,
+ m_scalingCollectorMap[probeContext]));
+
+ // Connect the ScalingCollector to the aggregator.
+ m_scalingCollectorMap[probeContext]->TraceConnect
+ ("Output",
+ probeContext,
+ MakeCallback (&GnuplotAggregator::Write2d, m_aggregator));
+ } else {
+ // Otherwise connect the collector directly to the aggregator
+ m_collectorMap[probeContext]->TraceConnect
+ ("Output",
+ probeContext,
+ MakeCallback (&GnuplotAggregator::Write2d, m_aggregator));
+ }
}
} // namespace ns3
Index: src/stats/helper/gnuplot-helper.h
===================================================================
--- a/src/stats/helper/gnuplot-helper.h
+++ b/src/stats/helper/gnuplot-helper.h
@@ -1,6 +1,7 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2013 University of Washington
+ * Copyright (c) 2015 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
@@ -16,6 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mitch Watrous (watrous@u.washington.edu)
+ * Modified by: Li Li (ll024@bucknell.edu)
*/
#ifndef GNUPLOT_HELPER_H
@@ -26,9 +28,13 @@
#include
#include "ns3/object-factory.h"
#include "ns3/ptr.h"
+#include "ns3/deprecated.h"
#include "ns3/probe.h"
#include "ns3/gnuplot-aggregator.h"
-#include "ns3/time-series-adaptor.h"
+#include "ns3/event-driven-collector.h"
+#include "ns3/time-series-collector.h"
+#include "ns3/nstime.h"
+#include "ns3/scaling-collector.h"
namespace ns3 {
@@ -67,7 +73,7 @@
const std::string &title,
const std::string &xLegend,
const std::string &yLegend,
- const std::string &terminalType = "png");
+ const std::string &terminalType = "png") NS_DEPRECATED;
virtual ~GnuplotHelper ();
@@ -78,7 +84,7 @@
* \param xLegend the legend for the x horizontal axis.
* \param yLegend the legend for the y vertical axis.
* \param terminalType terminal type setting string for output. The
- * default terminal type is "png"
+ * default terminal type is "png"
*
* Configures plot related parameters for this gnuplot helper so
* that it will create a space separated gnuplot data file named
@@ -94,6 +100,61 @@
const std::string &terminalType = "png");
/**
+ * \param terminalType terminal type setting string for output.
+ */
+ void SetTerminalType (const std::string &terminalType);
+
+ /**
+ * Data output from the collector may be scaled down by this amount
+ * in the resultant values; e.g. select a value of 1000 to make the
+ * y-axis units in terms of thousands. Default value is 1.
+ * Note that this function must be called before AddProbe() to have
+ * effect on the next probe trace source.
+ *
+ * \param scalingFactor the scaling factor factor applied on output
+ */
+ void SetScalingFactor (double scalingFactor);
+
+ /**
+ * Select the collector type and configure its attributes for any probes
+ * added thereafter (but not affecting probes added before).
+ * The default is "ns3::EventDrivenCollector".
+ * \param collectorType the ns-3 TypeId string of the collector type
+ * \param n0 the name of the attribute to set
+ * \param v0 the value of the attribute to set
+ * \param n1 the name of the attribute to set
+ * \param v1 the value of the attribute to set
+ * \param n2 the name of the attribute to set
+ * \param v2 the value of the attribute to set
+ * \param n3 the name of the attribute to set
+ * \param v3 the value of the attribute to set
+ * \param n4 the name of the attribute to set
+ * \param v4 the value of the attribute to set
+ * \param n5 the name of the attribute to set
+ * \param v5 the value of the attribute to set
+ * \param n6 the name of the attribute to set
+ * \param v6 the value of the attribute to set
+ * \param n7 the name of the attribute to set
+ * \param v7 the value of the attribute to set
+ */
+ void SetCollectorType (std::string collectorType,
+ std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+ std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+ std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+ std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+ std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+ std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+ std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+ std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+
+ /**
+ * Set the key location on the plot; the default is KEY_INSIDE.
+ * \param keyLocation the location of the key in the plot.
+ */
+ void SetKeyLocation (enum GnuplotAggregator::KeyLocation keyLocation);
+
+
+ /**
* \param typeId the type ID for the probe used when it is created.
* \param path Config path for underlying trace source to be probed
* \param probeTraceSource the probe trace source to access.
@@ -123,21 +184,41 @@
const std::string &path,
const std::string &probeTraceSource,
const std::string &title,
- enum GnuplotAggregator::KeyLocation keyLocation = GnuplotAggregator::KEY_INSIDE);
+ enum GnuplotAggregator::KeyLocation keyLocation = GnuplotAggregator::KEY_INSIDE) NS_DEPRECATED;
/**
- * \param adaptorName the timeSeriesAdaptor's name.
+ * \param typeId the type ID for the probe used when it is created.
+ * \param path Config path for underlying trace source to be probed
+ * \param probeTraceSource the probe trace source to access.
+ * \param dataSeriesName the data series name to be associated to this dataset
*
- * \brief Adds a time series adaptor to be used to make the plot.
+ * Plots one or more datasets on the previously configured plot by hooking
+ * the ns-3 trace source with a probe, and then plotting the values from the
+ * probeTraceSource. The dataset
+ * will have the provided title, and will consist of the 'newValue'
+ * at each timestamp. The currently configured collector type will
+ * determine the policy for exporting data to the GnuplotAggregator.
+ *
+ * If the config path has more than one match in the system
+ * (e.g. there is a wildcard), then one dataset for each match will
+ * be plotted. The dataset titles will be suffixed with the matched
+ * characters for each of the wildcards in the config path,
+ * separated by spaces. For example, if the proposed dataset title
+ * is the string "bytes", and there are two wildcards in the path,
+ * then dataset titles like "bytes-0 0" or "bytes-12 9" will be
+ * possible as labels for the datasets that are plotted.
*/
- void AddTimeSeriesAdaptor (const std::string &adaptorName);
+ void AddProbe (const std::string &typeId,
+ const std::string &path,
+ const std::string &probeTraceSource,
+ const std::string &dataSeriesName);
/**
* \param probeName the probe's name.
* \return Ptr to probe
* \brief Gets the specified probe.
*/
- Ptr GetProbe (std::string probeName) const;
+ Ptr GetProbe (std::string probeName) const NS_DEPRECATED;
/**
* \return Ptr to GnuplotAggregator object
@@ -146,7 +227,7 @@
* This function is non-const because an aggregator may be lazily
* created by this method.
*/
- Ptr GetAggregator ();
+ Ptr GetAggregator () NS_DEPRECATED;
private:
@@ -157,7 +238,7 @@
*
* \brief Adds a probe to be used to make the plot.
*/
- void AddProbe (const std::string &typeId,
+ void AddProbeToMap (const std::string &typeId,
const std::string &probeName,
const std::string &path);
@@ -174,14 +255,48 @@
* \param probeTraceSource the probe trace source to access.
* \param title the title to be associated to this dataset.
*
- * \brief Connects the probe to the aggregator.
+ * \brief Creates the data collection data flow chain, including
+ * a probe, one or more collectors, and an aggregator
*/
- void ConnectProbeToAggregator (const std::string &typeId,
+ void CreateDataCollectionChain (const std::string &typeId,
const std::string &matchIdentifier,
const std::string &path,
const std::string &probeTraceSource,
const std::string &title);
+ /**
+ * \param collectorName the name of the collector
+ *
+ * \brief Adds the collector to the GnuplotHelper.
+ */
+ void AddCollector(const std::string &collectorName);
+
+ /**
+ * \param collectorName the name of the ScalingCollector
+ *
+ * \brief Adds a scaling collector
+ */
+ void AddScalingCollector(const std::string &collectorName);
+
+ /**
+ * \param probeTraceSource the trace source of the probe
+ * \param probeName the name of the probe in the map
+ * \param probeContext the context of the probe in the collector map
+ *
+ * \brief Connects a probe to a Collector object
+ */
+ void ConnectProbeToCollector(const std::string probeTraceSource,
+ const std::string probeName,
+ const std::string probeContext);
+
+ /**
+ * \param probeContext the name of the collector in the map
+ *
+ * \brief connect a collector to an aggregator
+ */
+ void ConnectCollectorToAggregator(const std::string probeContext);
+
+
/// Used to create the probes and collectors as they are added.
ObjectFactory m_factory;
@@ -191,8 +306,11 @@
/// Maps probe names to probes.
std::map, std::string> > m_probeMap;
- /// Maps time series adaptor names to time series adaptors.
- std::map > m_timeSeriesAdaptorMap;
+ /// Maps Collector names to Collectors.
+ std::map > m_collectorMap;
+
+ // Maps ScalingCollector names to ScalingCollector
+ std::map > m_scalingCollectorMap;
/// Number of plot probes that have been created.
uint32_t m_plotProbeCount;
@@ -212,6 +330,15 @@
/// Terminal type for the plot.
std::string m_terminalType;
+ /// Factory object for instantiating collector
+ ObjectFactory m_collectorFactory;
+
+ /// The scaling factor
+ double m_scalingFactor;
+
+ /// The key location
+ enum GnuplotAggregator::KeyLocation m_keyLocation;
+
}; // class GnuplotHelper
Index: src/stats/model/collector.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/model/collector.cc
@@ -0,0 +1,98 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#include
+#include
+
+#include "ns3/object.h"
+#include "ns3/log.h"
+#include "ns3/boolean.h"
+#include "ns3/uinteger.h"
+#include "ns3/simulator.h"
+#include "ns3/collector.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("Collector");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Collector);
+
+TypeId
+Collector::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Collector")
+ .SetParent ();
+ return tid;
+}
+
+Collector::Collector ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+Collector::~Collector ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+Collector::TraceSinkBoolean (bool oldValue, bool newValue)
+{
+ NS_LOG_FUNCTION (this << oldValue << newValue);
+ TraceSinkDouble (oldValue, newValue);
+}
+
+void
+Collector::TraceSinkUinteger32 (uint32_t oldValue, uint32_t newValue)
+{
+ NS_LOG_FUNCTION (this << oldValue << newValue);
+ TraceSinkDouble (oldValue, newValue);
+}
+
+void
+Collector::TraceSinkUinteger16 (uint16_t oldValue, uint16_t newValue)
+{
+ NS_LOG_FUNCTION (this << oldValue << newValue);
+ TraceSinkDouble (oldValue, newValue);
+}
+
+void
+Collector::TraceSinkUinteger8 (uint8_t oldValue, uint8_t newValue)
+{
+ NS_LOG_FUNCTION (this << oldValue << newValue);
+ TraceSinkDouble (oldValue, newValue);
+}
+
+void
+Collector::TraceSinkSequenceNumber32 (SequenceNumber32 &oldValue, SequenceNumber32 &newValue)
+{
+ NS_LOG_FUNCTION (this << oldValue << newValue);
+ TraceSinkDouble (oldValue.GetValue (), newValue.GetValue ());
+}
+
+void
+Collector::TraceSinkTime (Time &oldValue, Time &newValue)
+{
+ NS_LOG_FUNCTION (this << oldValue << newValue);
+ TraceSinkDouble (oldValue.GetSeconds (), newValue.GetSeconds ());
+}
+
+}
Index: src/stats/model/collector.h
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/model/collector.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#ifndef COLLECTOR_H
+#define COLLECTOR_H
+
+#include "ns3/object.h"
+#include "ns3/nstime.h"
+#include "ns3/data-collection-object.h"
+#include "ns3/event-id.h"
+#include "ns3/type-id.h"
+#include "ns3/sequence-number.h"
+#include "ns3/nstime.h"
+
+namespace ns3 {
+
+class Collector : public DataCollectionObject
+{
+public:
+ static TypeId GetTypeId (void);
+
+ Collector ();
+ virtual ~Collector ();
+
+ /**
+ * \brief Collects the double values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ virtual void TraceSinkDouble (double oldValue, double newValue) = 0;
+
+ /**
+ * \brief Collects the boolean values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ virtual void TraceSinkBoolean (bool oldValue, bool newValue);
+
+ /**
+ * \brief Collects the uint32_t values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ virtual void TraceSinkUinteger32 (uint32_t oldValue, uint32_t newValue);
+
+ /**
+ * \brief Collects the uint16_t values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ virtual void TraceSinkUinteger16 (uint16_t oldValue, uint16_t newValue);
+
+ /**
+ * \brief Collects the uint8_t values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ virtual void TraceSinkUinteger8 (uint8_t oldValue, uint8_t newValue);
+
+ /**
+ * \brief Collects the SequenceNumber32 values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ virtual void TraceSinkSequenceNumber32 (SequenceNumber32 &oldValue, SequenceNumber32 &newValue);
+
+ /**
+ * \brief Collects the Time values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ virtual void TraceSinkTime (Time &oldValue, Time &newValue);
+
+
+};
+
+
+} // namespace ns3
+
+
+#endif // COLLECTOR_H
Index: src/stats/model/data-collection-object.cc
===================================================================
--- a/src/stats/model/data-collection-object.cc
+++ b/src/stats/model/data-collection-object.cc
@@ -21,13 +21,14 @@
#include "ns3/log.h"
#include "ns3/string.h"
#include "ns3/boolean.h"
+#include "ns3/nstime.h"
#include "data-collection-object.h"
+NS_LOG_COMPONENT_DEFINE ("DataCollectionObject");
+
namespace ns3 {
-NS_LOG_COMPONENT_DEFINE ("DataCollectionObject");
-
NS_OBJECT_ENSURE_REGISTERED (DataCollectionObject);
TypeId
@@ -94,4 +95,24 @@
m_enabled = false;
}
+void
+DataCollectionObject::SetEnabledPeriod (Time startTime, Time endTime)
+{
+ NS_LOG_FUNCTION (this);
+ m_startTime = startTime;
+ m_endTime = endTime;
+ isEnabledPeriodSet = true;
+ // automatically enable the collector in order for TimeDrivenCollector
+ // to shedule the first event. This line will do nothing to
+ // EventDrivenCollector
+ Enable ();
+}
+
+void
+DataCollectionObject::UnsetEnabledPeriod (void)
+{
+ isEnabledPeriodSet = false;
+}
+
+
} // namespace ns3
Index: src/stats/model/data-collection-object.h
===================================================================
--- a/src/stats/model/data-collection-object.h
+++ b/src/stats/model/data-collection-object.h
@@ -23,6 +23,7 @@
#include
#include "ns3/object.h"
+#include "ns3/nstime.h"
namespace ns3 {
@@ -47,9 +48,9 @@
virtual ~DataCollectionObject ();
/// Set the status of an individual object.
- void Enable (void);
+ virtual void Enable (void);
/// Unset the status of an individual object.
- void Disable (void);
+ virtual void Disable (void);
/// Check the status of an individual object.
virtual bool IsEnabled (void) const;
@@ -60,6 +61,64 @@
/// Set the object's name. All spaces are replaced by underscores.
void SetName (std::string name);
+ /// Define the Collector callback function signature. This is used
+ /// in the AddTraceSource() function in Collector class.
+ typedef void (* CollectorTraceCallback) (const double timeStamp, const bool value);
+
+ /**
+ * \param startTime the time the DataCollectionObject is enabled
+ * \param endTime the time the DataCollectionObject is disabled
+ *
+ * \brief set the time period in which the collector will be enabled.
+ *
+ * Note that once this method is called, you do not need to explicitly call
+ * Collector::Enable() or Collector::Disable() again. The Collector class
+ * will take care of everything for you.
+ *
+ * A good pratice will be that after calling SetEnabledPeriod(), do not
+ * mess around with Enable() and Disable() anymore. This function takes
+ * care of everything for you.
+ */
+ void SetEnabledPeriod (Time startTime, Time endTime);
+
+ /**
+ * \brief Disable the enabled period so that you can control the collector
+ * manually with Enable() and Disable()
+ */
+ void UnsetEnabledPeriod (void);
+
+ /**
+ * \brief Get the starting time of the DataCollectionObject
+ *
+ * \return the starting time of the DataCollectionObject
+ */
+ Time GetStartTime (void)
+ {
+ return m_startTime;
+ }
+
+ /**
+ * \brief Get the ending time of the DataCollectionObject
+ *
+ * \return the ending time of the DataCollectionObject
+ */
+ Time GetEndTime (void)
+ {
+ return m_endTime;
+ }
+
+
+ /**
+ * Return whether or not the enabled period is set
+ *
+ * \return a boolean value indicating whether or not the enabled period is set
+ */
+ bool IsEnabledPeriodSet (void)
+ {
+ return isEnabledPeriodSet;
+ }
+
+
protected:
/// Object's activation state.
bool m_enabled;
@@ -67,6 +126,17 @@
/// Name of the object within the data collection framework
std::string m_name;
+ /// Report Data to downstream objects
+ void ReportData (void);
+
+ /// The starting time of the DataCollectionObject
+ Time m_startTime;
+
+ /// The ending time of the DataCollectionObject
+ Time m_endTime;
+
+ /// Whether or not the enabled period is set
+ bool isEnabledPeriodSet;
};
} // namespace ns3
Index: src/stats/model/event-driven-collector.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/model/event-driven-collector.cc
@@ -0,0 +1,89 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#include "ns3/object.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/event-driven-collector.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("EventDrivenCollector");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (EventDrivenCollector);
+
+TypeId
+EventDrivenCollector::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::EventDrivenCollector")
+ .SetParent ()
+ .AddConstructor ()
+ .AddTraceSource ("Output",
+ "The double value received by the trace sink",
+ MakeTraceSourceAccessor (&EventDrivenCollector::m_output),
+ "ns3::DataCollectionObject::CollectorTraceCallback")
+ ;
+ return tid;
+}
+
+EventDrivenCollector::EventDrivenCollector ()
+ : Collector ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+EventDrivenCollector::~EventDrivenCollector ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+EventDrivenCollector::TraceSinkDouble (double oldValue, double newValue)
+{
+ NS_LOG_FUNCTION (this << oldValue << newValue);
+ if (!IsEnabled ())
+ {
+ NS_LOG_DEBUG ("Collector not enabled");
+ return;
+ }
+ m_doubleValue = newValue;
+
+ // Report data to downstream objects
+ ReportData ();
+}
+
+void
+EventDrivenCollector::ReportData (void)
+{
+ NS_LOG_FUNCTION (this);
+ if (!IsEnabled ())
+ {
+ return;
+ }
+ // get current simulation time
+ double time = Simulator::Now ().GetSeconds ();
+
+ // report the time and the newly received value to downstream
+ // objects
+ m_output (time, m_doubleValue);
+}
+
+} // namespace ns3
Index: src/stats/model/event-driven-collector.h
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/model/event-driven-collector.h
@@ -0,0 +1,77 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+
+#ifndef EVENT_DRIVEN_COLLECTOR_H
+#define EVENT_DRIVEN_COLLECTOR_H
+
+#include "ns3/object.h"
+#include "ns3/collector.h"
+#include "ns3/event-id.h"
+#include "ns3/type-id.h"
+#include "ns3/traced-value.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup collectors
+ * \brief Collector class used to collect a single trace source of
+ * double-valued data and output the data to downstream objects.
+ */
+class EventDrivenCollector : public Collector
+{
+public:
+ /**
+ * \brief Get the type ID
+ * \return the object TypeId
+ */
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Constructs a EventDrivenCollector object
+ */
+ EventDrivenCollector ();
+ virtual ~EventDrivenCollector ();
+
+ /**
+ * \brief Collects the double values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ void TraceSinkDouble (double oldValue, double newValue);
+
+private:
+ // the output data trace source
+ TracedCallback m_output;
+
+ /**
+ * \brief Reports data to downstream objects
+ */
+ void ReportData (void);
+
+ // a double value to keep track of the double value
+ // received by the trace sink
+ double m_doubleValue;
+};
+
+} //namespace ns3
+
+#endif // EVENT_DRIVEN_COLLECTOR_H
Index: src/stats/model/scaling-collector.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/model/scaling-collector.cc
@@ -0,0 +1,96 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#include "ns3/object.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/scaling-collector.h"
+
+NS_LOG_COMPONENT_DEFINE ("ScalingCollector");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (ScalingCollector);
+
+TypeId
+ScalingCollector::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::ScalingCollector")
+ .SetParent ()
+ .AddConstructor ()
+ .AddAttribute ("ScalingFactor",
+ "Input data will be scaled by multiplying by this quantity",
+ DoubleValue (1.0),
+ MakeDoubleAccessor (&ScalingCollector::m_scalingFactor),
+ MakeDoubleChecker ())
+ .AddTraceSource ("Output",
+ "The double value received by the trace sink after scaling",
+ MakeTraceSourceAccessor (&ScalingCollector::m_output),
+ "ns3::DataCollectionObject::CollectorTraceCallback")
+ ;
+ return tid;
+}
+
+ScalingCollector::ScalingCollector ()
+ : Collector ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+ScalingCollector::~ScalingCollector ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+ScalingCollector::TraceSinkDouble (double oldValue, double newValue)
+{
+ NS_LOG_FUNCTION (this << oldValue << newValue);
+ if (!IsEnabled ())
+ {
+ NS_LOG_DEBUG ("Collector not enabled");
+ return;
+ }
+
+ // scale the value received by multiplying it with the scaling
+ // factor, and store the data in m_doubleValue
+ m_doubleValue = newValue * m_scalingFactor;
+
+ // Report data to downstream objects
+ ReportData ();
+}
+
+void
+ScalingCollector::ReportData (void)
+{
+ NS_LOG_FUNCTION (this);
+ if (!IsEnabled ())
+ {
+ return;
+ }
+ // get current simulation time
+ double time = Simulator::Now ().GetSeconds ();
+
+ // report the time and the newly received value to downstream
+ // objects
+ m_output (time, m_doubleValue);
+}
+
+} //namespace ns3
Index: src/stats/model/scaling-collector.h
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/model/scaling-collector.h
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#ifndef SCALING_COLLECTOR_H
+#define SCALING_COLLECTOR_H
+
+#include "ns3/object.h"
+#include "ns3/collector.h"
+#include "ns3/event-id.h"
+#include "ns3/type-id.h"
+#include "ns3/traced-value.h"
+
+namespace ns3 {
+/**
+ * \ingroup collectors
+ * \brief Collector class used to multiply a single trace source of
+ * double-valued data by a scaling factor and output the scaled value
+ * to downstream objects
+ */
+class ScalingCollector : public Collector
+{
+public:
+ /**
+ * \brief Get the type ID
+ * \return the object TypeId
+ */
+ static TypeId GetTypeId (void);
+
+ ScalingCollector ();
+ virtual ~ScalingCollector ();
+
+ /**
+ * \brief Collects the double values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ void TraceSinkDouble (double oldValue, double newValue);
+
+private:
+ // the output data trace source
+ TracedCallback m_output;
+
+ /**
+ * \brief Reports data to downstream objects
+ */
+ void ReportData (void);
+
+ // a double value to keep track of the double value
+ // received by the trace sink
+ double m_doubleValue;
+
+ double m_scalingFactor;
+};
+
+
+} //namespace ns3
+
+#endif //SCALING_COLLECTOR_H
Index: src/stats/model/time-averaging-collector.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/model/time-averaging-collector.cc
@@ -0,0 +1,158 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#include "ns3/object.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/time-averaging-collector.h"
+
+NS_LOG_COMPONENT_DEFINE ("TimeAveragingCollector");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TimeAveragingCollector);
+
+TypeId
+TimeAveragingCollector::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::TimeAveragingCollector")
+ .SetParent ()
+ .AddConstructor ()
+ .AddAttribute ("Period",
+ "The period in seconds between reports",
+ TimeValue (Seconds (1.0)),
+ MakeTimeAccessor (&TimeAveragingCollector::SetPeriod,
+ &TimeAveragingCollector::GetPeriod),
+ MakeTimeChecker ())
+ .AddTraceSource ("Output",
+ "The double value received by the trace sink",
+ MakeTraceSourceAccessor (&TimeAveragingCollector::m_output),
+ "ns3::DataCollectionObject::CollectorTraceCallback")
+ ;
+ return tid;
+}
+
+TimeAveragingCollector::TimeAveragingCollector ()
+ : Collector (),
+ m_doubleValue (0),
+ m_hasReportBeenScheduled (false),
+ m_batchCount (0)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+TimeAveragingCollector::~TimeAveragingCollector ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+TimeAveragingCollector::ReportData (void)
+{
+ NS_LOG_FUNCTION (this);
+ if (!IsEnabled ())
+ {
+ return;
+ }
+ double time = Simulator::Now ().GetSeconds ();
+ // output the data downstream
+ m_output (time, m_doubleValue);
+
+ // clear the batch count
+ m_batchCount = 0;
+
+ m_reportEventId = Simulator::Schedule (m_period, &TimeAveragingCollector::ReportData, this);
+ m_hasReportBeenScheduled = true;
+}
+
+void
+TimeAveragingCollector::TraceSinkDouble (double oldValue, double newValue)
+{
+ NS_LOG_FUNCTION (this << oldValue << newValue);
+ if (!IsEnabled ())
+ {
+ NS_LOG_DEBUG ("Collector not enabled");
+ return;
+ }
+
+
+ // keep track of the average value
+ m_doubleValue = (m_doubleValue * m_batchCount + newValue) / (m_batchCount + 1);
+
+ // increment the batch count
+ m_batchCount++;
+}
+
+void
+TimeAveragingCollector::SetPeriod (Time period)
+{
+ m_period = period;
+ PeriodChanged ();
+ NS_LOG_DEBUG ("TimeAveragingCollector " << this << " period changed");
+}
+
+Time
+TimeAveragingCollector::GetPeriod () const
+{
+ NS_LOG_FUNCTION (this);
+ return m_period;
+}
+
+void
+TimeAveragingCollector::PeriodChanged (void)
+{
+ NS_LOG_FUNCTION (this);
+ if (m_hasReportBeenScheduled)
+ {
+ Simulator::Cancel (m_reportEventId);
+ m_hasReportBeenScheduled = false;
+ NS_LOG_DEBUG ("TimeAveragingCollector " << this << " data report has been cancelled");
+ }
+
+ if (!IsEnabled ())
+ {
+ return;
+ }
+
+ m_batchCount = 0;
+ m_doubleValue = 0;
+ m_reportEventId = Simulator::Schedule (m_period, &TimeAveragingCollector::ReportData, this);
+ m_hasReportBeenScheduled = true;
+ NS_LOG_DEBUG ("TimeAveragingCollector " << this << " data report has been scheduled");
+}
+
+// Override DataCollectionObject::Enable() to schedule the very first event
+// whenever the collector is enabled
+void
+TimeAveragingCollector::Enable (void)
+{
+ DataCollectionObject::Enable ();
+ if (m_hasReportBeenScheduled)
+ {
+ Simulator::Cancel (m_reportEventId);
+ m_hasReportBeenScheduled = false;
+ NS_LOG_DEBUG ("TimeAveragingCollector " << this << " data report has been cancelled");
+ }
+
+ m_reportEventId = Simulator::Schedule (m_period, &TimeAveragingCollector::ReportData, this);
+ m_hasReportBeenScheduled = true;
+}
+
+} // namespace ns3
Index: src/stats/model/time-averaging-collector.h
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/model/time-averaging-collector.h
@@ -0,0 +1,121 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#ifndef TIME_AVERAGING_COLLECTOR_H
+#define TIME_AVERAGING_COLLECTOR_H
+
+#include "ns3/object.h"
+#include "ns3/collector.h"
+#include "ns3/event-id.h"
+#include "ns3/type-id.h"
+#include "ns3/traced-value.h"
+#include "ns3/nstime.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup collectors
+ * \brief TimeAveragingCollector class collects a single trace of
+ * double-valued data and outputs the time-averaged value (i.e. a rate) every
+ * measurement period.
+ */
+class TimeAveragingCollector : public Collector
+{
+public:
+ /**
+ * \brief Get the type ID
+ * \return the object TypeId
+ */
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Constructs a TimeAveragingCollector object
+ */
+ TimeAveragingCollector ();
+
+ virtual ~TimeAveragingCollector ();
+
+ /**
+ * \brief Collects the double values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ void TraceSinkDouble (double oldValue, double newValue);
+
+ /**
+ * \brief Sets the time period to report data
+ *
+ * \param period a variable of type Time to indicate the period
+ */
+ void SetPeriod (Time period);
+
+ /**
+ * \brief Gets the time period to report data
+ *
+ * \return the time period to report data
+ */
+ Time GetPeriod () const;
+
+ /**
+ * \brief Override DataCollectionObject::Enable() to schedule the very
+ * first event whenever the collector is enabled. This method will
+ * also cancel any previously scheduled event if one exists.
+ *
+ * \sa ns3::DataCollectionObject::Enable
+ */
+ void Enable (void);
+private:
+ // the output data trace source
+ TracedCallback m_output;
+
+ /**
+ * \brief Reports data to downstream objects
+ */
+ void ReportData (void);
+
+ /**
+ * \brief Does necessary work every time the period has changed
+ */
+ void PeriodChanged (void);
+
+ // a double value to keep track of the double value
+ // received by the trace sink
+ double m_doubleValue;
+
+ // the period to output data
+ Time m_period;
+
+ // The event ID used to keep track of the scheduled event
+ EventId m_reportEventId;
+
+ // a boolean value showing whether or not an event has been scheduled
+ bool m_hasReportBeenScheduled;
+
+ // an integer value to keep track of the number of data points received
+ // in one batch (in between two TraceSink calls)
+ int m_batchCount;
+
+};
+
+
+} // namespace ns3
+
+#endif // TIME_AVERAGING_COLLECTOR_H
Index: src/stats/model/time-probe.cc
===================================================================
--- a/src/stats/model/time-probe.cc
+++ b/src/stats/model/time-probe.cc
@@ -28,6 +28,7 @@
#include "ns3/names.h"
#include "ns3/config.h"
#include "ns3/trace-source-accessor.h"
+#include "ns3/traced-value.h"
namespace ns3 {
@@ -45,7 +46,7 @@
.AddTraceSource ("Output",
"The double valued (units of seconds) probe output",
MakeTraceSourceAccessor (&TimeProbe::m_output),
- "ns3::TracedValue::DoubleCallback")
+ "ns3::Time::TracedValueCallback")
;
return tid;
}
@@ -53,7 +54,6 @@
TimeProbe::TimeProbe ()
{
NS_LOG_FUNCTION (this);
- m_output = 0;
}
TimeProbe::~TimeProbe ()
@@ -61,7 +61,7 @@
NS_LOG_FUNCTION (this);
}
-double
+Time
TimeProbe::GetValue (void) const
{
NS_LOG_FUNCTION (this);
@@ -71,7 +71,7 @@
TimeProbe::SetValue (Time newVal)
{
NS_LOG_FUNCTION (this << newVal.GetSeconds ());
- m_output = newVal.GetSeconds ();
+ m_output = newVal;
}
void
@@ -106,7 +106,7 @@
NS_LOG_FUNCTION (this << oldData.GetSeconds () << newData.GetSeconds ());
if (IsEnabled ())
{
- m_output = newData.GetSeconds ();
+ m_output = newData;
}
}
Index: src/stats/model/time-probe.h
===================================================================
--- a/src/stats/model/time-probe.h
+++ b/src/stats/model/time-probe.h
@@ -39,7 +39,7 @@
*
* 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
+ * Time. 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 ()
@@ -57,9 +57,9 @@
virtual ~TimeProbe ();
/**
- * \return the most recent value (units of seconds)
+ * \return the most recent value
*/
- double GetValue (void) const;
+ Time GetValue (void) const;
/**
* \param value set the traced Time to a new value
@@ -102,7 +102,7 @@
*/
void TraceSink (Time oldData, Time newData);
- TracedValue m_output; //!< Output trace source.
+ TracedValue m_output; //!< Output trace source.
};
} // namespace ns3
Index: src/stats/model/time-series-adaptor.cc
===================================================================
deleted file mode 100644
--- a/src/stats/model/time-series-adaptor.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013 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
- *
- * Author: Mitch Watrous (watrous@u.washington.edu)
- */
-
-#include
-#include
-
-#include "ns3/time-series-adaptor.h"
-#include "ns3/object.h"
-#include "ns3/traced-value.h"
-#include "ns3/log.h"
-#include "ns3/simulator.h"
-
-namespace ns3 {
-
-NS_LOG_COMPONENT_DEFINE ("TimeSeriesAdaptor");
-
-NS_OBJECT_ENSURE_REGISTERED (TimeSeriesAdaptor);
-
-TypeId
-TimeSeriesAdaptor::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::TimeSeriesAdaptor")
- .SetParent ()
- .SetGroupName ("Stats")
- .AddConstructor ()
- .AddTraceSource ( "Output",
- "The current simulation time versus "
- "the current value converted to a double",
- MakeTraceSourceAccessor (&TimeSeriesAdaptor::m_output),
- "ns3::TimeSeriesAdaptor::OutputTracedCallback")
- ;
- return tid;
-}
-
-TimeSeriesAdaptor::TimeSeriesAdaptor ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-TimeSeriesAdaptor::~TimeSeriesAdaptor ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-void
-TimeSeriesAdaptor::TraceSinkDouble (double oldData, double newData)
-{
- NS_LOG_FUNCTION (this << oldData << newData);
-
- // Don't do anything if the time series adaptor is not enabled.
- if (!IsEnabled ())
- {
- NS_LOG_DEBUG ("Time series adaptor not enabled");
- return;
- }
-
- // Time stamp the value with the current time in seconds.
- m_output (Simulator::Now ().GetSeconds (), newData);
-}
-
-void
-TimeSeriesAdaptor::TraceSinkBoolean (bool oldData, bool newData)
-{
- NS_LOG_FUNCTION (this << oldData << newData);
-
- // Call the trace sink that actually does something.
- TraceSinkDouble (oldData, newData);
-}
-
-void
-TimeSeriesAdaptor::TraceSinkUinteger8 (uint8_t oldData, uint8_t newData)
-{
- NS_LOG_FUNCTION (this << oldData << newData);
-
- // Call the trace sink that actually does something.
- TraceSinkDouble (oldData, newData);
-}
-
-void
-TimeSeriesAdaptor::TraceSinkUinteger16 (uint16_t oldData, uint16_t newData)
-{
- NS_LOG_FUNCTION (this << oldData << newData);
-
- // Call the trace sink that actually does something.
- TraceSinkDouble (oldData, newData);
-}
-
-void
-TimeSeriesAdaptor::TraceSinkUinteger32 (uint32_t oldData, uint32_t newData)
-{
- NS_LOG_FUNCTION (this << oldData << newData);
-
- // Call the trace sink that actually does something.
- TraceSinkDouble (oldData, newData);
-}
-
-} // namespace ns3
-
Index: src/stats/model/time-series-adaptor.h
===================================================================
deleted file mode 100644
--- a/src/stats/model/time-series-adaptor.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013 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
- *
- * Author: Mitch Watrous (watrous@u.washington.edu)
- */
-
-#ifndef TIME_SERIES_ADAPTOR_H
-#define TIME_SERIES_ADAPTOR_H
-
-#include "ns3/data-collection-object.h"
-#include "ns3/object.h"
-#include "ns3/type-id.h"
-#include "ns3/traced-value.h"
-
-namespace ns3 {
-
-/**
- * \ingroup aggregator
- *
- * \brief Takes probed values of different types and outputs the
- * current time plus the value with both converted to doubles.
- *
- * The role of the TimeSeriesAdaptor class is that of an adaptor
- * class, to take raw-valued probe data of different types, and output
- * a tuple of two double values. The first is a timestamp which may
- * be set to different resolutions (e.g. Seconds, Milliseconds, etc.)
- * in the future, but which presently is hardcoded to Seconds. The second
- * is the conversion of
- * a non-double value to a double value (possibly with loss of precision).
- *
- * It should be noted that time series adaptors convert
- * Simulation Time objects to double values in its output.
- */
-class TimeSeriesAdaptor : public DataCollectionObject
-{
-public:
- /**
- * \brief Get the type ID.
- * \return the object TypeId
- */
- static TypeId GetTypeId (void);
-
- TimeSeriesAdaptor ();
- virtual ~TimeSeriesAdaptor ();
-
- /**
- * \brief Trace sink for receiving data from double valued trace
- * sources.
- * \param oldData the original value.
- * \param newData the new value.
- *
- * This method serves as a trace sink to double valued trace
- * sources.
- */
- void TraceSinkDouble (double oldData, double newData);
-
- /**
- * \brief Trace sink for receiving data from bool valued trace
- * sources.
- * \param oldData the original value.
- * \param newData the new value.
- *
- * This method serves as a trace sink to bool valued trace
- * sources.
- */
- void TraceSinkBoolean (bool oldData, bool newData);
-
- /**
- * \brief Trace sink for receiving data from uint8_t valued trace
- * sources.
- * \param oldData the original value.
- * \param newData the new value.
- *
- * This method serves as a trace sink to uint8_t valued trace
- * sources.
- */
- void TraceSinkUinteger8 (uint8_t oldData, uint8_t newData);
-
- /**
- * \brief Trace sink for receiving data from uint16_t valued trace
- * sources.
- * \param oldData the original value.
- * \param newData the new value.
- *
- * This method serves as a trace sink to uint16_t valued trace
- * sources.
- */
- void TraceSinkUinteger16 (uint16_t oldData, uint16_t newData);
-
- /**
- * \brief Trace sink for receiving data from uint32_t valued trace
- * sources.
- * \param oldData the original value.
- * \param newData the new value.
- *
- * This method serves as a trace sink to uint32_t valued trace
- * sources.
- */
- void TraceSinkUinteger32 (uint32_t oldData, uint32_t newData);
-
- /**
- * TracedCallback signature for output trace.
- *
- * \param [in] now The current Time.
- * \param [in] data The new data value.
- */
- typedef void (* OutputTracedCallback) (const double now, const double data);
-
-private:
- TracedCallback m_output; //!< output trace
-};
-
-} // namespace ns3
-
-#endif // TIME_SERIES_ADAPTOR_H
Index: src/stats/model/time-series-collector.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/model/time-series-collector.cc
@@ -0,0 +1,146 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#include "ns3/object.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/time-series-collector.h"
+
+NS_LOG_COMPONENT_DEFINE ("TimeSeriesCollector");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (TimeSeriesCollector);
+
+TypeId
+TimeSeriesCollector::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::TimeSeriesCollector")
+ .SetParent ()
+ .AddConstructor ()
+ .AddAttribute ("Period",
+ "The period in seconds between reports",
+ TimeValue (Seconds (1.0)),
+ MakeTimeAccessor (&TimeSeriesCollector::SetPeriod,
+ &TimeSeriesCollector::GetPeriod),
+ MakeTimeChecker ())
+ .AddTraceSource ("Output",
+ "The double value received by the trace sink",
+ MakeTraceSourceAccessor (&TimeSeriesCollector::m_output),
+ "ns3::DataCollectionObject::CollectorTraceCallback")
+ ;
+ return tid;
+}
+
+TimeSeriesCollector::TimeSeriesCollector ()
+ : Collector (),
+ m_hasReportBeenScheduled (false)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+TimeSeriesCollector::~TimeSeriesCollector ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+TimeSeriesCollector::ReportData (void)
+{
+ NS_LOG_FUNCTION (this);
+ if (!IsEnabled ())
+ {
+ return;
+ }
+ double time = Simulator::Now ().GetSeconds ();
+ // output the data downstream
+ m_output (time, m_doubleValue);
+
+ m_reportEventId = Simulator::Schedule (m_period, &TimeSeriesCollector::ReportData, this);
+ m_hasReportBeenScheduled = true;
+}
+
+void
+TimeSeriesCollector::TraceSinkDouble (double oldValue, double newValue)
+{
+ NS_LOG_FUNCTION (this << oldValue << newValue);
+ if (!IsEnabled ())
+ {
+ NS_LOG_DEBUG ("Collector not enabled");
+ return;
+ }
+
+ // keep track of the double value received
+ m_doubleValue = newValue;
+}
+
+void
+TimeSeriesCollector::SetPeriod (Time period)
+{
+ m_period = period;
+ PeriodChanged ();
+}
+
+Time
+TimeSeriesCollector::GetPeriod () const
+{
+ NS_LOG_FUNCTION (this);
+ return m_period;
+}
+
+void
+TimeSeriesCollector::PeriodChanged (void)
+{
+ NS_LOG_FUNCTION (this);
+ if (m_hasReportBeenScheduled)
+ {
+ Simulator::Cancel (m_reportEventId);
+ m_hasReportBeenScheduled = false;
+ NS_LOG_DEBUG ("TimeSeriesCollector " << this << " data report has been cancelled");
+ }
+
+ if (!IsEnabled ())
+ {
+ return;
+ }
+
+ m_reportEventId = Simulator::Schedule (m_period, &TimeSeriesCollector::ReportData, this);
+ m_hasReportBeenScheduled = true;
+ NS_LOG_DEBUG ("TimeSeriesCollector " << this << " data report has been scheduled");
+}
+
+// Override DataCollectionObject::Enable() to schedule the very first event
+// whenever the collector is enabled
+void
+TimeSeriesCollector::Enable (void)
+{
+ DataCollectionObject::Enable ();
+ if (m_hasReportBeenScheduled)
+ {
+ Simulator::Cancel (m_reportEventId);
+ m_hasReportBeenScheduled = false;
+ NS_LOG_DEBUG ("TimeSeriesCollector " << this << " data report has been cancelled");
+ }
+
+ m_reportEventId = Simulator::Schedule (m_period, &TimeSeriesCollector::ReportData, this);
+ m_hasReportBeenScheduled = true;
+}
+
+} // namespace ns3
Index: src/stats/model/time-series-collector.h
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/model/time-series-collector.h
@@ -0,0 +1,109 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#ifndef TIME_SERIES_COLLECTOR_H
+#define TIME_SERIES_COLLECTOR_H
+
+#include "ns3/object.h"
+#include "ns3/collector.h"
+#include "ns3/event-id.h"
+#include "ns3/type-id.h"
+#include "ns3/traced-value.h"
+#include "ns3/nstime.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup collectors
+ * \brief TimeSeriesCollector class used to collect a single trace of
+ * double value and output the data to downstream objects every certain
+ * amount of time
+ */
+class TimeSeriesCollector : public Collector
+{
+public:
+ /**
+ * \brief Get the type ID
+ * \return the object TypeId
+ */
+ static TypeId GetTypeId (void);
+
+ /**
+ * \brief Constructs a TimeSeriesCollector object
+ */
+ TimeSeriesCollector ();
+
+ virtual ~TimeSeriesCollector ();
+
+ /**
+ * \brief Collects the double values produced by the upstream probes
+ *
+ * \param oldValue previous value produced by a Probe
+ * \param newValue new value produced by a Probe
+ */
+ void TraceSinkDouble (double oldValue, double newValue);
+
+ /**
+ * \brief Sets the time period to report data. Cancels any pending
+ * report if one is scheduled.
+ *
+ * \param period a variable of type Time to indicate the period
+ */
+ void SetPeriod (Time period);
+
+ /**
+ * \brief Gets the time period to report data
+ *
+ * \return the time period to report data
+ */
+ Time GetPeriod () const;
+
+ /**
+ * \brief Override DataCollectionObject::Enable() to schedule the very
+ * first event whenever the collector is enabled. This method will
+ * also cancel any previously scheduled event if one exists.
+ *
+ * \sa ns3::DataCollectionObject::Enable
+ */
+ void Enable (void);
+private:
+ // the output data trace source
+ TracedCallback m_output;
+
+ /**
+ * \brief Reports data to downstream objects
+ */
+ void ReportData (void);
+
+ // a double value to keep track of the double value
+ // received by the trace sink
+ double m_doubleValue;
+
+ Time m_period;
+ EventId m_reportEventId;
+ bool m_hasReportBeenScheduled;
+ void PeriodChanged (void);
+
+};
+
+
+} // namespace ns3
+
+#endif // TIME_SERIES_COLLECTOR_H
Index: src/stats/test/event-driven-collector-test-suite.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/test/event-driven-collector-test-suite.cc
@@ -0,0 +1,170 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#include
+#include
+#include "ns3/event-driven-collector.h"
+#include "ns3/double-probe.h"
+#include "ns3/test.h"
+#include "ns3/core-module.h"
+
+using namespace ns3;
+
+class EventDrivenCollectorSampleEmitter : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ EventDrivenCollectorSampleEmitter ()
+ {
+ m_var = CreateObject ();
+ }
+ virtual ~EventDrivenCollectorSampleEmitter ()
+ {
+ }
+ void Start ()
+ {
+ Reschedule ();
+ }
+ void Reschedule ()
+ {
+ m_time = m_var->GetValue ();
+ Simulator::Schedule (Seconds (m_time), &EventDrivenCollectorSampleEmitter::Report, this);
+ m_time += Simulator::Now ().GetSeconds ();
+ }
+ double GetTime ()
+ {
+ return m_time;
+ }
+ double GetValue ()
+ {
+ return aux;
+ }
+private:
+ void Report ()
+ {
+ aux = m_var->GetValue ();
+ m_trace = aux;
+ Reschedule ();
+ }
+ Ptr m_var;
+ double m_time;
+ TracedValue m_trace;
+ double aux;
+};
+
+
+TypeId
+EventDrivenCollectorSampleEmitter::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("EventDrivenCollectorSampleEmitter")
+ .SetParent ()
+ .AddTraceSource ("Emitter", "XX", MakeTraceSourceAccessor (&EventDrivenCollectorSampleEmitter::m_trace), "ns3::TracedValue::DoubleCallback")
+ ;
+ return tid;
+}
+
+
+// ===========================================================================
+// Test case
+// ===========================================================================
+
+class EventDrivenCollectorTestCase1 : public TestCase
+{
+public:
+ EventDrivenCollectorTestCase1 ();
+ virtual ~EventDrivenCollectorTestCase1 ();
+
+private:
+ virtual void DoRun (void);
+ void TraceSinkCallback (std::string context, double oldValue, double newValue);
+ void ReceiveDouble (std::string context, double oldValue, double newValue);
+ double receivedDouble;
+ Ptr collector;
+ Ptr s;
+};
+
+EventDrivenCollectorTestCase1::EventDrivenCollectorTestCase1 ()
+ : TestCase ("EventDrivenCollector test case 1")
+{
+ collector = CreateObject ();
+ s = CreateObject ();
+}
+
+EventDrivenCollectorTestCase1::~EventDrivenCollectorTestCase1 ()
+{
+}
+
+void
+EventDrivenCollectorTestCase1::DoRun (void)
+{
+ Ptr p = CreateObject ();
+ p->SetName ("EventDrivenCollectorSampleProbe");
+
+ Simulator::Schedule (Seconds (1), &EventDrivenCollectorSampleEmitter::Start, s);
+ p->SetAttribute ("Start", TimeValue (Seconds (100.0)));
+ p->SetAttribute ("Stop", TimeValue (Seconds (200.0)));
+ Simulator::Stop (Seconds (300));
+
+ Names::Add ("/Names/EventDrivenCollectorSampleEmitter", s);
+
+ // Hook probe to the emitter.
+ p->ConnectByObject ("Emitter", s);
+
+ // update the variable that keeps track of the data received
+ bool connected = p->TraceConnect ("Output", p->GetName (), MakeCallback (&EventDrivenCollectorTestCase1::ReceiveDouble, this));
+ NS_UNUSED (connected);
+
+ // Hook the collector to the probe
+ connected = p->TraceConnectWithoutContext ("Output", MakeCallback (&EventDrivenCollector::TraceSinkDouble, collector));
+
+ // connect the collector to the TraceSinkCallback.
+ connected = collector->TraceConnect ("Output", p->GetName (), MakeCallback (&EventDrivenCollectorTestCase1::TraceSinkCallback, this));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
+
+void
+EventDrivenCollectorTestCase1::TraceSinkCallback (std::string context, double oldValue, double newValue)
+{
+ NS_TEST_ASSERT_MSG_EQ_TOL (receivedDouble, newValue, 0.0001, "Value generated by the collector different than the actual value");
+}
+
+void
+EventDrivenCollectorTestCase1::ReceiveDouble (std::string context, double oldValue, double newValue)
+{
+ receivedDouble = newValue;
+}
+
+
+class EventDrivenCollectorTestSuite : public TestSuite
+{
+public:
+ EventDrivenCollectorTestSuite ();
+};
+
+EventDrivenCollectorTestSuite::EventDrivenCollectorTestSuite ()
+ : TestSuite ("event-driven-collector", UNIT)
+{
+ AddTestCase (new EventDrivenCollectorTestCase1, TestCase::QUICK);
+}
+
+static EventDrivenCollectorTestSuite EventDrivenCollectorTestSuite;
+
Index: src/stats/test/examples-to-run.py
===================================================================
--- a/src/stats/test/examples-to-run.py
+++ b/src/stats/test/examples-to-run.py
@@ -9,11 +9,15 @@
# See test.py for more information.
cpp_examples = [
("double-probe-example", "True", "True"),
+ ("event-driven-collector-example", "True", "True"),
("file-aggregator-example", "True", "True"),
("file-helper-example", "True", "True"),
("gnuplot-aggregator-example", "True", "True"),
("gnuplot-example", "False", "False"),
("gnuplot-helper-example", "True", "True"),
+ ("scaling-collector-example", "True", "True"),
+ ("time-averaging-collector-example", "True", "True"),
+ ("time-series-collector-example", "True", "True"),
]
# A list of Python examples to run in order to ensure that they remain
Index: src/stats/test/scaling-collector-test-suite.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/test/scaling-collector-test-suite.cc
@@ -0,0 +1,172 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#include
+#include
+#include "ns3/scaling-collector.h"
+#include "ns3/double-probe.h"
+#include "ns3/test.h"
+#include "ns3/core-module.h"
+
+using namespace ns3;
+
+class ScalingCollectorSampleEmitter : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ ScalingCollectorSampleEmitter ()
+ {
+ m_var = CreateObject ();
+ }
+ virtual ~ScalingCollectorSampleEmitter ()
+ {
+ }
+ void Start ()
+ {
+ Reschedule ();
+ }
+ void Reschedule ()
+ {
+ m_time = m_var->GetValue ();
+ Simulator::Schedule (Seconds (m_time), &ScalingCollectorSampleEmitter::Report, this);
+ m_time += Simulator::Now ().GetSeconds ();
+ }
+ double GetTime ()
+ {
+ return m_time;
+ }
+ double GetValue ()
+ {
+ return aux;
+ }
+private:
+ void Report ()
+ {
+ aux = m_var->GetValue ();
+ m_trace = aux;
+ Reschedule ();
+ }
+ Ptr m_var;
+ double m_time;
+ TracedValue m_trace;
+ double aux;
+};
+
+
+TypeId
+ScalingCollectorSampleEmitter::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ScalingCollectorSampleEmitter")
+ .SetParent ()
+ .AddTraceSource ("Emitter", "XX", MakeTraceSourceAccessor (&ScalingCollectorSampleEmitter::m_trace), "ns3::TracedValue::DoubleCallback")
+ ;
+ return tid;
+}
+
+
+// ===========================================================================
+// Test case
+// ===========================================================================
+
+class ScalingCollectorTestCase1 : public TestCase
+{
+public:
+ ScalingCollectorTestCase1 ();
+ virtual ~ScalingCollectorTestCase1 ();
+
+private:
+ virtual void DoRun (void);
+ void TraceSinkCallback (std::string context, double oldValue, double newValue);
+ void ReceiveDouble (std::string context, double oldValue, double newValue);
+ double receivedDouble;
+ Ptr collector;
+ Ptr s;
+};
+
+ScalingCollectorTestCase1::ScalingCollectorTestCase1 ()
+ : TestCase ("ScalingCollector test case 1")
+{
+}
+
+ScalingCollectorTestCase1::~ScalingCollectorTestCase1 ()
+{
+}
+
+void
+ScalingCollectorTestCase1::DoRun (void)
+{
+ collector = CreateObject ();
+ collector->SetAttribute ("ScalingFactor", DoubleValue (100));
+ s = CreateObject ();
+
+ Ptr p = CreateObject ();
+ p->SetName ("ScalingCollectorSampleProbe");
+
+ Simulator::Schedule (Seconds (1), &ScalingCollectorSampleEmitter::Start, s);
+ p->SetAttribute ("Start", TimeValue (Seconds (100.0)));
+ p->SetAttribute ("Stop", TimeValue (Seconds (200.0)));
+ Simulator::Stop (Seconds (300));
+
+ Names::Add ("/Names/ScalingCollectorSampleEmitter", s);
+
+ // Hook probe to the emitter.
+ p->ConnectByObject ("Emitter", s);
+
+ // update the variable that keeps track of the data received
+ bool connected = p->TraceConnect ("Output", p->GetName (), MakeCallback (&ScalingCollectorTestCase1::ReceiveDouble, this));
+ NS_UNUSED (connected);
+
+ // Hook the collector to the probe
+ connected = p->TraceConnectWithoutContext ("Output", MakeCallback (&ScalingCollector::TraceSinkDouble, collector));
+
+ // connect the collector to the TraceSinkCallback.
+ connected = collector->TraceConnect ("Output", p->GetName (), MakeCallback (&ScalingCollectorTestCase1::TraceSinkCallback, this));
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
+
+void
+ScalingCollectorTestCase1::TraceSinkCallback (std::string context, double oldValue, double newValue)
+{
+ NS_TEST_ASSERT_MSG_EQ_TOL (receivedDouble * 100, newValue, 0.0001, "Value generated by the collector different than the actual value");
+}
+
+void
+ScalingCollectorTestCase1::ReceiveDouble (std::string context, double oldValue, double newValue)
+{
+ receivedDouble = newValue;
+}
+
+
+class ScalingCollectorTestSuite : public TestSuite
+{
+public:
+ ScalingCollectorTestSuite ();
+};
+
+ScalingCollectorTestSuite::ScalingCollectorTestSuite ()
+ : TestSuite ("scaling-collector", UNIT)
+{
+ AddTestCase (new ScalingCollectorTestCase1, TestCase::QUICK);
+}
+
+static ScalingCollectorTestSuite ScalingCollectorTestSuite;
+
Index: src/stats/test/time-averaging-collector-test-suite.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/test/time-averaging-collector-test-suite.cc
@@ -0,0 +1,188 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#include
+#include
+#include "ns3/time-averaging-collector.h"
+#include "ns3/double-probe.h"
+#include "ns3/test.h"
+#include "ns3/core-module.h"
+
+using namespace ns3;
+
+class TimeAveragingCollectorSampleEmitter : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ TimeAveragingCollectorSampleEmitter ()
+ {
+ m_var = CreateObject ();
+ }
+ virtual ~TimeAveragingCollectorSampleEmitter ()
+ {
+ }
+ void Start ()
+ {
+ Reschedule ();
+ }
+ void Reschedule ()
+ {
+ m_time = m_var->GetValue ();
+ Simulator::Schedule (Seconds (m_time), &TimeAveragingCollectorSampleEmitter::Report, this);
+ m_time += Simulator::Now ().GetSeconds ();
+ }
+ double GetTime ()
+ {
+ return m_time;
+ }
+ double GetValue ()
+ {
+ return aux;
+ }
+private:
+ void Report ()
+ {
+ aux = m_var->GetValue ();
+ m_trace = aux;
+ Reschedule ();
+ }
+ Ptr m_var;
+ double m_time;
+ TracedValue m_trace;
+ double aux;
+};
+
+
+TypeId
+TimeAveragingCollectorSampleEmitter::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("TimeAveragingCollectorSampleEmitter")
+ .SetParent ()
+ .AddTraceSource ("Emitter", "XX", MakeTraceSourceAccessor (&TimeAveragingCollectorSampleEmitter::m_trace), "ns3::TracedValue::DoubleCallback")
+ ;
+ return tid;
+}
+
+
+// ===========================================================================
+// Test case
+// ===========================================================================
+
+class TimeAveragingCollectorTestCase1 : public TestCase
+{
+public:
+ TimeAveragingCollectorTestCase1 ();
+ virtual ~TimeAveragingCollectorTestCase1 ();
+
+private:
+ double currentTime;
+ double average;
+ double batchCount;
+ virtual void DoRun (void);
+ void TraceSinkCallback (std::string context, double oldValue, double newValue);
+ void ProbeTraceSinkCallback (double time, double newValue);
+ Ptr collector;
+ Ptr s;
+};
+
+TimeAveragingCollectorTestCase1::TimeAveragingCollectorTestCase1 ()
+ : TestCase ("TimeAveragingCollector test case 1")
+{
+}
+
+TimeAveragingCollectorTestCase1::~TimeAveragingCollectorTestCase1 ()
+{
+}
+
+void
+TimeAveragingCollectorTestCase1::DoRun (void)
+{
+ // let the collector generate outputs every 1 second
+ collector = CreateObject ();
+ collector->SetPeriod (Seconds (3));
+ collector->Enable ();
+ s = CreateObject ();
+ currentTime = 3;
+ average = 0;
+ batchCount = 0;
+
+ Ptr p = CreateObject ();
+ p->SetName ("TimeAveragingCollectorSampleProbe");
+
+ Simulator::Schedule (Seconds (0), &TimeAveragingCollectorSampleEmitter::Start, s);
+ p->SetAttribute ("Start", TimeValue (Seconds (0.0)));
+ p->SetAttribute ("Stop", TimeValue (Seconds (100.0)));
+ Simulator::Stop (Seconds (200));
+
+ Names::Add ("/Names/TimeAveragingCollectorSampleEmitter", s);
+
+ // Hook probe to the emitter.
+ p->ConnectByObject ("Emitter", s);
+
+ // Hook the collector to the probe
+ bool connected = p->TraceConnectWithoutContext ("Output", MakeCallback (&TimeAveragingCollector::TraceSinkDouble, collector));
+ NS_ASSERT (connected == true);
+
+ // Connect the probe to the test trace sink defined in this class
+ connected = p->TraceConnectWithoutContext ("Output", MakeCallback (&TimeAveragingCollectorTestCase1::ProbeTraceSinkCallback, this));
+ NS_ASSERT (connected == true);
+
+ // connect the collector to the TraceSinkCallback.
+ connected = collector->TraceConnect ("Output", p->GetName (), MakeCallback (&TimeAveragingCollectorTestCase1::TraceSinkCallback, this));
+ NS_ASSERT (connected == true);
+ NS_UNUSED (connected);
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
+
+void
+TimeAveragingCollectorTestCase1::TraceSinkCallback (std::string context, double time, double newValue)
+{
+ // check whether the collector is generating outputs every 3 second.
+ NS_TEST_ASSERT_MSG_EQ_TOL (currentTime, time, 0.0001, "Time generated by the collector different than the actual time");
+
+ // check whether the average value generated by the collector is correct
+ NS_TEST_ASSERT_MSG_EQ_TOL (average, newValue, 0.0001, "Average generated by the collector different than the actual average");
+ batchCount = 0;
+ currentTime += 3;
+}
+
+void
+TimeAveragingCollectorTestCase1::ProbeTraceSinkCallback (double time, double newValue)
+{
+ average = (average * batchCount + newValue) / (batchCount + 1);
+ batchCount++;
+}
+
+class TimeAveragingCollectorTestSuite : public TestSuite
+{
+public:
+ TimeAveragingCollectorTestSuite ();
+};
+
+TimeAveragingCollectorTestSuite::TimeAveragingCollectorTestSuite ()
+ : TestSuite ("time-averaging-collector", UNIT)
+{
+ AddTestCase (new TimeAveragingCollectorTestCase1, TestCase::QUICK);
+}
+
+static TimeAveragingCollectorTestSuite TimeAveragingCollectorTestSuite;
+
Index: src/stats/test/time-series-collector-test-suite.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/stats/test/time-series-collector-test-suite.cc
@@ -0,0 +1,168 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2015 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
+ *
+ * Author: Li Li (ll024@bucknell.edu)
+ */
+
+#include
+#include
+#include "ns3/time-series-collector.h"
+#include "ns3/double-probe.h"
+#include "ns3/test.h"
+#include "ns3/core-module.h"
+
+using namespace ns3;
+
+class TimeSeriesCollectorSampleEmitter : public Object
+{
+public:
+ static TypeId GetTypeId (void);
+ TimeSeriesCollectorSampleEmitter ()
+ {
+ m_var = CreateObject ();
+ }
+ virtual ~TimeSeriesCollectorSampleEmitter ()
+ {
+ }
+ void Start ()
+ {
+ Reschedule ();
+ }
+ void Reschedule ()
+ {
+ m_time = m_var->GetValue ();
+ Simulator::Schedule (Seconds (m_time), &TimeSeriesCollectorSampleEmitter::Report, this);
+ m_time += Simulator::Now ().GetSeconds ();
+ }
+ double GetTime ()
+ {
+ return m_time;
+ }
+ double GetValue ()
+ {
+ return aux;
+ }
+private:
+ void Report ()
+ {
+ aux = m_var->GetValue ();
+ m_trace = aux;
+ Reschedule ();
+ }
+ Ptr m_var;
+ double m_time;
+ TracedValue m_trace;
+ double aux;
+};
+
+
+TypeId
+TimeSeriesCollectorSampleEmitter::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("TimeSeriesCollectorSampleEmitter")
+ .SetParent ()
+ .AddTraceSource ("Emitter", "XX", MakeTraceSourceAccessor (&TimeSeriesCollectorSampleEmitter::m_trace), "ns3::TracedValue::DoubleCallback")
+ ;
+ return tid;
+}
+
+
+// ===========================================================================
+// Test case
+// ===========================================================================
+
+class TimeSeriesCollectorTestCase1 : public TestCase
+{
+public:
+ TimeSeriesCollectorTestCase1 ();
+ virtual ~TimeSeriesCollectorTestCase1 ();
+
+private:
+ double currentTime;
+ virtual void DoRun (void);
+ void TraceSinkCallback (std::string context, double oldValue, double newValue);
+ Ptr collector;
+ Ptr s;
+};
+
+TimeSeriesCollectorTestCase1::TimeSeriesCollectorTestCase1 ()
+ : TestCase ("TimeSeriesCollector test case 1")
+{
+}
+
+TimeSeriesCollectorTestCase1::~TimeSeriesCollectorTestCase1 ()
+{
+}
+
+void
+TimeSeriesCollectorTestCase1::DoRun (void)
+{
+ // let the collector generate outputs every 1 second
+ collector = CreateObject ();
+ collector->SetPeriod (Seconds (1));
+ collector->Enable ();
+ s = CreateObject ();
+ currentTime = 1;
+
+ Ptr p = CreateObject ();
+ p->SetName ("TimeSeriesCollectorSampleProbe");
+
+ Simulator::Schedule (Seconds (0), &TimeSeriesCollectorSampleEmitter::Start, s);
+ p->SetAttribute ("Start", TimeValue (Seconds (0.0)));
+ p->SetAttribute ("Stop", TimeValue (Seconds (100.0)));
+ Simulator::Stop (Seconds (200));
+
+ Names::Add ("/Names/TimeSeriesCollectorSampleEmitter", s);
+
+ // Hook probe to the emitter.
+ p->ConnectByObject ("Emitter", s);
+
+ // Hook the collector to the probe
+ bool connected = p->TraceConnectWithoutContext ("Output", MakeCallback (&TimeSeriesCollector::TraceSinkDouble, collector));
+ NS_ASSERT (connected == true);
+
+ // connect the collector to the TraceSinkCallback.
+ connected = collector->TraceConnect ("Output", p->GetName (), MakeCallback (&TimeSeriesCollectorTestCase1::TraceSinkCallback, this));
+ NS_ASSERT (connected == true);
+ NS_UNUSED (connected);
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
+
+void
+TimeSeriesCollectorTestCase1::TraceSinkCallback (std::string context, double time, double newValue)
+{
+ // check whether the collector is generating outputs every 1 second.
+ NS_TEST_ASSERT_MSG_EQ_TOL (currentTime, time, 0.0001, "Value generated by the collector different than the actual value");
+ currentTime += 1;
+}
+
+class TimeSeriesCollectorTestSuite : public TestSuite
+{
+public:
+ TimeSeriesCollectorTestSuite ();
+};
+
+TimeSeriesCollectorTestSuite::TimeSeriesCollectorTestSuite ()
+ : TestSuite ("time-series-collector", UNIT)
+{
+ AddTestCase (new TimeSeriesCollectorTestCase1, TestCase::QUICK);
+}
+
+static TimeSeriesCollectorTestSuite TimeSeriesCollectorTestSuite;
+
Index: src/stats/wscript
===================================================================
--- a/src/stats/wscript
+++ b/src/stats/wscript
@@ -29,10 +29,14 @@
'model/uinteger-8-probe.cc',
'model/uinteger-16-probe.cc',
'model/uinteger-32-probe.cc',
- 'model/time-series-adaptor.cc',
'model/file-aggregator.cc',
'model/gnuplot-aggregator.cc',
- 'model/get-wildcard-matches.cc',
+ 'model/get-wildcard-matches.cc',
+ 'model/collector.cc',
+ 'model/event-driven-collector.cc',
+ 'model/scaling-collector.cc',
+ 'model/time-series-collector.cc',
+ 'model/time-averaging-collector.cc',
]
module_test = bld.create_ns3_module_test_library('stats')
@@ -40,6 +44,10 @@
'test/basic-data-calculators-test-suite.cc',
'test/average-test-suite.cc',
'test/double-probe-test-suite.cc',
+ 'test/event-driven-collector-test-suite.cc',
+ 'test/scaling-collector-test-suite.cc',
+ 'test/time-series-collector-test-suite.cc',
+ 'test/time-averaging-collector-test-suite.cc',
]
headers = bld(features='ns3header')
@@ -63,10 +71,14 @@
'model/uinteger-8-probe.h',
'model/uinteger-16-probe.h',
'model/uinteger-32-probe.h',
- 'model/time-series-adaptor.h',
'model/file-aggregator.h',
'model/gnuplot-aggregator.h',
'model/get-wildcard-matches.h',
+ 'model/collector.h',
+ 'model/event-driven-collector.h',
+ 'model/scaling-collector.h',
+ 'model/time-series-collector.h',
+ 'model/time-averaging-collector.h',
]
if bld.env['SQLITE_STATS']: