data collection extensions for stats module
This commit is contained in:
@@ -36,6 +36,10 @@ massif.*
|
||||
\.patch$
|
||||
\.diff$
|
||||
\.tr$
|
||||
\.txt$
|
||||
\.sh$
|
||||
\.dat$
|
||||
\.plt$
|
||||
\#[^\#/]+\#$
|
||||
^coverity
|
||||
syntax: glob
|
||||
|
||||
@@ -15,6 +15,7 @@ cpp_examples = [
|
||||
("fourth", "True", "True"),
|
||||
("fifth", "True", "True"),
|
||||
("sixth", "True", "True"),
|
||||
("seventh", "True", "True"),
|
||||
]
|
||||
|
||||
# A list of Python examples to run in order to ensure that they remain
|
||||
|
||||
267
examples/tutorial/seventh.cc
Normal file
267
examples/tutorial/seventh.cc
Normal file
@@ -0,0 +1,267 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <fstream>
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/network-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/point-to-point-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/stats-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SeventhScriptExample");
|
||||
|
||||
// ===========================================================================
|
||||
//
|
||||
// node 0 node 1
|
||||
// +----------------+ +----------------+
|
||||
// | ns-3 TCP | | ns-3 TCP |
|
||||
// +----------------+ +----------------+
|
||||
// | 10.1.1.1 | | 10.1.1.2 |
|
||||
// +----------------+ +----------------+
|
||||
// | point-to-point | | point-to-point |
|
||||
// +----------------+ +----------------+
|
||||
// | |
|
||||
// +---------------------+
|
||||
// 5 Mbps, 2 ms
|
||||
//
|
||||
//
|
||||
// We want to look at changes in the ns-3 TCP congestion window. We need
|
||||
// to crank up a flow and hook the CongestionWindow attribute on the socket
|
||||
// of the sender. Normally one would use an on-off application to generate a
|
||||
// flow, but this has a couple of problems. First, the socket of the on-off
|
||||
// application is not created until Application Start time, so we wouldn't be
|
||||
// able to hook the socket (now) at configuration time. Second, even if we
|
||||
// could arrange a call after start time, the socket is not public so we
|
||||
// couldn't get at it.
|
||||
//
|
||||
// So, we can cook up a simple version of the on-off application that does what
|
||||
// we want. On the plus side we don't need all of the complexity of the on-off
|
||||
// application. On the minus side, we don't have a helper, so we have to get
|
||||
// a little more involved in the details, but this is trivial.
|
||||
//
|
||||
// So first, we create a socket and do the trace connect on it; then we pass
|
||||
// this socket into the constructor of our simple application which we then
|
||||
// install in the source node.
|
||||
// ===========================================================================
|
||||
//
|
||||
class MyApp : public Application
|
||||
{
|
||||
public:
|
||||
MyApp ();
|
||||
virtual ~MyApp ();
|
||||
|
||||
void Setup (Ptr<Socket> socket, Address address, uint32_t packetSize, uint32_t nPackets, DataRate dataRate);
|
||||
|
||||
private:
|
||||
virtual void StartApplication (void);
|
||||
virtual void StopApplication (void);
|
||||
|
||||
void ScheduleTx (void);
|
||||
void SendPacket (void);
|
||||
|
||||
Ptr<Socket> m_socket;
|
||||
Address m_peer;
|
||||
uint32_t m_packetSize;
|
||||
uint32_t m_nPackets;
|
||||
DataRate m_dataRate;
|
||||
EventId m_sendEvent;
|
||||
bool m_running;
|
||||
uint32_t m_packetsSent;
|
||||
};
|
||||
|
||||
MyApp::MyApp ()
|
||||
: m_socket (0),
|
||||
m_peer (),
|
||||
m_packetSize (0),
|
||||
m_nPackets (0),
|
||||
m_dataRate (0),
|
||||
m_sendEvent (),
|
||||
m_running (false),
|
||||
m_packetsSent (0)
|
||||
{
|
||||
}
|
||||
|
||||
MyApp::~MyApp ()
|
||||
{
|
||||
m_socket = 0;
|
||||
}
|
||||
|
||||
void
|
||||
MyApp::Setup (Ptr<Socket> socket, Address address, uint32_t packetSize, uint32_t nPackets, DataRate dataRate)
|
||||
{
|
||||
m_socket = socket;
|
||||
m_peer = address;
|
||||
m_packetSize = packetSize;
|
||||
m_nPackets = nPackets;
|
||||
m_dataRate = dataRate;
|
||||
}
|
||||
|
||||
void
|
||||
MyApp::StartApplication (void)
|
||||
{
|
||||
m_running = true;
|
||||
m_packetsSent = 0;
|
||||
m_socket->Bind ();
|
||||
m_socket->Connect (m_peer);
|
||||
SendPacket ();
|
||||
}
|
||||
|
||||
void
|
||||
MyApp::StopApplication (void)
|
||||
{
|
||||
m_running = false;
|
||||
|
||||
if (m_sendEvent.IsRunning ())
|
||||
{
|
||||
Simulator::Cancel (m_sendEvent);
|
||||
}
|
||||
|
||||
if (m_socket)
|
||||
{
|
||||
m_socket->Close ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MyApp::SendPacket (void)
|
||||
{
|
||||
Ptr<Packet> packet = Create<Packet> (m_packetSize);
|
||||
m_socket->Send (packet);
|
||||
|
||||
if (++m_packetsSent < m_nPackets)
|
||||
{
|
||||
ScheduleTx ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MyApp::ScheduleTx (void)
|
||||
{
|
||||
if (m_running)
|
||||
{
|
||||
Time tNext (Seconds (m_packetSize * 8 / static_cast<double> (m_dataRate.GetBitRate ())));
|
||||
m_sendEvent = Simulator::Schedule (tNext, &MyApp::SendPacket, this);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CwndChange (Ptr<OutputStreamWrapper> stream, uint32_t oldCwnd, uint32_t newCwnd)
|
||||
{
|
||||
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << newCwnd);
|
||||
*stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
|
||||
}
|
||||
|
||||
static void
|
||||
RxDrop (Ptr<PcapFileWrapper> file, Ptr<const Packet> p)
|
||||
{
|
||||
NS_LOG_UNCOND ("RxDrop at " << Simulator::Now ().GetSeconds ());
|
||||
file->Write (Simulator::Now (), p);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
NodeContainer nodes;
|
||||
nodes.Create (2);
|
||||
|
||||
PointToPointHelper pointToPoint;
|
||||
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
|
||||
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
|
||||
|
||||
NetDeviceContainer devices;
|
||||
devices = pointToPoint.Install (nodes);
|
||||
|
||||
Ptr<RateErrorModel> em = CreateObject<RateErrorModel> ();
|
||||
em->SetAttribute ("ErrorRate", DoubleValue (0.00001));
|
||||
devices.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (em));
|
||||
|
||||
InternetStackHelper stack;
|
||||
stack.Install (nodes);
|
||||
|
||||
Ipv4AddressHelper address;
|
||||
address.SetBase ("10.1.1.0", "255.255.255.252");
|
||||
Ipv4InterfaceContainer interfaces = address.Assign (devices);
|
||||
|
||||
uint16_t sinkPort = 8080;
|
||||
Address sinkAddress (InetSocketAddress (interfaces.GetAddress (1), sinkPort));
|
||||
PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
|
||||
ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (1));
|
||||
sinkApps.Start (Seconds (0.));
|
||||
sinkApps.Stop (Seconds (20.));
|
||||
|
||||
Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0), TcpSocketFactory::GetTypeId ());
|
||||
|
||||
Ptr<MyApp> app = CreateObject<MyApp> ();
|
||||
app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps"));
|
||||
nodes.Get (0)->AddApplication (app);
|
||||
app->SetStartTime (Seconds (1.));
|
||||
app->SetStopTime (Seconds (20.));
|
||||
|
||||
AsciiTraceHelper asciiTraceHelper;
|
||||
Ptr<OutputStreamWrapper> stream = asciiTraceHelper.CreateFileStream ("seventh.cwnd");
|
||||
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (&CwndChange, stream));
|
||||
|
||||
PcapHelper pcapHelper;
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("seventh.pcap", std::ios::out, PcapHelper::DLT_PPP);
|
||||
devices.Get (1)->TraceConnectWithoutContext ("PhyRxDrop", MakeBoundCallback (&RxDrop, file));
|
||||
|
||||
// Use GnuplotHelper to plot the packet byte count over time
|
||||
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, probe 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 ("ns3::Ipv4PacketProbe",
|
||||
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
|
||||
"OutputBytes",
|
||||
"Packet Byte Count",
|
||||
GnuplotAggregator::KEY_BELOW);
|
||||
|
||||
// Use FileHelper to write out the packet byte count over time
|
||||
FileHelper fileHelper;
|
||||
|
||||
// Configure the file to be written, and the formatting of output data.
|
||||
fileHelper.ConfigureFile ("seventh-packet-byte-count",
|
||||
FileAggregator::FORMATTED);
|
||||
|
||||
// Set the labels for this formatted output file.
|
||||
fileHelper.Set2dFormat ("Time (Seconds) = %.3e\tPacket Byte Count = %.0f");
|
||||
|
||||
// Specify the probe type, probe path (in configuration namespace), and
|
||||
// probe output trace source ("OutputBytes") to write.
|
||||
fileHelper.WriteProbe ("ns3::Ipv4PacketProbe",
|
||||
"/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
|
||||
"OutputBytes");
|
||||
|
||||
Simulator::Stop (Seconds (20));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,3 +23,6 @@ def build(bld):
|
||||
|
||||
obj = bld.create_ns3_program('sixth', ['core', 'point-to-point', 'internet', 'applications'])
|
||||
obj.source = 'sixth.cc'
|
||||
|
||||
obj = bld.create_ns3_program('seventh', ['core', 'stats', 'point-to-point', 'internet', 'applications'])
|
||||
obj.source = 'seventh.cc'
|
||||
|
||||
119
src/applications/model/application-packet-probe.cc
Normal file
119
src/applications/model/application-packet-probe.cc
Normal file
@@ -0,0 +1,119 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#include "ns3/application-packet-probe.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ApplicationPacketProbe");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (ApplicationPacketProbe);
|
||||
|
||||
TypeId
|
||||
ApplicationPacketProbe::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::ApplicationPacketProbe")
|
||||
.SetParent<Probe> ()
|
||||
.AddConstructor<ApplicationPacketProbe> ()
|
||||
.AddTraceSource ( "Output",
|
||||
"The packet plus its socket address that serve as the output for this probe",
|
||||
MakeTraceSourceAccessor (&ApplicationPacketProbe::m_output))
|
||||
.AddTraceSource ( "OutputBytes",
|
||||
"The number of bytes in the packet",
|
||||
MakeTraceSourceAccessor (&ApplicationPacketProbe::m_outputBytes))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
ApplicationPacketProbe::ApplicationPacketProbe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_packet = 0;
|
||||
}
|
||||
|
||||
ApplicationPacketProbe::~ApplicationPacketProbe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
void
|
||||
ApplicationPacketProbe::SetValue (Ptr<const Packet> packet, const Address& address)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << address);
|
||||
m_packet = packet;
|
||||
m_address = address;
|
||||
m_output (packet, address);
|
||||
|
||||
uint32_t packetSizeNew = packet->GetSize ();
|
||||
m_outputBytes (m_packetSizeOld, packetSizeNew);
|
||||
m_packetSizeOld = packetSizeNew;
|
||||
}
|
||||
|
||||
void
|
||||
ApplicationPacketProbe::SetValueByPath (std::string path, Ptr<const Packet> packet, const Address& address)
|
||||
{
|
||||
NS_LOG_FUNCTION (path << packet << address);
|
||||
Ptr<ApplicationPacketProbe> probe = Names::Find<ApplicationPacketProbe> (path);
|
||||
NS_ASSERT_MSG (probe, "Error: Can't find probe for path " << path);
|
||||
probe->SetValue (packet, address);
|
||||
}
|
||||
|
||||
bool
|
||||
ApplicationPacketProbe::ConnectByObject (std::string traceSource, Ptr<Object> obj)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << traceSource << obj);
|
||||
NS_LOG_DEBUG ("Name of probe (if any) in names database: " << Names::FindPath (obj));
|
||||
bool connected = obj->TraceConnectWithoutContext (traceSource, MakeCallback (&ns3::ApplicationPacketProbe::TraceSink, this));
|
||||
return connected;
|
||||
}
|
||||
|
||||
void
|
||||
ApplicationPacketProbe::ConnectByPath (std::string path)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << path);
|
||||
NS_LOG_DEBUG ("Name of probe to search for in config database: " << path);
|
||||
Config::ConnectWithoutContext (path, MakeCallback (&ns3::ApplicationPacketProbe::TraceSink, this));
|
||||
}
|
||||
|
||||
void
|
||||
ApplicationPacketProbe::TraceSink (Ptr<const Packet> packet, const Address& address)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << address);
|
||||
if (IsEnabled ())
|
||||
{
|
||||
m_packet = packet;
|
||||
m_address = address;
|
||||
m_output (packet, address);
|
||||
|
||||
uint32_t packetSizeNew = packet->GetSize ();
|
||||
m_outputBytes (m_packetSizeOld, packetSizeNew);
|
||||
m_packetSizeOld = packetSizeNew;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
120
src/applications/model/application-packet-probe.h
Normal file
120
src/applications/model/application-packet-probe.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#ifndef APPLICATION_PACKET_PROBE_H
|
||||
#define APPLICATION_PACKET_PROBE_H
|
||||
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/application.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/probe.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This class is designed to probe an underlying ns3 TraceSource
|
||||
* exporting a packet and a socket address. This probe exports a
|
||||
* trace source "Output" with arguments of type Ptr<const Packet> and
|
||||
* const Address&. This probe exports another trace source
|
||||
* "OutputBytes" with arguments of type uint32_t, which is the number
|
||||
* of bytes in the packet. The trace sources emit values when either
|
||||
* the probed trace source emits a new value, or when SetValue () is
|
||||
* called.
|
||||
*/
|
||||
class ApplicationPacketProbe : public Probe
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId ();
|
||||
ApplicationPacketProbe ();
|
||||
virtual ~ApplicationPacketProbe ();
|
||||
|
||||
/**
|
||||
* \brief Set a probe value
|
||||
*
|
||||
* \param packet set the traced packet equal to this
|
||||
* \param address set the socket address for the traced packet equal to this
|
||||
*/
|
||||
void SetValue (Ptr<const Packet> packet, const Address& address);
|
||||
|
||||
/**
|
||||
* \brief Set a probe value by its name in the Config system
|
||||
*
|
||||
* \param path config path to access the probe
|
||||
* \param packet set the traced packet equal to this
|
||||
* \param address set the socket address for the traced packet equal to this
|
||||
*/
|
||||
static void SetValueByPath (std::string path, Ptr<const Packet> packet, const Address& address);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source attribute provided by a given object
|
||||
*
|
||||
* \param traceSource the name of the attribute TraceSource to connect to
|
||||
* \param obj ns3::Object to connect to
|
||||
* \return true if the trace source was successfully connected
|
||||
*/
|
||||
virtual bool ConnectByObject (std::string traceSource, Ptr<Object> obj);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source provided by a config path
|
||||
*
|
||||
* \param path Config path to bind to
|
||||
*
|
||||
* Note, if an invalid path is provided, the probe will not be connected
|
||||
* to anything.
|
||||
*/
|
||||
virtual void ConnectByPath (std::string path);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Method to connect to an underlying ns3::TraceSource with
|
||||
* arguments of type Ptr<const Packet> and const Address&
|
||||
*
|
||||
* \param packet the traced packet
|
||||
* \param address the socket address for the traced packet
|
||||
*
|
||||
* \internal
|
||||
*/
|
||||
void TraceSink (Ptr<const Packet> packet, const Address& address);
|
||||
|
||||
TracedCallback<Ptr<const Packet>, const Address&> m_output;
|
||||
TracedCallback<uint32_t, uint32_t> m_outputBytes;
|
||||
|
||||
/// The traced packet.
|
||||
Ptr<const Packet> m_packet;
|
||||
|
||||
/// The socket address for the traced packet.
|
||||
Address m_address;
|
||||
|
||||
/// The size of the traced packet.
|
||||
uint32_t m_packetSizeOld;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // APPLICATION_PACKET_PROBE_H
|
||||
@@ -18,6 +18,7 @@ def build(bld):
|
||||
'model/udp-echo-client.cc',
|
||||
'model/udp-echo-server.cc',
|
||||
'model/v4ping.cc',
|
||||
'model/application-packet-probe.cc',
|
||||
'helper/bulk-send-helper.cc',
|
||||
'helper/on-off-helper.cc',
|
||||
'helper/packet-sink-helper.cc',
|
||||
@@ -50,6 +51,7 @@ def build(bld):
|
||||
'model/udp-echo-client.h',
|
||||
'model/udp-echo-server.h',
|
||||
'model/v4ping.h',
|
||||
'model/application-packet-probe.h',
|
||||
'helper/bulk-send-helper.h',
|
||||
'helper/on-off-helper.h',
|
||||
'helper/packet-sink-helper.h',
|
||||
|
||||
123
src/internet/model/ipv4-packet-probe.cc
Normal file
123
src/internet/model/ipv4-packet-probe.cc
Normal file
@@ -0,0 +1,123 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#include "ns3/ipv4-packet-probe.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Ipv4PacketProbe");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (Ipv4PacketProbe);
|
||||
|
||||
TypeId
|
||||
Ipv4PacketProbe::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::Ipv4PacketProbe")
|
||||
.SetParent<Probe> ()
|
||||
.AddConstructor<Ipv4PacketProbe> ()
|
||||
.AddTraceSource ( "Output",
|
||||
"The packet plus its IPv4 object and interface that serve as the output for this probe",
|
||||
MakeTraceSourceAccessor (&Ipv4PacketProbe::m_output))
|
||||
.AddTraceSource ( "OutputBytes",
|
||||
"The number of bytes in the packet",
|
||||
MakeTraceSourceAccessor (&Ipv4PacketProbe::m_outputBytes))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
Ipv4PacketProbe::Ipv4PacketProbe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_packet = 0;
|
||||
m_ipv4 = 0;
|
||||
m_interface = 0;
|
||||
}
|
||||
|
||||
Ipv4PacketProbe::~Ipv4PacketProbe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4PacketProbe::SetValue (Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << ipv4 << interface);
|
||||
m_packet = packet;
|
||||
m_ipv4 = ipv4;
|
||||
m_interface = interface;
|
||||
m_output (packet, ipv4, interface);
|
||||
|
||||
uint32_t packetSizeNew = packet->GetSize ();
|
||||
m_outputBytes (m_packetSizeOld, packetSizeNew);
|
||||
m_packetSizeOld = packetSizeNew;
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4PacketProbe::SetValueByPath (std::string path, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface)
|
||||
{
|
||||
NS_LOG_FUNCTION (path << packet << ipv4 << interface);
|
||||
Ptr<Ipv4PacketProbe> probe = Names::Find<Ipv4PacketProbe> (path);
|
||||
NS_ASSERT_MSG (probe, "Error: Can't find probe for path " << path);
|
||||
probe->SetValue (packet, ipv4, interface);
|
||||
}
|
||||
|
||||
bool
|
||||
Ipv4PacketProbe::ConnectByObject (std::string traceSource, Ptr<Object> obj)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << traceSource << obj);
|
||||
NS_LOG_DEBUG ("Name of probe (if any) in names database: " << Names::FindPath (obj));
|
||||
bool connected = obj->TraceConnectWithoutContext (traceSource, MakeCallback (&ns3::Ipv4PacketProbe::TraceSink, this));
|
||||
return connected;
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4PacketProbe::ConnectByPath (std::string path)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << path);
|
||||
NS_LOG_DEBUG ("Name of probe to search for in config database: " << path);
|
||||
Config::ConnectWithoutContext (path, MakeCallback (&ns3::Ipv4PacketProbe::TraceSink, this));
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4PacketProbe::TraceSink (Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet << ipv4 << interface);
|
||||
if (IsEnabled ())
|
||||
{
|
||||
m_packet = packet;
|
||||
m_ipv4 = ipv4;
|
||||
m_interface = interface;
|
||||
m_output (packet, ipv4, interface);
|
||||
|
||||
uint32_t packetSizeNew = packet->GetSize ();
|
||||
m_outputBytes (m_packetSizeOld, packetSizeNew);
|
||||
m_packetSizeOld = packetSizeNew;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
124
src/internet/model/ipv4-packet-probe.h
Normal file
124
src/internet/model/ipv4-packet-probe.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#ifndef IPV4_PACKET_PROBE_H
|
||||
#define IPV4_PACKET_PROBE_H
|
||||
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/probe.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This class is designed to probe an underlying ns3 TraceSource
|
||||
* exporting a packet, an IPv4 object, and an interface. This probe
|
||||
* exports a trace source "Output" with arguments of type Ptr<const Packet>,
|
||||
* Ptr<Ipv4>, and uint32_t. The Output trace source emits a value
|
||||
* when either the trace source emits a new value, or when SetValue ()
|
||||
* is called.
|
||||
*/
|
||||
class Ipv4PacketProbe : public Probe
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId ();
|
||||
Ipv4PacketProbe ();
|
||||
virtual ~Ipv4PacketProbe ();
|
||||
|
||||
/**
|
||||
* \brief Set a probe value
|
||||
*
|
||||
* \param packet set the traced packet equal to this
|
||||
* \param ipv4 set the IPv4 object for the traced packet equal to this
|
||||
* \param interface set the IPv4 interface for the traced packet equal to this
|
||||
*/
|
||||
void SetValue (Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface);
|
||||
|
||||
/**
|
||||
* \brief Set a probe value by its name in the Config system
|
||||
*
|
||||
* \param path config path to access the probe
|
||||
* \param packet set the traced packet equal to this
|
||||
* \param ipv4 set the IPv4 object for the traced packet equal to this
|
||||
* \param interface set the IPv4 interface for the traced packet equal to this
|
||||
*/
|
||||
static void SetValueByPath (std::string path, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source attribute provided by a given object
|
||||
*
|
||||
* \param traceSource the name of the attribute TraceSource to connect to
|
||||
* \param obj ns3::Object to connect to
|
||||
* \return true if the trace source was successfully connected
|
||||
*/
|
||||
virtual bool ConnectByObject (std::string traceSource, Ptr<Object> obj);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source provided by a config path
|
||||
*
|
||||
* \param path Config path to bind to
|
||||
*
|
||||
* Note, if an invalid path is provided, the probe will not be connected
|
||||
* to anything.
|
||||
*/
|
||||
virtual void ConnectByPath (std::string path);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Method to connect to an underlying ns3::TraceSource with
|
||||
* arguments of type Ptr<const Packet>, Ptr<Ipv4>, and uint32_t
|
||||
*
|
||||
* \param packet the traced packet
|
||||
* \param ipv4 the IPv4 object for the traced packet
|
||||
* \param interface the IPv4 interface for the traced packet
|
||||
*
|
||||
* \internal
|
||||
*/
|
||||
void TraceSink (Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface);
|
||||
|
||||
TracedCallback<Ptr<const Packet>, Ptr<Ipv4>, uint32_t> m_output;
|
||||
TracedCallback<uint32_t, uint32_t> m_outputBytes;
|
||||
|
||||
/// The traced packet.
|
||||
Ptr<const Packet> m_packet;
|
||||
|
||||
/// The IPv4 object for the traced packet.
|
||||
Ptr<Ipv4> m_ipv4;
|
||||
|
||||
/// The IPv4 interface for the traced packet.
|
||||
uint32_t m_interface;
|
||||
|
||||
/// The size of the traced packet.
|
||||
uint32_t m_packetSizeOld;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // IPV4_PACKET_PROBE_H
|
||||
@@ -189,6 +189,7 @@ def build(bld):
|
||||
'helper/ipv6-interface-container.cc',
|
||||
'helper/ipv6-routing-helper.cc',
|
||||
'model/ipv6-address-generator.cc',
|
||||
'model/ipv4-packet-probe.cc',
|
||||
]
|
||||
|
||||
internet_test = bld.create_ns3_module_test_library('internet')
|
||||
@@ -300,6 +301,7 @@ def build(bld):
|
||||
'model/tcp-tx-buffer.h',
|
||||
'model/tcp-rx-buffer.h',
|
||||
'model/rtt-estimator.h',
|
||||
'model/ipv4-packet-probe.h',
|
||||
]
|
||||
|
||||
if bld.env['NSC_ENABLED']:
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/mac48-address.h"
|
||||
|
||||
#include "basic-data-calculators.h"
|
||||
#include "ns3/basic-data-calculators.h"
|
||||
#include "packet-data-calculators.h"
|
||||
|
||||
using namespace ns3;
|
||||
@@ -23,8 +23,8 @@
|
||||
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/mac48-address.h"
|
||||
|
||||
#include "data-calculator.h"
|
||||
#include "ns3/data-calculator.h"
|
||||
#include "ns3/basic-data-calculators.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
117
src/network/utils/packet-probe.cc
Normal file
117
src/network/utils/packet-probe.cc
Normal file
@@ -0,0 +1,117 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#include "ns3/packet-probe.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("PacketProbe");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (PacketProbe);
|
||||
|
||||
TypeId
|
||||
PacketProbe::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::PacketProbe")
|
||||
.SetParent<Probe> ()
|
||||
.AddConstructor<PacketProbe> ()
|
||||
.AddTraceSource ( "Output",
|
||||
"The packet that serve as the output for this probe",
|
||||
MakeTraceSourceAccessor (&PacketProbe::m_output))
|
||||
.AddTraceSource ( "OutputBytes",
|
||||
"The number of bytes in the packet",
|
||||
MakeTraceSourceAccessor (&PacketProbe::m_outputBytes))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
PacketProbe::PacketProbe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_packet = 0;
|
||||
}
|
||||
|
||||
PacketProbe::~PacketProbe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
void
|
||||
PacketProbe::SetValue (Ptr<const Packet> packet)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet);
|
||||
m_packet = packet;
|
||||
m_output (packet);
|
||||
|
||||
uint32_t packetSizeNew = packet->GetSize ();
|
||||
m_outputBytes (m_packetSizeOld, packetSizeNew);
|
||||
m_packetSizeOld = packetSizeNew;
|
||||
}
|
||||
|
||||
void
|
||||
PacketProbe::SetValueByPath (std::string path, Ptr<const Packet> packet)
|
||||
{
|
||||
NS_LOG_FUNCTION (path << packet);
|
||||
Ptr<PacketProbe> probe = Names::Find<PacketProbe> (path);
|
||||
NS_ASSERT_MSG (probe, "Error: Can't find probe for path " << path);
|
||||
probe->SetValue (packet);
|
||||
}
|
||||
|
||||
bool
|
||||
PacketProbe::ConnectByObject (std::string traceSource, Ptr<Object> obj)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << traceSource << obj);
|
||||
NS_LOG_DEBUG ("Name of probe (if any) in names database: " << Names::FindPath (obj));
|
||||
bool connected = obj->TraceConnectWithoutContext (traceSource, MakeCallback (&ns3::PacketProbe::TraceSink, this));
|
||||
return connected;
|
||||
}
|
||||
|
||||
void
|
||||
PacketProbe::ConnectByPath (std::string path)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << path);
|
||||
NS_LOG_DEBUG ("Name of probe to search for in config database: " << path);
|
||||
Config::ConnectWithoutContext (path, MakeCallback (&ns3::PacketProbe::TraceSink, this));
|
||||
}
|
||||
|
||||
void
|
||||
PacketProbe::TraceSink (Ptr<const Packet> packet)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << packet);
|
||||
if (IsEnabled ())
|
||||
{
|
||||
m_packet = packet;
|
||||
m_output (packet);
|
||||
|
||||
uint32_t packetSizeNew = packet->GetSize ();
|
||||
m_outputBytes (m_packetSizeOld, packetSizeNew);
|
||||
m_packetSizeOld = packetSizeNew;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
112
src/network/utils/packet-probe.h
Normal file
112
src/network/utils/packet-probe.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#ifndef PACKET_PROBE_H
|
||||
#define PACKET_PROBE_H
|
||||
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/probe.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This class is designed to probe an underlying ns3 TraceSource
|
||||
* exporting a packet. This probe exports a trace source "Output"
|
||||
* with argument of type Ptr<const Packet>. This probe exports
|
||||
* another trace source "OutputBytes" with arguments of type uint32_t,
|
||||
* which is the number of bytes in the packet. The trace sources emit
|
||||
* values when either the probed trace source emits a new value, or
|
||||
* when SetValue () is called.
|
||||
*/
|
||||
class PacketProbe : public Probe
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId ();
|
||||
PacketProbe ();
|
||||
virtual ~PacketProbe ();
|
||||
|
||||
/**
|
||||
* \brief Set a probe value
|
||||
*
|
||||
* \param packet set the traced packet equal to this
|
||||
*/
|
||||
void SetValue (Ptr<const Packet> packet);
|
||||
|
||||
/**
|
||||
* \brief Set a probe value by its name in the Config system
|
||||
*
|
||||
* \param path config path to access the probe
|
||||
* \param packet set the traced packet equal to this
|
||||
*/
|
||||
static void SetValueByPath (std::string path, Ptr<const Packet> packet);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source attribute provided by a given object
|
||||
*
|
||||
* \param traceSource the name of the attribute TraceSource to connect to
|
||||
* \param obj ns3::Object to connect to
|
||||
* \return true if the trace source was successfully connected
|
||||
*/
|
||||
virtual bool ConnectByObject (std::string traceSource, Ptr<Object> obj);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source provided by a config path
|
||||
*
|
||||
* \param path Config path to bind to
|
||||
*
|
||||
* Note, if an invalid path is provided, the probe will not be connected
|
||||
* to anything.
|
||||
*/
|
||||
virtual void ConnectByPath (std::string path);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Method to connect to an underlying ns3::TraceSource with
|
||||
* arguments of type Ptr<const Packet>
|
||||
*
|
||||
* \param packet the traced packet
|
||||
*
|
||||
* \internal
|
||||
*/
|
||||
void TraceSink (Ptr<const Packet> packet);
|
||||
|
||||
TracedCallback<Ptr<const Packet> > m_output;
|
||||
TracedCallback<uint32_t, uint32_t> m_outputBytes;
|
||||
|
||||
/// The traced packet.
|
||||
Ptr<const Packet> m_packet;
|
||||
|
||||
/// The size of the traced packet.
|
||||
uint32_t m_packetSizeOld;
|
||||
};
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // PACKET_PROBE_H
|
||||
@@ -1,7 +1,7 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
network = bld.create_ns3_module('network', ['core'])
|
||||
network = bld.create_ns3_module('network', ['core', 'stats'])
|
||||
network.source = [
|
||||
'model/address.cc',
|
||||
'model/application.cc',
|
||||
@@ -52,6 +52,8 @@ def build(bld):
|
||||
'utils/red-queue.cc',
|
||||
'utils/simple-channel.cc',
|
||||
'utils/simple-net-device.cc',
|
||||
'utils/packet-data-calculators.cc',
|
||||
'utils/packet-probe.cc',
|
||||
'helper/application-container.cc',
|
||||
'helper/net-device-container.cc',
|
||||
'helper/node-container.cc',
|
||||
@@ -130,6 +132,8 @@ def build(bld):
|
||||
'utils/simple-channel.h',
|
||||
'utils/simple-net-device.h',
|
||||
'utils/pcap-test.h',
|
||||
'utils/packet-data-calculators.h',
|
||||
'utils/packet-probe.h',
|
||||
'helper/application-container.h',
|
||||
'helper/net-device-container.h',
|
||||
'helper/node-container.h',
|
||||
|
||||
197
src/stats/examples/double-probe-example.cc
Normal file
197
src/stats/examples/double-probe-example.cc
Normal file
@@ -0,0 +1,197 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2012 University of Washington
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example is designed to show the main features of an
|
||||
* ns3::DoubleProbe.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/double-probe.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("DoubleProbeExample");
|
||||
|
||||
/*
|
||||
* 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<double> m_counter; // normally this would be integer type
|
||||
Ptr<ExponentialRandomVariable> m_var;
|
||||
|
||||
};
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (Emitter);
|
||||
|
||||
TypeId
|
||||
Emitter::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::Emitter")
|
||||
.AddConstructor<Emitter> ()
|
||||
.SetParent<Object> ()
|
||||
.AddTraceSource ("Counter",
|
||||
"sample counter",
|
||||
MakeTraceSourceAccessor (&Emitter::m_counter))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
Emitter::Emitter (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_counter = 0;
|
||||
m_var = CreateObject<ExponentialRandomVariable> ();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// This is a function to test hooking a raw function to the trace source
|
||||
void
|
||||
NotifyViaTraceSource (std::string context, double oldVal, double newVal)
|
||||
{
|
||||
NS_LOG_DEBUG ("context: " << context << " old " << oldVal << " new " << newVal);
|
||||
}
|
||||
|
||||
// This is a function to test hooking it to the probe output
|
||||
void
|
||||
NotifyViaProbe (std::string context, double oldVal, double newVal)
|
||||
{
|
||||
NS_LOG_DEBUG ("context: " << context << " old " << oldVal << " new " << newVal);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
bool connected;
|
||||
|
||||
Ptr<Emitter> emitter = CreateObject<Emitter> ();
|
||||
Names::Add ("/Names/Emitter", emitter);
|
||||
|
||||
//
|
||||
// The below shows typical functionality without a probe
|
||||
// (connect a sink function to a trace source)
|
||||
//
|
||||
connected = emitter->TraceConnect ("Counter", "sample context", MakeCallback (&NotifyViaTraceSource));
|
||||
NS_ASSERT_MSG (connected, "Trace source not connected");
|
||||
|
||||
//
|
||||
// Next, we'll show several use cases of using a Probe to access and
|
||||
// filter the values of the underlying trace source
|
||||
//
|
||||
|
||||
//
|
||||
// Probe1 will be hooked directly to the Emitter trace source object
|
||||
//
|
||||
|
||||
// probe1 will be hooked to the Emitter trace source
|
||||
Ptr<DoubleProbe> probe1 = CreateObject<DoubleProbe> ();
|
||||
// the probe's name can serve as its context in the tracing
|
||||
probe1->SetName ("ObjectProbe");
|
||||
|
||||
// Connect the probe to the emitter's Counter
|
||||
connected = probe1->ConnectByObject ("Counter", emitter);
|
||||
NS_ASSERT_MSG (connected, "Trace source not connected to probe1");
|
||||
|
||||
// The probe itself should generate output. The context that we provide
|
||||
// to this probe (in this case, the probe name) will help to disambiguate
|
||||
// the source of the trace
|
||||
connected = probe1->TraceConnect ("Output", probe1->GetName (), MakeCallback (&NotifyViaProbe));
|
||||
NS_ASSERT_MSG (connected, "Trace source not connected to probe1 Output");
|
||||
|
||||
//
|
||||
// Probe2 will be hooked to the Emitter trace source object by
|
||||
// accessing it by path name in the Config database
|
||||
//
|
||||
|
||||
// Create another similar probe; this will hook up via a Config path
|
||||
Ptr<DoubleProbe> probe2 = CreateObject<DoubleProbe> ();
|
||||
probe2->SetName ("PathProbe");
|
||||
|
||||
// Note, no return value is checked here
|
||||
probe2->ConnectByPath ("/Names/Emitter/Counter");
|
||||
|
||||
// The probe itself should generate output. The context that we provide
|
||||
// to this probe (in this case, the probe name) will help to disambiguate
|
||||
// the source of the trace
|
||||
connected = probe2->TraceConnect ("Output", "/Names/Probes/PathProbe/Output", MakeCallback (&NotifyViaProbe));
|
||||
NS_ASSERT_MSG (connected, "Trace source not connected to probe2 Output");
|
||||
|
||||
//
|
||||
// Probe3 will be called by the emitter directly through the
|
||||
// static method SetValueByPath().
|
||||
//
|
||||
Ptr<DoubleProbe> probe3 = CreateObject<DoubleProbe> ();
|
||||
probe3->SetName ("StaticallyAccessedProbe");
|
||||
// We must add it to the config database
|
||||
Names::Add ("/Names/Probes", probe3->GetName (), probe3);
|
||||
|
||||
// The probe itself should generate output. The context that we provide
|
||||
// to this probe (in this case, the probe name) will help to disambiguate
|
||||
// the source of the trace
|
||||
connected = probe3->TraceConnect ("Output", "/Names/Probes/StaticallyAccessedProbe/Output", MakeCallback (&NotifyViaProbe));
|
||||
NS_ASSERT_MSG (connected, "Trace source not connected to probe3 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
|
||||
Simulator::Schedule (Seconds (0.0), &Emitter::Initialize, emitter);
|
||||
|
||||
Simulator::Stop (Seconds (100.0));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
173
src/stats/examples/file-aggregator-example.cc
Normal file
173
src/stats/examples/file-aggregator-example.cc
Normal file
@@ -0,0 +1,173 @@
|
||||
/* -*- 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 "ns3/core-module.h"
|
||||
#include "ns3/stats-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
namespace {
|
||||
|
||||
//===========================================================================
|
||||
// Function: CreateCommaSeparatedFile
|
||||
//
|
||||
//
|
||||
// This function creates a file with 2 columns of values and separated
|
||||
// by commas.
|
||||
//===========================================================================
|
||||
|
||||
void CreateCommaSeparatedFile ()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
string fileName = "file-aggregator-comma-separated.txt";
|
||||
string datasetContext = "Dataset/Context/String";
|
||||
|
||||
// Create an aggregator.
|
||||
Ptr<FileAggregator> aggregator =
|
||||
CreateObject<FileAggregator> (fileName, FileAggregator::COMMA_SEPARATED);
|
||||
|
||||
// aggregator must be turned on
|
||||
aggregator->Enable ();
|
||||
|
||||
double time;
|
||||
double value;
|
||||
|
||||
// Create the 2-D dataset.
|
||||
for (time = -5.0; time <= +5.0; time += 1.0)
|
||||
{
|
||||
// Calculate the 2-D curve
|
||||
//
|
||||
// 2
|
||||
// value = time .
|
||||
//
|
||||
value = time * time;
|
||||
|
||||
// Add this point to the plot.
|
||||
aggregator->Write2d (datasetContext, time, value);
|
||||
}
|
||||
|
||||
// Disable logging of data for the aggregator.
|
||||
aggregator->Disable ();
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// Function: CreateSpaceSeparatedFile
|
||||
//
|
||||
//
|
||||
// This function creates a file with 2 columns of values and separated
|
||||
// by spaces.
|
||||
//===========================================================================
|
||||
|
||||
void CreateSpaceSeparatedFile ()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
string fileName = "file-aggregator-space-separated.txt";
|
||||
string datasetContext = "Dataset/Context/String";
|
||||
|
||||
// Create an aggregator. Note that the default type is space
|
||||
// separated.
|
||||
Ptr<FileAggregator> aggregator =
|
||||
CreateObject<FileAggregator> (fileName);
|
||||
|
||||
// aggregator must be turned on
|
||||
aggregator->Enable ();
|
||||
|
||||
double time;
|
||||
double value;
|
||||
|
||||
// Create the 2-D dataset.
|
||||
for (time = -5.0; time <= +5.0; time += 1.0)
|
||||
{
|
||||
// Calculate the 2-D curve
|
||||
//
|
||||
// 2
|
||||
// value = time .
|
||||
//
|
||||
value = time * time;
|
||||
|
||||
// Add this point to the plot.
|
||||
aggregator->Write2d (datasetContext, time, value);
|
||||
}
|
||||
|
||||
// Disable logging of data for the aggregator.
|
||||
aggregator->Disable ();
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// Function: CreateFormattedFile
|
||||
//
|
||||
//
|
||||
// This function creates a file with formatted values.
|
||||
//===========================================================================
|
||||
|
||||
void CreateFormattedFile ()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
string fileName = "file-aggregator-formatted-values.txt";
|
||||
string datasetContext = "Dataset/Context/String";
|
||||
|
||||
// Create an aggregator that will have formatted values.
|
||||
Ptr<FileAggregator> aggregator =
|
||||
CreateObject<FileAggregator> (fileName, FileAggregator::FORMATTED);
|
||||
|
||||
// Set the format for the values.
|
||||
aggregator->Set2dFormat ("Time = %.3e\tValue = %.0f");
|
||||
|
||||
// aggregator must be turned on
|
||||
aggregator->Enable ();
|
||||
|
||||
double time;
|
||||
double value;
|
||||
|
||||
// Create the 2-D dataset.
|
||||
for (time = -5.0; time < 5.5; time += 1.0)
|
||||
{
|
||||
// Calculate the 2-D curve
|
||||
//
|
||||
// 2
|
||||
// value = time .
|
||||
//
|
||||
value = time * time;
|
||||
|
||||
// Add this point to the plot.
|
||||
aggregator->Write2d (datasetContext, time, value);
|
||||
}
|
||||
|
||||
// Disable logging of data for the aggregator.
|
||||
aggregator->Disable ();
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
CreateCommaSeparatedFile ();
|
||||
CreateSpaceSeparatedFile ();
|
||||
CreateFormattedFile ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
157
src/stats/examples/file-helper-example.cc
Normal file
157
src/stats/examples/file-helper-example.cc
Normal file
@@ -0,0 +1,157 @@
|
||||
/* -*- 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
|
||||
*
|
||||
* This is based on double-probe-example.cc.
|
||||
*
|
||||
* Author: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example is designed to show the main features of an
|
||||
* ns3::FileHelper.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/stats-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("FileHelperExample");
|
||||
|
||||
/*
|
||||
* 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<double> m_counter; // normally this would be integer type
|
||||
Ptr<ExponentialRandomVariable> m_var;
|
||||
|
||||
};
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (Emitter);
|
||||
|
||||
TypeId
|
||||
Emitter::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::Emitter")
|
||||
.AddConstructor<Emitter> ()
|
||||
.SetParent<Object> ()
|
||||
.AddTraceSource ("Counter",
|
||||
"sample counter",
|
||||
MakeTraceSourceAccessor (&Emitter::m_counter))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
Emitter::Emitter (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_counter = 0;
|
||||
m_var = CreateObject<ExponentialRandomVariable> ();
|
||||
}
|
||||
|
||||
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;
|
||||
Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Count, this);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
//
|
||||
// This Emitter has a trace source object that will emit values at
|
||||
// random times.
|
||||
//
|
||||
|
||||
Ptr<Emitter> emitter = CreateObject<Emitter> ();
|
||||
Names::Add ("/Names/Emitter", emitter);
|
||||
|
||||
//
|
||||
// This Probe will be hooked to the Emitter's trace source object by
|
||||
// accessing it by path name in the Config database.
|
||||
//
|
||||
|
||||
Ptr<DoubleProbe> probe = CreateObject<DoubleProbe> ();
|
||||
probe->SetName ("PathProbe");
|
||||
Names::Add ("/Names/Probe", probe);
|
||||
|
||||
// Note, no return value is checked here.
|
||||
probe->ConnectByPath ("/Names/Emitter/Counter");
|
||||
|
||||
//
|
||||
// This file helper will be used to put data values into a file.
|
||||
//
|
||||
|
||||
// Create the file helper.
|
||||
FileHelper fileHelper;
|
||||
|
||||
// Configure the file to be written.
|
||||
fileHelper.ConfigureFile ("file-helper-example",
|
||||
FileAggregator::FORMATTED);
|
||||
|
||||
// Set the labels for this formatted output file.
|
||||
fileHelper.Set2dFormat ("Time (Seconds) = %.3e\tCount = %.0f");
|
||||
|
||||
// Write the values generated by the probe. The path that we
|
||||
// provide helps to disambiguate the source of the trace.
|
||||
fileHelper.WriteProbe ("ns3::DoubleProbe",
|
||||
"/Names/Probe/Output",
|
||||
"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
|
||||
Simulator::Schedule (Seconds (0.0), &Emitter::Initialize, emitter);
|
||||
|
||||
Simulator::Stop (Seconds (100.0));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
91
src/stats/examples/gnuplot-aggregator-example.cc
Normal file
91
src/stats/examples/gnuplot-aggregator-example.cc
Normal file
@@ -0,0 +1,91 @@
|
||||
/* -*- 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 "ns3/core-module.h"
|
||||
#include "ns3/stats-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
namespace {
|
||||
|
||||
//===========================================================================
|
||||
// Function: Create2dPlot
|
||||
//
|
||||
//
|
||||
// This function creates a 2-Dimensional plot.
|
||||
//===========================================================================
|
||||
|
||||
void Create2dPlot ()
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
string fileNameWithoutExtension = "gnuplot-aggregator";
|
||||
string plotTitle = "Gnuplot Aggregator Plot";
|
||||
string plotXAxisHeading = "Time (seconds)";
|
||||
string plotYAxisHeading = "Double Values";
|
||||
string plotDatasetLabel = "Data Values";
|
||||
string datasetContext = "Dataset/Context/String";
|
||||
|
||||
// Create an aggregator.
|
||||
Ptr<GnuplotAggregator> aggregator =
|
||||
CreateObject<GnuplotAggregator> (fileNameWithoutExtension);
|
||||
|
||||
// Set the aggregator's properties.
|
||||
aggregator->SetTerminal ("png");
|
||||
aggregator->SetTitle (plotTitle);
|
||||
aggregator->SetLegend (plotXAxisHeading, plotYAxisHeading);
|
||||
|
||||
// Add a data set to the aggregator.
|
||||
aggregator->Add2dDataset (datasetContext, plotDatasetLabel);
|
||||
|
||||
// aggregator must be turned on
|
||||
aggregator->Enable ();
|
||||
|
||||
double time;
|
||||
double value;
|
||||
|
||||
// Create the 2-D dataset.
|
||||
for (time = -5.0; time <= +5.0; time += 1.0)
|
||||
{
|
||||
// Calculate the 2-D curve
|
||||
//
|
||||
// 2
|
||||
// value = time .
|
||||
//
|
||||
value = time * time;
|
||||
|
||||
// Add this point to the plot.
|
||||
aggregator->Write2d (datasetContext, time, value);
|
||||
}
|
||||
|
||||
// Disable logging of data for the aggregator.
|
||||
aggregator->Disable ();
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Create2dPlot ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -201,9 +201,9 @@ void Create3DPlotFile ()
|
||||
plot.AppendExtra ("set ticslevel 0");
|
||||
|
||||
// Set the labels for each axis.
|
||||
plot.AppendExtra ("set xlabel 'X Values'");
|
||||
plot.AppendExtra ("set ylabel 'Y Values'");
|
||||
plot.AppendExtra ("set zlabel 'Z Values'");
|
||||
plot.AppendExtra ("set xlabel \"X Values\"");
|
||||
plot.AppendExtra ("set ylabel \"Y Values\"");
|
||||
plot.AppendExtra ("set zlabel \"Z Values\"");
|
||||
|
||||
// Set the ranges for the x and y axis.
|
||||
plot.AppendExtra ("set xrange [-5:+5]");
|
||||
|
||||
160
src/stats/examples/gnuplot-helper-example.cc
Normal file
160
src/stats/examples/gnuplot-helper-example.cc
Normal file
@@ -0,0 +1,160 @@
|
||||
/* -*- 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
|
||||
*
|
||||
* This is based on double-probe-example.cc.
|
||||
*
|
||||
* Author: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example is designed to show the main features of an
|
||||
* ns3::GnuplotHelper.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/stats-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("GnuplotHelperExample");
|
||||
|
||||
/*
|
||||
* 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<double> m_counter; // normally this would be integer type
|
||||
Ptr<ExponentialRandomVariable> m_var;
|
||||
|
||||
};
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (Emitter);
|
||||
|
||||
TypeId
|
||||
Emitter::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::Emitter")
|
||||
.AddConstructor<Emitter> ()
|
||||
.SetParent<Object> ()
|
||||
.AddTraceSource ("Counter",
|
||||
"sample counter",
|
||||
MakeTraceSourceAccessor (&Emitter::m_counter))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
Emitter::Emitter (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_counter = 0;
|
||||
m_var = CreateObject<ExponentialRandomVariable> ();
|
||||
}
|
||||
|
||||
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;
|
||||
Simulator::Schedule (Seconds (m_var->GetValue ()), &Emitter::Count, this);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
//
|
||||
// This Emitter has a trace source object that will emit values at
|
||||
// random times.
|
||||
//
|
||||
|
||||
Ptr<Emitter> emitter = CreateObject<Emitter> ();
|
||||
Names::Add ("/Names/Emitter", emitter);
|
||||
|
||||
//
|
||||
// This Probe will be hooked to the Emitter's trace source object by
|
||||
// accessing it by path name in the Config database.
|
||||
//
|
||||
|
||||
Ptr<DoubleProbe> probe = CreateObject<DoubleProbe> ();
|
||||
probe->SetName ("PathProbe");
|
||||
Names::Add ("/Names/Probe", probe);
|
||||
|
||||
// Note, no return value is checked here.
|
||||
probe->ConnectByPath ("/Names/Emitter/Counter");
|
||||
|
||||
//
|
||||
// This gnuplot helper will be used to produce output used to make
|
||||
// gnuplot plots.
|
||||
//
|
||||
|
||||
// Create the gnuplot helper.
|
||||
GnuplotHelper plotHelper;
|
||||
|
||||
// Configure the plot.
|
||||
plotHelper.ConfigurePlot ("gnuplot-helper-example",
|
||||
"Emitter Counts vs. Time",
|
||||
"Time (Seconds)",
|
||||
"Emitter Count",
|
||||
"png");
|
||||
|
||||
// Plot the values generated by the probe. The path that we provide
|
||||
// helps to disambiguate the source of the trace.
|
||||
plotHelper.PlotProbe ("ns3::DoubleProbe",
|
||||
"/Names/Probe/Output",
|
||||
"Output",
|
||||
"Emitter Count",
|
||||
GnuplotAggregator::KEY_INSIDE);
|
||||
|
||||
// The Emitter object is not associated with an ns-3 node, so
|
||||
// it won't get started automatically, so we need to do this ourselves
|
||||
Simulator::Schedule (Seconds (0.0), &Emitter::Initialize, emitter);
|
||||
|
||||
Simulator::Stop (Seconds (100.0));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4,7 +4,22 @@ def build(bld):
|
||||
if not bld.env['ENABLE_EXAMPLES']:
|
||||
return;
|
||||
|
||||
obj = bld.create_ns3_program('gnuplot-example', ['stats'])
|
||||
obj = bld.create_ns3_program('gnuplot-example', ['network', 'stats'])
|
||||
obj.source = 'gnuplot-example.cc'
|
||||
|
||||
program = bld.create_ns3_program('double-probe-example', ['network', 'stats'])
|
||||
program.source = 'double-probe-example.cc'
|
||||
|
||||
program = bld.create_ns3_program('gnuplot-aggregator-example', ['network', 'stats'])
|
||||
program.source = 'gnuplot-aggregator-example.cc'
|
||||
|
||||
program = bld.create_ns3_program('gnuplot-helper-example', ['network', 'stats'])
|
||||
program.source = 'gnuplot-helper-example.cc'
|
||||
|
||||
program = bld.create_ns3_program('file-aggregator-example', ['network', 'stats'])
|
||||
program.source = 'file-aggregator-example.cc'
|
||||
|
||||
program = bld.create_ns3_program('file-helper-example', ['network', 'stats'])
|
||||
program.source = 'file-helper-example.cc'
|
||||
|
||||
|
||||
|
||||
559
src/stats/helper/file-helper.cc
Normal file
559
src/stats/helper/file-helper.cc
Normal file
@@ -0,0 +1,559 @@
|
||||
/* -*- 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 <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "file-helper.h"
|
||||
#include "ns3/abort.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/get-wildcard-matches.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("FileHelper");
|
||||
|
||||
FileHelper::FileHelper ()
|
||||
: m_aggregator (0),
|
||||
m_fileProbeCount (0),
|
||||
m_fileType (FileAggregator::SPACE_SEPARATED),
|
||||
m_outputFileNameWithoutExtension ("file-helper"),
|
||||
m_hasHeadingBeenSet (false)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Note that this does not construct an aggregator. It will be
|
||||
// constructed later when needed.
|
||||
}
|
||||
|
||||
FileHelper::FileHelper (const std::string &outputFileNameWithoutExtension,
|
||||
enum FileAggregator::FileType fileType)
|
||||
: m_aggregator (0),
|
||||
m_fileProbeCount (0),
|
||||
m_fileType (fileType),
|
||||
m_outputFileNameWithoutExtension (outputFileNameWithoutExtension),
|
||||
m_hasHeadingBeenSet (false)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Note that this does not construct an aggregator. It will be
|
||||
// constructed later when needed.
|
||||
}
|
||||
|
||||
FileHelper::~FileHelper ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::ConfigureFile (const std::string &outputFileNameWithoutExtension,
|
||||
enum FileAggregator::FileType fileType)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << outputFileNameWithoutExtension << fileType);
|
||||
|
||||
// See if an aggregator has already been constructed.
|
||||
if (m_aggregator != 0)
|
||||
{
|
||||
NS_LOG_WARN ("An existing aggregator object " << m_aggregator <<
|
||||
" may be destroyed if no references remain.");
|
||||
}
|
||||
|
||||
// Store these so that they can be used to construct the aggregator.
|
||||
m_fileType = fileType;
|
||||
m_outputFileNameWithoutExtension = outputFileNameWithoutExtension;
|
||||
m_hasHeadingBeenSet = false;
|
||||
|
||||
// Note that this does not construct an aggregator. It will be
|
||||
// constructed later when needed.
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::WriteProbe (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;
|
||||
|
||||
// See if the path has any wildcards.
|
||||
bool pathHasNoWildcards = path.find ("*") == std::string::npos;
|
||||
|
||||
// Remove the last token from the path.
|
||||
unsigned 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.
|
||||
Config::MatchContainer matches = Config::LookupMatches (pathWithoutLastToken);
|
||||
uint32_t matchCount = matches.GetN ();
|
||||
|
||||
// This is used to make the probe's context be unique.
|
||||
std::string matchIdentifier;
|
||||
|
||||
/// This is used to indicate if multiple aggregators are needed.
|
||||
bool onlyOneAggregator;
|
||||
|
||||
// Hook one or more probes and one or more aggregators 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";
|
||||
onlyOneAggregator = true;
|
||||
ConnectProbeToAggregator (typeId,
|
||||
matchIdentifier,
|
||||
path,
|
||||
probeTraceSource,
|
||||
m_outputFileNameWithoutExtension,
|
||||
onlyOneAggregator);
|
||||
}
|
||||
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 ();
|
||||
onlyOneAggregator = false;
|
||||
|
||||
// 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.
|
||||
ConnectProbeToAggregator (typeId,
|
||||
matchIdentifier,
|
||||
matchedPath,
|
||||
probeTraceSource,
|
||||
m_outputFileNameWithoutExtension + "-" + wildcardMatches,
|
||||
onlyOneAggregator);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is a problem if there are no matching config paths.
|
||||
NS_FATAL_ERROR ("Lookup of " << path << " got no matches");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::AddProbe (const std::string &typeId,
|
||||
const std::string &probeName,
|
||||
const std::string &path)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << typeId << probeName << path);
|
||||
|
||||
// See if this probe had already been added.
|
||||
if (m_probeMap.count (probeName) > 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That probe has already been added");
|
||||
}
|
||||
|
||||
// Prepare the factory to create an object with the requested type.
|
||||
m_factory.SetTypeId (typeId);
|
||||
|
||||
// Create a base class object in order to validate the type.
|
||||
Ptr<Probe> probe = m_factory.Create ()->GetObject<Probe> ();
|
||||
if (probe == 0)
|
||||
{
|
||||
NS_ABORT_MSG ("The requested type is not a probe");
|
||||
}
|
||||
|
||||
// Set the probe's name.
|
||||
probe->SetName (probeName);
|
||||
|
||||
// Set the path. Note that no return value is checked here.
|
||||
probe->ConnectByPath (path);
|
||||
|
||||
// Enable logging of data for the probe.
|
||||
probe->Enable ();
|
||||
|
||||
// Add this probe to the map so that its values can be used.
|
||||
m_probeMap[probeName] = std::make_pair (probe, typeId);
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::AddTimeSeriesAdaptor (const std::string &adaptorName)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << adaptorName);
|
||||
|
||||
// See if this time series adaptor had already been added.
|
||||
if (m_timeSeriesAdaptorMap.count (adaptorName) > 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That time series adaptor 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 it can be used.
|
||||
m_timeSeriesAdaptorMap[adaptorName] = timeSeriesAdaptor;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::AddAggregator (const std::string &aggregatorName,
|
||||
const std::string &outputFileName,
|
||||
bool onlyOneAggregator)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << aggregatorName << outputFileName << onlyOneAggregator);
|
||||
|
||||
// See if this file aggregator had already been added.
|
||||
if (m_aggregatorMap.count (aggregatorName) > 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That file aggregator has already been added");
|
||||
}
|
||||
|
||||
// If there is only going to be 1 file aggregator, then use the one
|
||||
// already constructed in the map.
|
||||
if (onlyOneAggregator)
|
||||
{
|
||||
// Get a pointer to the aggregator.
|
||||
Ptr<FileAggregator> singleAggregator = GetAggregatorSingle ();
|
||||
|
||||
m_aggregatorMap[aggregatorName] = singleAggregator;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the file aggregator with the proper file type.
|
||||
Ptr<FileAggregator> multipleAggregator =
|
||||
CreateObject<FileAggregator> (outputFileName, m_fileType);
|
||||
|
||||
// Set all of the format strings for the aggregator.
|
||||
multipleAggregator->Set1dFormat (m_1dFormat);
|
||||
multipleAggregator->Set2dFormat (m_2dFormat);
|
||||
multipleAggregator->Set3dFormat (m_3dFormat);
|
||||
multipleAggregator->Set4dFormat (m_4dFormat);
|
||||
multipleAggregator->Set5dFormat (m_5dFormat);
|
||||
multipleAggregator->Set6dFormat (m_6dFormat);
|
||||
multipleAggregator->Set7dFormat (m_7dFormat);
|
||||
multipleAggregator->Set8dFormat (m_8dFormat);
|
||||
multipleAggregator->Set9dFormat (m_9dFormat);
|
||||
multipleAggregator->Set10dFormat (m_10dFormat);
|
||||
|
||||
// Set the heading
|
||||
multipleAggregator->SetHeading (m_heading);
|
||||
|
||||
// Enable logging of data for the file aggregator.
|
||||
multipleAggregator->Enable ();
|
||||
|
||||
// Add this file aggregator to the map so that it can be used.
|
||||
m_aggregatorMap[aggregatorName] = multipleAggregator;
|
||||
}
|
||||
|
||||
Ptr<Probe>
|
||||
FileHelper::GetProbe (std::string probeName) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << probeName);
|
||||
|
||||
// Look for the probe.
|
||||
std::map<std::string, std::pair <Ptr<Probe>, std::string> >::const_iterator mapIterator = m_probeMap.find (probeName);
|
||||
|
||||
// Return the probe if it has been added.
|
||||
if (mapIterator != m_probeMap.end ())
|
||||
{
|
||||
return mapIterator->second.first;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ABORT_MSG ("That probe has not been added");
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<FileAggregator>
|
||||
FileHelper::GetAggregatorSingle ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Do a lazy construction of the single aggregator if it hasn't
|
||||
// already been constructed.
|
||||
if (!m_aggregator)
|
||||
{
|
||||
// Create the aggregator.
|
||||
std::string outputFileName = m_outputFileNameWithoutExtension + ".txt";
|
||||
m_aggregator = CreateObject<FileAggregator> (outputFileName, m_fileType);
|
||||
|
||||
// Set all of the format strings for the aggregator.
|
||||
m_aggregator->Set1dFormat (m_1dFormat);
|
||||
m_aggregator->Set2dFormat (m_2dFormat);
|
||||
m_aggregator->Set3dFormat (m_3dFormat);
|
||||
m_aggregator->Set4dFormat (m_4dFormat);
|
||||
m_aggregator->Set5dFormat (m_5dFormat);
|
||||
m_aggregator->Set6dFormat (m_6dFormat);
|
||||
m_aggregator->Set7dFormat (m_7dFormat);
|
||||
m_aggregator->Set8dFormat (m_8dFormat);
|
||||
m_aggregator->Set9dFormat (m_9dFormat);
|
||||
m_aggregator->Set10dFormat (m_10dFormat);
|
||||
|
||||
// Set the heading
|
||||
m_aggregator->SetHeading (m_heading);
|
||||
|
||||
// Enable logging of data for the aggregator.
|
||||
m_aggregator->Enable ();
|
||||
}
|
||||
return m_aggregator;
|
||||
}
|
||||
|
||||
Ptr<FileAggregator>
|
||||
FileHelper::GetAggregatorMultiple (const std::string &aggregatorName,
|
||||
const std::string &outputFileName)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// See if this file aggregator had already been added.
|
||||
if (m_aggregatorMap.count (aggregatorName) > 0)
|
||||
{
|
||||
return m_aggregatorMap[aggregatorName];
|
||||
}
|
||||
|
||||
// Do a lazy construction of the aggregator if it hasn't already
|
||||
// been constructed.
|
||||
bool onlyOneAggregator = false;
|
||||
AddAggregator (aggregatorName,
|
||||
outputFileName,
|
||||
onlyOneAggregator);
|
||||
|
||||
return m_aggregatorMap[aggregatorName];
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::SetHeading (const std::string &heading)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << heading);
|
||||
|
||||
m_hasHeadingBeenSet = true;
|
||||
m_heading = heading;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::Set1dFormat (const std::string &format)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << format);
|
||||
|
||||
m_1dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::Set2dFormat (const std::string &format)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << format);
|
||||
|
||||
m_2dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::Set3dFormat (const std::string &format)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << format);
|
||||
|
||||
m_3dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::Set4dFormat (const std::string &format)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << format);
|
||||
|
||||
m_4dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::Set5dFormat (const std::string &format)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << format);
|
||||
|
||||
m_5dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::Set6dFormat (const std::string &format)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << format);
|
||||
|
||||
m_6dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::Set7dFormat (const std::string &format)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << format);
|
||||
|
||||
m_7dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::Set8dFormat (const std::string &format)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << format);
|
||||
|
||||
m_8dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::Set9dFormat (const std::string &format)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << format);
|
||||
|
||||
m_9dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::Set10dFormat (const std::string &format)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << format);
|
||||
|
||||
m_10dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileHelper::ConnectProbeToAggregator (const std::string &typeId,
|
||||
const std::string &matchIdentifier,
|
||||
const std::string &path,
|
||||
const std::string &probeTraceSource,
|
||||
const std::string &outputFileNameWithoutExtension,
|
||||
bool onlyOneAggregator)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << typeId << matchIdentifier << path << probeTraceSource
|
||||
<< outputFileNameWithoutExtension << onlyOneAggregator);
|
||||
|
||||
// Increment the total number of file probes that have been created.
|
||||
m_fileProbeCount++;
|
||||
|
||||
// Create a unique name for this probe.
|
||||
std::ostringstream probeNameStream;
|
||||
probeNameStream << "FileProbe-" << m_fileProbeCount;
|
||||
std::string probeName = probeNameStream.str ();
|
||||
|
||||
// Create a unique dataset context string for this probe.
|
||||
std::string probeContext = probeName
|
||||
+ "/" + matchIdentifier + "/" + probeTraceSource;
|
||||
|
||||
// Add the probe to the map of probes, which will keep the probe in
|
||||
// memory after this function ends.
|
||||
AddProbe (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);
|
||||
|
||||
// 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::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
|
||||
{
|
||||
NS_FATAL_ERROR ("Unknown probe type " << m_probeMap[probeName].second << "; need to add support in the helper for this");
|
||||
}
|
||||
|
||||
// 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,
|
||||
probeContext,
|
||||
MakeCallback (&FileAggregator::Write2d,
|
||||
m_aggregatorMap[probeContext]));
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
323
src/stats/helper/file-helper.h
Normal file
323
src/stats/helper/file-helper.h
Normal file
@@ -0,0 +1,323 @@
|
||||
/* -*- 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 FILE_HELPER_H
|
||||
#define FILE_HELPER_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "ns3/object-factory.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/probe.h"
|
||||
#include "ns3/file-aggregator.h"
|
||||
#include "ns3/time-series-adaptor.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief Helper class used to put data values into a file.
|
||||
**/
|
||||
class FileHelper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a file helper that will create a space separated file
|
||||
* named "file-helper.txt" unless it is later configured otherwise.
|
||||
*/
|
||||
FileHelper ();
|
||||
|
||||
/**
|
||||
* \param outputFileNameWithoutExtension name of output file to
|
||||
* write with no extension
|
||||
* \param fileType type of file to write.
|
||||
*
|
||||
* Constructs a file helper that will create a file named
|
||||
* outputFileNameWithoutExtension plus possible extra information
|
||||
* from wildcard matches plus ".txt" with values printed as
|
||||
* specified by fileType. The default file type is space-separated.
|
||||
*/
|
||||
FileHelper (const std::string &outputFileNameWithoutExtension,
|
||||
enum FileAggregator::FileType fileType = FileAggregator::SPACE_SEPARATED);
|
||||
|
||||
virtual ~FileHelper ();
|
||||
|
||||
/**
|
||||
* \param outputFileNameWithoutExtension name of output file to
|
||||
* write with no extension
|
||||
* \param fileType type of file to write.
|
||||
*
|
||||
* Configures file related parameters for this file helper so that
|
||||
* it will create a file named outputFileNameWithoutExtension plus
|
||||
* possible extra information from wildcard matches plus ".txt" with
|
||||
* values printed as specified by fileType. The default file type
|
||||
* is space-separated.
|
||||
*/
|
||||
void ConfigureFile (const std::string &outputFileNameWithoutExtension,
|
||||
enum FileAggregator::FileType fileType = FileAggregator::SPACE_SEPARATED);
|
||||
|
||||
/**
|
||||
* \param typeId the type ID for the probe used when it is created.
|
||||
* \param path Config path to access the probe.
|
||||
* \param probeTraceSource the probe trace source to access.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 WriteProbe (const std::string &typeId,
|
||||
const std::string &path,
|
||||
const std::string &probeTraceSource);
|
||||
|
||||
/**
|
||||
* \param typeId the type ID for the probe used when it is created.
|
||||
* \param probeName the probe's name.
|
||||
* \param path Config path to access the probe
|
||||
*
|
||||
* \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);
|
||||
|
||||
/**
|
||||
* \param adaptorName the timeSeriesAdaptor's name.
|
||||
*
|
||||
* \brief Adds a time series adaptor to be used to write the file.
|
||||
*/
|
||||
void AddTimeSeriesAdaptor (const std::string &adaptorName);
|
||||
|
||||
/**
|
||||
* \param aggregatorName the aggregator's name.
|
||||
* \param outputFileName name of the file to write.
|
||||
* \param onlyOneAggregator indicates if more than one aggregator
|
||||
* should be created or not.
|
||||
*
|
||||
* \brief Adds an aggregator to be used to write values to files.
|
||||
*/
|
||||
void AddAggregator (const std::string &aggregatorName,
|
||||
const std::string &outputFileName,
|
||||
bool onlyOneAggregator);
|
||||
|
||||
/**
|
||||
* \param probeName the probe's name.
|
||||
*
|
||||
* \brief Gets the specified probe.
|
||||
*/
|
||||
Ptr<Probe> GetProbe (std::string probeName) const;
|
||||
|
||||
/**
|
||||
* \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<FileAggregator> GetAggregatorSingle ();
|
||||
|
||||
/**
|
||||
* \param aggregatorName name for aggregator.
|
||||
* \param outputFileName name of output file to write.
|
||||
*
|
||||
* \brief Gets one of the multiple aggregators from the map.
|
||||
*
|
||||
* This function is non-const because an aggregator may be lazily
|
||||
* created by this method.
|
||||
*/
|
||||
Ptr<FileAggregator> GetAggregatorMultiple (const std::string &aggregatorName,
|
||||
const std::string &outputFileName);
|
||||
|
||||
/**
|
||||
* \param heading the heading string.
|
||||
*
|
||||
* \brief Sets the heading string that will be printed on the first
|
||||
* line of the file.
|
||||
*
|
||||
* Note that the heading string will only be printed if it has been
|
||||
* set by calling this function.
|
||||
*/
|
||||
void SetHeading (const std::string &heading);
|
||||
|
||||
/**
|
||||
* \param format the 1D format string.
|
||||
*
|
||||
* \brief Sets the 1D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set1dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 2D format string.
|
||||
*
|
||||
* \brief Sets the 2D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set2dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 3D format string.
|
||||
*
|
||||
* \brief Sets the 3D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set3dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 4D format string.
|
||||
*
|
||||
* \brief Sets the 4D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set4dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 5D format string.
|
||||
*
|
||||
* \brief Sets the 5D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set5dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 6D format string.
|
||||
*
|
||||
* \brief Sets the 6D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set6dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 7D format string.
|
||||
*
|
||||
* \brief Sets the 7D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set7dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 8D format string.
|
||||
*
|
||||
* \brief Sets the 8D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set8dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 9D format string.
|
||||
*
|
||||
* \brief Sets the 9D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set9dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 10D format string.
|
||||
*
|
||||
* \brief Sets the 10D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set10dFormat (const std::string &format);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \param typeId the type ID for the probe used when it is created.
|
||||
* \param matchIdentifier this string is used to make the probe's
|
||||
* context be unique.
|
||||
* \param path Config path to access the probe.
|
||||
* \param probeTraceSource the probe trace source to access.
|
||||
* \param outputFileNameWithoutExtension name of output file to
|
||||
* write with no extension
|
||||
* \param onlyOneAggregator indicates if more than one aggregator
|
||||
* should be created or not.
|
||||
*
|
||||
* \brief Connects the probe to the aggregator.
|
||||
*
|
||||
* A fatal error will result if an unknown probe type is used.
|
||||
*/
|
||||
void ConnectProbeToAggregator (const std::string &typeId,
|
||||
const std::string &matchIdentifier,
|
||||
const std::string &path,
|
||||
const std::string &probeTraceSource,
|
||||
const std::string &outputFileNameWithoutExtension,
|
||||
bool onlyOneAggregator);
|
||||
|
||||
/// Used to create the probes and collectors as they are added.
|
||||
ObjectFactory m_factory;
|
||||
|
||||
/// The single aggregator that is always created in the constructor.
|
||||
Ptr<FileAggregator> m_aggregator;
|
||||
|
||||
/// Maps aggregator names to aggregators when multiple aggregators
|
||||
/// are needed.
|
||||
std::map<std::string, Ptr<FileAggregator> > m_aggregatorMap;
|
||||
|
||||
/// Maps probe names to probes.
|
||||
std::map<std::string, std::pair <Ptr<Probe>, std::string> > m_probeMap;
|
||||
|
||||
/// Maps time series adaptor names to time series adaptors.
|
||||
std::map<std::string, Ptr<TimeSeriesAdaptor> > m_timeSeriesAdaptorMap;
|
||||
|
||||
/// Number of file probes that have been created.
|
||||
uint32_t m_fileProbeCount;
|
||||
|
||||
/// Determines the kind of file written by the aggregator.
|
||||
enum FileAggregator::FileType m_fileType;
|
||||
|
||||
/// The name of the output file to created without its extension.
|
||||
std::string m_outputFileNameWithoutExtension;
|
||||
|
||||
/// Indicates if the heading line for the file has been set.
|
||||
bool m_hasHeadingBeenSet;
|
||||
|
||||
/// Heading line for the outputfile.
|
||||
std::string m_heading;
|
||||
|
||||
/// Format strings for C-style sprintf() function.
|
||||
std::string m_1dFormat;
|
||||
std::string m_2dFormat;
|
||||
std::string m_3dFormat;
|
||||
std::string m_4dFormat;
|
||||
std::string m_5dFormat;
|
||||
std::string m_6dFormat;
|
||||
std::string m_7dFormat;
|
||||
std::string m_8dFormat;
|
||||
std::string m_9dFormat;
|
||||
std::string m_10dFormat;
|
||||
|
||||
}; // class FileHelper
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // FILE_HELPER_H
|
||||
413
src/stats/helper/gnuplot-helper.cc
Normal file
413
src/stats/helper/gnuplot-helper.cc
Normal file
@@ -0,0 +1,413 @@
|
||||
/* -*- 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 <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "gnuplot-helper.h"
|
||||
#include "ns3/abort.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/get-wildcard-matches.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("GnuplotHelper");
|
||||
|
||||
GnuplotHelper::GnuplotHelper ()
|
||||
: m_aggregator (0),
|
||||
m_plotProbeCount (0),
|
||||
m_outputFileNameWithoutExtension ("gnuplot-helper"),
|
||||
m_title ("Gnuplot Helper Plot"),
|
||||
m_xLegend ("X Values"),
|
||||
m_yLegend ("Y Values"),
|
||||
m_terminalType ("png")
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Note that this does not construct an aggregator. It will be
|
||||
// constructed later when needed.
|
||||
}
|
||||
|
||||
GnuplotHelper::GnuplotHelper (const std::string &outputFileNameWithoutExtension,
|
||||
const std::string &title,
|
||||
const std::string &xLegend,
|
||||
const std::string &yLegend,
|
||||
const std::string &terminalType)
|
||||
: m_aggregator (0),
|
||||
m_plotProbeCount (0),
|
||||
m_outputFileNameWithoutExtension (outputFileNameWithoutExtension),
|
||||
m_title (title),
|
||||
m_xLegend (xLegend),
|
||||
m_yLegend (yLegend),
|
||||
m_terminalType (terminalType)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Construct the aggregator.
|
||||
ConstructAggregator ();
|
||||
}
|
||||
|
||||
GnuplotHelper::~GnuplotHelper ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotHelper::ConfigurePlot (const std::string &outputFileNameWithoutExtension,
|
||||
const std::string &title,
|
||||
const std::string &xLegend,
|
||||
const std::string &yLegend,
|
||||
const std::string &terminalType)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << outputFileNameWithoutExtension << title
|
||||
<< xLegend << yLegend << terminalType);
|
||||
|
||||
// See if an aggregator has already been constructed.
|
||||
if (m_aggregator != 0)
|
||||
{
|
||||
NS_LOG_WARN ("An existing aggregator object " << m_aggregator <<
|
||||
" may be destroyed if no references remain.");
|
||||
}
|
||||
|
||||
// Store these so that they can be used to construct the aggregator.
|
||||
m_outputFileNameWithoutExtension = outputFileNameWithoutExtension;
|
||||
m_title = title;
|
||||
m_xLegend = xLegend;
|
||||
m_yLegend = yLegend;
|
||||
m_terminalType = terminalType;
|
||||
|
||||
// Construct the aggregator.
|
||||
ConstructAggregator ();
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotHelper::PlotProbe (const std::string &typeId,
|
||||
const std::string &path,
|
||||
const std::string &probeTraceSource,
|
||||
const std::string &title,
|
||||
enum GnuplotAggregator::KeyLocation keyLocation)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << typeId << path << probeTraceSource << title << keyLocation);
|
||||
|
||||
// Get a pointer to the aggregator.
|
||||
Ptr<GnuplotAggregator> aggregator = GetAggregator ();
|
||||
|
||||
// Add a subtitle to the title to show the probe's path.
|
||||
aggregator->SetTitle ( m_title + " \\n\\nProbe Path: " + path);
|
||||
|
||||
// Set the default dataset plotting style for the values.
|
||||
aggregator->Set2dDatasetDefaultStyle (Gnuplot2dDataset::LINES_POINTS);
|
||||
|
||||
// Set the location of the key in the plot.
|
||||
aggregator->SetKeyLocation (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.
|
||||
unsigned 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.
|
||||
Config::MatchContainer matches = Config::LookupMatches (pathWithoutLastToken);
|
||||
uint32_t matchCount = matches.GetN ();
|
||||
|
||||
// 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";
|
||||
ConnectProbeToAggregator (typeId,
|
||||
matchIdentifier,
|
||||
path,
|
||||
probeTraceSource,
|
||||
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.
|
||||
ConnectProbeToAggregator (typeId,
|
||||
matchIdentifier,
|
||||
matchedPath,
|
||||
probeTraceSource,
|
||||
title + "-" + wildcardMatches);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// There is a problem if there are no matching config paths.
|
||||
NS_FATAL_ERROR ("Lookup of " << path << " got no matches");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotHelper::AddProbe (const std::string &typeId,
|
||||
const std::string &probeName,
|
||||
const std::string &path)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << typeId << probeName << path);
|
||||
|
||||
// See if this probe had already been added.
|
||||
if (m_probeMap.count (probeName) > 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That probe has already been added");
|
||||
}
|
||||
|
||||
// Prepare the factory to create an object with the requested type.
|
||||
m_factory.SetTypeId (typeId);
|
||||
|
||||
// Create a base class object in order to validate the type.
|
||||
Ptr<Probe> probe = m_factory.Create ()->GetObject<Probe> ();
|
||||
if (probe == 0)
|
||||
{
|
||||
NS_ABORT_MSG ("The requested type is not a probe");
|
||||
}
|
||||
|
||||
// Set the probe's name.
|
||||
probe->SetName (probeName);
|
||||
|
||||
// Set the path. Note that no return value is checked here.
|
||||
probe->ConnectByPath (path);
|
||||
|
||||
// Enable logging of data for the probe.
|
||||
probe->Enable ();
|
||||
|
||||
// Add this probe to the map so that its values can be used.
|
||||
m_probeMap[probeName] = std::make_pair (probe, typeId);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotHelper::AddTimeSeriesAdaptor (const std::string &adaptorName)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << adaptorName);
|
||||
|
||||
// See if this time series adaptor had already been added.
|
||||
if (m_timeSeriesAdaptorMap.count (adaptorName) > 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That time series adaptor 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;
|
||||
}
|
||||
|
||||
Ptr<Probe>
|
||||
GnuplotHelper::GetProbe (std::string probeName) const
|
||||
{
|
||||
// Look for the probe.
|
||||
std::map<std::string, std::pair <Ptr<Probe>, std::string> >::const_iterator mapIterator = m_probeMap.find (probeName);
|
||||
|
||||
// Return the probe if it has been added.
|
||||
if (mapIterator != m_probeMap.end ())
|
||||
{
|
||||
return mapIterator->second.first;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ABORT_MSG ("That probe has not been added");
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<GnuplotAggregator>
|
||||
GnuplotHelper::GetAggregator ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Do a lazy construction of the aggregator if it hasn't already
|
||||
// been constructed.
|
||||
if (!m_aggregator)
|
||||
{
|
||||
ConstructAggregator ();
|
||||
}
|
||||
return m_aggregator;
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotHelper::ConstructAggregator ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// Create the aggregator.
|
||||
m_aggregator = CreateObject<GnuplotAggregator> (m_outputFileNameWithoutExtension);
|
||||
|
||||
// Set the aggregator's properties.
|
||||
m_aggregator->SetTerminal (m_terminalType);
|
||||
m_aggregator->SetTitle (m_title);
|
||||
m_aggregator->SetLegend (m_xLegend, m_yLegend);
|
||||
|
||||
// Enable logging of data for the aggregator.
|
||||
m_aggregator->Enable ();
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotHelper::ConnectProbeToAggregator (const std::string &typeId,
|
||||
const std::string &matchIdentifier,
|
||||
const std::string &path,
|
||||
const std::string &probeTraceSource,
|
||||
const std::string &title)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << typeId << matchIdentifier << path << probeTraceSource
|
||||
<< title);
|
||||
|
||||
Ptr<GnuplotAggregator> aggregator = GetAggregator ();
|
||||
|
||||
// Increment the total number of plot probes that have been created.
|
||||
m_plotProbeCount++;
|
||||
|
||||
// Create a unique name for this probe.
|
||||
std::ostringstream probeNameStream;
|
||||
probeNameStream << "PlotProbe-" << m_plotProbeCount;
|
||||
std::string probeName = probeNameStream.str ();
|
||||
|
||||
// Create a unique dataset context string for this probe.
|
||||
std::string probeContext = probeName
|
||||
+ "/" + matchIdentifier + "/" + probeTraceSource;
|
||||
|
||||
// Add the probe to the map of probes, which will keep the probe in
|
||||
// memory after this function ends.
|
||||
AddProbe (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);
|
||||
|
||||
// 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::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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
212
src/stats/helper/gnuplot-helper.h
Normal file
212
src/stats/helper/gnuplot-helper.h
Normal file
@@ -0,0 +1,212 @@
|
||||
/* -*- 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 GNUPLOT_HELPER_H
|
||||
#define GNUPLOT_HELPER_H
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include "ns3/object-factory.h"
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/probe.h"
|
||||
#include "ns3/gnuplot-aggregator.h"
|
||||
#include "ns3/time-series-adaptor.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief Helper class used to make gnuplot plots.
|
||||
**/
|
||||
class GnuplotHelper
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructs a gnuplot helper that will create a space separated
|
||||
* gnuplot data file named "gnuplot-helper.dat", a gnuplot control
|
||||
* file named "gnuplot-helper.plt", and a shell script to generate
|
||||
* the gnuplot named "gnuplot-helper.sh" unless it is later
|
||||
* configured otherwise.
|
||||
*/
|
||||
GnuplotHelper ();
|
||||
|
||||
/**
|
||||
* \param outputFileNameWithoutExtension name of gnuplot related files to
|
||||
* write with no extension
|
||||
* \param title plot title string to use for this plot.
|
||||
* \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"
|
||||
*
|
||||
* Constructs a gnuplot helper that will create a space separated
|
||||
* gnuplot data file named outputFileNameWithoutExtension + ".dat",
|
||||
* a gnuplot control file named outputFileNameWithoutExtension +
|
||||
* ".plt", and a shell script to generate the gnuplot named
|
||||
* outputFileNameWithoutExtension + ".sh".
|
||||
*/
|
||||
GnuplotHelper (const std::string &outputFileNameWithoutExtension,
|
||||
const std::string &title,
|
||||
const std::string &xLegend,
|
||||
const std::string &yLegend,
|
||||
const std::string &terminalType = "png");
|
||||
|
||||
virtual ~GnuplotHelper ();
|
||||
|
||||
/**
|
||||
* \param outputFileNameWithoutExtension name of gnuplot related files to
|
||||
* write with no extension
|
||||
* \param title plot title string to use for this plot.
|
||||
* \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"
|
||||
*
|
||||
* Configures plot related parameters for this gnuplot helper so
|
||||
* that it will create a space separated gnuplot data file named
|
||||
* outputFileNameWithoutExtension + ".dat", a gnuplot control file
|
||||
* named outputFileNameWithoutExtension + ".plt", and a shell script
|
||||
* to generate the gnuplot named outputFileNameWithoutExtension +
|
||||
* ".sh".
|
||||
*/
|
||||
void ConfigurePlot (const std::string &outputFileNameWithoutExtension,
|
||||
const std::string &title,
|
||||
const std::string &xLegend,
|
||||
const std::string &yLegend,
|
||||
const std::string &terminalType = ".png");
|
||||
|
||||
/**
|
||||
* \param typeId the type ID for the probe used when it is created.
|
||||
* \param path Config path to access the probe.
|
||||
* \param probeTraceSource the probe trace source to access.
|
||||
* \param title the title to be associated to this dataset
|
||||
* \param keyLocation the location of the key in the plot.
|
||||
*
|
||||
* Plots a dataset generated by hooking the ns-3 trace source with a
|
||||
* probe, and then plot the values from the probeTraceSource. The dataset
|
||||
* will have the provided title, and will consist of the 'newValue'
|
||||
* at each timestamp.
|
||||
*
|
||||
* 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 PlotProbe (const std::string &typeId,
|
||||
const std::string &path,
|
||||
const std::string &probeTraceSource,
|
||||
const std::string &title,
|
||||
enum GnuplotAggregator::KeyLocation keyLocation = GnuplotAggregator::KEY_INSIDE);
|
||||
|
||||
/**
|
||||
* \param typeId the type ID for the probe used when it is created.
|
||||
* \param probeName the probe's name.
|
||||
* \param path Config path to access the probe.
|
||||
*
|
||||
* \brief Adds a probe to be used to make the plot.
|
||||
*/
|
||||
void AddProbe (const std::string &typeId,
|
||||
const std::string &probeName,
|
||||
const std::string &path);
|
||||
|
||||
/**
|
||||
* \param adaptorName the timeSeriesAdaptor's name.
|
||||
*
|
||||
* \brief Adds a time series adaptor to be used to make the plot.
|
||||
*/
|
||||
void AddTimeSeriesAdaptor (const std::string &adaptorName);
|
||||
|
||||
/**
|
||||
* \param probeName the probe's name.
|
||||
*
|
||||
* \brief Gets the specified probe.
|
||||
*/
|
||||
Ptr<Probe> GetProbe (std::string probeName) const;
|
||||
|
||||
/**
|
||||
* \brief Gets the aggregator.
|
||||
*
|
||||
* This function is non-const because an aggregator may be lazily
|
||||
* created by this method.
|
||||
*/
|
||||
Ptr<GnuplotAggregator> GetAggregator ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Constructs the aggregator.
|
||||
*/
|
||||
void ConstructAggregator ();
|
||||
|
||||
/**
|
||||
* \param typeId the type ID for the probe used when it is created.
|
||||
* \param matchIdentifier this string is used to make the probe's
|
||||
* context be unique.
|
||||
* \param path Config path to access the probe.
|
||||
* \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.
|
||||
*/
|
||||
void ConnectProbeToAggregator (const std::string &typeId,
|
||||
const std::string &matchIdentifier,
|
||||
const std::string &path,
|
||||
const std::string &probeTraceSource,
|
||||
const std::string &title);
|
||||
|
||||
/// Used to create the probes and collectors as they are added.
|
||||
ObjectFactory m_factory;
|
||||
|
||||
/// The aggregator used to make the plots.
|
||||
Ptr<GnuplotAggregator> m_aggregator;
|
||||
|
||||
/// Maps probe names to probes.
|
||||
std::map<std::string, std::pair <Ptr<Probe>, std::string> > m_probeMap;
|
||||
|
||||
/// Maps time series adaptor names to time series adaptors.
|
||||
std::map<std::string, Ptr<TimeSeriesAdaptor> > m_timeSeriesAdaptorMap;
|
||||
|
||||
/// Number of plot probes that have been created.
|
||||
uint32_t m_plotProbeCount;
|
||||
|
||||
/// The name of the output file to created without its extension.
|
||||
std::string m_outputFileNameWithoutExtension;
|
||||
|
||||
/// Title string to use for this plot.
|
||||
std::string m_title;
|
||||
|
||||
/// Legend for the x axis.
|
||||
std::string m_xLegend;
|
||||
|
||||
/// Legend for the y axis.
|
||||
std::string m_yLegend;
|
||||
|
||||
/// Terminal type for the plot.
|
||||
std::string m_terminalType;
|
||||
|
||||
}; // class GnuplotHelper
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // GNUPLOT_HELPER_H
|
||||
110
src/stats/model/boolean-probe.cc
Normal file
110
src/stats/model/boolean-probe.cc
Normal file
@@ -0,0 +1,110 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#include "ns3/boolean-probe.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("BooleanProbe");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (BooleanProbe);
|
||||
|
||||
TypeId
|
||||
BooleanProbe::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::BooleanProbe")
|
||||
.SetParent<Probe> ()
|
||||
.AddConstructor<BooleanProbe> ()
|
||||
.AddTraceSource ( "Output",
|
||||
"The bool that serves as output for this probe",
|
||||
MakeTraceSourceAccessor (&BooleanProbe::m_output))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
BooleanProbe::BooleanProbe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_output = 0;
|
||||
}
|
||||
|
||||
BooleanProbe::~BooleanProbe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
bool
|
||||
BooleanProbe::GetValue (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_output;
|
||||
}
|
||||
void
|
||||
BooleanProbe::SetValue (bool newVal)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << newVal);
|
||||
m_output = newVal;
|
||||
}
|
||||
|
||||
void
|
||||
BooleanProbe::SetValueByPath (std::string path, bool newVal)
|
||||
{
|
||||
NS_LOG_FUNCTION (path << newVal);
|
||||
Ptr<BooleanProbe> probe = Names::Find<BooleanProbe> (path);
|
||||
NS_ASSERT_MSG (probe, "Error: Can't find probe for path " << path);
|
||||
probe->SetValue (newVal);
|
||||
}
|
||||
|
||||
bool
|
||||
BooleanProbe::ConnectByObject (std::string traceSource, Ptr<Object> obj)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << traceSource << obj);
|
||||
NS_LOG_DEBUG ("Name of probe (if any) in names database: " << Names::FindPath (obj));
|
||||
bool connected = obj->TraceConnectWithoutContext (traceSource, MakeCallback (&ns3::BooleanProbe::TraceSink, this));
|
||||
return connected;
|
||||
}
|
||||
|
||||
void
|
||||
BooleanProbe::ConnectByPath (std::string path)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << path);
|
||||
NS_LOG_DEBUG ("Name of probe to search for in config database: " << path);
|
||||
Config::ConnectWithoutContext (path, MakeCallback (&ns3::BooleanProbe::TraceSink, this));
|
||||
}
|
||||
|
||||
void
|
||||
BooleanProbe::TraceSink (bool oldData, bool newData)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << oldData << newData);
|
||||
if (IsEnabled ())
|
||||
{
|
||||
m_output = newData;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
105
src/stats/model/boolean-probe.h
Normal file
105
src/stats/model/boolean-probe.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#ifndef BOOL_PROBE_H
|
||||
#define BOOL_PROBE_H
|
||||
|
||||
#include "ns3/probe.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This class is designed to probe an underlying ns3 TraceSource exporting
|
||||
* a bool. This probe exports a trace source "Output" of type bool.
|
||||
* The Output trace source emits a value when either the trace source
|
||||
* emits a new value, or when SetValue () is called.
|
||||
*
|
||||
* The current value of the probe can be polled with the GetValue ()
|
||||
* method.
|
||||
*/
|
||||
class BooleanProbe : public Probe
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId ();
|
||||
BooleanProbe ();
|
||||
virtual ~BooleanProbe ();
|
||||
|
||||
/**
|
||||
* \return the most recent value
|
||||
*/
|
||||
bool GetValue (void) const;
|
||||
|
||||
/**
|
||||
* \param value set the traced bool to a new value
|
||||
*/
|
||||
void SetValue (bool value);
|
||||
|
||||
/**
|
||||
* \brief Set a probe value by its name in the Config system
|
||||
*
|
||||
* \param path Config path to access the probe
|
||||
* \param value set the traced bool to a new value
|
||||
*/
|
||||
static void SetValueByPath (std::string path, bool value);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source attribute provided by a given object
|
||||
*
|
||||
* \param traceSource the name of the attribute TraceSource to connect to
|
||||
* \param obj ns3::Object to connect to
|
||||
* \return true if the trace source was successfully connected
|
||||
*/
|
||||
virtual bool ConnectByObject (std::string traceSource, Ptr<Object> obj);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source provided by a config path
|
||||
*
|
||||
* \param path Config path to bind to
|
||||
*
|
||||
* Note, if an invalid path is provided, the probe will not be connected
|
||||
* to anything.
|
||||
*/
|
||||
virtual void ConnectByPath (std::string path);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Method to connect to an underlying ns3::TraceSource of type bool
|
||||
*
|
||||
* \param oldData previous value of the bool
|
||||
* \param newData new value of the bool
|
||||
*
|
||||
* \internal
|
||||
*/
|
||||
void TraceSink (bool oldData, bool newData);
|
||||
|
||||
TracedValue<bool> m_output;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // BOOL_PROBE_H
|
||||
96
src/stats/model/data-collection-object.cc
Normal file
96
src/stats/model/data-collection-object.cc
Normal file
@@ -0,0 +1,96 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*/
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/boolean.h"
|
||||
|
||||
#include "data-collection-object.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("DataCollectionObject");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (DataCollectionObject);
|
||||
|
||||
TypeId
|
||||
DataCollectionObject::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::DataCollectionObject")
|
||||
.SetParent<Object> ()
|
||||
.AddConstructor<DataCollectionObject> ()
|
||||
.AddAttribute ( "Name",
|
||||
"Object's name",
|
||||
StringValue ("unnamed"), MakeStringAccessor (&DataCollectionObject::GetName, &DataCollectionObject::SetName), MakeStringChecker ())
|
||||
.AddAttribute ( "Enabled",
|
||||
"Object's enabled status",
|
||||
BooleanValue (true), MakeBooleanAccessor (&DataCollectionObject::m_enabled), MakeBooleanChecker ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
DataCollectionObject::DataCollectionObject ()
|
||||
{
|
||||
}
|
||||
|
||||
DataCollectionObject::~DataCollectionObject ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
bool
|
||||
DataCollectionObject::IsEnabled (void) const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
std::string
|
||||
DataCollectionObject::GetName (void) const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void
|
||||
DataCollectionObject::SetName (std::string name)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << name);
|
||||
for (size_t pos = name.find (" "); pos != std::string::npos; pos = name.find (" ", pos + 1, 1))
|
||||
{
|
||||
name[pos] = '_';
|
||||
}
|
||||
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
void
|
||||
DataCollectionObject::Enable (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_enabled = true;
|
||||
}
|
||||
|
||||
void
|
||||
DataCollectionObject::Disable (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
67
src/stats/model/data-collection-object.h
Normal file
67
src/stats/model/data-collection-object.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*/
|
||||
|
||||
#ifndef DATA_COLLECTION_OBJECT_H
|
||||
#define DATA_COLLECTION_OBJECT_H
|
||||
|
||||
#include <string>
|
||||
#include "ns3/object.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* Base class for data collection framework objects.
|
||||
*
|
||||
* All data collection objects have 1) a string name, and 2) enabled
|
||||
* or disabled status.
|
||||
*/
|
||||
class DataCollectionObject : public Object
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId ();
|
||||
|
||||
DataCollectionObject ();
|
||||
virtual ~DataCollectionObject ();
|
||||
|
||||
/// Set the status of an individual object.
|
||||
void Enable (void);
|
||||
void Disable (void);
|
||||
|
||||
/// Check the status of an individual object.
|
||||
virtual bool IsEnabled (void) const;
|
||||
|
||||
/// Get the object's name.
|
||||
std::string GetName (void) const;
|
||||
|
||||
/// Set the object's name. All spaces are replaced by underscores.
|
||||
void SetName (std::string name);
|
||||
|
||||
protected:
|
||||
/// Object's activation state.
|
||||
bool m_enabled;
|
||||
|
||||
/// Name of the object within the data collection framework
|
||||
std::string m_name;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // DATA_COLLECTION_OBJECT_H
|
||||
110
src/stats/model/double-probe.cc
Normal file
110
src/stats/model/double-probe.cc
Normal file
@@ -0,0 +1,110 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#include "ns3/double-probe.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("DoubleProbe");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (DoubleProbe);
|
||||
|
||||
TypeId
|
||||
DoubleProbe::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::DoubleProbe")
|
||||
.SetParent<Probe> ()
|
||||
.AddConstructor<DoubleProbe> ()
|
||||
.AddTraceSource ( "Output",
|
||||
"The double that serves as output for this probe",
|
||||
MakeTraceSourceAccessor (&DoubleProbe::m_output))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
DoubleProbe::DoubleProbe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_output = 0;
|
||||
}
|
||||
|
||||
DoubleProbe::~DoubleProbe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
double
|
||||
DoubleProbe::GetValue (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_output;
|
||||
}
|
||||
void
|
||||
DoubleProbe::SetValue (double newVal)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << newVal);
|
||||
m_output = newVal;
|
||||
}
|
||||
|
||||
void
|
||||
DoubleProbe::SetValueByPath (std::string path, double newVal)
|
||||
{
|
||||
NS_LOG_FUNCTION (path << newVal);
|
||||
Ptr<DoubleProbe> probe = Names::Find<DoubleProbe> (path);
|
||||
NS_ASSERT_MSG (probe, "Error: Can't find probe for path " << path);
|
||||
probe->SetValue (newVal);
|
||||
}
|
||||
|
||||
bool
|
||||
DoubleProbe::ConnectByObject (std::string traceSource, Ptr<Object> obj)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << traceSource << obj);
|
||||
NS_LOG_DEBUG ("Name of probe (if any) in names database: " << Names::FindPath (obj));
|
||||
bool connected = obj->TraceConnectWithoutContext (traceSource, MakeCallback (&ns3::DoubleProbe::TraceSink, this));
|
||||
return connected;
|
||||
}
|
||||
|
||||
void
|
||||
DoubleProbe::ConnectByPath (std::string path)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << path);
|
||||
NS_LOG_DEBUG ("Name of probe to search for in config database: " << path);
|
||||
Config::ConnectWithoutContext (path, MakeCallback (&ns3::DoubleProbe::TraceSink, this));
|
||||
}
|
||||
|
||||
void
|
||||
DoubleProbe::TraceSink (double oldData, double newData)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << oldData << newData);
|
||||
if (IsEnabled ())
|
||||
{
|
||||
m_output = newData;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
105
src/stats/model/double-probe.h
Normal file
105
src/stats/model/double-probe.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#ifndef DOUBLE_PROBE_H
|
||||
#define DOUBLE_PROBE_H
|
||||
|
||||
#include "ns3/probe.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This class is designed to probe an underlying ns3 TraceSource exporting
|
||||
* a double. This probe exports a trace source "Output" of type double.
|
||||
* The Output trace source emits a value when either the trace source
|
||||
* emits a new value, or when SetValue () is called.
|
||||
*
|
||||
* The current value of the probe can be polled with the GetValue ()
|
||||
* method.
|
||||
*/
|
||||
class DoubleProbe : public Probe
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId ();
|
||||
DoubleProbe ();
|
||||
virtual ~DoubleProbe ();
|
||||
|
||||
/**
|
||||
* \return the most recent value
|
||||
*/
|
||||
double GetValue (void) const;
|
||||
|
||||
/**
|
||||
* \param value set the traced double to a new value
|
||||
*/
|
||||
void SetValue (double value);
|
||||
|
||||
/**
|
||||
* \brief Set a probe value by its name in the Config system
|
||||
*
|
||||
* \param path Config path to access the probe
|
||||
* \param value set the traced double to a new value
|
||||
*/
|
||||
static void SetValueByPath (std::string path, double value);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source attribute provided by a given object
|
||||
*
|
||||
* \param traceSource the name of the attribute TraceSource to connect to
|
||||
* \param obj ns3::Object to connect to
|
||||
* \return true if the trace source was successfully connected
|
||||
*/
|
||||
virtual bool ConnectByObject (std::string traceSource, Ptr<Object> obj);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source provided by a config path
|
||||
*
|
||||
* \param path Config path to bind to
|
||||
*
|
||||
* Note, if an invalid path is provided, the probe will not be connected
|
||||
* to anything.
|
||||
*/
|
||||
virtual void ConnectByPath (std::string path);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Method to connect to an underlying ns3::TraceSource of type double
|
||||
*
|
||||
* \param oldData previous value of the double
|
||||
* \param newData new value of the double
|
||||
*
|
||||
* \internal
|
||||
*/
|
||||
void TraceSink (double oldData, double newData);
|
||||
|
||||
TracedValue<double> m_output;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // DOUBLE_PROBE_H
|
||||
661
src/stats/model/file-aggregator.cc
Normal file
661
src/stats/model/file-aggregator.cc
Normal file
@@ -0,0 +1,661 @@
|
||||
/* -*- 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 <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "file-aggregator.h"
|
||||
#include "ns3/abort.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("FileAggregator");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (FileAggregator);
|
||||
|
||||
TypeId
|
||||
FileAggregator::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::FileAggregator")
|
||||
.SetParent<DataCollectionObject> ()
|
||||
;
|
||||
|
||||
return tid;
|
||||
}
|
||||
|
||||
FileAggregator::FileAggregator (const std::string &outputFileName,
|
||||
enum FileType fileType)
|
||||
: m_outputFileName (outputFileName),
|
||||
m_fileType (fileType),
|
||||
m_hasHeadingBeenSet (false),
|
||||
m_1dFormat ("%e"),
|
||||
m_2dFormat ("%e %e"),
|
||||
m_3dFormat ("%e %e %e"),
|
||||
m_4dFormat ("%e %e %e %e"),
|
||||
m_5dFormat ("%e %e %e %e %e"),
|
||||
m_6dFormat ("%e %e %e %e %e %e"),
|
||||
m_7dFormat ("%e %e %e %e %e %e %e"),
|
||||
m_8dFormat ("%e %e %e %e %e %e %e %e"),
|
||||
m_9dFormat ("%e %e %e %e %e %e %e %e %e"),
|
||||
m_10dFormat ("%e %e %e %e %e %e %e %e %e %e")
|
||||
{
|
||||
// Set the values separator.
|
||||
switch (m_fileType)
|
||||
{
|
||||
case COMMA_SEPARATED:
|
||||
m_separator = ",";
|
||||
break;
|
||||
case TAB_SEPARATED:
|
||||
m_separator = "\t";
|
||||
break;
|
||||
default:
|
||||
// Space separated.
|
||||
m_separator = " ";
|
||||
break;
|
||||
}
|
||||
|
||||
// Open the output file.
|
||||
m_file.open (m_outputFileName.c_str ());
|
||||
}
|
||||
|
||||
FileAggregator::~FileAggregator ()
|
||||
{
|
||||
// Close the output file.
|
||||
m_file.close ();
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::SetFileType (enum FileType fileType)
|
||||
{
|
||||
m_fileType = fileType;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::SetHeading (const std::string &heading)
|
||||
{
|
||||
if (!m_hasHeadingBeenSet)
|
||||
{
|
||||
m_heading = heading;
|
||||
m_hasHeadingBeenSet = true;
|
||||
|
||||
// Print the heading to the file.
|
||||
m_file << m_heading << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Set1dFormat (const std::string &format)
|
||||
{
|
||||
m_1dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Set2dFormat (const std::string &format)
|
||||
{
|
||||
m_2dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Set3dFormat (const std::string &format)
|
||||
{
|
||||
m_3dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Set4dFormat (const std::string &format)
|
||||
{
|
||||
m_4dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Set5dFormat (const std::string &format)
|
||||
{
|
||||
m_5dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Set6dFormat (const std::string &format)
|
||||
{
|
||||
m_6dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Set7dFormat (const std::string &format)
|
||||
{
|
||||
m_7dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Set8dFormat (const std::string &format)
|
||||
{
|
||||
m_8dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Set9dFormat (const std::string &format)
|
||||
{
|
||||
m_9dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Set10dFormat (const std::string &format)
|
||||
{
|
||||
m_10dFormat = format;
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Write1d (std::string context,
|
||||
double v1)
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// Write the 1D data point to the file.
|
||||
if (m_fileType == FORMATTED)
|
||||
{
|
||||
// Initially, have the C-style string in the buffer, which
|
||||
// is terminated by a null character, be of length zero.
|
||||
char buffer[500];
|
||||
int maxBufferSize = 500;
|
||||
buffer[0] = 0;
|
||||
|
||||
// Format the value.
|
||||
int charWritten = snprintf (buffer,
|
||||
maxBufferSize,
|
||||
m_1dFormat.c_str (),
|
||||
v1);
|
||||
if (charWritten < 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Error writing value to output file");
|
||||
}
|
||||
|
||||
// Write the formatted value.
|
||||
m_file << buffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the value.
|
||||
m_file << v1 << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Write2d (std::string context,
|
||||
double v1,
|
||||
double v2)
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// Write the 2D data point to the file.
|
||||
if (m_fileType == FORMATTED)
|
||||
{
|
||||
// Initially, have the C-style string in the buffer, which
|
||||
// is terminated by a null character, be of length zero.
|
||||
char buffer[500];
|
||||
int maxBufferSize = 500;
|
||||
buffer[0] = 0;
|
||||
|
||||
// Format the values.
|
||||
int charWritten = snprintf (buffer,
|
||||
maxBufferSize,
|
||||
m_2dFormat.c_str (),
|
||||
v1,
|
||||
v2);
|
||||
if (charWritten < 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Error writing values to output file");
|
||||
}
|
||||
|
||||
// Write the formatted values.
|
||||
m_file << buffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the values with the proper separator.
|
||||
m_file << v1 << m_separator
|
||||
<< v2 << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Write3d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3)
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// Write the 3D data point to the file.
|
||||
if (m_fileType == FORMATTED)
|
||||
{
|
||||
// Initially, have the C-style string in the buffer, which
|
||||
// is terminated by a null character, be of length zero.
|
||||
char buffer[500];
|
||||
int maxBufferSize = 500;
|
||||
buffer[0] = 0;
|
||||
|
||||
// Format the values.
|
||||
int charWritten = snprintf (buffer,
|
||||
maxBufferSize,
|
||||
m_3dFormat.c_str (),
|
||||
v1,
|
||||
v2,
|
||||
v3);
|
||||
if (charWritten < 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Error writing values to output file");
|
||||
}
|
||||
|
||||
// Write the formatted values.
|
||||
m_file << buffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the values with the proper separator.
|
||||
m_file << v1 << m_separator
|
||||
<< v2 << m_separator
|
||||
<< v3 << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Write4d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4)
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// Write the 4D data point to the file.
|
||||
if (m_fileType == FORMATTED)
|
||||
{
|
||||
// Initially, have the C-style string in the buffer, which
|
||||
// is terminated by a null character, be of length zero.
|
||||
char buffer[500];
|
||||
int maxBufferSize = 500;
|
||||
buffer[0] = 0;
|
||||
|
||||
// Format the values.
|
||||
int charWritten = snprintf (buffer,
|
||||
maxBufferSize,
|
||||
m_4dFormat.c_str (),
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
v4);
|
||||
if (charWritten < 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Error writing values to output file");
|
||||
}
|
||||
|
||||
// Write the formatted values.
|
||||
m_file << buffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the values with the proper separator.
|
||||
m_file << v1 << m_separator
|
||||
<< v2 << m_separator
|
||||
<< v3 << m_separator
|
||||
<< v4 << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Write5d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5)
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// Write the 5D data point to the file.
|
||||
if (m_fileType == FORMATTED)
|
||||
{
|
||||
// Initially, have the C-style string in the buffer, which
|
||||
// is terminated by a null character, be of length zero.
|
||||
char buffer[500];
|
||||
int maxBufferSize = 500;
|
||||
buffer[0] = 0;
|
||||
|
||||
// Format the values.
|
||||
int charWritten = snprintf (buffer,
|
||||
maxBufferSize,
|
||||
m_5dFormat.c_str (),
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
v4,
|
||||
v5);
|
||||
if (charWritten < 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Error writing values to output file");
|
||||
}
|
||||
|
||||
// Write the formatted values.
|
||||
m_file << buffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the values with the proper separator.
|
||||
m_file << v1 << m_separator
|
||||
<< v2 << m_separator
|
||||
<< v3 << m_separator
|
||||
<< v4 << m_separator
|
||||
<< v5 << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Write6d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5,
|
||||
double v6)
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// Write the 6D data point to the file.
|
||||
if (m_fileType == FORMATTED)
|
||||
{
|
||||
// Initially, have the C-style string in the buffer, which
|
||||
// is terminated by a null character, be of length zero.
|
||||
char buffer[500];
|
||||
int maxBufferSize = 500;
|
||||
buffer[0] = 0;
|
||||
|
||||
// Format the values.
|
||||
int charWritten = snprintf (buffer,
|
||||
maxBufferSize,
|
||||
m_6dFormat.c_str (),
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
v4,
|
||||
v5,
|
||||
v6);
|
||||
if (charWritten < 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Error writing values to output file");
|
||||
}
|
||||
|
||||
// Write the formatted values.
|
||||
m_file << buffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the values with the proper separator.
|
||||
m_file << v1 << m_separator
|
||||
<< v2 << m_separator
|
||||
<< v3 << m_separator
|
||||
<< v4 << m_separator
|
||||
<< v5 << m_separator
|
||||
<< v6 << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Write7d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5,
|
||||
double v6,
|
||||
double v7)
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// Write the 7D data point to the file.
|
||||
if (m_fileType == FORMATTED)
|
||||
{
|
||||
// Initially, have the C-style string in the buffer, which
|
||||
// is terminated by a null character, be of length zero.
|
||||
char buffer[500];
|
||||
int maxBufferSize = 500;
|
||||
buffer[0] = 0;
|
||||
|
||||
// Format the values.
|
||||
int charWritten = snprintf (buffer,
|
||||
maxBufferSize,
|
||||
m_7dFormat.c_str (),
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
v4,
|
||||
v5,
|
||||
v6,
|
||||
v7);
|
||||
if (charWritten < 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Error writing values to output file");
|
||||
}
|
||||
|
||||
// Write the formatted values.
|
||||
m_file << buffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the values with the proper separator.
|
||||
m_file << v1 << m_separator
|
||||
<< v2 << m_separator
|
||||
<< v3 << m_separator
|
||||
<< v4 << m_separator
|
||||
<< v5 << m_separator
|
||||
<< v6 << m_separator
|
||||
<< v7 << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Write8d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5,
|
||||
double v6,
|
||||
double v7,
|
||||
double v8)
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// Write the 8D data point to the file.
|
||||
if (m_fileType == FORMATTED)
|
||||
{
|
||||
// Initially, have the C-style string in the buffer, which
|
||||
// is terminated by a null character, be of length zero.
|
||||
char buffer[500];
|
||||
int maxBufferSize = 500;
|
||||
buffer[0] = 0;
|
||||
|
||||
// Format the values.
|
||||
int charWritten = snprintf (buffer,
|
||||
maxBufferSize,
|
||||
m_8dFormat.c_str (),
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
v4,
|
||||
v5,
|
||||
v6,
|
||||
v7,
|
||||
v8);
|
||||
if (charWritten < 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Error writing values to output file");
|
||||
}
|
||||
|
||||
// Write the formatted values.
|
||||
m_file << buffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the values with the proper separator.
|
||||
m_file << v1 << m_separator
|
||||
<< v2 << m_separator
|
||||
<< v3 << m_separator
|
||||
<< v4 << m_separator
|
||||
<< v5 << m_separator
|
||||
<< v6 << m_separator
|
||||
<< v7 << m_separator
|
||||
<< v8 << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Write9d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5,
|
||||
double v6,
|
||||
double v7,
|
||||
double v8,
|
||||
double v9)
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// Write the 9D data point to the file.
|
||||
if (m_fileType == FORMATTED)
|
||||
{
|
||||
// Initially, have the C-style string in the buffer, which
|
||||
// is terminated by a null character, be of length zero.
|
||||
char buffer[500];
|
||||
int maxBufferSize = 500;
|
||||
buffer[0] = 0;
|
||||
|
||||
// Format the values.
|
||||
int charWritten = snprintf (buffer,
|
||||
maxBufferSize,
|
||||
m_9dFormat.c_str (),
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
v4,
|
||||
v5,
|
||||
v6,
|
||||
v7,
|
||||
v8,
|
||||
v9);
|
||||
if (charWritten < 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Error writing values to output file");
|
||||
}
|
||||
|
||||
// Write the formatted values.
|
||||
m_file << buffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the values with the proper separator.
|
||||
m_file << v1 << m_separator
|
||||
<< v2 << m_separator
|
||||
<< v3 << m_separator
|
||||
<< v4 << m_separator
|
||||
<< v5 << m_separator
|
||||
<< v6 << m_separator
|
||||
<< v7 << m_separator
|
||||
<< v8 << m_separator
|
||||
<< v9 << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FileAggregator::Write10d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5,
|
||||
double v6,
|
||||
double v7,
|
||||
double v8,
|
||||
double v9,
|
||||
double v10)
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
// Write the 10D data point to the file.
|
||||
if (m_fileType == FORMATTED)
|
||||
{
|
||||
// Initially, have the C-style string in the buffer, which
|
||||
// is terminated by a null character, be of length zero.
|
||||
char buffer[500];
|
||||
int maxBufferSize = 500;
|
||||
buffer[0] = 0;
|
||||
|
||||
// Format the values.
|
||||
int charWritten = snprintf (buffer,
|
||||
maxBufferSize,
|
||||
m_10dFormat.c_str (),
|
||||
v1,
|
||||
v2,
|
||||
v3,
|
||||
v4,
|
||||
v5,
|
||||
v6,
|
||||
v7,
|
||||
v8,
|
||||
v9,
|
||||
v10);
|
||||
if (charWritten < 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("Error writing values to output file");
|
||||
}
|
||||
|
||||
// Write the formatted values.
|
||||
m_file << buffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write the values with the proper separator.
|
||||
m_file << v1 << m_separator
|
||||
<< v2 << m_separator
|
||||
<< v3 << m_separator
|
||||
<< v4 << m_separator
|
||||
<< v5 << m_separator
|
||||
<< v6 << m_separator
|
||||
<< v7 << m_separator
|
||||
<< v8 << m_separator
|
||||
<< v9 << m_separator
|
||||
<< v10 << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
384
src/stats/model/file-aggregator.h
Normal file
384
src/stats/model/file-aggregator.h
Normal file
@@ -0,0 +1,384 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FILE_AGGREGATOR_H
|
||||
#define FILE_AGGREGATOR_H
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "ns3/data-collection-object.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This aggregator sends values it receives to a file.
|
||||
**/
|
||||
class FileAggregator : public DataCollectionObject
|
||||
{
|
||||
public:
|
||||
/// The type of file written by the aggregator.
|
||||
enum FileType
|
||||
{
|
||||
FORMATTED,
|
||||
SPACE_SEPARATED,
|
||||
COMMA_SEPARATED,
|
||||
TAB_SEPARATED
|
||||
};
|
||||
|
||||
static TypeId GetTypeId ();
|
||||
|
||||
/**
|
||||
* \param outputFileName name of the file to write.
|
||||
* \param fileType type of file to write.
|
||||
*
|
||||
* Constructs a file aggregator that will create a file named
|
||||
* outputFileName with values printed as specified by fileType. The
|
||||
* default file type is space-separated.
|
||||
*/
|
||||
FileAggregator (const std::string &outputFileName,
|
||||
enum FileType fileType = SPACE_SEPARATED);
|
||||
|
||||
virtual ~FileAggregator ();
|
||||
|
||||
/**
|
||||
* \param fileType file type specifies the separator to use in
|
||||
* printing the file.
|
||||
*
|
||||
* \brief Set the file type to create, which determines the
|
||||
* separator to use when printing values to the file.
|
||||
*/
|
||||
void SetFileType (enum FileType fileType);
|
||||
|
||||
/**
|
||||
* \param heading the heading string.
|
||||
*
|
||||
* \brief Sets the heading string that will be printed on the first
|
||||
* line of the file.
|
||||
*
|
||||
* Note that the heading string will only be printed if it has been
|
||||
* set by calling this function.
|
||||
*/
|
||||
void SetHeading (const std::string &heading);
|
||||
|
||||
/**
|
||||
* \param format the 1D format string.
|
||||
*
|
||||
* \brief Sets the 1D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set1dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 2D format string.
|
||||
*
|
||||
* \brief Sets the 2D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set2dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 3D format string.
|
||||
*
|
||||
* \brief Sets the 3D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set3dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 4D format string.
|
||||
*
|
||||
* \brief Sets the 4D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set4dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 5D format string.
|
||||
*
|
||||
* \brief Sets the 5D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set5dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 6D format string.
|
||||
*
|
||||
* \brief Sets the 6D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set6dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 7D format string.
|
||||
*
|
||||
* \brief Sets the 7D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set7dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 8D format string.
|
||||
*
|
||||
* \brief Sets the 8D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set8dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 9D format string.
|
||||
*
|
||||
* \brief Sets the 9D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set9dFormat (const std::string &format);
|
||||
|
||||
/**
|
||||
* \param format the 10D format string.
|
||||
*
|
||||
* \brief Sets the 10D format string for the C-style sprintf()
|
||||
* function.
|
||||
*/
|
||||
void Set10dFormat (const std::string &format);
|
||||
|
||||
// Below are hooked to connectors exporting data
|
||||
// They are not overloaded since it confuses the compiler when made
|
||||
// into callbacks
|
||||
|
||||
/**
|
||||
* \param context specifies the 1D dataset these values came from.
|
||||
* \param v1 value for the new data point.
|
||||
*
|
||||
* \brief Writes 1 value to the file.
|
||||
*/
|
||||
void Write1d (std::string context,
|
||||
double v1);
|
||||
|
||||
/**
|
||||
* \param context specifies the 2D dataset these values came from.
|
||||
* \param v1 first value for the new data point.
|
||||
* \param v2 second value for the new data point.
|
||||
*
|
||||
* \brief Writes 2 values to the file.
|
||||
*/
|
||||
void Write2d (std::string context,
|
||||
double v1,
|
||||
double v2);
|
||||
|
||||
/**
|
||||
* \param context specifies the 3D dataset these values came from.
|
||||
* \param v1 first value for the new data point.
|
||||
* \param v2 second value for the new data point.
|
||||
* \param v3 third value for the new data point.
|
||||
*
|
||||
* \brief Writes 3 values to the file.
|
||||
*/
|
||||
void Write3d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3);
|
||||
|
||||
/**
|
||||
* \param context specifies the 4D dataset these values came from.
|
||||
* \param v1 first value for the new data point.
|
||||
* \param v2 second value for the new data point.
|
||||
* \param v3 third value for the new data point.
|
||||
* \param v4 fourth value for the new data point.
|
||||
*
|
||||
* \brief Writes 4 values to the file.
|
||||
*/
|
||||
void Write4d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4);
|
||||
|
||||
/**
|
||||
* \param context specifies the 5D dataset these values came from.
|
||||
* \param v1 first value for the new data point.
|
||||
* \param v2 second value for the new data point.
|
||||
* \param v3 third value for the new data point.
|
||||
* \param v4 fourth value for the new data point.
|
||||
* \param v5 fifth value for the new data point.
|
||||
*
|
||||
* \brief Writes 5 values to the file.
|
||||
*/
|
||||
void Write5d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5);
|
||||
|
||||
/**
|
||||
* \param context specifies the 6D dataset these values came from.
|
||||
* \param v1 first value for the new data point.
|
||||
* \param v2 second value for the new data point.
|
||||
* \param v3 third value for the new data point.
|
||||
* \param v4 fourth value for the new data point.
|
||||
* \param v5 fifth value for the new data point.
|
||||
* \param v6 sixth value for the new data point.
|
||||
*
|
||||
* \brief Writes 6 values to the file.
|
||||
*/
|
||||
void Write6d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5,
|
||||
double v6);
|
||||
|
||||
/**
|
||||
* \param context specifies the 7D dataset these values came from.
|
||||
* \param v1 first value for the new data point.
|
||||
* \param v2 second value for the new data point.
|
||||
* \param v3 third value for the new data point.
|
||||
* \param v4 fourth value for the new data point.
|
||||
* \param v5 fifth value for the new data point.
|
||||
* \param v6 sixth value for the new data point.
|
||||
* \param v7 seventh value for the new data point.
|
||||
*
|
||||
* \brief Writes 7 values to the file.
|
||||
*/
|
||||
void Write7d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5,
|
||||
double v6,
|
||||
double v7);
|
||||
|
||||
/**
|
||||
* \param context specifies the 8D dataset these values came from.
|
||||
* \param v1 first value for the new data point.
|
||||
* \param v2 second value for the new data point.
|
||||
* \param v3 third value for the new data point.
|
||||
* \param v4 fourth value for the new data point.
|
||||
* \param v5 fifth value for the new data point.
|
||||
* \param v6 sixth value for the new data point.
|
||||
* \param v7 seventh value for the new data point.
|
||||
* \param v8 eighth value for the new data point.
|
||||
*
|
||||
* \brief Writes 8 values to the file.
|
||||
*/
|
||||
void Write8d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5,
|
||||
double v6,
|
||||
double v7,
|
||||
double v8);
|
||||
|
||||
/**
|
||||
* \param context specifies the 9D dataset these values came from.
|
||||
* \param v1 first value for the new data point.
|
||||
* \param v2 second value for the new data point.
|
||||
* \param v3 third value for the new data point.
|
||||
* \param v4 fourth value for the new data point.
|
||||
* \param v5 fifth value for the new data point.
|
||||
* \param v6 sixth value for the new data point.
|
||||
* \param v7 seventh value for the new data point.
|
||||
* \param v8 eighth value for the new data point.
|
||||
* \param v9 nineth value for the new data point.
|
||||
*
|
||||
* \brief Writes 9 values to the file.
|
||||
*/
|
||||
void Write9d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5,
|
||||
double v6,
|
||||
double v7,
|
||||
double v8,
|
||||
double v9);
|
||||
|
||||
/**
|
||||
* \param context specifies the 10D dataset these values came from.
|
||||
* \param v1 first value for the new data point.
|
||||
* \param v2 second value for the new data point.
|
||||
* \param v3 third value for the new data point.
|
||||
* \param v4 fourth value for the new data point.
|
||||
* \param v5 fifth value for the new data point.
|
||||
* \param v6 sixth value for the new data point.
|
||||
* \param v7 seventh value for the new data point.
|
||||
* \param v8 eighth value for the new data point.
|
||||
* \param v9 nineth value for the new data point.
|
||||
* \param v10 tenth value for the new data point.
|
||||
*
|
||||
* \brief Writes 10 values to the file.
|
||||
*/
|
||||
void Write10d (std::string context,
|
||||
double v1,
|
||||
double v2,
|
||||
double v3,
|
||||
double v4,
|
||||
double v5,
|
||||
double v6,
|
||||
double v7,
|
||||
double v8,
|
||||
double v9,
|
||||
double v10);
|
||||
|
||||
private:
|
||||
/// The file name.
|
||||
std::string m_outputFileName;
|
||||
|
||||
/// Used to write values to the file.
|
||||
std::ofstream m_file;
|
||||
|
||||
/// Determines the kind of file written by the aggregator.
|
||||
enum FileType m_fileType;
|
||||
|
||||
/// Printed between values in the file.
|
||||
std::string m_separator;
|
||||
|
||||
/// Indicates if the heading line for the file has been set.
|
||||
bool m_hasHeadingBeenSet;
|
||||
|
||||
/// Heading line for the outputfile.
|
||||
std::string m_heading;
|
||||
|
||||
/// Format strings for C-style sprintf() function.
|
||||
std::string m_1dFormat;
|
||||
std::string m_2dFormat;
|
||||
std::string m_3dFormat;
|
||||
std::string m_4dFormat;
|
||||
std::string m_5dFormat;
|
||||
std::string m_6dFormat;
|
||||
std::string m_7dFormat;
|
||||
std::string m_8dFormat;
|
||||
std::string m_9dFormat;
|
||||
std::string m_10dFormat;
|
||||
|
||||
}; // class FileAggregator
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // FILE_AGGREGATOR_H
|
||||
148
src/stats/model/get-wildcard-matches.cc
Normal file
148
src/stats/model/get-wildcard-matches.cc
Normal file
@@ -0,0 +1,148 @@
|
||||
/* -*- 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 <string>
|
||||
#include <vector>
|
||||
#include "get-wildcard-matches.h"
|
||||
#include "ns3/assert.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
std::string
|
||||
GetWildcardMatches (const std::string &configPath,
|
||||
const std::string &matchedPath,
|
||||
const std::string &wildcardSeparator)
|
||||
{
|
||||
// If the Config path is just "*", return the whole matched path.
|
||||
if (configPath == "*")
|
||||
{
|
||||
return matchedPath;
|
||||
}
|
||||
|
||||
std::vector<std::string> nonWildcardTokens;
|
||||
std::vector<std::size_t> nonWildcardTokenPositions;
|
||||
|
||||
size_t nonWildcardTokenCount;
|
||||
size_t wildcardCount = 0;
|
||||
|
||||
// Get the non-wildcard tokens from the Config path.
|
||||
size_t tokenStart;
|
||||
size_t asterisk = -1;
|
||||
do
|
||||
{
|
||||
// Find the non-wildcard token.
|
||||
tokenStart = asterisk + 1;
|
||||
asterisk = configPath.find ("*", tokenStart);
|
||||
|
||||
// If a wildcard character was found, increment this counter.
|
||||
if (asterisk != std::string::npos)
|
||||
{
|
||||
wildcardCount++;
|
||||
}
|
||||
|
||||
// Save this non-wildcard token.
|
||||
nonWildcardTokens.push_back (configPath.substr (tokenStart, asterisk - tokenStart));
|
||||
}
|
||||
while (asterisk != std::string::npos);
|
||||
|
||||
// If there are no wildcards, return an empty string.
|
||||
if (wildcardCount == 0)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
// Set the number of non-wildcard tokens in the Config path.
|
||||
nonWildcardTokenCount = nonWildcardTokens.size ();
|
||||
|
||||
size_t i;
|
||||
|
||||
// Find the positions of the non-wildcard tokens in the matched path.
|
||||
size_t token;
|
||||
tokenStart = 0;
|
||||
for (i = 0; i < nonWildcardTokenCount; i++)
|
||||
{
|
||||
// Look for the non-wilcard token.
|
||||
token = matchedPath.find (nonWildcardTokens[i], tokenStart);
|
||||
|
||||
// Make sure that the token is found.
|
||||
if (token == std::string::npos)
|
||||
{
|
||||
NS_ASSERT_MSG (false, "Error: non-wildcard token not found in matched path");
|
||||
}
|
||||
|
||||
// Save the position of this non-wildcard token.
|
||||
nonWildcardTokenPositions.push_back (token);
|
||||
|
||||
// Start looking for the next non-wildcard token after the end of
|
||||
// this one.
|
||||
tokenStart = token + nonWildcardTokens[i].size ();
|
||||
}
|
||||
|
||||
std::string wildcardMatches = "";
|
||||
|
||||
// Put the text matches from the matched path for each of the
|
||||
// wildcards in the Config path into a string, separated by the
|
||||
// specified separator.
|
||||
size_t wildcardMatchesSet = 0;
|
||||
size_t matchStart;
|
||||
size_t matchEnd;
|
||||
for (i = 0; i < nonWildcardTokenCount; i++)
|
||||
{
|
||||
// Find the start and end of this wildcard match.
|
||||
matchStart = nonWildcardTokenPositions[i] + nonWildcardTokens[i].size ();
|
||||
if (i != nonWildcardTokenCount - 1)
|
||||
{
|
||||
matchEnd = nonWildcardTokenPositions[i + 1] - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
matchEnd = matchedPath.length () - 1;
|
||||
}
|
||||
|
||||
// This algorithm gets confused by zero length non-wildcard
|
||||
// tokens. So, only add this wildcard match and update the
|
||||
// counters if the match was calculated to start before it began.
|
||||
if (matchStart <= matchEnd)
|
||||
{
|
||||
// Add the wildcard match.
|
||||
wildcardMatches += matchedPath.substr (matchStart,
|
||||
matchEnd - matchStart + 1);
|
||||
|
||||
// See if all of the wilcard matches have been set.
|
||||
wildcardMatchesSet++;
|
||||
if (wildcardMatchesSet == wildcardCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If there are still more to set, add the separator to
|
||||
// the end of the one just added.
|
||||
wildcardMatches += wildcardSeparator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the wildcard matches.
|
||||
return wildcardMatches;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
44
src/stats/model/get-wildcard-matches.h
Normal file
44
src/stats/model/get-wildcard-matches.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* -*- 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 GET_WILDCARD_MATCHES_H
|
||||
#define GET_WILDCARD_MATCHES_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \param configPath Config path to access the probe.
|
||||
* \param matchedPath the path that matched the Config path.
|
||||
* \param wildcardSeparator the text to put betwen the wildcard
|
||||
* matches. By default, a space is used.
|
||||
*
|
||||
* \brief Returns the text matches from the matched path for each of
|
||||
* the wildcards in the Config path, separated by the wild card
|
||||
* separator.
|
||||
*/
|
||||
std::string GetWildcardMatches (const std::string &configPath,
|
||||
const std::string &matchedPath,
|
||||
const std::string &wildcardSeparator = " ");
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // GET_WILDCARD_MATCHES_H
|
||||
327
src/stats/model/gnuplot-aggregator.cc
Normal file
327
src/stats/model/gnuplot-aggregator.cc
Normal file
@@ -0,0 +1,327 @@
|
||||
/* -*- 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 <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "gnuplot-aggregator.h"
|
||||
#include "ns3/abort.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("GnuplotAggregator");
|
||||
NS_OBJECT_ENSURE_REGISTERED (GnuplotAggregator);
|
||||
|
||||
TypeId
|
||||
GnuplotAggregator::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::GnuplotAggregator")
|
||||
.SetParent<DataCollectionObject> ()
|
||||
;
|
||||
|
||||
return tid;
|
||||
}
|
||||
|
||||
GnuplotAggregator::GnuplotAggregator (const std::string &outputFileNameWithoutExtension)
|
||||
: m_outputFileNameWithoutExtension (outputFileNameWithoutExtension),
|
||||
m_graphicsFileName (m_outputFileNameWithoutExtension + ".png"),
|
||||
m_title ("Data Values"),
|
||||
m_xLegend ("X Values"),
|
||||
m_yLegend ("Y Values"),
|
||||
m_titleSet (false),
|
||||
m_xAndYLegendsSet (false),
|
||||
m_gnuplot (m_graphicsFileName)
|
||||
{
|
||||
}
|
||||
|
||||
GnuplotAggregator::~GnuplotAggregator ()
|
||||
{
|
||||
// Give any warnings that should be issued.
|
||||
if (!m_titleSet)
|
||||
{
|
||||
NS_LOG_UNCOND ("Warning: The plot title was not set for the gnuplot aggregator");
|
||||
}
|
||||
if (!m_xAndYLegendsSet)
|
||||
{
|
||||
NS_LOG_UNCOND ("Warning: The axis legends were not set for the gnuplot aggregator");
|
||||
}
|
||||
|
||||
std::string dataFileName = m_outputFileNameWithoutExtension + ".dat";
|
||||
std::string plotFileName = m_outputFileNameWithoutExtension + ".plt";
|
||||
std::string scriptFileName = m_outputFileNameWithoutExtension + ".sh";
|
||||
|
||||
// Open the gnuplot plot and data files.
|
||||
std::ofstream plotFile;
|
||||
plotFile.open (plotFileName.c_str ());
|
||||
std::ofstream dataFile;
|
||||
dataFile.open (dataFileName.c_str ());
|
||||
|
||||
// Skip any NaN's that appear in data.
|
||||
m_gnuplot.AppendExtra ("set datafile missing \"-nan\"");
|
||||
|
||||
// Write the gnuplot plot and data files.
|
||||
m_gnuplot.GenerateOutput (plotFile, dataFile, dataFileName);
|
||||
|
||||
// Close the gnuplot plot and data files.
|
||||
plotFile.close ();
|
||||
dataFile.close ();
|
||||
|
||||
// Open the shell script file.
|
||||
std::ofstream scriptFile;
|
||||
scriptFile.open (scriptFileName.c_str ());
|
||||
|
||||
// Write the shell script file.
|
||||
scriptFile << "#!/bin/sh" << std::endl;
|
||||
scriptFile << std::endl;
|
||||
scriptFile << "gnuplot " << plotFileName << std::endl;
|
||||
|
||||
// Close the shell script file.
|
||||
scriptFile.close ();
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Write2d (std::string context, double x, double y)
|
||||
{
|
||||
if (m_2dDatasetMap.count (context) == 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That 2D data set has not been added");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
// Add this 2D data point to its dataset.
|
||||
m_2dDatasetMap[context].Add (x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Write2dWithXErrorDelta (std::string context,
|
||||
double x,
|
||||
double y,
|
||||
double errorDelta)
|
||||
{
|
||||
// See if this dataset has been added.
|
||||
if (m_2dDatasetMap.count (context) == 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That 2D data set has not been added");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
// Add this 2D data point with its error bar to its dataset.
|
||||
m_2dDatasetMap[context].Add (x, y, errorDelta);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Write2dWithYErrorDelta (std::string context,
|
||||
double x,
|
||||
double y,
|
||||
double errorDelta)
|
||||
{
|
||||
// See if this dataset has been added.
|
||||
if (m_2dDatasetMap.count (context) == 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That 2D data set has not been added");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
// Add this 2D data point with its error bar to its dataset.
|
||||
m_2dDatasetMap[context].Add (x, y, errorDelta);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Write2dWithXYErrorDelta (std::string context,
|
||||
double x,
|
||||
double y,
|
||||
double xErrorDelta,
|
||||
double yErrorDelta)
|
||||
{
|
||||
// See if this dataset has been added.
|
||||
if (m_2dDatasetMap.count (context) == 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That 2D data set has not been added");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
// Add this 2D data point with its error bar to its dataset.
|
||||
m_2dDatasetMap[context].Add (x, y, xErrorDelta, yErrorDelta);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::SetTerminal (const std::string &terminal)
|
||||
{
|
||||
// Change the extension for the graphics file.
|
||||
m_graphicsFileName = m_outputFileNameWithoutExtension + "." + terminal;
|
||||
|
||||
// Update the gnuplot, too.
|
||||
m_gnuplot.SetTerminal (terminal);
|
||||
m_gnuplot.SetOutputFilename (m_graphicsFileName);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::SetTitle (const std::string &title)
|
||||
{
|
||||
m_gnuplot.SetTitle (title);
|
||||
m_titleSet = true;
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::SetLegend (const std::string &xLegend, const std::string &yLegend)
|
||||
{
|
||||
m_gnuplot.SetLegend (xLegend, yLegend);
|
||||
m_xAndYLegendsSet = true;
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::SetExtra (const std::string &extra)
|
||||
{
|
||||
m_gnuplot.SetExtra (extra);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::AppendExtra (const std::string &extra)
|
||||
{
|
||||
m_gnuplot.AppendExtra (extra);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Add2dDataset (const std::string &dataset, const std::string &title)
|
||||
{
|
||||
// See if this dataset had already been added.
|
||||
if (m_2dDatasetMap.count (dataset) > 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That 2D data set has already been added");
|
||||
}
|
||||
|
||||
// Add this dataset to the map so that its values can be saved.
|
||||
Gnuplot2dDataset gnuplot2dDataset (title);
|
||||
m_2dDatasetMap[dataset] = gnuplot2dDataset;
|
||||
|
||||
// Add this dataset to the plot so that its values can be plotted.
|
||||
m_gnuplot.AddDataset (m_2dDatasetMap[dataset]);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Set2dDatasetDefaultExtra (const std::string &extra)
|
||||
{
|
||||
Gnuplot2dDataset::SetDefaultExtra (extra);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Set2dDatasetExtra (const std::string &dataset, const std::string &extra)
|
||||
{
|
||||
if (m_2dDatasetMap.count (dataset) == 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That 2D data set has not been added");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the extra parameters for the dataset.
|
||||
m_2dDatasetMap[dataset].SetExtra (extra);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Write2dDatasetEmptyLine (const std::string &dataset)
|
||||
{
|
||||
if (m_2dDatasetMap.count (dataset) == 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That 2D data set has not been added");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
// Add an empty line to the dataset.
|
||||
m_2dDatasetMap[dataset].AddEmptyLine ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Set2dDatasetDefaultStyle (enum Gnuplot2dDataset::Style style)
|
||||
{
|
||||
Gnuplot2dDataset::SetDefaultStyle (style);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Set2dDatasetStyle (const std::string &dataset, enum Gnuplot2dDataset::Style style)
|
||||
{
|
||||
if (m_2dDatasetMap.count (dataset) == 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That 2D data set has not been added");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the style for the dataset.
|
||||
m_2dDatasetMap[dataset].SetStyle (style);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Set2dDatasetDefaultErrorBars (enum Gnuplot2dDataset::ErrorBars errorBars)
|
||||
{
|
||||
Gnuplot2dDataset::SetDefaultErrorBars (errorBars);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::Set2dDatasetErrorBars (const std::string &dataset, enum Gnuplot2dDataset::ErrorBars errorBars)
|
||||
{
|
||||
if (m_2dDatasetMap.count (dataset) == 0)
|
||||
{
|
||||
NS_ABORT_MSG ("That 2D data set has not been added");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the error bars for the dataset.
|
||||
m_2dDatasetMap[dataset].SetErrorBars (errorBars);
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotAggregator::SetKeyLocation (enum GnuplotAggregator::KeyLocation keyLocation)
|
||||
{
|
||||
// Set the specifed key location.
|
||||
switch (keyLocation)
|
||||
{
|
||||
case NO_KEY:
|
||||
m_gnuplot.AppendExtra ("set key off");
|
||||
break;
|
||||
case KEY_ABOVE:
|
||||
m_gnuplot.AppendExtra ("set key outside center above");
|
||||
break;
|
||||
case KEY_BELOW:
|
||||
m_gnuplot.AppendExtra ("set key outside center below");
|
||||
break;
|
||||
default:
|
||||
m_gnuplot.AppendExtra ("set key inside");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
296
src/stats/model/gnuplot-aggregator.h
Normal file
296
src/stats/model/gnuplot-aggregator.h
Normal file
@@ -0,0 +1,296 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GNUPLOT_AGGREGATOR_H
|
||||
#define GNUPLOT_AGGREGATOR_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "ns3/gnuplot.h"
|
||||
#include "ns3/data-collection-object.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This aggregator produces output used to make gnuplot plots.
|
||||
**/
|
||||
class GnuplotAggregator : public DataCollectionObject
|
||||
{
|
||||
public:
|
||||
/// The location of the key in the plot.
|
||||
enum KeyLocation
|
||||
{
|
||||
NO_KEY,
|
||||
KEY_INSIDE,
|
||||
KEY_ABOVE,
|
||||
KEY_BELOW
|
||||
};
|
||||
|
||||
static TypeId GetTypeId ();
|
||||
|
||||
/**
|
||||
* \param outputFileNameWithoutExtension name of gnuplot related
|
||||
* files to write with no extension
|
||||
*
|
||||
* Constructs a gnuplot file aggregator that will create a space
|
||||
* separated gnuplot data file named outputFileNameWithoutExtension
|
||||
* + ".dat", a gnuplot control file named
|
||||
* outputFileNameWithoutExtension + ".plt", and a shell script to
|
||||
* generate the gnuplot named outputFileNameWithoutExtension +
|
||||
* ".sh".
|
||||
*/
|
||||
GnuplotAggregator (const std::string &outputFileNameWithoutExtension);
|
||||
|
||||
virtual ~GnuplotAggregator ();
|
||||
|
||||
// Below are hooked to connectors exporting data
|
||||
// They are not overloaded since it confuses the compiler when made
|
||||
// into callbacks
|
||||
|
||||
/**
|
||||
* \param context specifies the gnuplot 2D dataset for these values
|
||||
* \param x x coordinate for the new data point
|
||||
* \param y y coordinate for the new data point
|
||||
*
|
||||
* \brief Writes a 2D value to a 2D gnuplot dataset.
|
||||
*
|
||||
* Use this method with error bar style NONE.
|
||||
*/
|
||||
void Write2d (std::string context, double x, double y);
|
||||
|
||||
/**
|
||||
* \param context specifies the gnuplot 2D dataset for these values
|
||||
* \param x x coordinate for the new data point
|
||||
* \param y y coordinate for the new data point
|
||||
* \param errorDelta x data point uncertainty
|
||||
*
|
||||
* \brief Writes a 2D value to a 2D gnuplot dataset with error bars
|
||||
* in the x direction.
|
||||
*
|
||||
* Use this method with error bar style X.
|
||||
*/
|
||||
void Write2dWithXErrorDelta (std::string context,
|
||||
double x,
|
||||
double y,
|
||||
double errorDelta);
|
||||
|
||||
/**
|
||||
* \param context specifies the gnuplot 2D dataset for these values
|
||||
* \param x x coordinate for the new data point
|
||||
* \param y y coordinate for the new data point
|
||||
* \param errorDelta y data point uncertainty
|
||||
*
|
||||
* \brief Writes a 2D value to a 2D gnuplot dataset with error bars
|
||||
* in the y direction.
|
||||
*
|
||||
* Use this method with error bar style Y.
|
||||
*/
|
||||
void Write2dWithYErrorDelta (std::string context,
|
||||
double x,
|
||||
double y,
|
||||
double errorDelta);
|
||||
|
||||
/**
|
||||
* \param context specifies the gnuplot 2D dataset for these values
|
||||
* \param x x coordinate for the new data point
|
||||
* \param y y coordinate for the new data point
|
||||
* \param xErrorDelta x data point uncertainty
|
||||
* \param yErrorDelta y data point uncertainty
|
||||
*
|
||||
* \brief Writes a 2D value to a 2D gnuplot dataset with error bars
|
||||
* in the x and y directions.
|
||||
*
|
||||
* Use this method with error bar style XY.
|
||||
*/
|
||||
void Write2dWithXYErrorDelta (std::string context,
|
||||
double x,
|
||||
double y,
|
||||
double xErrorDelta,
|
||||
double yErrorDelta);
|
||||
|
||||
// Methods to configure the plot
|
||||
|
||||
/**
|
||||
* \param terminal terminal setting string for output. The default terminal
|
||||
* string is "png"
|
||||
*/
|
||||
void SetTerminal (const std::string &terminal);
|
||||
|
||||
/**
|
||||
* \param title set new plot title string to use for this plot.
|
||||
*/
|
||||
void SetTitle (const std::string &title);
|
||||
|
||||
/**
|
||||
* \param xLegend the legend for the x horizontal axis
|
||||
* \param yLegend the legend for the y vertical axis
|
||||
*/
|
||||
void SetLegend (const std::string &xLegend, const std::string &yLegend);
|
||||
|
||||
/**
|
||||
* \param extra set extra gnuplot directive for output.
|
||||
*/
|
||||
void SetExtra (const std::string &extra);
|
||||
|
||||
/**
|
||||
* \param extra append extra gnuplot directive for output.
|
||||
*/
|
||||
void AppendExtra (const std::string &extra);
|
||||
|
||||
// Methods for datasets
|
||||
|
||||
/**
|
||||
* \param dataset the gnuplot 2D dataset to be plotted.
|
||||
* \param title the title to be associated to this dataset.
|
||||
*
|
||||
* \brief Adds a 2D dataset to the plot.
|
||||
*
|
||||
* Creates an empty dataset. Usually, the dataset's title is
|
||||
* displayed in the legend box.
|
||||
*
|
||||
* The string in dataset should match the context for the Collector
|
||||
* it is connected to.
|
||||
*/
|
||||
void Add2dDataset (const std::string &dataset, const std::string &title);
|
||||
|
||||
/**
|
||||
* \param extra extra formatting
|
||||
*
|
||||
* \brief Change extra formatting style parameters for newly created
|
||||
* objects.
|
||||
*/
|
||||
static void Set2dDatasetDefaultExtra (const std::string &extra);
|
||||
|
||||
/**
|
||||
* \param dataset the gnuplot 2D dataset to be plotted.
|
||||
* \param extra extra formatting
|
||||
*
|
||||
* \brief Add extra formatting parameters to this dataset.
|
||||
*
|
||||
* The string in dataset should match the context for the Collector
|
||||
* it is connected to.
|
||||
*/
|
||||
void Set2dDatasetExtra (const std::string &dataset, const std::string &extra);
|
||||
|
||||
/**
|
||||
* \param dataset the gnuplot 2D dataset to be plotted.
|
||||
*
|
||||
* \brief Add an empty line in the data output sequence.
|
||||
*
|
||||
* Writes an empty line in the plot data, which breaks continuous
|
||||
* lines and does other things in the output.
|
||||
*
|
||||
* The string in dataset should match the context for the Collector
|
||||
* it is connected to.
|
||||
*/
|
||||
void Write2dDatasetEmptyLine (const std::string &dataset);
|
||||
|
||||
/**
|
||||
* \param style the style of plotting to use for newly created datasets.
|
||||
*
|
||||
* \brief Change default style for all newly created objects.
|
||||
*/
|
||||
static void Set2dDatasetDefaultStyle (enum Gnuplot2dDataset::Style style);
|
||||
|
||||
/**
|
||||
* \param dataset the gnuplot 2D dataset to be plotted.
|
||||
* \param style the style of plotting to use for this dataset.
|
||||
*
|
||||
* \brief Set the style of plotting to use for this dataset.
|
||||
*
|
||||
* The string in dataset should match the context for the Collector
|
||||
* it is connected to.
|
||||
*/
|
||||
void Set2dDatasetStyle (const std::string &dataset, enum Gnuplot2dDataset::Style style);
|
||||
|
||||
/**
|
||||
* \param errorBars the style of errorbars to use for newly created datasets.
|
||||
*
|
||||
* \brief Change default errorbars style for all newly created objects.
|
||||
*/
|
||||
static void Set2dDatasetDefaultErrorBars (enum Gnuplot2dDataset::ErrorBars errorBars);
|
||||
|
||||
/**
|
||||
* \param dataset the gnuplot 2D dataset to be plotted.
|
||||
* \param errorBars the style of errorbars to display.
|
||||
*
|
||||
* \brief Set the error bars to use for this dataset.
|
||||
*
|
||||
* If you use any style other than none, you need
|
||||
* to make sure you store the delta information in
|
||||
* this dataset with the right GnuplotDataset::Add
|
||||
* method.
|
||||
*
|
||||
* The string in dataset should match the context for the Collector
|
||||
* it is connected to.
|
||||
*/
|
||||
void Set2dDatasetErrorBars (const std::string &dataset, enum Gnuplot2dDataset::ErrorBars errorBars);
|
||||
|
||||
/**
|
||||
* \param keyLocation the location of the key in the plot.
|
||||
*
|
||||
* \brief Set the location of the key in the plot.
|
||||
*/
|
||||
void SetKeyLocation (enum KeyLocation keyLocation);
|
||||
|
||||
private:
|
||||
/// The output file name without any extension.
|
||||
std::string m_outputFileNameWithoutExtension;
|
||||
|
||||
/// The graphics file name with its extension.
|
||||
std::string m_graphicsFileName;
|
||||
|
||||
/// The title.
|
||||
std::string m_title;
|
||||
|
||||
/// The terminal.
|
||||
std::string m_terminal;
|
||||
|
||||
/// The x legend.
|
||||
std::string m_xLegend;
|
||||
|
||||
/// The y legend.
|
||||
std::string m_yLegend;
|
||||
|
||||
/// The extra gnuplot command that will be added to the gnuplot
|
||||
/// control statements.
|
||||
std::string m_extra;
|
||||
|
||||
/// Set equal to true after setting the title.
|
||||
bool m_titleSet;
|
||||
|
||||
/// Set equal to true after setting the x and y legends.
|
||||
bool m_xAndYLegendsSet;
|
||||
|
||||
/// Used to create gnuplot files.
|
||||
Gnuplot m_gnuplot;
|
||||
|
||||
/// Maps context strings to 2D datasets.
|
||||
std::map<std::string, Gnuplot2dDataset> m_2dDatasetMap;
|
||||
|
||||
}; // class GnuplotAggregator
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // GNUPLOT_AGGREGATOR_H
|
||||
@@ -50,17 +50,30 @@ struct GnuplotDataset::Data
|
||||
virtual std::string GetCommand () const = 0;
|
||||
|
||||
/**
|
||||
* Prints the plot description used as argument to (s)plot. Either the
|
||||
* function expression or a datafile description. Should include m_title and
|
||||
* m_extra in the output.
|
||||
* Prints the plot description used as argument to (s)plot. Either
|
||||
* the function expression or a datafile description. Should include
|
||||
* m_title and m_extra in the output.
|
||||
*
|
||||
* If more than one output file is being generated, i.e. separate
|
||||
* data and control files, then the index for the current dataset
|
||||
* and the name for the data file are also included.
|
||||
*/
|
||||
virtual void PrintExpression (std::ostream &os) const = 0;
|
||||
virtual void PrintExpression (std::ostream &os,
|
||||
bool generateOneOutputFile,
|
||||
unsigned int dataFileDatasetIndex,
|
||||
std::string &dataFileName) const = 0;
|
||||
|
||||
/**
|
||||
* Print the inline data file contents trailing the plot command. Empty for
|
||||
* functions.
|
||||
*/
|
||||
virtual void PrintDatafile (std::ostream &os) const = 0;
|
||||
virtual void PrintDataFile (std::ostream &os, bool generateOneOutputFile) const = 0;
|
||||
|
||||
/**
|
||||
* Checks to see if this GnuplotDataset is empty.
|
||||
* \return indicates if this GnuplotDataset is empty.
|
||||
*/
|
||||
virtual bool IsEmpty () const = 0;
|
||||
};
|
||||
|
||||
GnuplotDataset::Data::Data(const std::string& title)
|
||||
@@ -142,8 +155,12 @@ struct Gnuplot2dDataset::Data2d : public GnuplotDataset::Data
|
||||
Data2d(const std::string& title);
|
||||
|
||||
virtual std::string GetCommand () const;
|
||||
virtual void PrintExpression (std::ostream &os) const;
|
||||
virtual void PrintDatafile (std::ostream &os) const;
|
||||
virtual void PrintExpression (std::ostream &os,
|
||||
bool generateOneOutputFile,
|
||||
unsigned int dataFileDatasetIndex,
|
||||
std::string &dataFileName) const;
|
||||
virtual void PrintDataFile (std::ostream &os, bool generateOneOutputFile) const;
|
||||
virtual bool IsEmpty () const;
|
||||
};
|
||||
|
||||
Gnuplot2dDataset::Data2d::Data2d(const std::string& title)
|
||||
@@ -160,12 +177,24 @@ Gnuplot2dDataset::Data2d::GetCommand () const
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot2dDataset::Data2d::PrintExpression (std::ostream &os) const
|
||||
Gnuplot2dDataset::Data2d::PrintExpression (std::ostream &os,
|
||||
bool generateOneOutputFile,
|
||||
unsigned int dataFileDatasetIndex,
|
||||
std::string &dataFileName) const
|
||||
{
|
||||
os << "'-' ";
|
||||
// Print the appropriate thing based on whether separate output and
|
||||
// date files are being generated.
|
||||
if (generateOneOutputFile)
|
||||
{
|
||||
os << "\"-\" ";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "\"" << dataFileName << "\" index " << dataFileDatasetIndex;
|
||||
}
|
||||
|
||||
if (m_title.size ())
|
||||
os << " title '" << m_title << "'";
|
||||
os << " title \"" << m_title << "\"";
|
||||
|
||||
switch (m_style) {
|
||||
case LINES:
|
||||
@@ -227,7 +256,7 @@ Gnuplot2dDataset::Data2d::PrintExpression (std::ostream &os) const
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot2dDataset::Data2d::PrintDatafile (std::ostream &os) const
|
||||
Gnuplot2dDataset::Data2d::PrintDataFile (std::ostream &os, bool generateOneOutputFile) const
|
||||
{
|
||||
for (PointSet::const_iterator i = m_pointset.begin ();
|
||||
i != m_pointset.end (); ++i)
|
||||
@@ -252,7 +281,24 @@ Gnuplot2dDataset::Data2d::PrintDatafile (std::ostream &os) const
|
||||
break;
|
||||
}
|
||||
}
|
||||
os << "e" << std::endl;
|
||||
|
||||
// Print the appropriate thing based on whether separate output and
|
||||
// date files are being generated.
|
||||
if (generateOneOutputFile)
|
||||
{
|
||||
os << "e" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
os << std::endl;
|
||||
os << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Gnuplot2dDataset::Data2d::IsEmpty () const
|
||||
{
|
||||
return (m_pointset.size () == 0);
|
||||
}
|
||||
|
||||
// --- Gnuplot2dDataset ---------------------------------------------------- //
|
||||
@@ -352,8 +398,12 @@ struct Gnuplot2dFunction::Function2d : public GnuplotDataset::Data
|
||||
Function2d(const std::string& title, const std::string& function);
|
||||
|
||||
virtual std::string GetCommand () const;
|
||||
virtual void PrintExpression (std::ostream &os) const;
|
||||
virtual void PrintDatafile (std::ostream &os) const;
|
||||
virtual void PrintExpression (std::ostream &os,
|
||||
bool generateOneOutputFile,
|
||||
unsigned int dataFileDatasetIndex,
|
||||
std::string &dataFileName) const;
|
||||
virtual void PrintDataFile (std::ostream &os, bool generateOneOutputFile) const;
|
||||
virtual bool IsEmpty () const;
|
||||
};
|
||||
|
||||
Gnuplot2dFunction::Function2d::Function2d(const std::string& title, const std::string& function)
|
||||
@@ -369,22 +419,31 @@ Gnuplot2dFunction::Function2d::GetCommand () const
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot2dFunction::Function2d::PrintExpression (std::ostream &os) const
|
||||
Gnuplot2dFunction::Function2d::PrintExpression (std::ostream &os,
|
||||
bool generateOneOutputFile,
|
||||
unsigned int dataFileDatasetIndex,
|
||||
std::string &dataFileName) const
|
||||
{
|
||||
os << m_function;
|
||||
|
||||
if (m_title.size ())
|
||||
os << " title '" << m_title << "'";
|
||||
os << " title \"" << m_title << "\"";
|
||||
|
||||
if (m_extra.size ())
|
||||
os << " " << m_extra;
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot2dFunction::Function2d::PrintDatafile (std::ostream &os) const
|
||||
Gnuplot2dFunction::Function2d::PrintDataFile (std::ostream &os, bool generateOneOutputFile) const
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Gnuplot2dFunction::Function2d::IsEmpty () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- Gnuplot2dFunction --------------------------------------------------- //
|
||||
|
||||
Gnuplot2dFunction::Gnuplot2dFunction (const std::string& title, const std::string& function)
|
||||
@@ -414,8 +473,12 @@ struct Gnuplot3dDataset::Data3d : public GnuplotDataset::Data
|
||||
Data3d(const std::string& title);
|
||||
|
||||
virtual std::string GetCommand () const;
|
||||
virtual void PrintExpression (std::ostream &os) const;
|
||||
virtual void PrintDatafile (std::ostream &os) const;
|
||||
virtual void PrintExpression (std::ostream &os,
|
||||
bool generateOneOutputFile,
|
||||
unsigned int dataFileDatasetIndex,
|
||||
std::string &dataFileName) const;
|
||||
virtual void PrintDataFile (std::ostream &os, bool generateOneOutputFile) const;
|
||||
virtual bool IsEmpty () const;
|
||||
};
|
||||
|
||||
Gnuplot3dDataset::Data3d::Data3d(const std::string& title)
|
||||
@@ -431,22 +494,25 @@ Gnuplot3dDataset::Data3d::GetCommand () const
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot3dDataset::Data3d::PrintExpression (std::ostream &os) const
|
||||
Gnuplot3dDataset::Data3d::PrintExpression (std::ostream &os,
|
||||
bool generateOneOutputFile,
|
||||
unsigned int dataFileDatasetIndex,
|
||||
std::string &dataFileName) const
|
||||
{
|
||||
os << "'-' ";
|
||||
os << "\"-\" ";
|
||||
|
||||
if (m_style.size ())
|
||||
os << " " << m_style;
|
||||
|
||||
if (m_title.size ())
|
||||
os << " title '" << m_title << "'";
|
||||
os << " title \"" << m_title << "\"";
|
||||
|
||||
if (m_extra.size ())
|
||||
os << " " << m_extra;
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot3dDataset::Data3d::PrintDatafile (std::ostream &os) const
|
||||
Gnuplot3dDataset::Data3d::PrintDataFile (std::ostream &os, bool generateOneOutputFile) const
|
||||
{
|
||||
for (PointSet::const_iterator i = m_pointset.begin ();
|
||||
i != m_pointset.end (); ++i)
|
||||
@@ -461,6 +527,12 @@ Gnuplot3dDataset::Data3d::PrintDatafile (std::ostream &os) const
|
||||
os << "e" << std::endl;
|
||||
}
|
||||
|
||||
bool
|
||||
Gnuplot3dDataset::Data3d::IsEmpty () const
|
||||
{
|
||||
return (m_pointset.size () == 0);
|
||||
}
|
||||
|
||||
// --- Gnuplot3dDataset ---------------------------------------------------- //
|
||||
|
||||
std::string Gnuplot3dDataset::m_defaultStyle = "";
|
||||
@@ -514,8 +586,12 @@ struct Gnuplot3dFunction::Function3d : public GnuplotDataset::Data
|
||||
Function3d(const std::string& title, const std::string& function);
|
||||
|
||||
virtual std::string GetCommand () const;
|
||||
virtual void PrintExpression (std::ostream &os) const;
|
||||
virtual void PrintDatafile (std::ostream &os) const;
|
||||
virtual void PrintExpression (std::ostream &os,
|
||||
bool generateOneOutputFile,
|
||||
unsigned int dataFileDatasetIndex,
|
||||
std::string &dataFileName) const;
|
||||
virtual void PrintDataFile (std::ostream &os, bool generateOneOutputFile) const;
|
||||
virtual bool IsEmpty () const;
|
||||
};
|
||||
|
||||
Gnuplot3dFunction::Function3d::Function3d(const std::string& title, const std::string& function)
|
||||
@@ -531,22 +607,31 @@ Gnuplot3dFunction::Function3d::GetCommand () const
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot3dFunction::Function3d::PrintExpression (std::ostream &os) const
|
||||
Gnuplot3dFunction::Function3d::PrintExpression (std::ostream &os,
|
||||
bool generateOneOutputFile,
|
||||
unsigned int dataFileDatasetIndex,
|
||||
std::string &dataFileName) const
|
||||
{
|
||||
os << m_function;
|
||||
|
||||
if (m_title.size ())
|
||||
os << " title '" << m_title << "'";
|
||||
os << " title \"" << m_title << "\"";
|
||||
|
||||
if (m_extra.size ())
|
||||
os << " " << m_extra;
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot3dFunction::Function3d::PrintDatafile (std::ostream &os) const
|
||||
Gnuplot3dFunction::Function3d::PrintDataFile (std::ostream &os, bool generateOneOutputFile) const
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Gnuplot3dFunction::Function3d::IsEmpty () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- Gnuplot3dFunction --------------------------------------------------- //
|
||||
|
||||
Gnuplot3dFunction::Gnuplot3dFunction (const std::string& title, const std::string& function)
|
||||
@@ -565,10 +650,17 @@ Gnuplot3dFunction::SetFunction (const std::string& function)
|
||||
Gnuplot::Gnuplot (const std::string& outputFilename, const std::string& title)
|
||||
: m_outputFilename (outputFilename),
|
||||
m_terminal ( DetectTerminal (outputFilename) ),
|
||||
m_title (title)
|
||||
m_title (title),
|
||||
m_generateOneOutputFile (false),
|
||||
m_dataFileDatasetIndex (0)
|
||||
{
|
||||
}
|
||||
|
||||
void Gnuplot::SetOutputFilename (const std::string& outputFilename)
|
||||
{
|
||||
m_outputFilename = outputFilename;
|
||||
}
|
||||
|
||||
std::string Gnuplot::DetectTerminal (const std::string& filename)
|
||||
{
|
||||
std::string::size_type dotpos = filename.rfind ('.');
|
||||
@@ -623,25 +715,38 @@ Gnuplot::AddDataset (const GnuplotDataset& dataset)
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot::GenerateOutput (std::ostream &os) const
|
||||
Gnuplot::GenerateOutput (std::ostream &os)
|
||||
{
|
||||
// If this version of this function is called, it is assumed that a
|
||||
// single output file is being generated.
|
||||
m_generateOneOutputFile = true;
|
||||
|
||||
// Send the gnuplot metadata to the same stream as the data stream.
|
||||
GenerateOutput (os, os, "");
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot::GenerateOutput (std::ostream &osControl,
|
||||
std::ostream &osData,
|
||||
std::string dataFileName)
|
||||
{
|
||||
if (m_terminal.size ())
|
||||
os << "set terminal " << m_terminal << std::endl;
|
||||
osControl << "set terminal " << m_terminal << std::endl;
|
||||
|
||||
if (m_outputFilename.size ())
|
||||
os << "set output '" << m_outputFilename << "'" << std::endl;
|
||||
osControl << "set output \"" << m_outputFilename << "\"" << std::endl;
|
||||
|
||||
if (m_title.size ())
|
||||
os << "set title '" << m_title << "'" << std::endl;
|
||||
osControl << "set title \"" << m_title << "\"" << std::endl;
|
||||
|
||||
if (m_xLegend.size ())
|
||||
os << "set xlabel '" << m_xLegend << "'" << std::endl;
|
||||
osControl << "set xlabel \"" << m_xLegend << "\"" << std::endl;
|
||||
|
||||
if (m_yLegend.size ())
|
||||
os << "set ylabel '" << m_yLegend << "'" << std::endl;
|
||||
osControl << "set ylabel \"" << m_yLegend << "\"" << std::endl;
|
||||
|
||||
if (m_extra.size ())
|
||||
os << m_extra << std::endl;
|
||||
osControl << m_extra << std::endl;
|
||||
|
||||
if (m_datasets.empty ())
|
||||
return;
|
||||
@@ -658,31 +763,49 @@ Gnuplot::GenerateOutput (std::ostream &os) const
|
||||
"Cannot mix 'plot' and 'splot' GnuplotDatasets.");
|
||||
}
|
||||
|
||||
os << command << " ";
|
||||
osControl << command << " ";
|
||||
|
||||
// Print all dataset expressions
|
||||
|
||||
bool isDataEmpty;
|
||||
for (Datasets::const_iterator i = m_datasets.begin (); i != m_datasets.end ();)
|
||||
{
|
||||
i->m_data->PrintExpression (os);
|
||||
// Only print the dataset if it's not empty.
|
||||
isDataEmpty = i->m_data->IsEmpty ();
|
||||
if (!isDataEmpty)
|
||||
{
|
||||
// Print the appropriate expression based on whether we are
|
||||
// generating separate output and date files.
|
||||
i->m_data->PrintExpression (osControl,
|
||||
m_generateOneOutputFile,
|
||||
m_dataFileDatasetIndex,
|
||||
dataFileName);
|
||||
|
||||
m_dataFileDatasetIndex++;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (i != m_datasets.end ())
|
||||
if (i != m_datasets.end () && !isDataEmpty)
|
||||
{
|
||||
os << ", ";
|
||||
osControl << ", ";
|
||||
}
|
||||
}
|
||||
os << std::endl;
|
||||
osControl << std::endl;
|
||||
|
||||
// followed by the inline datafile.
|
||||
|
||||
for (Datasets::const_iterator i = m_datasets.begin (); i != m_datasets.end (); i++)
|
||||
{
|
||||
i->m_data->PrintDatafile (os);
|
||||
i->m_data->PrintDataFile (osData, m_generateOneOutputFile);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Gnuplot::SetDataFileDatasetIndex (unsigned int index)
|
||||
{
|
||||
m_dataFileDatasetIndex = index;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
GnuplotCollection::GnuplotCollection (const std::string& outputFilename)
|
||||
@@ -713,20 +836,42 @@ GnuplotCollection::GetPlot (unsigned int id)
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotCollection::GenerateOutput (std::ostream &os) const
|
||||
GnuplotCollection::GenerateOutput (std::ostream &os)
|
||||
{
|
||||
// If this version of this function is called, it is assumed that a
|
||||
// single output file is being generated.
|
||||
|
||||
if (m_terminal.size ())
|
||||
os << "set terminal " << m_terminal << std::endl;
|
||||
|
||||
if (m_outputFilename.size ())
|
||||
os << "set output '" << m_outputFilename << "'" << std::endl;
|
||||
os << "set output \"" << m_outputFilename << "\"" << std::endl;
|
||||
|
||||
for (Plots::const_iterator i = m_plots.begin (); i != m_plots.end (); ++i)
|
||||
for (Plots::iterator i = m_plots.begin (); i != m_plots.end (); ++i)
|
||||
{
|
||||
i->GenerateOutput (os);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GnuplotCollection::GenerateOutput (std::ostream &osControl, std::ostream &osData,
|
||||
std::string dataFileName)
|
||||
{
|
||||
// If this version of this function is called, it is assumed that
|
||||
// separate output and date files are being generated.
|
||||
|
||||
if (m_terminal.size ())
|
||||
osControl << "set terminal " << m_terminal << std::endl;
|
||||
|
||||
if (m_outputFilename.size ())
|
||||
osControl << "set output \"" << m_outputFilename << "\"" << std::endl;
|
||||
|
||||
for (Plots::iterator i = m_plots.begin (); i != m_plots.end (); ++i)
|
||||
{
|
||||
i->GenerateOutput (osControl, osData, dataFileName);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -351,6 +351,13 @@ public:
|
||||
*/
|
||||
Gnuplot (const std::string& outputFilename="", const std::string& title = "");
|
||||
|
||||
/**
|
||||
* \param outputFilename the name of the file where the rendering of the
|
||||
* graph will be generated if you feed the command stream output by
|
||||
* Gnuplot::GenerateOutput to the gnuplot program.
|
||||
*/
|
||||
void SetOutputFilename (const std::string& outputFilename);
|
||||
|
||||
/**
|
||||
* Crude attempt to auto-detect the correct terminal setting by inspecting
|
||||
* the filename's extension.
|
||||
@@ -391,10 +398,37 @@ public:
|
||||
void AddDataset (const GnuplotDataset& dataset);
|
||||
|
||||
/**
|
||||
* \param os the output stream on which the relevant gnuplot commands should
|
||||
* be generated. Including output file and terminal headers.
|
||||
* \param os the output stream on which the relevant gnuplot
|
||||
* commands should be generated. Including output file and terminal
|
||||
* headers.
|
||||
*
|
||||
* \brief Writes gnuplot commands and data values to a single
|
||||
* output stream.
|
||||
*/
|
||||
void GenerateOutput (std::ostream &os) const;
|
||||
void GenerateOutput (std::ostream &os);
|
||||
|
||||
/**
|
||||
* \param osControl the output stream on which the relevant gnuplot
|
||||
* contol commands should be generated. Including output file and
|
||||
* terminal headers.
|
||||
* \param osData the output stream on which the relevant gnuplot
|
||||
* data values should be generated.
|
||||
* \param dataFileName the name for the data file that will be
|
||||
* written.
|
||||
*
|
||||
* \brief Writes gnuplot commands and data values to two
|
||||
* different outputs streams.
|
||||
*/
|
||||
void GenerateOutput (std::ostream &osControl,
|
||||
std::ostream &osData,
|
||||
std::string dataFileName);
|
||||
|
||||
/**
|
||||
* \param index the index for the data stream in the data file.
|
||||
*
|
||||
* \brief Sets the current data stream index in the data file.
|
||||
*/
|
||||
void SetDataFileDatasetIndex (unsigned int index);
|
||||
|
||||
private:
|
||||
typedef std::vector<GnuplotDataset> Datasets;
|
||||
@@ -408,6 +442,10 @@ private:
|
||||
std::string m_xLegend;
|
||||
std::string m_yLegend;
|
||||
std::string m_extra;
|
||||
|
||||
bool m_generateOneOutputFile;
|
||||
|
||||
unsigned int m_dataFileDatasetIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -446,8 +484,21 @@ public:
|
||||
* \param os the output stream on which the relevant gnuplot commands should
|
||||
* be generated.
|
||||
*/
|
||||
void GenerateOutput (std::ostream &os) const;
|
||||
void GenerateOutput (std::ostream &os);
|
||||
|
||||
/**
|
||||
* \param osControl the output stream on which the relevant gnuplot
|
||||
* contol commands should be generated. Including output file and
|
||||
* terminal headers.
|
||||
* \param osData the output stream on which the relevant gnuplot
|
||||
* data values should be generated.
|
||||
* \param dataFileName the name for the data file that will be
|
||||
* written.
|
||||
*/
|
||||
void GenerateOutput (std::ostream &osControl,
|
||||
std::ostream &osData,
|
||||
std::string dataFileName);
|
||||
|
||||
private:
|
||||
typedef std::vector<Gnuplot> Plots;
|
||||
|
||||
|
||||
71
src/stats/model/probe.cc
Normal file
71
src/stats/model/probe.cc
Normal file
@@ -0,0 +1,71 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*/
|
||||
|
||||
#include "ns3/probe.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/log.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Probe");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (Probe);
|
||||
|
||||
TypeId
|
||||
Probe::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::Probe")
|
||||
.SetParent<DataCollectionObject> ()
|
||||
.AddAttribute ("Start",
|
||||
"Time data collection starts",
|
||||
TimeValue (Seconds (0)),
|
||||
MakeTimeAccessor (&Probe::m_start),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("Stop",
|
||||
"Time when data collection stops. The special time value of 0 disables this attribute",
|
||||
TimeValue (Seconds (0)),
|
||||
MakeTimeAccessor (&Probe::m_stop),
|
||||
MakeTimeChecker ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
Probe::Probe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
Probe::~Probe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
bool
|
||||
Probe::IsEnabled (void) const
|
||||
{
|
||||
return (DataCollectionObject::IsEnabled ()
|
||||
&& Simulator::Now () >= m_start
|
||||
&& (m_stop == Seconds (0) || Simulator::Now () < m_stop));
|
||||
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
79
src/stats/model/probe.h
Normal file
79
src/stats/model/probe.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*/
|
||||
|
||||
#ifndef PROBE_H
|
||||
#define PROBE_H
|
||||
|
||||
#include "ns3/data-collection-object.h"
|
||||
#include "ns3/nstime.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* Base class for probes.
|
||||
*
|
||||
* This class provides general functionality to control each
|
||||
* probe and the data generated by it.
|
||||
*/
|
||||
|
||||
class Probe : public DataCollectionObject
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId ();
|
||||
Probe ();
|
||||
virtual ~Probe ();
|
||||
|
||||
/**
|
||||
* \return true if Probe is currently enabled
|
||||
*/
|
||||
virtual bool IsEnabled (void) const;
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source attribute provided by a given object
|
||||
*
|
||||
* \param traceSource the name of the attribute TraceSource to connect to
|
||||
* \param obj ns3::Object to connect to
|
||||
* \return true if the trace source was successfully connected
|
||||
*/
|
||||
virtual bool ConnectByObject (std::string traceSource, Ptr<Object> obj) = 0;
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source provided by a config path
|
||||
*
|
||||
* \param path Config path to bind to
|
||||
*
|
||||
* Note, if an invalid path is provided, the probe will not be connected
|
||||
* to anything.
|
||||
*/
|
||||
virtual void ConnectByPath (std::string path) = 0;
|
||||
|
||||
protected:
|
||||
/// Time when logging starts.
|
||||
Time m_start;
|
||||
|
||||
/// Time when logging stops.
|
||||
Time m_stop;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // PROBE_H
|
||||
112
src/stats/model/time-series-adaptor.cc
Normal file
112
src/stats/model/time-series-adaptor.cc
Normal file
@@ -0,0 +1,112 @@
|
||||
/* -*- 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 <cmath>
|
||||
#include <cfloat>
|
||||
|
||||
#include "ns3/time-series-adaptor.h"
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("TimeSeriesAdaptor");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (TimeSeriesAdaptor);
|
||||
|
||||
TypeId
|
||||
TimeSeriesAdaptor::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::TimeSeriesAdaptor")
|
||||
.SetParent<DataCollectionObject> ()
|
||||
.AddConstructor<TimeSeriesAdaptor> ()
|
||||
.AddTraceSource ( "Output",
|
||||
"The current simulation time versus the current value converted to a double",
|
||||
MakeTraceSourceAccessor (&TimeSeriesAdaptor::m_output))
|
||||
;
|
||||
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
|
||||
|
||||
115
src/stats/model/time-series-adaptor.h
Normal file
115
src/stats/model/time-series-adaptor.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/* -*- 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 {
|
||||
|
||||
/**
|
||||
* \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:
|
||||
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);
|
||||
|
||||
private:
|
||||
TracedCallback<double, double> m_output;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // TIME_SERIES_ADAPTOR_H
|
||||
109
src/stats/model/uinteger-16-probe.cc
Normal file
109
src/stats/model/uinteger-16-probe.cc
Normal file
@@ -0,0 +1,109 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#include "ns3/uinteger-16-probe.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Uinteger16Probe");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (Uinteger16Probe);
|
||||
|
||||
TypeId
|
||||
Uinteger16Probe::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::Uinteger16Probe")
|
||||
.SetParent<Probe> ()
|
||||
.AddConstructor<Uinteger16Probe> ()
|
||||
.AddTraceSource ( "Output",
|
||||
"The uint16_t that serves as output for this probe",
|
||||
MakeTraceSourceAccessor (&Uinteger16Probe::m_output))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
Uinteger16Probe::Uinteger16Probe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_output = 0;
|
||||
}
|
||||
|
||||
Uinteger16Probe::~Uinteger16Probe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
Uinteger16Probe::GetValue (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_output;
|
||||
}
|
||||
void
|
||||
Uinteger16Probe::SetValue (uint16_t newVal)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << newVal);
|
||||
m_output = newVal;
|
||||
}
|
||||
|
||||
void
|
||||
Uinteger16Probe::SetValueByPath (std::string path, uint16_t newVal)
|
||||
{
|
||||
NS_LOG_FUNCTION (path << newVal);
|
||||
Ptr<Uinteger16Probe> probe = Names::Find<Uinteger16Probe> (path);
|
||||
NS_ASSERT_MSG (probe, "Error: Can't find probe for path " << path);
|
||||
probe->SetValue (newVal);
|
||||
}
|
||||
|
||||
bool
|
||||
Uinteger16Probe::ConnectByObject (std::string traceSource, Ptr<Object> obj)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << traceSource << obj);
|
||||
NS_LOG_DEBUG ("Name of probe (if any) in names database: " << Names::FindPath (obj));
|
||||
bool connected = obj->TraceConnectWithoutContext (traceSource, MakeCallback (&ns3::Uinteger16Probe::TraceSink, this));
|
||||
return connected;
|
||||
}
|
||||
|
||||
void
|
||||
Uinteger16Probe::ConnectByPath (std::string path)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << path);
|
||||
NS_LOG_DEBUG ("Name of probe to search for in config database: " << path);
|
||||
Config::ConnectWithoutContext (path, MakeCallback (&ns3::Uinteger16Probe::TraceSink, this));
|
||||
}
|
||||
|
||||
void
|
||||
Uinteger16Probe::TraceSink (uint16_t oldData, uint16_t newData)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << oldData << newData);
|
||||
if (IsEnabled ())
|
||||
{
|
||||
m_output = newData;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
101
src/stats/model/uinteger-16-probe.h
Normal file
101
src/stats/model/uinteger-16-probe.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#ifndef UINTEGER_16_PROBE_H
|
||||
#define UINTEGER_16_PROBE_H
|
||||
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/probe.h"
|
||||
#include "ns3/traced-value.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This class is designed to probe an underlying ns3 TraceSource exporting
|
||||
* an uint16_t. This probe exports a trace source "Output" of type uint16_t.
|
||||
* The Output trace source emits a value when either the trace source
|
||||
* emits a new value, or when SetValue () is called.
|
||||
*
|
||||
* The current value of the probe can be polled with the GetValue () method.
|
||||
*/
|
||||
class Uinteger16Probe : public Probe
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId ();
|
||||
Uinteger16Probe ();
|
||||
virtual ~Uinteger16Probe ();
|
||||
|
||||
/**
|
||||
* \return the most recent value
|
||||
*/
|
||||
uint16_t GetValue (void) const;
|
||||
|
||||
/**
|
||||
* \param value set the traced uint16_t to a new value
|
||||
*/
|
||||
void SetValue (uint16_t value);
|
||||
|
||||
/**
|
||||
* \brief Set a probe value by its name in the Config system
|
||||
*
|
||||
* \param path Config path to access the probe
|
||||
* \param value set the traced uint16_t to a new value
|
||||
*/
|
||||
static void SetValueByPath (std::string path, uint16_t value);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source attribute provided by a given object
|
||||
*
|
||||
* \param traceSource the name of the attribute TraceSource to connect to
|
||||
* \param obj ns3::Object to connect to
|
||||
* \return true if the trace source was successfully connected
|
||||
*/
|
||||
virtual bool ConnectByObject (std::string traceSource, Ptr<Object> obj);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source provided by a config path
|
||||
*
|
||||
* \param path Config path to bind to
|
||||
*
|
||||
* Note, if an invalid path is provided, the probe will not be connected
|
||||
* to anything.
|
||||
*/
|
||||
virtual void ConnectByPath (std::string path);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Method to connect to an underlying ns3::TraceSource of type uint16_t
|
||||
*
|
||||
* \param oldData previous value of the uint16_t
|
||||
* \param newData new value of the uint16_t
|
||||
*
|
||||
* \internal
|
||||
*/
|
||||
void TraceSink (uint16_t oldData, uint16_t newData);
|
||||
|
||||
TracedValue<uint16_t> m_output;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // UINTEGER_16_PROBE_H
|
||||
109
src/stats/model/uinteger-32-probe.cc
Normal file
109
src/stats/model/uinteger-32-probe.cc
Normal file
@@ -0,0 +1,109 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#include "ns3/uinteger-32-probe.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Uinteger32Probe");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (Uinteger32Probe);
|
||||
|
||||
TypeId
|
||||
Uinteger32Probe::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::Uinteger32Probe")
|
||||
.SetParent<Probe> ()
|
||||
.AddConstructor<Uinteger32Probe> ()
|
||||
.AddTraceSource ( "Output",
|
||||
"The uint32_t that serves as output for this probe",
|
||||
MakeTraceSourceAccessor (&Uinteger32Probe::m_output))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
Uinteger32Probe::Uinteger32Probe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_output = 0;
|
||||
}
|
||||
|
||||
Uinteger32Probe::~Uinteger32Probe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Uinteger32Probe::GetValue (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_output;
|
||||
}
|
||||
void
|
||||
Uinteger32Probe::SetValue (uint32_t newVal)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << newVal);
|
||||
m_output = newVal;
|
||||
}
|
||||
|
||||
void
|
||||
Uinteger32Probe::SetValueByPath (std::string path, uint32_t newVal)
|
||||
{
|
||||
NS_LOG_FUNCTION (path << newVal);
|
||||
Ptr<Uinteger32Probe> probe = Names::Find<Uinteger32Probe> (path);
|
||||
NS_ASSERT_MSG (probe, "Error: Can't find probe for path " << path);
|
||||
probe->SetValue (newVal);
|
||||
}
|
||||
|
||||
bool
|
||||
Uinteger32Probe::ConnectByObject (std::string traceSource, Ptr<Object> obj)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << traceSource << obj);
|
||||
NS_LOG_DEBUG ("Name of probe (if any) in names database: " << Names::FindPath (obj));
|
||||
bool connected = obj->TraceConnectWithoutContext (traceSource, MakeCallback (&ns3::Uinteger32Probe::TraceSink, this));
|
||||
return connected;
|
||||
}
|
||||
|
||||
void
|
||||
Uinteger32Probe::ConnectByPath (std::string path)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << path);
|
||||
NS_LOG_DEBUG ("Name of probe to search for in config database: " << path);
|
||||
Config::ConnectWithoutContext (path, MakeCallback (&ns3::Uinteger32Probe::TraceSink, this));
|
||||
}
|
||||
|
||||
void
|
||||
Uinteger32Probe::TraceSink (uint32_t oldData, uint32_t newData)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << oldData << newData);
|
||||
if (IsEnabled ())
|
||||
{
|
||||
m_output = newData;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
101
src/stats/model/uinteger-32-probe.h
Normal file
101
src/stats/model/uinteger-32-probe.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#ifndef UINTEGER_32_PROBE_H
|
||||
#define UINTEGER_32_PROBE_H
|
||||
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/probe.h"
|
||||
#include "ns3/traced-value.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This class is designed to probe an underlying ns3 TraceSource exporting
|
||||
* an uint32_t. This probe exports a trace source "Output" of type uint32_t.
|
||||
* The Output trace source emits a value when either the trace source
|
||||
* emits a new value, or when SetValue () is called.
|
||||
*
|
||||
* The current value of the probe can be polled with the GetValue () method.
|
||||
*/
|
||||
class Uinteger32Probe : public Probe
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId ();
|
||||
Uinteger32Probe ();
|
||||
virtual ~Uinteger32Probe ();
|
||||
|
||||
/**
|
||||
* \return the most recent value
|
||||
*/
|
||||
uint32_t GetValue (void) const;
|
||||
|
||||
/**
|
||||
* \param value set the traced uint32_t to a new value
|
||||
*/
|
||||
void SetValue (uint32_t value);
|
||||
|
||||
/**
|
||||
* \brief Set a probe value by its name in the Config system
|
||||
*
|
||||
* \param path Config path to access the probe
|
||||
* \param value set the traced uint32_t to a new value
|
||||
*/
|
||||
static void SetValueByPath (std::string path, uint32_t value);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source attribute provided by a given object
|
||||
*
|
||||
* \param traceSource the name of the attribute TraceSource to connect to
|
||||
* \param obj ns3::Object to connect to
|
||||
* \return true if the trace source was successfully connected
|
||||
*/
|
||||
virtual bool ConnectByObject (std::string traceSource, Ptr<Object> obj);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source provided by a config path
|
||||
*
|
||||
* \param path Config path to bind to
|
||||
*
|
||||
* Note, if an invalid path is provided, the probe will not be connected
|
||||
* to anything.
|
||||
*/
|
||||
virtual void ConnectByPath (std::string path);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Method to connect to an underlying ns3::TraceSource of type uint32_t
|
||||
*
|
||||
* \param oldData previous value of the uint32_t
|
||||
* \param newData new value of the uint32_t
|
||||
*
|
||||
* \internal
|
||||
*/
|
||||
void TraceSink (uint32_t oldData, uint32_t newData);
|
||||
|
||||
TracedValue<uint32_t> m_output;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // UINTEGER_32_PROBE_H
|
||||
109
src/stats/model/uinteger-8-probe.cc
Normal file
109
src/stats/model/uinteger-8-probe.cc
Normal file
@@ -0,0 +1,109 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#include "ns3/uinteger-8-probe.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/names.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Uinteger8Probe");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (Uinteger8Probe);
|
||||
|
||||
TypeId
|
||||
Uinteger8Probe::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::Uinteger8Probe")
|
||||
.SetParent<Probe> ()
|
||||
.AddConstructor<Uinteger8Probe> ()
|
||||
.AddTraceSource ( "Output",
|
||||
"The uint8_t that serves as output for this probe",
|
||||
MakeTraceSourceAccessor (&Uinteger8Probe::m_output))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
Uinteger8Probe::Uinteger8Probe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_output = 0;
|
||||
}
|
||||
|
||||
Uinteger8Probe::~Uinteger8Probe ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
Uinteger8Probe::GetValue (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_output;
|
||||
}
|
||||
void
|
||||
Uinteger8Probe::SetValue (uint8_t newVal)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << newVal);
|
||||
m_output = newVal;
|
||||
}
|
||||
|
||||
void
|
||||
Uinteger8Probe::SetValueByPath (std::string path, uint8_t newVal)
|
||||
{
|
||||
NS_LOG_FUNCTION (path << newVal);
|
||||
Ptr<Uinteger8Probe> probe = Names::Find<Uinteger8Probe> (path);
|
||||
NS_ASSERT_MSG (probe, "Error: Can't find probe for path " << path);
|
||||
probe->SetValue (newVal);
|
||||
}
|
||||
|
||||
bool
|
||||
Uinteger8Probe::ConnectByObject (std::string traceSource, Ptr<Object> obj)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << traceSource << obj);
|
||||
NS_LOG_DEBUG ("Name of probe (if any) in names database: " << Names::FindPath (obj));
|
||||
bool connected = obj->TraceConnectWithoutContext (traceSource, MakeCallback (&ns3::Uinteger8Probe::TraceSink, this));
|
||||
return connected;
|
||||
}
|
||||
|
||||
void
|
||||
Uinteger8Probe::ConnectByPath (std::string path)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << path);
|
||||
NS_LOG_DEBUG ("Name of probe to search for in config database: " << path);
|
||||
Config::ConnectWithoutContext (path, MakeCallback (&ns3::Uinteger8Probe::TraceSink, this));
|
||||
}
|
||||
|
||||
void
|
||||
Uinteger8Probe::TraceSink (uint8_t oldData, uint8_t newData)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << oldData << newData);
|
||||
if (IsEnabled ())
|
||||
{
|
||||
m_output = newData;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
101
src/stats/model/uinteger-8-probe.h
Normal file
101
src/stats/model/uinteger-8-probe.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2011 Bucknell University
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: L. Felipe Perrone (perrone@bucknell.edu)
|
||||
* Tiago G. Rodrigues (tgr002@bucknell.edu)
|
||||
*
|
||||
* Modified by: Mitch Watrous (watrous@u.washington.edu)
|
||||
*/
|
||||
|
||||
#ifndef UINTEGER_8_PROBE_H
|
||||
#define UINTEGER_8_PROBE_H
|
||||
|
||||
#include "ns3/callback.h"
|
||||
#include "ns3/probe.h"
|
||||
#include "ns3/traced-value.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* This class is designed to probe an underlying ns3 TraceSource exporting
|
||||
* an uint8_t. This probe exports a trace source "Output" of type uint8_t.
|
||||
* The Output trace source emits a value when either the trace source
|
||||
* emits a new value, or when SetValue () is called.
|
||||
*
|
||||
* The current value of the probe can be polled with the GetValue () method.
|
||||
*/
|
||||
class Uinteger8Probe : public Probe
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId ();
|
||||
Uinteger8Probe ();
|
||||
virtual ~Uinteger8Probe ();
|
||||
|
||||
/**
|
||||
* \return the most recent value
|
||||
*/
|
||||
uint8_t GetValue (void) const;
|
||||
|
||||
/**
|
||||
* \param value set the traced uint8_t to a new value
|
||||
*/
|
||||
void SetValue (uint8_t value);
|
||||
|
||||
/**
|
||||
* \brief Set a probe value by its name in the Config system
|
||||
*
|
||||
* \param path Config path to access the probe
|
||||
* \param value set the traced uint8_t to a new value
|
||||
*/
|
||||
static void SetValueByPath (std::string path, uint8_t value);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source attribute provided by a given object
|
||||
*
|
||||
* \param traceSource the name of the attribute TraceSource to connect to
|
||||
* \param obj ns3::Object to connect to
|
||||
* \return true if the trace source was successfully connected
|
||||
*/
|
||||
virtual bool ConnectByObject (std::string traceSource, Ptr<Object> obj);
|
||||
|
||||
/**
|
||||
* \brief connect to a trace source provided by a config path
|
||||
*
|
||||
* \param path Config path to bind to
|
||||
*
|
||||
* Note, if an invalid path is provided, the probe will not be connected
|
||||
* to anything.
|
||||
*/
|
||||
virtual void ConnectByPath (std::string path);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Method to connect to an underlying ns3::TraceSource of type uint8_t
|
||||
*
|
||||
* \param oldData previous value of the uint8_t
|
||||
* \param newData new value of the uint8_t
|
||||
*
|
||||
* \internal
|
||||
*/
|
||||
void TraceSink (uint8_t oldData, uint8_t newData);
|
||||
|
||||
TracedValue<uint8_t> m_output;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif // UINTEGER_8_PROBE_H
|
||||
165
src/stats/test/double-probe-test-suite.cc
Normal file
165
src/stats/test/double-probe-test-suite.cc
Normal file
@@ -0,0 +1,165 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
|
||||
// Include a header file from your module to test.
|
||||
#include "ns3/double-probe.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/core-module.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
class SampleEmitter : public Object
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
SampleEmitter ()
|
||||
{
|
||||
}
|
||||
virtual ~SampleEmitter ()
|
||||
{
|
||||
}
|
||||
void Start ()
|
||||
{
|
||||
Reschedule ();
|
||||
}
|
||||
void Reschedule ()
|
||||
{
|
||||
m_time = m_var.GetValue ();
|
||||
Simulator::Schedule (Seconds (m_time), &SampleEmitter::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 ();
|
||||
}
|
||||
ExponentialVariable m_var;
|
||||
double m_time;
|
||||
TracedValue<double> m_trace;
|
||||
double aux;
|
||||
};
|
||||
|
||||
Ptr<SampleEmitter> s = CreateObject<SampleEmitter> ();
|
||||
|
||||
TypeId
|
||||
SampleEmitter::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("SampleEmitter")
|
||||
.SetParent<Object> ()
|
||||
.AddTraceSource ("Emitter", "XX", MakeTraceSourceAccessor (&SampleEmitter::m_trace))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
class ProbeTestCase1 : public TestCase
|
||||
{
|
||||
public:
|
||||
ProbeTestCase1 ();
|
||||
virtual ~ProbeTestCase1 ();
|
||||
|
||||
private:
|
||||
virtual void DoRun (void);
|
||||
void TraceSink (std::string context, double oldValue, double newValue);
|
||||
uint32_t m_objectProbed;
|
||||
uint32_t m_pathProbed;
|
||||
};
|
||||
|
||||
ProbeTestCase1::ProbeTestCase1 ()
|
||||
: TestCase ("basic probe test case"),
|
||||
m_objectProbed (0),
|
||||
m_pathProbed (0)
|
||||
{
|
||||
}
|
||||
|
||||
ProbeTestCase1::~ProbeTestCase1 ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ProbeTestCase1::TraceSink (std::string context, double oldValue, double newValue)
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_GT (Simulator::Now (), Seconds (100), "Probed a value outside of the time window");
|
||||
NS_TEST_ASSERT_MSG_LT (Simulator::Now (), Seconds (200), "Probed a value outside of the time window");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ_TOL (s->GetValue (), newValue, 0.00001, "Value probed different than value in the variable");
|
||||
|
||||
if (context == "testProbe")
|
||||
{
|
||||
m_objectProbed++;
|
||||
}
|
||||
else if (context == "testProbe2")
|
||||
{
|
||||
m_pathProbed++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ProbeTestCase1::DoRun (void)
|
||||
{
|
||||
// Test that all instances of probe data are between time window specified
|
||||
// Check also that probes can be hooked to sources by Object and by path
|
||||
|
||||
Ptr<DoubleProbe> p = CreateObject<DoubleProbe> ();
|
||||
p->SetName ("testProbe");
|
||||
|
||||
Simulator::Schedule (Seconds (1), &SampleEmitter::Start, s);
|
||||
p->SetAttribute ("Start", TimeValue (Seconds (100.0)));
|
||||
p->SetAttribute ("Stop", TimeValue (Seconds (200.0)));
|
||||
Simulator::Stop (Seconds (300));
|
||||
|
||||
// Register our emitter object so we can fetch it by using the Config
|
||||
// namespace
|
||||
Names::Add ("/Names/SampleEmitter", s);
|
||||
|
||||
// Hook probe to the emitter.
|
||||
p->ConnectByObject ("Emitter", s);
|
||||
|
||||
// Hook our test function to the probe trace source
|
||||
p->TraceConnect ("Output", p->GetName (), MakeCallback (&ProbeTestCase1::TraceSink, this));
|
||||
|
||||
// Repeat but hook the probe to the object this time using the Config
|
||||
// name set above
|
||||
Ptr<DoubleProbe> p2 = CreateObject<DoubleProbe> ();
|
||||
p2->SetName ("testProbe2");
|
||||
p2->SetAttribute ("Start", TimeValue (Seconds (100.0)));
|
||||
p2->SetAttribute ("Stop", TimeValue (Seconds (200.0)));
|
||||
|
||||
// Hook probe to the emitter.
|
||||
p2->ConnectByPath ("/Names/SampleEmitter/Emitter");
|
||||
|
||||
// Hook our test function to the probe trace source
|
||||
p2->TraceConnect ("Output", p2->GetName (), MakeCallback (&ProbeTestCase1::TraceSink, this));
|
||||
|
||||
Simulator::Run ();
|
||||
|
||||
// Check that each trace sink was called
|
||||
NS_TEST_ASSERT_MSG_GT (m_objectProbed, 0, "Trace sink for object probe never called");
|
||||
NS_TEST_ASSERT_MSG_GT (m_pathProbed, 0, "Trace sink for path probe never called");
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
|
||||
class ProbeTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
ProbeTestSuite ();
|
||||
};
|
||||
|
||||
ProbeTestSuite::ProbeTestSuite ()
|
||||
: TestSuite ("double-probe", UNIT)
|
||||
{
|
||||
AddTestCase (new ProbeTestCase1, TestCase::QUICK);
|
||||
}
|
||||
|
||||
// Do not forget to allocate an instance of this TestSuite
|
||||
static ProbeTestSuite probeTestSuite;
|
||||
|
||||
@@ -8,7 +8,12 @@
|
||||
#
|
||||
# See test.py for more information.
|
||||
cpp_examples = [
|
||||
("double-probe-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"),
|
||||
]
|
||||
|
||||
# A list of Python examples to run in order to ensure that they remain
|
||||
|
||||
@@ -11,29 +11,44 @@ def configure(conf):
|
||||
"library 'sqlite3' not found")
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_ns3_module('stats', ['network'])
|
||||
obj = bld.create_ns3_module('stats', ['core'])
|
||||
obj.source = [
|
||||
'helper/delay-jitter-estimation.cc',
|
||||
'helper/file-helper.cc',
|
||||
'helper/gnuplot-helper.cc',
|
||||
'model/data-calculator.cc',
|
||||
'model/packet-data-calculators.cc',
|
||||
'model/time-data-calculators.cc',
|
||||
'model/data-output-interface.cc',
|
||||
'model/omnet-data-output.cc',
|
||||
'model/data-collector.cc',
|
||||
'model/gnuplot.cc',
|
||||
'helper/delay-jitter-estimation.cc',
|
||||
'model/data-collection-object.cc',
|
||||
'model/probe.cc',
|
||||
'model/boolean-probe.cc',
|
||||
'model/double-probe.cc',
|
||||
'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',
|
||||
]
|
||||
|
||||
module_test = bld.create_ns3_module_test_library('stats')
|
||||
module_test.source = [
|
||||
'test/basic-data-calculators-test-suite.cc',
|
||||
'test/average-test-suite.cc',
|
||||
'test/double-probe-test-suite.cc',
|
||||
]
|
||||
|
||||
headers = bld(features='ns3header')
|
||||
headers.module = 'stats'
|
||||
headers.source = [
|
||||
'helper/delay-jitter-estimation.h',
|
||||
'helper/file-helper.h',
|
||||
'helper/gnuplot-helper.h',
|
||||
'model/data-calculator.h',
|
||||
'model/packet-data-calculators.h',
|
||||
'model/time-data-calculators.h',
|
||||
'model/basic-data-calculators.h',
|
||||
'model/data-output-interface.h',
|
||||
@@ -41,7 +56,17 @@ def build(bld):
|
||||
'model/data-collector.h',
|
||||
'model/gnuplot.h',
|
||||
'model/average.h',
|
||||
'helper/delay-jitter-estimation.h',
|
||||
'model/data-collection-object.h',
|
||||
'model/probe.h',
|
||||
'model/boolean-probe.h',
|
||||
'model/double-probe.h',
|
||||
'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',
|
||||
]
|
||||
|
||||
if bld.env['SQLITE_STATS']:
|
||||
|
||||
Reference in New Issue
Block a user