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 <iostream> |
@@ -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<GnuplotAggregator> 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> collector = DynamicCast<Collector> (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> timeSeriesAdaptor = CreateObject<TimeSeriesAdaptor> (); |
- |
- // 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. |
buherman
2015/06/29 08:53:53
A little bit too much indenting.
|
+ m_collectorMap[collectorName] = collector; |
} |
Ptr<Probe> |
@@ -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<GnuplotAggregator> 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> scalingCollector = CreateObject<ScalingCollector> (); |
+ |
+ // 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; |
+} |
buherman
2015/06/29 08:53:53
Several lines above this are indented too long.
|
+ |
+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 |
buherman
2015/06/29 08:53:53
IMO, one of the use cases of ScalingCollector is t
|
+ 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)); |
+ } |
buherman
2015/06/29 08:53:53
The position of curly braces in the above block is
|
} |
} // namespace ns3 |